From 6d7813d52d527d988cb8e8f9c1419e8314a621c7 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sat, 8 Feb 2025 17:39:16 +0700 Subject: [PATCH 1/6] Implement logic to only generate __isTypeOf for implementing types OR union members --- .../src/base-resolvers-visitor.ts | 91 +++++++++++++++---- .../ts-resolvers.federation.interface.spec.ts | 1 - .../ts-resolvers.federation.mappers.spec.ts | 2 - .../tests/ts-resolvers.federation.spec.ts | 15 --- .../tests/ts-resolvers.interface.spec.ts | 49 ++++++++++ .../tests/ts-resolvers.union.spec.ts | 57 ++++++++++++ 6 files changed, 181 insertions(+), 34 deletions(-) diff --git a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts index bcdb478d8b0..64a0f9bb877 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts @@ -6,9 +6,11 @@ import { DirectiveDefinitionNode, EnumTypeDefinitionNode, FieldDefinitionNode, + GraphQLInterfaceType, GraphQLNamedType, GraphQLObjectType, GraphQLSchema, + GraphQLUnionType, InputValueDefinitionNode, InterfaceTypeDefinitionNode, isEnumType, @@ -671,6 +673,31 @@ export class BaseResolversVisitor< baseGeneratedTypename?: string; }; } = {}; + protected _parsedSchemaMeta: { + types: { + interface: Record< + string, + { + type: GraphQLInterfaceType; + implementingTypes: Record; + } + >; + union: Record< + string, + { + type: GraphQLUnionType; + unionMembers: Record; + } + >; + }; + typesWithIsTypeOf: Record; + } = { + types: { + interface: {}, + union: {}, + }, + typesWithIsTypeOf: {}, + }; protected _collectedDirectiveResolvers: { [key: string]: string } = {}; protected _variablesTransformer: OperationVariablesToObject; protected _usedMappers: { [key: string]: boolean } = {}; @@ -745,6 +772,11 @@ export class BaseResolversVisitor< this.config.namespacedImportName ); + // 1. Parse schema meta at the start once, + // so we can use it in subsequent generate functions + this.parseSchemaMeta(); + + // 2. Generate types for resolvers this._resolversTypes = this.createResolversFields({ applyWrapper: type => this.applyResolverTypeWrapper(type), clearWrapper: type => this.clearResolverTypeWrapper(type), @@ -1006,7 +1038,7 @@ export class BaseResolversVisitor< const { unionMember, excludeTypes } = this.config.resolversNonOptionalTypename; res[typeName] = this.getAbstractMembersType({ typeName, - memberTypes: schemaType.getTypes(), + memberTypes: Object.values(this._parsedSchemaMeta.types.union[schemaType.name].unionMembers), isTypenameNonOptional: unionMember && !excludeTypes?.includes(typeName), }); } @@ -1028,24 +1060,11 @@ export class BaseResolversVisitor< const schemaType = allSchemaTypes[typeName]; if (isInterfaceType(schemaType)) { - const allTypesMap = this._schema.getTypeMap(); - const implementingTypes: GraphQLObjectType[] = []; - - for (const graphqlType of Object.values(allTypesMap)) { - if (graphqlType instanceof GraphQLObjectType) { - const allInterfaces = graphqlType.getInterfaces(); - - if (allInterfaces.some(int => int.name === schemaType.name)) { - implementingTypes.push(graphqlType); - } - } - } - const { interfaceImplementingType, excludeTypes } = this.config.resolversNonOptionalTypename; res[typeName] = this.getAbstractMembersType({ typeName, - memberTypes: implementingTypes, + memberTypes: Object.values(this._parsedSchemaMeta.types.interface[schemaType.name].implementingTypes), isTypenameNonOptional: interfaceImplementingType && !excludeTypes?.includes(typeName), }); } @@ -1584,6 +1603,46 @@ export class BaseResolversVisitor< return contextType; } + private parseSchemaMeta(): void { + const allSchemaTypes = this._schema.getTypeMap(); + const typeNames = this._federation.filterTypeNames(Object.keys(allSchemaTypes)); + + for (const typeName of typeNames) { + const schemaType = allSchemaTypes[typeName]; + + if (isUnionType(schemaType)) { + this._parsedSchemaMeta.types.union[schemaType.name] = { + type: schemaType, + unionMembers: {}, + }; + + const unionMemberTypes = schemaType.getTypes(); + for (const type of unionMemberTypes) { + this._parsedSchemaMeta.types.union[schemaType.name].unionMembers[type.name] = type; + this._parsedSchemaMeta.typesWithIsTypeOf[type.name] = true; + } + } + + if (isInterfaceType(schemaType)) { + this._parsedSchemaMeta.types.interface[schemaType.name] = { + type: schemaType, + implementingTypes: {}, + }; + + for (const graphqlType of Object.values(allSchemaTypes)) { + if (graphqlType instanceof GraphQLObjectType) { + const allInterfaces = graphqlType.getInterfaces(); + + if (allInterfaces.some(int => int.name === schemaType.name)) { + this._parsedSchemaMeta.types.interface[schemaType.name].implementingTypes[graphqlType.name] = graphqlType; + this._parsedSchemaMeta.typesWithIsTypeOf[graphqlType.name] = true; + } + } + } + } + } + } + protected applyRequireFields(argsType: string, fields: InputValueDefinitionNode[]): string { this._globalDeclarations.add(REQUIRE_FIELDS_TYPE); return `RequireFields<${argsType}, ${fields.map(f => `'${f.name.value}'`).join(' | ')}>`; @@ -1624,7 +1683,7 @@ export class BaseResolversVisitor< ).value; }); - if (!rootType) { + if (!rootType && this._parsedSchemaMeta.typesWithIsTypeOf[typeName]) { fieldsContent.push( indent( `${ diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.interface.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.interface.spec.ts index 8ef9616ff40..b71c937b241 100644 --- a/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.interface.spec.ts +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.interface.spec.ts @@ -181,7 +181,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation - Interface', () => { export type PersonNameResolvers = { first?: Resolver; last?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; export type Resolvers = { diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.mappers.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.mappers.spec.ts index 9db647c00cc..93710cce5f7 100644 --- a/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.mappers.spec.ts +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.mappers.spec.ts @@ -147,13 +147,11 @@ describe('TypeScript Resolvers Plugin + Apollo Federation - mappers', () => { __resolveReference?: ReferenceResolver, { __typename: 'User' } & GraphQLRecursivePick, ContextType>; id?: Resolver; name?: Resolver, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; }; export type UserProfileResolvers = { id?: Resolver; user?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; export type Resolvers = { diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.spec.ts index 71723b55187..fb73dc0d613 100644 --- a/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.spec.ts +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.spec.ts @@ -90,7 +90,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { id?: Resolver; name?: Resolver, ParentType, ContextType>; username?: Resolver, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; }; `); @@ -99,7 +98,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { export type SingleResolvableResolvers = { __resolveReference?: ReferenceResolver, { __typename: 'SingleResolvable' } & GraphQLRecursivePick, ContextType>; id?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; `); @@ -107,7 +105,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { expect(content).toBeSimilarStringTo(` export type SingleNonResolvableResolvers = { id?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; `); @@ -118,7 +115,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { id?: Resolver; id2?: Resolver; id3?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; `); @@ -129,7 +125,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { id?: Resolver; id2?: Resolver; id3?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; `); @@ -139,7 +134,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { id?: Resolver; id2?: Resolver; id3?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; `); @@ -147,7 +141,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { expect(content).toBeSimilarStringTo(` export type BookResolvers = { id?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; `); }); @@ -222,7 +215,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { __resolveReference?: ReferenceResolver, { __typename: 'User' } & GraphQLRecursivePick, ContextType>; id?: Resolver, ContextType>; name?: Resolver, { __typename: 'User' } & GraphQLRecursivePick, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; } `); @@ -231,7 +223,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { __resolveReference?: ReferenceResolver, { __typename: 'Name' } & GraphQLRecursivePick, ContextType>; first?: Resolver, ContextType>; last?: Resolver, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; } `); }); @@ -263,7 +254,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { __resolveReference?: ReferenceResolver, { __typename: 'User' } & GraphQLRecursivePick, ContextType>; id?: Resolver, ContextType>; username?: Resolver, { __typename: 'User' } & GraphQLRecursivePick & GraphQLRecursivePick, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; }; `); }); @@ -299,7 +289,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { export type UserResolvers = { __resolveReference?: ReferenceResolver, { __typename: 'User' } & GraphQLRecursivePick, ContextType>; username?: Resolver, { __typename: 'User' } & GraphQLRecursivePick & GraphQLRecursivePick, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; }; `); }); @@ -332,7 +321,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { export type UserResolvers = { __resolveReference?: ReferenceResolver, { __typename: 'User' } & GraphQLRecursivePick, ContextType>; username?: Resolver, { __typename: 'User' } & GraphQLRecursivePick, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; }; `); }); @@ -366,7 +354,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { __resolveReference?: ReferenceResolver, { __typename: 'User' } & GraphQLRecursivePick, ContextType>; name?: Resolver; username?: Resolver, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; }; `); }); @@ -401,7 +388,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { __resolveReference?: ReferenceResolver, { __typename: 'User' } & GraphQLRecursivePick, ContextType>; id?: Resolver, ContextType>; name?: Resolver, { __typename: 'User' } & GraphQLRecursivePick, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; }; `); }); @@ -528,7 +514,6 @@ describe('TypeScript Resolvers Plugin + Apollo Federation', () => { __resolveReference?: ReferenceResolver, { __typename: 'User' } & (GraphQLRecursivePick | GraphQLRecursivePick), ContextType>; name?: Resolver, { __typename: 'User' } & (GraphQLRecursivePick | GraphQLRecursivePick), ContextType>; username?: Resolver, { __typename: 'User' } & (GraphQLRecursivePick | GraphQLRecursivePick), ContextType>; - __isTypeOf?: IsTypeOfResolverFn; }; `); }); diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.interface.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.interface.spec.ts index 64e997ac25d..a0810501325 100644 --- a/packages/plugins/typescript/resolvers/tests/ts-resolvers.interface.spec.ts +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.interface.spec.ts @@ -460,4 +460,53 @@ describe('TypeScript Resolvers Plugin - Interfaces', () => { }; `); }); + + it('generates __isTypeOf for only implementing object types', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface Node { + id: ID! + } + type Cat implements Node { + id: ID! + name: String! + } + type Dog implements Node { + id: ID! + isGoodBoy: Boolean! + } + type Human { + _id: ID! + } + `); + + const result = await plugin( + schema, + [], + { generateInternalResolversIfNeeded: { __isTypeOf: true } }, + { outputFile: '' } + ); + + expect(result.content).toBeSimilarStringTo(` + export type CatResolvers = { + id?: Resolver; + name?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; + } + `); + + expect(result.content).toBeSimilarStringTo(` + export type DogResolvers = { + id?: Resolver; + isGoodBoy?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; + }; + `); + + // Human does not implement Node, so it does not have __isTypeOf + expect(result.content).toBeSimilarStringTo(` + export type HumanResolvers = { + _id?: Resolver; + }; + `); + }); }); diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.union.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.union.spec.ts index 72580745c32..7375e2c3ed8 100644 --- a/packages/plugins/typescript/resolvers/tests/ts-resolvers.union.spec.ts +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.union.spec.ts @@ -236,4 +236,61 @@ describe('TypeScript Resolvers Plugin - Union', () => { }; `); }); + + it('generates __isTypeOf for only union members', async () => { + const schema = buildSchema(/* GraphQL */ ` + type MemberOne { + id: ID! + } + type MemberTwo { + id: ID! + name: String! + } + type MemberThree { + id: ID! + isMember: Boolean! + } + union Union = MemberOne | MemberTwo | MemberThree + type Normal { + id: ID! + } + `); + + const result = await plugin( + schema, + [], + { generateInternalResolversIfNeeded: { __isTypeOf: true } }, + { outputFile: '' } + ); + + expect(result.content).toBeSimilarStringTo(` + export type MemberOneResolvers = { + id?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; + } + `); + + expect(result.content).toBeSimilarStringTo(` + export type MemberTwoResolvers = { + id?: Resolver; + name?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; + }; + `); + + expect(result.content).toBeSimilarStringTo(` + export type MemberThreeResolvers = { + id?: Resolver; + isMember?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; + }; + `); + + // Normal type is not a union member, so it does not have __isTypeOf + expect(result.content).toBeSimilarStringTo(` + export type NormalResolvers = { + id?: Resolver; + }; + `); + }); }); From 1b23c10de4e2753f14b7ee2fca69c09eaf28d5da Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sat, 8 Feb 2025 17:41:23 +0700 Subject: [PATCH 2/6] Remove unused types --- .../src/base-resolvers-visitor.ts | 13 ------------- .../other/visitor-plugin-common/src/types.ts | 3 --- 2 files changed, 16 deletions(-) diff --git a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts index 64a0f9bb877..c45a0792d83 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts @@ -35,8 +35,6 @@ import { ConvertOptions, DeclarationKind, EnumValuesMap, - type NormalizedGenerateInternalResolversIfNeededConfig, - type GenerateInternalResolversIfNeededConfig, NormalizedAvoidOptionalsConfig, NormalizedScalarsMap, ParsedEnumValuesMap, @@ -79,7 +77,6 @@ export interface ParsedResolversConfig extends ParsedConfig { resolverTypeSuffix: string; allResolversTypeName: string; internalResolversPrefix: string; - generateInternalResolversIfNeeded: NormalizedGenerateInternalResolversIfNeededConfig; directiveResolverMappings: Record; resolversNonOptionalTypename: ResolversNonOptionalTypenameConfig; avoidCheckingAbstractTypesRecursively: boolean; @@ -586,15 +583,6 @@ export interface RawResolversConfig extends RawConfig { * If you are using `mercurius-js`, please set this field to empty string for better compatibility. */ internalResolversPrefix?: string; - /** - * @type object - * @default {} - * @description If relevant internal resolvers are set to `true`, the resolver type will only be generated if the right conditions are met. - * Enabling this allows a more correct type generation for the resolvers. - * For example: - * - `__isTypeOf` is generated for implementing types and union members - */ - generateInternalResolversIfNeeded?: GenerateInternalResolversIfNeededConfig; /** * @description Makes `__typename` of resolver mappings non-optional without affecting the base types. * @default false @@ -706,7 +694,6 @@ export class BaseResolversVisitor< protected _hasReferencedResolversUnionTypes = false; protected _hasReferencedResolversInterfaceTypes = false; protected _resolversUnionTypes: Record = {}; - protected _resolversUnionParentTypes: Record = {}; protected _resolversInterfaceTypes: Record = {}; protected _rootTypeNames = new Set(); protected _globalDeclarations = new Set(); diff --git a/packages/plugins/other/visitor-plugin-common/src/types.ts b/packages/plugins/other/visitor-plugin-common/src/types.ts index e2e2004bfea..88f01fe14ed 100644 --- a/packages/plugins/other/visitor-plugin-common/src/types.ts +++ b/packages/plugins/other/visitor-plugin-common/src/types.ts @@ -138,6 +138,3 @@ export interface CustomDirectivesConfig { */ apolloUnmask?: boolean; } - -export interface GenerateInternalResolversIfNeededConfig {} -export type NormalizedGenerateInternalResolversIfNeededConfig = Required; From 6ff434ee4cc41c83e88b0bfb8077915d99644659 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sat, 8 Feb 2025 17:42:42 +0700 Subject: [PATCH 3/6] Add changeset --- .changeset/angry-lamps-notice.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/angry-lamps-notice.md diff --git a/.changeset/angry-lamps-notice.md b/.changeset/angry-lamps-notice.md new file mode 100644 index 00000000000..857afd3b8a4 --- /dev/null +++ b/.changeset/angry-lamps-notice.md @@ -0,0 +1,7 @@ +--- +'@graphql-codegen/visitor-plugin-common': major +'@graphql-codegen/typescript-resolvers': major +'@graphql-codegen/plugin-helpers': major +--- + +BREAKING CHANGES: Do not generate \_\_isTypeOf for non-implementing types or non-union members From 47d1cf77137d9781dbb76a4eb360ccf0a0292a00 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sat, 8 Feb 2025 19:37:56 +0700 Subject: [PATCH 4/6] Remove generateInternalResolversIfNeeded --- .../resolvers/tests/ts-resolvers.interface.spec.ts | 7 +------ .../typescript/resolvers/tests/ts-resolvers.union.spec.ts | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.interface.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.interface.spec.ts index a0810501325..72c4c41844c 100644 --- a/packages/plugins/typescript/resolvers/tests/ts-resolvers.interface.spec.ts +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.interface.spec.ts @@ -479,12 +479,7 @@ describe('TypeScript Resolvers Plugin - Interfaces', () => { } `); - const result = await plugin( - schema, - [], - { generateInternalResolversIfNeeded: { __isTypeOf: true } }, - { outputFile: '' } - ); + const result = await plugin(schema, [], {}, { outputFile: '' }); expect(result.content).toBeSimilarStringTo(` export type CatResolvers = { diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.union.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.union.spec.ts index 7375e2c3ed8..7dd3d3db299 100644 --- a/packages/plugins/typescript/resolvers/tests/ts-resolvers.union.spec.ts +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.union.spec.ts @@ -256,12 +256,7 @@ describe('TypeScript Resolvers Plugin - Union', () => { } `); - const result = await plugin( - schema, - [], - { generateInternalResolversIfNeeded: { __isTypeOf: true } }, - { outputFile: '' } - ); + const result = await plugin(schema, [], {}, { outputFile: '' }); expect(result.content).toBeSimilarStringTo(` export type MemberOneResolvers = { From 61e6158e27281e66be569bb52e1a13db2f227837 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sat, 8 Feb 2025 19:50:44 +0700 Subject: [PATCH 5/6] Fix dev tests --- dev-test/modules/types.ts | 3 --- dev-test/subpath-import/result.d.ts | 2 -- dev-test/test-schema/resolvers-federation.ts | 5 ----- dev-test/test-schema/resolvers-root.ts | 2 -- dev-test/test-schema/resolvers-stitching.ts | 1 - dev-test/test-schema/resolvers-types.ts | 1 - dev-test/test-schema/typings.ts | 1 - 7 files changed, 15 deletions(-) diff --git a/dev-test/modules/types.ts b/dev-test/modules/types.ts index 4a4bf594d23..27f8fe89372 100644 --- a/dev-test/modules/types.ts +++ b/dev-test/modules/types.ts @@ -220,7 +220,6 @@ export type ArticleResolvers< id?: Resolver; text?: Resolver; title?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; export type CreditCardResolvers< @@ -241,7 +240,6 @@ export type DonationResolvers< id?: Resolver; recipient?: Resolver; sender?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; export type MutationResolvers< @@ -298,7 +296,6 @@ export type UserResolvers< id?: Resolver; lastName?: Resolver; paymentOptions?: Resolver>, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; }; export type Resolvers = { diff --git a/dev-test/subpath-import/result.d.ts b/dev-test/subpath-import/result.d.ts index f066002aea9..bc93a06cac9 100644 --- a/dev-test/subpath-import/result.d.ts +++ b/dev-test/subpath-import/result.d.ts @@ -144,7 +144,6 @@ export type UserResolvers< name?: Resolver; password?: Resolver; updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; export type MutationResolvers< @@ -157,7 +156,6 @@ export type MutationResolvers< FiedContextType, RequireFields >; - __isTypeOf?: IsTypeOfResolverFn; }; export type Resolvers = { diff --git a/dev-test/test-schema/resolvers-federation.ts b/dev-test/test-schema/resolvers-federation.ts index ba1feb00f47..b9ce39f9bb8 100644 --- a/dev-test/test-schema/resolvers-federation.ts +++ b/dev-test/test-schema/resolvers-federation.ts @@ -166,7 +166,6 @@ export type AddressResolvers< city?: Resolver, ParentType, ContextType>; lines?: Resolver; state?: Resolver, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; }; export type BookResolvers< @@ -174,7 +173,6 @@ export type BookResolvers< ParentType extends ResolversParentTypes['Book'] = ResolversParentTypes['Book'] > = { id?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; export type LinesResolvers< @@ -183,7 +181,6 @@ export type LinesResolvers< > = { line1?: Resolver; line2?: Resolver, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; }; export type QueryResolvers< @@ -216,8 +213,6 @@ export type UserResolvers< GraphQLRecursivePick, ContextType >; - - __isTypeOf?: IsTypeOfResolverFn; }; export type Resolvers = { diff --git a/dev-test/test-schema/resolvers-root.ts b/dev-test/test-schema/resolvers-root.ts index ca4941f0f61..ada62e8385f 100644 --- a/dev-test/test-schema/resolvers-root.ts +++ b/dev-test/test-schema/resolvers-root.ts @@ -141,7 +141,6 @@ export type QueryResolvers< ParentType extends ResolversParentTypes['Query'] = ResolversParentTypes['Query'] > = { someDummyField?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; export type QueryRootResolvers< @@ -172,7 +171,6 @@ export type UserResolvers< email?: Resolver; id?: Resolver; name?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; export type Resolvers = { diff --git a/dev-test/test-schema/resolvers-stitching.ts b/dev-test/test-schema/resolvers-stitching.ts index 8954a721b9a..f7338232eda 100644 --- a/dev-test/test-schema/resolvers-stitching.ts +++ b/dev-test/test-schema/resolvers-stitching.ts @@ -162,7 +162,6 @@ export type UserResolvers< email?: Resolver; id?: Resolver; name?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; export type Resolvers = { diff --git a/dev-test/test-schema/resolvers-types.ts b/dev-test/test-schema/resolvers-types.ts index 6bb026ac0c8..07dac436dc3 100644 --- a/dev-test/test-schema/resolvers-types.ts +++ b/dev-test/test-schema/resolvers-types.ts @@ -148,7 +148,6 @@ export type UserResolvers< email?: Resolver; id?: Resolver; name?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; export type Resolvers = { diff --git a/dev-test/test-schema/typings.ts b/dev-test/test-schema/typings.ts index 707d55a9502..851d7d6e401 100644 --- a/dev-test/test-schema/typings.ts +++ b/dev-test/test-schema/typings.ts @@ -136,7 +136,6 @@ export type UserResolvers< email?: Resolver; id?: Resolver; name?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; }; export type Resolvers = { From 77ac90adfa3a7fc4904e6474c32d23785f9e1a63 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sat, 8 Feb 2025 20:48:03 +0700 Subject: [PATCH 6/6] Refactor to use parsedSchemaMeta --- .../src/base-resolvers-visitor.ts | 73 ++++++++----------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts index c45a0792d83..3f9a4055124 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts @@ -1015,22 +1015,20 @@ export class BaseResolversVisitor< return {}; } - const allSchemaTypes = this._schema.getTypeMap(); - const typeNames = this._federation.filterTypeNames(Object.keys(allSchemaTypes)); - - const unionTypes = typeNames.reduce>((res, typeName) => { - const schemaType = allSchemaTypes[typeName]; - - if (isUnionType(schemaType)) { - const { unionMember, excludeTypes } = this.config.resolversNonOptionalTypename; - res[typeName] = this.getAbstractMembersType({ - typeName, - memberTypes: Object.values(this._parsedSchemaMeta.types.union[schemaType.name].unionMembers), - isTypenameNonOptional: unionMember && !excludeTypes?.includes(typeName), - }); - } - return res; - }, {}); + const unionTypes = Object.entries(this._parsedSchemaMeta.types.union).reduce>( + (res, [typeName, { type: schemaType, unionMembers }]) => { + if (isUnionType(schemaType)) { + const { unionMember, excludeTypes } = this.config.resolversNonOptionalTypename; + res[typeName] = this.getAbstractMembersType({ + typeName, + memberTypes: Object.values(unionMembers), + isTypenameNonOptional: unionMember && !excludeTypes?.includes(typeName), + }); + } + return res; + }, + {} + ); return unionTypes; } @@ -1040,24 +1038,22 @@ export class BaseResolversVisitor< return {}; } - const allSchemaTypes = this._schema.getTypeMap(); - const typeNames = this._federation.filterTypeNames(Object.keys(allSchemaTypes)); - - const interfaceTypes = typeNames.reduce>((res, typeName) => { - const schemaType = allSchemaTypes[typeName]; + const interfaceTypes = Object.entries(this._parsedSchemaMeta.types.interface).reduce>( + (res, [typeName, { type: schemaType, implementingTypes }]) => { + if (isInterfaceType(schemaType)) { + const { interfaceImplementingType, excludeTypes } = this.config.resolversNonOptionalTypename; - if (isInterfaceType(schemaType)) { - const { interfaceImplementingType, excludeTypes } = this.config.resolversNonOptionalTypename; - - res[typeName] = this.getAbstractMembersType({ - typeName, - memberTypes: Object.values(this._parsedSchemaMeta.types.interface[schemaType.name].implementingTypes), - isTypenameNonOptional: interfaceImplementingType && !excludeTypes?.includes(typeName), - }); - } + res[typeName] = this.getAbstractMembersType({ + typeName, + memberTypes: Object.values(implementingTypes), + isTypenameNonOptional: interfaceImplementingType && !excludeTypes?.includes(typeName), + }); + } - return res; - }, {}); + return res; + }, + {} + ); return interfaceTypes; } @@ -1857,25 +1853,14 @@ export class BaseResolversVisitor< suffix: this.config.resolverTypeSuffix, }); const declarationKind = 'type'; - const allTypesMap = this._schema.getTypeMap(); - const implementingTypes: string[] = []; - const typeName = node.name as any as string; + const implementingTypes = Object.keys(this._parsedSchemaMeta.types.interface[typeName].implementingTypes); this._collectedResolvers[typeName] = { typename: name + '', baseGeneratedTypename: name, }; - for (const graphqlType of Object.values(allTypesMap)) { - if (graphqlType instanceof GraphQLObjectType) { - const allInterfaces = graphqlType.getInterfaces(); - if (allInterfaces.find(int => int.name === typeName)) { - implementingTypes.push(graphqlType.name); - } - } - } - const parentType = this.getParentTypeToUse(typeName); const genericTypes: string[] = [