@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.
Files changed (45) hide show
  1. package/cjs/base-documents-visitor.js +8 -0
  2. package/cjs/base-resolvers-visitor.js +5 -7
  3. package/cjs/base-types-visitor.js +40 -87
  4. package/cjs/base-visitor.js +1 -7
  5. package/cjs/client-side-base-visitor.js +4 -14
  6. package/cjs/convert-schema-enum-to-declaration-block-string.js +164 -0
  7. package/cjs/graphql-type-utils.js +15 -0
  8. package/cjs/imports.js +55 -7
  9. package/cjs/index.js +2 -0
  10. package/cjs/selection-set-processor/pre-resolve-types.js +9 -5
  11. package/cjs/selection-set-to-object.js +12 -18
  12. package/cjs/utils.js +22 -1
  13. package/esm/base-documents-visitor.js +8 -0
  14. package/esm/base-resolvers-visitor.js +5 -7
  15. package/esm/base-types-visitor.js +41 -88
  16. package/esm/base-visitor.js +1 -7
  17. package/esm/client-side-base-visitor.js +5 -15
  18. package/esm/convert-schema-enum-to-declaration-block-string.js +159 -0
  19. package/esm/graphql-type-utils.js +11 -0
  20. package/esm/imports.js +53 -7
  21. package/esm/index.js +2 -0
  22. package/esm/selection-set-processor/pre-resolve-types.js +11 -7
  23. package/esm/selection-set-to-object.js +12 -18
  24. package/esm/utils.js +20 -0
  25. package/package.json +2 -2
  26. package/typings/base-documents-visitor.d.cts +49 -1
  27. package/typings/base-documents-visitor.d.ts +49 -1
  28. package/typings/base-types-visitor.d.cts +1 -6
  29. package/typings/base-types-visitor.d.ts +1 -6
  30. package/typings/base-visitor.d.cts +1 -8
  31. package/typings/base-visitor.d.ts +1 -8
  32. package/typings/convert-schema-enum-to-declaration-block-string.d.cts +25 -0
  33. package/typings/convert-schema-enum-to-declaration-block-string.d.ts +25 -0
  34. package/typings/graphql-type-utils.d.cts +2 -0
  35. package/typings/graphql-type-utils.d.ts +2 -0
  36. package/typings/imports.d.cts +12 -2
  37. package/typings/imports.d.ts +12 -2
  38. package/typings/index.d.cts +2 -0
  39. package/typings/index.d.ts +2 -0
  40. package/typings/selection-set-processor/base.d.cts +5 -3
  41. package/typings/selection-set-processor/base.d.ts +5 -3
  42. package/typings/selection-set-to-object.d.cts +4 -4
  43. package/typings/selection-set-to-object.d.ts +4 -4
  44. package/typings/utils.d.cts +2 -1
  45. 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(field.alias.value, selectedFieldType, isConditional, isOptional)
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(field.name.value, selectedFieldType, isConditional, isOptional),
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: `${this._processor.config.formatNamedField('__typename')}${optionalTypename ? '?' : ''}`,
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
- if (operationTypes.includes(typeName)) {
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 (isEnumType(schemaType) && this.config.enumValues[typeName]) {
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
- const onlyUnderscoresPattern = /^_+$/;
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(this._buildTypeImport(mappedValue.input.import, mappedValue.input.source, mappedValue.input.default));
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(this._buildTypeImport(mappedValue.output.import, mappedValue.output.source, mappedValue.output.default));
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 this._buildTypeImport(mappedValue.import, mappedValue.source, mappedValue.default);
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 = this.getNodeComment(node);
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 Object.keys(this.config.enumValues)
278
- .flatMap(enumName => {
279
- const mappedValue = this.config.enumValues[enumName];
280
- if (mappedValue.sourceFile) {
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(this.buildEnumValuesBlock(enumName, node.values)).string;
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
  }
@@ -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 ?? true,
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 { normalizeImportExtension, oldVisit } from '@graphql-codegen/plugin-helpers';
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
- const importExtension = normalizeImportExtension({
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
- documentPath += normalizeImportExtension({
334
- emitLegacyCommonJSImports: this.config.emitLegacyCommonJSImports,
335
- importExtension: this.config.importExtension,
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
+ };