@wundergraph/composition 0.15.0 → 0.16.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.
@@ -15,6 +15,7 @@ const merge_1 = require("@graphql-tools/merge");
15
15
  const constants_1 = require("../utils/constants");
16
16
  const normalization_factory_1 = require("../normalization/normalization-factory");
17
17
  const utils_4 = require("../normalization/utils");
18
+ const index_1 = require("graphql/index");
18
19
  class FederationFactory {
19
20
  abstractToConcreteTypeNames = new Map();
20
21
  areFieldsExternal = false;
@@ -28,7 +29,7 @@ class FederationFactory {
28
29
  currentSubgraphName = '';
29
30
  childName = '';
30
31
  directiveDefinitions = new Map();
31
- entities = new Map();
32
+ entityContainersByTypeName;
32
33
  errors = [];
33
34
  evaluatedObjectLikesBySubgraph = new Map();
34
35
  extensions = new Map();
@@ -46,36 +47,22 @@ class FederationFactory {
46
47
  outputFieldTypeNameSet = new Set();
47
48
  parents = new Map();
48
49
  rootTypeNames = new Set([string_constants_1.DEFAULT_MUTATION, string_constants_1.DEFAULT_QUERY, string_constants_1.DEFAULT_SUBSCRIPTION]);
49
- subgraphs = [];
50
+ internalSubgraphBySubgraphName;
50
51
  shareableErrorTypeNames = new Map();
51
- subgraphConfigBySubgraphName;
52
52
  warnings;
53
- constructor(subgraphs, subgraphConfigBySubgraphName, entityInterfaceFederationDataByTypeName, warnings) {
54
- this.subgraphs = subgraphs;
55
- this.subgraphConfigBySubgraphName = subgraphConfigBySubgraphName;
53
+ constructor(entityContainersByTypeName, entityInterfaceFederationDataByTypeName, internalSubgraphBySubgraphName, warnings) {
54
+ this.entityContainersByTypeName = entityContainersByTypeName;
56
55
  this.entityInterfaceFederationDataByTypeName = entityInterfaceFederationDataByTypeName;
56
+ this.internalSubgraphBySubgraphName = internalSubgraphBySubgraphName;
57
57
  this.warnings = warnings || [];
58
58
  }
59
59
  isObjectRootType(node) {
60
60
  return this.rootTypeNames.has(node.name.value);
61
61
  }
62
- upsertEntity(node) {
63
- const typeName = node.name.value;
64
- const entity = this.entities.get(typeName);
65
- if (entity) {
66
- entity.subgraphs.add(this.currentSubgraphName);
67
- return;
68
- }
69
- this.entities.set(typeName, {
70
- fields: new Set(),
71
- subgraphs: new Set([this.currentSubgraphName]),
72
- });
73
- }
74
62
  populateMultiGraphAndRenameOperations(subgraphs) {
75
- for (const subgraph of subgraphs) {
63
+ for (const subgraph of subgraphs.values()) {
76
64
  this.currentSubgraphName = subgraph.name;
77
65
  (0, subgraph_1.walkSubgraphToCollectObjectLikesAndDirectiveDefinitions)(this, subgraph);
78
- (0, subgraph_1.walkSubgraphToCollectFields)(this, subgraph);
79
66
  }
80
67
  }
81
68
  getEnumMergeMethod(enumName) {
@@ -238,7 +225,7 @@ class FederationFactory {
238
225
  isFieldExternal(node) {
239
226
  return this.areFieldsExternal || (0, utils_1.isNodeExternal)(node);
240
227
  }
241
- isFieldShareable(node, parent) {
228
+ isFieldShareable(node) {
242
229
  return (!this.isCurrentSubgraphVersionTwo || this.areFieldsShareable || this.isFieldEntityKey() || (0, utils_1.isNodeShareable)(node));
243
230
  }
244
231
  getOverrideTargetSubgraphName(node) {
@@ -275,7 +262,7 @@ class FederationFactory {
275
262
  this.upsertArguments(node, directiveDefinition.arguments);
276
263
  (0, utils_1.setLongestDescriptionForNode)(directiveDefinition.node, node.description);
277
264
  directiveDefinition.node.repeatable = directiveDefinition.node.repeatable && node.repeatable;
278
- directiveDefinition.subgraphs.add(this.currentSubgraphName);
265
+ directiveDefinition.subgraphNames.add(this.currentSubgraphName);
279
266
  return;
280
267
  }
281
268
  const executableLocations = (0, utils_1.extractExecutableDirectiveLocations)(node.locations, new Set());
@@ -283,7 +270,7 @@ class FederationFactory {
283
270
  arguments: this.upsertArguments(node, new Map()),
284
271
  executableLocations,
285
272
  node: (0, ast_1.directiveDefinitionNodeToMutable)(node),
286
- subgraphs: new Set([this.currentSubgraphName]),
273
+ subgraphNames: new Set([this.currentSubgraphName]),
287
274
  });
288
275
  if (executableLocations.size > 0) {
289
276
  this.executableDirectives.add(directiveName);
@@ -309,8 +296,8 @@ class FederationFactory {
309
296
  }
310
297
  // shareability doesn't matter if:
311
298
  // the field has only been seen exactly twice—the target override and the source override
312
- if (fieldContainer.subgraphs.size === 2 &&
313
- fieldContainer.subgraphs.has(fieldContainer.overrideTargetSubgraphName)) {
299
+ if (fieldContainer.subgraphNames.size === 2 &&
300
+ fieldContainer.subgraphNames.has(fieldContainer.overrideTargetSubgraphName)) {
314
301
  continue;
315
302
  }
316
303
  unshareableFields += 1;
@@ -331,7 +318,7 @@ class FederationFactory {
331
318
  }
332
319
  const fieldMap = parent.fields;
333
320
  const isFieldExternal = this.isFieldExternal(node);
334
- const isFieldShareable = this.isFieldShareable(node, parent);
321
+ const isFieldShareable = this.isFieldShareable(node);
335
322
  const fieldPath = `${this.parentTypeName}.${this.childName}`;
336
323
  const fieldRootTypeName = (0, type_merging_1.getNamedTypeForChild)(fieldPath, node.type);
337
324
  const existingFieldContainer = fieldMap.get(this.childName);
@@ -339,7 +326,7 @@ class FederationFactory {
339
326
  if (existingFieldContainer) {
340
327
  this.extractPersistedDirectives(node.directives || [], existingFieldContainer.directives);
341
328
  (0, utils_1.setLongestDescriptionForNode)(existingFieldContainer.node, node.description);
342
- existingFieldContainer.subgraphs.add(this.currentSubgraphName);
329
+ existingFieldContainer.subgraphNames.add(this.currentSubgraphName);
343
330
  existingFieldContainer.overrideTargetSubgraphName = targetSubgraph;
344
331
  existingFieldContainer.subgraphsByShareable.set(this.currentSubgraphName, isFieldShareable);
345
332
  existingFieldContainer.subgraphsByExternal.set(this.currentSubgraphName, isFieldExternal);
@@ -385,7 +372,7 @@ class FederationFactory {
385
372
  node: (0, ast_1.fieldDefinitionNodeToMutable)(node, this.parentTypeName),
386
373
  namedTypeName: fieldRootTypeName,
387
374
  overrideTargetSubgraphName: targetSubgraph,
388
- subgraphs: new Set([this.currentSubgraphName]),
375
+ subgraphNames: new Set([this.currentSubgraphName]),
389
376
  subgraphsByShareable: new Map([[this.currentSubgraphName, isFieldShareable]]),
390
377
  subgraphsByExternal: new Map([[this.currentSubgraphName, isFieldExternal]]),
391
378
  });
@@ -465,7 +452,7 @@ class FederationFactory {
465
452
  (0, utils_1.setLongestDescriptionForNode)(parent.node, node.description);
466
453
  this.extractPersistedDirectives(node.directives || [], parent.directives);
467
454
  (0, utils_1.extractInterfaces)(node, parent.interfaces);
468
- parent.subgraphs.add(this.currentSubgraphName);
455
+ parent.subgraphNames.add(this.currentSubgraphName);
469
456
  return;
470
457
  }
471
458
  this.parents.set(parentTypeName, {
@@ -477,7 +464,7 @@ class FederationFactory {
477
464
  ...node,
478
465
  kind: graphql_1.Kind.INTERFACE_TYPE_DEFINITION,
479
466
  }),
480
- subgraphs: new Set([this.currentSubgraphName]),
467
+ subgraphNames: new Set([this.currentSubgraphName]),
481
468
  });
482
469
  }
483
470
  upsertParentNode(node) {
@@ -526,7 +513,7 @@ class FederationFactory {
526
513
  throw (0, errors_1.incompatibleParentKindFatalError)(parentTypeName, node.kind, parent.kind);
527
514
  }
528
515
  (0, utils_1.extractInterfaces)(node, parent.interfaces);
529
- parent.subgraphs.add(this.currentSubgraphName);
516
+ parent.subgraphNames.add(this.currentSubgraphName);
530
517
  return;
531
518
  }
532
519
  this.parents.set(parentTypeName, {
@@ -535,7 +522,7 @@ class FederationFactory {
535
522
  interfaces: (0, utils_1.extractInterfaces)(node, new Set()),
536
523
  kind: node.kind,
537
524
  node: (0, ast_1.interfaceTypeDefinitionNodeToMutable)(node),
538
- subgraphs: new Set([this.currentSubgraphName]),
525
+ subgraphNames: new Set([this.currentSubgraphName]),
539
526
  });
540
527
  return;
541
528
  case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
@@ -557,7 +544,7 @@ class FederationFactory {
557
544
  throw (0, errors_1.incompatibleParentKindFatalError)(parentTypeName, node.kind, parent.kind);
558
545
  }
559
546
  (0, utils_1.extractInterfaces)(node, parent.interfaces);
560
- parent.subgraphs.add(this.currentSubgraphName);
547
+ parent.subgraphNames.add(this.currentSubgraphName);
561
548
  return;
562
549
  }
563
550
  this.parents.set(parentTypeName, {
@@ -567,7 +554,7 @@ class FederationFactory {
567
554
  isRootType: this.isParentRootType,
568
555
  kind: node.kind,
569
556
  node: (0, ast_1.objectTypeDefinitionNodeToMutable)(node),
570
- subgraphs: new Set([this.currentSubgraphName]),
557
+ subgraphNames: new Set([this.currentSubgraphName]),
571
558
  });
572
559
  return;
573
560
  case graphql_1.Kind.UNION_TYPE_DEFINITION:
@@ -597,7 +584,7 @@ class FederationFactory {
597
584
  if (extension.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
598
585
  throw (0, errors_1.incompatibleParentKindFatalError)(this.parentTypeName, graphql_1.Kind.OBJECT_TYPE_EXTENSION, extension.kind);
599
586
  }
600
- extension.subgraphs.add(this.currentSubgraphName);
587
+ extension.subgraphNames.add(this.currentSubgraphName);
601
588
  (0, utils_1.extractInterfaces)(node, extension.interfaces);
602
589
  this.extractPersistedDirectives(node.directives || [], extension.directives);
603
590
  return;
@@ -611,7 +598,7 @@ class FederationFactory {
611
598
  isRootType: this.isParentRootType,
612
599
  kind: graphql_1.Kind.OBJECT_TYPE_EXTENSION,
613
600
  node: (0, ast_1.objectTypeExtensionNodeToMutable)(node),
614
- subgraphs: new Set([this.currentSubgraphName]),
601
+ subgraphNames: new Set([this.currentSubgraphName]),
615
602
  });
616
603
  }
617
604
  isTypeValidImplementation(originalType, implementationType) {
@@ -736,7 +723,7 @@ class FederationFactory {
736
723
  }
737
724
  mergeArguments(container, args, errors, argumentNames) {
738
725
  for (const argumentContainer of container.arguments.values()) {
739
- const missingSubgraphs = (0, utils_3.getEntriesNotInHashSet)(container.subgraphs, argumentContainer.subgraphs);
726
+ const missingSubgraphs = (0, utils_3.getEntriesNotInHashSet)(container.subgraphNames, argumentContainer.subgraphs);
740
727
  const argumentName = argumentContainer.node.name.value;
741
728
  if (missingSubgraphs.length > 0) {
742
729
  // Required arguments must be defined in all subgraphs that define the field
@@ -764,7 +751,7 @@ class FederationFactory {
764
751
  if (!this.executableDirectives.has(directiveName)) {
765
752
  return;
766
753
  }
767
- if (this.subgraphs.length !== directiveContainer.subgraphs.size) {
754
+ if (this.internalSubgraphBySubgraphName.size !== directiveContainer.subgraphNames.size) {
768
755
  return;
769
756
  }
770
757
  directiveContainer.node.locations = (0, utils_1.setToNameNodeArray)(directiveContainer.executableLocations);
@@ -883,7 +870,7 @@ class FederationFactory {
883
870
  return true;
884
871
  }
885
872
  if (entityAncestorName === parentTypeName) {
886
- const hasOverlap = (0, utils_3.doSetsHaveAnyOverlap)(fieldSubgraphs, (0, utils_3.getOrThrowError)(this.entities, entityAncestorName, string_constants_1.ENTITIES).subgraphs);
873
+ const hasOverlap = (0, utils_3.doSetsHaveAnyOverlap)(fieldSubgraphs, (0, utils_3.getOrThrowError)(this.entityContainersByTypeName, entityAncestorName, string_constants_1.ENTITIES).subgraphNames);
887
874
  this.graphPaths.set(path, hasOverlap);
888
875
  return hasOverlap;
889
876
  }
@@ -906,7 +893,7 @@ class FederationFactory {
906
893
  return false;
907
894
  }
908
895
  isFieldExternalInAllMutualSubgraphs(subgraphs, fieldContainer) {
909
- const mutualSubgraphs = (0, utils_3.getAllMutualEntries)(subgraphs, fieldContainer.subgraphs);
896
+ const mutualSubgraphs = (0, utils_3.getAllMutualEntries)(subgraphs, fieldContainer.subgraphNames);
910
897
  if (mutualSubgraphs.size < 1) {
911
898
  return false;
912
899
  }
@@ -934,7 +921,7 @@ class FederationFactory {
934
921
  }
935
922
  for (const entityAncestor of entityAncestors) {
936
923
  const entityContainer = (0, utils_3.getOrThrowError)(this.parents, entityAncestor, string_constants_1.PARENTS);
937
- const mutualEntityAncestorRootTypeFieldSubgraphs = (0, utils_3.getAllMutualEntries)(rootTypeFieldSubgraphs, entityContainer.subgraphs);
924
+ const mutualEntityAncestorRootTypeFieldSubgraphs = (0, utils_3.getAllMutualEntries)(rootTypeFieldSubgraphs, entityContainer.subgraphNames);
938
925
  const mutualEntityAncestorSubgraphs = (0, utils_3.getAllMutualEntries)(mutualEntityAncestorRootTypeFieldSubgraphs, objectSubgraphs);
939
926
  for (const mutualSubgraph of mutualEntityAncestorSubgraphs) {
940
927
  const objects = this.evaluatedObjectLikesBySubgraph.get(mutualSubgraph);
@@ -968,12 +955,12 @@ class FederationFactory {
968
955
  if (this.isFieldExternalInAllMutualSubgraphs(rootTypeFieldData.subgraphs, fieldContainer)) {
969
956
  continue;
970
957
  }
971
- this.updateEvaluatedSubgraphOccurrences(rootTypeFieldData.subgraphs, parentContainer.subgraphs, entityAncestors, parentTypeName);
958
+ this.updateEvaluatedSubgraphOccurrences(rootTypeFieldData.subgraphs, parentContainer.subgraphNames, entityAncestors, parentTypeName);
972
959
  evaluatedObjectLikes.add(parentTypeName);
973
- const isFieldResolvable = (0, utils_3.doSetsHaveAnyOverlap)(rootTypeFieldData.subgraphs, fieldContainer.subgraphs) ||
974
- this.isFieldResolvableByEntityAncestor(entityAncestors, fieldContainer.subgraphs, parentTypeName);
960
+ const isFieldResolvable = (0, utils_3.doSetsHaveAnyOverlap)(rootTypeFieldData.subgraphs, fieldContainer.subgraphNames) ||
961
+ this.isFieldResolvableByEntityAncestor(entityAncestors, fieldContainer.subgraphNames, parentTypeName);
975
962
  const newCurrentFieldPath = currentFieldPath + (isParentAbstract ? ' ' : '.') + fieldName;
976
- const entity = this.entities.get(fieldNamedTypeName);
963
+ const entity = this.entityContainersByTypeName.get(fieldNamedTypeName);
977
964
  if (isFieldResolvable) {
978
965
  // The base scalars are not in this.parentMap
979
966
  if (constants_1.BASE_SCALARS.has(fieldNamedTypeName)) {
@@ -991,7 +978,7 @@ class FederationFactory {
991
978
  case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
992
979
  // intentional fallthrough
993
980
  case graphql_1.Kind.UNION_TYPE_DEFINITION:
994
- this.evaluateResolvabilityOfAbstractType(fieldNamedTypeName, childContainer.kind, rootTypeFieldData, newCurrentFieldPath, evaluatedObjectLikes, entity ? [...entityAncestors, fieldNamedTypeName] : [...entityAncestors], fieldContainer.subgraphs);
981
+ this.evaluateResolvabilityOfAbstractType(fieldNamedTypeName, childContainer.kind, rootTypeFieldData, newCurrentFieldPath, evaluatedObjectLikes, entity ? [...entityAncestors, fieldNamedTypeName] : [...entityAncestors]);
995
982
  continue;
996
983
  default:
997
984
  this.errors.push((0, errors_1.unexpectedObjectResponseType)(newCurrentFieldPath, (0, utils_3.kindToTypeString)(childContainer.kind)));
@@ -999,7 +986,7 @@ class FederationFactory {
999
986
  }
1000
987
  }
1001
988
  if (constants_1.BASE_SCALARS.has(fieldNamedTypeName)) {
1002
- this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldContainer.subgraphs], newCurrentFieldPath, parentTypeName));
989
+ this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldContainer.subgraphNames], newCurrentFieldPath, parentTypeName));
1003
990
  continue;
1004
991
  }
1005
992
  const childContainer = (0, utils_3.getOrThrowError)(this.parents, fieldNamedTypeName, string_constants_1.PARENTS);
@@ -1007,21 +994,21 @@ class FederationFactory {
1007
994
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
1008
995
  // intentional fallthrough
1009
996
  case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
1010
- this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldContainer.subgraphs], newCurrentFieldPath, parentTypeName));
997
+ this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldContainer.subgraphNames], newCurrentFieldPath, parentTypeName));
1011
998
  continue;
1012
999
  case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
1013
1000
  // intentional fallthrough
1014
1001
  case graphql_1.Kind.UNION_TYPE_DEFINITION:
1015
1002
  // intentional fallthrough
1016
1003
  case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
1017
- this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldContainer.subgraphs], newCurrentFieldPath + string_constants_1.SELECTION_REPRESENTATION, parentTypeName));
1004
+ this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldContainer.subgraphNames], newCurrentFieldPath + string_constants_1.SELECTION_REPRESENTATION, parentTypeName));
1018
1005
  continue;
1019
1006
  default:
1020
1007
  this.errors.push((0, errors_1.unexpectedObjectResponseType)(newCurrentFieldPath, (0, utils_3.kindToTypeString)(childContainer.kind)));
1021
1008
  }
1022
1009
  }
1023
1010
  }
1024
- evaluateResolvabilityOfAbstractType(abstractTypeName, abstractKind, rootTypeFieldData, currentFieldPath, evaluatedObjectLikes, entityAncestors, parentSubgraphs) {
1011
+ evaluateResolvabilityOfAbstractType(abstractTypeName, abstractKind, rootTypeFieldData, currentFieldPath, evaluatedObjectLikes, entityAncestors) {
1025
1012
  if (evaluatedObjectLikes.has(abstractTypeName)) {
1026
1013
  return;
1027
1014
  }
@@ -1040,17 +1027,148 @@ class FederationFactory {
1040
1027
  throw (0, errors_1.unexpectedParentKindErrorMessage)(concreteTypeName, 'Object', (0, utils_3.kindToTypeString)(concreteParentContainer.kind));
1041
1028
  }
1042
1029
  // If the concrete type is unreachable through an inline fragment, it is not an error
1043
- if (!(0, utils_3.doSetsHaveAnyOverlap)(concreteParentContainer.subgraphs, rootTypeFieldData.subgraphs)) {
1030
+ if (!(0, utils_3.doSetsHaveAnyOverlap)(concreteParentContainer.subgraphNames, rootTypeFieldData.subgraphs)) {
1044
1031
  continue;
1045
1032
  }
1046
- const entity = this.entities.get(concreteTypeName);
1033
+ const entity = this.entityContainersByTypeName.get(concreteTypeName);
1047
1034
  this.evaluateResolvabilityOfObject(concreteParentContainer, rootTypeFieldData, currentFieldPath + ` ... on ` + concreteTypeName, evaluatedObjectLikes, entity ? [...entityAncestors, concreteTypeName] : [...entityAncestors], true);
1048
1035
  }
1049
1036
  }
1037
+ validateKeyFieldSetsForImplicitEntity(entityContainer) {
1038
+ const internalSubgraph = (0, utils_3.getOrThrowError)(this.internalSubgraphBySubgraphName, this.currentSubgraphName, 'internalSubgraphBySubgraphName');
1039
+ const parentContainerByTypeName = internalSubgraph.parentContainerByTypeName;
1040
+ const extensionContainerByTypeName = internalSubgraph.extensionContainerByTypeName;
1041
+ const implicitEntityContainer = parentContainerByTypeName.get(entityContainer.typeName) ||
1042
+ extensionContainerByTypeName.get(entityContainer.typeName);
1043
+ if (!implicitEntityContainer ||
1044
+ (implicitEntityContainer.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION &&
1045
+ implicitEntityContainer.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION)) {
1046
+ throw (0, errors_1.incompatibleParentKindFatalError)(entityContainer.typeName, graphql_1.Kind.OBJECT_TYPE_DEFINITION, implicitEntityContainer?.kind || graphql_1.Kind.NULL);
1047
+ }
1048
+ const configurationData = (0, utils_3.getOrThrowError)(internalSubgraph.configurationDataMap, entityContainer.typeName, 'internalSubgraph.configurationDataMap');
1049
+ const keyFieldNames = new Set();
1050
+ const keys = [];
1051
+ // Any errors in the field sets would be caught when evaluating the explicit entities, so they are ignored here
1052
+ for (const fieldSet of entityContainer.keyFieldSets) {
1053
+ // Create a new selection set so that the value can be parsed as a new DocumentNode
1054
+ const { error, documentNode } = (0, utils_1.safeParse)('{' + fieldSet + '}');
1055
+ if (error || !documentNode) {
1056
+ // This would be caught as an error elsewhere
1057
+ continue;
1058
+ }
1059
+ const parentContainers = [implicitEntityContainer];
1060
+ const definedFields = [];
1061
+ let currentDepth = -1;
1062
+ let shouldDefineSelectionSet = true;
1063
+ let shouldAddKeyFieldSet = true;
1064
+ (0, index_1.visit)(documentNode, {
1065
+ Argument: {
1066
+ enter() {
1067
+ // Fields that define arguments are never allowed in a key FieldSet
1068
+ // However, at this stage, it actually means the argument is undefined on the field
1069
+ shouldAddKeyFieldSet = false;
1070
+ return index_1.BREAK;
1071
+ },
1072
+ },
1073
+ Field: {
1074
+ enter(node) {
1075
+ const parentContainer = parentContainers[currentDepth];
1076
+ const parentTypeName = parentContainer.name.value;
1077
+ // If an object-like was just visited, a selection set should have been entered
1078
+ if (shouldDefineSelectionSet) {
1079
+ shouldAddKeyFieldSet = false;
1080
+ return index_1.BREAK;
1081
+ }
1082
+ const fieldName = node.name.value;
1083
+ const fieldPath = `${parentTypeName}.${fieldName}`;
1084
+ const fieldContainer = parentContainer.fields.get(fieldName);
1085
+ // undefined if the field does not exist on the parent
1086
+ if (!fieldContainer || fieldContainer.arguments.size || definedFields[currentDepth].has(fieldName)) {
1087
+ shouldAddKeyFieldSet = false;
1088
+ return index_1.BREAK;
1089
+ }
1090
+ definedFields[currentDepth].add(fieldName);
1091
+ // Depth 0 is the original parent type
1092
+ // If a field is external, but it's part of a key FieldSet, it will be included in the root configuration
1093
+ if (currentDepth === 0) {
1094
+ keyFieldNames.add(fieldName);
1095
+ }
1096
+ const namedTypeName = (0, type_merging_1.getNamedTypeForChild)(fieldPath, fieldContainer.node.type);
1097
+ // The base scalars are not in the parents map
1098
+ if (constants_1.BASE_SCALARS.has(namedTypeName)) {
1099
+ return;
1100
+ }
1101
+ // The child could itself be a parent and could exist as an object extension
1102
+ const childContainer = parentContainerByTypeName.get(namedTypeName) || extensionContainerByTypeName.get(namedTypeName);
1103
+ if (!childContainer) {
1104
+ shouldAddKeyFieldSet = false;
1105
+ return index_1.BREAK;
1106
+ }
1107
+ if (childContainer.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION ||
1108
+ childContainer.kind === graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
1109
+ shouldDefineSelectionSet = true;
1110
+ parentContainers.push(childContainer);
1111
+ return;
1112
+ }
1113
+ // interfaces and unions are invalid in a key directive
1114
+ if ((0, utils_1.isKindAbstract)(childContainer.kind)) {
1115
+ shouldAddKeyFieldSet = false;
1116
+ return index_1.BREAK;
1117
+ }
1118
+ },
1119
+ },
1120
+ InlineFragment: {
1121
+ enter() {
1122
+ shouldAddKeyFieldSet = false;
1123
+ return index_1.BREAK;
1124
+ },
1125
+ },
1126
+ SelectionSet: {
1127
+ enter() {
1128
+ if (!shouldDefineSelectionSet) {
1129
+ shouldAddKeyFieldSet = false;
1130
+ return index_1.BREAK;
1131
+ }
1132
+ currentDepth += 1;
1133
+ shouldDefineSelectionSet = false;
1134
+ if (currentDepth < 0 || currentDepth >= parentContainers.length) {
1135
+ shouldAddKeyFieldSet = false;
1136
+ return index_1.BREAK;
1137
+ }
1138
+ definedFields.push(new Set());
1139
+ },
1140
+ leave() {
1141
+ if (shouldDefineSelectionSet) {
1142
+ shouldAddKeyFieldSet = false;
1143
+ return index_1.BREAK;
1144
+ }
1145
+ // Empty selection sets would be a parse error, so it is unnecessary to handle them
1146
+ currentDepth -= 1;
1147
+ parentContainers.pop();
1148
+ definedFields.pop();
1149
+ },
1150
+ },
1151
+ });
1152
+ if (!shouldAddKeyFieldSet) {
1153
+ continue;
1154
+ }
1155
+ // Add any top-level fields that compose the key in case they are external
1156
+ (0, utils_3.addIterableValuesToSet)(keyFieldNames, configurationData.fieldNames);
1157
+ keys.push({
1158
+ fieldName: '',
1159
+ selectionSet: (0, utils_4.getNormalizedFieldSet)(documentNode),
1160
+ disableEntityResolver: true,
1161
+ });
1162
+ }
1163
+ if (keys.length > 0) {
1164
+ configurationData.isRootNode = true;
1165
+ configurationData.keys = keys;
1166
+ }
1167
+ }
1050
1168
  federate() {
1051
- this.populateMultiGraphAndRenameOperations(this.subgraphs);
1169
+ this.populateMultiGraphAndRenameOperations(this.internalSubgraphBySubgraphName);
1052
1170
  const factory = this;
1053
- for (const subgraph of this.subgraphs) {
1171
+ for (const subgraph of this.internalSubgraphBySubgraphName.values()) {
1054
1172
  this.isCurrentSubgraphVersionTwo = subgraph.isVersionTwo;
1055
1173
  this.currentSubgraphName = subgraph.name;
1056
1174
  this.keyFieldNamesByParentTypeName = subgraph.keyFieldNamesByParentTypeName;
@@ -1064,7 +1182,7 @@ class FederationFactory {
1064
1182
  continue;
1065
1183
  }
1066
1184
  for (const subgraphName of entityInterfaceData.interfaceObjectSubgraphs) {
1067
- const configurationDataMap = (0, utils_3.getOrThrowError)(this.subgraphConfigBySubgraphName, subgraphName, 'subgraphConfigBySubgraphName').configurationDataMap;
1185
+ const configurationDataMap = (0, utils_3.getOrThrowError)(this.internalSubgraphBySubgraphName, subgraphName, 'internalSubgraphBySubgraphName').configurationDataMap;
1068
1186
  const concreteTypeNames = this.abstractToConcreteTypeNames.get(typeName);
1069
1187
  if (!concreteTypeNames) {
1070
1188
  continue;
@@ -1087,10 +1205,10 @@ class FederationFactory {
1087
1205
  continue;
1088
1206
  }
1089
1207
  // The subgraph locations of the interface object must be added to the concrete types that implement it
1090
- const entity = this.entities.get(concreteTypeName);
1208
+ const entity = this.entityContainersByTypeName.get(concreteTypeName);
1091
1209
  if (entity) {
1092
1210
  // TODO error if not an entity
1093
- entity.subgraphs.add(subgraphName);
1211
+ entity.subgraphNames.add(subgraphName);
1094
1212
  }
1095
1213
  const configurationData = {
1096
1214
  fieldNames,
@@ -1144,7 +1262,7 @@ class FederationFactory {
1144
1262
  this.childName = extensionFieldName;
1145
1263
  this.upsertExtensionFieldArguments(extensionFieldContainer.arguments, baseFieldContainer.arguments);
1146
1264
  (0, utils_1.setLongestDescriptionForNode)(baseFieldContainer.node, extensionFieldContainer.node.description);
1147
- (0, utils_3.addIterableValuesToSet)(extensionFieldContainer.subgraphs, baseFieldContainer.subgraphs);
1265
+ (0, utils_3.addIterableValuesToSet)(extensionFieldContainer.subgraphNames, baseFieldContainer.subgraphNames);
1148
1266
  continue;
1149
1267
  }
1150
1268
  const parent = this.shareableErrorTypeNames.get(typeName);
@@ -1166,8 +1284,7 @@ class FederationFactory {
1166
1284
  this.errors.push((0, errors_1.shareableFieldDefinitionsError)(parent, children));
1167
1285
  }
1168
1286
  const objectLikeContainersWithInterfaces = [];
1169
- for (const parentContainer of this.parents.values()) {
1170
- const parentTypeName = parentContainer.node.name.value;
1287
+ for (const [parentTypeName, parentContainer] of this.parents) {
1171
1288
  switch (parentContainer.kind) {
1172
1289
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
1173
1290
  const values = [];
@@ -1299,7 +1416,7 @@ class FederationFactory {
1299
1416
  if (evaluatedRootScalarsAndEnums.has(rootTypeFieldNamedTypeName)) {
1300
1417
  continue;
1301
1418
  }
1302
- if (!this.shouldEvaluateObjectLike(rootTypeFieldContainer.subgraphs, rootTypeFieldNamedTypeName)) {
1419
+ if (!this.shouldEvaluateObjectLike(rootTypeFieldContainer.subgraphNames, rootTypeFieldNamedTypeName)) {
1303
1420
  continue;
1304
1421
  }
1305
1422
  const childContainer = (0, utils_3.getOrThrowError)(this.parents, rootTypeFieldNamedTypeName, string_constants_1.PARENTS);
@@ -1309,7 +1426,7 @@ class FederationFactory {
1309
1426
  fieldTypeNodeString: (0, merge_1.printTypeNode)(rootTypeFieldContainer.node.type),
1310
1427
  path: fieldPath,
1311
1428
  typeName: rootTypeName,
1312
- subgraphs: rootTypeFieldContainer.subgraphs,
1429
+ subgraphs: rootTypeFieldContainer.subgraphNames,
1313
1430
  };
1314
1431
  switch (childContainer.kind) {
1315
1432
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
@@ -1320,12 +1437,12 @@ class FederationFactory {
1320
1437
  evaluatedRootScalarsAndEnums.add(rootTypeFieldNamedTypeName);
1321
1438
  continue;
1322
1439
  case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
1323
- this.evaluateResolvabilityOfObject(childContainer, rootTypeFieldData, fieldPath, new Set(), this.entities.has(rootTypeFieldNamedTypeName) ? [rootTypeFieldNamedTypeName] : []);
1440
+ this.evaluateResolvabilityOfObject(childContainer, rootTypeFieldData, fieldPath, new Set(), this.entityContainersByTypeName.has(rootTypeFieldNamedTypeName) ? [rootTypeFieldNamedTypeName] : []);
1324
1441
  continue;
1325
1442
  case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
1326
1443
  // intentional fallthrough
1327
1444
  case graphql_1.Kind.UNION_TYPE_DEFINITION:
1328
- this.evaluateResolvabilityOfAbstractType(rootTypeFieldNamedTypeName, childContainer.kind, rootTypeFieldData, fieldPath, new Set(), this.entities.has(rootTypeFieldNamedTypeName) ? [rootTypeFieldNamedTypeName] : [], rootTypeFieldContainer.subgraphs);
1445
+ this.evaluateResolvabilityOfAbstractType(rootTypeFieldNamedTypeName, childContainer.kind, rootTypeFieldData, fieldPath, new Set(), this.entityContainersByTypeName.has(rootTypeFieldNamedTypeName) ? [rootTypeFieldNamedTypeName] : []);
1329
1446
  continue;
1330
1447
  default:
1331
1448
  this.errors.push((0, errors_1.unexpectedObjectResponseType)(fieldPath, (0, utils_3.kindToTypeString)(childContainer.kind)));
@@ -1340,10 +1457,17 @@ class FederationFactory {
1340
1457
  kind: graphql_1.Kind.DOCUMENT,
1341
1458
  definitions,
1342
1459
  };
1460
+ const subgraphConfigBySubgraphName = new Map();
1461
+ for (const subgraph of this.internalSubgraphBySubgraphName.values()) {
1462
+ subgraphConfigBySubgraphName.set(subgraph.name, {
1463
+ configurationDataMap: subgraph.configurationDataMap,
1464
+ schema: subgraph.schema,
1465
+ });
1466
+ }
1343
1467
  return {
1344
1468
  federationResult: {
1345
1469
  argumentConfigurations: this.argumentConfigurations,
1346
- subgraphConfigBySubgraphName: this.subgraphConfigBySubgraphName,
1470
+ subgraphConfigBySubgraphName,
1347
1471
  federatedGraphAST: newAst,
1348
1472
  federatedGraphSchema: (0, graphql_1.buildASTSchema)(newAst),
1349
1473
  },
@@ -1356,21 +1480,14 @@ function federateSubgraphs(subgraphs) {
1356
1480
  if (subgraphs.length < 1) {
1357
1481
  return { errors: [errors_1.minimumSubgraphRequirementError] };
1358
1482
  }
1359
- const { errors, internalSubgraphsBySubgraphName, warnings } = (0, normalization_factory_1.batchNormalize)(subgraphs);
1483
+ const { entityContainerByTypeName, errors, internalSubgraphBySubgraphName, warnings } = (0, normalization_factory_1.batchNormalize)(subgraphs);
1360
1484
  if (errors) {
1361
1485
  return { errors };
1362
1486
  }
1363
- const internalSubgraphs = [];
1364
- const subgraphConfigBySubgraphName = new Map();
1365
1487
  const entityInterfaceFederationDataByTypeName = new Map();
1366
1488
  const invalidEntityInterfacesByTypeName = new Map();
1367
1489
  const validEntityInterfaceTypeNames = new Set();
1368
- for (const [subgraphName, internalSubgraph] of internalSubgraphsBySubgraphName) {
1369
- internalSubgraphs.push(internalSubgraph);
1370
- subgraphConfigBySubgraphName.set(subgraphName, {
1371
- configurationDataMap: internalSubgraph.configurationDataMap,
1372
- schema: internalSubgraph.schema,
1373
- });
1490
+ for (const [subgraphName, internalSubgraph] of internalSubgraphBySubgraphName) {
1374
1491
  for (const [typeName, entityInterfaceData] of internalSubgraph.entityInterfaces) {
1375
1492
  // Always add each entity interface to the invalid entity interfaces map
1376
1493
  // If not, earlier checks would not account for implementations not yet seen
@@ -1402,8 +1519,7 @@ function federateSubgraphs(subgraphs) {
1402
1519
  ],
1403
1520
  };
1404
1521
  }
1405
- const federationFactory = new FederationFactory(internalSubgraphs, subgraphConfigBySubgraphName, entityInterfaceFederationDataByTypeName, warnings);
1406
- return federationFactory.federate();
1522
+ return new FederationFactory(entityContainerByTypeName, entityInterfaceFederationDataByTypeName, internalSubgraphBySubgraphName, warnings).federate();
1407
1523
  }
1408
1524
  exports.federateSubgraphs = federateSubgraphs;
1409
1525
  //# sourceMappingURL=federation-factory.js.map