@graphql-codegen/visitor-plugin-common 6.2.2 → 7.0.0-alpha-20251224115216-0c4a535bdb152e75b9296d4c259f7dad0a13158f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/base-documents-visitor.js +8 -0
- package/cjs/base-resolvers-visitor.js +5 -7
- package/cjs/base-types-visitor.js +40 -87
- package/cjs/base-visitor.js +1 -7
- package/cjs/client-side-base-visitor.js +4 -14
- package/cjs/convert-schema-enum-to-declaration-block-string.js +164 -0
- package/cjs/graphql-type-utils.js +15 -0
- package/cjs/imports.js +55 -7
- package/cjs/index.js +2 -0
- package/cjs/selection-set-processor/pre-resolve-types.js +9 -5
- package/cjs/selection-set-to-object.js +12 -18
- package/cjs/utils.js +22 -1
- package/esm/base-documents-visitor.js +8 -0
- package/esm/base-resolvers-visitor.js +5 -7
- package/esm/base-types-visitor.js +41 -88
- package/esm/base-visitor.js +1 -7
- package/esm/client-side-base-visitor.js +5 -15
- package/esm/convert-schema-enum-to-declaration-block-string.js +159 -0
- package/esm/graphql-type-utils.js +11 -0
- package/esm/imports.js +53 -7
- package/esm/index.js +2 -0
- package/esm/selection-set-processor/pre-resolve-types.js +11 -7
- package/esm/selection-set-to-object.js +12 -18
- package/esm/utils.js +20 -0
- package/package.json +2 -2
- package/typings/base-documents-visitor.d.cts +49 -1
- package/typings/base-documents-visitor.d.ts +49 -1
- package/typings/base-types-visitor.d.cts +1 -6
- package/typings/base-types-visitor.d.ts +1 -6
- package/typings/base-visitor.d.cts +1 -8
- package/typings/base-visitor.d.ts +1 -8
- package/typings/convert-schema-enum-to-declaration-block-string.d.cts +25 -0
- package/typings/convert-schema-enum-to-declaration-block-string.d.ts +25 -0
- package/typings/graphql-type-utils.d.cts +2 -0
- package/typings/graphql-type-utils.d.ts +2 -0
- package/typings/imports.d.cts +12 -2
- package/typings/imports.d.ts +12 -2
- package/typings/index.d.cts +2 -0
- package/typings/index.d.ts +2 -0
- package/typings/selection-set-processor/base.d.cts +5 -3
- package/typings/selection-set-processor/base.d.ts +5 -3
- package/typings/selection-set-to-object.d.cts +4 -4
- package/typings/selection-set-to-object.d.ts +4 -4
- package/typings/utils.d.cts +2 -1
- package/typings/utils.d.ts +2 -1
|
@@ -266,6 +266,7 @@ class SelectionSetToObject {
|
|
|
266
266
|
mustAddEmptyObject = true;
|
|
267
267
|
}
|
|
268
268
|
for (const incrementalNode of incrementalNodes) {
|
|
269
|
+
// 1. fragment masking
|
|
269
270
|
if (this._config.inlineFragmentTypes === 'mask' && 'fragmentName' in incrementalNode) {
|
|
270
271
|
const { fields: incrementalFields, dependentTypes: incrementalDependentTypes } = this.buildSelectionSet(schemaType, [incrementalNode], { unsetTypes: true, parentFieldName: parentName });
|
|
271
272
|
const incrementalSet = this.selectionSetStringFromFields(incrementalFields);
|
|
@@ -273,6 +274,7 @@ class SelectionSetToObject {
|
|
|
273
274
|
dependentTypes.push(...incrementalDependentTypes);
|
|
274
275
|
continue;
|
|
275
276
|
}
|
|
277
|
+
// 2. @defer
|
|
276
278
|
const { fields: initialFields, dependentTypes: initialDependentTypes } = this.buildSelectionSet(schemaType, [incrementalNode], { parentFieldName: parentName });
|
|
277
279
|
const { fields: subsequentFields, dependentTypes: subsequentDependentTypes } = this.buildSelectionSet(schemaType, [incrementalNode], { unsetTypes: true, parentFieldName: parentName });
|
|
278
280
|
const initialSet = this.selectionSetStringFromFields(initialFields);
|
|
@@ -466,12 +468,17 @@ class SelectionSetToObject {
|
|
|
466
468
|
const selectionSetObjects = selectionSet.transformSelectionSet(options.parentFieldName ? `${options.parentFieldName}_${fieldName}` : fieldName);
|
|
467
469
|
linkFieldsInterfaces.push(...selectionSetObjects.dependentTypes);
|
|
468
470
|
const isConditional = (0, utils_js_1.hasConditionalDirectives)(field) || inlineFragmentConditional;
|
|
469
|
-
const isOptional = options.unsetTypes;
|
|
470
471
|
linkFields.push({
|
|
471
472
|
alias: field.alias
|
|
472
|
-
? this._processor.config.formatNamedField(
|
|
473
|
+
? this._processor.config.formatNamedField({
|
|
474
|
+
name: field.alias.value,
|
|
475
|
+
isOptional: isConditional || options.unsetTypes,
|
|
476
|
+
})
|
|
473
477
|
: undefined,
|
|
474
|
-
name: this._processor.config.formatNamedField(
|
|
478
|
+
name: this._processor.config.formatNamedField({
|
|
479
|
+
name: field.name.value,
|
|
480
|
+
isOptional: isConditional || options.unsetTypes,
|
|
481
|
+
}),
|
|
475
482
|
type: realSelectedFieldType.name,
|
|
476
483
|
selectionSet: this._processor.config.wrapTypeWithModifiers(selectionSetObjects.mergedTypeString.split(`\n`).join(`\n `), selectedFieldType),
|
|
477
484
|
});
|
|
@@ -524,7 +531,7 @@ class SelectionSetToObject {
|
|
|
524
531
|
if (nonOptionalTypename || addTypename || queriedForTypename) {
|
|
525
532
|
const optionalTypename = !queriedForTypename && !nonOptionalTypename;
|
|
526
533
|
return {
|
|
527
|
-
name:
|
|
534
|
+
name: this._processor.config.formatNamedField({ name: '__typename', isOptional: optionalTypename }),
|
|
528
535
|
type: `'${type.name}'`,
|
|
529
536
|
};
|
|
530
537
|
}
|
|
@@ -683,20 +690,7 @@ class SelectionSetToObject {
|
|
|
683
690
|
buildParentFieldName(typeName, parentName) {
|
|
684
691
|
// queries/mutations/fragments are guaranteed to be unique type names,
|
|
685
692
|
// so we can skip affixing the field names with typeName
|
|
686
|
-
|
|
687
|
-
return parentName;
|
|
688
|
-
}
|
|
689
|
-
const schemaType = this._schema.getType(typeName);
|
|
690
|
-
// Check if current selection set has fragments (e.g., "... AppNotificationFragment" or "... on AppNotification")
|
|
691
|
-
const hasFragment = this._selectionSet?.selections?.some(selection => selection.kind === graphql_1.Kind.INLINE_FRAGMENT || selection.kind === graphql_1.Kind.FRAGMENT_SPREAD) ?? false;
|
|
692
|
-
// When the parent schema type is an interface:
|
|
693
|
-
// - If we're processing inline fragments, use the concrete type name
|
|
694
|
-
// - If we're processing the interface directly, use the interface name
|
|
695
|
-
// - If we're in a named fragment, always use the concrete type name
|
|
696
|
-
if ((0, graphql_1.isObjectType)(schemaType) && this._parentSchemaType && (0, graphql_1.isInterfaceType)(this._parentSchemaType) && !hasFragment) {
|
|
697
|
-
return `${parentName}_${this._parentSchemaType.name}`;
|
|
698
|
-
}
|
|
699
|
-
return `${parentName}_${typeName}`;
|
|
693
|
+
return operationTypes.includes(typeName) ? parentName : `${parentName}_${typeName}`;
|
|
700
694
|
}
|
|
701
695
|
}
|
|
702
696
|
exports.SelectionSetToObject = SelectionSetToObject;
|
package/cjs/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getFieldNames = exports.getFieldNodeNameValue = exports.REQUIRE_FIELDS_TYPE = exports.OMIT_TYPE = exports.DeclarationBlock = exports.getConfigValue = void 0;
|
|
3
|
+
exports.getNodeComment = exports.getFieldNames = exports.getFieldNodeNameValue = exports.REQUIRE_FIELDS_TYPE = exports.OMIT_TYPE = exports.DeclarationBlock = exports.getConfigValue = void 0;
|
|
4
4
|
exports.quoteIfNeeded = quoteIfNeeded;
|
|
5
5
|
exports.block = block;
|
|
6
6
|
exports.wrapWithSingleQuotes = wrapWithSingleQuotes;
|
|
@@ -535,3 +535,24 @@ const getFieldNames = ({ selections, fieldNames = new Set(), parentName = '', lo
|
|
|
535
535
|
return fieldNames;
|
|
536
536
|
};
|
|
537
537
|
exports.getFieldNames = getFieldNames;
|
|
538
|
+
const getNodeComment = (node) => {
|
|
539
|
+
let commentText = node.description?.value;
|
|
540
|
+
const deprecationDirective = node.directives.find(v => v.name.value === 'deprecated');
|
|
541
|
+
if (deprecationDirective) {
|
|
542
|
+
const deprecationReason = getDeprecationReason(deprecationDirective);
|
|
543
|
+
commentText = `${commentText ? `${commentText}\n` : ''}@deprecated ${deprecationReason}`;
|
|
544
|
+
}
|
|
545
|
+
const comment = transformComment(commentText, 1);
|
|
546
|
+
return comment;
|
|
547
|
+
};
|
|
548
|
+
exports.getNodeComment = getNodeComment;
|
|
549
|
+
const getDeprecationReason = (directive) => {
|
|
550
|
+
if (directive.name.value === 'deprecated') {
|
|
551
|
+
let reason = 'Field no longer supported';
|
|
552
|
+
const deprecatedReason = directive.arguments[0];
|
|
553
|
+
if (deprecatedReason && deprecatedReason.value.kind === graphql_1.Kind.STRING) {
|
|
554
|
+
reason = deprecatedReason.value.value;
|
|
555
|
+
}
|
|
556
|
+
return reason;
|
|
557
|
+
}
|
|
558
|
+
};
|
|
@@ -37,6 +37,8 @@ export class BaseDocumentsVisitor extends BaseVisitor {
|
|
|
37
37
|
operationResultSuffix: getConfigValue(rawConfig.operationResultSuffix, ''),
|
|
38
38
|
scalars: buildScalarsFromConfig(_schema, rawConfig, defaultScalars),
|
|
39
39
|
customDirectives: getConfigValue(rawConfig.customDirectives, { apolloUnmask: false }),
|
|
40
|
+
generatesOperationTypes: getConfigValue(rawConfig.generatesOperationTypes, true),
|
|
41
|
+
importSchemaTypesFrom: getConfigValue(rawConfig.importSchemaTypesFrom, ''),
|
|
40
42
|
...(additionalConfig || {}),
|
|
41
43
|
});
|
|
42
44
|
this._schema = _schema;
|
|
@@ -77,6 +79,9 @@ export class BaseDocumentsVisitor extends BaseVisitor {
|
|
|
77
79
|
});
|
|
78
80
|
}
|
|
79
81
|
FragmentDefinition(node) {
|
|
82
|
+
if (!this.config.generatesOperationTypes) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
80
85
|
const fragmentRootType = this._schema.getType(node.typeCondition.name.value);
|
|
81
86
|
const selectionSet = this._selectionSetToObject.createNext(fragmentRootType, node.selectionSet);
|
|
82
87
|
const fragmentSuffix = this.getFragmentSuffix(node);
|
|
@@ -102,6 +107,9 @@ export class BaseDocumentsVisitor extends BaseVisitor {
|
|
|
102
107
|
return variablesBlock;
|
|
103
108
|
}
|
|
104
109
|
OperationDefinition(node) {
|
|
110
|
+
if (!this.config.generatesOperationTypes) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
105
113
|
const name = this.handleAnonymousOperation(node);
|
|
106
114
|
const operationRootType = getRootType(node.operation, this._schema);
|
|
107
115
|
if (!operationRootType) {
|
|
@@ -171,17 +171,15 @@ export class BaseResolversVisitor extends BaseVisitor {
|
|
|
171
171
|
const isMapped = this.config.mappers[typeName];
|
|
172
172
|
const isScalar = this.config.scalars[typeName];
|
|
173
173
|
const hasDefaultMapper = !!this.config.defaultMapper?.type;
|
|
174
|
-
// Check for mappers first, even for root types, to allow overriding rootValueType
|
|
175
|
-
if (isMapped && this.config.mappers[typeName].type && !hasPlaceholder(this.config.mappers[typeName].type)) {
|
|
176
|
-
this.markMapperAsUsed(typeName);
|
|
177
|
-
prev[typeName] = applyWrapper(this.config.mappers[typeName].type);
|
|
178
|
-
return prev;
|
|
179
|
-
}
|
|
180
174
|
if (isRootType) {
|
|
181
175
|
prev[typeName] = applyWrapper(this.config.rootValueType.type);
|
|
182
176
|
return prev;
|
|
183
177
|
}
|
|
184
|
-
if (
|
|
178
|
+
if (isMapped && this.config.mappers[typeName].type && !hasPlaceholder(this.config.mappers[typeName].type)) {
|
|
179
|
+
this.markMapperAsUsed(typeName);
|
|
180
|
+
prev[typeName] = applyWrapper(this.config.mappers[typeName].type);
|
|
181
|
+
}
|
|
182
|
+
else if (isEnumType(schemaType) && this.config.enumValues[typeName]) {
|
|
185
183
|
const isExternalFile = !!this.config.enumValues[typeName].sourceFile;
|
|
186
184
|
prev[typeName] = isExternalFile
|
|
187
185
|
? this.convertName(this.config.enumValues[typeName].typeIdentifier, {
|
|
@@ -4,9 +4,10 @@ import { normalizeDeclarationKind } from './declaration-kinds.js';
|
|
|
4
4
|
import { parseEnumValues } from './enum-values.js';
|
|
5
5
|
import { transformDirectiveArgumentAndInputFieldMappings } from './mappers.js';
|
|
6
6
|
import { DEFAULT_SCALARS } from './scalars.js';
|
|
7
|
-
import { buildScalarsFromConfig, DeclarationBlock, getConfigValue, indent, isOneOfInputObjectType, transformComment, wrapWithSingleQuotes, } from './utils.js';
|
|
7
|
+
import { buildScalarsFromConfig, DeclarationBlock, getConfigValue, indent, isOneOfInputObjectType, transformComment, getNodeComment, wrapWithSingleQuotes, } from './utils.js';
|
|
8
8
|
import { OperationVariablesToObject } from './variables-to-object.js';
|
|
9
|
-
|
|
9
|
+
import { buildEnumValuesBlock } from './convert-schema-enum-to-declaration-block-string.js';
|
|
10
|
+
import { buildTypeImport, getEnumsImports } from './imports.js';
|
|
10
11
|
export class BaseTypesVisitor extends BaseVisitor {
|
|
11
12
|
_schema;
|
|
12
13
|
_argumentsTransformer;
|
|
@@ -55,10 +56,20 @@ export class BaseTypesVisitor extends BaseVisitor {
|
|
|
55
56
|
return Object.keys(this.config.scalars).reduce((res, enumName) => {
|
|
56
57
|
const mappedValue = this.config.scalars[enumName];
|
|
57
58
|
if (mappedValue.input.isExternal) {
|
|
58
|
-
res.push(
|
|
59
|
+
res.push(buildTypeImport({
|
|
60
|
+
identifier: mappedValue.input.import,
|
|
61
|
+
source: mappedValue.input.source,
|
|
62
|
+
asDefault: mappedValue.input.default,
|
|
63
|
+
useTypeImports: this.config.useTypeImports,
|
|
64
|
+
}));
|
|
59
65
|
}
|
|
60
66
|
if (mappedValue.output.isExternal) {
|
|
61
|
-
res.push(
|
|
67
|
+
res.push(buildTypeImport({
|
|
68
|
+
identifier: mappedValue.output.import,
|
|
69
|
+
source: mappedValue.output.source,
|
|
70
|
+
asDefault: mappedValue.output.default,
|
|
71
|
+
useTypeImports: this.config.useTypeImports,
|
|
72
|
+
}));
|
|
62
73
|
}
|
|
63
74
|
return res;
|
|
64
75
|
}, []);
|
|
@@ -68,7 +79,12 @@ export class BaseTypesVisitor extends BaseVisitor {
|
|
|
68
79
|
.map(directive => {
|
|
69
80
|
const mappedValue = this.config.directiveArgumentAndInputFieldMappings[directive];
|
|
70
81
|
if (mappedValue.isExternal) {
|
|
71
|
-
return
|
|
82
|
+
return buildTypeImport({
|
|
83
|
+
identifier: mappedValue.import,
|
|
84
|
+
source: mappedValue.source,
|
|
85
|
+
asDefault: mappedValue.default,
|
|
86
|
+
useTypeImports: this.config.useTypeImports,
|
|
87
|
+
});
|
|
72
88
|
}
|
|
73
89
|
return null;
|
|
74
90
|
})
|
|
@@ -165,7 +181,7 @@ export class BaseTypesVisitor extends BaseVisitor {
|
|
|
165
181
|
return '';
|
|
166
182
|
const typeString = node.type;
|
|
167
183
|
const { type } = this._parsedConfig.declarationKind;
|
|
168
|
-
const comment =
|
|
184
|
+
const comment = getNodeComment(node);
|
|
169
185
|
return comment + indent(`${node.name.value}: ${typeString}${this.getPunctuation(type)}`);
|
|
170
186
|
}
|
|
171
187
|
UnionTypeDefinition(node, key, parent) {
|
|
@@ -249,43 +265,11 @@ export class BaseTypesVisitor extends BaseVisitor {
|
|
|
249
265
|
// We empty this because we handle scalars in a different way, see constructor.
|
|
250
266
|
return '';
|
|
251
267
|
}
|
|
252
|
-
_buildTypeImport(identifier, source, asDefault = false) {
|
|
253
|
-
const { useTypeImports } = this.config;
|
|
254
|
-
if (asDefault) {
|
|
255
|
-
if (useTypeImports) {
|
|
256
|
-
return `import type { default as ${identifier} } from '${source}';`;
|
|
257
|
-
}
|
|
258
|
-
return `import ${identifier} from '${source}';`;
|
|
259
|
-
}
|
|
260
|
-
return `import${useTypeImports ? ' type' : ''} { ${identifier} } from '${source}';`;
|
|
261
|
-
}
|
|
262
|
-
handleEnumValueMapper(typeIdentifier, importIdentifier, sourceIdentifier, sourceFile) {
|
|
263
|
-
if (importIdentifier !== sourceIdentifier) {
|
|
264
|
-
// use namespace import to dereference nested enum
|
|
265
|
-
// { enumValues: { MyEnum: './my-file#NS.NestedEnum' } }
|
|
266
|
-
return [
|
|
267
|
-
this._buildTypeImport(importIdentifier || sourceIdentifier, sourceFile),
|
|
268
|
-
`import ${typeIdentifier} = ${sourceIdentifier};`,
|
|
269
|
-
];
|
|
270
|
-
}
|
|
271
|
-
if (sourceIdentifier !== typeIdentifier) {
|
|
272
|
-
return [this._buildTypeImport(`${sourceIdentifier} as ${typeIdentifier}`, sourceFile)];
|
|
273
|
-
}
|
|
274
|
-
return [this._buildTypeImport(importIdentifier || sourceIdentifier, sourceFile)];
|
|
275
|
-
}
|
|
276
268
|
getEnumsImports() {
|
|
277
|
-
return
|
|
278
|
-
.
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (mappedValue.isDefault) {
|
|
282
|
-
return [this._buildTypeImport(mappedValue.typeIdentifier, mappedValue.sourceFile, true)];
|
|
283
|
-
}
|
|
284
|
-
return this.handleEnumValueMapper(mappedValue.typeIdentifier, mappedValue.importIdentifier, mappedValue.sourceIdentifier, mappedValue.sourceFile);
|
|
285
|
-
}
|
|
286
|
-
return [];
|
|
287
|
-
})
|
|
288
|
-
.filter(Boolean);
|
|
269
|
+
return getEnumsImports({
|
|
270
|
+
enumValues: this.config.enumValues,
|
|
271
|
+
useTypeImports: this.config.useTypeImports,
|
|
272
|
+
});
|
|
289
273
|
}
|
|
290
274
|
EnumTypeDefinition(node) {
|
|
291
275
|
const enumName = node.name.value;
|
|
@@ -301,7 +285,21 @@ export class BaseTypesVisitor extends BaseVisitor {
|
|
|
301
285
|
useTypesSuffix: this.config.enumSuffix,
|
|
302
286
|
}))
|
|
303
287
|
.withComment(node.description.value)
|
|
304
|
-
.withBlock(
|
|
288
|
+
.withBlock(buildEnumValuesBlock({
|
|
289
|
+
typeName: enumName,
|
|
290
|
+
values: node.values,
|
|
291
|
+
schema: this._schema,
|
|
292
|
+
naming: {
|
|
293
|
+
convert: this.config.convert,
|
|
294
|
+
typesPrefix: this.config.typesPrefix,
|
|
295
|
+
useTypesPrefix: this.config.enumPrefix,
|
|
296
|
+
typesSuffix: this.config.typesSuffix,
|
|
297
|
+
useTypesSuffix: this.config.enumSuffix,
|
|
298
|
+
},
|
|
299
|
+
ignoreEnumValuesFromSchema: this.config.ignoreEnumValuesFromSchema,
|
|
300
|
+
declarationBlockConfig: this._declarationBlockConfig,
|
|
301
|
+
enumValues: this.config.enumValues,
|
|
302
|
+
})).string;
|
|
305
303
|
}
|
|
306
304
|
makeValidEnumIdentifier(identifier) {
|
|
307
305
|
if (/^[0-9]/.exec(identifier)) {
|
|
@@ -309,31 +307,6 @@ export class BaseTypesVisitor extends BaseVisitor {
|
|
|
309
307
|
}
|
|
310
308
|
return identifier;
|
|
311
309
|
}
|
|
312
|
-
buildEnumValuesBlock(typeName, values) {
|
|
313
|
-
const schemaEnumType = this._schema
|
|
314
|
-
? this._schema.getType(typeName)
|
|
315
|
-
: undefined;
|
|
316
|
-
return values
|
|
317
|
-
.map(enumOption => {
|
|
318
|
-
const optionName = this.makeValidEnumIdentifier(this.convertName(enumOption, {
|
|
319
|
-
useTypesPrefix: false,
|
|
320
|
-
// We can only strip out the underscores if the value contains other
|
|
321
|
-
// characters. Otherwise we'll generate syntactically invalid code.
|
|
322
|
-
transformUnderscore: !onlyUnderscoresPattern.test(enumOption.name.value),
|
|
323
|
-
}));
|
|
324
|
-
const comment = this.getNodeComment(enumOption);
|
|
325
|
-
const schemaEnumValue = schemaEnumType && !this.config.ignoreEnumValuesFromSchema
|
|
326
|
-
? schemaEnumType.getValue(enumOption.name.value).value
|
|
327
|
-
: undefined;
|
|
328
|
-
let enumValue = typeof schemaEnumValue === 'undefined' ? enumOption.name.value : schemaEnumValue;
|
|
329
|
-
if (typeof this.config.enumValues[typeName]?.mappedValues?.[enumValue] !== 'undefined') {
|
|
330
|
-
enumValue = this.config.enumValues[typeName].mappedValues[enumValue];
|
|
331
|
-
}
|
|
332
|
-
return (comment +
|
|
333
|
-
indent(`${optionName}${this._declarationBlockConfig.enumNameValueSeparator} ${wrapWithSingleQuotes(enumValue, typeof schemaEnumValue !== 'undefined')}`));
|
|
334
|
-
})
|
|
335
|
-
.join(',\n');
|
|
336
|
-
}
|
|
337
310
|
DirectiveDefinition(_node) {
|
|
338
311
|
return '';
|
|
339
312
|
}
|
|
@@ -420,26 +393,6 @@ export class BaseTypesVisitor extends BaseVisitor {
|
|
|
420
393
|
SchemaExtension() {
|
|
421
394
|
return null;
|
|
422
395
|
}
|
|
423
|
-
getNodeComment(node) {
|
|
424
|
-
let commentText = node.description?.value;
|
|
425
|
-
const deprecationDirective = node.directives.find(v => v.name.value === 'deprecated');
|
|
426
|
-
if (deprecationDirective) {
|
|
427
|
-
const deprecationReason = this.getDeprecationReason(deprecationDirective);
|
|
428
|
-
commentText = `${commentText ? `${commentText}\n` : ''}@deprecated ${deprecationReason}`;
|
|
429
|
-
}
|
|
430
|
-
const comment = transformComment(commentText, 1);
|
|
431
|
-
return comment;
|
|
432
|
-
}
|
|
433
|
-
getDeprecationReason(directive) {
|
|
434
|
-
if (directive.name.value === 'deprecated') {
|
|
435
|
-
let reason = 'Field no longer supported';
|
|
436
|
-
const deprecatedReason = directive.arguments[0];
|
|
437
|
-
if (deprecatedReason && deprecatedReason.value.kind === Kind.STRING) {
|
|
438
|
-
reason = deprecatedReason.value.value;
|
|
439
|
-
}
|
|
440
|
-
return reason;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
396
|
wrapWithListType(str) {
|
|
444
397
|
return `Array<${str}>`;
|
|
445
398
|
}
|
package/esm/base-visitor.js
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import autoBind from 'auto-bind';
|
|
2
2
|
import { convertFactory } from './naming.js';
|
|
3
|
-
import { normalizeImportExtension } from '@graphql-codegen/plugin-helpers';
|
|
4
3
|
export class BaseVisitor {
|
|
5
4
|
_parsedConfig;
|
|
6
5
|
_declarationBlockConfig = {};
|
|
7
6
|
scalars;
|
|
8
7
|
constructor(rawConfig, additionalConfig) {
|
|
9
|
-
const importExtension = normalizeImportExtension({
|
|
10
|
-
emitLegacyCommonJSImports: rawConfig.emitLegacyCommonJSImports,
|
|
11
|
-
importExtension: rawConfig.importExtension,
|
|
12
|
-
});
|
|
13
8
|
this._parsedConfig = {
|
|
14
9
|
convert: convertFactory(rawConfig),
|
|
15
10
|
typesPrefix: rawConfig.typesPrefix || '',
|
|
@@ -21,8 +16,7 @@ export class BaseVisitor {
|
|
|
21
16
|
useTypeImports: !!rawConfig.useTypeImports,
|
|
22
17
|
allowEnumStringTypes: !!rawConfig.allowEnumStringTypes,
|
|
23
18
|
inlineFragmentTypes: rawConfig.inlineFragmentTypes ?? 'inline',
|
|
24
|
-
emitLegacyCommonJSImports: rawConfig.emitLegacyCommonJSImports
|
|
25
|
-
importExtension,
|
|
19
|
+
emitLegacyCommonJSImports: rawConfig.emitLegacyCommonJSImports === undefined ? true : !!rawConfig.emitLegacyCommonJSImports,
|
|
26
20
|
extractAllFieldsToTypes: rawConfig.extractAllFieldsToTypes ?? false,
|
|
27
21
|
printFieldsOnNewLines: rawConfig.printFieldsOnNewLines ?? false,
|
|
28
22
|
includeExternalFragments: rawConfig.includeExternalFragments ?? false,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { basename, extname } from 'path';
|
|
2
|
-
import {
|
|
2
|
+
import { oldVisit } from '@graphql-codegen/plugin-helpers';
|
|
3
3
|
import { optimizeDocumentNode } from '@graphql-tools/optimize';
|
|
4
4
|
import autoBind from 'auto-bind';
|
|
5
5
|
import { pascalCase } from 'change-case-all';
|
|
@@ -292,11 +292,7 @@ export class ClientSideBaseVisitor extends BaseVisitor {
|
|
|
292
292
|
}
|
|
293
293
|
clearExtension(path) {
|
|
294
294
|
const extension = extname(path);
|
|
295
|
-
|
|
296
|
-
emitLegacyCommonJSImports: this.config.emitLegacyCommonJSImports,
|
|
297
|
-
importExtension: this.config.importExtension,
|
|
298
|
-
});
|
|
299
|
-
if (extension === importExtension) {
|
|
295
|
+
if (!this.config.emitLegacyCommonJSImports && extension === '.js') {
|
|
300
296
|
return path;
|
|
301
297
|
}
|
|
302
298
|
if (EXTENSIONS_TO_REMOVE.includes(extension)) {
|
|
@@ -330,10 +326,9 @@ export class ClientSideBaseVisitor extends BaseVisitor {
|
|
|
330
326
|
if (this._collectedOperations.length > 0) {
|
|
331
327
|
if (this.config.importDocumentNodeExternallyFrom === 'near-operation-file' && this._documents.length === 1) {
|
|
332
328
|
let documentPath = `./${this.clearExtension(basename(this._documents[0].location))}`;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
});
|
|
329
|
+
if (!this.config.emitLegacyCommonJSImports) {
|
|
330
|
+
documentPath += '.js';
|
|
331
|
+
}
|
|
337
332
|
this._imports.add(`import * as Operations from '${documentPath}';`);
|
|
338
333
|
}
|
|
339
334
|
else {
|
|
@@ -351,10 +346,6 @@ export class ClientSideBaseVisitor extends BaseVisitor {
|
|
|
351
346
|
}
|
|
352
347
|
const excludeFragments = options.excludeFragments || this.config.globalNamespace || this.config.documentMode !== DocumentMode.graphQLTag;
|
|
353
348
|
if (!excludeFragments) {
|
|
354
|
-
const importExtension = normalizeImportExtension({
|
|
355
|
-
emitLegacyCommonJSImports: this.config.emitLegacyCommonJSImports,
|
|
356
|
-
importExtension: this.config.importExtension,
|
|
357
|
-
});
|
|
358
349
|
const deduplicatedImports = Object.values(groupBy(this.config.fragmentImports, fi => fi.importSource.path))
|
|
359
350
|
.map((fragmentImports) => ({
|
|
360
351
|
...fragmentImports[0],
|
|
@@ -363,7 +354,6 @@ export class ClientSideBaseVisitor extends BaseVisitor {
|
|
|
363
354
|
identifiers: unique(flatten(fragmentImports.map(fi => fi.importSource.identifiers)), identifier => identifier.name),
|
|
364
355
|
},
|
|
365
356
|
emitLegacyCommonJSImports: this.config.emitLegacyCommonJSImports,
|
|
366
|
-
importExtension,
|
|
367
357
|
}))
|
|
368
358
|
.filter(fragmentImport => fragmentImport.outputPath !== fragmentImport.importSource.path);
|
|
369
359
|
for (const fragmentImport of deduplicatedImports) {
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { DeclarationBlock, indent, transformComment, getNodeComment, wrapWithSingleQuotes, } from './utils.js';
|
|
2
|
+
export const convertSchemaEnumToDeclarationBlockString = ({ schema, node, enumName, enumValues, futureProofEnums, ignoreEnumValuesFromSchema, outputType, declarationBlockConfig, naming, }) => {
|
|
3
|
+
if (enumValues[enumName]?.sourceFile) {
|
|
4
|
+
return `export { ${enumValues[enumName].typeIdentifier} };\n`;
|
|
5
|
+
}
|
|
6
|
+
const getValueFromConfig = (enumValue) => {
|
|
7
|
+
if (typeof enumValues[enumName]?.mappedValues?.[enumValue] !== 'undefined') {
|
|
8
|
+
return enumValues[enumName].mappedValues[enumValue];
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
};
|
|
12
|
+
const withFutureAddedValue = [futureProofEnums ? [indent('| ' + wrapWithSingleQuotes('%future added value'))] : []];
|
|
13
|
+
const enumTypeName = convertName({
|
|
14
|
+
options: {
|
|
15
|
+
typesPrefix: naming.typesPrefix,
|
|
16
|
+
typesSuffix: naming.typesSuffix,
|
|
17
|
+
useTypesPrefix: naming.useTypesPrefix,
|
|
18
|
+
useTypesSuffix: naming.useTypesSuffix,
|
|
19
|
+
},
|
|
20
|
+
convert: () => naming.convert(node),
|
|
21
|
+
});
|
|
22
|
+
if (outputType === 'string-literal') {
|
|
23
|
+
return new DeclarationBlock(declarationBlockConfig)
|
|
24
|
+
.export()
|
|
25
|
+
.asKind('type')
|
|
26
|
+
.withComment(node.description?.value)
|
|
27
|
+
.withName(enumTypeName)
|
|
28
|
+
.withContent('\n' +
|
|
29
|
+
node.values
|
|
30
|
+
.map(enumOption => {
|
|
31
|
+
const name = enumOption.name.value;
|
|
32
|
+
const enumValue = getValueFromConfig(name) ?? name;
|
|
33
|
+
const comment = transformComment(enumOption.description?.value, 1);
|
|
34
|
+
return comment + indent('| ' + wrapWithSingleQuotes(enumValue));
|
|
35
|
+
})
|
|
36
|
+
.concat(...withFutureAddedValue)
|
|
37
|
+
.join('\n')).string;
|
|
38
|
+
}
|
|
39
|
+
if (outputType === 'native-numeric') {
|
|
40
|
+
return new DeclarationBlock(declarationBlockConfig)
|
|
41
|
+
.export()
|
|
42
|
+
.withComment(node.description?.value)
|
|
43
|
+
.withName(enumTypeName)
|
|
44
|
+
.asKind('enum')
|
|
45
|
+
.withBlock(node.values
|
|
46
|
+
.map((enumOption, i) => {
|
|
47
|
+
const valueFromConfig = getValueFromConfig(enumOption.name.value);
|
|
48
|
+
const enumValue = valueFromConfig ?? i;
|
|
49
|
+
const comment = transformComment(enumOption.description?.value, 1);
|
|
50
|
+
const optionName = makeValidEnumIdentifier(convertName({
|
|
51
|
+
options: {
|
|
52
|
+
typesPrefix: naming.typesPrefix,
|
|
53
|
+
typesSuffix: naming.typesSuffix,
|
|
54
|
+
useTypesPrefix: false,
|
|
55
|
+
},
|
|
56
|
+
convert: () => naming.convert(enumOption, { transformUnderscore: true }),
|
|
57
|
+
}));
|
|
58
|
+
return comment + indent(optionName) + ` = ${enumValue}`;
|
|
59
|
+
})
|
|
60
|
+
.concat(...withFutureAddedValue)
|
|
61
|
+
.join(',\n')).string;
|
|
62
|
+
}
|
|
63
|
+
if (outputType === 'const') {
|
|
64
|
+
const typeName = `export type ${enumTypeName} = typeof ${enumTypeName}[keyof typeof ${enumTypeName}];`;
|
|
65
|
+
const enumAsConst = new DeclarationBlock({
|
|
66
|
+
...declarationBlockConfig,
|
|
67
|
+
blockTransformer: block => {
|
|
68
|
+
return block + ' as const';
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
.export()
|
|
72
|
+
.asKind('const')
|
|
73
|
+
.withName(enumTypeName)
|
|
74
|
+
.withComment(node.description?.value)
|
|
75
|
+
.withBlock(node.values
|
|
76
|
+
.map(enumOption => {
|
|
77
|
+
const optionName = makeValidEnumIdentifier(convertName({
|
|
78
|
+
options: {
|
|
79
|
+
typesPrefix: naming.typesPrefix,
|
|
80
|
+
typesSuffix: naming.typesPrefix,
|
|
81
|
+
},
|
|
82
|
+
convert: () => naming.convert(enumOption, {
|
|
83
|
+
transformUnderscore: true,
|
|
84
|
+
}),
|
|
85
|
+
}));
|
|
86
|
+
const comment = transformComment(enumOption.description?.value, 1);
|
|
87
|
+
const name = enumOption.name.value;
|
|
88
|
+
const enumValue = getValueFromConfig(name) ?? name;
|
|
89
|
+
return comment + indent(`${optionName}: ${wrapWithSingleQuotes(enumValue)}`);
|
|
90
|
+
})
|
|
91
|
+
.join(',\n')).string;
|
|
92
|
+
return [enumAsConst, typeName].join('\n');
|
|
93
|
+
}
|
|
94
|
+
return new DeclarationBlock(declarationBlockConfig)
|
|
95
|
+
.export()
|
|
96
|
+
.asKind(outputType === 'native-const' ? 'const enum' : 'enum')
|
|
97
|
+
.withName(enumTypeName)
|
|
98
|
+
.withComment(node.description?.value)
|
|
99
|
+
.withBlock(buildEnumValuesBlock({
|
|
100
|
+
typeName: enumName,
|
|
101
|
+
values: node.values,
|
|
102
|
+
schema,
|
|
103
|
+
naming,
|
|
104
|
+
ignoreEnumValuesFromSchema,
|
|
105
|
+
declarationBlockConfig,
|
|
106
|
+
enumValues,
|
|
107
|
+
})).string;
|
|
108
|
+
};
|
|
109
|
+
export const buildEnumValuesBlock = ({ typeName, values, schema, naming, ignoreEnumValuesFromSchema, declarationBlockConfig, enumValues, }) => {
|
|
110
|
+
const schemaEnumType = schema
|
|
111
|
+
? schema.getType(typeName)
|
|
112
|
+
: undefined;
|
|
113
|
+
return values
|
|
114
|
+
.map(enumOption => {
|
|
115
|
+
const onlyUnderscoresPattern = /^_+$/;
|
|
116
|
+
const optionName = makeValidEnumIdentifier(convertName({
|
|
117
|
+
options: {
|
|
118
|
+
useTypesPrefix: false,
|
|
119
|
+
typesPrefix: naming.typesPrefix,
|
|
120
|
+
typesSuffix: naming.typesSuffix,
|
|
121
|
+
},
|
|
122
|
+
convert: () => naming.convert(enumOption, {
|
|
123
|
+
// We can only strip out the underscores if the value contains other
|
|
124
|
+
// characters. Otherwise we'll generate syntactically invalid code.
|
|
125
|
+
transformUnderscore: !onlyUnderscoresPattern.test(enumOption.name.value),
|
|
126
|
+
}),
|
|
127
|
+
}));
|
|
128
|
+
const comment = getNodeComment(enumOption);
|
|
129
|
+
const schemaEnumValue = schemaEnumType && !ignoreEnumValuesFromSchema
|
|
130
|
+
? schemaEnumType.getValue(enumOption.name.value).value
|
|
131
|
+
: undefined;
|
|
132
|
+
let enumValue = typeof schemaEnumValue === 'undefined' ? enumOption.name.value : schemaEnumValue;
|
|
133
|
+
if (typeof enumValues[typeName]?.mappedValues?.[enumValue] !== 'undefined') {
|
|
134
|
+
enumValue = enumValues[typeName].mappedValues[enumValue];
|
|
135
|
+
}
|
|
136
|
+
return (comment +
|
|
137
|
+
indent(`${optionName}${declarationBlockConfig.enumNameValueSeparator} ${wrapWithSingleQuotes(enumValue, typeof schemaEnumValue !== 'undefined')}`));
|
|
138
|
+
})
|
|
139
|
+
.join(',\n');
|
|
140
|
+
};
|
|
141
|
+
const makeValidEnumIdentifier = (identifier) => {
|
|
142
|
+
if (/^[0-9]/.exec(identifier)) {
|
|
143
|
+
return wrapWithSingleQuotes(identifier, true);
|
|
144
|
+
}
|
|
145
|
+
return identifier;
|
|
146
|
+
};
|
|
147
|
+
const convertName = ({ convert, options, }) => {
|
|
148
|
+
const useTypesPrefix = typeof options.useTypesPrefix === 'boolean' ? options.useTypesPrefix : true;
|
|
149
|
+
const useTypesSuffix = typeof options.useTypesSuffix === 'boolean' ? options.useTypesSuffix : true;
|
|
150
|
+
let convertedName = '';
|
|
151
|
+
if (useTypesPrefix) {
|
|
152
|
+
convertedName += options.typesPrefix;
|
|
153
|
+
}
|
|
154
|
+
convertedName += convert();
|
|
155
|
+
if (useTypesSuffix) {
|
|
156
|
+
convertedName += options.typesSuffix;
|
|
157
|
+
}
|
|
158
|
+
return convertedName;
|
|
159
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { isIntrospectionType, isSpecifiedScalarType } from 'graphql';
|
|
2
|
+
export const isNativeNamedType = (namedType) => {
|
|
3
|
+
// "Native" NamedType in this context means the following:
|
|
4
|
+
// 1. introspection types i.e. with `__` prefixes
|
|
5
|
+
// 2. base scalars e.g. Boolean, Int, etc.
|
|
6
|
+
// 3. Other natives (mostly base scalars) which was not defined in the schema i.e. no `astNode`
|
|
7
|
+
if (isSpecifiedScalarType(namedType) || isIntrospectionType(namedType) || !namedType.astNode) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
return false;
|
|
11
|
+
};
|