From 40e4307ff3ebe3b916df022c0f29b239ee361f69 Mon Sep 17 00:00:00 2001 From: Laurin Quast Date: Fri, 27 Aug 2021 14:26:18 +0200 Subject: [PATCH 1/2] fix: revert unnecessary breaking change for resolveType --- src/execution/execute.ts | 27 ++++++++++++++------------- src/type/definition.ts | 2 +- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/execution/execute.ts b/src/execution/execute.ts index 8429cae8c5..971c2a37ec 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -36,6 +36,7 @@ import type { GraphQLResolveInfo, GraphQLTypeResolver, GraphQLList, + GraphQLNamedType, } from '../type/definition'; import { assertValidSchema } from '../type/validate'; import { @@ -813,46 +814,46 @@ function completeAbstractValue( } function ensureValidRuntimeType( - runtimeTypeName: unknown, + runtimeObjectTypeOrTypeName: unknown, exeContext: ExecutionContext, returnType: GraphQLAbstractType, fieldNodes: ReadonlyArray, info: GraphQLResolveInfo, result: unknown, ): GraphQLObjectType { - if (runtimeTypeName == null) { + if (runtimeObjectTypeOrTypeName == null) { throw new GraphQLError( `Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}". Either the "${returnType.name}" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.`, fieldNodes, ); } + let runtimeType: GraphQLNamedType | undefined; + // releases before 16.0.0 supported returning `GraphQLObjectType` from `resolveType` // TODO: remove in 17.0.0 release - if (isObjectType(runtimeTypeName)) { - throw new GraphQLError( - 'Support for returning GraphQLObjectType from resolveType was removed in graphql-js@16.0.0 please return type name instead.', - ); - } - - if (typeof runtimeTypeName !== 'string') { + if (isObjectType(runtimeObjectTypeOrTypeName)) { + runtimeType = runtimeObjectTypeOrTypeName; + } else if (typeof runtimeObjectTypeOrTypeName !== 'string') { throw new GraphQLError( `Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}" with ` + - `value ${inspect(result)}, received "${inspect(runtimeTypeName)}".`, + `value ${inspect(result)}, ` + + `received "${inspect(runtimeObjectTypeOrTypeName)}".`, ); + } else { + runtimeType = exeContext.schema.getType(runtimeObjectTypeOrTypeName); } - const runtimeType = exeContext.schema.getType(runtimeTypeName); if (runtimeType == null) { throw new GraphQLError( - `Abstract type "${returnType.name}" was resolved to a type "${runtimeTypeName}" that does not exist inside the schema.`, + `Abstract type "${returnType.name}" was resolved to a type "${runtimeObjectTypeOrTypeName}" that does not exist inside the schema.`, fieldNodes, ); } if (!isObjectType(runtimeType)) { throw new GraphQLError( - `Abstract type "${returnType.name}" was resolved to a non-object type "${runtimeTypeName}".`, + `Abstract type "${returnType.name}" was resolved to a non-object type "${runtimeObjectTypeOrTypeName}".`, fieldNodes, ); } diff --git a/src/type/definition.ts b/src/type/definition.ts index 6e5f0fe409..1a2ab1af24 100644 --- a/src/type/definition.ts +++ b/src/type/definition.ts @@ -953,7 +953,7 @@ export type GraphQLTypeResolver = ( context: TContext, info: GraphQLResolveInfo, abstractType: GraphQLAbstractType, -) => PromiseOrValue; +) => PromiseOrValue; export type GraphQLIsTypeOfFn = ( source: TSource, From d3ae05db627b018130819cadb134925347c80f68 Mon Sep 17 00:00:00 2001 From: Laurin Quast Date: Fri, 27 Aug 2021 14:43:20 +0200 Subject: [PATCH 2/2] test: breaking change revert adjustments --- src/execution/__tests__/abstract-test.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/execution/__tests__/abstract-test.ts b/src/execution/__tests__/abstract-test.ts index 0dd097f527..e0dbe10d31 100644 --- a/src/execution/__tests__/abstract-test.ts +++ b/src/execution/__tests__/abstract-test.ts @@ -553,6 +553,14 @@ describe('Execute: Handles execution of abstract types', () => { }; } + function expectNoError({ forTypeName }: { forTypeName: unknown }) { + const rootValue = { pet: { __typename: forTypeName } }; + const result = executeSync({ schema, document, rootValue }); + expect(result).to.deep.equal({ + data: { pet: { name: null } }, + }); + } + expectError({ forTypeName: undefined }).toEqual( 'Abstract type "Pet" must resolve to an Object type at runtime for field "Query.pet". Either the "Pet" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.', ); @@ -580,8 +588,6 @@ describe('Execute: Handles execution of abstract types', () => { // @ts-expect-error assertInterfaceType(schema.getType('Pet')).resolveType = () => schema.getType('Cat'); - expectError({ forTypeName: undefined }).toEqual( - 'Support for returning GraphQLObjectType from resolveType was removed in graphql-js@16.0.0 please return type name instead.', - ); + expectNoError({ forTypeName: undefined }); }); });