Skip to content

Commit ae8e835

Browse files
authored
Merge branch 'master' into update-typescript-input-output-type
2 parents eb4264c + 50471e6 commit ae8e835

File tree

8 files changed

+157
-6
lines changed

8 files changed

+157
-6
lines changed

.changeset/long-owls-matter.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
'@graphql-codegen/visitor-plugin-common': minor
3+
'@graphql-codegen/typescript-resolvers': minor
4+
---
5+
6+
Add excludeTypes config to resolversNonOptionalTypename
7+
8+
This disables the adding of `__typename` in resolver types for any specified typename. This could be useful e.g. if you're wanting to enable this for all new types going forward but not do a big migration.
9+
10+
Usage example:
11+
12+
```typescript
13+
const config: CodegenConfig = {
14+
schema: 'src/schema/**/*.graphql',
15+
generates: {
16+
'src/schema/types.ts': {
17+
plugins: ['typescript', 'typescript-resolvers'],
18+
config: {
19+
resolversNonOptionalTypename: {
20+
unionMember: true,
21+
excludeTypes: ['MyType'],
22+
}
23+
}
24+
},
25+
},
26+
};
27+
```

.changeset/quiet-rocks-sin.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphql-codegen/cli': patch
3+
---
4+
5+
Fixed option ignoreNoDocuments when using graphql configs

packages/graphql-codegen-cli/src/codegen.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,20 @@ export async function executeCodegen(input: CodegenContext | Types.Config): Prom
274274

275275
const hash = JSON.stringify(documentPointerMap);
276276
const result = await cache('documents', hash, async () => {
277-
const documents = await context.loadDocuments(documentPointerMap);
278-
return {
279-
documents,
280-
};
277+
try {
278+
const documents = await context.loadDocuments(documentPointerMap);
279+
return {
280+
documents,
281+
};
282+
} catch (error) {
283+
if (config.ignoreNoDocuments) {
284+
return {
285+
documents: [],
286+
};
287+
}
288+
289+
throw error;
290+
}
281291
});
282292

283293
outputDocuments = result.documents;

packages/graphql-codegen-cli/tests/generate-and-save.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Types } from '@graphql-codegen/plugin-helpers';
33
import { useMonorepo } from '@graphql-codegen/testing';
44
import makeDir from 'make-dir';
55
import { generate } from '../src/generate-and-save.js';
6+
import { createContext } from '../src/config.js';
67
import * as fs from '../src/utils/file-system.js';
78

89
const SIMPLE_TEST_SCHEMA = `type MyType { f: String } type Query { f: String }`;
@@ -76,6 +77,22 @@ describe('generate-and-save', () => {
7677
expect(writeSpy).not.toHaveBeenCalled();
7778
});
7879

80+
test('should not error when ignoreNoDocuments config option is present', async () => {
81+
jest.spyOn(fs, 'writeFile').mockImplementation();
82+
const config = await createContext({
83+
config: './tests/test-files/graphql.config.json',
84+
project: undefined,
85+
errorsOnly: true,
86+
overwrite: true,
87+
profile: true,
88+
require: [],
89+
silent: false,
90+
watch: false,
91+
});
92+
93+
await generate(config, false);
94+
});
95+
7996
test('should use global overwrite option and write a file', async () => {
8097
const filename = 'overwrite.ts';
8198
const writeSpy = jest.spyOn(fs, 'writeFile').mockImplementation();
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"schema": ["../test-documents/schema.graphql"],
3+
"documents": ["../test-documents/empty.graphql"],
4+
"extensions": {
5+
"codegen": {
6+
"ignoreNoDocuments": true,
7+
"generates": {
8+
"./gql/": {
9+
"preset": "client"
10+
}
11+
}
12+
}
13+
}
14+
}

packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,49 @@ export interface RawResolversConfig extends RawConfig {
542542
/**
543543
* @description Makes `__typename` of resolver mappings non-optional without affecting the base types.
544544
* @default false
545+
*
546+
* @exampleMarkdown
547+
* ## Enable for all
548+
*
549+
* ```ts filename="codegen.ts"
550+
* import type { CodegenConfig } from '@graphql-codegen/cli';
551+
*
552+
* const config: CodegenConfig = {
553+
* // ...
554+
* generates: {
555+
* 'path/to/file': {
556+
* plugins: ['typescript', 'typescript-resolver'],
557+
* config: {
558+
* resolversNonOptionalTypename: true // or { unionMember: true, interfaceImplementingType: true }
559+
* },
560+
* },
561+
* },
562+
* };
563+
* export default config;
564+
* ```
565+
*
566+
* ## Enable except for some types
567+
*
568+
* ```ts filename="codegen.ts"
569+
* import type { CodegenConfig } from '@graphql-codegen/cli';
570+
*
571+
* const config: CodegenConfig = {
572+
* // ...
573+
* generates: {
574+
* 'path/to/file': {
575+
* plugins: ['typescript', 'typescript-resolver'],
576+
* config: {
577+
* resolversNonOptionalTypename: {
578+
* unionMember: true,
579+
* interfaceImplementingType: true,
580+
* excludeTypes: ['MyType'],
581+
* }
582+
* },
583+
* },
584+
* },
585+
* };
586+
* export default config;
587+
* ```
545588
*/
546589
resolversNonOptionalTypename?: boolean | ResolversNonOptionalTypenameConfig;
547590
/**
@@ -876,10 +919,11 @@ export class BaseResolversVisitor<
876919
const schemaType = allSchemaTypes[typeName];
877920

878921
if (isUnionType(schemaType)) {
922+
const { unionMember, excludeTypes } = this.config.resolversNonOptionalTypename;
879923
res[typeName] = this.getAbstractMembersType({
880924
typeName,
881925
memberTypes: schemaType.getTypes(),
882-
isTypenameNonOptional: this.config.resolversNonOptionalTypename.unionMember,
926+
isTypenameNonOptional: unionMember && !excludeTypes?.includes(typeName),
883927
});
884928
}
885929
return res;
@@ -913,10 +957,12 @@ export class BaseResolversVisitor<
913957
}
914958
}
915959

960+
const { interfaceImplementingType, excludeTypes } = this.config.resolversNonOptionalTypename;
961+
916962
res[typeName] = this.getAbstractMembersType({
917963
typeName,
918964
memberTypes: implementingTypes,
919-
isTypenameNonOptional: this.config.resolversNonOptionalTypename.interfaceImplementingType,
965+
isTypenameNonOptional: interfaceImplementingType && !excludeTypes?.includes(typeName),
920966
});
921967
}
922968

packages/plugins/other/visitor-plugin-common/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,5 @@ export type FragmentDirectives = {
120120
export interface ResolversNonOptionalTypenameConfig {
121121
unionMember?: boolean;
122122
interfaceImplementingType?: boolean;
123+
excludeTypes?: string[];
123124
}

packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,37 @@ export type MyTypeResolvers<ContextType = any, ParentType extends ResolversParen
431431

432432
expect(result.content).not.toBeSimilarStringTo('export type ResolversInterfaceTypes');
433433
});
434+
435+
it('resolversNonOptionalTypename - excludes types', async () => {
436+
const result = await plugin(
437+
resolversTestingSchema,
438+
[],
439+
{
440+
resolversNonOptionalTypename: {
441+
unionMember: true,
442+
interfaceImplementingType: true,
443+
excludeTypes: ['ChildUnion', 'AnotherNode', 'Node'],
444+
},
445+
},
446+
{ outputFile: '' }
447+
);
448+
449+
expect(result.content).toBeSimilarStringTo(`
450+
export type ResolversUnionTypes<RefType extends Record<string, unknown>> = {
451+
ChildUnion: ( Child ) | ( MyOtherType );
452+
MyUnion: ( Omit<MyType, 'unionChild'> & { unionChild?: Maybe<RefType['ChildUnion']> } & { __typename: 'MyType' } ) | ( MyOtherType & { __typename: 'MyOtherType' } );
453+
};
454+
`);
455+
456+
expect(result.content).toBeSimilarStringTo(`
457+
export type ResolversInterfaceTypes<RefType extends Record<string, unknown>> = {
458+
Node: ( SomeNode );
459+
AnotherNode: ( Omit<AnotherNodeWithChild, 'unionChild'> & { unionChild?: Maybe<RefType['ChildUnion']> } ) | ( Omit<AnotherNodeWithAll, 'unionChild' | 'unionChildren'> & { unionChild?: Maybe<RefType['ChildUnion']>, unionChildren: Array<RefType['ChildUnion']> } );
460+
WithChild: ( Omit<AnotherNodeWithChild, 'unionChild'> & { unionChild?: Maybe<RefType['ChildUnion']> } & { __typename: 'AnotherNodeWithChild' } ) | ( Omit<AnotherNodeWithAll, 'unionChild' | 'unionChildren'> & { unionChild?: Maybe<RefType['ChildUnion']>, unionChildren: Array<RefType['ChildUnion']> } & { __typename: 'AnotherNodeWithAll' } );
461+
WithChildren: ( Omit<AnotherNodeWithAll, 'unionChild' | 'unionChildren'> & { unionChild?: Maybe<RefType['ChildUnion']>, unionChildren: Array<RefType['ChildUnion']> } & { __typename: 'AnotherNodeWithAll' } );
462+
};
463+
`);
464+
});
434465
});
435466

436467
it('directiveResolverMappings - should generate correct types (import definition)', async () => {

0 commit comments

Comments
 (0)