Skip to content

Commit c2be6b3

Browse files
committed
Adjust config inheritance to reflect usage and type-hint better (#10560)
* Refactor utility function to match practice * Fix config option inheritance - addTypename/skipTypename: is only a types-visitor concern. This is moved to types-visitor from base-visitor - nonOptionalTypename: is a documents-visitor and types-visitor concern. Moved from base-visitor there - extractAllFieldsToTypes: is a documents-visitor concern. Moved from base-visitor there - enumPrefix and enumSuffix: need to be in base-visitor as all 3 types of visitors need this to correctly sync the enum type names. This is moved to base visitor - ignoreEnumValuesFromSchema: is a documents-visitor and types-visitor concern. Moved from base-visitor there. - globalNamespace: is a documents-visitor concern. Moved from base-visitor there Other changes: - documents-visitor no longer extends types-visitor _option types_ as they have two distinct usages now. The types now extend base-visitor types. This is now consistent with documents-visitor extending base-visitor - Classes now handle config parsing and types at the same level e.g. if typescript-operations plugin parses configOne, then the types for configOne must be in that class, rather than in base-documents-visitor * Remove references and tests related to skipTypename in operations plugin * Add changeset
1 parent fdaf5d6 commit c2be6b3

File tree

11 files changed

+233
-436
lines changed

11 files changed

+233
-436
lines changed

.changeset/brown-things-jump.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': major
3+
'@graphql-codegen/typescript-operations': major
4+
'@graphql-codegen/typescript': major
5+
'@graphql-codegen/typescript-resolvers': major
6+
---
7+
8+
BREAKING CHANGE: visitors' config option are moved based on their use case
9+
10+
- addTypename/skipTypename: is only a types-visitor concern. This is moved to types-visitor from base-visitor
11+
- nonOptionalTypename: is a documents-visitor and types-visitor concern. Moved from base-visitor there
12+
- extractAllFieldsToTypes: is a documents-visitor concern. Moved from base-visitor there
13+
- enumPrefix and enumSuffix: need to be in base-visitor as all 3 types of visitors need this to correctly sync the enum type names. This is moved to base visitor
14+
- ignoreEnumValuesFromSchema: is a documents-visitor and types-visitor concern. Moved from base-visitor there.
15+
- globalNamespace: is a documents-visitor concern. Moved from base-visitor there
16+
17+
Refactors
18+
19+
- documents-visitor no longer extends types-visitor _option types_ as they have two distinct usages now. The types now extend base-visitor types. This is now consistent with documents-visitor extending base-visitor
20+
- Classes now handle config parsing and types at the same level e.g. if typescript-operations plugin parses configOne, then the types for configOne must be in that class, rather than in base-documents-visitor
21+
22+
Note: These visitors are rolled up into one type for simplicity
23+
24+
- base-visitor: includes `base-visitor`
25+
- documents-visitor: includes `base-documents-visitor` and `typescript-operations` visitor
26+
- types-visitor: includes `base-types-visitor` and `typescript` visitor
27+
- resolvers-visitor: includes `base-resolvers-visitor` and `typescript-resolvers` visitor

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

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,31 @@ import {
77
OperationTypeNode,
88
VariableDefinitionNode,
99
} from 'graphql';
10-
import { ParsedTypesConfig, RawTypesConfig } from './base-types-visitor.js';
11-
import { BaseVisitor } from './base-visitor.js';
10+
import { BaseVisitor, type RawConfig, type ParsedConfig } from './base-visitor.js';
1211
import { DEFAULT_SCALARS } from './scalars.js';
1312
import { SelectionSetToObject } from './selection-set-to-object.js';
1413
import { NormalizedScalarsMap, CustomDirectivesConfig } from './types.js';
1514
import { buildScalarsFromConfig, DeclarationBlock, DeclarationBlockConfig, getConfigValue } from './utils.js';
1615
import { OperationVariablesToObject } from './variables-to-object.js';
1716

18-
function getRootType(operation: OperationTypeNode, schema: GraphQLSchema) {
19-
switch (operation) {
20-
case 'query':
21-
return schema.getQueryType();
22-
case 'mutation':
23-
return schema.getMutationType();
24-
case 'subscription':
25-
return schema.getSubscriptionType();
26-
}
27-
throw new Error(`Unknown operation type: ${operation}`);
28-
}
29-
30-
export interface ParsedDocumentsConfig extends ParsedTypesConfig {
17+
export interface ParsedDocumentsConfig extends ParsedConfig {
3118
extractAllFieldsToTypes: boolean;
32-
globalNamespace: boolean;
3319
operationResultSuffix: string;
3420
dedupeOperationSuffix: boolean;
3521
omitOperationSuffix: boolean;
3622
namespacedImportName: string | null;
3723
exportFragmentSpreadSubTypes: boolean;
3824
skipTypeNameForRoot: boolean;
25+
nonOptionalTypename: boolean;
26+
globalNamespace: boolean;
3927
experimentalFragmentVariables: boolean;
4028
mergeFragmentTypes: boolean;
4129
customDirectives: CustomDirectivesConfig;
4230
generatesOperationTypes: boolean;
4331
importSchemaTypesFrom: string;
4432
}
4533

46-
export interface RawDocumentsConfig extends RawTypesConfig {
34+
export interface RawDocumentsConfig extends RawConfig {
4735
/**
4836
* @default false
4937
* @description Avoid adding `__typename` for root types. This is ignored when a selection explicitly specifies `__typename`.
@@ -67,6 +55,30 @@ export interface RawDocumentsConfig extends RawTypesConfig {
6755
* ```
6856
*/
6957
skipTypeNameForRoot?: boolean;
58+
/**
59+
* @default false
60+
* @description Automatically adds `__typename` field to the generated types, even when they are not specified
61+
* in the selection set, and makes it non-optional
62+
*
63+
* @exampleMarkdown
64+
* ```ts filename="codegen.ts"
65+
* import type { CodegenConfig } from '@graphql-codegen/cli';
66+
*
67+
* const config: CodegenConfig = {
68+
* // ...
69+
* generates: {
70+
* 'path/to/file': {
71+
* // plugins...
72+
* config: {
73+
* nonOptionalTypename: true
74+
* },
75+
* },
76+
* },
77+
* };
78+
* export default config;
79+
* ```
80+
*/
81+
nonOptionalTypename?: boolean;
7082
/**
7183
* @default false
7284
* @description Puts all generated code under `global` namespace. Useful for Stencil integration.
@@ -199,6 +211,14 @@ export interface RawDocumentsConfig extends RawTypesConfig {
199211
* ```
200212
*/
201213
importSchemaTypesFrom?: string;
214+
/**
215+
* @default false
216+
* @description Extract all field types to their own types, instead of inlining them.
217+
* This helps to reduce type duplication, and makes type errors more readable.
218+
* It can also significantly reduce the size of the generated code, the generation time,
219+
* and the typechecking time.
220+
*/
221+
extractAllFieldsToTypes?: boolean;
202222
}
203223

204224
export class BaseDocumentsVisitor<
@@ -218,11 +238,10 @@ export class BaseDocumentsVisitor<
218238
) {
219239
super(rawConfig, {
220240
exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false),
221-
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
222-
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
223241
dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false),
224242
omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false),
225243
skipTypeNameForRoot: getConfigValue(rawConfig.skipTypeNameForRoot, false),
244+
nonOptionalTypename: getConfigValue(rawConfig.nonOptionalTypename, false),
226245
namespacedImportName: getConfigValue(rawConfig.namespacedImportName, null),
227246
experimentalFragmentVariables: getConfigValue(rawConfig.experimentalFragmentVariables, false),
228247
globalNamespace: !!rawConfig.globalNamespace,
@@ -231,6 +250,7 @@ export class BaseDocumentsVisitor<
231250
customDirectives: getConfigValue(rawConfig.customDirectives, { apolloUnmask: false }),
232251
generatesOperationTypes: getConfigValue(rawConfig.generatesOperationTypes, true),
233252
importSchemaTypesFrom: getConfigValue(rawConfig.importSchemaTypesFrom, ''),
253+
extractAllFieldsToTypes: getConfigValue(rawConfig.extractAllFieldsToTypes, false),
234254
...((additionalConfig || {}) as any),
235255
});
236256

@@ -380,3 +400,15 @@ export class BaseDocumentsVisitor<
380400
.join('\n\n');
381401
}
382402
}
403+
404+
function getRootType(operation: OperationTypeNode, schema: GraphQLSchema) {
405+
switch (operation) {
406+
case 'query':
407+
return schema.getQueryType();
408+
case 'mutation':
409+
return schema.getMutationType();
410+
case 'subscription':
411+
return schema.getSubscriptionType();
412+
}
413+
throw new Error(`Unknown operation type: ${operation}`);
414+
}

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

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ export interface ParsedResolversConfig extends ParsedConfig {
6969
enumValues: ParsedEnumValuesMap;
7070
resolverTypeWrapperSignature: string;
7171
federation: boolean;
72-
enumPrefix: boolean;
73-
enumSuffix: boolean;
7472
optionalResolveType: boolean;
7573
immutableTypes: boolean;
7674
namespacedImportName: string;
@@ -509,59 +507,7 @@ export interface RawResolversConfig extends RawConfig {
509507
* @description Supports Apollo Federation
510508
*/
511509
federation?: boolean;
512-
/**
513-
* @default true
514-
* @description Allow you to disable prefixing for generated enums, works in combination with `typesPrefix`.
515-
*
516-
* @exampleMarkdown
517-
* ## Disable enum prefixes
518-
*
519-
* ```ts filename="codegen.ts"
520-
* import type { CodegenConfig } from '@graphql-codegen/cli';
521-
*
522-
* const config: CodegenConfig = {
523-
* // ...
524-
* generates: {
525-
* 'path/to/file': {
526-
* plugins: ['typescript', 'typescript-resolver'],
527-
* config: {
528-
* typesPrefix: 'I',
529-
* enumPrefix: false
530-
* },
531-
* },
532-
* },
533-
* };
534-
* export default config;
535-
* ```
536-
*/
537-
enumPrefix?: boolean;
538510

539-
/**
540-
* @default true
541-
* @description Allow you to disable suffixing for generated enums, works in combination with `typesSuffix`.
542-
*
543-
* @exampleMarkdown
544-
* ## Disable enum suffixes
545-
*
546-
* ```ts filename="codegen.ts"
547-
* import type { CodegenConfig } from '@graphql-codegen/cli';
548-
*
549-
* const config: CodegenConfig = {
550-
* // ...
551-
* generates: {
552-
* 'path/to/file': {
553-
* plugins: ['typescript', 'typescript-resolver'],
554-
* config: {
555-
* typesSuffix: 'I',
556-
* enumSuffix: false
557-
* },
558-
* },
559-
* },
560-
* };
561-
* export default config;
562-
* ```
563-
*/
564-
enumSuffix?: boolean;
565511
/**
566512
* @description Configures behavior for custom directives from various GraphQL libraries.
567513
* @exampleMarkdown
@@ -795,8 +741,6 @@ export class BaseResolversVisitor<
795741
super(rawConfig, {
796742
immutableTypes: getConfigValue(rawConfig.immutableTypes, false),
797743
optionalResolveType: getConfigValue(rawConfig.optionalResolveType, false),
798-
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
799-
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
800744
federation: getConfigValue(rawConfig.federation, false),
801745
resolverTypeWrapperSignature: getConfigValue(rawConfig.resolverTypeWrapperSignature, 'Promise<T> | T'),
802746
enumValues: parseEnumValues({

0 commit comments

Comments
 (0)