From 7291f3d2907bb4d6a4ca811de803c3a89dcdff46 Mon Sep 17 00:00:00 2001 From: Trevor Scheer Date: Tue, 19 Apr 2022 11:36:30 -0700 Subject: [PATCH 1/3] Move __resolveReference resolvers on to extensions The entity __resolveReference resolver is currently placed directly on to GraphQL*Type objects. This breaks the API, as the expectation is to put things like this on to the `extensions` field of objects contained within a GraphQLSchema. This moves the resolver off of the object and into the extensions where it belongs. Fixes: https://github.com/apollographql/federation/issues/1131 Fixes: https://github.com/ardatan/graphql-tools/issues/2687 Fixes: https://github.com/ardatan/graphql-tools/pull/2857 --- .../src/schema-helper/addResolversToSchema.ts | 14 ++++++++++++-- .../src/schema-helper/buildSchemaFromSDL.ts | 14 ++++++++++++-- subgraph-js/src/schemaExtensions.ts | 8 ++------ subgraph-js/src/types.ts | 6 +++--- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/gateway-js/src/schema-helper/addResolversToSchema.ts b/gateway-js/src/schema-helper/addResolversToSchema.ts index c97785088..66ef694a5 100644 --- a/gateway-js/src/schema-helper/addResolversToSchema.ts +++ b/gateway-js/src/schema-helper/addResolversToSchema.ts @@ -19,7 +19,12 @@ export function addResolversToSchema( if (isAbstractType(type)) { for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) { - if (fieldName.startsWith("__")) { + if (fieldName === "__resolveReference") { + type.extensions = { + ...type.extensions, + resolveReference: fieldConfig, + }; + } else if (fieldName.startsWith("__")) { (type as any)[fieldName.substring(2)] = fieldConfig; } } @@ -65,7 +70,12 @@ export function addResolversToSchema( const fieldMap = type.getFields(); for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) { - if (fieldName.startsWith("__")) { + if (fieldName === "__resolveReference") { + type.extensions = { + ...type.extensions, + resolveReference: fieldConfig, + }; + } else if (fieldName.startsWith("__")) { (type as any)[fieldName.substring(2)] = fieldConfig; continue; } diff --git a/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts b/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts index 966c9c826..17cb83410 100644 --- a/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts +++ b/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts @@ -108,7 +108,12 @@ export function addResolversToSchema( if (isAbstractType(type)) { for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) { - if (fieldName.startsWith("__")) { + if (fieldName === "__resolveReference") { + type.extensions = { + ...type.extensions, + resolveReference: fieldConfig, + }; + } else if (fieldName.startsWith("__")) { (type as any)[fieldName.substring(2)] = fieldConfig; } } @@ -154,7 +159,12 @@ export function addResolversToSchema( const fieldMap = type.getFields(); for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) { - if (fieldName.startsWith("__")) { + if (fieldName === "__resolveReference") { + type.extensions = { + ...type.extensions, + resolveReference: fieldConfig, + }; + } else if (fieldName.startsWith("__")) { (type as any)[fieldName.substring(2)] = fieldConfig; continue; } diff --git a/subgraph-js/src/schemaExtensions.ts b/subgraph-js/src/schemaExtensions.ts index 2f6b10b5a..3c52ca1fa 100644 --- a/subgraph-js/src/schemaExtensions.ts +++ b/subgraph-js/src/schemaExtensions.ts @@ -7,11 +7,7 @@ type GraphQLReferenceResolver = ( ) => any; declare module 'graphql/type/definition' { - interface GraphQLObjectType { - resolveReference?: GraphQLReferenceResolver; - } - - interface GraphQLObjectTypeConfig { - resolveReference?: GraphQLReferenceResolver; + interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> { + resolveReference?: GraphQLReferenceResolver<_TContext> } } diff --git a/subgraph-js/src/types.ts b/subgraph-js/src/types.ts index ae1af11ba..db90d74c9 100644 --- a/subgraph-js/src/types.ts +++ b/subgraph-js/src/types.ts @@ -93,9 +93,9 @@ export function entitiesResolver({ } } - const resolveReference = type.resolveReference - ? type.resolveReference - : function defaultResolveReference() { + const resolveReference = + type.extensions?.resolveReference ?? + function defaultResolveReference() { return reference; }; From e504e2755e270dc7a1b24dc3c4b75e7afbab5774 Mon Sep 17 00:00:00 2001 From: Trevor Scheer Date: Wed, 20 Apr 2022 10:45:40 -0700 Subject: [PATCH 2/3] Nest extensions (and fix types accordingly) --- .../src/schema-helper/addResolversToSchema.ts | 10 ++++++-- gateway-js/src/typings/graphql.ts | 25 +++++++++++++++++++ .../src/schema-helper/buildSchemaFromSDL.ts | 10 ++++++-- subgraph-js/src/schemaExtensions.ts | 14 ++++++++++- subgraph-js/src/types.ts | 2 +- 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 gateway-js/src/typings/graphql.ts diff --git a/gateway-js/src/schema-helper/addResolversToSchema.ts b/gateway-js/src/schema-helper/addResolversToSchema.ts index 66ef694a5..2e1a3774c 100644 --- a/gateway-js/src/schema-helper/addResolversToSchema.ts +++ b/gateway-js/src/schema-helper/addResolversToSchema.ts @@ -22,7 +22,10 @@ export function addResolversToSchema( if (fieldName === "__resolveReference") { type.extensions = { ...type.extensions, - resolveReference: fieldConfig, + apolloSubgraph: { + ...type.extensions.apolloSubgraph, + resolveReference: fieldConfig, + }, }; } else if (fieldName.startsWith("__")) { (type as any)[fieldName.substring(2)] = fieldConfig; @@ -73,7 +76,10 @@ export function addResolversToSchema( if (fieldName === "__resolveReference") { type.extensions = { ...type.extensions, - resolveReference: fieldConfig, + apolloSubgraph: { + ...type.extensions.apolloSubgraph, + resolveReference: fieldConfig + }, }; } else if (fieldName.startsWith("__")) { (type as any)[fieldName.substring(2)] = fieldConfig; diff --git a/gateway-js/src/typings/graphql.ts b/gateway-js/src/typings/graphql.ts new file mode 100644 index 000000000..9197a586e --- /dev/null +++ b/gateway-js/src/typings/graphql.ts @@ -0,0 +1,25 @@ +import { GraphQLResolveInfo } from 'graphql'; + +type GraphQLReferenceResolver = ( + reference: object, + context: TContext, + info: GraphQLResolveInfo, +) => any; + +interface ApolloSubgraphExtensions { + resolveReference?: GraphQLReferenceResolver; +} + +declare module 'graphql/type/definition' { + interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> { + apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; + } + + interface GraphQLInterfaceTypeExtensions<_TSource = any, _TContext = any> { + apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; + } + + interface GraphQLUnionTypeExtensions<_TSource = any, _TContext = any> { + apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; + } +} diff --git a/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts b/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts index 17cb83410..31966e622 100644 --- a/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts +++ b/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts @@ -111,7 +111,10 @@ export function addResolversToSchema( if (fieldName === "__resolveReference") { type.extensions = { ...type.extensions, - resolveReference: fieldConfig, + apolloSubgraph: { + ...type.extensions.apolloSubgraph, + resolveReference: fieldConfig + }, }; } else if (fieldName.startsWith("__")) { (type as any)[fieldName.substring(2)] = fieldConfig; @@ -162,7 +165,10 @@ export function addResolversToSchema( if (fieldName === "__resolveReference") { type.extensions = { ...type.extensions, - resolveReference: fieldConfig, + apolloSubgraph: { + ...type.extensions.apolloSubgraph, + resolveReference: fieldConfig + }, }; } else if (fieldName.startsWith("__")) { (type as any)[fieldName.substring(2)] = fieldConfig; diff --git a/subgraph-js/src/schemaExtensions.ts b/subgraph-js/src/schemaExtensions.ts index 3c52ca1fa..9197a586e 100644 --- a/subgraph-js/src/schemaExtensions.ts +++ b/subgraph-js/src/schemaExtensions.ts @@ -6,8 +6,20 @@ type GraphQLReferenceResolver = ( info: GraphQLResolveInfo, ) => any; +interface ApolloSubgraphExtensions { + resolveReference?: GraphQLReferenceResolver; +} + declare module 'graphql/type/definition' { interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> { - resolveReference?: GraphQLReferenceResolver<_TContext> + apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; + } + + interface GraphQLInterfaceTypeExtensions<_TSource = any, _TContext = any> { + apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; + } + + interface GraphQLUnionTypeExtensions<_TSource = any, _TContext = any> { + apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; } } diff --git a/subgraph-js/src/types.ts b/subgraph-js/src/types.ts index db90d74c9..55b14b903 100644 --- a/subgraph-js/src/types.ts +++ b/subgraph-js/src/types.ts @@ -94,7 +94,7 @@ export function entitiesResolver({ } const resolveReference = - type.extensions?.resolveReference ?? + type.extensions?.apolloSubgraph?.resolveReference ?? function defaultResolveReference() { return reference; }; From d4f7b7f4154dcdf03eedfb73d5a6242170bc267e Mon Sep 17 00:00:00 2001 From: Trevor Scheer Date: Wed, 20 Apr 2022 15:06:31 -0700 Subject: [PATCH 3/3] Namespace with apollo.subgraph --- .../src/schema-helper/addResolversToSchema.ts | 18 ++++++++++++------ gateway-js/src/typings/graphql.ts | 12 +++++++++--- .../src/schema-helper/buildSchemaFromSDL.ts | 18 ++++++++++++------ subgraph-js/src/schemaExtensions.ts | 12 +++++++++--- subgraph-js/src/types.ts | 2 +- 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/gateway-js/src/schema-helper/addResolversToSchema.ts b/gateway-js/src/schema-helper/addResolversToSchema.ts index 2e1a3774c..7733f0557 100644 --- a/gateway-js/src/schema-helper/addResolversToSchema.ts +++ b/gateway-js/src/schema-helper/addResolversToSchema.ts @@ -22,9 +22,12 @@ export function addResolversToSchema( if (fieldName === "__resolveReference") { type.extensions = { ...type.extensions, - apolloSubgraph: { - ...type.extensions.apolloSubgraph, - resolveReference: fieldConfig, + apollo: { + ...type.extensions.apollo, + subgraph: { + ...type.extensions.apollo?.subgraph, + resolveReference: fieldConfig, + } }, }; } else if (fieldName.startsWith("__")) { @@ -76,9 +79,12 @@ export function addResolversToSchema( if (fieldName === "__resolveReference") { type.extensions = { ...type.extensions, - apolloSubgraph: { - ...type.extensions.apolloSubgraph, - resolveReference: fieldConfig + apollo: { + ...type.extensions.apollo, + subgraph: { + ...type.extensions.apollo?.subgraph, + resolveReference: fieldConfig, + } }, }; } else if (fieldName.startsWith("__")) { diff --git a/gateway-js/src/typings/graphql.ts b/gateway-js/src/typings/graphql.ts index 9197a586e..af398cfdd 100644 --- a/gateway-js/src/typings/graphql.ts +++ b/gateway-js/src/typings/graphql.ts @@ -12,14 +12,20 @@ interface ApolloSubgraphExtensions { declare module 'graphql/type/definition' { interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> { - apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; + apollo?: { + subgraph?: ApolloSubgraphExtensions<_TContext>; + } } interface GraphQLInterfaceTypeExtensions<_TSource = any, _TContext = any> { - apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; + apollo?: { + subgraph?: ApolloSubgraphExtensions<_TContext>; + } } interface GraphQLUnionTypeExtensions<_TSource = any, _TContext = any> { - apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; + apollo?: { + subgraph?: ApolloSubgraphExtensions<_TContext>; + } } } diff --git a/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts b/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts index 31966e622..b90bbfd0b 100644 --- a/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts +++ b/subgraph-js/src/schema-helper/buildSchemaFromSDL.ts @@ -111,9 +111,12 @@ export function addResolversToSchema( if (fieldName === "__resolveReference") { type.extensions = { ...type.extensions, - apolloSubgraph: { - ...type.extensions.apolloSubgraph, - resolveReference: fieldConfig + apollo: { + ...type.extensions.apollo, + subgraph: { + ...type.extensions.apollo?.subgraph, + resolveReference: fieldConfig, + } }, }; } else if (fieldName.startsWith("__")) { @@ -165,9 +168,12 @@ export function addResolversToSchema( if (fieldName === "__resolveReference") { type.extensions = { ...type.extensions, - apolloSubgraph: { - ...type.extensions.apolloSubgraph, - resolveReference: fieldConfig + apollo: { + ...type.extensions.apollo, + subgraph: { + ...type.extensions.apollo?.subgraph, + resolveReference: fieldConfig, + } }, }; } else if (fieldName.startsWith("__")) { diff --git a/subgraph-js/src/schemaExtensions.ts b/subgraph-js/src/schemaExtensions.ts index 9197a586e..10d10b96a 100644 --- a/subgraph-js/src/schemaExtensions.ts +++ b/subgraph-js/src/schemaExtensions.ts @@ -12,14 +12,20 @@ interface ApolloSubgraphExtensions { declare module 'graphql/type/definition' { interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> { - apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; + apollo?: { + subgraph?: ApolloSubgraphExtensions<_TContext>; + }; } interface GraphQLInterfaceTypeExtensions<_TSource = any, _TContext = any> { - apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; + apollo?: { + subgraph?: ApolloSubgraphExtensions<_TContext>; + }; } interface GraphQLUnionTypeExtensions<_TSource = any, _TContext = any> { - apolloSubgraph?: ApolloSubgraphExtensions<_TContext>; + apollo?: { + subgraph?: ApolloSubgraphExtensions<_TContext>; + }; } } diff --git a/subgraph-js/src/types.ts b/subgraph-js/src/types.ts index 55b14b903..3828646a1 100644 --- a/subgraph-js/src/types.ts +++ b/subgraph-js/src/types.ts @@ -94,7 +94,7 @@ export function entitiesResolver({ } const resolveReference = - type.extensions?.apolloSubgraph?.resolveReference ?? + type.extensions.apollo?.subgraph?.resolveReference ?? function defaultResolveReference() { return reference; };