Skip to content

Commit 74a7a97

Browse files
committed
Use enum converter for Enum
1 parent ff9bce6 commit 74a7a97

File tree

5 files changed

+84
-11
lines changed

5 files changed

+84
-11
lines changed

packages/plugins/typescript/operations/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"dependencies": {
1616
"@graphql-codegen/plugin-helpers": "^6.0.0",
1717
"@graphql-codegen/typescript": "^5.0.4",
18+
"@graphql-codegen/schema-ast": "^5.0.0",
1819
"@graphql-codegen/visitor-plugin-common": "6.1.2",
1920
"auto-bind": "~4.0.0",
2021
"tslib": "~2.6.0"

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AvoidOptionalsConfig, RawDocumentsConfig } from '@graphql-codegen/visitor-plugin-common';
1+
import { AvoidOptionalsConfig, type EnumValuesMap, RawDocumentsConfig } from '@graphql-codegen/visitor-plugin-common';
22

33
/**
44
* @description This plugin generates TypeScript types based on your GraphQLSchema _and_ your GraphQL operations and fragments.
@@ -336,4 +336,8 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig {
336336
nullability?: {
337337
errorHandlingClient: boolean;
338338
};
339+
340+
enumType?: 'string-literal' | 'native-numeric' | 'const' | 'native-const' | 'native';
341+
enumValues?: EnumValuesMap;
342+
futureProofEnums?: boolean;
339343
}

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

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { oldVisit, PluginFunction, Types } from '@graphql-codegen/plugin-helpers';
2+
import { transformSchemaAST } from '@graphql-codegen/schema-ast';
23
import { optimizeOperations } from '@graphql-codegen/visitor-plugin-common';
34
import { concatAST, GraphQLSchema } from 'graphql';
45
import { TypeScriptDocumentsPluginConfig } from './config.js';
@@ -22,11 +23,9 @@ export const plugin: PluginFunction<TypeScriptDocumentsPluginConfig, Types.Compl
2223

2324
const visitor = new TypeScriptDocumentsVisitor(schema, config, allAst);
2425

25-
const visitorResult = oldVisit(allAst, {
26-
leave: visitor,
27-
});
26+
const operationsResult = oldVisit(allAst, { leave: visitor });
2827

29-
let content = visitorResult.definitions.join('\n');
28+
let operationsContent = operationsResult.definitions.join('\n');
3029

3130
if (config.addOperationExport) {
3231
const exportConsts = [];
@@ -37,23 +36,37 @@ export const plugin: PluginFunction<TypeScriptDocumentsPluginConfig, Types.Compl
3736
}
3837
}
3938

40-
content = visitorResult.definitions.concat(exportConsts).join('\n');
39+
operationsContent = operationsResult.definitions.concat(exportConsts).join('\n');
4140
}
4241

4342
if (config.globalNamespace) {
44-
content = `
43+
operationsContent = `
4544
declare global {
46-
${content}
45+
${operationsContent}
4746
}`;
4847
}
4948

49+
const schemaTypes = oldVisit(transformSchemaAST(schema, config).ast, { leave: visitor });
50+
51+
// IMPORTANT: when a visitor leaves a node with no transformation logic,
52+
// It will leave the node as an object.
53+
// Here, we filter in nodes that have been turned into strings, i.e. they have been transformed
54+
// This way, we do not have to explicitly declare a method for every node type to convert them to null
55+
const schemaTypesContent = schemaTypes.definitions.filter(def => typeof def === 'string').join('\n');
56+
57+
const content: string[] = [];
58+
if (schemaTypesContent) {
59+
content.push(schemaTypesContent);
60+
}
61+
content.push(operationsContent);
62+
5063
return {
5164
prepend: [
5265
...visitor.getImports(),
5366
...visitor.getGlobalDeclarations(visitor.config.noExport),
5467
'type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };',
5568
],
56-
content,
69+
content: content.join('\n'),
5770
};
5871
};
5972

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import {
22
BaseDocumentsVisitor,
3+
convertSchemaEnumToDeclarationBlockString,
34
DeclarationKind,
45
generateFragmentImportStatement,
56
getConfigValue,
67
LoadedFragment,
78
normalizeAvoidOptionals,
89
NormalizedAvoidOptionalsConfig,
910
ParsedDocumentsConfig,
11+
type ParsedEnumValuesMap,
12+
parseEnumValues,
1013
PreResolveTypesProcessor,
1114
SelectionSetProcessorConfig,
1215
SelectionSetToObject,
@@ -15,6 +18,7 @@ import {
1518
import autoBind from 'auto-bind';
1619
import {
1720
type DocumentNode,
21+
EnumTypeDefinitionNode,
1822
type FragmentDefinitionNode,
1923
GraphQLEnumType,
2024
GraphQLInputObjectType,
@@ -39,6 +43,9 @@ export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig {
3943
noExport: boolean;
4044
maybeValue: string;
4145
allowUndefinedQueryVariables: boolean;
46+
enumType: 'string-literal' | 'native-numeric' | 'const' | 'native-const' | 'native';
47+
futureProofEnums: boolean;
48+
enumValues: ParsedEnumValuesMap;
4249
}
4350

4451
type UsedNamedInputTypes = Record<string, GraphQLNamedInputType>;
@@ -60,6 +67,13 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor<
6067
preResolveTypes: getConfigValue(config.preResolveTypes, true),
6168
mergeFragmentTypes: getConfigValue(config.mergeFragmentTypes, false),
6269
allowUndefinedQueryVariables: getConfigValue(config.allowUndefinedQueryVariables, false),
70+
enumType: getConfigValue(config.enumType, 'string-literal'),
71+
enumValues: parseEnumValues({
72+
schema,
73+
mapOrStr: config.enumValues,
74+
ignoreEnumValuesFromSchema: config.ignoreEnumValuesFromSchema,
75+
}),
76+
futureProofEnums: getConfigValue(config.futureProofEnums, false),
6377
} as TypeScriptDocumentsParsedConfig,
6478
schema
6579
);
@@ -156,6 +170,31 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor<
156170
};
157171
}
158172

173+
EnumTypeDefinition(node: EnumTypeDefinitionNode): string {
174+
const enumName = node.name.value;
175+
if (!this._usedNamedInputTypes[enumName]) {
176+
return null;
177+
}
178+
179+
return convertSchemaEnumToDeclarationBlockString({
180+
schema: this._schema,
181+
node,
182+
declarationBlockConfig: this._declarationBlockConfig,
183+
enumName,
184+
enumValues: this.config.enumValues,
185+
futureProofEnums: this.config.futureProofEnums,
186+
ignoreEnumValuesFromSchema: this.config.ignoreEnumValuesFromSchema,
187+
outputType: this.config.enumType,
188+
naming: {
189+
convert: this.config.convert,
190+
typesPrefix: this.config.typesPrefix,
191+
typesSuffix: this.config.typesSuffix,
192+
useTypesPrefix: this.config.enumPrefix,
193+
useTypesSuffix: this.config.enumSuffix,
194+
},
195+
});
196+
}
197+
159198
public getImports(): Array<string> {
160199
return !this.config.globalNamespace &&
161200
(this.config.inlineFragmentTypes === 'combine' || this.config.inlineFragmentTypes === 'mask')

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ describe('TypeScript Operations Plugin - Standalone', () => {
3737
input UsersInput {
3838
from: DateTime
3939
to: DateTime
40+
role: UserRole
4041
}
4142
4243
type UsersResponseOk {
@@ -69,8 +70,8 @@ describe('TypeScript Operations Plugin - Standalone', () => {
6970
}
7071
}
7172
72-
query UsersWithScalarInput($from: DateTime!, $to: DateTime) {
73-
users(input: { from: $from, to: $to }) {
73+
query UsersWithScalarInput($from: DateTime!, $to: DateTime, $role: UserRole) {
74+
users(input: { from: $from, to: $to, role: $role }) {
7475
... on UsersResponseOk {
7576
result {
7677
__typename
@@ -87,6 +88,10 @@ describe('TypeScript Operations Plugin - Standalone', () => {
8788

8889
expect(result).toMatchInlineSnapshot(`
8990
"type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
91+
export type UserRole =
92+
| 'ADMIN'
93+
| 'CUSTOMER';
94+
9095
export type UserQueryVariables = Exact<{
9196
id: string;
9297
}>;
@@ -107,6 +112,7 @@ describe('TypeScript Operations Plugin - Standalone', () => {
107112
export type UsersWithScalarInputQueryVariables = Exact<{
108113
from: any;
109114
to?: any | null;
115+
role?: UserRole | null;
110116
}>;
111117
112118
@@ -157,3 +163,13 @@ describe('TypeScript Operations Plugin - Standalone', () => {
157163
`);
158164
});
159165
});
166+
167+
describe('TypeScript Operations Plugin - Enum', () => {
168+
it.todo('does not generate unused enum in variables and result');
169+
it.todo('handles native numeric enum correctly');
170+
it.todo('handles const enum correctly');
171+
it.todo('handles native const enum correctly');
172+
it.todo('handles native enum correctly');
173+
it.todo('handles EnumValues correctly');
174+
// Bring over tests from https://github.com/dotansimha/graphql-code-generator/blob/accdab69106605241933e9d66d64dc7077656f30/packages/plugins/typescript/typescript/tests/typescript.spec.ts
175+
});

0 commit comments

Comments
 (0)