@wundergraph/composition 0.18.4 → 0.19.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.
Files changed (54) hide show
  1. package/dist/ast/utils.d.ts +2 -9
  2. package/dist/ast/utils.js +2 -73
  3. package/dist/ast/utils.js.map +1 -1
  4. package/dist/errors/errors.d.ts +13 -19
  5. package/dist/errors/errors.js +50 -67
  6. package/dist/errors/errors.js.map +1 -1
  7. package/dist/federation/federation-factory.d.ts +17 -46
  8. package/dist/federation/federation-factory.js +391 -1002
  9. package/dist/federation/federation-factory.js.map +1 -1
  10. package/dist/federation/utils.d.ts +1 -115
  11. package/dist/federation/utils.js +0 -29
  12. package/dist/federation/utils.js.map +1 -1
  13. package/dist/federation/walkers.d.ts +3 -0
  14. package/dist/federation/walkers.js +120 -0
  15. package/dist/federation/walkers.js.map +1 -0
  16. package/dist/index.d.ts +2 -1
  17. package/dist/index.js +2 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/normalization/normalization-factory.d.ts +26 -18
  20. package/dist/normalization/normalization-factory.js +139 -141
  21. package/dist/normalization/normalization-factory.js.map +1 -1
  22. package/dist/normalization/utils.js +53 -54
  23. package/dist/normalization/utils.js.map +1 -1
  24. package/dist/normalization/walkers.js +156 -128
  25. package/dist/normalization/walkers.js.map +1 -1
  26. package/dist/router-configuration/router-configuration.d.ts +0 -1
  27. package/dist/schema-building/ast.d.ts +17 -5
  28. package/dist/schema-building/ast.js +32 -17
  29. package/dist/schema-building/ast.js.map +1 -1
  30. package/dist/schema-building/type-definition-data.d.ts +51 -25
  31. package/dist/schema-building/type-extension-data.d.ts +11 -7
  32. package/dist/schema-building/type-merging.d.ts +2 -4
  33. package/dist/schema-building/type-merging.js +8 -27
  34. package/dist/schema-building/type-merging.js.map +1 -1
  35. package/dist/schema-building/utils.d.ts +41 -18
  36. package/dist/schema-building/utils.js +855 -111
  37. package/dist/schema-building/utils.js.map +1 -1
  38. package/dist/subgraph/subgraph.d.ts +8 -10
  39. package/dist/subgraph/subgraph.js +1 -237
  40. package/dist/subgraph/subgraph.js.map +1 -1
  41. package/dist/tsconfig.tsbuildinfo +1 -1
  42. package/dist/utils/constants.d.ts +8 -1
  43. package/dist/utils/constants.js +47 -19
  44. package/dist/utils/constants.js.map +1 -1
  45. package/dist/utils/string-constants.d.ts +10 -4
  46. package/dist/utils/string-constants.js +20 -6
  47. package/dist/utils/string-constants.js.map +1 -1
  48. package/dist/utils/utils.d.ts +4 -4
  49. package/dist/utils/utils.js +10 -4
  50. package/dist/utils/utils.js.map +1 -1
  51. package/package.json +4 -3
  52. package/dist/ast/ast.d.ts +0 -97
  53. package/dist/ast/ast.js +0 -168
  54. package/dist/ast/ast.js.map +0 -1
@@ -5,42 +5,43 @@ const graphql_1 = require("graphql");
5
5
  const utils_1 = require("../ast/utils");
6
6
  const utils_2 = require("./utils");
7
7
  const constants_1 = require("../utils/constants");
8
- const type_merging_1 = require("../schema-building/type-merging");
9
8
  const utils_3 = require("../utils/utils");
10
9
  const errors_1 = require("../errors/errors");
11
10
  const string_constants_1 = require("../utils/string-constants");
12
11
  const buildASTSchema_1 = require("../buildASTSchema/buildASTSchema");
13
12
  const merge_1 = require("@graphql-tools/merge");
14
- const ast_1 = require("../ast/ast");
15
13
  const subgraph_1 = require("../subgraph/subgraph");
16
14
  const warnings_1 = require("../warnings/warnings");
17
15
  const walkers_1 = require("./walkers");
18
16
  const utils_4 = require("../schema-building/utils");
17
+ const graphology_1 = require("graphology");
18
+ const ast_1 = require("../schema-building/ast");
19
19
  function normalizeSubgraphFromString(subgraphSDL) {
20
20
  const { error, documentNode } = (0, utils_1.safeParse)(subgraphSDL);
21
21
  if (error || !documentNode) {
22
22
  return { errors: [(0, errors_1.subgraphInvalidSyntaxError)(error)] };
23
23
  }
24
- const normalizationFactory = new NormalizationFactory();
24
+ const normalizationFactory = new NormalizationFactory(new graphology_1.MultiGraph());
25
25
  return normalizationFactory.normalize(documentNode);
26
26
  }
27
27
  exports.normalizeSubgraphFromString = normalizeSubgraphFromString;
28
- function normalizeSubgraph(document, subgraphName) {
29
- const normalizationFactory = new NormalizationFactory(subgraphName);
28
+ function normalizeSubgraph(document, graph, subgraphName) {
29
+ const normalizationFactory = new NormalizationFactory(graph || new graphology_1.MultiGraph(), subgraphName);
30
30
  return normalizationFactory.normalize(document);
31
31
  }
32
32
  exports.normalizeSubgraph = normalizeSubgraph;
33
33
  class NormalizationFactory {
34
- abstractToConcreteTypeNames = new Map();
35
- directiveDefinitionByDirectiveName = new Map();
36
34
  argumentName = '';
37
35
  authorizationDataByParentTypeName = new Map();
38
36
  childName = '';
39
- configurationDataMap = new Map();
37
+ concreteTypeNamesByAbstractTypeName = new Map();
38
+ configurationDataByParentTypeName = new Map();
40
39
  customDirectiveDefinitions = new Map();
40
+ directiveDefinitionByDirectiveName = new Map();
41
41
  errors = [];
42
42
  entityContainerByTypeName = new Map();
43
43
  entityInterfaces = new Map();
44
+ graph;
44
45
  parentExtensionDataByTypeName = new Map();
45
46
  interfaceTypeNamesWithAuthorizationDirectives = new Set();
46
47
  isCurrentParentExtension = false;
@@ -52,9 +53,10 @@ class NormalizationFactory {
52
53
  lastChildNodeKind = graphql_1.Kind.NULL;
53
54
  leafTypeNamesWithAuthorizationDirectives = new Set();
54
55
  keyFieldNamesByParentTypeName = new Map();
55
- operationTypeNames = new Map();
56
+ operationTypeNodeByTypeName = new Map();
57
+ originalTypeNameByRenamedTypeName = new Map();
56
58
  parentDefinitionDataByTypeName = new Map();
57
- parentTypeName = '';
59
+ originalParentTypeName = '';
58
60
  parentsWithChildArguments = new Set();
59
61
  eventsConfigurations = new Map();
60
62
  overridesByTargetSubgraphName = new Map();
@@ -62,13 +64,15 @@ class NormalizationFactory {
62
64
  schemaDefinition;
63
65
  referencedDirectiveNames = new Set();
64
66
  referencedTypeNames = new Set();
67
+ renamedParentTypeName = '';
65
68
  warnings = [];
66
69
  subgraphName;
67
- constructor(subgraphName) {
70
+ constructor(graph, subgraphName) {
68
71
  for (const [baseDirectiveName, baseDirectiveDefinition] of constants_1.BASE_DIRECTIVE_DEFINITION_BY_DIRECTIVE_NAME) {
69
72
  this.directiveDefinitionByDirectiveName.set(baseDirectiveName, baseDirectiveDefinition);
70
73
  }
71
- this.subgraphName = subgraphName;
74
+ this.graph = graph;
75
+ this.subgraphName = subgraphName || string_constants_1.N_A;
72
76
  this.schemaDefinition = {
73
77
  directivesByDirectiveName: new Map(),
74
78
  kind: graphql_1.Kind.SCHEMA_DEFINITION,
@@ -94,32 +98,18 @@ class NormalizationFactory {
94
98
  return { hasUnhandledError: true, typeString: (0, utils_3.kindToTypeString)(parentContainer.kind) };
95
99
  }
96
100
  }
97
- extractArguments(node, argumentDataByArgumentName, fieldPath) {
98
- if (!node.arguments) {
99
- return argumentDataByArgumentName;
100
- }
101
- this.parentsWithChildArguments.add(this.parentTypeName);
102
- const duplicatedArguments = new Set();
103
- for (const argumentNode of node.arguments) {
104
- const argumentName = argumentNode.name.value;
105
- if (argumentDataByArgumentName.has(argumentName)) {
106
- duplicatedArguments.add(argumentName);
107
- continue;
108
- }
109
- argumentDataByArgumentName.set(argumentName, (0, ast_1.inputValueDefinitionNodeToMutable)(argumentNode, this.parentTypeName));
110
- }
111
- if (duplicatedArguments.size > 0) {
112
- this.errors.push((0, errors_1.duplicateArgumentsError)(fieldPath, [...duplicatedArguments]));
113
- }
114
- return argumentDataByArgumentName;
115
- }
116
101
  validateArguments(fieldData, fieldPath) {
117
102
  const invalidArguments = [];
118
103
  for (const [argumentName, argumentNode] of fieldData.argumentDataByArgumentName) {
119
- const namedType = (0, type_merging_1.getNamedTypeForChild)(fieldPath + `(${argumentName}...)`, argumentNode.type);
120
- const { hasUnhandledError, typeString } = this.validateInputNamedType(namedType);
104
+ const namedTypeName = (0, ast_1.getTypeNodeNamedTypeName)(argumentNode.type);
105
+ const { hasUnhandledError, typeString } = this.validateInputNamedType(namedTypeName);
121
106
  if (hasUnhandledError) {
122
- invalidArguments.push({ argumentName, namedType, typeString, typeName: (0, merge_1.printTypeNode)(argumentNode.type) });
107
+ invalidArguments.push({
108
+ argumentName,
109
+ namedType: namedTypeName,
110
+ typeString,
111
+ typeName: (0, merge_1.printTypeNode)(argumentNode.type),
112
+ });
123
113
  }
124
114
  }
125
115
  if (invalidArguments.length > 0) {
@@ -128,7 +118,8 @@ class NormalizationFactory {
128
118
  }
129
119
  // Note that directive validation errors are handled elsewhere
130
120
  getAuthorizationData(node) {
131
- let authorizationData = this.authorizationDataByParentTypeName.get(this.parentTypeName);
121
+ const parentTypeName = this.renamedParentTypeName || this.originalParentTypeName;
122
+ let authorizationData = this.authorizationDataByParentTypeName.get(parentTypeName);
132
123
  (0, utils_3.resetAuthorizationData)(authorizationData);
133
124
  if (!node.directives) {
134
125
  return authorizationData;
@@ -158,10 +149,10 @@ class NormalizationFactory {
158
149
  return authorizationData;
159
150
  }
160
151
  if ((0, utils_3.isNodeKindInterface)(node.kind)) {
161
- this.interfaceTypeNamesWithAuthorizationDirectives.add(this.parentTypeName);
152
+ this.interfaceTypeNamesWithAuthorizationDirectives.add(parentTypeName);
162
153
  }
163
154
  if (!authorizationData) {
164
- authorizationData = (0, utils_3.setAndGetValue)(this.authorizationDataByParentTypeName, this.parentTypeName, (0, utils_3.newAuthorizationData)(this.parentTypeName));
155
+ authorizationData = (0, utils_3.setAndGetValue)(this.authorizationDataByParentTypeName, this.renamedParentTypeName || this.originalParentTypeName, (0, utils_3.newAuthorizationData)(parentTypeName));
165
156
  }
166
157
  authorizationData.hasParentLevelAuthorization = true;
167
158
  authorizationData.requiresAuthentication = requiresAuthentication;
@@ -181,7 +172,7 @@ class NormalizationFactory {
181
172
  return authorizationData;
182
173
  }
183
174
  if (orScopes.length > utils_3.maxOrScopes) {
184
- this.invalidOrScopesHostPaths.add(this.parentTypeName);
175
+ this.invalidOrScopesHostPaths.add(this.originalParentTypeName);
185
176
  return;
186
177
  }
187
178
  for (const scopes of orScopes) {
@@ -205,7 +196,7 @@ class NormalizationFactory {
205
196
  if (!node.directives) {
206
197
  return directivesByDirectiveName;
207
198
  }
208
- const hostPath = this.childName ? `${this.parentTypeName}.${this.childName}` : this.parentTypeName;
199
+ const hostPath = this.childName ? `${this.originalParentTypeName}.${this.childName}` : this.originalParentTypeName;
209
200
  const authorizationDirectives = [];
210
201
  for (const directiveNode of node.directives) {
211
202
  const errorMessages = (0, utils_4.getDirectiveValidationErrors)(directiveNode, node.kind, directivesByDirectiveName, this.directiveDefinitionByDirectiveName, this.handledRepeatedDirectivesByHostPath, hostPath);
@@ -237,10 +228,11 @@ class NormalizationFactory {
237
228
  if (authorizationDirectives.length < 1) {
238
229
  return directivesByDirectiveName;
239
230
  }
231
+ const parentTypeName = this.renamedParentTypeName || this.originalParentTypeName;
240
232
  if (node.kind !== graphql_1.Kind.FIELD_DEFINITION) {
241
- this.leafTypeNamesWithAuthorizationDirectives.add(this.parentTypeName);
233
+ this.leafTypeNamesWithAuthorizationDirectives.add(parentTypeName);
242
234
  }
243
- const parentAuthorizationData = (0, utils_3.getValueOrDefault)(this.authorizationDataByParentTypeName, this.parentTypeName, () => (0, utils_3.newAuthorizationData)(this.parentTypeName));
235
+ const parentAuthorizationData = (0, utils_3.getValueOrDefault)(this.authorizationDataByParentTypeName, parentTypeName, () => (0, utils_3.newAuthorizationData)(parentTypeName));
244
236
  const authorizationData = (0, utils_3.getAuthorizationDataToUpdate)(parentAuthorizationData, node, this.childName);
245
237
  for (const directiveNode of authorizationDirectives) {
246
238
  const directiveName = directiveNode.name.value;
@@ -290,65 +282,33 @@ class NormalizationFactory {
290
282
  typeName: name,
291
283
  });
292
284
  }
293
- handleExtensionWithFields(node) {
285
+ handleExtensionWithFields(node, isRootType = false) {
294
286
  this.isCurrentParentExtension = true;
295
- const extension = this.parentExtensionDataByTypeName.get(this.parentTypeName);
287
+ const parentExtensionData = this.parentExtensionDataByTypeName.get(this.originalParentTypeName);
296
288
  const convertedKind = (0, utils_4.convertKindForExtension)(node);
297
- if (extension) {
298
- if (extension.kind !== convertedKind) {
299
- this.errors.push((0, errors_1.incompatibleExtensionKindsError)(node, extension.kind));
289
+ if (parentExtensionData) {
290
+ if (parentExtensionData.kind !== convertedKind) {
291
+ this.errors.push((0, errors_1.incompatibleExtensionKindsError)(node, parentExtensionData.kind));
300
292
  return false;
301
293
  }
302
- (0, utils_4.extractDirectives)(node, extension.directivesByDirectiveName, this.errors, this.directiveDefinitionByDirectiveName, this.handledRepeatedDirectivesByHostPath, this.parentTypeName);
303
- (0, utils_1.extractInterfaces)(node, extension.implementedInterfaceTypeNames, this.errors);
294
+ (0, utils_4.extractDirectives)(node, parentExtensionData.directivesByDirectiveName, this.errors, this.directiveDefinitionByDirectiveName, this.handledRepeatedDirectivesByHostPath, this.originalParentTypeName);
295
+ (0, utils_1.extractInterfaces)(node, parentExtensionData.implementedInterfaceTypeNames, this.errors);
304
296
  return;
305
297
  }
306
298
  const isEntity = (0, utils_1.isObjectLikeNodeEntity)(node);
307
- (0, utils_4.upsertExtensionWithFieldsDataByNode)(this.parentExtensionDataByTypeName, node, this.errors, this.directiveDefinitionByDirectiveName, this.handledRepeatedDirectivesByHostPath, isEntity);
299
+ (0, utils_4.addExtensionWithFieldsDataByNode)(this.parentExtensionDataByTypeName, node, this.errors, this.directiveDefinitionByDirectiveName, this.handledRepeatedDirectivesByHostPath, isEntity, isRootType, this.subgraphName, this.renamedParentTypeName);
308
300
  // TODO re-assess this line
309
301
  if (node.kind === graphql_1.Kind.INTERFACE_TYPE_DEFINITION || node.kind === graphql_1.Kind.INTERFACE_TYPE_EXTENSION || !isEntity) {
310
302
  return;
311
303
  }
312
- const fieldSetContainer = (0, utils_3.getValueOrDefault)(this.fieldSetContainerByTypeName, this.parentTypeName, utils_2.newFieldSetContainer);
304
+ const fieldSetContainer = (0, utils_3.getValueOrDefault)(this.fieldSetContainerByTypeName, this.originalParentTypeName, utils_2.newFieldSetContainer);
313
305
  this.extractKeyFieldSets(node, fieldSetContainer);
314
306
  (0, utils_3.upsertEntityContainerProperties)(this.entityContainerByTypeName, {
315
- typeName: this.parentTypeName,
307
+ typeName: this.originalParentTypeName,
316
308
  keyFieldSets: fieldSetContainer.keys,
317
309
  ...(this.subgraphName ? { subgraphNames: [this.subgraphName] } : {}),
318
310
  });
319
311
  }
320
- isTypeValidImplementation(originalType, implementationType) {
321
- if (originalType.kind === graphql_1.Kind.NON_NULL_TYPE) {
322
- if (implementationType.kind !== graphql_1.Kind.NON_NULL_TYPE) {
323
- return false;
324
- }
325
- return this.isTypeValidImplementation(originalType.type, implementationType.type);
326
- }
327
- if (implementationType.kind === graphql_1.Kind.NON_NULL_TYPE) {
328
- return this.isTypeValidImplementation(originalType, implementationType.type);
329
- }
330
- switch (originalType.kind) {
331
- case graphql_1.Kind.NAMED_TYPE:
332
- if (implementationType.kind === graphql_1.Kind.NAMED_TYPE) {
333
- const originalTypeName = originalType.name.value;
334
- const implementationTypeName = implementationType.name.value;
335
- if (originalTypeName === implementationTypeName) {
336
- return true;
337
- }
338
- const concreteTypes = this.abstractToConcreteTypeNames.get(originalTypeName);
339
- if (!concreteTypes) {
340
- return false;
341
- }
342
- return concreteTypes.has(implementationTypeName);
343
- }
344
- return false;
345
- default:
346
- if (implementationType.kind === graphql_1.Kind.LIST_TYPE) {
347
- return this.isTypeValidImplementation(originalType.type, implementationType.type);
348
- }
349
- return false;
350
- }
351
- }
352
312
  extractKeyFieldSets(node, fieldSetContainer) {
353
313
  const rawFieldSets = fieldSetContainer.keys;
354
314
  const parentTypeName = node.name.value;
@@ -419,7 +379,7 @@ class NormalizationFactory {
419
379
  unimplementedArguments: new Set(),
420
380
  };
421
381
  // The implemented field type must be equally or more restrictive than the original interface field type
422
- if (!this.isTypeValidImplementation(interfaceField.node.type, containerField.node.type)) {
382
+ if (!(0, utils_4.isTypeValidImplementation)(interfaceField.node.type, containerField.node.type, this.concreteTypeNamesByAbstractTypeName)) {
423
383
  hasErrors = true;
424
384
  hasNestedErrors = true;
425
385
  invalidFieldImplementation.implementedResponseType = (0, merge_1.printTypeNode)(containerField.node.type);
@@ -465,7 +425,7 @@ class NormalizationFactory {
465
425
  }
466
426
  }
467
427
  if (implementationErrorsMap.size) {
468
- this.errors.push((0, errors_1.unimplementedInterfaceFieldsError)(container.typeName, (0, utils_3.kindToTypeString)(container.kind), implementationErrorsMap));
428
+ this.errors.push((0, errors_1.unimplementedInterfaceFieldsError)(container.name, (0, utils_3.kindToTypeString)(container.kind), implementationErrorsMap));
469
429
  }
470
430
  }
471
431
  handleOverrideDeclaration(node, hostPath, errorMessages) {
@@ -480,7 +440,7 @@ class NormalizationFactory {
480
440
  return;
481
441
  }
482
442
  const overrideDataForSubgraph = (0, utils_3.getValueOrDefault)(this.overridesByTargetSubgraphName, targetSubgraphName, () => new Map());
483
- const overriddenFieldNamesForParent = (0, utils_3.getValueOrDefault)(overrideDataForSubgraph, this.parentTypeName, () => new Set());
443
+ const overriddenFieldNamesForParent = (0, utils_3.getValueOrDefault)(overrideDataForSubgraph, this.renamedParentTypeName || this.originalParentTypeName, () => new Set());
484
444
  overriddenFieldNamesForParent.add(this.childName);
485
445
  }
486
446
  extractEventDirectivesToConfiguration(node) {
@@ -539,7 +499,7 @@ class NormalizationFactory {
539
499
  if (!topic) {
540
500
  throw new Error(`Event directives must have a topic argument`);
541
501
  }
542
- const configuration = (0, utils_3.getValueOrDefault)(this.eventsConfigurations, this.parentTypeName, () => []);
502
+ const configuration = (0, utils_3.getValueOrDefault)(this.eventsConfigurations, this.renamedParentTypeName || this.originalParentTypeName, () => []);
543
503
  configuration.push({
544
504
  type: eventType,
545
505
  fieldName: this.childName,
@@ -561,7 +521,7 @@ class NormalizationFactory {
561
521
  if (!interfaceAuthorizationData) {
562
522
  continue;
563
523
  }
564
- const concreteTypeNames = this.abstractToConcreteTypeNames.get(interfaceTypeName);
524
+ const concreteTypeNames = this.concreteTypeNamesByAbstractTypeName.get(interfaceTypeName);
565
525
  for (const concreteTypeName of concreteTypeNames || []) {
566
526
  const concreteAuthorizationData = (0, utils_3.getValueOrDefault)(this.authorizationDataByParentTypeName, concreteTypeName, () => (0, utils_3.newAuthorizationData)(concreteTypeName));
567
527
  for (const [fieldName, interfaceFieldAuthorizationData,] of interfaceAuthorizationData.fieldAuthorizationDataByFieldName) {
@@ -604,18 +564,22 @@ class NormalizationFactory {
604
564
  if (this.schemaDefinition.operationTypes.size > 0) {
605
565
  definitions.push((0, utils_4.getSchemaNodeByData)(this.schemaDefinition, this.errors, this.directiveDefinitionByDirectiveName));
606
566
  }
607
- const validExtensionOrphans = new Set();
608
- const parentsToIgnore = new Set();
567
+ const validParentExtensionOrphansByTypeName = new Map();
568
+ const handledParentTypeNames = new Set();
609
569
  for (const [extensionTypeName, parentExtensionData] of this.parentExtensionDataByTypeName) {
610
570
  const isEntity = this.entityContainerByTypeName.has(extensionTypeName);
571
+ const newParentTypeName = parentExtensionData.kind === graphql_1.Kind.OBJECT_TYPE_EXTENSION
572
+ ? parentExtensionData.renamedTypeName || extensionTypeName
573
+ : extensionTypeName;
611
574
  const configurationData = {
612
575
  fieldNames: new Set(),
613
576
  isRootNode: isEntity,
614
- typeName: extensionTypeName,
577
+ typeName: newParentTypeName,
615
578
  };
616
- this.configurationDataMap.set(extensionTypeName, configurationData);
579
+ this.configurationDataByParentTypeName.set(newParentTypeName, configurationData);
617
580
  if (parentExtensionData.kind === graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
618
- if (this.operationTypeNames.has(extensionTypeName)) {
581
+ if (this.operationTypeNodeByTypeName.has(extensionTypeName)) {
582
+ configurationData.isRootNode = true;
619
583
  parentExtensionData.fieldDataByFieldName.delete(string_constants_1.SERVICE_FIELD);
620
584
  parentExtensionData.fieldDataByFieldName.delete(string_constants_1.ENTITIES_FIELD);
621
585
  }
@@ -628,7 +592,7 @@ class NormalizationFactory {
628
592
  }
629
593
  else {
630
594
  this.validateInterfaceImplementations(parentExtensionData);
631
- validExtensionOrphans.add(extensionTypeName);
595
+ validParentExtensionOrphansByTypeName.set(extensionTypeName, parentExtensionData);
632
596
  definitions.push((0, utils_4.getParentWithFieldsNodeByData)(parentExtensionData, this.errors, this.directiveDefinitionByDirectiveName, this.authorizationDataByParentTypeName));
633
597
  }
634
598
  continue;
@@ -664,8 +628,9 @@ class NormalizationFactory {
664
628
  // intentional fallthrough
665
629
  case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
666
630
  const extensionWithFieldsData = parentExtensionData;
667
- const operationTypeNode = this.operationTypeNames.get(extensionTypeName);
631
+ const operationTypeNode = this.operationTypeNodeByTypeName.get(extensionTypeName);
668
632
  if (operationTypeNode) {
633
+ configurationData.isRootNode = true;
669
634
  extensionWithFieldsData.fieldDataByFieldName.delete(string_constants_1.SERVICE_FIELD);
670
635
  extensionWithFieldsData.fieldDataByFieldName.delete(string_constants_1.ENTITIES_FIELD);
671
636
  }
@@ -704,10 +669,10 @@ class NormalizationFactory {
704
669
  throw (0, errors_1.unexpectedKindFatalError)(extensionTypeName);
705
670
  }
706
671
  // At this point, the base type has been dealt with, so it doesn't need to be dealt with again
707
- parentsToIgnore.add(extensionTypeName);
672
+ handledParentTypeNames.add(extensionTypeName);
708
673
  }
709
674
  for (const [parentTypeName, parentDefinitionData] of this.parentDefinitionDataByTypeName) {
710
- if (parentsToIgnore.has(parentTypeName)) {
675
+ if (handledParentTypeNames.has(parentTypeName)) {
711
676
  continue;
712
677
  }
713
678
  switch (parentDefinitionData.kind) {
@@ -721,7 +686,7 @@ class NormalizationFactory {
721
686
  // intentional fallthrough
722
687
  case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
723
688
  const isEntity = this.entityContainerByTypeName.has(parentTypeName);
724
- const operationTypeNode = this.operationTypeNames.get(parentTypeName);
689
+ const operationTypeNode = this.operationTypeNodeByTypeName.get(parentTypeName);
725
690
  if (operationTypeNode) {
726
691
  parentDefinitionData.fieldDataByFieldName.delete(string_constants_1.SERVICE_FIELD);
727
692
  parentDefinitionData.fieldDataByFieldName.delete(string_constants_1.ENTITIES_FIELD);
@@ -731,28 +696,31 @@ class NormalizationFactory {
731
696
  parentDefinitionData.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION) {
732
697
  continue;
733
698
  }
734
- for (const [fieldName, fieldContainer] of parentDefinitionData.fieldDataByFieldName) {
699
+ for (const [fieldName, fieldData] of parentDefinitionData.fieldDataByFieldName) {
735
700
  // Arguments can only be fully validated once all parents types are known
736
- this.validateArguments(fieldContainer, `${parentTypeName}.${fieldName}`);
701
+ this.validateArguments(fieldData, `${parentTypeName}.${fieldName}`);
737
702
  }
738
703
  }
704
+ const newParentTypeName = parentDefinitionData.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION
705
+ ? parentDefinitionData.renamedTypeName || parentTypeName
706
+ : parentTypeName;
739
707
  const configurationData = {
740
708
  fieldNames: new Set(),
741
709
  isRootNode: isEntity,
742
- typeName: parentTypeName,
710
+ typeName: newParentTypeName,
743
711
  };
744
712
  const entityInterfaceData = this.entityInterfaces.get(parentTypeName);
745
713
  if (entityInterfaceData) {
746
714
  entityInterfaceData.concreteTypeNames =
747
- this.abstractToConcreteTypeNames.get(parentTypeName) || new Set();
715
+ this.concreteTypeNamesByAbstractTypeName.get(parentTypeName) || new Set();
748
716
  configurationData.isInterfaceObject = entityInterfaceData.isInterfaceObject;
749
717
  configurationData.entityInterfaceConcreteTypeNames = entityInterfaceData.concreteTypeNames;
750
718
  }
751
- const events = this.eventsConfigurations.get(parentTypeName);
719
+ const events = this.eventsConfigurations.get(newParentTypeName);
752
720
  if (events) {
753
721
  configurationData.events = events;
754
722
  }
755
- this.configurationDataMap.set(parentTypeName, configurationData);
723
+ this.configurationDataByParentTypeName.set(newParentTypeName, configurationData);
756
724
  (0, utils_2.addNonExternalFieldsToSet)(parentDefinitionData.fieldDataByFieldName, configurationData.fieldNames);
757
725
  this.validateInterfaceImplementations(parentDefinitionData);
758
726
  definitions.push((0, utils_4.getParentWithFieldsNodeByData)(parentDefinitionData, this.errors, this.directiveDefinitionByDirectiveName, this.authorizationDataByParentTypeName));
@@ -773,10 +741,10 @@ class NormalizationFactory {
773
741
  }
774
742
  // Check that explicitly defined operations types are valid objects and that their fields are also valid
775
743
  for (const operationType of Object.values(graphql_1.OperationTypeNode)) {
776
- const node = this.schemaDefinition.operationTypes.get(operationType);
744
+ const operationTypeNode = this.schemaDefinition.operationTypes.get(operationType);
777
745
  const defaultTypeName = (0, utils_3.getOrThrowError)(utils_1.operationTypeNodeToDefaultType, operationType, string_constants_1.OPERATION_TO_DEFAULT);
778
746
  // If an operation type name was not declared, use the default
779
- const operationTypeName = node ? (0, type_merging_1.getNamedTypeForChild)(`schema.${operationType}`, node.type) : defaultTypeName;
747
+ const operationTypeName = operationTypeNode ? (0, ast_1.getTypeNodeNamedTypeName)(operationTypeNode.type) : defaultTypeName;
780
748
  // If a custom type is used, the default type should not be defined
781
749
  if (operationTypeName !== defaultTypeName &&
782
750
  (this.parentDefinitionDataByTypeName.has(defaultTypeName) ||
@@ -784,43 +752,42 @@ class NormalizationFactory {
784
752
  this.errors.push((0, errors_1.invalidRootTypeDefinitionError)(operationType, operationTypeName, defaultTypeName));
785
753
  continue;
786
754
  }
787
- const object = this.parentDefinitionDataByTypeName.get(operationTypeName);
788
- const extension = this.parentExtensionDataByTypeName.get(operationTypeName);
789
- // Node is truthy if an operation type was explicitly declared
790
- if (node) {
755
+ const objectData = this.parentDefinitionDataByTypeName.get(operationTypeName);
756
+ const extensionData = this.parentExtensionDataByTypeName.get(operationTypeName);
757
+ // operationTypeNode is truthy if an operation type was explicitly declared
758
+ if (operationTypeNode) {
791
759
  // If the type is not defined in the schema, it's always an error
792
- if (!object && !extension) {
760
+ if (!objectData && !extensionData) {
793
761
  this.errors.push((0, errors_1.undefinedTypeError)(operationTypeName));
794
762
  continue;
795
763
  }
796
764
  // Add the explicitly defined type to the map for the federation-factory
797
- this.operationTypeNames.set(operationTypeName, operationType);
765
+ this.operationTypeNodeByTypeName.set(operationTypeName, operationType);
798
766
  }
799
- if (!object && !extension) {
767
+ if (!objectData && !extensionData) {
800
768
  continue;
801
769
  }
802
- const rootNode = this.configurationDataMap.get(operationTypeName);
770
+ const rootNode = this.configurationDataByParentTypeName.get(defaultTypeName);
803
771
  if (rootNode) {
804
772
  rootNode.isRootNode = true;
805
773
  rootNode.typeName = defaultTypeName;
806
774
  }
807
- const containers = [object, extension];
808
- for (const container of containers) {
809
- if (!container) {
775
+ const parentDatas = [objectData, extensionData];
776
+ for (const parentData of parentDatas) {
777
+ if (!parentData) {
810
778
  continue;
811
779
  }
812
- if (container.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION && container.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
813
- this.errors.push((0, errors_1.operationDefinitionError)(operationTypeName, operationType, container.kind));
780
+ if (parentData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION && parentData.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
781
+ this.errors.push((0, errors_1.operationDefinitionError)(operationTypeName, operationType, parentData.kind));
814
782
  continue;
815
783
  }
816
784
  // Root types fields whose response type is an extension orphan could be valid through a federated graph
817
785
  // However, the field would have to be shareable to ever be valid TODO
818
- for (const [fieldName, fieldData] of container.fieldDataByFieldName) {
819
- const fieldPath = `${operationTypeName}.${fieldName}`;
820
- const fieldTypeName = (0, type_merging_1.getNamedTypeForChild)(fieldPath, fieldData.node.type);
786
+ for (const fieldData of parentData.fieldDataByFieldName.values()) {
787
+ const fieldTypeName = (0, ast_1.getTypeNodeNamedTypeName)(fieldData.node.type);
821
788
  if (!constants_1.BASE_SCALARS.has(fieldTypeName) &&
822
789
  !this.parentDefinitionDataByTypeName.has(fieldTypeName) &&
823
- !validExtensionOrphans.has(fieldTypeName)) {
790
+ !validParentExtensionOrphansByTypeName.has(fieldTypeName)) {
824
791
  this.errors.push((0, errors_1.undefinedTypeError)(fieldTypeName));
825
792
  }
826
793
  }
@@ -837,18 +804,27 @@ class NormalizationFactory {
837
804
  }
838
805
  }
839
806
  for (const [parentTypeName, fieldSetContainers] of this.fieldSetContainerByTypeName) {
840
- const parentContainer = this.parentDefinitionDataByTypeName.get(parentTypeName) ||
807
+ const parentData = this.parentDefinitionDataByTypeName.get(parentTypeName) ||
841
808
  this.parentExtensionDataByTypeName.get(parentTypeName);
842
- if (!parentContainer ||
843
- (parentContainer.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION &&
844
- parentContainer.kind != graphql_1.Kind.OBJECT_TYPE_EXTENSION &&
845
- parentContainer.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION &&
846
- parentContainer.kind !== graphql_1.Kind.INTERFACE_TYPE_EXTENSION)) {
809
+ if (!parentData ||
810
+ (parentData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION &&
811
+ parentData.kind != graphql_1.Kind.OBJECT_TYPE_EXTENSION &&
812
+ parentData.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION &&
813
+ parentData.kind !== graphql_1.Kind.INTERFACE_TYPE_EXTENSION)) {
847
814
  this.errors.push((0, errors_1.undefinedObjectLikeParentError)(parentTypeName));
848
815
  continue;
849
816
  }
850
817
  // this is where keys, provides, and requires are added to the ConfigurationData
851
- (0, utils_2.validateAndAddDirectivesWithFieldSetToConfigurationData)(this, parentContainer, fieldSetContainers);
818
+ (0, utils_2.validateAndAddDirectivesWithFieldSetToConfigurationData)(this, parentData, fieldSetContainers);
819
+ }
820
+ const persistedDirectiveDefinitionDataByDirectiveName = new Map();
821
+ for (const directiveDefinitionNode of this.directiveDefinitionByDirectiveName.values()) {
822
+ // TODO @composeDirective directives would also be handled here
823
+ const executableLocations = (0, utils_1.extractExecutableDirectiveLocations)(directiveDefinitionNode.locations, new Set());
824
+ if (executableLocations.size < 1) {
825
+ continue;
826
+ }
827
+ (0, utils_4.addPersistedDirectiveDefinitionDataByNode)(persistedDirectiveDefinitionDataByDirectiveName, directiveDefinitionNode, this.errors, this.directiveDefinitionByDirectiveName, this.handledRepeatedDirectivesByHostPath, executableLocations, this.subgraphName);
852
828
  }
853
829
  if (this.errors.length > 0) {
854
830
  return { errors: this.errors };
@@ -862,15 +838,19 @@ class NormalizationFactory {
862
838
  authorizationDataByParentTypeName: this.authorizationDataByParentTypeName,
863
839
  // configurationDataMap is map of ConfigurationData per type name.
864
840
  // It is an Intermediate configuration object that will be converted to an engine configuration in the router
865
- configurationDataMap: this.configurationDataMap,
841
+ concreteTypeNamesByAbstractTypeName: this.concreteTypeNamesByAbstractTypeName,
842
+ configurationDataByParentTypeName: this.configurationDataByParentTypeName,
866
843
  entityContainerByTypeName: this.entityContainerByTypeName,
867
844
  entityInterfaces: this.entityInterfaces,
868
- parentExtensionDataByTypeName: this.parentExtensionDataByTypeName,
845
+ parentDefinitionDataByTypeName: this.parentDefinitionDataByTypeName,
846
+ parentExtensionDataByTypeName: validParentExtensionOrphansByTypeName,
869
847
  isVersionTwo: this.isSubgraphVersionTwo,
870
848
  keyFieldNamesByParentTypeName: this.keyFieldNamesByParentTypeName,
871
- operationTypes: this.operationTypeNames,
849
+ operationTypes: this.operationTypeNodeByTypeName,
850
+ originalTypeNameByRenamedTypeName: this.originalTypeNameByRenamedTypeName,
872
851
  overridesByTargetSubgraphName: this.overridesByTargetSubgraphName,
873
852
  parentDataByTypeName: this.parentDefinitionDataByTypeName,
853
+ persistedDirectiveDefinitionDataByDirectiveName,
874
854
  subgraphAST: newAST,
875
855
  subgraphString: (0, graphql_1.print)(newAST),
876
856
  schema: (0, buildASTSchema_1.buildASTSchema)(newAST, { assumeValid: true }),
@@ -881,6 +861,7 @@ class NormalizationFactory {
881
861
  exports.NormalizationFactory = NormalizationFactory;
882
862
  function batchNormalize(subgraphs) {
883
863
  const authorizationDataByParentTypeName = new Map();
864
+ const concreteTypeNamesByAbstractTypeName = new Map();
884
865
  const entityContainerByTypeName = new Map();
885
866
  const internalSubgraphBySubgraphName = new Map();
886
867
  const allOverridesByTargetSubgraphName = new Map();
@@ -899,13 +880,14 @@ function batchNormalize(subgraphs) {
899
880
  (0, subgraph_1.recordSubgraphName)(subgraph.name, subgraphNames, nonUniqueSubgraphNames);
900
881
  }
901
882
  }
883
+ const graph = new graphology_1.MultiGraph();
902
884
  for (let i = 0; i < subgraphs.length; i++) {
903
885
  const subgraph = subgraphs[i];
904
886
  const subgraphName = subgraph.name || `subgraph-${i}-${Date.now()}`;
905
887
  if (!subgraph.name) {
906
888
  invalidNameErrorMessages.push((0, errors_1.invalidSubgraphNameErrorMessage)(i, subgraphName));
907
889
  }
908
- const { errors, normalizationResult } = normalizeSubgraph(subgraph.definitions, subgraph.name);
890
+ const { errors, normalizationResult } = normalizeSubgraph(subgraph.definitions, graph, subgraph.name);
909
891
  if (errors) {
910
892
  validationErrors.push((0, errors_1.subgraphValidationError)(subgraphName, errors));
911
893
  continue;
@@ -918,21 +900,30 @@ function batchNormalize(subgraphs) {
918
900
  for (const authorizationData of normalizationResult.authorizationDataByParentTypeName.values()) {
919
901
  (0, utils_3.upsertAuthorizationData)(authorizationDataByParentTypeName, authorizationData, invalidOrScopesHostPaths);
920
902
  }
903
+ for (const [abstractTypeName, incomingConcreteTypeNames,] of normalizationResult.concreteTypeNamesByAbstractTypeName) {
904
+ const existingConcreteTypeNames = concreteTypeNamesByAbstractTypeName.get(abstractTypeName);
905
+ if (!existingConcreteTypeNames) {
906
+ concreteTypeNamesByAbstractTypeName.set(abstractTypeName, new Set(incomingConcreteTypeNames));
907
+ continue;
908
+ }
909
+ (0, utils_3.addIterableValuesToSet)(incomingConcreteTypeNames, existingConcreteTypeNames);
910
+ }
921
911
  for (const entityContainer of normalizationResult.entityContainerByTypeName.values()) {
922
912
  (0, utils_3.upsertEntityContainer)(entityContainerByTypeName, entityContainer);
923
913
  }
924
914
  if (subgraph.name) {
925
915
  internalSubgraphBySubgraphName.set(subgraphName, {
926
- configurationDataMap: normalizationResult.configurationDataMap,
916
+ configurationDataByParentTypeName: normalizationResult.configurationDataByParentTypeName,
927
917
  definitions: normalizationResult.subgraphAST,
928
918
  entityInterfaces: normalizationResult.entityInterfaces,
929
- parentExtensionDataByTypeName: normalizationResult.parentExtensionDataByTypeName,
930
919
  keyFieldNamesByParentTypeName: normalizationResult.keyFieldNamesByParentTypeName,
931
920
  isVersionTwo: normalizationResult.isVersionTwo,
932
921
  name: subgraphName,
933
922
  operationTypes: normalizationResult.operationTypes,
934
923
  overriddenFieldNamesByParentTypeName: new Map(),
935
- parentDataByTypeName: normalizationResult.parentDataByTypeName,
924
+ parentDefinitionDataByTypeName: normalizationResult.parentDataByTypeName,
925
+ parentExtensionDataByTypeName: normalizationResult.parentExtensionDataByTypeName,
926
+ persistedDirectiveDefinitionDataByDirectiveName: normalizationResult.persistedDirectiveDefinitionDataByDirectiveName,
936
927
  schema: normalizationResult.schema,
937
928
  url: subgraph.url,
938
929
  });
@@ -943,8 +934,11 @@ function batchNormalize(subgraphs) {
943
934
  for (const [targetSubgraphName, overridesData] of normalizationResult.overridesByTargetSubgraphName) {
944
935
  const isTargetValid = subgraphNames.has(targetSubgraphName);
945
936
  for (const [parentTypeName, fieldNames] of overridesData) {
937
+ /* It's possible for a renamed root type to have a field overridden, so make sure any errors at this stage are
938
+ propagated with the original typename. */
939
+ const originalParentTypeName = normalizationResult.originalTypeNameByRenamedTypeName.get(parentTypeName) || parentTypeName;
946
940
  if (!isTargetValid) {
947
- warnings.push((0, warnings_1.invalidOverrideTargetSubgraphNameWarning)(targetSubgraphName, parentTypeName, [...fieldNames]));
941
+ warnings.push((0, warnings_1.invalidOverrideTargetSubgraphNameWarning)(targetSubgraphName, originalParentTypeName, [...fieldNames]));
948
942
  }
949
943
  else {
950
944
  const overridesData = (0, utils_3.getValueOrDefault)(allOverridesByTargetSubgraphName, targetSubgraphName, () => new Map());
@@ -952,7 +946,7 @@ function batchNormalize(subgraphs) {
952
946
  (0, utils_3.addIterableValuesToSet)(fieldNames, existingFieldNames);
953
947
  }
954
948
  for (const fieldName of fieldNames) {
955
- const fieldPath = `${parentTypeName}.${fieldName}`;
949
+ const fieldPath = `${originalParentTypeName}.${fieldName}`;
956
950
  const sourceSubgraphs = overrideSourceSubgraphNamesByFieldPath.get(fieldPath);
957
951
  if (!sourceSubgraphs) {
958
952
  overrideSourceSubgraphNamesByFieldPath.set(fieldPath, [subgraphName]);
@@ -983,8 +977,10 @@ function batchNormalize(subgraphs) {
983
977
  if (allErrors.length > 0) {
984
978
  return {
985
979
  authorizationDataByParentTypeName,
980
+ concreteTypeNamesByAbstractTypeName,
986
981
  entityContainerByTypeName,
987
982
  errors: allErrors,
983
+ graph,
988
984
  internalSubgraphBySubgraphName,
989
985
  ...(warnings.length > 0 ? { warnings } : {}),
990
986
  };
@@ -993,19 +989,21 @@ function batchNormalize(subgraphs) {
993
989
  const internalSubgraph = (0, utils_3.getOrThrowError)(internalSubgraphBySubgraphName, targetSubgraphName, 'internalSubgraphBySubgraphName');
994
990
  internalSubgraph.overriddenFieldNamesByParentTypeName = overridesData;
995
991
  for (const [parentTypeName, fieldNames] of overridesData) {
996
- const configurationData = internalSubgraph.configurationDataMap.get(parentTypeName);
992
+ const configurationData = internalSubgraph.configurationDataByParentTypeName.get(parentTypeName);
997
993
  if (!configurationData) {
998
994
  continue;
999
995
  }
1000
996
  (0, utils_3.subtractSourceSetFromTargetSet)(fieldNames, configurationData.fieldNames);
1001
997
  if (configurationData.fieldNames.size < 1) {
1002
- internalSubgraph.configurationDataMap.delete(parentTypeName);
998
+ internalSubgraph.configurationDataByParentTypeName.delete(parentTypeName);
1003
999
  }
1004
1000
  }
1005
1001
  }
1006
1002
  return {
1007
1003
  authorizationDataByParentTypeName,
1004
+ concreteTypeNamesByAbstractTypeName,
1008
1005
  entityContainerByTypeName: entityContainerByTypeName,
1006
+ graph,
1009
1007
  internalSubgraphBySubgraphName: internalSubgraphBySubgraphName,
1010
1008
  ...(warnings.length > 0 ? { warnings } : {}),
1011
1009
  };