Skip to content

Commit

Permalink
Added support for enumSuffix (#9304)
Browse files Browse the repository at this point in the history
Co-authored-by: Saihajpreet Singh <saihajpreet.singh@gmail.com>
Co-authored-by: Aleksandra <alexsandra.sikora@gmail.com>
  • Loading branch information
3 people authored May 23, 2023
1 parent 4d9ea1a commit e1dc75f
Show file tree
Hide file tree
Showing 15 changed files with 222 additions and 5 deletions.
8 changes: 8 additions & 0 deletions .changeset/swift-hornets-camp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@graphql-codegen/typescript-operations": minor
"@graphql-codegen/typescript-resolvers": minor
"@graphql-codegen/typescript": minor
"@graphql-codegen/visitor-plugin-common": minor
---

Added support for disabling suffixes on Enums.
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export class BaseDocumentsVisitor<
super(rawConfig, {
exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false),
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
preResolveTypes: getConfigValue(rawConfig.preResolveTypes, true),
dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false),
omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export interface ParsedResolversConfig extends ParsedConfig {
resolverTypeWrapperSignature: string;
federation: boolean;
enumPrefix: boolean;
enumSuffix: boolean;
optionalResolveType: boolean;
immutableTypes: boolean;
namespacedImportName: string;
Expand Down Expand Up @@ -500,6 +501,33 @@ export interface RawResolversConfig extends RawConfig {
* ```
*/
enumPrefix?: boolean;

/**
* @default true
* @description Allow you to disable suffixing for generated enums, works in combination with `typesSuffix`.
*
* @exampleMarkdown
* ## Disable enum suffixes
*
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file': {
* plugins: ['typescript', 'typescript-resolver'],
* config: {
* typesSuffix: 'I',
* enumSuffix: false
* },
* },
* },
* };
* export default config;
* ```
*/
enumSuffix?: boolean;
/**
* @default false
* @description Sets the `__resolveType` field as optional field.
Expand Down Expand Up @@ -635,6 +663,7 @@ export class BaseResolversVisitor<
immutableTypes: getConfigValue(rawConfig.immutableTypes, false),
optionalResolveType: getConfigValue(rawConfig.optionalResolveType, false),
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
federation: getConfigValue(rawConfig.federation, false),
resolverTypeWrapperSignature: getConfigValue(rawConfig.resolverTypeWrapperSignature, 'Promise<T> | T'),
enumValues: parseEnumValues({
Expand Down Expand Up @@ -816,7 +845,14 @@ export class BaseResolversVisitor<
const generic = this.convertName(currentType);
prev[typeName] = applyWrapper(`${type}<${generic}>['${typeName}']`);
} else if (isEnumType(schemaType)) {
prev[typeName] = this.convertName(typeName, { useTypesPrefix: this.config.enumPrefix }, true);
prev[typeName] = this.convertName(
typeName,
{
useTypesPrefix: this.config.enumPrefix,
useTypesSuffix: this.config.enumSuffix,
},
true
);
} else {
prev[typeName] = this.convertName(typeName, {}, true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export interface ParsedTypesConfig extends ParsedConfig {
onlyEnums: boolean;
onlyOperationTypes: boolean;
enumPrefix: boolean;
enumSuffix: boolean;
fieldWrapperValue: string;
wrapFieldDefinitions: boolean;
entireFieldWrapperValue: string;
Expand Down Expand Up @@ -226,6 +227,32 @@ export interface RawTypesConfig extends RawConfig {
* ```
*/
enumPrefix?: boolean;
/**
* @default true
* @description Allow you to disable suffixing for generated enums, works in combination with `typesSuffix`.
*
* @exampleMarkdown
* ## Disable enum suffixes
*
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file': {
* // plugins...
* config: {
* typesSuffix: 'I',
* enumSuffix: false
* },
* },
* },
* };
* export default config;
* ```
*/
enumSuffix?: boolean;
/**
* @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.
* @default T
Expand Down Expand Up @@ -482,6 +509,7 @@ export class BaseTypesVisitor<
) {
super(rawConfig, {
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
onlyEnums: getConfigValue(rawConfig.onlyEnums, false),
onlyOperationTypes: getConfigValue(rawConfig.onlyOperationTypes, false),
addUnderscoreToArgsType: getConfigValue(rawConfig.addUnderscoreToArgsType, false),
Expand Down Expand Up @@ -855,7 +883,12 @@ export class BaseTypesVisitor<
return new DeclarationBlock(this._declarationBlockConfig)
.export()
.asKind('enum')
.withName(this.convertName(node, { useTypesPrefix: this.config.enumPrefix }))
.withName(
this.convertName(node, {
useTypesPrefix: this.config.enumPrefix,
useTypesSuffix: this.config.enumSuffix,
})
)
.withComment(node.description as any as string)
.withBlock(this.buildEnumValuesBlock(enumName, node.values)).string;
}
Expand Down Expand Up @@ -993,7 +1026,10 @@ export class BaseTypesVisitor<
const schemaType = this._schema.getType(node.name as any);

if (schemaType && isEnumType(schemaType)) {
return this.convertName(node, { useTypesPrefix: this.config.enumPrefix });
return this.convertName(node, {
useTypesPrefix: this.config.enumPrefix,
useTypesSuffix: this.config.enumSuffix,
});
}

return this.convertName(node);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type SelectionSetProcessorConfig = {
namespacedImportName: string | null;
convertName: ConvertNameFn<any>;
enumPrefix: boolean | null;
enumSuffix: boolean | null;
scalars: NormalizedScalarsMap;
formatNamedField(
name: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ export class PreResolveTypesProcessor extends BaseSelectionSetProcessor<Selectio
if (isEnumType(baseType)) {
typeToUse =
(this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : '') +
this.config.convertName(baseType.name, { useTypesPrefix: this.config.enumPrefix });
this.config.convertName(baseType.name, {
useTypesPrefix: this.config.enumPrefix,
useTypesSuffix: this.config.enumSuffix,
});
} else if (this.config.scalars[baseType.name]) {
typeToUse = this.config.scalars[baseType.name].output;
}
Expand Down Expand Up @@ -92,7 +95,10 @@ export class PreResolveTypesProcessor extends BaseSelectionSetProcessor<Selectio
if (isEnumType(baseType)) {
typeToUse =
(this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : '') +
this.config.convertName(baseType.name, { useTypesPrefix: this.config.enumPrefix });
this.config.convertName(baseType.name, {
useTypesPrefix: this.config.enumPrefix,
useTypesSuffix: this.config.enumSuffix,
});
}

const name = this.config.formatNamedField(aliasedField.alias, fieldObj.type, undefined, unsetTypes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class OperationVariablesToObject {
protected _namespacedImportName: string | null = null,
protected _enumNames: string[] = [],
protected _enumPrefix = true,
protected _enumSuffix = true,
protected _enumValues: ParsedEnumValuesMap = {},
protected _applyCoercion: Boolean = false,
protected _directiveArgumentAndInputFieldMappings: ParsedDirectiveArgumentAndInputFieldMappings = {}
Expand Down Expand Up @@ -104,6 +105,7 @@ export class OperationVariablesToObject {
} else {
typeValue = `${prefix}${this._convertName(baseType, {
useTypesPrefix: this._enumNames.includes(typeName) ? this._enumPrefix : true,
useTypesSuffix: this._enumNames.includes(typeName) ? this._enumSuffix : true,
})}`;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,31 @@ export type IResolversParentTypes = {
Boolean: Scalars['Boolean']['output']
String: Scalars['String']['output']
};
`
);
});

it('generates proper types when typesSuffix is used along with `enumSuffix: false`', () => {
const visitor = new BaseResolversVisitor(
{
mappers: {
B: './some-file#B',
},
typesSuffix: 'I',
enumSuffix: false,
},
{} as ParsedResolversConfig,
schema
);

expect(visitor.buildResolversParentTypes()).toEqual(
`/** Mapping between all available schema types and the resolvers parents */
export type ResolversParentTypesI = {
Query: {}
A: AI
Boolean: Scalars['Boolean']['output']
String: Scalars['String']['output']
};
`
);
});
Expand Down
2 changes: 2 additions & 0 deletions packages/plugins/typescript/operations/src/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor<
namespacedImportName: this.config.namespacedImportName,
convertName: this.convertName.bind(this),
enumPrefix: this.config.enumPrefix,
enumSuffix: this.config.enumSuffix,
scalars: this.scalars,
formatNamedField,
wrapTypeWithModifiers(baseType, type) {
Expand Down Expand Up @@ -109,6 +110,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor<
this.config.namespacedImportName,
enumsNames,
this.config.enumPrefix,
this.config.enumSuffix,
this.config.enumValues,
this.config.arrayInputCoercion,
undefined,
Expand Down
52 changes: 52 additions & 0 deletions packages/plugins/typescript/operations/tests/ts-documents.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2644,6 +2644,58 @@ describe('TypeScript Operations Plugin', () => {
expect(o).toContain(`__typename?: 'Information_Entry', id: Information_EntryType,`);
});

it('Should produce valid output with preResolveTypes=true and enums with no suffixes', async () => {
const ast = parse(/* GraphQL */ `
query test($e: Information_EntryType!) {
info {
...information
}
infoArgTest(e: $e) {
...information
}
}
fragment information on Information {
entries {
id
value
}
}
`);
const testSchema = buildSchema(/* GraphQL */ `
type Information {
entries: [Information_Entry!]!
}
enum Information_EntryType {
NAME
ADDRESS
}
type Information_Entry {
id: Information_EntryType!
value: String
}
type Query {
infoArgTest(e: Information_EntryType!): Information
info: Information
}
`);
const config = { preResolveTypes: true, typesSuffix: 'I', enumSuffix: false };
const { content } = await plugin(testSchema, [{ location: 'test-file.ts', document: ast }], config, {
outputFile: '',
});

const o = await validate(content, config, testSchema);
expect(o).toBeSimilarStringTo(` export type TestQueryVariablesI = Exact<{
e: Information_EntryType;
}>;`);
expect(o).toContain(`export type QueryI = {`);
expect(o).toContain(`export enum Information_EntryType {`);
expect(o).toContain(`__typename?: 'Information_Entry', id: Information_EntryType,`);
});

it('Should build a basic selection set based on basic query', async () => {
const ast = parse(/* GraphQL */ `
query dummy {
Expand Down
1 change: 1 addition & 0 deletions packages/plugins/typescript/resolvers/src/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export class TypeScriptResolversVisitor extends BaseResolversVisitor<
this.config.namespacedImportName,
[],
this.config.enumPrefix,
this.config.enumSuffix,
this.config.enumValues
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export class TypeScriptOperationVariablesToObject extends OperationVariablesToOb
_namespacedImportName: string | null = null,
_enumNames: string[] = [],
_enumPrefix = true,
_enumSuffix = true,
_enumValues: ParsedEnumValuesMap = {},
_applyCoercion: Boolean = false,
_directiveArgumentAndInputFieldMappings: ParsedDirectiveArgumentAndInputFieldMappings = {},
Expand All @@ -29,6 +30,7 @@ export class TypeScriptOperationVariablesToObject extends OperationVariablesToOb
_namespacedImportName,
_enumNames,
_enumPrefix,
_enumSuffix,
_enumValues,
_applyCoercion,
_directiveArgumentAndInputFieldMappings
Expand Down
2 changes: 2 additions & 0 deletions packages/plugins/typescript/typescript/src/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export class TsVisitor<
null,
enumNames,
pluginConfig.enumPrefix,
pluginConfig.enumSuffix,
this.config.enumValues,
false,
this.config.directiveArgumentAndInputFieldMappings,
Expand Down Expand Up @@ -373,6 +374,7 @@ export class TsVisitor<

const enumTypeName = this.convertName(node, {
useTypesPrefix: this.config.enumPrefix,
useTypesSuffix: this.config.enumSuffix,
});

if (this.config.enumsAsTypes) {
Expand Down
15 changes: 15 additions & 0 deletions packages/plugins/typescript/typescript/tests/typescript.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3085,6 +3085,21 @@ describe('TypeScript', () => {
validateTs(result);
});

it('Should allow to disable typesSuffix for enums', async () => {
const schema = buildSchema(`type T { f: String, e: E } enum E { A }`);
const result = (await plugin(
schema,
[],
{ typesSuffix: 'I', enumSuffix: false },
{ outputFile: '' }
)) as Types.ComplexPluginOutput;

expect(result.content).toContain(`export enum E {`);
expect(result.content).toContain(`e?: Maybe<E>;`);

validateTs(result);
});

it('Should enable typesPrefix for enums by default', async () => {
const schema = buildSchema(`type T { f: String, e: E } enum E { A }`);
const result = await plugin(schema, [], { typesPrefix: 'I' }, { outputFile: '' });
Expand Down
Loading

0 comments on commit e1dc75f

Please sign in to comment.