@graphql-codegen/visitor-plugin-common 7.2.0 → 7.2.1-alpha-20260719125849-4e20a28d5fee4dafc8a6cf0e22a03eedfd6ab3ff

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.
@@ -73,7 +73,10 @@ class SelectionSetToObject {
73
73
  // fragment (using @defer).
74
74
  const fieldsWithFragmentDirectives = fields.map(field => ({
75
75
  ...field,
76
- fragmentDirectives: directives,
76
+ // A field may already carry `fragmentDirectives` from an enclosing
77
+ // conditional fragment spread; keep those in addition to the
78
+ // directives on this inline fragment, instead of overwriting them.
79
+ fragmentDirectives: [...(field.fragmentDirectives || []), ...(directives || [])],
77
80
  }));
78
81
  if ((0, graphql_1.isObjectType)(typeOnSchema)) {
79
82
  this._appendToTypeMap(types, typeOnSchema.name, fieldsWithFragmentDirectives);
@@ -518,7 +521,7 @@ class SelectionSetToObject {
518
521
  selectionNodes = [...selectionNodes];
519
522
  let inlineFragmentConditional = false;
520
523
  for (const selectionNode of selectionNodes) {
521
- // 1. Handle Field or Directtives selection nodes
524
+ // 1. Handle Field or Directives selection nodes
522
525
  if ('kind' in selectionNode) {
523
526
  if (selectionNode.kind === graphql_1.Kind.FIELD) {
524
527
  if (selectionNode.selectionSet) {
@@ -594,6 +597,9 @@ class SelectionSetToObject {
594
597
  if (fragmentType == null) {
595
598
  throw new TypeError(`Unexpected error: Type ${selectionNode.onType} does not exist within schema.`);
596
599
  }
600
+ // #region Recursively find all fields and nested fields of the SelectionSet
601
+ // And by pushing the fields to `selectionNodes`
602
+ // The for loop continues to build SelectionSet & nested SelectionSet exhaustively
597
603
  if (parentSchemaType.name === selectionNode.onType ||
598
604
  parentSchemaType
599
605
  .getInterfaces()
@@ -601,14 +607,21 @@ class SelectionSetToObject {
601
607
  ((0, graphql_1.isUnionType)(fragmentType) &&
602
608
  fragmentType.getTypes().find(objectType => objectType.name === parentSchemaType.name))) {
603
609
  // also process fields from fragment that apply for this parentType
604
- const { selectionNodesByTypeName } = this.flattenSelectionSet(selectionNode.selectionNodes, parentSchemaType);
610
+ const { selectionNodesByTypeName, selectionNodesByTypeNameConditional } = this.flattenSelectionSet(selectionNode.selectionNodes, parentSchemaType);
605
611
  const typeNodes = selectionNodesByTypeName.get(parentSchemaType.name) ?? [];
606
612
  selectionNodes.push(...typeNodes);
607
613
  for (const iinterface of parentSchemaType.getInterfaces()) {
608
614
  const typeNodes = selectionNodesByTypeName.get(iinterface.name) ?? [];
609
615
  selectionNodes.push(...typeNodes);
610
616
  }
617
+ for (const conditionalNodes of selectionNodesByTypeNameConditional) {
618
+ const _selectionNodes = (conditionalNodes.get(parentSchemaType.name) || []).filter((node) => 'fragmentDirectives' in node);
619
+ for (const selectionNode of _selectionNodes) {
620
+ selectionNodes.push(selectionNode);
621
+ }
622
+ }
611
623
  }
624
+ // #endregion
612
625
  }
613
626
  const linkFields = [];
614
627
  const linkFieldsInterfaces = [];
@@ -637,26 +650,30 @@ class SelectionSetToObject {
637
650
  });
638
651
  }
639
652
  const typeInfoField = this.buildTypeNameField(parentSchemaType, this._config.nonOptionalTypename, requireTypename, this._config.skipTypeNameForRoot);
653
+ // Only add the typename field if we're not merging fragment
654
+ // types. If we are merging, we need to wait until we know all
655
+ // the involved typenames.
656
+ const transformedTypenameFields = typeInfoField &&
657
+ (!this._config.mergeFragmentTypes || this._config.inlineFragmentTypes === 'mask')
658
+ ? this._processor.transformTypenameField(typeInfoField.type, typeInfoField.name)
659
+ : [];
660
+ const transformedPrimitiveFields = this._processor.transformPrimitiveFields(parentSchemaType, Array.from(primitiveFields.values()).map(field => ({
661
+ isConditional: (0, utils_js_1.hasConditionalDirectives)(field.directives) ||
662
+ (0, utils_js_1.hasConditionalDirectives)(field.fragmentDirectives),
663
+ fieldName: field.name.value,
664
+ })), options.unsetTypes);
665
+ const transformedAliasesPrimitiveFields = this._processor.transformAliasesPrimitiveFields(parentSchemaType, Array.from(primitiveAliasFields.values()).map(field => ({
666
+ alias: field.alias.value,
667
+ fieldName: field.name.value,
668
+ isConditional: (0, utils_js_1.hasConditionalDirectives)(field.directives) ||
669
+ (0, utils_js_1.hasConditionalDirectives)(field.fragmentDirectives),
670
+ })), options.unsetTypes);
671
+ const transformedLinkFields = this._processor.transformLinkFields(linkFields, options.unsetTypes);
640
672
  const transformed = [
641
- // Only add the typename field if we're not merging fragment
642
- // types. If we are merging, we need to wait until we know all
643
- // the involved typenames.
644
- ...(typeInfoField &&
645
- (!this._config.mergeFragmentTypes || this._config.inlineFragmentTypes === 'mask')
646
- ? this._processor.transformTypenameField(typeInfoField.type, typeInfoField.name)
647
- : []),
648
- ...this._processor.transformPrimitiveFields(parentSchemaType, Array.from(primitiveFields.values()).map(field => ({
649
- isConditional: (0, utils_js_1.hasConditionalDirectives)(field.directives) ||
650
- (0, utils_js_1.hasConditionalDirectives)(field.fragmentDirectives),
651
- fieldName: field.name.value,
652
- })), options.unsetTypes),
653
- ...this._processor.transformAliasesPrimitiveFields(parentSchemaType, Array.from(primitiveAliasFields.values()).map(field => ({
654
- alias: field.alias.value,
655
- fieldName: field.name.value,
656
- isConditional: (0, utils_js_1.hasConditionalDirectives)(field.directives) ||
657
- (0, utils_js_1.hasConditionalDirectives)(field.fragmentDirectives),
658
- })), options.unsetTypes),
659
- ...this._processor.transformLinkFields(linkFields, options.unsetTypes),
673
+ ...transformedTypenameFields,
674
+ ...transformedPrimitiveFields,
675
+ ...transformedAliasesPrimitiveFields,
676
+ ...transformedLinkFields,
660
677
  ].filter(Boolean);
661
678
  const allStrings = transformed.filter(t => typeof t === 'string');
662
679
  const allObjectsMerged = transformed
@@ -69,7 +69,10 @@ export class SelectionSetToObject {
69
69
  // fragment (using @defer).
70
70
  const fieldsWithFragmentDirectives = fields.map(field => ({
71
71
  ...field,
72
- fragmentDirectives: directives,
72
+ // A field may already carry `fragmentDirectives` from an enclosing
73
+ // conditional fragment spread; keep those in addition to the
74
+ // directives on this inline fragment, instead of overwriting them.
75
+ fragmentDirectives: [...(field.fragmentDirectives || []), ...(directives || [])],
73
76
  }));
74
77
  if (isObjectType(typeOnSchema)) {
75
78
  this._appendToTypeMap(types, typeOnSchema.name, fieldsWithFragmentDirectives);
@@ -514,7 +517,7 @@ export class SelectionSetToObject {
514
517
  selectionNodes = [...selectionNodes];
515
518
  let inlineFragmentConditional = false;
516
519
  for (const selectionNode of selectionNodes) {
517
- // 1. Handle Field or Directtives selection nodes
520
+ // 1. Handle Field or Directives selection nodes
518
521
  if ('kind' in selectionNode) {
519
522
  if (selectionNode.kind === Kind.FIELD) {
520
523
  if (selectionNode.selectionSet) {
@@ -590,6 +593,9 @@ export class SelectionSetToObject {
590
593
  if (fragmentType == null) {
591
594
  throw new TypeError(`Unexpected error: Type ${selectionNode.onType} does not exist within schema.`);
592
595
  }
596
+ // #region Recursively find all fields and nested fields of the SelectionSet
597
+ // And by pushing the fields to `selectionNodes`
598
+ // The for loop continues to build SelectionSet & nested SelectionSet exhaustively
593
599
  if (parentSchemaType.name === selectionNode.onType ||
594
600
  parentSchemaType
595
601
  .getInterfaces()
@@ -597,14 +603,21 @@ export class SelectionSetToObject {
597
603
  (isUnionType(fragmentType) &&
598
604
  fragmentType.getTypes().find(objectType => objectType.name === parentSchemaType.name))) {
599
605
  // also process fields from fragment that apply for this parentType
600
- const { selectionNodesByTypeName } = this.flattenSelectionSet(selectionNode.selectionNodes, parentSchemaType);
606
+ const { selectionNodesByTypeName, selectionNodesByTypeNameConditional } = this.flattenSelectionSet(selectionNode.selectionNodes, parentSchemaType);
601
607
  const typeNodes = selectionNodesByTypeName.get(parentSchemaType.name) ?? [];
602
608
  selectionNodes.push(...typeNodes);
603
609
  for (const iinterface of parentSchemaType.getInterfaces()) {
604
610
  const typeNodes = selectionNodesByTypeName.get(iinterface.name) ?? [];
605
611
  selectionNodes.push(...typeNodes);
606
612
  }
613
+ for (const conditionalNodes of selectionNodesByTypeNameConditional) {
614
+ const _selectionNodes = (conditionalNodes.get(parentSchemaType.name) || []).filter((node) => 'fragmentDirectives' in node);
615
+ for (const selectionNode of _selectionNodes) {
616
+ selectionNodes.push(selectionNode);
617
+ }
618
+ }
607
619
  }
620
+ // #endregion
608
621
  }
609
622
  const linkFields = [];
610
623
  const linkFieldsInterfaces = [];
@@ -633,26 +646,30 @@ export class SelectionSetToObject {
633
646
  });
634
647
  }
635
648
  const typeInfoField = this.buildTypeNameField(parentSchemaType, this._config.nonOptionalTypename, requireTypename, this._config.skipTypeNameForRoot);
649
+ // Only add the typename field if we're not merging fragment
650
+ // types. If we are merging, we need to wait until we know all
651
+ // the involved typenames.
652
+ const transformedTypenameFields = typeInfoField &&
653
+ (!this._config.mergeFragmentTypes || this._config.inlineFragmentTypes === 'mask')
654
+ ? this._processor.transformTypenameField(typeInfoField.type, typeInfoField.name)
655
+ : [];
656
+ const transformedPrimitiveFields = this._processor.transformPrimitiveFields(parentSchemaType, Array.from(primitiveFields.values()).map(field => ({
657
+ isConditional: hasConditionalDirectives(field.directives) ||
658
+ hasConditionalDirectives(field.fragmentDirectives),
659
+ fieldName: field.name.value,
660
+ })), options.unsetTypes);
661
+ const transformedAliasesPrimitiveFields = this._processor.transformAliasesPrimitiveFields(parentSchemaType, Array.from(primitiveAliasFields.values()).map(field => ({
662
+ alias: field.alias.value,
663
+ fieldName: field.name.value,
664
+ isConditional: hasConditionalDirectives(field.directives) ||
665
+ hasConditionalDirectives(field.fragmentDirectives),
666
+ })), options.unsetTypes);
667
+ const transformedLinkFields = this._processor.transformLinkFields(linkFields, options.unsetTypes);
636
668
  const transformed = [
637
- // Only add the typename field if we're not merging fragment
638
- // types. If we are merging, we need to wait until we know all
639
- // the involved typenames.
640
- ...(typeInfoField &&
641
- (!this._config.mergeFragmentTypes || this._config.inlineFragmentTypes === 'mask')
642
- ? this._processor.transformTypenameField(typeInfoField.type, typeInfoField.name)
643
- : []),
644
- ...this._processor.transformPrimitiveFields(parentSchemaType, Array.from(primitiveFields.values()).map(field => ({
645
- isConditional: hasConditionalDirectives(field.directives) ||
646
- hasConditionalDirectives(field.fragmentDirectives),
647
- fieldName: field.name.value,
648
- })), options.unsetTypes),
649
- ...this._processor.transformAliasesPrimitiveFields(parentSchemaType, Array.from(primitiveAliasFields.values()).map(field => ({
650
- alias: field.alias.value,
651
- fieldName: field.name.value,
652
- isConditional: hasConditionalDirectives(field.directives) ||
653
- hasConditionalDirectives(field.fragmentDirectives),
654
- })), options.unsetTypes),
655
- ...this._processor.transformLinkFields(linkFields, options.unsetTypes),
669
+ ...transformedTypenameFields,
670
+ ...transformedPrimitiveFields,
671
+ ...transformedAliasesPrimitiveFields,
672
+ ...transformedLinkFields,
656
673
  ].filter(Boolean);
657
674
  const allStrings = transformed.filter(t => typeof t === 'string');
658
675
  const allObjectsMerged = transformed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-codegen/visitor-plugin-common",
3
- "version": "7.2.0",
3
+ "version": "7.2.1-alpha-20260719125849-4e20a28d5fee4dafc8a6cf0e22a03eedfd6ab3ff",
4
4
  "peerDependencies": {
5
5
  "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
6
6
  },
@@ -14,7 +14,7 @@ type FragmentSpreadUsage = {
14
14
  /**
15
15
  * @description EnrichedFieldNode are field nodes enriched with Codegen metadata for subsequent processing
16
16
  */
17
- type EnrichedFieldNode = FieldNode & {
17
+ export type EnrichedFieldNode = FieldNode & {
18
18
  /**
19
19
  * A field node may implicitly inherit fragment directives from parents
20
20
  * For example, if the field's parent is marked with `@skip`, the field is implicitly marked with `@skip` as well
@@ -14,7 +14,7 @@ type FragmentSpreadUsage = {
14
14
  /**
15
15
  * @description EnrichedFieldNode are field nodes enriched with Codegen metadata for subsequent processing
16
16
  */
17
- type EnrichedFieldNode = FieldNode & {
17
+ export type EnrichedFieldNode = FieldNode & {
18
18
  /**
19
19
  * A field node may implicitly inherit fragment directives from parents
20
20
  * For example, if the field's parent is marked with `@skip`, the field is implicitly marked with `@skip` as well
@@ -1,6 +1,7 @@
1
1
  import { DirectiveNode, EnumValueDefinitionNode, FieldDefinitionNode, FieldNode, FragmentSpreadNode, GraphQLInputObjectType, GraphQLNamedType, GraphQLObjectType, GraphQLOutputType, GraphQLSchema, InlineFragmentNode, InputValueDefinitionNode, NamedTypeNode, NameNode, SelectionNode, SelectionSetNode, StringValueNode, TypeNode } from 'graphql';
2
- import { RawConfig } from './base-visitor.cjs';
3
- import { LoadedFragment, NormalizedScalarsMap, ParsedScalarsMap, ScalarsMap } from './types.cjs';
2
+ import type { RawConfig } from './base-visitor.cjs';
3
+ import type { EnrichedFieldNode } from './selection-set-to-object.cjs';
4
+ import type { LoadedFragment, NormalizedScalarsMap, ParsedScalarsMap, ScalarsMap } from './types.cjs';
4
5
  export declare const getConfigValue: <T = any>(value: T, defaultValue: T) => T;
5
6
  export declare function quoteIfNeeded(array: string[], joinWith?: string): string;
6
7
  export declare function block(array: any): string;
@@ -50,7 +51,7 @@ export declare const REQUIRE_FIELDS_TYPE = "export type RequireFields<T, K exten
50
51
  export declare function mergeSelectionSets(selectionSet1: SelectionSetNode, selectionSet2: SelectionSetNode): SelectionSetNode;
51
52
  export declare const getFieldNodeNameValue: (node: FieldNode) => string;
52
53
  export declare function separateSelectionSet(selections: ReadonlyArray<SelectionNode>): {
53
- fields: FieldNode[];
54
+ fields: EnrichedFieldNode[];
54
55
  spreads: FragmentSpreadNode[];
55
56
  inlines: InlineFragmentNode[];
56
57
  };
@@ -1,6 +1,7 @@
1
1
  import { DirectiveNode, EnumValueDefinitionNode, FieldDefinitionNode, FieldNode, FragmentSpreadNode, GraphQLInputObjectType, GraphQLNamedType, GraphQLObjectType, GraphQLOutputType, GraphQLSchema, InlineFragmentNode, InputValueDefinitionNode, NamedTypeNode, NameNode, SelectionNode, SelectionSetNode, StringValueNode, TypeNode } from 'graphql';
2
- import { RawConfig } from './base-visitor.js';
3
- import { LoadedFragment, NormalizedScalarsMap, ParsedScalarsMap, ScalarsMap } from './types.js';
2
+ import type { RawConfig } from './base-visitor.js';
3
+ import type { EnrichedFieldNode } from './selection-set-to-object.js';
4
+ import type { LoadedFragment, NormalizedScalarsMap, ParsedScalarsMap, ScalarsMap } from './types.js';
4
5
  export declare const getConfigValue: <T = any>(value: T, defaultValue: T) => T;
5
6
  export declare function quoteIfNeeded(array: string[], joinWith?: string): string;
6
7
  export declare function block(array: any): string;
@@ -50,7 +51,7 @@ export declare const REQUIRE_FIELDS_TYPE = "export type RequireFields<T, K exten
50
51
  export declare function mergeSelectionSets(selectionSet1: SelectionSetNode, selectionSet2: SelectionSetNode): SelectionSetNode;
51
52
  export declare const getFieldNodeNameValue: (node: FieldNode) => string;
52
53
  export declare function separateSelectionSet(selections: ReadonlyArray<SelectionNode>): {
53
- fields: FieldNode[];
54
+ fields: EnrichedFieldNode[];
54
55
  spreads: FragmentSpreadNode[];
55
56
  inlines: InlineFragmentNode[];
56
57
  };