Skip to content

Commit c062fd8

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 4ce7cde commit c062fd8

11 files changed

Lines changed: 234 additions & 346 deletions

File tree

.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,8 +7,7 @@ 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 { CustomDirectivesConfig, NormalizedScalarsMap } from './types.js';
@@ -20,35 +19,24 @@ import {
2019
} from './utils.js';
2120
import { OperationVariablesToObject } from './variables-to-object.js';
2221

23-
function getRootType(operation: OperationTypeNode, schema: GraphQLSchema) {
24-
switch (operation) {
25-
case 'query':
26-
return schema.getQueryType();
27-
case 'mutation':
28-
return schema.getMutationType();
29-
case 'subscription':
30-
return schema.getSubscriptionType();
31-
}
32-
throw new Error(`Unknown operation type: ${operation}`);
33-
}
34-
35-
export interface ParsedDocumentsConfig extends ParsedTypesConfig {
22+
export interface ParsedDocumentsConfig extends ParsedConfig {
3623
extractAllFieldsToTypes: boolean;
37-
globalNamespace: boolean;
3824
operationResultSuffix: string;
3925
dedupeOperationSuffix: boolean;
4026
omitOperationSuffix: boolean;
4127
namespacedImportName: string | null;
4228
exportFragmentSpreadSubTypes: boolean;
4329
skipTypeNameForRoot: boolean;
30+
nonOptionalTypename: boolean;
31+
globalNamespace: boolean;
4432
experimentalFragmentVariables: boolean;
4533
mergeFragmentTypes: boolean;
4634
customDirectives: CustomDirectivesConfig;
4735
generatesOperationTypes: boolean;
4836
importSchemaTypesFrom: string;
4937
}
5038

51-
export interface RawDocumentsConfig extends RawTypesConfig {
39+
export interface RawDocumentsConfig extends RawConfig {
5240
/**
5341
* @default false
5442
* @description Avoid adding `__typename` for root types. This is ignored when a selection explicitly specifies `__typename`.
@@ -72,6 +60,30 @@ export interface RawDocumentsConfig extends RawTypesConfig {
7260
* ```
7361
*/
7462
skipTypeNameForRoot?: boolean;
63+
/**
64+
* @default false
65+
* @description Automatically adds `__typename` field to the generated types, even when they are not specified
66+
* in the selection set, and makes it non-optional
67+
*
68+
* @exampleMarkdown
69+
* ```ts filename="codegen.ts"
70+
* import type { CodegenConfig } from '@graphql-codegen/cli';
71+
*
72+
* const config: CodegenConfig = {
73+
* // ...
74+
* generates: {
75+
* 'path/to/file': {
76+
* // plugins...
77+
* config: {
78+
* nonOptionalTypename: true
79+
* },
80+
* },
81+
* },
82+
* };
83+
* export default config;
84+
* ```
85+
*/
86+
nonOptionalTypename?: boolean;
7587
/**
7688
* @default false
7789
* @description Puts all generated code under `global` namespace. Useful for Stencil integration.
@@ -204,6 +216,14 @@ export interface RawDocumentsConfig extends RawTypesConfig {
204216
* ```
205217
*/
206218
importSchemaTypesFrom?: string;
219+
/**
220+
* @default false
221+
* @description Extract all field types to their own types, instead of inlining them.
222+
* This helps to reduce type duplication, and makes type errors more readable.
223+
* It can also significantly reduce the size of the generated code, the generation time,
224+
* and the typechecking time.
225+
*/
226+
extractAllFieldsToTypes?: boolean;
207227
}
208228

209229
export class BaseDocumentsVisitor<
@@ -223,11 +243,10 @@ export class BaseDocumentsVisitor<
223243
) {
224244
super(rawConfig, {
225245
exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false),
226-
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
227-
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
228246
dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false),
229247
omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false),
230248
skipTypeNameForRoot: getConfigValue(rawConfig.skipTypeNameForRoot, false),
249+
nonOptionalTypename: getConfigValue(rawConfig.nonOptionalTypename, false),
231250
namespacedImportName: getConfigValue(rawConfig.namespacedImportName, null),
232251
experimentalFragmentVariables: getConfigValue(rawConfig.experimentalFragmentVariables, false),
233252
globalNamespace: !!rawConfig.globalNamespace,
@@ -238,6 +257,7 @@ export class BaseDocumentsVisitor<
238257
}),
239258
generatesOperationTypes: getConfigValue(rawConfig.generatesOperationTypes, true),
240259
importSchemaTypesFrom: getConfigValue(rawConfig.importSchemaTypesFrom, ''),
260+
extractAllFieldsToTypes: getConfigValue(rawConfig.extractAllFieldsToTypes, false),
241261
...((additionalConfig || {}) as any),
242262
});
243263

@@ -394,3 +414,15 @@ export class BaseDocumentsVisitor<
394414
.join('\n\n');
395415
}
396416
}
417+
418+
function getRootType(operation: OperationTypeNode, schema: GraphQLSchema) {
419+
switch (operation) {
420+
case 'query':
421+
return schema.getQueryType();
422+
case 'mutation':
423+
return schema.getMutationType();
424+
case 'subscription':
425+
return schema.getSubscriptionType();
426+
}
427+
throw new Error(`Unknown operation type: ${operation}`);
428+
}

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
@@ -79,8 +79,6 @@ export interface ParsedResolversConfig extends ParsedConfig {
7979
enumValues: ParsedEnumValuesMap;
8080
resolverTypeWrapperSignature: string;
8181
federation: boolean;
82-
enumPrefix: boolean;
83-
enumSuffix: boolean;
8482
optionalResolveType: boolean;
8583
immutableTypes: boolean;
8684
namespacedImportName: string;
@@ -522,59 +520,7 @@ export interface RawResolversConfig extends RawConfig {
522520
* @description Supports Apollo Federation
523521
*/
524522
federation?: boolean;
525-
/**
526-
* @default true
527-
* @description Allow you to disable prefixing for generated enums, works in combination with `typesPrefix`.
528-
*
529-
* @exampleMarkdown
530-
* ## Disable enum prefixes
531-
*
532-
* ```ts filename="codegen.ts"
533-
* import type { CodegenConfig } from '@graphql-codegen/cli';
534-
*
535-
* const config: CodegenConfig = {
536-
* // ...
537-
* generates: {
538-
* 'path/to/file': {
539-
* plugins: ['typescript', 'typescript-resolver'],
540-
* config: {
541-
* typesPrefix: 'I',
542-
* enumPrefix: false
543-
* },
544-
* },
545-
* },
546-
* };
547-
* export default config;
548-
* ```
549-
*/
550-
enumPrefix?: boolean;
551523

552-
/**
553-
* @default true
554-
* @description Allow you to disable suffixing for generated enums, works in combination with `typesSuffix`.
555-
*
556-
* @exampleMarkdown
557-
* ## Disable enum suffixes
558-
*
559-
* ```ts filename="codegen.ts"
560-
* import type { CodegenConfig } from '@graphql-codegen/cli';
561-
*
562-
* const config: CodegenConfig = {
563-
* // ...
564-
* generates: {
565-
* 'path/to/file': {
566-
* plugins: ['typescript', 'typescript-resolver'],
567-
* config: {
568-
* typesSuffix: 'I',
569-
* enumSuffix: false
570-
* },
571-
* },
572-
* },
573-
* };
574-
* export default config;
575-
* ```
576-
*/
577-
enumSuffix?: boolean;
578524
/**
579525
* @description Configures behavior for custom directives from various GraphQL libraries.
580526
* @exampleMarkdown
@@ -811,8 +757,6 @@ export class BaseResolversVisitor<
811757
super(rawConfig, {
812758
immutableTypes: getConfigValue(rawConfig.immutableTypes, false),
813759
optionalResolveType: getConfigValue(rawConfig.optionalResolveType, false),
814-
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
815-
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
816760
federation: getConfigValue(rawConfig.federation, false),
817761
resolverTypeWrapperSignature: getConfigValue(
818762
rawConfig.resolverTypeWrapperSignature,

0 commit comments

Comments
 (0)