Skip to content

Commit e1dc75f

Browse files
esfomeadosaihajbeerose
authored
Added support for enumSuffix (#9304)
Co-authored-by: Saihajpreet Singh <[email protected]> Co-authored-by: Aleksandra <[email protected]>
1 parent 4d9ea1a commit e1dc75f

File tree

15 files changed

+222
-5
lines changed

15 files changed

+222
-5
lines changed

.changeset/swift-hornets-camp.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@graphql-codegen/typescript-operations": minor
3+
"@graphql-codegen/typescript-resolvers": minor
4+
"@graphql-codegen/typescript": minor
5+
"@graphql-codegen/visitor-plugin-common": minor
6+
---
7+
8+
Added support for disabling suffixes on Enums.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ export class BaseDocumentsVisitor<
168168
super(rawConfig, {
169169
exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false),
170170
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
171+
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
171172
preResolveTypes: getConfigValue(rawConfig.preResolveTypes, true),
172173
dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false),
173174
omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false),

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

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export interface ParsedResolversConfig extends ParsedConfig {
6666
resolverTypeWrapperSignature: string;
6767
federation: boolean;
6868
enumPrefix: boolean;
69+
enumSuffix: boolean;
6970
optionalResolveType: boolean;
7071
immutableTypes: boolean;
7172
namespacedImportName: string;
@@ -500,6 +501,33 @@ export interface RawResolversConfig extends RawConfig {
500501
* ```
501502
*/
502503
enumPrefix?: boolean;
504+
505+
/**
506+
* @default true
507+
* @description Allow you to disable suffixing for generated enums, works in combination with `typesSuffix`.
508+
*
509+
* @exampleMarkdown
510+
* ## Disable enum suffixes
511+
*
512+
* ```ts filename="codegen.ts"
513+
* import type { CodegenConfig } from '@graphql-codegen/cli';
514+
*
515+
* const config: CodegenConfig = {
516+
* // ...
517+
* generates: {
518+
* 'path/to/file': {
519+
* plugins: ['typescript', 'typescript-resolver'],
520+
* config: {
521+
* typesSuffix: 'I',
522+
* enumSuffix: false
523+
* },
524+
* },
525+
* },
526+
* };
527+
* export default config;
528+
* ```
529+
*/
530+
enumSuffix?: boolean;
503531
/**
504532
* @default false
505533
* @description Sets the `__resolveType` field as optional field.
@@ -635,6 +663,7 @@ export class BaseResolversVisitor<
635663
immutableTypes: getConfigValue(rawConfig.immutableTypes, false),
636664
optionalResolveType: getConfigValue(rawConfig.optionalResolveType, false),
637665
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
666+
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
638667
federation: getConfigValue(rawConfig.federation, false),
639668
resolverTypeWrapperSignature: getConfigValue(rawConfig.resolverTypeWrapperSignature, 'Promise<T> | T'),
640669
enumValues: parseEnumValues({
@@ -816,7 +845,14 @@ export class BaseResolversVisitor<
816845
const generic = this.convertName(currentType);
817846
prev[typeName] = applyWrapper(`${type}<${generic}>['${typeName}']`);
818847
} else if (isEnumType(schemaType)) {
819-
prev[typeName] = this.convertName(typeName, { useTypesPrefix: this.config.enumPrefix }, true);
848+
prev[typeName] = this.convertName(
849+
typeName,
850+
{
851+
useTypesPrefix: this.config.enumPrefix,
852+
useTypesSuffix: this.config.enumSuffix,
853+
},
854+
true
855+
);
820856
} else {
821857
prev[typeName] = this.convertName(typeName, {}, true);
822858

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

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export interface ParsedTypesConfig extends ParsedConfig {
5353
onlyEnums: boolean;
5454
onlyOperationTypes: boolean;
5555
enumPrefix: boolean;
56+
enumSuffix: boolean;
5657
fieldWrapperValue: string;
5758
wrapFieldDefinitions: boolean;
5859
entireFieldWrapperValue: string;
@@ -226,6 +227,32 @@ export interface RawTypesConfig extends RawConfig {
226227
* ```
227228
*/
228229
enumPrefix?: boolean;
230+
/**
231+
* @default true
232+
* @description Allow you to disable suffixing for generated enums, works in combination with `typesSuffix`.
233+
*
234+
* @exampleMarkdown
235+
* ## Disable enum suffixes
236+
*
237+
* ```ts filename="codegen.ts"
238+
* import type { CodegenConfig } from '@graphql-codegen/cli';
239+
*
240+
* const config: CodegenConfig = {
241+
* // ...
242+
* generates: {
243+
* 'path/to/file': {
244+
* // plugins...
245+
* config: {
246+
* typesSuffix: 'I',
247+
* enumSuffix: false
248+
* },
249+
* },
250+
* },
251+
* };
252+
* export default config;
253+
* ```
254+
*/
255+
enumSuffix?: boolean;
229256
/**
230257
* @description Allow you to add wrapper for field type, use T as the generic value. Make sure to set `wrapFieldDefinitions` to `true` in order to make this flag work.
231258
* @default T
@@ -482,6 +509,7 @@ export class BaseTypesVisitor<
482509
) {
483510
super(rawConfig, {
484511
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
512+
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
485513
onlyEnums: getConfigValue(rawConfig.onlyEnums, false),
486514
onlyOperationTypes: getConfigValue(rawConfig.onlyOperationTypes, false),
487515
addUnderscoreToArgsType: getConfigValue(rawConfig.addUnderscoreToArgsType, false),
@@ -855,7 +883,12 @@ export class BaseTypesVisitor<
855883
return new DeclarationBlock(this._declarationBlockConfig)
856884
.export()
857885
.asKind('enum')
858-
.withName(this.convertName(node, { useTypesPrefix: this.config.enumPrefix }))
886+
.withName(
887+
this.convertName(node, {
888+
useTypesPrefix: this.config.enumPrefix,
889+
useTypesSuffix: this.config.enumSuffix,
890+
})
891+
)
859892
.withComment(node.description as any as string)
860893
.withBlock(this.buildEnumValuesBlock(enumName, node.values)).string;
861894
}
@@ -993,7 +1026,10 @@ export class BaseTypesVisitor<
9931026
const schemaType = this._schema.getType(node.name as any);
9941027

9951028
if (schemaType && isEnumType(schemaType)) {
996-
return this.convertName(node, { useTypesPrefix: this.config.enumPrefix });
1029+
return this.convertName(node, {
1030+
useTypesPrefix: this.config.enumPrefix,
1031+
useTypesSuffix: this.config.enumSuffix,
1032+
});
9971033
}
9981034

9991035
return this.convertName(node);

packages/plugins/other/visitor-plugin-common/src/selection-set-processor/base.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export type SelectionSetProcessorConfig = {
1111
namespacedImportName: string | null;
1212
convertName: ConvertNameFn<any>;
1313
enumPrefix: boolean | null;
14+
enumSuffix: boolean | null;
1415
scalars: NormalizedScalarsMap;
1516
formatNamedField(
1617
name: string,

packages/plugins/other/visitor-plugin-common/src/selection-set-processor/pre-resolve-types.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ export class PreResolveTypesProcessor extends BaseSelectionSetProcessor<Selectio
5454
if (isEnumType(baseType)) {
5555
typeToUse =
5656
(this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : '') +
57-
this.config.convertName(baseType.name, { useTypesPrefix: this.config.enumPrefix });
57+
this.config.convertName(baseType.name, {
58+
useTypesPrefix: this.config.enumPrefix,
59+
useTypesSuffix: this.config.enumSuffix,
60+
});
5861
} else if (this.config.scalars[baseType.name]) {
5962
typeToUse = this.config.scalars[baseType.name].output;
6063
}
@@ -92,7 +95,10 @@ export class PreResolveTypesProcessor extends BaseSelectionSetProcessor<Selectio
9295
if (isEnumType(baseType)) {
9396
typeToUse =
9497
(this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : '') +
95-
this.config.convertName(baseType.name, { useTypesPrefix: this.config.enumPrefix });
98+
this.config.convertName(baseType.name, {
99+
useTypesPrefix: this.config.enumPrefix,
100+
useTypesSuffix: this.config.enumSuffix,
101+
});
96102
}
97103

98104
const name = this.config.formatNamedField(aliasedField.alias, fieldObj.type, undefined, unsetTypes);

packages/plugins/other/visitor-plugin-common/src/variables-to-object.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export class OperationVariablesToObject {
2424
protected _namespacedImportName: string | null = null,
2525
protected _enumNames: string[] = [],
2626
protected _enumPrefix = true,
27+
protected _enumSuffix = true,
2728
protected _enumValues: ParsedEnumValuesMap = {},
2829
protected _applyCoercion: Boolean = false,
2930
protected _directiveArgumentAndInputFieldMappings: ParsedDirectiveArgumentAndInputFieldMappings = {}
@@ -104,6 +105,7 @@ export class OperationVariablesToObject {
104105
} else {
105106
typeValue = `${prefix}${this._convertName(baseType, {
106107
useTypesPrefix: this._enumNames.includes(typeName) ? this._enumPrefix : true,
108+
useTypesSuffix: this._enumNames.includes(typeName) ? this._enumSuffix : true,
107109
})}`;
108110
}
109111
}

packages/plugins/other/visitor-plugin-common/tests/create-resolvers-fields.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,31 @@ export type IResolversParentTypes = {
8080
Boolean: Scalars['Boolean']['output']
8181
String: Scalars['String']['output']
8282
};
83+
`
84+
);
85+
});
86+
87+
it('generates proper types when typesSuffix is used along with `enumSuffix: false`', () => {
88+
const visitor = new BaseResolversVisitor(
89+
{
90+
mappers: {
91+
B: './some-file#B',
92+
},
93+
typesSuffix: 'I',
94+
enumSuffix: false,
95+
},
96+
{} as ParsedResolversConfig,
97+
schema
98+
);
99+
100+
expect(visitor.buildResolversParentTypes()).toEqual(
101+
`/** Mapping between all available schema types and the resolvers parents */
102+
export type ResolversParentTypesI = {
103+
Query: {}
104+
A: AI
105+
Boolean: Scalars['Boolean']['output']
106+
String: Scalars['String']['output']
107+
};
83108
`
84109
);
85110
});

packages/plugins/typescript/operations/src/visitor.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor<
7878
namespacedImportName: this.config.namespacedImportName,
7979
convertName: this.convertName.bind(this),
8080
enumPrefix: this.config.enumPrefix,
81+
enumSuffix: this.config.enumSuffix,
8182
scalars: this.scalars,
8283
formatNamedField,
8384
wrapTypeWithModifiers(baseType, type) {
@@ -109,6 +110,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor<
109110
this.config.namespacedImportName,
110111
enumsNames,
111112
this.config.enumPrefix,
113+
this.config.enumSuffix,
112114
this.config.enumValues,
113115
this.config.arrayInputCoercion,
114116
undefined,

packages/plugins/typescript/operations/tests/ts-documents.spec.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,6 +2644,58 @@ describe('TypeScript Operations Plugin', () => {
26442644
expect(o).toContain(`__typename?: 'Information_Entry', id: Information_EntryType,`);
26452645
});
26462646

2647+
it('Should produce valid output with preResolveTypes=true and enums with no suffixes', async () => {
2648+
const ast = parse(/* GraphQL */ `
2649+
query test($e: Information_EntryType!) {
2650+
info {
2651+
...information
2652+
}
2653+
infoArgTest(e: $e) {
2654+
...information
2655+
}
2656+
}
2657+
2658+
fragment information on Information {
2659+
entries {
2660+
id
2661+
value
2662+
}
2663+
}
2664+
`);
2665+
const testSchema = buildSchema(/* GraphQL */ `
2666+
type Information {
2667+
entries: [Information_Entry!]!
2668+
}
2669+
2670+
enum Information_EntryType {
2671+
NAME
2672+
ADDRESS
2673+
}
2674+
2675+
type Information_Entry {
2676+
id: Information_EntryType!
2677+
value: String
2678+
}
2679+
2680+
type Query {
2681+
infoArgTest(e: Information_EntryType!): Information
2682+
info: Information
2683+
}
2684+
`);
2685+
const config = { preResolveTypes: true, typesSuffix: 'I', enumSuffix: false };
2686+
const { content } = await plugin(testSchema, [{ location: 'test-file.ts', document: ast }], config, {
2687+
outputFile: '',
2688+
});
2689+
2690+
const o = await validate(content, config, testSchema);
2691+
expect(o).toBeSimilarStringTo(` export type TestQueryVariablesI = Exact<{
2692+
e: Information_EntryType;
2693+
}>;`);
2694+
expect(o).toContain(`export type QueryI = {`);
2695+
expect(o).toContain(`export enum Information_EntryType {`);
2696+
expect(o).toContain(`__typename?: 'Information_Entry', id: Information_EntryType,`);
2697+
});
2698+
26472699
it('Should build a basic selection set based on basic query', async () => {
26482700
const ast = parse(/* GraphQL */ `
26492701
query dummy {

0 commit comments

Comments
 (0)