@wundergraph/composition 0.14.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.
@@ -36,28 +36,28 @@ class NormalizationFactory {
36
36
  configurationDataMap = new Map();
37
37
  customDirectiveDefinitions = new Map();
38
38
  errors = [];
39
- entities = new Set();
39
+ entityContainerByTypeName = new Map();
40
40
  entityInterfaces = new Map();
41
- extensions = new Map();
41
+ extensionContainerByTypeName = new Map();
42
42
  isCurrentParentExtension = false;
43
43
  isCurrentParentRootType = false;
44
44
  isSubgraphVersionTwo = false;
45
- fieldSetsByParent = new Map();
45
+ fieldSetContainerByTypeName = new Map();
46
46
  handledRepeatedDirectivesByHostPath = new Map();
47
47
  lastParentNodeKind = graphql_1.Kind.NULL;
48
48
  lastChildNodeKind = graphql_1.Kind.NULL;
49
- keyFieldsByParentTypeName = new Map();
49
+ keyFieldNamesByParentTypeName = new Map();
50
50
  operationTypeNames = new Map();
51
- parents = new Map();
51
+ parentContainerByTypeName = new Map();
52
52
  parentTypeName = '';
53
53
  parentsWithChildArguments = new Set();
54
54
  eventsConfigurations = new Map();
55
55
  overridesByTargetSubgraphName = new Map();
56
56
  schemaDefinition;
57
- subgraphName;
58
57
  referencedDirectives = new Set();
59
58
  referencedTypeNames = new Set();
60
59
  warnings = [];
60
+ subgraphName;
61
61
  constructor(subgraphName) {
62
62
  for (const baseDirectiveDefinition of constants_1.BASE_DIRECTIVE_DEFINITIONS) {
63
63
  this.allDirectiveDefinitions.set(baseDirectiveDefinition.name.value, baseDirectiveDefinition);
@@ -74,7 +74,7 @@ class NormalizationFactory {
74
74
  if (constants_1.BASE_SCALARS.has(namedType)) {
75
75
  return { hasUnhandledError: false, typeString: '' };
76
76
  }
77
- const parentContainer = this.parents.get(namedType);
77
+ const parentContainer = this.parentContainerByTypeName.get(namedType);
78
78
  if (!parentContainer) {
79
79
  this.errors.push((0, errors_1.undefinedTypeError)(namedType));
80
80
  return { hasUnhandledError: false, typeString: '' };
@@ -282,7 +282,7 @@ class NormalizationFactory {
282
282
  }
283
283
  handleObjectLikeExtension(node) {
284
284
  this.isCurrentParentExtension = true;
285
- const extension = this.extensions.get(this.parentTypeName);
285
+ const extension = this.extensionContainerByTypeName.get(this.parentTypeName);
286
286
  const convertedKind = this.convertKindForExtension(node);
287
287
  if (extension) {
288
288
  if (extension.kind !== convertedKind) {
@@ -294,7 +294,7 @@ class NormalizationFactory {
294
294
  return;
295
295
  }
296
296
  const isEntity = (0, utils_1.isObjectLikeNodeEntity)(node);
297
- this.extensions.set(this.parentTypeName, {
297
+ this.extensionContainerByTypeName.set(this.parentTypeName, {
298
298
  directives: this.extractDirectives(node, new Map()),
299
299
  fields: new Map(),
300
300
  interfaces: (0, utils_1.extractInterfaces)(node, new Set(), this.errors),
@@ -305,9 +305,13 @@ class NormalizationFactory {
305
305
  if (node.kind === graphql_1.Kind.INTERFACE_TYPE_DEFINITION || node.kind === graphql_1.Kind.INTERFACE_TYPE_EXTENSION || !isEntity) {
306
306
  return;
307
307
  }
308
- this.entities.add(this.parentTypeName);
309
- const fieldSets = (0, utils_3.getValueOrDefault)(this.fieldSetsByParent, this.parentTypeName, utils_2.newFieldSetContainer);
310
- this.extractKeyFieldSets(node, fieldSets.keys);
308
+ const fieldSetContainer = (0, utils_3.getValueOrDefault)(this.fieldSetContainerByTypeName, this.parentTypeName, utils_2.newFieldSetContainer);
309
+ this.extractKeyFieldSets(node, fieldSetContainer);
310
+ (0, utils_3.upsertEntityContainerProperties)(this.entityContainerByTypeName, {
311
+ typeName: this.parentTypeName,
312
+ keyFieldSets: fieldSetContainer.keys,
313
+ ...(this.subgraphName ? { subgraphNames: [this.subgraphName] } : {}),
314
+ });
311
315
  }
312
316
  validateChildDirectives(child, hostPath) {
313
317
  const childKind = child.node.kind;
@@ -395,7 +399,8 @@ class NormalizationFactory {
395
399
  operationTypeNode === graphql_1.OperationTypeNode.MUTATION ||
396
400
  operationTypeNode === graphql_1.OperationTypeNode.SUBSCRIPTION);
397
401
  }
398
- extractKeyFieldSets(node, rawFieldSets) {
402
+ extractKeyFieldSets(node, fieldSetContainer) {
403
+ const rawFieldSets = fieldSetContainer.keys;
399
404
  const parentTypeName = node.name.value;
400
405
  if (!node.directives?.length) {
401
406
  // This should never happen
@@ -414,6 +419,9 @@ class NormalizationFactory {
414
419
  for (const arg of directive.arguments) {
415
420
  const argumentName = arg.name.value;
416
421
  if (arg.name.value === string_constants_1.RESOLVABLE) {
422
+ if (arg.value.kind === graphql_1.Kind.BOOLEAN && !arg.value.value) {
423
+ fieldSetContainer.disableEntityResolver = true;
424
+ }
417
425
  continue;
418
426
  }
419
427
  if (arg.name.value !== string_constants_1.FIELDS) {
@@ -437,7 +445,7 @@ class NormalizationFactory {
437
445
  }
438
446
  const implementationErrorsMap = new Map();
439
447
  for (const interfaceName of container.interfaces) {
440
- const interfaceContainer = (0, utils_3.getOrThrowError)(this.parents, interfaceName, string_constants_1.PARENTS);
448
+ const interfaceContainer = (0, utils_3.getOrThrowError)(this.parentContainerByTypeName, interfaceName, string_constants_1.PARENTS);
441
449
  if (interfaceContainer.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION) {
442
450
  throw (0, errors_1.incompatibleParentKindFatalError)(interfaceName, graphql_1.Kind.INTERFACE_TYPE_DEFINITION, interfaceContainer.kind);
443
451
  }
@@ -510,7 +518,7 @@ class NormalizationFactory {
510
518
  this.errors.push((0, errors_1.unimplementedInterfaceFieldsError)(container.name.value, (0, utils_3.kindToTypeString)(container.kind), implementationErrorsMap));
511
519
  }
512
520
  }
513
- handleOverride(node, fieldName) {
521
+ handleOverride(node) {
514
522
  if (node.name.value !== string_constants_1.OVERRIDE) {
515
523
  return;
516
524
  }
@@ -652,7 +660,6 @@ class NormalizationFactory {
652
660
  after the visitor has visited the entire schema and the subgraph is known to be a V2 graph. Consequently,
653
661
  allDirectiveDefinitions cannot be used to check for duplicate definitions, and another set (below) is required */
654
662
  const definedDirectives = new Set();
655
- let fieldName = '';
656
663
  const handledRootTypes = new Set();
657
664
  // Collect any renamed root types
658
665
  (0, graphql_1.visit)(document, {
@@ -718,7 +725,7 @@ class NormalizationFactory {
718
725
  Directive: {
719
726
  enter(node) {
720
727
  const name = node.name.value;
721
- factory.handleOverride(node, fieldName);
728
+ factory.handleOverride(node);
722
729
  if (constants_1.VERSION_TWO_DIRECTIVES.has(name)) {
723
730
  factory.isSubgraphVersionTwo = true;
724
731
  return false;
@@ -732,13 +739,13 @@ class NormalizationFactory {
732
739
  EnumTypeDefinition: {
733
740
  enter(node) {
734
741
  const name = node.name.value;
735
- if (factory.parents.has(name)) {
742
+ if (factory.parentContainerByTypeName.has(name)) {
736
743
  factory.errors.push((0, errors_1.duplicateTypeDefinitionError)((0, utils_3.kindToTypeString)(node.kind), name));
737
744
  return false;
738
745
  }
739
746
  factory.parentTypeName = name;
740
747
  factory.lastParentNodeKind = node.kind;
741
- factory.parents.set(name, {
748
+ factory.parentContainerByTypeName.set(name, {
742
749
  description: (0, utils_1.formatDescription)(node.description),
743
750
  directives: factory.extractDirectives(node, new Map()),
744
751
  kind: node.kind,
@@ -757,7 +764,7 @@ class NormalizationFactory {
757
764
  factory.parentTypeName = name;
758
765
  factory.lastParentNodeKind = node.kind;
759
766
  factory.isCurrentParentExtension = true;
760
- const extension = factory.extensions.get(factory.parentTypeName);
767
+ const extension = factory.extensionContainerByTypeName.get(factory.parentTypeName);
761
768
  if (extension) {
762
769
  if (extension.kind !== graphql_1.Kind.ENUM_TYPE_EXTENSION) {
763
770
  factory.errors.push((0, errors_1.incompatibleExtensionKindsError)(node, extension.kind));
@@ -766,7 +773,7 @@ class NormalizationFactory {
766
773
  factory.extractDirectives(node, extension.directives);
767
774
  return;
768
775
  }
769
- factory.extensions.set(name, {
776
+ factory.extensionContainerByTypeName.set(name, {
770
777
  directives: factory.extractDirectives(node, new Map()),
771
778
  kind: node.kind,
772
779
  name: node.name,
@@ -785,8 +792,8 @@ class NormalizationFactory {
785
792
  factory.childName = name;
786
793
  factory.lastChildNodeKind = node.kind;
787
794
  const parent = factory.isCurrentParentExtension
788
- ? (0, utils_3.getOrThrowError)(factory.extensions, factory.parentTypeName, string_constants_1.EXTENSIONS)
789
- : (0, utils_3.getOrThrowError)(factory.parents, factory.parentTypeName, string_constants_1.PARENTS);
795
+ ? (0, utils_3.getOrThrowError)(factory.extensionContainerByTypeName, factory.parentTypeName, string_constants_1.EXTENSIONS)
796
+ : (0, utils_3.getOrThrowError)(factory.parentContainerByTypeName, factory.parentTypeName, string_constants_1.PARENTS);
790
797
  if (parent.kind !== graphql_1.Kind.ENUM_TYPE_DEFINITION && parent.kind !== graphql_1.Kind.ENUM_TYPE_EXTENSION) {
791
798
  throw (0, errors_1.unexpectedKindFatalError)(name);
792
799
  }
@@ -810,39 +817,39 @@ class NormalizationFactory {
810
817
  },
811
818
  FieldDefinition: {
812
819
  enter(node) {
813
- const name = node.name.value;
814
- if (factory.isCurrentParentRootType && (name === string_constants_1.SERVICE_FIELD || name === string_constants_1.ENTITIES_FIELD)) {
820
+ const fieldName = node.name.value;
821
+ if (factory.isCurrentParentRootType && (fieldName === string_constants_1.SERVICE_FIELD || fieldName === string_constants_1.ENTITIES_FIELD)) {
815
822
  return false;
816
823
  }
817
- factory.childName = name;
824
+ factory.childName = fieldName;
818
825
  factory.lastChildNodeKind = node.kind;
819
826
  if (factory.canContainEventDirectives()) {
820
827
  factory.extractEventDirectives(node);
821
828
  }
822
- const fieldPath = `${factory.parentTypeName}.${name}`;
829
+ const fieldPath = `${factory.parentTypeName}.${fieldName}`;
823
830
  factory.lastChildNodeKind = node.kind;
824
831
  const fieldNamedTypeName = (0, type_merging_1.getNamedTypeForChild)(fieldPath, node.type);
825
832
  if (!constants_1.BASE_SCALARS.has(fieldNamedTypeName)) {
826
833
  factory.referencedTypeNames.add(fieldNamedTypeName);
827
834
  }
828
835
  const parent = factory.isCurrentParentExtension
829
- ? (0, utils_3.getOrThrowError)(factory.extensions, factory.parentTypeName, string_constants_1.EXTENSIONS)
830
- : (0, utils_3.getOrThrowError)(factory.parents, factory.parentTypeName, string_constants_1.PARENTS);
836
+ ? (0, utils_3.getOrThrowError)(factory.extensionContainerByTypeName, factory.parentTypeName, string_constants_1.EXTENSIONS)
837
+ : (0, utils_3.getOrThrowError)(factory.parentContainerByTypeName, factory.parentTypeName, string_constants_1.PARENTS);
831
838
  if (parent.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION &&
832
839
  parent.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION &&
833
840
  parent.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION &&
834
841
  parent.kind !== graphql_1.Kind.INTERFACE_TYPE_EXTENSION) {
835
842
  throw (0, errors_1.unexpectedKindFatalError)(factory.parentTypeName);
836
843
  }
837
- if (parent.fields.has(name)) {
838
- factory.errors.push((0, errors_1.duplicateFieldDefinitionError)(name, factory.parentTypeName));
844
+ if (parent.fields.has(fieldName)) {
845
+ factory.errors.push((0, errors_1.duplicateFieldDefinitionError)(fieldName, factory.parentTypeName));
839
846
  return;
840
847
  }
841
848
  // recreate the node so the argument descriptions are updated
842
849
  const fieldContainer = {
843
850
  arguments: factory.extractArguments(node, new Map(), fieldPath),
844
851
  directives: factory.extractDirectives(node, new Map()),
845
- name,
852
+ name: fieldName,
846
853
  node: {
847
854
  ...node,
848
855
  arguments: node.arguments?.map((arg) => ({
@@ -851,27 +858,31 @@ class NormalizationFactory {
851
858
  })),
852
859
  },
853
860
  };
854
- parent.fields.set(name, fieldContainer);
855
- // Only entities will have an existing FieldSet
856
- const existingFieldSet = factory.fieldSetsByParent.get(factory.parentTypeName);
857
- if (existingFieldSet) {
858
- // @requires should only be defined on a field whose parent is an entity
859
- // If there is existingFieldSet, it's an entity
860
- (0, utils_2.extractFieldSetValue)(name, existingFieldSet.requires, fieldContainer.directives.get(string_constants_1.REQUIRES));
861
- // @provides only makes sense on entities, but the field can be encountered before the type definition
862
- // When the FieldSet is evaluated, it will be checked whether the field is an entity.
863
- (0, utils_2.extractFieldSetValue)(name, existingFieldSet.provides, fieldContainer.directives.get(string_constants_1.PROVIDES));
864
- return;
861
+ parent.fields.set(fieldName, fieldContainer);
862
+ const entityContainer = factory.entityContainerByTypeName.get(factory.parentTypeName);
863
+ if (entityContainer) {
864
+ entityContainer.fieldNames.add(fieldName);
865
+ // Only entities will have an existing FieldSet
866
+ const existingFieldSet = factory.fieldSetContainerByTypeName.get(factory.parentTypeName);
867
+ if (existingFieldSet) {
868
+ // @requires should only be defined on a field whose parent is an entity
869
+ // If there is existingFieldSet, it's an entity
870
+ (0, utils_2.extractFieldSetValue)(fieldName, existingFieldSet.requires, fieldContainer.directives.get(string_constants_1.REQUIRES));
871
+ // @provides only makes sense on entities, but the field can be encountered before the type definition
872
+ // When the FieldSet is evaluated, it will be checked whether the field is an entity.
873
+ (0, utils_2.extractFieldSetValue)(fieldName, existingFieldSet.provides, fieldContainer.directives.get(string_constants_1.PROVIDES));
874
+ return;
875
+ }
865
876
  }
866
877
  const providesDirectives = fieldContainer.directives.get(string_constants_1.PROVIDES);
867
878
  // Check whether the directive exists to avoid creating unnecessary fieldSet configurations
868
879
  if (!providesDirectives) {
869
880
  return;
870
881
  }
871
- const fieldSetContainer = (0, utils_3.getValueOrDefault)(factory.fieldSetsByParent, factory.parentTypeName, utils_2.newFieldSetContainer);
882
+ const fieldSetContainer = (0, utils_3.getValueOrDefault)(factory.fieldSetContainerByTypeName, factory.parentTypeName, utils_2.newFieldSetContainer);
872
883
  // @provides only makes sense on entities, but the field can be encountered before the type definition
873
884
  // When the FieldSet is evaluated, it will be checked whether the field is an entity.
874
- (0, utils_2.extractFieldSetValue)(name, fieldSetContainer.provides, providesDirectives);
885
+ (0, utils_2.extractFieldSetValue)(fieldName, fieldSetContainer.provides, providesDirectives);
875
886
  },
876
887
  leave() {
877
888
  factory.childName = '';
@@ -881,13 +892,13 @@ class NormalizationFactory {
881
892
  InputObjectTypeDefinition: {
882
893
  enter(node) {
883
894
  const name = node.name.value;
884
- if (factory.parents.has(name)) {
895
+ if (factory.parentContainerByTypeName.has(name)) {
885
896
  factory.errors.push((0, errors_1.duplicateTypeDefinitionError)((0, utils_3.kindToTypeString)(node.kind), name));
886
897
  return false;
887
898
  }
888
899
  factory.lastParentNodeKind = node.kind;
889
900
  factory.parentTypeName = name;
890
- factory.parents.set(name, {
901
+ factory.parentContainerByTypeName.set(name, {
891
902
  description: (0, utils_1.formatDescription)(node.description),
892
903
  directives: factory.extractDirectives(node, new Map()),
893
904
  fields: new Map(),
@@ -906,7 +917,7 @@ class NormalizationFactory {
906
917
  factory.parentTypeName = name;
907
918
  factory.lastParentNodeKind = node.kind;
908
919
  factory.isCurrentParentExtension = true;
909
- const extension = factory.extensions.get(factory.parentTypeName);
920
+ const extension = factory.extensionContainerByTypeName.get(factory.parentTypeName);
910
921
  if (extension) {
911
922
  if (extension.kind !== graphql_1.Kind.INPUT_OBJECT_TYPE_EXTENSION) {
912
923
  factory.errors.push((0, errors_1.incompatibleExtensionKindsError)(node, extension.kind));
@@ -915,7 +926,7 @@ class NormalizationFactory {
915
926
  factory.extractDirectives(node, extension.directives);
916
927
  return;
917
928
  }
918
- factory.extensions.set(name, {
929
+ factory.extensionContainerByTypeName.set(name, {
919
930
  directives: factory.extractDirectives(node, new Map()),
920
931
  fields: new Map(),
921
932
  kind: node.kind,
@@ -944,8 +955,8 @@ class NormalizationFactory {
944
955
  factory.referencedTypeNames.add(valueRootTypeName);
945
956
  }
946
957
  const parent = factory.isCurrentParentExtension
947
- ? (0, utils_3.getOrThrowError)(factory.extensions, factory.parentTypeName, string_constants_1.EXTENSIONS)
948
- : (0, utils_3.getOrThrowError)(factory.parents, factory.parentTypeName, string_constants_1.PARENTS);
958
+ ? (0, utils_3.getOrThrowError)(factory.extensionContainerByTypeName, factory.parentTypeName, string_constants_1.EXTENSIONS)
959
+ : (0, utils_3.getOrThrowError)(factory.parentContainerByTypeName, factory.parentTypeName, string_constants_1.PARENTS);
949
960
  if (parent.kind !== graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION && parent.kind !== graphql_1.Kind.INPUT_OBJECT_TYPE_EXTENSION) {
950
961
  throw (0, errors_1.unexpectedKindFatalError)(factory.parentTypeName);
951
962
  }
@@ -976,20 +987,12 @@ class NormalizationFactory {
976
987
  if ((0, utils_1.isNodeExtension)(node)) {
977
988
  return factory.handleObjectLikeExtension(node);
978
989
  }
979
- if (factory.parents.has(name)) {
990
+ if (factory.parentContainerByTypeName.has(name)) {
980
991
  factory.errors.push((0, errors_1.duplicateTypeDefinitionError)((0, utils_3.kindToTypeString)(node.kind), name));
981
992
  return false;
982
993
  }
983
994
  const isEntity = (0, utils_1.isObjectLikeNodeEntity)(node);
984
- if (isEntity) {
985
- factory.entityInterfaces.set(name, {
986
- interfaceFieldNames: new Set(node.fields?.map((field) => field.name.value)),
987
- interfaceObjectFieldNames: new Set(),
988
- isInterfaceObject: false,
989
- typeName: name,
990
- });
991
- }
992
- factory.parents.set(name, {
995
+ factory.parentContainerByTypeName.set(name, {
993
996
  description: (0, utils_1.formatDescription)(node.description),
994
997
  directives: factory.extractDirectives(node, new Map()),
995
998
  fields: new Map(),
@@ -1001,9 +1004,19 @@ class NormalizationFactory {
1001
1004
  if (!isEntity) {
1002
1005
  return;
1003
1006
  }
1004
- factory.entities.add(name);
1005
- const fieldSets = (0, utils_3.getValueOrDefault)(factory.fieldSetsByParent, name, utils_2.newFieldSetContainer);
1006
- factory.extractKeyFieldSets(node, fieldSets.keys);
1007
+ factory.entityInterfaces.set(name, {
1008
+ concreteTypeNames: new Set(),
1009
+ interfaceFieldNames: new Set(node.fields?.map((field) => field.name.value)),
1010
+ interfaceObjectFieldNames: new Set(),
1011
+ isInterfaceObject: false,
1012
+ typeName: name,
1013
+ });
1014
+ (0, utils_3.upsertEntityContainerProperties)(factory.entityContainerByTypeName, {
1015
+ typeName: factory.parentTypeName,
1016
+ ...(factory.subgraphName ? { subgraphNames: [factory.subgraphName] } : {}),
1017
+ });
1018
+ const fieldSetContainer = (0, utils_3.getValueOrDefault)(factory.fieldSetContainerByTypeName, name, utils_2.newFieldSetContainer);
1019
+ factory.extractKeyFieldSets(node, fieldSetContainer);
1007
1020
  },
1008
1021
  leave() {
1009
1022
  factory.parentTypeName = '';
@@ -1025,12 +1038,12 @@ class NormalizationFactory {
1025
1038
  },
1026
1039
  ObjectTypeDefinition: {
1027
1040
  enter(node) {
1028
- const name = node.name.value;
1029
- if (name === string_constants_1.SERVICE_OBJECT) {
1041
+ const typeName = node.name.value;
1042
+ if (typeName === string_constants_1.SERVICE_OBJECT) {
1030
1043
  return false;
1031
1044
  }
1032
- factory.isCurrentParentRootType = string_constants_1.ROOT_TYPES.has(name) || factory.operationTypeNames.has(name);
1033
- factory.parentTypeName = name;
1045
+ factory.isCurrentParentRootType = string_constants_1.ROOT_TYPES.has(typeName) || factory.operationTypeNames.has(typeName);
1046
+ factory.parentTypeName = typeName;
1034
1047
  factory.lastParentNodeKind = node.kind;
1035
1048
  (0, utils_1.addConcreteTypesForImplementedInterfaces)(node, factory.abstractToConcreteTypeNames);
1036
1049
  factory.handleInterfaceObject(node);
@@ -1038,12 +1051,12 @@ class NormalizationFactory {
1038
1051
  if ((0, utils_1.isNodeExtension)(node)) {
1039
1052
  return factory.handleObjectLikeExtension(node);
1040
1053
  }
1041
- if (factory.parents.has(name)) {
1042
- factory.errors.push((0, errors_1.duplicateTypeDefinitionError)((0, utils_3.kindToTypeString)(node.kind), name));
1054
+ if (factory.parentContainerByTypeName.has(typeName)) {
1055
+ factory.errors.push((0, errors_1.duplicateTypeDefinitionError)((0, utils_3.kindToTypeString)(node.kind), typeName));
1043
1056
  return false;
1044
1057
  }
1045
1058
  const isEntity = (0, utils_1.isObjectLikeNodeEntity)(node);
1046
- factory.parents.set(name, {
1059
+ factory.parentContainerByTypeName.set(typeName, {
1047
1060
  description: (0, utils_1.formatDescription)(node.description),
1048
1061
  directives: factory.extractDirectives(node, new Map()),
1049
1062
  fields: new Map(),
@@ -1055,9 +1068,13 @@ class NormalizationFactory {
1055
1068
  if (!isEntity) {
1056
1069
  return;
1057
1070
  }
1058
- factory.entities.add(name);
1059
- const fieldSets = (0, utils_3.getValueOrDefault)(factory.fieldSetsByParent, name, utils_2.newFieldSetContainer);
1060
- factory.extractKeyFieldSets(node, fieldSets.keys);
1071
+ const fieldSetContainer = (0, utils_3.getValueOrDefault)(factory.fieldSetContainerByTypeName, typeName, utils_2.newFieldSetContainer);
1072
+ factory.extractKeyFieldSets(node, fieldSetContainer);
1073
+ (0, utils_3.upsertEntityContainerProperties)(factory.entityContainerByTypeName, {
1074
+ typeName: factory.parentTypeName,
1075
+ keyFieldSets: fieldSetContainer.keys,
1076
+ ...(factory.subgraphName ? { subgraphNames: [factory.subgraphName] } : {}),
1077
+ });
1061
1078
  },
1062
1079
  leave() {
1063
1080
  factory.isCurrentParentRootType = false;
@@ -1091,14 +1108,14 @@ class NormalizationFactory {
1091
1108
  if (name === string_constants_1.ANY_SCALAR) {
1092
1109
  return false;
1093
1110
  }
1094
- const parent = factory.parents.get(name);
1111
+ const parent = factory.parentContainerByTypeName.get(name);
1095
1112
  if (parent) {
1096
1113
  factory.errors.push((0, errors_1.duplicateTypeDefinitionError)((0, utils_3.kindToTypeString)(node.kind), name));
1097
1114
  return false;
1098
1115
  }
1099
1116
  factory.parentTypeName = name;
1100
1117
  factory.lastParentNodeKind = node.kind;
1101
- factory.parents.set(name, {
1118
+ factory.parentContainerByTypeName.set(name, {
1102
1119
  description: (0, utils_1.formatDescription)(node.description),
1103
1120
  directives: factory.extractDirectives(node, new Map()),
1104
1121
  kind: graphql_1.Kind.SCALAR_TYPE_DEFINITION,
@@ -1116,7 +1133,7 @@ class NormalizationFactory {
1116
1133
  if (name === string_constants_1.ANY_SCALAR) {
1117
1134
  return false;
1118
1135
  }
1119
- const extension = factory.extensions.get(name);
1136
+ const extension = factory.extensionContainerByTypeName.get(name);
1120
1137
  if (extension) {
1121
1138
  if (extension.kind !== graphql_1.Kind.SCALAR_TYPE_EXTENSION) {
1122
1139
  factory.errors.push((0, errors_1.incompatibleExtensionKindsError)(node, extension.kind));
@@ -1127,7 +1144,7 @@ class NormalizationFactory {
1127
1144
  else {
1128
1145
  factory.parentTypeName = name;
1129
1146
  factory.lastParentNodeKind = node.kind;
1130
- factory.extensions.set(name, {
1147
+ factory.extensionContainerByTypeName.set(name, {
1131
1148
  directives: factory.extractDirectives(node, new Map()),
1132
1149
  kind: node.kind,
1133
1150
  name: node.name,
@@ -1147,7 +1164,7 @@ class NormalizationFactory {
1147
1164
  return false;
1148
1165
  }
1149
1166
  factory.parentTypeName = name;
1150
- const parent = factory.parents.get(name);
1167
+ const parent = factory.parentContainerByTypeName.get(name);
1151
1168
  if (parent) {
1152
1169
  factory.errors.push((0, errors_1.duplicateTypeDefinitionError)((0, utils_3.kindToTypeString)(node.kind), name));
1153
1170
  return false;
@@ -1158,7 +1175,7 @@ class NormalizationFactory {
1158
1175
  }
1159
1176
  factory.lastParentNodeKind = node.kind;
1160
1177
  (0, utils_1.addConcreteTypesForUnion)(node, factory.abstractToConcreteTypeNames);
1161
- factory.parents.set(name, {
1178
+ factory.parentContainerByTypeName.set(name, {
1162
1179
  description: (0, utils_1.formatDescription)(node.description),
1163
1180
  directives: factory.extractDirectives(node, new Map()),
1164
1181
  kind: node.kind,
@@ -1177,7 +1194,7 @@ class NormalizationFactory {
1177
1194
  if (name === string_constants_1.ENTITY_UNION) {
1178
1195
  return false;
1179
1196
  }
1180
- const extension = factory.extensions.get(name);
1197
+ const extension = factory.extensionContainerByTypeName.get(name);
1181
1198
  if (!node.types) {
1182
1199
  factory.errors.push();
1183
1200
  return false;
@@ -1192,7 +1209,7 @@ class NormalizationFactory {
1192
1209
  factory.extractDirectives(node, extension.directives);
1193
1210
  }
1194
1211
  else {
1195
- factory.extensions.set(name, {
1212
+ factory.extensionContainerByTypeName.set(name, {
1196
1213
  directives: factory.extractDirectives(node, new Map()),
1197
1214
  kind: node.kind,
1198
1215
  name: node.name,
@@ -1225,8 +1242,8 @@ class NormalizationFactory {
1225
1242
  }
1226
1243
  const validExtensionOrphans = new Set();
1227
1244
  const parentsToIgnore = new Set();
1228
- for (const [extensionTypeName, extensionContainer] of this.extensions) {
1229
- const isEntity = this.entities.has(extensionTypeName);
1245
+ for (const [extensionTypeName, extensionContainer] of this.extensionContainerByTypeName) {
1246
+ const isEntity = this.entityContainerByTypeName.has(extensionTypeName);
1230
1247
  const configurationData = {
1231
1248
  fieldNames: new Set(),
1232
1249
  isRootNode: isEntity,
@@ -1240,7 +1257,7 @@ class NormalizationFactory {
1240
1257
  }
1241
1258
  (0, utils_2.addNonExternalFieldsToSet)(extensionContainer.fields, configurationData.fieldNames);
1242
1259
  }
1243
- const baseType = this.parents.get(extensionTypeName);
1260
+ const baseType = this.parentContainerByTypeName.get(extensionTypeName);
1244
1261
  if (!baseType) {
1245
1262
  if (extensionContainer.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
1246
1263
  this.errors.push((0, errors_1.noBaseTypeExtensionError)(extensionTypeName));
@@ -1305,10 +1322,12 @@ class NormalizationFactory {
1305
1322
  this.mergeUniqueInterfaces(objectLikeExtension.interfaces, baseType.interfaces, extensionTypeName);
1306
1323
  this.validateInterfaceImplementations(baseType);
1307
1324
  definitions.push((0, utils_2.objectLikeContainerToNode)(this, baseType, objectLikeExtension));
1308
- // interfaces and objects must define at least one field
1325
+ // Interfaces and objects must define at least one field
1309
1326
  if (baseType.fields.size < 1 && !(0, utils_2.isNodeQuery)(extensionTypeName, operationTypeNode)) {
1310
1327
  this.errors.push((0, errors_1.noFieldDefinitionsError)((0, utils_3.kindToTypeString)(baseType.kind), extensionTypeName));
1311
1328
  }
1329
+ // Add the non-external base type field names to the configuration data
1330
+ (0, utils_2.addNonExternalFieldsToSet)(baseType.fields, configurationData.fieldNames);
1312
1331
  break;
1313
1332
  case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
1314
1333
  definitions.push((0, utils_2.scalarContainerToNode)(this, baseType, extensionContainer));
@@ -1323,7 +1342,7 @@ class NormalizationFactory {
1323
1342
  // At this point, the base type has been dealt with, so it doesn't need to be dealt with again
1324
1343
  parentsToIgnore.add(extensionTypeName);
1325
1344
  }
1326
- for (const [parentTypeName, parentContainer] of this.parents) {
1345
+ for (const [parentTypeName, parentContainer] of this.parentContainerByTypeName) {
1327
1346
  if (parentsToIgnore.has(parentTypeName)) {
1328
1347
  continue;
1329
1348
  }
@@ -1337,7 +1356,7 @@ class NormalizationFactory {
1337
1356
  case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
1338
1357
  // intentional fallthrough
1339
1358
  case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
1340
- const isEntity = this.entities.has(parentTypeName);
1359
+ const isEntity = this.entityContainerByTypeName.has(parentTypeName);
1341
1360
  const operationTypeNode = this.operationTypeNames.get(parentTypeName);
1342
1361
  if (operationTypeNode) {
1343
1362
  parentContainer.fields.delete(string_constants_1.SERVICE_FIELD);
@@ -1358,6 +1377,13 @@ class NormalizationFactory {
1358
1377
  isRootNode: isEntity,
1359
1378
  typeName: parentTypeName,
1360
1379
  };
1380
+ const entityInterfaceData = this.entityInterfaces.get(parentTypeName);
1381
+ if (entityInterfaceData) {
1382
+ entityInterfaceData.concreteTypeNames =
1383
+ this.abstractToConcreteTypeNames.get(parentTypeName) || new Set();
1384
+ configurationData.isInterfaceObject = entityInterfaceData.isInterfaceObject;
1385
+ configurationData.entityInterfaceConcreteTypeNames = entityInterfaceData.concreteTypeNames;
1386
+ }
1361
1387
  const events = this.eventsConfigurations.get(parentTypeName);
1362
1388
  if (events) {
1363
1389
  configurationData.events = events;
@@ -1389,12 +1415,12 @@ class NormalizationFactory {
1389
1415
  const operationTypeName = node ? (0, type_merging_1.getNamedTypeForChild)(`schema.${operationType}`, node.type) : defaultTypeName;
1390
1416
  // If a custom type is used, the default type should not be defined
1391
1417
  if (operationTypeName !== defaultTypeName &&
1392
- (this.parents.has(defaultTypeName) || this.extensions.has(defaultTypeName))) {
1418
+ (this.parentContainerByTypeName.has(defaultTypeName) || this.extensionContainerByTypeName.has(defaultTypeName))) {
1393
1419
  this.errors.push((0, errors_1.invalidRootTypeDefinitionError)(operationType, operationTypeName, defaultTypeName));
1394
1420
  continue;
1395
1421
  }
1396
- const object = this.parents.get(operationTypeName);
1397
- const extension = this.extensions.get(operationTypeName);
1422
+ const object = this.parentContainerByTypeName.get(operationTypeName);
1423
+ const extension = this.extensionContainerByTypeName.get(operationTypeName);
1398
1424
  // Node is truthy if an operation type was explicitly declared
1399
1425
  if (node) {
1400
1426
  // If the type is not defined in the schema, it's always an error
@@ -1429,7 +1455,7 @@ class NormalizationFactory {
1429
1455
  const fieldPath = `${operationTypeName}.${fieldName}`;
1430
1456
  const fieldTypeName = (0, type_merging_1.getNamedTypeForChild)(fieldPath, fieldContainer.node.type);
1431
1457
  if (!constants_1.BASE_SCALARS.has(fieldTypeName) &&
1432
- !this.parents.has(fieldTypeName) &&
1458
+ !this.parentContainerByTypeName.has(fieldTypeName) &&
1433
1459
  !validExtensionOrphans.has(fieldTypeName)) {
1434
1460
  this.errors.push((0, errors_1.undefinedTypeError)(fieldTypeName));
1435
1461
  }
@@ -1437,16 +1463,17 @@ class NormalizationFactory {
1437
1463
  }
1438
1464
  }
1439
1465
  for (const referencedTypeName of this.referencedTypeNames) {
1440
- if (this.parents.has(referencedTypeName) || this.entities.has(referencedTypeName)) {
1466
+ if (this.parentContainerByTypeName.has(referencedTypeName) ||
1467
+ this.entityContainerByTypeName.has(referencedTypeName)) {
1441
1468
  continue;
1442
1469
  }
1443
- const extension = this.extensions.get(referencedTypeName);
1470
+ const extension = this.extensionContainerByTypeName.get(referencedTypeName);
1444
1471
  if (!extension || extension.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
1445
1472
  this.errors.push((0, errors_1.undefinedTypeError)(referencedTypeName));
1446
1473
  }
1447
1474
  }
1448
- for (const [parentTypeName, fieldSets] of this.fieldSetsByParent) {
1449
- const parentContainer = this.parents.get(parentTypeName) || this.extensions.get(parentTypeName);
1475
+ for (const [parentTypeName, fieldSetContainers] of this.fieldSetContainerByTypeName) {
1476
+ const parentContainer = this.parentContainerByTypeName.get(parentTypeName) || this.extensionContainerByTypeName.get(parentTypeName);
1450
1477
  if (!parentContainer ||
1451
1478
  (parentContainer.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION &&
1452
1479
  parentContainer.kind != graphql_1.Kind.OBJECT_TYPE_EXTENSION &&
@@ -1455,7 +1482,8 @@ class NormalizationFactory {
1455
1482
  this.errors.push((0, errors_1.undefinedObjectLikeParentError)(parentTypeName));
1456
1483
  continue;
1457
1484
  }
1458
- (0, utils_2.validateDirectivesWithFieldSet)(this, parentContainer, fieldSets);
1485
+ // this is where keys, provides, and requires are added to the ConfigurationData
1486
+ (0, utils_2.validateAndAddDirectivesWithFieldSetToConfigurationData)(this, parentContainer, fieldSetContainers);
1459
1487
  }
1460
1488
  if (this.errors.length > 0) {
1461
1489
  return { errors: this.errors };
@@ -1469,11 +1497,14 @@ class NormalizationFactory {
1469
1497
  // configurationDataMap is map of ConfigurationData per type name.
1470
1498
  // It is an Intermediate configuration object that will be converted to an engine configuration in the router
1471
1499
  configurationDataMap: this.configurationDataMap,
1500
+ entityContainerByTypeName: this.entityContainerByTypeName,
1472
1501
  entityInterfaces: this.entityInterfaces,
1502
+ extensionContainerByTypeName: this.extensionContainerByTypeName,
1473
1503
  isVersionTwo: this.isSubgraphVersionTwo,
1474
- keyFieldsByParentTypeName: this.keyFieldsByParentTypeName,
1504
+ keyFieldNamesByParentTypeName: this.keyFieldNamesByParentTypeName,
1475
1505
  operationTypes: this.operationTypeNames,
1476
1506
  overridesByTargetSubgraphName: this.overridesByTargetSubgraphName,
1507
+ parentContainerByTypeName: this.parentContainerByTypeName,
1477
1508
  subgraphAST: newAST,
1478
1509
  subgraphString: (0, graphql_1.print)(newAST),
1479
1510
  schema: (0, buildASTSchema_1.buildASTSchema)(newAST, { assumeValid: true }),
@@ -1483,15 +1514,17 @@ class NormalizationFactory {
1483
1514
  }
1484
1515
  exports.NormalizationFactory = NormalizationFactory;
1485
1516
  function batchNormalize(subgraphs) {
1517
+ const entityContainersByTypeName = new Map();
1486
1518
  const internalSubgraphsBySubgraphName = new Map();
1487
1519
  const allOverridesByTargetSubgraphName = new Map();
1488
1520
  const overrideSourceSubgraphNamesByFieldPath = new Map();
1489
1521
  const duplicateOverriddenFieldPaths = new Set();
1490
- const validationErrors = [];
1522
+ const parentContainerMapsBySubgraphName = new Map();
1491
1523
  const subgraphNames = new Set();
1492
1524
  const nonUniqueSubgraphNames = new Set();
1493
1525
  const invalidNameErrorMessages = [];
1494
1526
  const warnings = [];
1527
+ const validationErrors = [];
1495
1528
  // Record the subgraph names first, so that subgraph references can be validated
1496
1529
  for (const subgraph of subgraphs) {
1497
1530
  if (subgraph.name) {
@@ -1513,16 +1546,22 @@ function batchNormalize(subgraphs) {
1513
1546
  validationErrors.push((0, errors_1.subgraphValidationError)(subgraphName, [errors_1.subgraphValidationFailureError]));
1514
1547
  continue;
1515
1548
  }
1549
+ parentContainerMapsBySubgraphName.set(subgraphName, normalizationResult.parentContainerByTypeName);
1550
+ for (const entityContainer of normalizationResult.entityContainerByTypeName.values()) {
1551
+ (0, utils_3.upsertEntityContainer)(entityContainersByTypeName, entityContainer);
1552
+ }
1516
1553
  if (subgraph.name) {
1517
1554
  internalSubgraphsBySubgraphName.set(subgraphName, {
1518
1555
  configurationDataMap: normalizationResult.configurationDataMap,
1519
1556
  definitions: normalizationResult.subgraphAST,
1520
1557
  entityInterfaces: normalizationResult.entityInterfaces,
1521
- keyFieldsByParentTypeName: normalizationResult.keyFieldsByParentTypeName,
1558
+ extensionContainerByTypeName: normalizationResult.extensionContainerByTypeName,
1559
+ keyFieldNamesByParentTypeName: normalizationResult.keyFieldNamesByParentTypeName,
1522
1560
  isVersionTwo: normalizationResult.isVersionTwo,
1523
1561
  name: subgraphName,
1524
1562
  operationTypes: normalizationResult.operationTypes,
1525
1563
  overriddenFieldNamesByParentTypeName: new Map(),
1564
+ parentContainerByTypeName: normalizationResult.parentContainerByTypeName,
1526
1565
  schema: normalizationResult.schema,
1527
1566
  url: subgraph.url,
1528
1567
  });
@@ -1567,9 +1606,13 @@ function batchNormalize(subgraphs) {
1567
1606
  allErrors.push((0, errors_1.duplicateOverriddenFieldsError)(duplicateOverriddenFieldErrorMessages));
1568
1607
  }
1569
1608
  allErrors.push(...validationErrors);
1570
- const warningsToPropagate = warnings.length > 0 ? warnings : undefined;
1571
1609
  if (allErrors.length > 0) {
1572
- return { errors: allErrors, internalSubgraphsBySubgraphName, warnings: warningsToPropagate };
1610
+ return {
1611
+ entityContainerByTypeName: entityContainersByTypeName,
1612
+ errors: allErrors,
1613
+ internalSubgraphBySubgraphName: internalSubgraphsBySubgraphName,
1614
+ ...(warnings.length > 0 ? { warnings } : {}),
1615
+ };
1573
1616
  }
1574
1617
  for (const [targetSubgraphName, overridesData] of allOverridesByTargetSubgraphName) {
1575
1618
  const internalSubgraph = (0, utils_3.getOrThrowError)(internalSubgraphsBySubgraphName, targetSubgraphName, 'normalizedSubgraphsByName');
@@ -1586,8 +1629,9 @@ function batchNormalize(subgraphs) {
1586
1629
  }
1587
1630
  }
1588
1631
  return {
1589
- internalSubgraphsBySubgraphName: internalSubgraphsBySubgraphName,
1590
- warnings: warningsToPropagate,
1632
+ entityContainerByTypeName: entityContainersByTypeName,
1633
+ internalSubgraphBySubgraphName: internalSubgraphsBySubgraphName,
1634
+ ...(warnings.length > 0 ? { warnings } : {}),
1591
1635
  };
1592
1636
  }
1593
1637
  exports.batchNormalize = batchNormalize;