@wundergraph/composition 0.23.1 → 0.24.0

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.
@@ -167,7 +167,7 @@ class FederationFactory {
167
167
  return true;
168
168
  }
169
169
  if (entityAncestorName === parentTypeName) {
170
- const hasOverlap = (0, utils_3.doSetsHaveAnyOverlap)(fieldSubgraphs, (0, utils_3.getOrThrowError)(this.entityDataByTypeName, entityAncestorName, string_constants_1.ENTITIES).subgraphNames);
170
+ const hasOverlap = (0, utils_3.doSetsIntersect)(fieldSubgraphs, (0, utils_3.getOrThrowError)(this.entityDataByTypeName, entityAncestorName, string_constants_1.ENTITIES).subgraphNames);
171
171
  this.graphPaths.set(path, hasOverlap);
172
172
  return hasOverlap;
173
173
  }
@@ -244,7 +244,7 @@ class FederationFactory {
244
244
  }
245
245
  this.updateEvaluatedSubgraphOccurrences(rootTypeFieldData.subgraphs, objectData.subgraphNames, entityAncestors, parentTypeName);
246
246
  evaluatedObjectLikes.add(parentTypeName);
247
- const isFieldResolvable = (0, utils_3.doSetsHaveAnyOverlap)(rootTypeFieldData.subgraphs, fieldData.subgraphNames) ||
247
+ const isFieldResolvable = (0, utils_3.doSetsIntersect)(rootTypeFieldData.subgraphs, fieldData.subgraphNames) ||
248
248
  this.isFieldResolvableByEntityAncestor(entityAncestors, fieldData.subgraphNames, parentTypeName);
249
249
  const newCurrentFieldPath = currentFieldPath + (isParentAbstract ? ' ' : '.') + fieldName;
250
250
  const entity = this.entityDataByTypeName.get(namedFieldTypeName);
@@ -314,7 +314,7 @@ class FederationFactory {
314
314
  throw (0, errors_1.unexpectedParentKindErrorMessage)(concreteTypeName, 'Object', (0, utils_3.kindToTypeString)(concreteTypeData.kind));
315
315
  }
316
316
  // If the concrete type is unreachable through an inline fragment, it is not an error
317
- if (!(0, utils_3.doSetsHaveAnyOverlap)(concreteTypeData.subgraphNames, rootTypeFieldData.subgraphs)) {
317
+ if (!(0, utils_3.doSetsIntersect)(concreteTypeData.subgraphNames, rootTypeFieldData.subgraphs)) {
318
318
  continue;
319
319
  }
320
320
  const entity = this.entityDataByTypeName.get(concreteTypeName);
@@ -560,9 +560,16 @@ class FederationFactory {
560
560
  }
561
561
  }
562
562
  }
563
- upsertEnumValueData(enumValueDataByValueName, incomingData) {
563
+ upsertEnumValueData(enumValueDataByValueName, incomingData, isParentInaccessible) {
564
564
  const existingData = enumValueDataByValueName.get(incomingData.name);
565
- (0, utils_5.extractPersistedDirectives)(existingData?.persistedDirectivesData || incomingData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
565
+ const baseData = existingData || incomingData;
566
+ const enumValuePath = `${incomingData.parentTypeName}.${incomingData.name}`;
567
+ (0, utils_5.extractPersistedDirectives)(baseData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
568
+ const isFieldInaccessible = (0, utils_5.isNodeDataInaccessible)(incomingData);
569
+ if (isParentInaccessible || isFieldInaccessible) {
570
+ this.inaccessiblePaths.add(enumValuePath);
571
+ }
572
+ this.recordTagNamesByPath(baseData, enumValuePath);
566
573
  if (!existingData) {
567
574
  incomingData.node = {
568
575
  directives: [],
@@ -575,9 +582,12 @@ class FederationFactory {
575
582
  existingData.appearances += 1;
576
583
  (0, utils_5.setLongestDescription)(existingData, incomingData);
577
584
  }
578
- upsertInputValueData(inputValueDataByValueName, incomingData) {
585
+ // To facilitate the splitting of tag paths, field arguments do not use the renamedPath property for tagNamesByPath
586
+ upsertInputValueData(inputValueDataByValueName, incomingData, path) {
579
587
  const existingData = inputValueDataByValueName.get(incomingData.name);
580
- (0, utils_5.extractPersistedDirectives)(existingData?.persistedDirectivesData || incomingData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
588
+ const baseData = existingData || incomingData;
589
+ (0, utils_5.extractPersistedDirectives)(baseData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
590
+ this.recordTagNamesByPath(baseData, path || baseData.renamedPath);
581
591
  if (!existingData) {
582
592
  incomingData.node = {
583
593
  directives: [],
@@ -629,17 +639,13 @@ class FederationFactory {
629
639
  (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, incomingData.namedTypeName, () => new Set()).add(fieldPath);
630
640
  this.namedOutputTypeNames.add(incomingData.namedTypeName);
631
641
  const existingData = fieldDataByFieldName.get(incomingData.name);
632
- (0, utils_5.extractPersistedDirectives)(existingData?.persistedDirectivesData || incomingData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
642
+ const baseData = existingData || incomingData;
643
+ (0, utils_5.extractPersistedDirectives)(baseData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
633
644
  const isFieldInaccessible = (0, utils_5.isNodeDataInaccessible)(incomingData);
634
645
  if (isParentInaccessible || isFieldInaccessible) {
635
646
  this.inaccessiblePaths.add(fieldPath);
636
647
  }
637
- if (incomingData.persistedDirectivesData.tags.size > 0) {
638
- const tagNames = (0, utils_3.getValueOrDefault)(this.tagNamesByPath, fieldPath, () => new Set());
639
- for (const tagName of incomingData.persistedDirectivesData.tags.keys()) {
640
- tagNames.add(tagName);
641
- }
642
- }
648
+ this.recordTagNamesByPath(baseData, fieldPath);
643
649
  if (!existingData) {
644
650
  fieldDataByFieldName.set(incomingData.name, incomingData);
645
651
  incomingData.node = {
@@ -656,22 +662,15 @@ class FederationFactory {
656
662
  name: (0, utils_1.stringToNameNode)(inputValueData.name),
657
663
  type: inputValueData.type,
658
664
  };
659
- const argumentPath = `${fieldPath}(${argumentName}: ... )`;
660
665
  const namedArgumentTypeName = (0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type);
661
- (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(argumentPath);
666
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(inputValueData.renamedPath);
662
667
  this.namedInputValueTypeNames.add(namedArgumentTypeName);
663
668
  (0, utils_5.extractPersistedDirectives)(inputValueData.persistedDirectivesData, inputValueData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
664
669
  /* If either the parent or the field to which the field belongs are declared inaccessible, the nullability
665
670
  ** of the argument is not considered. However, if only the argument is declared inaccessible, it is an
666
671
  ** error. */
667
- this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, argumentPath, fieldPath);
668
- if (inputValueData.persistedDirectivesData.tags.size > 0) {
669
- const tagArgumentPath = `${fieldPath}.${argumentName}`;
670
- const tagNames = (0, utils_3.getValueOrDefault)(this.tagNamesByPath, tagArgumentPath, () => new Set());
671
- for (const tagName of inputValueData.persistedDirectivesData.tags.keys()) {
672
- tagNames.add(tagName);
673
- }
674
- }
672
+ this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, inputValueData.renamedPath, fieldPath);
673
+ this.recordTagNamesByPath(inputValueData, `${fieldPath}.${argumentName}`);
675
674
  }
676
675
  return;
677
676
  }
@@ -686,22 +685,14 @@ class FederationFactory {
686
685
  this.errors.push((0, errors_1.incompatibleChildTypesError)(fieldPath, typeErrors[0], typeErrors[1]));
687
686
  }
688
687
  for (const [argumentName, inputValueData] of incomingData.argumentDataByArgumentName) {
689
- const argumentPath = `${fieldPath}(${argumentName}: ... )`;
690
688
  const namedArgumentTypeName = (0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type);
691
- (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(argumentPath);
689
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(inputValueData.renamedPath);
692
690
  this.namedInputValueTypeNames.add(namedArgumentTypeName);
693
691
  /* If either the parent or the field to which the field belongs are declared inaccessible, the nullability
694
692
  ** of the argument is not considered. However, if only the argument is declared inaccessible, it is an
695
693
  ** error. */
696
- this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, argumentPath, fieldPath);
697
- if (inputValueData.persistedDirectivesData.tags.size > 0) {
698
- const tagArgumentPath = `${fieldPath}.${argumentName}`;
699
- const tagNames = (0, utils_3.getValueOrDefault)(this.tagNamesByPath, tagArgumentPath, () => new Set());
700
- for (const tagName of inputValueData.persistedDirectivesData.tags.keys()) {
701
- tagNames.add(tagName);
702
- }
703
- }
704
- this.upsertInputValueData(existingData.argumentDataByArgumentName, inputValueData);
694
+ this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, inputValueData.renamedPath, fieldPath);
695
+ this.upsertInputValueData(existingData.argumentDataByArgumentName, inputValueData, `${fieldPath}.${argumentName}`);
705
696
  }
706
697
  (0, utils_5.setLongestDescription)(existingData, incomingData);
707
698
  existingData.isInaccessible ||= incomingData.isInaccessible;
@@ -718,21 +709,25 @@ class FederationFactory {
718
709
  }
719
710
  return members;
720
711
  }
712
+ recordTagNamesByPath(data, nodePath) {
713
+ const path = nodePath || data.name;
714
+ if (data.persistedDirectivesData.tags.size > 0) {
715
+ const tagNames = (0, utils_3.getValueOrDefault)(this.tagNamesByPath, path, () => new Set());
716
+ for (const tagName of data.persistedDirectivesData.tags.keys()) {
717
+ tagNames.add(tagName);
718
+ }
719
+ }
720
+ }
721
721
  upsertParentDefinitionData(incomingData, subgraphName) {
722
722
  const entityInterfaceData = this.entityInterfaceFederationDataByTypeName.get(incomingData.name);
723
723
  const existingData = this.parentDefinitionDataByTypeName.get(incomingData.name);
724
724
  const baseData = existingData || incomingData;
725
725
  (0, utils_5.extractPersistedDirectives)(baseData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
726
+ this.recordTagNamesByPath(baseData);
726
727
  const isParentInaccessible = (0, utils_5.isNodeDataInaccessible)(baseData);
727
728
  if (isParentInaccessible) {
728
729
  this.inaccessiblePaths.add(incomingData.name);
729
730
  }
730
- if (incomingData.persistedDirectivesData.tags.size > 0) {
731
- const tagNames = (0, utils_3.getValueOrDefault)(this.tagNamesByPath, incomingData.name, () => new Set());
732
- for (const tagName of incomingData.persistedDirectivesData.tags.keys()) {
733
- tagNames.add(tagName);
734
- }
735
- }
736
731
  if (!existingData) {
737
732
  if (entityInterfaceData && entityInterfaceData.interfaceObjectSubgraphs.has(subgraphName)) {
738
733
  incomingData.kind = graphql_1.Kind.INTERFACE_TYPE_DEFINITION;
@@ -745,14 +740,16 @@ class FederationFactory {
745
740
  switch (incomingData.kind) {
746
741
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
747
742
  for (const [enumValueName, enumValueData] of incomingData.enumValueDataByValueName) {
743
+ const enumValuePath = `${incomingData.name}.${enumValueName}`;
748
744
  enumValueData.node = {
749
745
  directives: [],
750
746
  kind: enumValueData.node.kind,
751
747
  name: (0, utils_1.stringToNameNode)(enumValueData.name),
752
748
  };
753
749
  (0, utils_5.extractPersistedDirectives)(enumValueData.persistedDirectivesData, enumValueData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
750
+ this.recordTagNamesByPath(enumValueData, enumValuePath);
754
751
  if ((0, utils_5.isNodeDataInaccessible)(enumValueData)) {
755
- this.inaccessiblePaths.add(`${incomingData.name}.${enumValueName}`);
752
+ this.inaccessiblePaths.add(enumValuePath);
756
753
  }
757
754
  }
758
755
  return;
@@ -765,12 +762,12 @@ class FederationFactory {
765
762
  type: inputValueData.type,
766
763
  };
767
764
  const namedInputFieldTypeName = (0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type);
768
- const inputFieldPath = `${incomingData.name}.${inputFieldName}`;
769
- (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedInputFieldTypeName, () => new Set()).add(inputFieldPath);
765
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedInputFieldTypeName, () => new Set()).add(inputValueData.renamedPath);
770
766
  this.namedInputValueTypeNames.add(namedInputFieldTypeName);
771
767
  (0, utils_5.extractPersistedDirectives)(inputValueData.persistedDirectivesData, inputValueData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
768
+ this.recordTagNamesByPath(inputValueData, `${incomingData.name}.${inputFieldName}`);
772
769
  if (isParentInaccessible || (0, utils_5.isNodeDataInaccessible)(inputValueData)) {
773
- this.inaccessiblePaths.add(inputFieldPath);
770
+ this.inaccessiblePaths.add(inputValueData.renamedPath);
774
771
  }
775
772
  }
776
773
  return;
@@ -789,6 +786,7 @@ class FederationFactory {
789
786
  (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, fieldData.namedTypeName, () => new Set()).add(fieldPath);
790
787
  this.namedOutputTypeNames.add(fieldData.namedTypeName);
791
788
  (0, utils_5.extractPersistedDirectives)(fieldData.persistedDirectivesData, fieldData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
789
+ this.recordTagNamesByPath(fieldData, fieldPath);
792
790
  const isFieldInaccessible = (0, utils_5.isNodeDataInaccessible)(fieldData);
793
791
  if (isParentInaccessible || isFieldInaccessible) {
794
792
  this.inaccessiblePaths.add(fieldPath);
@@ -801,14 +799,14 @@ class FederationFactory {
801
799
  type: inputValueData.type,
802
800
  };
803
801
  const namedArgumentTypeName = (0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type);
804
- const argumentPath = `${fieldPath}(${argumentName}: ... )`;
805
- (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(argumentPath);
802
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(inputValueData.renamedPath);
806
803
  this.namedInputValueTypeNames.add(namedArgumentTypeName);
807
804
  (0, utils_5.extractPersistedDirectives)(inputValueData.persistedDirectivesData, inputValueData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
805
+ this.recordTagNamesByPath(inputValueData, `${fieldPath}.${argumentName}`);
808
806
  /* If either the parent or the field to which the field belongs are declared inaccessible, the nullability
809
807
  ** of the argument is not considered. However, if only the argument is declared inaccessible, it is an
810
808
  ** error. */
811
- this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, argumentPath, fieldPath);
809
+ this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, inputValueData.renamedPath, fieldPath);
812
810
  }
813
811
  }
814
812
  return;
@@ -831,7 +829,7 @@ class FederationFactory {
831
829
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
832
830
  existingData.appearances += 1;
833
831
  for (const data of incomingData.enumValueDataByValueName.values()) {
834
- this.upsertEnumValueData(existingData.enumValueDataByValueName, data);
832
+ this.upsertEnumValueData(existingData.enumValueDataByValueName, data, isParentInaccessible);
835
833
  }
836
834
  return;
837
835
  case graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
@@ -846,6 +844,7 @@ class FederationFactory {
846
844
  (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedInputFieldTypeName, () => new Set()).add(inputFieldPath);
847
845
  this.namedInputValueTypeNames.add(namedInputFieldTypeName);
848
846
  this.upsertInputValueData(existingData.inputValueDataByValueName, inputValueData);
847
+ this.recordTagNamesByPath(inputValueData, inputFieldPath);
849
848
  if (isParentInaccessible || (0, utils_5.isNodeDataInaccessible)(inputValueData)) {
850
849
  this.inaccessiblePaths.add(inputFieldPath);
851
850
  }
@@ -857,16 +856,10 @@ class FederationFactory {
857
856
  if (isParentInaccessible && !existingData.isInaccessible) {
858
857
  this.propagateInaccessibilityToExistingChildren(existingData);
859
858
  }
860
- const objectData = incomingData;
861
- if (objectData.persistedDirectivesData.tags.size > 0) {
862
- const tagNames = (0, utils_3.getValueOrDefault)(this.tagNamesByPath, incomingData.name, () => new Set());
863
- for (const tagName of objectData.persistedDirectivesData.tags.keys()) {
864
- tagNames.add(tagName);
865
- }
866
- }
867
- (0, utils_3.addIterableValuesToSet)(objectData.implementedInterfaceTypeNames, existingData.implementedInterfaceTypeNames);
868
- (0, utils_3.addIterableValuesToSet)(objectData.subgraphNames, existingData.subgraphNames);
869
- for (const fieldData of objectData.fieldDataByFieldName.values()) {
859
+ const definitionWithFieldsData = incomingData;
860
+ (0, utils_3.addIterableValuesToSet)(definitionWithFieldsData.implementedInterfaceTypeNames, existingData.implementedInterfaceTypeNames);
861
+ (0, utils_3.addIterableValuesToSet)(definitionWithFieldsData.subgraphNames, existingData.subgraphNames);
862
+ for (const fieldData of definitionWithFieldsData.fieldDataByFieldName.values()) {
870
863
  this.upsertFieldData(existingData.fieldDataByFieldName, fieldData, isParentInaccessible || existingData.isInaccessible);
871
864
  }
872
865
  return;
@@ -882,6 +875,7 @@ class FederationFactory {
882
875
  const existingData = this.objectExtensionDataByTypeName.get(incomingData.name);
883
876
  const baseData = existingData || incomingData;
884
877
  (0, utils_5.extractPersistedDirectives)(baseData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
878
+ this.recordTagNamesByPath(baseData);
885
879
  const isParentInaccessible = (0, utils_5.isNodeDataInaccessible)(baseData);
886
880
  if (isParentInaccessible) {
887
881
  this.inaccessiblePaths.add(incomingData.name);
@@ -903,6 +897,7 @@ class FederationFactory {
903
897
  (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, fieldData.namedTypeName, () => new Set()).add(fieldPath);
904
898
  this.namedOutputTypeNames.add(fieldData.namedTypeName);
905
899
  (0, utils_5.extractPersistedDirectives)(fieldData.persistedDirectivesData, fieldData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
900
+ this.recordTagNamesByPath(fieldData, fieldPath);
906
901
  const isFieldInaccessible = (0, utils_5.isNodeDataInaccessible)(fieldData);
907
902
  if (isParentInaccessible || isFieldInaccessible) {
908
903
  this.inaccessiblePaths.add(fieldPath);
@@ -915,11 +910,11 @@ class FederationFactory {
915
910
  type: inputValueData.type,
916
911
  };
917
912
  const namedArgumentTypeName = (0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type);
918
- const argumentPath = `${fieldPath}(${argumentName}: ... )`;
919
- (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(argumentPath);
913
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(inputValueData.renamedPath);
920
914
  this.namedInputValueTypeNames.add(namedArgumentTypeName);
921
915
  (0, utils_5.extractPersistedDirectives)(inputValueData.persistedDirectivesData, inputValueData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
922
- this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, argumentPath, fieldPath);
916
+ this.recordTagNamesByPath(inputValueData, `${incomingData.name}.${argumentName}`);
917
+ this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, inputValueData.renamedPath, fieldPath);
923
918
  }
924
919
  }
925
920
  this.objectExtensionDataByTypeName.set(incomingData.name, incomingData);
@@ -947,8 +942,7 @@ class FederationFactory {
947
942
  const fieldPath = `${fieldData.renamedParentTypeName}.${fieldName}`;
948
943
  this.inaccessiblePaths.add(fieldPath);
949
944
  for (const [argumentName, inputValueData] of fieldData.argumentDataByArgumentName) {
950
- const argumentPath = `${fieldPath}(${argumentName}: ... )`;
951
- this.inaccessiblePaths.add(argumentPath);
945
+ this.inaccessiblePaths.add(inputValueData.renamedPath);
952
946
  }
953
947
  }
954
948
  }
@@ -1258,7 +1252,7 @@ class FederationFactory {
1258
1252
  invalidFieldNames.add(fieldName);
1259
1253
  }
1260
1254
  fieldNodes.push((0, utils_5.getNodeWithPersistedDirectivesByFieldData)(fieldData, this.persistedDirectiveDefinitionByDirectiveName, argumentNodes, this.errors));
1261
- if (fieldData.isInaccessible) {
1255
+ if ((0, utils_5.isNodeDataInaccessible)(fieldData)) {
1262
1256
  continue;
1263
1257
  }
1264
1258
  clientSchemaFieldNodes.push((0, utils_5.getClientSchemaFieldNodeByFieldData)(fieldData));
@@ -1436,6 +1430,10 @@ class FederationFactory {
1436
1430
  kind: graphql_1.Kind.DOCUMENT,
1437
1431
  definitions: this.routerDefinitions,
1438
1432
  };
1433
+ const newClientSchema = (0, graphql_1.buildASTSchema)({
1434
+ kind: graphql_1.Kind.DOCUMENT,
1435
+ definitions: this.clientDefinitions,
1436
+ });
1439
1437
  const subgraphConfigBySubgraphName = new Map();
1440
1438
  for (const subgraph of this.internalSubgraphBySubgraphName.values()) {
1441
1439
  subgraphConfigBySubgraphName.set(subgraph.name, {
@@ -1452,36 +1450,61 @@ class FederationFactory {
1452
1450
  subgraphConfigBySubgraphName,
1453
1451
  federatedGraphAST: newRouterAST,
1454
1452
  federatedGraphSchema: (0, graphql_1.buildASTSchema)(newRouterAST),
1455
- federatedGraphClientSchema: this.getFederatedClientSchema(),
1453
+ federatedGraphClientSchema: newClientSchema,
1454
+ ...this.getClientSchemaObjectBoolean(),
1456
1455
  },
1457
1456
  ...warnings,
1458
1457
  };
1459
1458
  }
1460
- getFederatedClientSchema() {
1459
+ getClientSchemaObjectBoolean() {
1460
+ // If the schema does not implement @tag nor @inaccessible, an empty object will be spread
1461
1461
  if (this.inaccessiblePaths.size < 1 && this.tagNamesByPath.size < 1) {
1462
- return (0, graphql_1.buildASTSchema)({
1463
- kind: graphql_1.Kind.DOCUMENT,
1464
- definitions: [],
1465
- });
1462
+ return {};
1463
+ }
1464
+ // otherwise, the object is spread in as true
1465
+ return { shouldIncludeClientSchema: true };
1466
+ }
1467
+ handleChildRemovalByTag(parentDefinitionData, children, childTagDataByChildName, tagsToExclude) {
1468
+ let accessibleChildren = children.size;
1469
+ for (const [childName, childTagData] of childTagDataByChildName) {
1470
+ const childData = (0, utils_3.getOrThrowError)(children, childName, `${parentDefinitionData.name}.childDataByChildName`);
1471
+ if ((0, utils_5.isNodeDataInaccessible)(childData)) {
1472
+ accessibleChildren -= 1;
1473
+ continue;
1474
+ }
1475
+ if ((0, utils_3.doSetsIntersect)(tagsToExclude, childTagData.tagNames)) {
1476
+ (0, utils_3.getValueOrDefault)(childData.persistedDirectivesData.directives, string_constants_1.INACCESSIBLE, () => [
1477
+ (0, utils_3.generateSimpleDirective)(string_constants_1.INACCESSIBLE),
1478
+ ]);
1479
+ this.inaccessiblePaths.add(`${parentDefinitionData.name}.${childName}`);
1480
+ accessibleChildren -= 1;
1481
+ }
1482
+ }
1483
+ if (accessibleChildren < 1) {
1484
+ parentDefinitionData.persistedDirectivesData.directives.set(string_constants_1.INACCESSIBLE, [
1485
+ (0, utils_3.generateSimpleDirective)(string_constants_1.INACCESSIBLE),
1486
+ ]);
1487
+ this.inaccessiblePaths.add(parentDefinitionData.name);
1466
1488
  }
1467
- return (0, graphql_1.buildASTSchema)({
1468
- kind: graphql_1.Kind.DOCUMENT,
1469
- definitions: this.clientDefinitions,
1470
- });
1471
1489
  }
1472
- buildFederationContractResult(tagExclusions) {
1490
+ buildFederationContractResult(tagsToExclude) {
1473
1491
  if (!this.isVersionTwo) {
1474
1492
  /* If all the subgraphs are version one, the @inaccessible directive won't be present.
1475
1493
  ** However, contracts require @inaccessible to exclude applicable tagged types. */
1476
1494
  this.routerDefinitions.push(constants_1.INACCESSIBLE_DEFINITION);
1477
1495
  }
1478
- for (const [typeName, parentTagData] of this.parentTagDataByTypeName) {
1479
- // TODO assess children
1480
- const parentDefinitionData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, typeName, string_constants_1.PARENT_DEFINITION_DATA);
1481
- if ((0, utils_3.doSetsHaveAnyOverlap)(tagExclusions, parentTagData.tagNames)) {
1482
- (0, utils_3.getValueOrDefault)(parentDefinitionData.persistedDirectivesData.directives, string_constants_1.INACCESSIBLE, () => [
1496
+ for (const [parentTypeName, parentTagData] of this.parentTagDataByTypeName) {
1497
+ const parentDefinitionData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, parentTypeName, string_constants_1.PARENT_DEFINITION_DATA);
1498
+ if ((0, utils_5.isNodeDataInaccessible)(parentDefinitionData)) {
1499
+ continue;
1500
+ }
1501
+ if ((0, utils_3.doSetsIntersect)(tagsToExclude, parentTagData.tagNames)) {
1502
+ parentDefinitionData.persistedDirectivesData.directives.set(string_constants_1.INACCESSIBLE, [
1483
1503
  (0, utils_3.generateSimpleDirective)(string_constants_1.INACCESSIBLE),
1484
1504
  ]);
1505
+ this.inaccessiblePaths.add(parentTypeName);
1506
+ // If the parent is inaccessible, there is no need to assess further
1507
+ continue;
1485
1508
  }
1486
1509
  if (parentTagData.childTagDataByChildName.size < 1) {
1487
1510
  continue;
@@ -1489,37 +1512,49 @@ class FederationFactory {
1489
1512
  switch (parentDefinitionData.kind) {
1490
1513
  case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
1491
1514
  // intentional fallthrough
1492
- case graphql_1.Kind.ENUM_TYPE_DEFINITION:
1493
- // intentional fallthrough
1494
1515
  case graphql_1.Kind.UNION_TYPE_DEFINITION:
1495
1516
  continue;
1517
+ case graphql_1.Kind.ENUM_TYPE_DEFINITION:
1518
+ this.handleChildRemovalByTag(parentDefinitionData, parentDefinitionData.enumValueDataByValueName, parentTagData.childTagDataByChildName, tagsToExclude);
1519
+ break;
1496
1520
  case graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
1497
- for (const [inputFieldName, childTagData] of parentTagData.childTagDataByChildName) {
1498
- const inputValueData = (0, utils_3.getOrThrowError)(parentDefinitionData.inputValueDataByValueName, inputFieldName, 'parentDefinitionData.inputValueDataByValueName');
1499
- if ((0, utils_3.doSetsHaveAnyOverlap)(tagExclusions, childTagData.tagNames)) {
1500
- (0, utils_3.getValueOrDefault)(inputValueData.persistedDirectivesData.directives, string_constants_1.INACCESSIBLE, () => [
1501
- (0, utils_3.generateSimpleDirective)(string_constants_1.INACCESSIBLE),
1502
- ]);
1503
- }
1504
- }
1521
+ this.handleChildRemovalByTag(parentDefinitionData, parentDefinitionData.inputValueDataByValueName, parentTagData.childTagDataByChildName, tagsToExclude);
1505
1522
  break;
1506
1523
  default:
1524
+ let accessibleFields = parentDefinitionData.fieldDataByFieldName.size;
1507
1525
  for (const [fieldName, childTagData] of parentTagData.childTagDataByChildName) {
1508
- const fieldData = (0, utils_3.getOrThrowError)(parentDefinitionData.fieldDataByFieldName, fieldName, 'parentDefinitionData.fieldDataByFieldName');
1509
- if ((0, utils_3.doSetsHaveAnyOverlap)(tagExclusions, childTagData.tagNames)) {
1526
+ const fieldData = (0, utils_3.getOrThrowError)(parentDefinitionData.fieldDataByFieldName, fieldName, `${parentTypeName}.fieldDataByFieldName`);
1527
+ if ((0, utils_5.isNodeDataInaccessible)(fieldData)) {
1528
+ accessibleFields -= 1;
1529
+ continue;
1530
+ }
1531
+ if ((0, utils_3.doSetsIntersect)(tagsToExclude, childTagData.tagNames)) {
1510
1532
  (0, utils_3.getValueOrDefault)(fieldData.persistedDirectivesData.directives, string_constants_1.INACCESSIBLE, () => [
1511
1533
  (0, utils_3.generateSimpleDirective)(string_constants_1.INACCESSIBLE),
1512
1534
  ]);
1535
+ this.inaccessiblePaths.add(`${parentTypeName}.${fieldName}`);
1536
+ accessibleFields -= 1;
1537
+ continue;
1513
1538
  }
1514
1539
  for (const [argumentName, tagNames] of childTagData.tagNamesByArgumentName) {
1515
- const inputValueData = (0, utils_3.getOrThrowError)(fieldData.argumentDataByArgumentName, argumentName, 'fieldData.argumentDataByArgumentName');
1516
- if ((0, utils_3.doSetsHaveAnyOverlap)(tagExclusions, tagNames)) {
1540
+ const inputValueData = (0, utils_3.getOrThrowError)(fieldData.argumentDataByArgumentName, argumentName, `${fieldName}.argumentDataByArgumentName`);
1541
+ if ((0, utils_5.isNodeDataInaccessible)(inputValueData)) {
1542
+ continue;
1543
+ }
1544
+ if ((0, utils_3.doSetsIntersect)(tagsToExclude, tagNames)) {
1517
1545
  (0, utils_3.getValueOrDefault)(inputValueData.persistedDirectivesData.directives, string_constants_1.INACCESSIBLE, () => [
1518
1546
  (0, utils_3.generateSimpleDirective)(string_constants_1.INACCESSIBLE),
1519
1547
  ]);
1548
+ this.inaccessiblePaths.add(inputValueData.renamedPath);
1520
1549
  }
1521
1550
  }
1522
1551
  }
1552
+ if (accessibleFields < 1) {
1553
+ parentDefinitionData.persistedDirectivesData.directives.set(string_constants_1.INACCESSIBLE, [
1554
+ (0, utils_3.generateSimpleDirective)(string_constants_1.INACCESSIBLE),
1555
+ ]);
1556
+ this.inaccessiblePaths.add(parentTypeName);
1557
+ }
1523
1558
  }
1524
1559
  }
1525
1560
  for (const data of this.potentialPersistedDirectiveDefinitionDataByDirectiveName.values()) {
@@ -1537,6 +1572,10 @@ class FederationFactory {
1537
1572
  kind: graphql_1.Kind.DOCUMENT,
1538
1573
  definitions: this.routerDefinitions,
1539
1574
  };
1575
+ const newClientSchema = (0, graphql_1.buildASTSchema)({
1576
+ kind: graphql_1.Kind.DOCUMENT,
1577
+ definitions: this.clientDefinitions,
1578
+ });
1540
1579
  const subgraphConfigBySubgraphName = new Map();
1541
1580
  for (const subgraph of this.internalSubgraphBySubgraphName.values()) {
1542
1581
  subgraphConfigBySubgraphName.set(subgraph.name, {
@@ -1553,7 +1592,8 @@ class FederationFactory {
1553
1592
  subgraphConfigBySubgraphName,
1554
1593
  federatedGraphAST: newRouterAST,
1555
1594
  federatedGraphSchema: (0, graphql_1.buildASTSchema)(newRouterAST),
1556
- federatedGraphClientSchema: this.getFederatedClientSchema(),
1595
+ federatedGraphClientSchema: newClientSchema,
1596
+ ...this.getClientSchemaObjectBoolean(),
1557
1597
  },
1558
1598
  warnings,
1559
1599
  };