Skip to content

Commit

Permalink
Move __resolveReference resolvers on to extensions (version-0.x) (
Browse files Browse the repository at this point in the history
#1747)

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: #1131
Fixes: ardatan/graphql-tools#2687
Fixes: ardatan/graphql-tools#2857
  • Loading branch information
trevor-scheer authored Apr 20, 2022
1 parent b73c224 commit 36de7cd
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 13 deletions.
30 changes: 28 additions & 2 deletions gateway-js/src/schema-helper/addResolversToSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,20 @@ export function addResolversToSchema(

if (isAbstractType(type)) {
for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
if (fieldName.startsWith("__")) {
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;
}
}
Expand Down Expand Up @@ -65,7 +78,20 @@ 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,
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;
}
Expand Down
31 changes: 31 additions & 0 deletions gateway-js/src/typings/graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { GraphQLResolveInfo } from 'graphql';

type GraphQLReferenceResolver<TContext> = (
reference: object,
context: TContext,
info: GraphQLResolveInfo,
) => any;

interface ApolloSubgraphExtensions<TContext> {
resolveReference?: GraphQLReferenceResolver<TContext>;
}

declare module 'graphql/type/definition' {
interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> {
apollo?: {
subgraph?: ApolloSubgraphExtensions<_TContext>;
}
}

interface GraphQLInterfaceTypeExtensions<_TSource = any, _TContext = any> {
apollo?: {
subgraph?: ApolloSubgraphExtensions<_TContext>;
}
}

interface GraphQLUnionTypeExtensions<_TSource = any, _TContext = any> {
apollo?: {
subgraph?: ApolloSubgraphExtensions<_TContext>;
}
}
}
30 changes: 28 additions & 2 deletions subgraph-js/src/schema-helper/buildSchemaFromSDL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,20 @@ export function addResolversToSchema(

if (isAbstractType(type)) {
for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
if (fieldName.startsWith("__")) {
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;
}
}
Expand Down Expand Up @@ -153,7 +166,20 @@ 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,
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;
}
Expand Down
22 changes: 18 additions & 4 deletions subgraph-js/src/schemaExtensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,26 @@ type GraphQLReferenceResolver<TContext> = (
info: GraphQLResolveInfo,
) => any;

interface ApolloSubgraphExtensions<TContext> {
resolveReference?: GraphQLReferenceResolver<TContext>;
}

declare module 'graphql/type/definition' {
interface GraphQLObjectType {
resolveReference?: GraphQLReferenceResolver<any>;
interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> {
apollo?: {
subgraph?: ApolloSubgraphExtensions<_TContext>;
};
}

interface GraphQLInterfaceTypeExtensions<_TSource = any, _TContext = any> {
apollo?: {
subgraph?: ApolloSubgraphExtensions<_TContext>;
};
}

interface GraphQLObjectTypeConfig<TSource, TContext> {
resolveReference?: GraphQLReferenceResolver<TContext>;
interface GraphQLUnionTypeExtensions<_TSource = any, _TContext = any> {
apollo?: {
subgraph?: ApolloSubgraphExtensions<_TContext>;
};
}
}
10 changes: 5 additions & 5 deletions subgraph-js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ export const entitiesField: GraphQLFieldConfig<any, any> = {
}
}

const resolveReference = type.resolveReference
? type.resolveReference
: function defaultResolveReference() {
return reference;
};
const resolveReference =
type.extensions?.apollo?.subgraph?.resolveReference ??
function defaultResolveReference() {
return reference;
};

// FIXME somehow get this to show up special in Studio traces?
const result = resolveReference(reference, context, info);
Expand Down

0 comments on commit 36de7cd

Please sign in to comment.