Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dev-test/modules/blog/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export namespace BlogModule {
export type User = Types.User;
export type Query = Pick<Types.Query, DefinedFields['Query']>;

export type ArticleResolvers = Pick<Types.ArticleResolvers, DefinedFields['Article'] | '__isTypeOf'>;
export type ArticleResolvers = Pick<Types.ArticleResolvers, DefinedFields['Article']>;
export type QueryResolvers = Pick<Types.QueryResolvers, DefinedFields['Query']>;

export interface Resolvers {
Expand Down
2 changes: 1 addition & 1 deletion dev-test/modules/dotanions/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export namespace DotanionsModule {

export type PaypalResolvers = Pick<Types.PaypalResolvers, DefinedFields['Paypal'] | '__isTypeOf'>;
export type CreditCardResolvers = Pick<Types.CreditCardResolvers, DefinedFields['CreditCard'] | '__isTypeOf'>;
export type DonationResolvers = Pick<Types.DonationResolvers, DefinedFields['Donation'] | '__isTypeOf'>;
export type DonationResolvers = Pick<Types.DonationResolvers, DefinedFields['Donation']>;
export type MutationResolvers = Pick<Types.MutationResolvers, DefinedFields['Mutation']>;
export type UserResolvers = Pick<Types.UserResolvers, DefinedFields['User']>;

Expand Down
2 changes: 1 addition & 1 deletion dev-test/modules/users/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export namespace UsersModule {
export type User = Pick<Types.User, DefinedFields['User']>;
export type Query = Pick<Types.Query, DefinedFields['Query']>;

export type UserResolvers = Pick<Types.UserResolvers, DefinedFields['User'] | '__isTypeOf'>;
export type UserResolvers = Pick<Types.UserResolvers, DefinedFields['User']>;
export type QueryResolvers = Pick<Types.QueryResolvers, DefinedFields['Query']>;

export interface Resolvers {
Expand Down
6 changes: 6 additions & 0 deletions packages/presets/graphql-modules/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @graphql-codegen/graphql-modules-preset

## 5.0.1

### Patch Changes

- [#10447](https://github.com/dotansimha/graphql-code-generator/pull/10447) [`5dad86e`](https://github.com/dotansimha/graphql-code-generator/commit/5dad86e4753369e288fba5821722507d88afb3dc) Thanks [@eddeee888](https://github.com/eddeee888)! - Fix \_\_isTypeOf wrongly picked on objects that are not implementing types or union members

## 5.0.0

### Major Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/presets/graphql-modules/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@graphql-codegen/graphql-modules-preset",
"version": "5.0.0",
"version": "5.0.1",
"description": "GraphQL Code Generator preset for modularized schema",
"repository": {
"type": "git",
Expand Down
19 changes: 18 additions & 1 deletion packages/presets/graphql-modules/src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type RegistryKeys = 'objects' | 'inputs' | 'interfaces' | 'scalars' | 'unions' |
type Registry = Record<RegistryKeys, string[]>;
const registryKeys: RegistryKeys[] = ['objects', 'inputs', 'interfaces', 'scalars', 'unions', 'enums'];
const resolverKeys: Array<Extract<RegistryKeys, 'objects' | 'enums' | 'scalars'>> = ['scalars', 'objects', 'enums'];
const withIsTypeOfKeys: Array<'objects'> = ['objects'];

export function buildModule(
name: string,
Expand Down Expand Up @@ -65,6 +66,7 @@ export function buildModule(
const picks: Record<RegistryKeys, Record<string, string[]>> = createObject(registryKeys, () => ({}));
const defined: Registry = createObject(registryKeys, () => []);
const extended: Registry = createObject(registryKeys, () => []);
const withIsTypeOf: { objects: string[] } = createObject(withIsTypeOfKeys, () => []);

// List of types used in objects, fields, arguments etc
const usedTypes = collectUsedTypes(doc);
Expand Down Expand Up @@ -216,7 +218,9 @@ export function buildModule(
'DefinedFields',
// In case of enabled `requireRootResolvers` flag, the preset has to produce a non-optional properties.
requireRootResolvers && rootTypes.includes(name),
!rootTypes.includes(name) && defined.objects.includes(name) ? ` | '__isTypeOf'` : ''
!rootTypes.includes(name) && defined.objects.includes(name) && withIsTypeOf.objects.includes(name)
? ` | '__isTypeOf'`
: ''
)
)
.join('\n'),
Expand Down Expand Up @@ -405,6 +409,11 @@ export function buildModule(
case Kind.OBJECT_TYPE_DEFINITION: {
defined.objects.push(name);
collectFields(node, picks.objects);

if (node.interfaces?.length > 0) {
withIsTypeOf.objects.push(name);
}

break;
}

Expand Down Expand Up @@ -433,6 +442,10 @@ export function buildModule(

case Kind.UNION_TYPE_DEFINITION: {
defined.unions.push(name);

for (const namedType of node.types || []) {
pushUnique(withIsTypeOf.objects, namedType.name.value);
}
break;
}
}
Expand All @@ -453,6 +466,10 @@ export function buildModule(

pushUnique(extended.objects, name);

if (node.interfaces?.length > 0) {
pushUnique(withIsTypeOf.objects, name);
}

break;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export type Mutation = Pick<Types.Mutation, DefinedFields['Mutation']>;

export type PaypalResolvers = Pick<Types.PaypalResolvers, DefinedFields['Paypal'] | '__isTypeOf'>;
export type CreditCardResolvers = Pick<Types.CreditCardResolvers, DefinedFields['CreditCard'] | '__isTypeOf'>;
export type DonationResolvers = Pick<Types.DonationResolvers, DefinedFields['Donation'] | '__isTypeOf'>;
export type DonationResolvers = Pick<Types.DonationResolvers, DefinedFields['Donation']>;
export type MutationResolvers = Pick<Types.MutationResolvers, DefinedFields['Mutation']>;
export type UserResolvers = Pick<Types.UserResolvers, DefinedFields['User']>;

Expand Down
87 changes: 87 additions & 0 deletions packages/presets/graphql-modules/tests/builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -479,3 +479,90 @@ test('should generate a signature for ResolveMiddleware (with widlcards)', () =>
};
`);
});

test('only picks __isTypeOf from implementing types (of Interfaces) and union members', () => {
const output = buildModule(
'test',
parse(/* GraphQL */ `
type Query {
me: User
pet: Pet
offer: Offer
}

type User {
id: ID!
username: String!
}

interface Pet {
id: ID!
name: String!
}
type Cat implements Pet {
id: ID!
name: String!
canScratch: Boolean!
}
type Dog implements Pet {
id: ID!
name: String!
canBark: Boolean!
}
type Elephant {
id: ID!
}
extend type Elephant implements Pet {
name: String!
hasTrunk: Boolean!
}

union Offer = Discount | Coupon
type Discount {
id: ID!
name: String!
}
type Coupon {
id: ID!
name: String!
}
`),
{
importPath: '../types',
importNamespace: 'core',
encapsulate: 'none',
requireRootResolvers: false,
shouldDeclare: false,
rootTypes: ROOT_TYPES,
baseVisitor,
useGraphQLModules: true,
}
);

// User does not pick `__isTypeOf` because it is not a union member, or implementing types
expect(output).toBeSimilarStringTo(`
export type UserResolvers = Pick<core.UserResolvers, DefinedFields['User']>;
`);

// Cat picks `__isTypeOf` because it is an implementing type of Pet
expect(output).toBeSimilarStringTo(`
export type CatResolvers = Pick<core.CatResolvers, DefinedFields['Cat'] | '__isTypeOf'>;
`);
// Dog picks `__isTypeOf` because it is an implementing type of Pet
expect(output).toBeSimilarStringTo(`
export type DogResolvers = Pick<core.DogResolvers, DefinedFields['Dog'] | '__isTypeOf'>;
`);
// Elephant picks `__isTypeOf` because it is an implementing type of Pet, via `extend type `
expect(output).toBeSimilarStringTo(`
export type ElephantResolvers = Pick<core.ElephantResolvers, DefinedFields['Elephant'] | '__isTypeOf'>;
`);

// Discount picks `__isTypeOf` because it is a union member
expect(output).toBeSimilarStringTo(`
export type DiscountResolvers = Pick<core.DiscountResolvers, DefinedFields['Discount'] | '__isTypeOf'>;
`);
// Coupon picks `__isTypeOf` because it is a union member
expect(output).toBeSimilarStringTo(`
export type CouponResolvers = Pick<core.CouponResolvers, DefinedFields['Coupon'] | '__isTypeOf'>;
`);
});
4 changes: 2 additions & 2 deletions packages/presets/graphql-modules/tests/integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('Integration', () => {
test('should not duplicate type even if type and extend type are in the same module', async () => {
const { result } = await executeCodegen(options);

const userResolversStr = `export type UserResolvers = Pick<Types.UserResolvers, DefinedFields['User'] | '__isTypeOf'>;`;
const userResolversStr = `export type UserResolvers = Pick<Types.UserResolvers, DefinedFields['User']>;`;
const nbOfTimeUserResolverFound = result[4].content.split(userResolversStr).length - 1;

expect(nbOfTimeUserResolverFound).toBe(1);
Expand Down Expand Up @@ -176,7 +176,7 @@ describe('Integration', () => {

// Only Query related properties should be required
expect(usersModuleOutput.content).toBeSimilarStringTo(`
export type UserResolvers = Pick<Types.UserResolvers, DefinedFields['User'] | '__isTypeOf'>;
export type UserResolvers = Pick<Types.UserResolvers, DefinedFields['User']>;
export type QueryResolvers = Required<Pick<Types.QueryResolvers, DefinedFields['Query']>>;
`);
expect(usersModuleOutput.content).toBeSimilarStringTo(`
Expand Down
Loading