diff --git a/federation-integration-testsuite-js/src/fixtures/accounts.ts b/federation-integration-testsuite-js/src/fixtures/accounts.ts index 226e6cc5a..317422960 100644 --- a/federation-integration-testsuite-js/src/fixtures/accounts.ts +++ b/federation-integration-testsuite-js/src/fixtures/accounts.ts @@ -52,7 +52,10 @@ export const typeDefs = gql` description: String } - type User @key(fields: "id") @key(fields: "username name { first last }") @tag(name: "from-accounts") { + type User + @key(fields: "id") + @key(fields: "username name { first last }") + @tag(name: "from-accounts") { id: ID! @tag(name: "accounts") name: Name @cacheControl(inheritMaxAge: true) username: String @@ -130,21 +133,21 @@ const libraryUsers: { [name: string]: string[] } = { export const resolvers: GraphQLResolverMap = { RootQuery: { user(_, args) { - return { id: args.id }; + return users.find((user) => user.id === args.id); }, me() { - return { id: '1' }; + return users.find((user) => user.id === '1'); }, }, User: { - __resolveObject(object) { + __resolveReference(object) { // Nested key example for @key(fields: "username name { first last }") if (object.username && object.name.first && object.name.last) { - users.find(user => user.username === object.username); + users.find((user) => user.username === object.username); } - return users.find(user => user.id === object.id); + return users.find((user) => user.id === object.id); }, birthDate(user, args) { return args.locale @@ -154,20 +157,20 @@ export const resolvers: GraphQLResolverMap = { : user.birthDate; }, metadata(object) { - const metaIndex = metadata.findIndex(m => m.id === object.id); - return metadata[metaIndex].metadata.map(obj => ({ name: obj.name })); + const metaIndex = metadata.findIndex((m) => m.id === object.id); + return metadata[metaIndex].metadata.map((obj) => ({ name: obj.name })); }, }, UserMetadata: { address(object) { - const metaIndex = metadata.findIndex(m => - m.metadata.find(o => o.name === object.name), + const metaIndex = metadata.findIndex((m) => + m.metadata.find((o) => o.name === object.name), ); return metadata[metaIndex].metadata[0].address; }, description(object) { - const metaIndex = metadata.findIndex(m => - m.metadata.find(o => o.name === object.name), + const metaIndex = metadata.findIndex((m) => + m.metadata.find((o) => o.name === object.name), ); return metadata[metaIndex].metadata[0].description; }, @@ -177,13 +180,13 @@ export const resolvers: GraphQLResolverMap = { const libraryUserIds = libraryUsers[name]; return libraryUserIds && libraryUserIds.find((id: string) => id === userId) - ? { id: userId } + ? users.find((user) => user.id === userId) : null; }, }, Mutation: { login(_, args) { - return users.find(user => user.username === args.username); + return users.find((user) => user.username === args.username); }, }, }; diff --git a/federation-integration-testsuite-js/src/fixtures/books.ts b/federation-integration-testsuite-js/src/fixtures/books.ts index 31eb20c5b..d8ab57720 100644 --- a/federation-integration-testsuite-js/src/fixtures/books.ts +++ b/federation-integration-testsuite-js/src/fixtures/books.ts @@ -119,7 +119,7 @@ const books = [ export const resolvers: GraphQLResolverMap = { Book: { - __resolveObject(object) { + __resolveReference(object) { return books.find(book => book.isbn === object.isbn); }, similarBooks(object) { @@ -137,7 +137,7 @@ export const resolvers: GraphQLResolverMap = { }, Query: { book(_, args) { - return { isbn: args.isbn }; + return books.find(book => book.isbn === args.isbn); }, books() { return books; diff --git a/gateway-js/src/__tests__/executeQueryPlan.test.ts b/gateway-js/src/__tests__/executeQueryPlan.test.ts index 6783824d2..b391a1a2b 100644 --- a/gateway-js/src/__tests__/executeQueryPlan.test.ts +++ b/gateway-js/src/__tests__/executeQueryPlan.test.ts @@ -20,7 +20,7 @@ import { buildComposedSchema, QueryPlanner } from '@apollo/query-planner'; import { ApolloGateway } from '..'; import { ApolloServerBase as ApolloServer } from 'apollo-server-core'; import { getFederatedTestingSchema } from './execution-utils'; -import { addResolversToSchema, GraphQLResolverMap } from '../schema-helper'; +import { addResolversToSchema, GraphQLResolverMap } from '@apollo/subgraph/src/schema-helper'; expect.addSnapshotSerializer(astSerializer); expect.addSnapshotSerializer(queryPlanSerializer); diff --git a/gateway-js/src/__tests__/execution-utils.ts b/gateway-js/src/__tests__/execution-utils.ts index 1768b6a21..5cab581f4 100644 --- a/gateway-js/src/__tests__/execution-utils.ts +++ b/gateway-js/src/__tests__/execution-utils.ts @@ -1,7 +1,7 @@ import { GraphQLSchemaModule, GraphQLResolverMap, -} from '../schema-helper'; +} from '@apollo/subgraph/src/schema-helper'; import { GraphQLRequest, GraphQLExecutionResult } from 'apollo-server-types'; import type { Logger } from '@apollo/utils.logger'; import { diff --git a/gateway-js/src/__tests__/gateway/endToEnd.test.ts b/gateway-js/src/__tests__/gateway/endToEnd.test.ts index 5f5ef1328..91eeed93d 100644 --- a/gateway-js/src/__tests__/gateway/endToEnd.test.ts +++ b/gateway-js/src/__tests__/gateway/endToEnd.test.ts @@ -4,7 +4,7 @@ import fetch from 'node-fetch'; import { ApolloGateway } from '../..'; import { fixtures } from 'apollo-federation-integration-testsuite'; import { ApolloServerPluginInlineTrace } from 'apollo-server-core'; -import { GraphQLSchemaModule } from '../../schema-helper'; +import { GraphQLSchemaModule } from '@apollo/subgraph/src/schema-helper'; async function startFederatedServer(modules: GraphQLSchemaModule[]) { const schema = buildSubgraphSchema(modules); diff --git a/gateway-js/src/__tests__/gateway/reporting.test.ts b/gateway-js/src/__tests__/gateway/reporting.test.ts index fd90a4c72..a31a8693d 100644 --- a/gateway-js/src/__tests__/gateway/reporting.test.ts +++ b/gateway-js/src/__tests__/gateway/reporting.test.ts @@ -10,7 +10,7 @@ import { Report, Trace } from 'apollo-reporting-protobuf'; import { fixtures } from 'apollo-federation-integration-testsuite'; import { nockAfterEach, nockBeforeEach } from '../nockAssertions'; import resolvable, { Resolvable } from '@josephg/resolvable'; -import { GraphQLSchemaModule } from '../../schema-helper'; +import { GraphQLSchemaModule } from '@apollo/subgraph/src/schema-helper'; // Normalize specific fields that change often (eg timestamps) to static values, // to make snapshot testing viable. (If these helpers are more generally diff --git a/gateway-js/src/__tests__/integration/complex-key.test.ts b/gateway-js/src/__tests__/integration/complex-key.test.ts index 74c9e15f0..de91b7e5c 100644 --- a/gateway-js/src/__tests__/integration/complex-key.test.ts +++ b/gateway-js/src/__tests__/integration/complex-key.test.ts @@ -91,11 +91,11 @@ const userService: ServiceDefinitionModule = { ); }, organization(user) { - return { id: user.organizationId }; + return organizations.find(org => org.id === user.organizationId); }, }, Organization: { - __resolveObject(object) { + __resolveReference(object) { return organizations.find(org => org.id === object.id); }, }, diff --git a/gateway-js/src/datasources/__tests__/LocalGraphQLDataSource.test.ts b/gateway-js/src/datasources/__tests__/LocalGraphQLDataSource.test.ts index 34ff446f6..37911971a 100644 --- a/gateway-js/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +++ b/gateway-js/src/datasources/__tests__/LocalGraphQLDataSource.test.ts @@ -1,7 +1,7 @@ import { LocalGraphQLDataSource } from '../LocalGraphQLDataSource'; import { buildSubgraphSchema } from '@apollo/subgraph'; import gql from 'graphql-tag'; -import { GraphQLResolverMap } from '../../schema-helper'; +import { GraphQLResolverMap } from '@apollo/subgraph/src/schema-helper'; import { GraphQLRequestContext } from 'apollo-server-types'; import { GraphQLDataSourceRequestKind } from '../types'; diff --git a/gateway-js/src/schema-helper/addResolversToSchema.ts b/gateway-js/src/schema-helper/addResolversToSchema.ts deleted file mode 100644 index 5ba92758e..000000000 --- a/gateway-js/src/schema-helper/addResolversToSchema.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { - GraphQLSchema, - isObjectType, - GraphQLEnumType, - isAbstractType, - isScalarType, - isEnumType, - GraphQLEnumValueConfig, -} from 'graphql'; - -import { GraphQLResolverMap } from './resolverMap'; - -export function addResolversToSchema( - schema: GraphQLSchema, - resolvers: GraphQLResolverMap -) { - for (const [typeName, fieldConfigs] of Object.entries(resolvers)) { - const type = schema.getType(typeName); - - if (isAbstractType(type)) { - for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) { - if (fieldName === "__resolveReference") { - type.extensions = { - ...type.extensions, - apollo: { - // extensions is nullable in graphql@15 so the conditional chain is - // necessary for back compat - ...type.extensions?.apollo, - subgraph: { - ...type.extensions?.apollo?.subgraph, - resolveReference: fieldConfig, - } - }, - }; - } else if (fieldName.startsWith("__")) { - (type as any)[fieldName.substring(2)] = fieldConfig; - } - } - } - - if (isScalarType(type)) { - for (const fn in fieldConfigs) { - (type as any)[fn] = (fieldConfigs as any)[fn]; - } - } - - if (isEnumType(type)) { - const values = type.getValues(); - const newValues: { [key: string]: GraphQLEnumValueConfig } = {}; - values.forEach(value => { - let newValue = (fieldConfigs as any)[value.name]; - if (newValue === undefined) { - newValue = value.name; - } - - newValues[value.name] = { - value: newValue, - deprecationReason: value.deprecationReason, - description: value.description, - astNode: value.astNode, - extensions: undefined - }; - }); - - // In place updating hack to get around pulling in the full - // schema walking and immutable updating machinery from graphql-tools - Object.assign( - type, - new GraphQLEnumType({ - ...type.toConfig(), - values: newValues - }) - ); - } - - if (!isObjectType(type)) continue; - - const fieldMap = type.getFields(); - - for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) { - if (fieldName === "__resolveReference") { - type.extensions = { - ...type.extensions, - apollo: { - // extensions is nullable in graphql@15 so the conditional chain is - // necessary for back compat - ...type.extensions?.apollo, - subgraph: { - ...type.extensions?.apollo?.subgraph, - resolveReference: fieldConfig, - } - }, - }; - } else if (fieldName.startsWith("__")) { - (type as any)[fieldName.substring(2)] = fieldConfig; - continue; - } - - const field = fieldMap[fieldName]; - if (!field) continue; - - if (typeof fieldConfig === "function") { - field.resolve = fieldConfig; - } else { - field.resolve = fieldConfig.resolve; - } - } - } -} diff --git a/gateway-js/src/schema-helper/index.ts b/gateway-js/src/schema-helper/index.ts deleted file mode 100644 index 18d126f17..000000000 --- a/gateway-js/src/schema-helper/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './resolverMap'; -export * from './addResolversToSchema'; diff --git a/gateway-js/src/schema-helper/resolverMap.ts b/gateway-js/src/schema-helper/resolverMap.ts deleted file mode 100644 index b57bc188a..000000000 --- a/gateway-js/src/schema-helper/resolverMap.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { GraphQLFieldResolver, GraphQLScalarType, DocumentNode } from 'graphql'; - -export interface GraphQLSchemaModule { - typeDefs: DocumentNode; - resolvers?: GraphQLResolverMap; -} - -// eslint-disable-next-line @typescript-eslint/ban-types -export interface GraphQLResolverMap { - [typeName: string]: - | { - [fieldName: string]: - | GraphQLFieldResolver - | { - requires?: string; - resolve: GraphQLFieldResolver; - }; - } - | GraphQLScalarType - | { - [enumValue: string]: string | number; - }; -} diff --git a/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts b/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts index 898c3d6ce..616c94a05 100644 --- a/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts +++ b/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts @@ -107,7 +107,7 @@ export function addResolversToSchema( if (isAbstractType(type)) { for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) { - if (fieldName === "__resolveReference") { + if (fieldName === '__resolveReference') { type.extensions = { ...type.extensions, apollo: { @@ -117,11 +117,11 @@ export function addResolversToSchema( subgraph: { ...type.extensions?.apollo?.subgraph, resolveReference: fieldConfig, - } + }, }, }; - } else if (fieldName.startsWith("__")) { - (type as any)[fieldName.substring(2)] = fieldConfig; + } else if (fieldName === '__resolveType') { + type.resolveType = fieldConfig; } } } @@ -166,7 +166,7 @@ export function addResolversToSchema( const fieldMap = type.getFields(); for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) { - if (fieldName === "__resolveReference") { + if (fieldName === '__resolveReference') { type.extensions = { ...type.extensions, apollo: { @@ -176,11 +176,12 @@ export function addResolversToSchema( subgraph: { ...type.extensions?.apollo?.subgraph, resolveReference: fieldConfig, - } + }, }, }; - } else if (fieldName.startsWith("__")) { - (type as any)[fieldName.substring(2)] = fieldConfig; + continue; + } else if (fieldName === '__isTypeOf') { + type.isTypeOf = fieldConfig; continue; }