@wundergraph/composition 0.18.4 → 0.18.5

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 +1 -1
  17. package/dist/index.js +1 -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 +7 -1
  43. package/dist/utils/constants.js +24 -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
@@ -1,43 +1,38 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.federateSubgraphs = exports.FederationFactory = void 0;
4
- const graphology_1 = require("graphology");
5
4
  const graphql_1 = require("graphql");
6
- const ast_1 = require("../ast/ast");
5
+ const ast_1 = require("../schema-building/ast");
7
6
  const utils_1 = require("../ast/utils");
8
7
  const errors_1 = require("../errors/errors");
9
- const type_merging_1 = require("../schema-building/type-merging");
10
- const utils_2 = require("./utils");
11
- const subgraph_1 = require("../subgraph/subgraph");
12
8
  const string_constants_1 = require("../utils/string-constants");
13
- const utils_3 = require("../utils/utils");
9
+ const utils_2 = require("../utils/utils");
14
10
  const merge_1 = require("@graphql-tools/merge");
15
11
  const constants_1 = require("../utils/constants");
16
12
  const normalization_factory_1 = require("../normalization/normalization-factory");
17
- const utils_4 = require("../normalization/utils");
13
+ const utils_3 = require("../normalization/utils");
14
+ const utils_4 = require("../schema-building/utils");
15
+ const walkers_1 = require("./walkers");
18
16
  class FederationFactory {
19
17
  authorizationDataByParentTypeName;
20
- abstractToConcreteTypeNames = new Map();
21
18
  areFieldsExternal = false;
22
19
  areFieldsShareable = false;
23
- argumentTypeNameSet = new Set();
20
+ concreteTypeNamesByAbstractTypeName;
24
21
  fieldConfigurationByFieldPath = new Map();
22
+ namedInputValueTypeNames = new Set();
23
+ namedOutputTypeNames = new Set();
25
24
  entityInterfaceFederationDataByTypeName;
26
25
  executableDirectives = new Set();
27
26
  parentTypeName = '';
28
- persistedDirectives = new Set([string_constants_1.DEPRECATED, string_constants_1.INACCESSIBLE, string_constants_1.TAG]);
29
27
  persistedDirectiveDefinitions = new Set([string_constants_1.AUTHENTICATED, string_constants_1.DEPRECATED, string_constants_1.INACCESSIBLE, string_constants_1.TAG, string_constants_1.REQUIRES_SCOPES]);
30
28
  currentSubgraphName = '';
31
29
  childName = '';
32
- directiveDefinitions = new Map();
33
30
  entityContainersByTypeName;
34
31
  errors = [];
35
32
  evaluatedObjectLikesBySubgraph = new Map();
36
- extensions = new Map();
37
- graph = new graphology_1.MultiGraph();
33
+ graph;
38
34
  graphEdges = new Set();
39
35
  graphPaths = new Map();
40
- inputFieldTypeNameSet = new Set();
41
36
  invalidOrScopesHostPaths = new Set();
42
37
  isCurrentParentEntity = false;
43
38
  isCurrentParentInterface = false;
@@ -45,595 +40,54 @@ class FederationFactory {
45
40
  isCurrentParentExtensionType = false;
46
41
  isParentRootType = false;
47
42
  isParentInputObject = false;
48
- keyFieldNamesByParentTypeName = new Map();
49
- outputFieldTypeNameSet = new Set();
50
- parents = new Map();
43
+ outputFieldTypeNames = new Set();
44
+ parentDefinitionDataByTypeName = new Map();
45
+ objectExtensionDataByTypeName = new Map();
46
+ persistedDirectiveDefinitionByDirectiveName = new Map([
47
+ [string_constants_1.AUTHENTICATED, constants_1.AUTHENTICATED_DEFINITION],
48
+ [string_constants_1.DEPRECATED, constants_1.DEPRECATED_DEFINITION],
49
+ [string_constants_1.INACCESSIBLE, constants_1.INACCESSIBLE_DEFINITION],
50
+ [string_constants_1.REQUIRES_SCOPES, constants_1.REQUIRES_SCOPES_DEFINITION],
51
+ [string_constants_1.TAG, constants_1.TAG_DEFINITION],
52
+ ]);
51
53
  rootTypeNames = new Set([string_constants_1.DEFAULT_MUTATION, string_constants_1.DEFAULT_QUERY, string_constants_1.DEFAULT_SUBSCRIPTION]);
52
54
  internalSubgraphBySubgraphName;
53
55
  shareableErrorTypeNames = new Map();
54
- renamedTypeNameByOriginalTypeName = new Map();
55
56
  warnings;
56
- constructor(authorizationDataByParentTypeName, entityContainersByTypeName, entityInterfaceFederationDataByTypeName, internalSubgraphBySubgraphName, warnings) {
57
+ constructor(authorizationDataByParentTypeName, concreteTypeNamesByAbstractTypeName, entityContainersByTypeName, entityInterfaceFederationDataByTypeName, graph, internalSubgraphBySubgraphName, warnings) {
57
58
  this.authorizationDataByParentTypeName = authorizationDataByParentTypeName;
59
+ this.concreteTypeNamesByAbstractTypeName = concreteTypeNamesByAbstractTypeName;
58
60
  this.entityContainersByTypeName = entityContainersByTypeName;
59
61
  this.entityInterfaceFederationDataByTypeName = entityInterfaceFederationDataByTypeName;
62
+ this.graph = graph;
60
63
  this.internalSubgraphBySubgraphName = internalSubgraphBySubgraphName;
61
64
  this.warnings = warnings || [];
62
65
  }
63
- isObjectRootType(node) {
64
- return this.rootTypeNames.has(node.name.value);
65
- }
66
- populateMultiGraphAndRenameOperations(subgraphs) {
67
- for (const subgraph of subgraphs.values()) {
68
- this.currentSubgraphName = subgraph.name;
69
- (0, subgraph_1.walkSubgraphToCollectObjectLikesAndDirectiveDefinitions)(this, subgraph);
70
- }
71
- }
72
- getEnumMergeMethod(enumName) {
73
- if (this.inputFieldTypeNameSet.has(enumName) || this.argumentTypeNameSet.has(enumName)) {
74
- if (this.outputFieldTypeNameSet.has(enumName)) {
75
- return utils_2.MergeMethod.CONSISTENT;
76
- }
77
- return utils_2.MergeMethod.INTERSECTION;
78
- }
79
- return utils_2.MergeMethod.UNION;
80
- }
81
- validateArgumentDefaultValues(argName, existingDefaultValue, newDefaultValue) {
82
- if (existingDefaultValue.kind !== newDefaultValue.kind) {
83
- // This should be caught by subgraph validation
84
- this.errors.push((0, errors_1.incompatibleArgumentDefaultValueTypeError)(argName, this.parentTypeName, this.childName, existingDefaultValue.kind, newDefaultValue.kind));
85
- }
86
- if ('value' in newDefaultValue && existingDefaultValue.value !== newDefaultValue.value) {
87
- this.errors.push((0, errors_1.incompatibleArgumentDefaultValueError)(argName, this.parentTypeName, this.childName, existingDefaultValue.value, newDefaultValue.value));
88
- }
89
- }
90
- compareAndValidateArgumentDefaultValues(existingArg, newArg) {
91
- const newDefaultValue = newArg.defaultValue;
92
- existingArg.node.defaultValue = existingArg.node.defaultValue || newDefaultValue;
93
- if (!existingArg.node.defaultValue || !newDefaultValue) {
94
- existingArg.includeDefaultValue = false;
95
- return;
96
- }
97
- const argumentName = existingArg.node.name.value;
98
- const existingDefaultValue = existingArg.node.defaultValue;
99
- switch (existingDefaultValue.kind) {
100
- case graphql_1.Kind.LIST: // TODO
101
- break;
102
- case graphql_1.Kind.NULL:
103
- break;
104
- case graphql_1.Kind.OBJECT:
105
- break;
106
- // BOOLEAN, ENUM, FLOAT, INT, and STRING intentionally fall through
107
- case graphql_1.Kind.BOOLEAN:
108
- case graphql_1.Kind.ENUM:
109
- case graphql_1.Kind.FLOAT:
110
- case graphql_1.Kind.INT:
111
- case graphql_1.Kind.STRING:
112
- this.validateArgumentDefaultValues(argumentName, existingDefaultValue, newDefaultValue);
113
- break;
114
- default:
115
- throw (0, errors_1.unexpectedArgumentKindFatalError)(argumentName, this.childName);
116
- }
117
- }
118
- upsertRequiredSubgraph(set, isRequired) {
119
- if (isRequired) {
120
- set.add(this.currentSubgraphName);
121
- }
122
- return set;
123
- }
124
- upsertExtensionPersistedDirectives(extensionDirectives, baseDirectives) {
125
- // Add unique tag directives
126
- for (const [tagValue, tagDirectiveNode] of extensionDirectives.tags) {
127
- baseDirectives.tags.set(tagValue, tagDirectiveNode);
128
- }
129
- // Push other directives
130
- for (const [directiveName, directiveNodes] of extensionDirectives.directives) {
131
- const existingDirectives = baseDirectives.directives.get(directiveName);
132
- if (!existingDirectives) {
133
- baseDirectives.directives.set(directiveName, directiveNodes);
134
- continue;
135
- }
136
- existingDirectives.push(...directiveNodes);
137
- }
138
- // If the extension has no deprecated directive, there's nothing further to do
139
- const extensionDeprecatedDirective = extensionDirectives.deprecated.directive;
140
- const extensionDeprecatedReason = extensionDirectives.deprecated.reason;
141
- if (!extensionDeprecatedDirective || !extensionDeprecatedReason) {
142
- return;
143
- }
144
- // If there is no reason or the existing reason is longer, return
145
- if (baseDirectives.deprecated.directive &&
146
- baseDirectives.deprecated.reason &&
147
- extensionDeprecatedReason.length < baseDirectives.deprecated.reason.length) {
148
- return;
149
- }
150
- // Only update if the new reason is longer
151
- baseDirectives.deprecated.directive = extensionDeprecatedDirective;
152
- baseDirectives.deprecated.reason = extensionDeprecatedReason;
153
- }
154
- upsertExtensionFieldArguments(extensionFieldArguments, baseFieldArguments) {
155
- for (const [argumentName, extensionArgumentContainer] of extensionFieldArguments) {
156
- const existingArgumentContainer = baseFieldArguments.get(argumentName);
157
- if (!existingArgumentContainer) {
158
- // If the argument doesn't exist on the base field, simply add it
159
- baseFieldArguments.set(argumentName, extensionArgumentContainer);
160
- continue;
161
- }
162
- if (extensionArgumentContainer.requiredSubgraphs.size > 0) {
163
- // If the argument is required on any extensions, add it to the base requiredSubgraphs set
164
- (0, utils_3.addIterableValuesToSet)(extensionArgumentContainer.requiredSubgraphs, existingArgumentContainer.requiredSubgraphs);
165
- }
166
- // Add the subgraphs in which the extensions' arguments are found to the base subgraphs set
167
- (0, utils_3.addIterableValuesToSet)(extensionArgumentContainer.subgraphs, existingArgumentContainer.subgraphs);
168
- // Set the most restrictive type for the argument
169
- const { typeErrors, typeNode } = (0, type_merging_1.getMostRestrictiveMergedTypeNode)(existingArgumentContainer.node.type, extensionArgumentContainer.node.type, this.childName, argumentName);
170
- if (typeNode) {
171
- existingArgumentContainer.node.type = typeNode;
172
- }
173
- else {
174
- if (!typeErrors || typeErrors.length < 2) {
175
- throw (0, errors_1.argumentTypeMergeFatalError)(argumentName, this.childName);
176
- }
177
- this.errors.push((0, errors_1.incompatibleArgumentTypesError)(argumentName, this.parentTypeName, this.childName, typeErrors[0], typeErrors[1]));
178
- }
179
- this.compareAndValidateArgumentDefaultValues(existingArgumentContainer, extensionArgumentContainer.node);
180
- this.upsertExtensionPersistedDirectives(extensionArgumentContainer.directives, existingArgumentContainer.directives);
181
- }
182
- }
183
- // TODO validation of default values
184
- upsertArguments(node, argumentMap) {
185
- if (!node.arguments) {
186
- return argumentMap;
187
- }
188
- for (const argumentNode of node.arguments) {
189
- const argName = argumentNode.name.value;
190
- const argPath = `${node.name.value}(${argName}...)`;
191
- this.argumentTypeNameSet.add((0, type_merging_1.getNamedTypeForChild)(argPath, argumentNode.type));
192
- const isRequired = (0, type_merging_1.isTypeRequired)(argumentNode.type);
193
- const existingArgumentContainer = argumentMap.get(argName);
194
- if (!existingArgumentContainer) {
195
- argumentMap.set(argName, {
196
- directives: this.extractPersistedDirectives(argumentNode.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
197
- includeDefaultValue: !!argumentNode.defaultValue,
198
- node: (0, ast_1.inputValueDefinitionNodeToMutable)(argumentNode, this.childName),
199
- requiredSubgraphs: this.upsertRequiredSubgraph(new Set(), isRequired),
200
- subgraphs: new Set([this.currentSubgraphName]),
201
- });
202
- continue;
203
- }
204
- this.extractPersistedDirectives(argumentNode.directives || [], existingArgumentContainer.directives);
205
- (0, utils_1.setLongestDescriptionForNode)(existingArgumentContainer.node, argumentNode.description);
206
- this.upsertRequiredSubgraph(existingArgumentContainer.requiredSubgraphs, isRequired);
207
- existingArgumentContainer.subgraphs.add(this.currentSubgraphName);
208
- const { typeErrors, typeNode } = (0, type_merging_1.getMostRestrictiveMergedTypeNode)(existingArgumentContainer.node.type, argumentNode.type, this.childName, argName);
209
- if (typeNode) {
210
- existingArgumentContainer.node.type = typeNode;
211
- }
212
- else {
213
- if (!typeErrors || typeErrors.length < 2) {
214
- throw (0, errors_1.argumentTypeMergeFatalError)(argName, this.childName);
215
- }
216
- this.errors.push((0, errors_1.incompatibleArgumentTypesError)(argName, this.parentTypeName, this.childName, typeErrors[0], typeErrors[1]));
217
- }
218
- this.compareAndValidateArgumentDefaultValues(existingArgumentContainer, argumentNode);
219
- }
220
- return argumentMap;
221
- }
222
- isFieldEntityKey() {
223
- const parent = this.keyFieldNamesByParentTypeName.get(this.parentTypeName);
224
- if (parent) {
225
- return parent.has(this.childName);
226
- }
227
- return false;
228
- }
229
- isFieldExternal(node) {
230
- return this.areFieldsExternal || (0, utils_1.isNodeExternal)(node);
231
- }
232
- isFieldShareable(node) {
233
- return (!this.isCurrentSubgraphVersionTwo || this.areFieldsShareable || this.isFieldEntityKey() || (0, utils_1.isNodeShareable)(node));
234
- }
235
- upsertDirectiveNode(node) {
236
- const directiveName = node.name.value;
237
- const directiveDefinition = this.directiveDefinitions.get(directiveName);
238
- if (directiveDefinition) {
239
- if (!this.executableDirectives.has(directiveName)) {
240
- return;
241
- }
242
- if ((0, utils_1.mergeExecutableDirectiveLocations)(node.locations, directiveDefinition).size < 1) {
243
- this.executableDirectives.delete(directiveName);
244
- return;
245
- }
246
- this.upsertArguments(node, directiveDefinition.arguments);
247
- (0, utils_1.setLongestDescriptionForNode)(directiveDefinition.node, node.description);
248
- directiveDefinition.node.repeatable = directiveDefinition.node.repeatable && node.repeatable;
249
- directiveDefinition.subgraphNames.add(this.currentSubgraphName);
250
- return;
251
- }
252
- const executableLocations = (0, utils_1.extractExecutableDirectiveLocations)(node.locations, new Set());
253
- this.directiveDefinitions.set(directiveName, {
254
- arguments: this.upsertArguments(node, new Map()),
255
- executableLocations,
256
- node: (0, ast_1.directiveDefinitionNodeToMutable)(node),
257
- subgraphNames: new Set([this.currentSubgraphName]),
258
- });
259
- if (executableLocations.size > 0) {
260
- this.executableDirectives.add(directiveName);
261
- }
262
- }
263
- isShareabilityOfAllFieldInstancesValid(fieldContainer) {
264
- let shareableFields = 0;
265
- let unshareableFields = 0;
266
- for (const [subgraphName, isShareable] of fieldContainer.subgraphsByShareable) {
267
- /*
268
- shareability is ignored if:
269
- 1. the field is external
270
- 2. the field is overridden by another subgraph (in which case it has not been upserted)
271
- */
272
- if (fieldContainer.subgraphsByExternal.get(subgraphName)) {
273
- continue;
274
- }
275
- if (isShareable) {
276
- if (unshareableFields) {
277
- return false;
278
- }
279
- shareableFields += 1;
280
- continue;
281
- }
282
- unshareableFields += 1;
283
- if (shareableFields || unshareableFields > 1) {
284
- return false;
285
- }
286
- }
287
- return true;
288
- }
289
- upsertFieldNode(node) {
290
- const parent = this.isCurrentParentExtensionType
291
- ? (0, utils_3.getOrThrowError)(this.extensions, this.parentTypeName, string_constants_1.EXTENSIONS)
292
- : (0, utils_3.getOrThrowError)(this.parents, this.parentTypeName, string_constants_1.PARENTS);
293
- if (parent.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION &&
294
- parent.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION &&
295
- parent.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
296
- throw (0, errors_1.unexpectedKindFatalError)(this.parentTypeName);
297
- }
298
- const fieldMap = parent.fields;
299
- const isFieldExternal = this.isFieldExternal(node);
300
- const isFieldShareable = this.isFieldShareable(node);
301
- const fieldPath = `${this.parentTypeName}.${this.childName}`;
302
- const fieldRootTypeName = (0, type_merging_1.getNamedTypeForChild)(fieldPath, node.type);
303
- const existingFieldContainer = fieldMap.get(this.childName);
304
- if (existingFieldContainer) {
305
- this.extractPersistedDirectives(node.directives || [], existingFieldContainer.directives);
306
- (0, utils_1.setLongestDescriptionForNode)(existingFieldContainer.node, node.description);
307
- existingFieldContainer.subgraphNames.add(this.currentSubgraphName);
308
- existingFieldContainer.subgraphsByShareable.set(this.currentSubgraphName, isFieldShareable);
309
- existingFieldContainer.subgraphsByExternal.set(this.currentSubgraphName, isFieldExternal);
310
- const { typeErrors, typeNode } = (0, type_merging_1.getLeastRestrictiveMergedTypeNode)(existingFieldContainer.node.type, node.type, this.parentTypeName, this.childName);
311
- if (typeNode) {
312
- existingFieldContainer.node.type = typeNode;
313
- }
314
- else {
315
- if (!typeErrors || typeErrors.length < 2) {
316
- throw (0, errors_1.fieldTypeMergeFatalError)(this.childName);
317
- }
318
- this.errors.push((0, errors_1.incompatibleChildTypesError)(this.parentTypeName, this.childName, typeErrors[0], typeErrors[1]));
319
- }
320
- this.upsertArguments(node, existingFieldContainer.arguments);
321
- /* A field is valid if one of the following is true:
322
- 1. The field is an interface
323
- 2. The field is external
324
- 3. Non-external fields are ALL shareable
325
- 4. All other fields besides the current field are external
326
- */
327
- if (this.isCurrentParentInterface ||
328
- isFieldExternal ||
329
- (existingFieldContainer.isShareable && isFieldShareable) ||
330
- this.isShareabilityOfAllFieldInstancesValid(existingFieldContainer) ||
331
- this.entityInterfaceFederationDataByTypeName.has(this.parentTypeName) // TODO handle shareability with interfaceObjects
332
- ) {
333
- return;
334
- }
335
- const shareableErrorTypeNames = this.shareableErrorTypeNames.get(this.parentTypeName);
336
- if (shareableErrorTypeNames) {
337
- shareableErrorTypeNames.add(this.childName);
338
- }
339
- else {
340
- this.shareableErrorTypeNames.set(this.parentTypeName, new Set([this.childName]));
341
- }
342
- return;
343
- }
344
- this.outputFieldTypeNameSet.add(fieldRootTypeName);
345
- fieldMap.set(this.childName, {
346
- arguments: this.upsertArguments(node, new Map()),
347
- directives: this.extractPersistedDirectives(node.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
348
- isShareable: isFieldShareable,
349
- node: (0, ast_1.fieldDefinitionNodeToMutable)(node, this.parentTypeName),
350
- namedTypeName: fieldRootTypeName,
351
- subgraphNames: new Set([this.currentSubgraphName]),
352
- subgraphsByShareable: new Map([[this.currentSubgraphName, isFieldShareable]]),
353
- subgraphsByExternal: new Map([[this.currentSubgraphName, isFieldExternal]]),
354
- });
355
- }
356
- upsertValueNode(node) {
357
- const parent = this.parents.get(this.parentTypeName);
358
- switch (node.kind) {
359
- case graphql_1.Kind.ENUM_VALUE_DEFINITION:
360
- if (!parent) {
361
- // This should never happen
362
- throw (0, errors_1.federationInvalidParentTypeError)(this.parentTypeName, this.childName);
363
- }
364
- if (parent.kind !== graphql_1.Kind.ENUM_TYPE_DEFINITION) {
365
- throw (0, errors_1.incompatibleParentKindFatalError)(this.parentTypeName, graphql_1.Kind.ENUM_TYPE_DEFINITION, parent.kind);
366
- }
367
- const enumValues = parent.values;
368
- const enumValueContainer = enumValues.get(this.childName);
369
- if (enumValueContainer) {
370
- this.extractPersistedDirectives(node.directives || [], enumValueContainer.directives);
371
- (0, utils_1.setLongestDescriptionForNode)(enumValueContainer.node, node.description);
372
- enumValueContainer.appearances += 1;
373
- return;
374
- }
375
- enumValues.set(this.childName, {
376
- appearances: 1,
377
- directives: this.extractPersistedDirectives(node.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
378
- node: (0, ast_1.enumValueDefinitionNodeToMutable)(node),
379
- });
380
- return;
381
- case graphql_1.Kind.INPUT_VALUE_DEFINITION:
382
- if (!parent || !this.isParentInputObject) {
383
- // these are arguments to a directive
384
- return;
385
- }
386
- if (parent.kind !== graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION) {
387
- throw (0, errors_1.incompatibleParentKindFatalError)(this.parentTypeName, graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION, parent.kind);
388
- }
389
- const inputValues = parent.fields;
390
- const inputValueContainer = inputValues.get(this.childName);
391
- if (inputValueContainer) {
392
- this.extractPersistedDirectives(node.directives || [], inputValueContainer.directives);
393
- inputValueContainer.appearances += 1;
394
- (0, utils_1.setLongestDescriptionForNode)(inputValueContainer.node, node.description);
395
- const { typeErrors, typeNode } = (0, type_merging_1.getMostRestrictiveMergedTypeNode)(inputValueContainer.node.type, node.type, this.parentTypeName, this.childName);
396
- if (typeNode) {
397
- inputValueContainer.node.type = typeNode;
398
- }
399
- else {
400
- if (!typeErrors || typeErrors.length < 2) {
401
- throw (0, errors_1.fieldTypeMergeFatalError)(this.childName);
402
- }
403
- this.errors.push((0, errors_1.incompatibleChildTypesError)(this.parentTypeName, this.childName, typeErrors[0], typeErrors[1]));
404
- }
405
- return;
406
- }
407
- const valuePath = `${this.parentTypeName}.${this.childName}`;
408
- const inputValueNamedType = (0, type_merging_1.getNamedTypeForChild)(valuePath, node.type);
409
- this.inputFieldTypeNameSet.add(inputValueNamedType);
410
- inputValues.set(this.childName, {
411
- appearances: 1,
412
- directives: this.extractPersistedDirectives(node.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
413
- includeDefaultValue: !!node.defaultValue,
414
- node: (0, ast_1.inputValueDefinitionNodeToMutable)(node, this.parentTypeName),
415
- });
416
- return;
417
- default:
418
- throw (0, errors_1.unexpectedKindFatalError)(this.childName);
419
- }
420
- }
421
- upsertInterfaceObjectParentNode(node) {
422
- const parentTypeName = node.name.value;
423
- const parent = this.parents.get(parentTypeName);
424
- if (parent) {
425
- if (parent.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION) {
426
- throw (0, errors_1.incompatibleParentKindFatalError)(parentTypeName, node.kind, parent.kind);
427
- }
428
- (0, utils_1.setLongestDescriptionForNode)(parent.node, node.description);
429
- this.extractPersistedDirectives(node.directives || [], parent.directives);
430
- (0, utils_1.extractInterfaces)(node, parent.interfaces);
431
- parent.subgraphNames.add(this.currentSubgraphName);
432
- return;
433
- }
434
- this.parents.set(parentTypeName, {
435
- directives: this.extractPersistedDirectives(node.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
436
- fields: new Map(),
437
- interfaces: (0, utils_1.extractInterfaces)(node, new Set()),
438
- kind: graphql_1.Kind.INTERFACE_TYPE_DEFINITION,
439
- node: (0, ast_1.interfaceTypeDefinitionNodeToMutable)({
440
- ...node,
441
- kind: graphql_1.Kind.INTERFACE_TYPE_DEFINITION,
442
- }),
443
- subgraphNames: new Set([this.currentSubgraphName]),
444
- });
445
- }
446
- upsertParentNode(node) {
447
- const parentTypeName = node.name.value;
448
- const parent = this.parents.get(parentTypeName);
449
- if (parent) {
450
- (0, utils_1.setLongestDescriptionForNode)(parent.node, node.description);
451
- this.extractPersistedDirectives(node.directives || [], parent.directives);
452
- }
453
- switch (node.kind) {
454
- case graphql_1.Kind.ENUM_TYPE_DEFINITION:
455
- if (parent) {
456
- if (parent.kind !== node.kind) {
457
- throw (0, errors_1.incompatibleParentKindFatalError)(parentTypeName, node.kind, parent.kind);
458
- }
459
- parent.appearances += 1;
460
- return;
461
- }
462
- this.parents.set(parentTypeName, {
463
- appearances: 1,
464
- directives: this.extractPersistedDirectives(node.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
465
- values: new Map(),
466
- kind: node.kind,
467
- node: (0, ast_1.enumTypeDefinitionNodeToMutable)(node),
468
- });
469
- return;
470
- case graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
471
- if (parent) {
472
- if (parent.kind !== node.kind) {
473
- throw (0, errors_1.incompatibleParentKindFatalError)(parentTypeName, node.kind, parent.kind);
474
- }
475
- parent.appearances += 1;
476
- return;
477
- }
478
- this.parents.set(parentTypeName, {
479
- appearances: 1,
480
- directives: this.extractPersistedDirectives(node.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
481
- fields: new Map(),
482
- kind: node.kind,
483
- node: (0, ast_1.inputObjectTypeDefinitionNodeToMutable)(node),
484
- });
485
- return;
486
- case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
487
- if (parent) {
488
- if (parent.kind !== node.kind) {
489
- throw (0, errors_1.incompatibleParentKindFatalError)(parentTypeName, node.kind, parent.kind);
490
- }
491
- (0, utils_1.extractInterfaces)(node, parent.interfaces);
492
- parent.subgraphNames.add(this.currentSubgraphName);
493
- return;
494
- }
495
- this.parents.set(parentTypeName, {
496
- directives: this.extractPersistedDirectives(node.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
497
- fields: new Map(),
498
- interfaces: (0, utils_1.extractInterfaces)(node, new Set()),
499
- kind: node.kind,
500
- node: (0, ast_1.interfaceTypeDefinitionNodeToMutable)(node),
501
- subgraphNames: new Set([this.currentSubgraphName]),
502
- });
503
- return;
504
- case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
505
- if (parent) {
506
- if (parent.kind !== node.kind) {
507
- throw (0, errors_1.incompatibleParentKindFatalError)(parentTypeName, node.kind, parent.kind);
508
- }
509
- return;
510
- }
511
- this.parents.set(parentTypeName, {
512
- directives: this.extractPersistedDirectives(node.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
513
- kind: node.kind,
514
- node: (0, ast_1.scalarTypeDefinitionNodeToMutable)(node),
515
- });
516
- return;
517
- case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
518
- if (parent) {
519
- if (parent.kind !== node.kind) {
520
- throw (0, errors_1.incompatibleParentKindFatalError)(parentTypeName, node.kind, parent.kind);
521
- }
522
- (0, utils_1.extractInterfaces)(node, parent.interfaces);
523
- parent.subgraphNames.add(this.currentSubgraphName);
524
- return;
525
- }
526
- this.parents.set(parentTypeName, {
527
- directives: this.extractPersistedDirectives(node.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
528
- fields: new Map(),
529
- interfaces: (0, utils_1.extractInterfaces)(node, new Set()),
530
- isRootType: this.isParentRootType,
531
- kind: node.kind,
532
- node: (0, ast_1.objectTypeDefinitionNodeToMutable)(node),
533
- subgraphNames: new Set([this.currentSubgraphName]),
534
- });
535
- return;
536
- case graphql_1.Kind.UNION_TYPE_DEFINITION:
537
- if (parent) {
538
- if (parent.kind !== node.kind) {
539
- throw (0, errors_1.incompatibleParentKindFatalError)(parentTypeName, node.kind, parent.kind);
540
- }
541
- if (!node.types || node.types.length < 1) {
542
- this.errors.push((0, errors_1.invalidUnionError)(parent.node.name.value));
543
- return;
544
- }
545
- node.types?.forEach((member) => parent.members.add(member.name.value));
546
- return;
547
- }
548
- this.parents.set(parentTypeName, {
549
- directives: this.extractPersistedDirectives(node.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
550
- kind: node.kind,
551
- members: new Set(node.types?.map((member) => member.name.value)),
552
- node: (0, ast_1.unionTypeDefinitionNodeToMutable)(node),
553
- });
554
- return;
555
- }
556
- }
557
- upsertExtensionNode(node) {
558
- const extension = this.extensions.get(this.parentTypeName);
559
- if (extension) {
560
- if (extension.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
561
- throw (0, errors_1.incompatibleParentKindFatalError)(this.parentTypeName, graphql_1.Kind.OBJECT_TYPE_EXTENSION, extension.kind);
562
- }
563
- extension.subgraphNames.add(this.currentSubgraphName);
564
- (0, utils_1.extractInterfaces)(node, extension.interfaces);
565
- this.extractPersistedDirectives(node.directives || [], extension.directives);
566
- return;
567
- }
568
- // build a new extension
569
- const interfaces = (0, utils_1.extractInterfaces)(node, new Set());
570
- this.extensions.set(this.parentTypeName, {
571
- directives: this.extractPersistedDirectives(node.directives || [], (0, utils_2.newPersistedDirectivesContainer)()),
572
- fields: new Map(),
573
- interfaces,
574
- isRootType: this.isParentRootType,
575
- kind: graphql_1.Kind.OBJECT_TYPE_EXTENSION,
576
- node: (0, ast_1.objectTypeExtensionNodeToMutable)(node),
577
- subgraphNames: new Set([this.currentSubgraphName]),
578
- });
579
- }
580
- isTypeValidImplementation(originalType, implementationType) {
581
- if (originalType.kind === graphql_1.Kind.NON_NULL_TYPE) {
582
- if (implementationType.kind !== graphql_1.Kind.NON_NULL_TYPE) {
583
- return false;
584
- }
585
- return this.isTypeValidImplementation(originalType.type, implementationType.type);
586
- }
587
- if (implementationType.kind === graphql_1.Kind.NON_NULL_TYPE) {
588
- return this.isTypeValidImplementation(originalType, implementationType.type);
589
- }
590
- switch (originalType.kind) {
591
- case graphql_1.Kind.NAMED_TYPE:
592
- if (implementationType.kind === graphql_1.Kind.NAMED_TYPE) {
593
- const originalTypeName = originalType.name.value;
594
- const implementationTypeName = implementationType.name.value;
595
- if (originalTypeName === implementationTypeName) {
596
- return true;
597
- }
598
- const concreteTypes = this.abstractToConcreteTypeNames.get(originalTypeName);
599
- if (!concreteTypes) {
600
- return false;
601
- }
602
- return concreteTypes.has(implementationTypeName);
603
- }
604
- return false;
605
- default:
606
- if (implementationType.kind === graphql_1.Kind.LIST_TYPE) {
607
- return this.isTypeValidImplementation(originalType.type, implementationType.type);
608
- }
609
- return false;
610
- }
611
- }
612
- getAndValidateImplementedInterfaces(container) {
66
+ getValidImplementedInterfaces(data) {
613
67
  const interfaces = [];
614
- if (container.interfaces.size < 1) {
68
+ if (data.implementedInterfaceTypeNames.size < 1) {
615
69
  return interfaces;
616
70
  }
617
71
  const implementationErrorsMap = new Map();
618
- for (const interfaceName of container.interfaces) {
72
+ for (const interfaceName of data.implementedInterfaceTypeNames) {
619
73
  interfaces.push((0, utils_1.stringToNamedTypeNode)(interfaceName));
620
- const interfaceContainer = this.parents.get(interfaceName);
621
- if (!interfaceContainer) {
74
+ const interfaceData = this.parentDefinitionDataByTypeName.get(interfaceName);
75
+ if (!interfaceData) {
622
76
  this.errors.push((0, errors_1.undefinedTypeError)(interfaceName));
623
77
  continue;
624
78
  }
625
- if (interfaceContainer.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION) {
626
- throw (0, errors_1.incompatibleParentKindFatalError)(interfaceName, graphql_1.Kind.INTERFACE_TYPE_DEFINITION, interfaceContainer.kind);
79
+ if (interfaceData.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION) {
80
+ throw (0, errors_1.incompatibleParentKindFatalError)(interfaceName, graphql_1.Kind.INTERFACE_TYPE_DEFINITION, interfaceData.kind);
627
81
  }
628
82
  const implementationErrors = {
629
83
  invalidFieldImplementations: new Map(),
630
84
  unimplementedFields: [],
631
85
  };
632
86
  let hasErrors = false;
633
- for (const [fieldName, interfaceField] of interfaceContainer.fields) {
87
+ for (const [fieldName, interfaceField] of interfaceData.fieldDataByFieldName) {
634
88
  let hasNestedErrors = false;
635
- const containerField = container.fields.get(fieldName);
636
- if (!containerField) {
89
+ const fieldData = data.fieldDataByFieldName.get(fieldName);
90
+ if (!fieldData) {
637
91
  hasErrors = true;
638
92
  implementationErrors.unimplementedFields.push(fieldName);
639
93
  continue;
@@ -645,25 +99,25 @@ class FederationFactory {
645
99
  unimplementedArguments: new Set(),
646
100
  };
647
101
  // The implemented field type must be equally or more restrictive than the original interface field type
648
- if (!this.isTypeValidImplementation(interfaceField.node.type, containerField.node.type)) {
102
+ if (!(0, utils_4.isTypeValidImplementation)(interfaceField.node.type, fieldData.node.type, this.concreteTypeNamesByAbstractTypeName)) {
649
103
  hasErrors = true;
650
104
  hasNestedErrors = true;
651
- invalidFieldImplementation.implementedResponseType = (0, merge_1.printTypeNode)(containerField.node.type);
105
+ invalidFieldImplementation.implementedResponseType = (0, merge_1.printTypeNode)(fieldData.node.type);
652
106
  }
653
107
  const handledArguments = new Set();
654
- for (const [argumentName, inputValueContainer] of interfaceField.arguments) {
655
- const interfaceArgument = inputValueContainer.node;
108
+ for (const [argumentName, inputValueData] of interfaceField.argumentDataByArgumentName) {
109
+ const interfaceArgument = inputValueData.node;
656
110
  handledArguments.add(argumentName);
657
- const containerArgument = containerField.arguments.get(argumentName)?.node;
111
+ const argumentNode = fieldData.argumentDataByArgumentName.get(argumentName)?.node;
658
112
  // The type implementing the interface must include all arguments with no variation for that argument
659
- if (!containerArgument) {
113
+ if (!argumentNode) {
660
114
  hasErrors = true;
661
115
  hasNestedErrors = true;
662
116
  invalidFieldImplementation.unimplementedArguments.add(argumentName);
663
117
  continue;
664
118
  }
665
119
  // Implemented arguments should be the exact same type
666
- const actualType = (0, merge_1.printTypeNode)(containerArgument.type);
120
+ const actualType = (0, merge_1.printTypeNode)(argumentNode.type);
667
121
  const expectedType = (0, merge_1.printTypeNode)(interfaceArgument.type);
668
122
  if (expectedType !== actualType) {
669
123
  hasErrors = true;
@@ -672,7 +126,7 @@ class FederationFactory {
672
126
  }
673
127
  }
674
128
  // Additional arguments must be optional (nullable)
675
- for (const [argumentName, inputValueContainer] of containerField.arguments) {
129
+ for (const [argumentName, inputValueContainer] of fieldData.argumentDataByArgumentName) {
676
130
  const argumentNode = inputValueContainer.node;
677
131
  if (handledArguments.has(argumentName)) {
678
132
  continue;
@@ -693,168 +147,10 @@ class FederationFactory {
693
147
  }
694
148
  }
695
149
  if (implementationErrorsMap.size) {
696
- this.errors.push((0, errors_1.unimplementedInterfaceFieldsError)(container.node.name.value, (0, utils_3.kindToTypeString)(container.kind), implementationErrorsMap));
150
+ this.errors.push((0, errors_1.unimplementedInterfaceFieldsError)(data.node.name.value, (0, utils_2.kindToTypeString)(data.kind), implementationErrorsMap));
697
151
  }
698
152
  return interfaces;
699
153
  }
700
- mergeArguments(container, args, errors, argumentNames) {
701
- for (const argumentContainer of container.arguments.values()) {
702
- const missingSubgraphs = (0, utils_3.getEntriesNotInHashSet)(container.subgraphNames, argumentContainer.subgraphs);
703
- const argumentName = argumentContainer.node.name.value;
704
- if (missingSubgraphs.length > 0) {
705
- // Required arguments must be defined in all subgraphs that define the field
706
- if (argumentContainer.requiredSubgraphs.size > 0) {
707
- errors.push({
708
- argumentName,
709
- missingSubgraphs,
710
- requiredSubgraphs: [...argumentContainer.requiredSubgraphs],
711
- });
712
- }
713
- // If the argument is always optional, but it's not defined in all subgraphs that define the field,
714
- // the argument should not be included in the federated graph
715
- continue;
716
- }
717
- argumentContainer.node.defaultValue = argumentContainer.includeDefaultValue
718
- ? argumentContainer.node.defaultValue
719
- : undefined;
720
- args.push((0, utils_1.pushPersistedDirectivesAndGetNode)(argumentContainer));
721
- if (argumentNames) {
722
- argumentNames.push(argumentName);
723
- }
724
- }
725
- }
726
- addValidExecutableDirectiveDefinition(directiveName, directiveContainer, definitions) {
727
- if (!this.executableDirectives.has(directiveName)) {
728
- return;
729
- }
730
- if (this.internalSubgraphBySubgraphName.size !== directiveContainer.subgraphNames.size) {
731
- return;
732
- }
733
- directiveContainer.node.locations = (0, utils_1.setToNameNodeArray)(directiveContainer.executableLocations);
734
- if (!directiveContainer.arguments) {
735
- definitions.push(directiveContainer.node);
736
- return;
737
- }
738
- const args = [];
739
- const errors = [];
740
- this.mergeArguments(directiveContainer, args, errors);
741
- if (errors.length > 0) {
742
- this.errors.push((0, errors_1.invalidRequiredArgumentsError)(string_constants_1.DIRECTIVE_DEFINITION, directiveName, errors));
743
- return;
744
- }
745
- directiveContainer.node.arguments = args;
746
- definitions.push(directiveContainer.node);
747
- }
748
- pushAuthorizationDirectives(fieldContainer, parentTypeName) {
749
- const authorizationData = this.authorizationDataByParentTypeName.get(parentTypeName);
750
- if (!authorizationData) {
751
- return;
752
- }
753
- const fieldAuthorizationData = authorizationData.fieldAuthorizationDataByFieldName.get(fieldContainer.node.name.value);
754
- if (!fieldAuthorizationData) {
755
- return;
756
- }
757
- if (fieldAuthorizationData.requiresAuthentication) {
758
- fieldContainer.directives.directives.set(string_constants_1.AUTHENTICATED, [(0, utils_3.generateSimpleDirective)(string_constants_1.AUTHENTICATED)]);
759
- }
760
- if (fieldAuthorizationData.requiredScopes.length > 0) {
761
- fieldContainer.directives.directives.set(string_constants_1.REQUIRES_SCOPES, [
762
- (0, utils_3.generateRequiresScopesDirective)(fieldAuthorizationData.requiredScopes),
763
- ]);
764
- }
765
- }
766
- getMergedFieldDefinitionNode(fieldContainer, parentTypeName) {
767
- this.pushAuthorizationDirectives(fieldContainer, parentTypeName);
768
- (0, utils_1.pushPersistedDirectivesAndGetNode)(fieldContainer);
769
- if (fieldContainer.arguments.size < 1) {
770
- return fieldContainer.node;
771
- }
772
- const fieldName = fieldContainer.node.name.value;
773
- const fieldPath = `${parentTypeName}.${fieldName}`;
774
- const args = [];
775
- const errors = [];
776
- const argumentNames = [];
777
- this.mergeArguments(fieldContainer, args, errors, argumentNames);
778
- if (errors.length > 0) {
779
- this.errors.push((0, errors_1.invalidRequiredArgumentsError)(string_constants_1.FIELD, fieldPath, errors));
780
- }
781
- else if (argumentNames.length > 0) {
782
- this.fieldConfigurationByFieldPath.set(`${parentTypeName}.${fieldName}`, {
783
- argumentNames,
784
- fieldName,
785
- typeName: parentTypeName,
786
- });
787
- }
788
- fieldContainer.node.arguments = args;
789
- return fieldContainer.node;
790
- }
791
- // the deprecated directive with the longest reason is kept
792
- upsertDeprecatedDirective(directive, deprecatedDirectiveContainer) {
793
- if (!directive.arguments || directive.arguments.length < 1) {
794
- deprecatedDirectiveContainer.directive = directive;
795
- return;
796
- }
797
- if (directive.arguments.length !== 1) {
798
- this.errors.push(errors_1.invalidDeprecatedDirectiveError);
799
- return;
800
- }
801
- const reasonArgument = directive.arguments[0].value;
802
- if (reasonArgument.kind !== graphql_1.Kind.STRING) {
803
- this.errors.push(errors_1.invalidDeprecatedDirectiveError);
804
- return;
805
- }
806
- if (deprecatedDirectiveContainer.reason &&
807
- reasonArgument.value.length < deprecatedDirectiveContainer.reason.length) {
808
- return;
809
- }
810
- deprecatedDirectiveContainer.reason = reasonArgument.value;
811
- deprecatedDirectiveContainer.directive = directive;
812
- }
813
- // tags with the same name string are merged
814
- mergeTagDirectives(directive, map) {
815
- // the directive has been validated in the normalizer
816
- if (!directive.arguments || directive.arguments.length !== 1) {
817
- this.errors.push(errors_1.invalidTagDirectiveError); // should never happen
818
- return;
819
- }
820
- const nameArgument = directive.arguments[0].value;
821
- if (nameArgument.kind !== graphql_1.Kind.STRING) {
822
- this.errors.push(errors_1.invalidTagDirectiveError); // should never happen
823
- return;
824
- }
825
- map.set(nameArgument.value, directive);
826
- }
827
- extractPersistedDirectives(directives, container) {
828
- if (directives.length < 1) {
829
- return container;
830
- }
831
- for (const directive of directives) {
832
- const directiveName = directive.name.value;
833
- if (!this.persistedDirectives.has(directiveName)) {
834
- continue;
835
- }
836
- if (directiveName == string_constants_1.DEPRECATED) {
837
- this.upsertDeprecatedDirective(directive, container.deprecated);
838
- continue;
839
- }
840
- if (directiveName === string_constants_1.TAG) {
841
- this.mergeTagDirectives(directive, container.tags);
842
- continue;
843
- }
844
- const existingDirectives = container.directives.get(directiveName);
845
- if (!existingDirectives) {
846
- container.directives.set(directiveName, [directive]);
847
- continue;
848
- }
849
- // Naïvely ignore non-repeatable directives
850
- const definition = (0, utils_3.getOrThrowError)(this.directiveDefinitions, directiveName, 'directiveDefinitions');
851
- if (!definition.node.repeatable) {
852
- continue;
853
- }
854
- existingDirectives.push(directive);
855
- }
856
- return container;
857
- }
858
154
  isFieldResolvableByEntityAncestor(entityAncestors, fieldSubgraphs, parentTypeName) {
859
155
  if (!this.graph.hasNode(parentTypeName)) {
860
156
  return false;
@@ -865,11 +161,11 @@ class FederationFactory {
865
161
  return true;
866
162
  }
867
163
  if (entityAncestorName === parentTypeName) {
868
- const hasOverlap = (0, utils_3.doSetsHaveAnyOverlap)(fieldSubgraphs, (0, utils_3.getOrThrowError)(this.entityContainersByTypeName, entityAncestorName, string_constants_1.ENTITIES).subgraphNames);
164
+ const hasOverlap = (0, utils_2.doSetsHaveAnyOverlap)(fieldSubgraphs, (0, utils_2.getOrThrowError)(this.entityContainersByTypeName, entityAncestorName, string_constants_1.ENTITIES).subgraphNames);
869
165
  this.graphPaths.set(path, hasOverlap);
870
166
  return hasOverlap;
871
167
  }
872
- if ((0, utils_3.hasSimplePath)(this.graph, entityAncestorName, parentTypeName)) {
168
+ if ((0, utils_2.hasSimplePath)(this.graph, entityAncestorName, parentTypeName)) {
873
169
  this.graphPaths.set(path, true);
874
170
  return true;
875
171
  }
@@ -887,22 +183,8 @@ class FederationFactory {
887
183
  }
888
184
  return false;
889
185
  }
890
- isFieldExternalInAllMutualSubgraphs(subgraphs, fieldContainer) {
891
- const mutualSubgraphs = (0, utils_3.getAllMutualEntries)(subgraphs, fieldContainer.subgraphNames);
892
- if (mutualSubgraphs.size < 1) {
893
- return false;
894
- }
895
- for (const mutualSubgraph of mutualSubgraphs) {
896
- const isExternal = fieldContainer.subgraphsByExternal.get(mutualSubgraph);
897
- if (isExternal) {
898
- continue;
899
- }
900
- return false;
901
- }
902
- return true;
903
- }
904
186
  updateEvaluatedSubgraphOccurrences(rootTypeFieldSubgraphs, objectSubgraphs, entityAncestors, parentTypeName) {
905
- const mutualSubgraphs = (0, utils_3.getAllMutualEntries)(rootTypeFieldSubgraphs, objectSubgraphs);
187
+ const mutualSubgraphs = (0, utils_2.getAllMutualEntries)(rootTypeFieldSubgraphs, objectSubgraphs);
906
188
  if (mutualSubgraphs.size > 0) {
907
189
  for (const mutualSubgraph of mutualSubgraphs) {
908
190
  const evaluatedObjects = this.evaluatedObjectLikesBySubgraph.get(mutualSubgraph);
@@ -914,23 +196,23 @@ class FederationFactory {
914
196
  }
915
197
  }
916
198
  }
917
- for (const entityAncestor of entityAncestors) {
918
- const entityContainer = (0, utils_3.getOrThrowError)(this.parents, entityAncestor, string_constants_1.PARENTS);
919
- const mutualEntityAncestorRootTypeFieldSubgraphs = (0, utils_3.getAllMutualEntries)(rootTypeFieldSubgraphs, entityContainer.subgraphNames);
920
- const mutualEntityAncestorSubgraphs = (0, utils_3.getAllMutualEntries)(mutualEntityAncestorRootTypeFieldSubgraphs, objectSubgraphs);
921
- for (const mutualSubgraph of mutualEntityAncestorSubgraphs) {
922
- const objects = this.evaluatedObjectLikesBySubgraph.get(mutualSubgraph);
199
+ for (const entityAncestorTypeName of entityAncestors) {
200
+ const entityContainer = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, entityAncestorTypeName, 'parentDefinitionDataByTypeName');
201
+ const mutualEntityAncestorRootTypeFieldSubgraphs = (0, utils_2.getAllMutualEntries)(rootTypeFieldSubgraphs, entityContainer.subgraphNames);
202
+ const mutualEntityAncestorSubgraphsNames = (0, utils_2.getAllMutualEntries)(mutualEntityAncestorRootTypeFieldSubgraphs, objectSubgraphs);
203
+ for (const mutualSubgraphName of mutualEntityAncestorSubgraphsNames) {
204
+ const objects = this.evaluatedObjectLikesBySubgraph.get(mutualSubgraphName);
923
205
  if (objects) {
924
206
  objects.add(parentTypeName);
925
207
  }
926
208
  else {
927
- this.evaluatedObjectLikesBySubgraph.set(mutualSubgraph, new Set([parentTypeName]));
209
+ this.evaluatedObjectLikesBySubgraph.set(mutualSubgraphName, new Set([parentTypeName]));
928
210
  }
929
211
  }
930
212
  }
931
213
  }
932
- evaluateResolvabilityOfObject(parentContainer, rootTypeFieldData, currentFieldPath, evaluatedObjectLikes, entityAncestors, isParentAbstract = false) {
933
- const parentTypeName = parentContainer.node.name.value;
214
+ evaluateResolvabilityOfObject(objectData, rootTypeFieldData, currentFieldPath, evaluatedObjectLikes, entityAncestors, isParentAbstract = false) {
215
+ const parentTypeName = objectData.name;
934
216
  if (evaluatedObjectLikes.has(parentTypeName)) {
935
217
  return;
936
218
  }
@@ -938,68 +220,68 @@ class FederationFactory {
938
220
  evaluatedObjectLikes.add(parentTypeName);
939
221
  return;
940
222
  }
941
- for (const [fieldName, fieldContainer] of parentContainer.fields) {
942
- const fieldNamedTypeName = fieldContainer.namedTypeName;
943
- if (string_constants_1.ROOT_TYPES.has(fieldNamedTypeName)) {
223
+ for (const [fieldName, fieldData] of objectData.fieldDataByFieldName) {
224
+ const namedFieldTypeName = fieldData.namedTypeName;
225
+ if (string_constants_1.ROOT_TYPES.has(namedFieldTypeName)) {
944
226
  continue;
945
227
  }
946
228
  // Avoid an infinite loop with self-referential objects
947
- if (evaluatedObjectLikes.has(fieldNamedTypeName)) {
229
+ if (evaluatedObjectLikes.has(namedFieldTypeName)) {
948
230
  continue;
949
231
  }
950
- if (this.isFieldExternalInAllMutualSubgraphs(rootTypeFieldData.subgraphs, fieldContainer)) {
232
+ if ((0, utils_4.isFieldExternalInAllMutualSubgraphs)(rootTypeFieldData.subgraphs, fieldData)) {
951
233
  continue;
952
234
  }
953
- this.updateEvaluatedSubgraphOccurrences(rootTypeFieldData.subgraphs, parentContainer.subgraphNames, entityAncestors, parentTypeName);
235
+ this.updateEvaluatedSubgraphOccurrences(rootTypeFieldData.subgraphs, objectData.subgraphNames, entityAncestors, parentTypeName);
954
236
  evaluatedObjectLikes.add(parentTypeName);
955
- const isFieldResolvable = (0, utils_3.doSetsHaveAnyOverlap)(rootTypeFieldData.subgraphs, fieldContainer.subgraphNames) ||
956
- this.isFieldResolvableByEntityAncestor(entityAncestors, fieldContainer.subgraphNames, parentTypeName);
237
+ const isFieldResolvable = (0, utils_2.doSetsHaveAnyOverlap)(rootTypeFieldData.subgraphs, fieldData.subgraphNames) ||
238
+ this.isFieldResolvableByEntityAncestor(entityAncestors, fieldData.subgraphNames, parentTypeName);
957
239
  const newCurrentFieldPath = currentFieldPath + (isParentAbstract ? ' ' : '.') + fieldName;
958
- const entity = this.entityContainersByTypeName.get(fieldNamedTypeName);
240
+ const entity = this.entityContainersByTypeName.get(namedFieldTypeName);
959
241
  if (isFieldResolvable) {
960
242
  // The base scalars are not in this.parentMap
961
- if (constants_1.BASE_SCALARS.has(fieldNamedTypeName)) {
243
+ if (constants_1.BASE_SCALARS.has(namedFieldTypeName)) {
962
244
  continue;
963
245
  }
964
- const childContainer = (0, utils_3.getOrThrowError)(this.parents, fieldNamedTypeName, string_constants_1.PARENTS);
965
- switch (childContainer.kind) {
246
+ const namedTypeData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, namedFieldTypeName, 'parentDefinitionDataByTypeName');
247
+ switch (namedTypeData.kind) {
966
248
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
967
249
  // intentional fallthrough
968
250
  case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
969
251
  continue;
970
252
  case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
971
- this.evaluateResolvabilityOfObject(childContainer, rootTypeFieldData, newCurrentFieldPath, evaluatedObjectLikes, entity ? [...entityAncestors, fieldNamedTypeName] : [...entityAncestors]);
253
+ this.evaluateResolvabilityOfObject(namedTypeData, rootTypeFieldData, newCurrentFieldPath, evaluatedObjectLikes, entity ? [...entityAncestors, namedFieldTypeName] : [...entityAncestors]);
972
254
  continue;
973
255
  case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
974
256
  // intentional fallthrough
975
257
  case graphql_1.Kind.UNION_TYPE_DEFINITION:
976
- this.evaluateResolvabilityOfAbstractType(fieldNamedTypeName, childContainer.kind, rootTypeFieldData, newCurrentFieldPath, evaluatedObjectLikes, entity ? [...entityAncestors, fieldNamedTypeName] : [...entityAncestors]);
258
+ this.evaluateResolvabilityOfAbstractType(namedFieldTypeName, namedTypeData.kind, rootTypeFieldData, newCurrentFieldPath, evaluatedObjectLikes, entity ? [...entityAncestors, namedFieldTypeName] : [...entityAncestors]);
977
259
  continue;
978
260
  default:
979
- this.errors.push((0, errors_1.unexpectedObjectResponseType)(newCurrentFieldPath, (0, utils_3.kindToTypeString)(childContainer.kind)));
261
+ this.errors.push((0, errors_1.unexpectedObjectResponseType)(newCurrentFieldPath, (0, utils_2.kindToTypeString)(namedTypeData.kind)));
980
262
  continue;
981
263
  }
982
264
  }
983
- if (constants_1.BASE_SCALARS.has(fieldNamedTypeName)) {
984
- this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldContainer.subgraphNames], newCurrentFieldPath, parentTypeName));
265
+ if (constants_1.BASE_SCALARS.has(namedFieldTypeName)) {
266
+ this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldData.subgraphNames], newCurrentFieldPath, parentTypeName));
985
267
  continue;
986
268
  }
987
- const childContainer = (0, utils_3.getOrThrowError)(this.parents, fieldNamedTypeName, string_constants_1.PARENTS);
988
- switch (childContainer.kind) {
269
+ const namedTypeData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, namedFieldTypeName, 'parentDefinitionDataByTypeName');
270
+ switch (namedTypeData.kind) {
989
271
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
990
272
  // intentional fallthrough
991
273
  case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
992
- this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldContainer.subgraphNames], newCurrentFieldPath, parentTypeName));
274
+ this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldData.subgraphNames], newCurrentFieldPath, parentTypeName));
993
275
  continue;
994
276
  case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
995
277
  // intentional fallthrough
996
278
  case graphql_1.Kind.UNION_TYPE_DEFINITION:
997
279
  // intentional fallthrough
998
280
  case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
999
- this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldContainer.subgraphNames], newCurrentFieldPath + string_constants_1.SELECTION_REPRESENTATION, parentTypeName));
281
+ this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldData.subgraphNames], newCurrentFieldPath + string_constants_1.SELECTION_REPRESENTATION, parentTypeName));
1000
282
  continue;
1001
283
  default:
1002
- this.errors.push((0, errors_1.unexpectedObjectResponseType)(newCurrentFieldPath, (0, utils_3.kindToTypeString)(childContainer.kind)));
284
+ this.errors.push((0, errors_1.unexpectedObjectResponseType)(newCurrentFieldPath, (0, utils_2.kindToTypeString)(namedTypeData.kind)));
1003
285
  }
1004
286
  }
1005
287
  }
@@ -1008,30 +290,30 @@ class FederationFactory {
1008
290
  return;
1009
291
  }
1010
292
  evaluatedObjectLikes.add(abstractTypeName);
1011
- const concreteTypeNames = this.abstractToConcreteTypeNames.get(abstractTypeName);
293
+ const concreteTypeNames = this.concreteTypeNamesByAbstractTypeName.get(abstractTypeName);
1012
294
  if (!concreteTypeNames) {
1013
- (0, errors_1.noConcreteTypesForAbstractTypeError)((0, utils_3.kindToTypeString)(abstractKind), abstractTypeName);
295
+ (0, errors_1.noConcreteTypesForAbstractTypeError)((0, utils_2.kindToTypeString)(abstractKind), abstractTypeName);
1014
296
  return;
1015
297
  }
1016
298
  for (const concreteTypeName of concreteTypeNames) {
1017
299
  if (evaluatedObjectLikes.has(concreteTypeName)) {
1018
300
  continue;
1019
301
  }
1020
- const concreteParentContainer = (0, utils_3.getOrThrowError)(this.parents, concreteTypeName, string_constants_1.PARENTS);
1021
- if (concreteParentContainer.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
1022
- throw (0, errors_1.unexpectedParentKindErrorMessage)(concreteTypeName, 'Object', (0, utils_3.kindToTypeString)(concreteParentContainer.kind));
302
+ const concreteTypeData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, concreteTypeName, 'parentDefinitionDataByTypeName');
303
+ if (concreteTypeData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
304
+ throw (0, errors_1.unexpectedParentKindErrorMessage)(concreteTypeName, 'Object', (0, utils_2.kindToTypeString)(concreteTypeData.kind));
1023
305
  }
1024
306
  // If the concrete type is unreachable through an inline fragment, it is not an error
1025
- if (!(0, utils_3.doSetsHaveAnyOverlap)(concreteParentContainer.subgraphNames, rootTypeFieldData.subgraphs)) {
307
+ if (!(0, utils_2.doSetsHaveAnyOverlap)(concreteTypeData.subgraphNames, rootTypeFieldData.subgraphs)) {
1026
308
  continue;
1027
309
  }
1028
310
  const entity = this.entityContainersByTypeName.get(concreteTypeName);
1029
- this.evaluateResolvabilityOfObject(concreteParentContainer, rootTypeFieldData, currentFieldPath + ` ... on ` + concreteTypeName, evaluatedObjectLikes, entity ? [...entityAncestors, concreteTypeName] : [...entityAncestors], true);
311
+ this.evaluateResolvabilityOfObject(concreteTypeData, rootTypeFieldData, currentFieldPath + ` ... on ` + concreteTypeName, evaluatedObjectLikes, entity ? [...entityAncestors, concreteTypeName] : [...entityAncestors], true);
1030
312
  }
1031
313
  }
1032
314
  validateKeyFieldSetsForImplicitEntity(entityContainer) {
1033
- const internalSubgraph = (0, utils_3.getOrThrowError)(this.internalSubgraphBySubgraphName, this.currentSubgraphName, 'internalSubgraphBySubgraphName');
1034
- const parentContainerByTypeName = internalSubgraph.parentDataByTypeName;
315
+ const internalSubgraph = (0, utils_2.getOrThrowError)(this.internalSubgraphBySubgraphName, this.currentSubgraphName, 'internalSubgraphBySubgraphName');
316
+ const parentContainerByTypeName = internalSubgraph.parentDefinitionDataByTypeName;
1035
317
  const extensionContainerByTypeName = internalSubgraph.parentExtensionDataByTypeName;
1036
318
  const implicitEntityContainer = parentContainerByTypeName.get(entityContainer.typeName) ||
1037
319
  extensionContainerByTypeName.get(entityContainer.typeName);
@@ -1040,7 +322,7 @@ class FederationFactory {
1040
322
  implicitEntityContainer.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION)) {
1041
323
  throw (0, errors_1.incompatibleParentKindFatalError)(entityContainer.typeName, graphql_1.Kind.OBJECT_TYPE_DEFINITION, implicitEntityContainer?.kind || graphql_1.Kind.NULL);
1042
324
  }
1043
- const configurationData = (0, utils_3.getOrThrowError)(internalSubgraph.configurationDataMap, entityContainer.typeName, 'internalSubgraph.configurationDataMap');
325
+ const configurationData = (0, utils_2.getOrThrowError)(internalSubgraph.configurationDataByParentTypeName, entityContainer.typeName, 'internalSubgraph.configurationDataMap');
1044
326
  const keyFieldNames = new Set();
1045
327
  const keys = [];
1046
328
  // Any errors in the field sets would be caught when evaluating the explicit entities, so they are ignored here
@@ -1068,19 +350,15 @@ class FederationFactory {
1068
350
  Field: {
1069
351
  enter(node) {
1070
352
  const parentContainer = parentContainers[currentDepth];
1071
- const parentTypeName = parentContainer.typeName;
1072
353
  // If an object-like was just visited, a selection set should have been entered
1073
354
  if (shouldDefineSelectionSet) {
1074
355
  shouldAddKeyFieldSet = false;
1075
356
  return graphql_1.BREAK;
1076
357
  }
1077
358
  const fieldName = node.name.value;
1078
- const fieldPath = `${parentTypeName}.${fieldName}`;
1079
- const fieldContainer = parentContainer.fieldDataByFieldName.get(fieldName);
359
+ const fieldData = parentContainer.fieldDataByFieldName.get(fieldName);
1080
360
  // undefined if the field does not exist on the parent
1081
- if (!fieldContainer ||
1082
- fieldContainer.argumentDataByArgumentName.size ||
1083
- definedFields[currentDepth].has(fieldName)) {
361
+ if (!fieldData || fieldData.argumentDataByArgumentName.size || definedFields[currentDepth].has(fieldName)) {
1084
362
  shouldAddKeyFieldSet = false;
1085
363
  return graphql_1.BREAK;
1086
364
  }
@@ -1090,7 +368,7 @@ class FederationFactory {
1090
368
  if (currentDepth === 0) {
1091
369
  keyFieldNames.add(fieldName);
1092
370
  }
1093
- const namedTypeName = (0, type_merging_1.getNamedTypeForChild)(fieldPath, fieldContainer.node.type);
371
+ const namedTypeName = (0, ast_1.getTypeNodeNamedTypeName)(fieldData.node.type);
1094
372
  // The base scalars are not in the parents map
1095
373
  if (constants_1.BASE_SCALARS.has(namedTypeName)) {
1096
374
  return;
@@ -1150,10 +428,10 @@ class FederationFactory {
1150
428
  continue;
1151
429
  }
1152
430
  // Add any top-level fields that compose the key in case they are external
1153
- (0, utils_3.addIterableValuesToSet)(keyFieldNames, configurationData.fieldNames);
431
+ (0, utils_2.addIterableValuesToSet)(keyFieldNames, configurationData.fieldNames);
1154
432
  keys.push({
1155
433
  fieldName: '',
1156
- selectionSet: (0, utils_4.getNormalizedFieldSet)(documentNode),
434
+ selectionSet: (0, utils_3.getNormalizedFieldSet)(documentNode),
1157
435
  disableEntityResolver: true,
1158
436
  });
1159
437
  }
@@ -1162,51 +440,76 @@ class FederationFactory {
1162
440
  configurationData.keys = keys;
1163
441
  }
1164
442
  }
1165
- handleAuthorizationDataForRenamedTypes() {
1166
- for (const [originalTypeName, renamedTypeName] of this.renamedTypeNameByOriginalTypeName) {
1167
- const originalAuthorizationData = this.authorizationDataByParentTypeName.get(originalTypeName);
1168
- if (!originalAuthorizationData) {
443
+ getEnumValueMergeMethod(enumTypeName) {
444
+ if (this.namedInputValueTypeNames.has(enumTypeName)) {
445
+ if (this.namedOutputTypeNames.has(enumTypeName)) {
446
+ return utils_4.MergeMethod.CONSISTENT;
447
+ }
448
+ return utils_4.MergeMethod.INTERSECTION;
449
+ }
450
+ return utils_4.MergeMethod.UNION;
451
+ }
452
+ federate() {
453
+ const persistedDirectiveDefinitionDataByDirectiveName = new Map();
454
+ let shouldSkipPersistedExecutableDirectives = false;
455
+ let subgraphNumber = 0;
456
+ let isVersionTwo = false;
457
+ for (const internalSubgraph of this.internalSubgraphBySubgraphName.values()) {
458
+ subgraphNumber += 1;
459
+ this.currentSubgraphName = internalSubgraph.name;
460
+ isVersionTwo ||= internalSubgraph.isVersionTwo;
461
+ (0, walkers_1.createMultiGraphAndRenameRootTypes)(this, internalSubgraph);
462
+ for (const parentDefinitionData of internalSubgraph.parentDefinitionDataByTypeName.values()) {
463
+ (0, utils_4.upsertParentDefinitionData)(this.parentDefinitionDataByTypeName, parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.entityInterfaceFederationDataByTypeName, this.namedOutputTypeNames, this.namedInputValueTypeNames, internalSubgraph.name, this.errors);
464
+ }
465
+ for (const objectExtensionData of internalSubgraph.parentExtensionDataByTypeName.values()) {
466
+ (0, utils_4.upsertObjectExtensionData)(this.objectExtensionDataByTypeName, objectExtensionData, this.persistedDirectiveDefinitionByDirectiveName, this.namedOutputTypeNames, this.namedInputValueTypeNames, this.errors);
467
+ }
468
+ if (shouldSkipPersistedExecutableDirectives) {
1169
469
  continue;
1170
470
  }
1171
- originalAuthorizationData.typeName = renamedTypeName;
1172
- const renamedAuthorizationData = this.authorizationDataByParentTypeName.get(renamedTypeName);
1173
- if (!renamedAuthorizationData) {
1174
- this.authorizationDataByParentTypeName.set(renamedTypeName, originalAuthorizationData);
471
+ /* If a subgraph defines no executable directives, it is not possible for any definition to be in all subgraphs.
472
+ Consequently, it is no longer necessary to check for any persisted executable directives. */
473
+ if (!internalSubgraph.persistedDirectiveDefinitionDataByDirectiveName.size) {
474
+ shouldSkipPersistedExecutableDirectives = true;
475
+ continue;
1175
476
  }
1176
- else {
1177
- for (const [fieldName, incomingFieldAuthorizationData,] of renamedAuthorizationData.fieldAuthorizationDataByFieldName) {
1178
- if (!(0, utils_3.upsertFieldAuthorizationData)(originalAuthorizationData.fieldAuthorizationDataByFieldName, incomingFieldAuthorizationData)) {
1179
- this.invalidOrScopesHostPaths.add(`${renamedTypeName}.${fieldName}`);
1180
- }
1181
- }
477
+ for (const persistedDirectiveDefinitionData of internalSubgraph.persistedDirectiveDefinitionDataByDirectiveName.values()) {
478
+ (0, utils_4.upsertPersistedDirectiveDefinitionData)(persistedDirectiveDefinitionDataByDirectiveName, persistedDirectiveDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.namedInputValueTypeNames, subgraphNumber, this.errors);
479
+ }
480
+ /* Invalid directives keys are deleted; if there are no entries left, it is no longer necessary to evaluate more
481
+ executable directives. */
482
+ if (!persistedDirectiveDefinitionDataByDirectiveName.size) {
483
+ shouldSkipPersistedExecutableDirectives = true;
1182
484
  }
1183
- this.authorizationDataByParentTypeName.delete(originalTypeName);
1184
485
  }
1185
- }
1186
- federate() {
1187
- this.populateMultiGraphAndRenameOperations(this.internalSubgraphBySubgraphName);
1188
- const factory = this;
1189
- for (const subgraph of this.internalSubgraphBySubgraphName.values()) {
1190
- this.isCurrentSubgraphVersionTwo = subgraph.isVersionTwo;
1191
- this.currentSubgraphName = subgraph.name;
1192
- this.keyFieldNamesByParentTypeName = subgraph.keyFieldNamesByParentTypeName;
1193
- (0, subgraph_1.walkSubgraphToFederate)(subgraph.definitions, subgraph.overriddenFieldNamesByParentTypeName, factory);
486
+ const definitions = isVersionTwo
487
+ ? [
488
+ constants_1.AUTHENTICATED_DEFINITION,
489
+ constants_1.DEPRECATED_DEFINITION,
490
+ constants_1.INACCESSIBLE_DEFINITION,
491
+ constants_1.REQUIRES_SCOPES_DEFINITION,
492
+ constants_1.TAG_DEFINITION,
493
+ constants_1.SCOPE_SCALAR_DEFINITION,
494
+ ]
495
+ : [constants_1.DEPRECATED_DEFINITION, constants_1.TAG_DEFINITION];
496
+ for (const data of persistedDirectiveDefinitionDataByDirectiveName.values()) {
497
+ (0, utils_4.addValidPersistedDirectiveDefinitionNodeByData)(definitions, data, this.persistedDirectiveDefinitionByDirectiveName, this.errors);
1194
498
  }
1195
- this.handleAuthorizationDataForRenamedTypes();
1196
499
  for (const [typeName, entityInterfaceData] of this.entityInterfaceFederationDataByTypeName) {
1197
- (0, utils_3.subtractSourceSetFromTargetSet)(entityInterfaceData.interfaceFieldNames, entityInterfaceData.interfaceObjectFieldNames);
1198
- const entityInterface = (0, utils_3.getOrThrowError)(this.parents, typeName, 'parents');
500
+ (0, utils_2.subtractSourceSetFromTargetSet)(entityInterfaceData.interfaceFieldNames, entityInterfaceData.interfaceObjectFieldNames);
501
+ const entityInterface = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, typeName, 'parentDefinitionDataByTypeName');
1199
502
  if (entityInterface.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION) {
1200
503
  // TODO error
1201
504
  continue;
1202
505
  }
1203
506
  for (const subgraphName of entityInterfaceData.interfaceObjectSubgraphs) {
1204
- const configurationDataMap = (0, utils_3.getOrThrowError)(this.internalSubgraphBySubgraphName, subgraphName, 'internalSubgraphBySubgraphName').configurationDataMap;
1205
- const concreteTypeNames = this.abstractToConcreteTypeNames.get(typeName);
507
+ const configurationDataMap = (0, utils_2.getOrThrowError)(this.internalSubgraphBySubgraphName, subgraphName, 'internalSubgraphBySubgraphName').configurationDataByParentTypeName;
508
+ const concreteTypeNames = this.concreteTypeNamesByAbstractTypeName.get(typeName);
1206
509
  if (!concreteTypeNames) {
1207
510
  continue;
1208
511
  }
1209
- const interfaceObjectConfiguration = (0, utils_3.getOrThrowError)(configurationDataMap, typeName, 'configurationDataMap');
512
+ const interfaceObjectConfiguration = (0, utils_2.getOrThrowError)(configurationDataMap, typeName, 'configurationDataMap');
1210
513
  const keys = interfaceObjectConfiguration.keys;
1211
514
  if (!keys) {
1212
515
  // TODO no keys error
@@ -1221,15 +524,15 @@ class FederationFactory {
1221
524
  continue;
1222
525
  }
1223
526
  if (authorizationData) {
1224
- const concreteAuthorizationData = (0, utils_3.getValueOrDefault)(this.authorizationDataByParentTypeName, concreteTypeName, () => (0, utils_3.newAuthorizationData)(concreteTypeName));
527
+ const concreteAuthorizationData = (0, utils_2.getValueOrDefault)(this.authorizationDataByParentTypeName, concreteTypeName, () => (0, utils_2.newAuthorizationData)(concreteTypeName));
1225
528
  for (const fieldAuthorizationData of authorizationData.fieldAuthorizationDataByFieldName.values()) {
1226
- if (!(0, utils_3.upsertFieldAuthorizationData)(concreteAuthorizationData.fieldAuthorizationDataByFieldName, fieldAuthorizationData)) {
529
+ if (!(0, utils_2.upsertFieldAuthorizationData)(concreteAuthorizationData.fieldAuthorizationDataByFieldName, fieldAuthorizationData)) {
1227
530
  this.invalidOrScopesHostPaths.add(`${concreteTypeName}.${fieldAuthorizationData.fieldName}`);
1228
531
  }
1229
532
  }
1230
533
  }
1231
- const concreteTypeContainer = (0, utils_3.getOrThrowError)(this.parents, concreteTypeName, 'parents');
1232
- if (concreteTypeContainer.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
534
+ const concreteTypeData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, concreteTypeName, 'parentDefinitionDataByTypeName');
535
+ if (concreteTypeData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
1233
536
  continue;
1234
537
  }
1235
538
  // The subgraph locations of the interface object must be added to the concrete types that implement it
@@ -1245,198 +548,284 @@ class FederationFactory {
1245
548
  typeName: concreteTypeName,
1246
549
  };
1247
550
  for (const fieldName of entityInterfaceData.interfaceObjectFieldNames) {
1248
- const existingFieldContainer = concreteTypeContainer.fields.get(fieldName);
1249
- if (existingFieldContainer) {
551
+ const existingFieldData = concreteTypeData.fieldDataByFieldName.get(fieldName);
552
+ if (existingFieldData) {
1250
553
  // TODO handle shareability
1251
554
  continue;
1252
555
  }
1253
- const interfaceFieldContainer = (0, utils_3.getOrThrowError)(entityInterface.fields, fieldName, 'entityInterface.fields');
1254
- concreteTypeContainer.fields.set(fieldName, { ...interfaceFieldContainer });
556
+ const interfaceFieldData = (0, utils_2.getOrThrowError)(entityInterface.fieldDataByFieldName, fieldName, `${typeName}.fieldDataByFieldName`);
557
+ concreteTypeData.fieldDataByFieldName.set(fieldName, { ...interfaceFieldData });
1255
558
  }
1256
559
  configurationDataMap.set(concreteTypeName, configurationData);
1257
560
  }
1258
561
  }
1259
562
  }
1260
563
  if (this.invalidOrScopesHostPaths.size > 0) {
1261
- this.errors.push((0, errors_1.orScopesLimitError)(utils_3.maxOrScopes, [...this.invalidOrScopesHostPaths]));
1262
- }
1263
- const definitions = [];
1264
- for (const [directiveName, directiveContainer] of this.directiveDefinitions) {
1265
- if (this.persistedDirectiveDefinitions.has(directiveName)) {
1266
- definitions.push(directiveContainer.node);
1267
- continue;
1268
- }
1269
- // The definitions must be present in all subgraphs to be kept in the federated graph
1270
- this.addValidExecutableDirectiveDefinition(directiveName, directiveContainer, definitions);
1271
- }
1272
- if (this.directiveDefinitions.has(string_constants_1.REQUIRES_SCOPES)) {
1273
- definitions.push(constants_1.SCOPE_SCALAR_DEFINITION);
1274
- }
1275
- for (const [typeName, extension] of this.extensions) {
1276
- this.parentTypeName = typeName;
1277
- if (extension.isRootType && !this.parents.has(typeName)) {
1278
- this.upsertParentNode((0, ast_1.objectTypeExtensionNodeToMutableDefinitionNode)(extension.node));
1279
- }
1280
- const baseObject = this.parents.get(typeName);
1281
- if (!baseObject) {
1282
- this.errors.push((0, errors_1.noBaseTypeExtensionError)(typeName));
1283
- continue;
1284
- }
1285
- if (baseObject.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
1286
- throw (0, errors_1.incompatibleParentKindFatalError)(typeName, graphql_1.Kind.OBJECT_TYPE_DEFINITION, baseObject.kind);
1287
- }
1288
- this.upsertExtensionPersistedDirectives(extension.directives, baseObject.directives);
1289
- for (const [extensionFieldName, extensionFieldContainer] of extension.fields) {
1290
- const baseFieldContainer = baseObject.fields.get(extensionFieldName);
1291
- if (!baseFieldContainer) {
1292
- baseObject.fields.set(extensionFieldName, extensionFieldContainer);
1293
- continue;
1294
- }
1295
- if (baseFieldContainer.isShareable && extensionFieldContainer.isShareable) {
1296
- this.childName = extensionFieldName;
1297
- this.upsertExtensionFieldArguments(extensionFieldContainer.arguments, baseFieldContainer.arguments);
1298
- (0, utils_1.setLongestDescriptionForNode)(baseFieldContainer.node, extensionFieldContainer.node.description);
1299
- (0, utils_3.addIterableValuesToSet)(extensionFieldContainer.subgraphNames, baseFieldContainer.subgraphNames);
1300
- continue;
1301
- }
1302
- const parent = this.shareableErrorTypeNames.get(typeName);
1303
- if (parent) {
1304
- parent.add(extensionFieldName);
1305
- continue;
1306
- }
1307
- this.shareableErrorTypeNames.set(typeName, new Set([extensionFieldName]));
1308
- }
1309
- for (const interfaceName of extension.interfaces) {
1310
- baseObject.interfaces.add(interfaceName);
1311
- }
1312
- }
1313
- for (const [parentTypeName, children] of this.shareableErrorTypeNames) {
1314
- const parent = (0, utils_3.getOrThrowError)(this.parents, parentTypeName, string_constants_1.PARENTS);
1315
- if (parent.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
1316
- throw (0, errors_1.incompatibleParentKindFatalError)(parentTypeName, graphql_1.Kind.OBJECT_TYPE_DEFINITION, parent.kind);
1317
- }
1318
- this.errors.push((0, errors_1.shareableFieldDefinitionsError)(parent, children));
1319
- }
1320
- const objectLikeContainersWithInterfaces = [];
1321
- for (const [parentTypeName, parentContainer] of this.parents) {
1322
- switch (parentContainer.kind) {
564
+ this.errors.push((0, errors_1.orScopesLimitError)(utils_2.maxOrScopes, [...this.invalidOrScopesHostPaths]));
565
+ }
566
+ for (const [parentTypeName, objectExtensionData] of this.objectExtensionDataByTypeName) {
567
+ (0, utils_4.upsertValidObjectExtensionData)(this.parentDefinitionDataByTypeName, objectExtensionData, this.persistedDirectiveDefinitionByDirectiveName, this.namedOutputTypeNames, this.namedInputValueTypeNames, this.errors, this.authorizationDataByParentTypeName.get(parentTypeName));
568
+ }
569
+ // for (const [typeName, extension] of this.extensions) {
570
+ // this.parentTypeName = typeName;
571
+ // if (extension.isRootType && !this.parents.has(typeName)) {
572
+ // this.upsertParentNode(objectTypeExtensionNodeToMutableDefinitionNode(extension.node));
573
+ // }
574
+ // const baseObject = this.parents.get(typeName);
575
+ // if (!baseObject) {
576
+ // this.errors.push(noBaseTypeExtensionError(typeName));
577
+ // continue;
578
+ // }
579
+ //
580
+ // if (baseObject.kind !== Kind.OBJECT_TYPE_DEFINITION) {
581
+ // throw incompatibleParentKindFatalError(typeName, Kind.OBJECT_TYPE_DEFINITION, baseObject.kind);
582
+ // }
583
+ // this.upsertExtensionPersistedDirectives(extension.directives, baseObject.directives);
584
+ // for (const [extensionFieldName, extensionFieldContainer] of extension.fields) {
585
+ // const baseFieldContainer = baseObject.fields.get(extensionFieldName);
586
+ // if (!baseFieldContainer) {
587
+ // baseObject.fields.set(extensionFieldName, extensionFieldContainer);
588
+ // continue;
589
+ // }
590
+ // if (baseFieldContainer.isShareable && extensionFieldContainer.isShareable) {
591
+ // this.childName = extensionFieldName;
592
+ // this.upsertExtensionFieldArguments(extensionFieldContainer.arguments, baseFieldContainer.arguments);
593
+ // addIterableValuesToSet(extensionFieldContainer.subgraphNames, baseFieldContainer.subgraphNames);
594
+ // continue;
595
+ // }
596
+ // const parent = this.shareableErrorTypeNames.get(typeName);
597
+ // if (parent) {
598
+ // parent.add(extensionFieldName);
599
+ // continue;
600
+ // }
601
+ // this.shareableErrorTypeNames.set(typeName, new Set<string>([extensionFieldName]));
602
+ // }
603
+ // for (const interfaceName of extension.interfaces) {
604
+ // baseObject.interfaces.add(interfaceName);
605
+ // }
606
+ // }
607
+ // for (const [parentTypeName, children] of this.shareableErrorTypeNames) {
608
+ // const parent = getOrThrowError(this.parents, parentTypeName, PARENTS);
609
+ // if (parent.kind !== Kind.OBJECT_TYPE_DEFINITION) {
610
+ // throw incompatibleParentKindFatalError(parentTypeName, Kind.OBJECT_TYPE_DEFINITION, parent.kind);
611
+ // }
612
+ // this.errors.push(shareableFieldDefinitionsError(parent, children));
613
+ // }
614
+ const definitionsWithInterfaces = [];
615
+ for (const [parentTypeName, parentDefinitionData] of this.parentDefinitionDataByTypeName) {
616
+ switch (parentDefinitionData.kind) {
1323
617
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
1324
- const values = [];
1325
- const mergeMethod = this.getEnumMergeMethod(parentTypeName);
1326
- for (const enumValueContainer of parentContainer.values.values()) {
1327
- (0, utils_1.pushPersistedDirectivesAndGetNode)(enumValueContainer);
618
+ const enumValueNodes = [];
619
+ const mergeMethod = this.getEnumValueMergeMethod(parentTypeName);
620
+ for (const enumValueData of parentDefinitionData.enumValueDataByValueName.values()) {
621
+ const enumValueNode = (0, utils_4.getNodeWithPersistedDirectivesByData)(enumValueData, this.persistedDirectiveDefinitionByDirectiveName, this.errors);
1328
622
  switch (mergeMethod) {
1329
- case utils_2.MergeMethod.CONSISTENT:
1330
- if (enumValueContainer.appearances < parentContainer.appearances) {
623
+ case utils_4.MergeMethod.CONSISTENT:
624
+ if (parentDefinitionData.appearances > enumValueData.appearances) {
1331
625
  this.errors.push((0, errors_1.incompatibleSharedEnumError)(parentTypeName));
1332
626
  }
1333
- values.push(enumValueContainer.node);
627
+ enumValueNodes.push(enumValueNode);
1334
628
  break;
1335
- case utils_2.MergeMethod.INTERSECTION:
1336
- if (enumValueContainer.appearances === parentContainer.appearances) {
1337
- values.push(enumValueContainer.node);
629
+ case utils_4.MergeMethod.INTERSECTION:
630
+ if (parentDefinitionData.appearances === enumValueData.appearances) {
631
+ enumValueNodes.push(enumValueNode);
1338
632
  }
1339
633
  break;
1340
634
  default:
1341
- values.push(enumValueContainer.node);
635
+ enumValueNodes.push(enumValueNode);
1342
636
  break;
1343
637
  }
1344
638
  }
1345
- parentContainer.node.values = values;
1346
- definitions.push((0, utils_1.pushPersistedDirectivesAndGetNode)(parentContainer));
639
+ parentDefinitionData.node.values = enumValueNodes;
640
+ definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1347
641
  break;
1348
642
  case graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
1349
- const inputValues = [];
1350
- for (const inputValueContainer of parentContainer.fields.values()) {
1351
- (0, utils_1.pushPersistedDirectivesAndGetNode)(inputValueContainer);
1352
- if (parentContainer.appearances === inputValueContainer.appearances) {
1353
- inputValues.push(inputValueContainer.node);
643
+ const invalidRequiredInputs = [];
644
+ const inputValueNodes = [];
645
+ for (const [inputValueName, inputValueData] of parentDefinitionData.inputValueDataByValueName) {
646
+ if (parentDefinitionData.subgraphNames.size === inputValueData.subgraphNames.size) {
647
+ inputValueNodes.push((0, utils_4.getNodeWithPersistedDirectivesByInputValueData)(inputValueData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1354
648
  }
1355
- else if ((0, type_merging_1.isTypeRequired)(inputValueContainer.node.type)) {
1356
- this.errors.push((0, errors_1.federationRequiredInputFieldError)(parentTypeName, inputValueContainer.node.name.value));
1357
- break;
649
+ else if ((0, utils_4.isTypeRequired)(inputValueData.type)) {
650
+ invalidRequiredInputs.push({
651
+ inputValueName,
652
+ missingSubgraphs: (0, utils_2.getEntriesNotInHashSet)(parentDefinitionData.subgraphNames, inputValueData.subgraphNames),
653
+ requiredSubgraphs: [...inputValueData.requiredSubgraphNames],
654
+ });
1358
655
  }
1359
656
  }
1360
- parentContainer.node.fields = inputValues;
1361
- definitions.push((0, utils_1.pushPersistedDirectivesAndGetNode)(parentContainer));
1362
- break;
1363
- case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
1364
- const interfaceFields = [];
1365
- for (const fieldContainer of parentContainer.fields.values()) {
1366
- if ((0, utils_2.isFieldInaccessible)(fieldContainer)) {
1367
- continue;
1368
- }
1369
- interfaceFields.push(this.getMergedFieldDefinitionNode(fieldContainer, parentTypeName));
1370
- }
1371
- parentContainer.node.fields = interfaceFields;
1372
- (0, utils_1.pushPersistedDirectivesAndGetNode)(parentContainer);
1373
- // Interface implementations can only be evaluated after they've been fully merged
1374
- if (parentContainer.interfaces.size > 0) {
1375
- objectLikeContainersWithInterfaces.push(parentContainer);
1376
- }
1377
- else {
1378
- definitions.push(parentContainer.node);
1379
- }
1380
- if (interfaceFields.length < 1) {
1381
- this.errors.push((0, errors_1.allFieldDefinitionsAreInaccessibleError)('interface', parentTypeName));
657
+ if (invalidRequiredInputs.length > 0) {
658
+ this.errors.push((0, errors_1.invalidRequiredInputValueError)(string_constants_1.INPUT_OBJECT, parentTypeName, invalidRequiredInputs, false));
659
+ break;
1382
660
  }
661
+ parentDefinitionData.node.fields = inputValueNodes;
662
+ definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1383
663
  break;
664
+ case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
665
+ // intentional fallthrough
1384
666
  case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
1385
- const fields = [];
1386
- for (const fieldContainer of parentContainer.fields.values()) {
1387
- if ((0, utils_2.isFieldInaccessible)(fieldContainer)) {
667
+ const fieldNodes = [];
668
+ const invalidFieldNames = new Set();
669
+ const isObject = parentDefinitionData.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION;
670
+ for (const [fieldName, fieldData] of parentDefinitionData.fieldDataByFieldName) {
671
+ (0, utils_4.pushAuthorizationDirectives)(fieldData, this.authorizationDataByParentTypeName.get(parentTypeName));
672
+ const argumentNodes = (0, utils_4.getValidFieldArgumentNodes)(fieldData, this.persistedDirectiveDefinitionByDirectiveName, this.fieldConfigurationByFieldPath, this.errors);
673
+ if (isObject && !(0, utils_4.isShareabilityOfAllFieldInstancesValid)(fieldData)) {
674
+ invalidFieldNames.add(fieldName);
675
+ }
676
+ if (fieldData.isInaccessible) {
1388
677
  continue;
1389
678
  }
1390
- fields.push(this.getMergedFieldDefinitionNode(fieldContainer, parentTypeName));
679
+ fieldNodes.push((0, utils_4.getNodeWithPersistedDirectivesByFieldData)(fieldData, this.persistedDirectiveDefinitionByDirectiveName, argumentNodes, this.errors));
1391
680
  }
1392
- parentContainer.node.fields = fields;
1393
- (0, utils_1.pushPersistedDirectivesAndGetNode)(parentContainer);
1394
- // Interface implementations can only be evaluated after they've been fully merged
1395
- if (parentContainer.interfaces.size > 0) {
1396
- objectLikeContainersWithInterfaces.push(parentContainer);
681
+ if (isObject && invalidFieldNames.size > 0) {
682
+ this.errors.push((0, errors_1.invalidFieldShareabilityError)(parentDefinitionData, invalidFieldNames));
683
+ }
684
+ parentDefinitionData.node.fields = fieldNodes;
685
+ // Implemented interfaces can only be validated after all fields are merged
686
+ if (parentDefinitionData.implementedInterfaceTypeNames.size > 0) {
687
+ definitionsWithInterfaces.push(parentDefinitionData);
1397
688
  }
1398
689
  else {
1399
- definitions.push(parentContainer.node);
690
+ definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1400
691
  }
1401
- if (fields.length < 1) {
1402
- if ((0, utils_4.isNodeQuery)(parentTypeName)) {
692
+ if (fieldNodes.length < 1) {
693
+ if ((0, utils_3.isNodeQuery)(parentTypeName)) {
1403
694
  this.errors.push(errors_1.noQueryRootTypeError);
1404
695
  }
1405
696
  else {
1406
- this.errors.push((0, errors_1.allFieldDefinitionsAreInaccessibleError)('object', parentTypeName));
697
+ this.errors.push((0, errors_1.allFieldDefinitionsAreInaccessibleError)((0, utils_2.kindToTypeString)(parentDefinitionData.kind), parentTypeName));
1407
698
  }
1408
699
  }
1409
700
  break;
1410
701
  case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
1411
702
  if (!constants_1.BASE_SCALARS.has(parentTypeName)) {
1412
- definitions.push((0, utils_1.pushPersistedDirectivesAndGetNode)(parentContainer));
703
+ definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1413
704
  }
1414
705
  break;
1415
706
  case graphql_1.Kind.UNION_TYPE_DEFINITION:
1416
- const types = [];
1417
- for (const memberName of parentContainer.members) {
1418
- types.push((0, utils_1.stringToNamedTypeNode)(memberName));
1419
- }
1420
- parentContainer.node.types = types;
1421
- definitions.push((0, utils_1.pushPersistedDirectivesAndGetNode)(parentContainer));
707
+ parentDefinitionData.node.types = (0, utils_2.mapToArrayOfValues)(parentDefinitionData.memberByMemberTypeName);
708
+ definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1422
709
  break;
1423
710
  }
1424
711
  }
1425
- for (const container of objectLikeContainersWithInterfaces) {
1426
- container.node.interfaces = this.getAndValidateImplementedInterfaces(container);
1427
- definitions.push(container.node);
1428
- }
1429
- const query = this.parents.get(string_constants_1.QUERY);
1430
- if (!query || query.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION || query.fields.size < 1) {
712
+ // for (const [parentTypeName, parentContainer] of this.parents) {
713
+ // switch (parentContainer.kind) {
714
+ // case Kind.ENUM_TYPE_DEFINITION:
715
+ // const values: MutableEnumValueDefinitionNode[] = [];
716
+ // const mergeMethod = this.getEnumMergeMethod(parentTypeName);
717
+ // for (const enumValueContainer of parentContainer.values.values()) {
718
+ // pushPersistedDirectivesAndGetNode(enumValueContainer);
719
+ // switch (mergeMethod) {
720
+ // case MergeMethod.CONSISTENT:
721
+ // if (enumValueContainer.appearances < parentContainer.appearances) {
722
+ // this.errors.push(incompatibleSharedEnumError(parentTypeName));
723
+ // }
724
+ // values.push(enumValueContainer.node);
725
+ // break;
726
+ // case MergeMethod.INTERSECTION:
727
+ // if (enumValueContainer.appearances === parentContainer.appearances) {
728
+ // values.push(enumValueContainer.node);
729
+ // }
730
+ // break;
731
+ // default:
732
+ // values.push(enumValueContainer.node);
733
+ // break;
734
+ // }
735
+ // }
736
+ // parentContainer.node.values = values;
737
+ // definitions.push(pushPersistedDirectivesAndGetNode(parentContainer));
738
+ // break;
739
+ // case Kind.INPUT_OBJECT_TYPE_DEFINITION:
740
+ // const inputValues: InputValueDefinitionNode[] = [];
741
+ // for (const inputValueContainer of parentContainer.fields.values()) {
742
+ // pushPersistedDirectivesAndGetNode(inputValueContainer);
743
+ // if (parentContainer.appearances === inputValueContainer.appearances) {
744
+ // inputValues.push(inputValueContainer.node);
745
+ // } else if (isTypeRequired(inputValueContainer.node.type)) {
746
+ // this.errors.push(federationRequiredInputFieldError(parentTypeName, inputValueContainer.node.name.value));
747
+ // break;
748
+ // }
749
+ // }
750
+ // parentContainer.node.fields = inputValues;
751
+ // definitions.push(pushPersistedDirectivesAndGetNode(parentContainer));
752
+ // break;
753
+ // case Kind.INTERFACE_TYPE_DEFINITION:
754
+ // const interfaceFields: FieldDefinitionNode[] = [];
755
+ // for (const fieldContainer of parentContainer.fields.values()) {
756
+ // if (isFieldInaccessible(fieldContainer)) {
757
+ // continue;
758
+ // }
759
+ // interfaceFields.push(this.getMergedFieldDefinitionNode(fieldContainer, parentTypeName));
760
+ // }
761
+ // parentContainer.node.fields = interfaceFields;
762
+ // pushPersistedDirectivesAndGetNode(parentContainer);
763
+ // // Interface implementations can only be evaluated after they've been fully merged
764
+ // if (parentContainer.interfaces.size > 0) {
765
+ // definitionsWithInterfaces.push(parentContainer);
766
+ // } else {
767
+ // definitions.push(parentContainer.node);
768
+ // }
769
+ // if (interfaceFields.length < 1) {
770
+ // this.errors.push(allFieldDefinitionsAreInaccessibleError('interface', parentTypeName));
771
+ // }
772
+ // break;
773
+ // case Kind.OBJECT_TYPE_DEFINITION:
774
+ // const fields: FieldDefinitionNode[] = [];
775
+ // for (const fieldContainer of parentContainer.fields.values()) {
776
+ // if (isFieldInaccessible(fieldContainer)) {
777
+ // continue;
778
+ // }
779
+ // fields.push(this.getMergedFieldDefinitionNode(fieldContainer, parentTypeName));
780
+ // }
781
+ // parentContainer.node.fields = fields;
782
+ // pushPersistedDirectivesAndGetNode(parentContainer);
783
+ // // Interface implementations can only be evaluated after they've been fully merged
784
+ // if (parentContainer.interfaces.size > 0) {
785
+ // definitionsWithInterfaces.push(parentContainer);
786
+ // }
787
+ // } else {
788
+ // definitions.push(parentContainer.node);
789
+ // }
790
+ // if (fields.length < 1) {
791
+ // if (isNodeQuery(parentTypeName)) {
792
+ // this.errors.push(noQueryRootTypeError);
793
+ // } else {
794
+ // this.errors.push(allFieldDefinitionsAreInaccessibleError('object', parentTypeName));
795
+ // }
796
+ // }
797
+ // break;
798
+ // case Kind.SCALAR_TYPE_DEFINITION:
799
+ // if (!BASE_SCALARS.has(parentTypeName)) {
800
+ // definitions.push(pushPersistedDirectivesAndGetNode(parentContainer));
801
+ // }
802
+ // break;
803
+ // case Kind.UNION_TYPE_DEFINITION:
804
+ // const types: NamedTypeNode[] = [];
805
+ // for (const memberName of parentContainer.members) {
806
+ // types.push(stringToNamedTypeNode(memberName));
807
+ // }
808
+ // parentContainer.node.types = types;
809
+ // definitions.push(pushPersistedDirectivesAndGetNode(parentContainer));
810
+ // break;
811
+ // }
812
+ // }
813
+ for (const data of definitionsWithInterfaces) {
814
+ data.node.interfaces = this.getValidImplementedInterfaces(data);
815
+ definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(data, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
816
+ }
817
+ const query = this.parentDefinitionDataByTypeName.get(string_constants_1.QUERY);
818
+ if (!query || query.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION || query.fieldDataByFieldName.size < 1) {
1431
819
  this.errors.push(errors_1.noQueryRootTypeError);
1432
820
  }
1433
821
  // return any composition errors before checking whether all fields are resolvable
1434
822
  if (this.errors.length > 0) {
1435
823
  return { errors: this.errors };
1436
824
  }
825
+ // TODO add back resolvability check
1437
826
  for (const rootTypeName of string_constants_1.ROOT_TYPES) {
1438
- const rootTypeContainer = this.parents.get(rootTypeName);
1439
- if (!rootTypeContainer || rootTypeContainer.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
827
+ const rootTypeData = this.parentDefinitionDataByTypeName.get(rootTypeName);
828
+ if (!rootTypeData || rootTypeData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
1440
829
  continue;
1441
830
  }
1442
831
  // After evaluating all of a root type's fields, break and return if there are errors
@@ -1445,41 +834,41 @@ class FederationFactory {
1445
834
  }
1446
835
  // If a root type field returns a Scalar or Enum, track it so that it is not evaluated it again
1447
836
  const evaluatedRootScalarsAndEnums = new Set(constants_1.BASE_SCALARS);
1448
- for (const [rootTypeFieldName, rootTypeFieldContainer] of rootTypeContainer.fields) {
1449
- const rootTypeFieldNamedTypeName = rootTypeFieldContainer.namedTypeName;
1450
- if (evaluatedRootScalarsAndEnums.has(rootTypeFieldNamedTypeName)) {
837
+ for (const [rootTypeFieldName, fieldData] of rootTypeData.fieldDataByFieldName) {
838
+ const namedRootFieldTypeName = fieldData.namedTypeName;
839
+ if (evaluatedRootScalarsAndEnums.has(namedRootFieldTypeName)) {
1451
840
  continue;
1452
841
  }
1453
- if (!this.shouldEvaluateObjectLike(rootTypeFieldContainer.subgraphNames, rootTypeFieldNamedTypeName)) {
842
+ if (!this.shouldEvaluateObjectLike(fieldData.subgraphNames, namedRootFieldTypeName)) {
1454
843
  continue;
1455
844
  }
1456
- const childContainer = (0, utils_3.getOrThrowError)(this.parents, rootTypeFieldNamedTypeName, string_constants_1.PARENTS);
845
+ const namedTypeData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, namedRootFieldTypeName, 'parentDefinitionDataByTypeName');
1457
846
  const fieldPath = `${rootTypeName}.${rootTypeFieldName}`;
1458
847
  const rootTypeFieldData = {
1459
848
  fieldName: rootTypeFieldName,
1460
- fieldTypeNodeString: (0, merge_1.printTypeNode)(rootTypeFieldContainer.node.type),
849
+ fieldTypeNodeString: (0, merge_1.printTypeNode)(fieldData.node.type),
1461
850
  path: fieldPath,
1462
851
  typeName: rootTypeName,
1463
- subgraphs: rootTypeFieldContainer.subgraphNames,
852
+ subgraphs: fieldData.subgraphNames,
1464
853
  };
1465
- switch (childContainer.kind) {
854
+ switch (namedTypeData.kind) {
1466
855
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
1467
856
  // intentional fallthrough
1468
857
  case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
1469
858
  // Root type fields whose response type is an Enums and Scalars will always be resolvable
1470
859
  // Consequently, subsequent checks can be skipped
1471
- evaluatedRootScalarsAndEnums.add(rootTypeFieldNamedTypeName);
860
+ evaluatedRootScalarsAndEnums.add(namedRootFieldTypeName);
1472
861
  continue;
1473
862
  case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
1474
- this.evaluateResolvabilityOfObject(childContainer, rootTypeFieldData, fieldPath, new Set(), this.entityContainersByTypeName.has(rootTypeFieldNamedTypeName) ? [rootTypeFieldNamedTypeName] : []);
863
+ this.evaluateResolvabilityOfObject(namedTypeData, rootTypeFieldData, fieldPath, new Set(), this.entityContainersByTypeName.has(namedRootFieldTypeName) ? [namedRootFieldTypeName] : []);
1475
864
  continue;
1476
865
  case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
1477
866
  // intentional fallthrough
1478
867
  case graphql_1.Kind.UNION_TYPE_DEFINITION:
1479
- this.evaluateResolvabilityOfAbstractType(rootTypeFieldNamedTypeName, childContainer.kind, rootTypeFieldData, fieldPath, new Set(), this.entityContainersByTypeName.has(rootTypeFieldNamedTypeName) ? [rootTypeFieldNamedTypeName] : []);
868
+ this.evaluateResolvabilityOfAbstractType(namedRootFieldTypeName, namedTypeData.kind, rootTypeFieldData, fieldPath, new Set(), this.entityContainersByTypeName.has(namedRootFieldTypeName) ? [namedRootFieldTypeName] : []);
1480
869
  continue;
1481
870
  default:
1482
- this.errors.push((0, errors_1.unexpectedObjectResponseType)(fieldPath, (0, utils_3.kindToTypeString)(childContainer.kind)));
871
+ this.errors.push((0, errors_1.unexpectedObjectResponseType)(fieldPath, (0, utils_2.kindToTypeString)(namedTypeData.kind)));
1483
872
  }
1484
873
  }
1485
874
  }
@@ -1494,12 +883,12 @@ class FederationFactory {
1494
883
  const subgraphConfigBySubgraphName = new Map();
1495
884
  for (const subgraph of this.internalSubgraphBySubgraphName.values()) {
1496
885
  subgraphConfigBySubgraphName.set(subgraph.name, {
1497
- configurationDataMap: subgraph.configurationDataMap,
886
+ configurationDataMap: subgraph.configurationDataByParentTypeName,
1498
887
  schema: subgraph.schema,
1499
888
  });
1500
889
  }
1501
890
  for (const authorizationData of this.authorizationDataByParentTypeName.values()) {
1502
- (0, utils_3.upsertAuthorizationConfiguration)(this.fieldConfigurationByFieldPath, authorizationData);
891
+ (0, utils_2.upsertAuthorizationConfiguration)(this.fieldConfigurationByFieldPath, authorizationData);
1503
892
  }
1504
893
  return {
1505
894
  federationResult: {
@@ -1517,7 +906,7 @@ function federateSubgraphs(subgraphs) {
1517
906
  if (subgraphs.length < 1) {
1518
907
  return { errors: [errors_1.minimumSubgraphRequirementError] };
1519
908
  }
1520
- const { authorizationDataByParentTypeName, entityContainerByTypeName, errors, internalSubgraphBySubgraphName, warnings, } = (0, normalization_factory_1.batchNormalize)(subgraphs);
909
+ const { authorizationDataByParentTypeName, concreteTypeNamesByAbstractTypeName, entityContainerByTypeName, errors, graph, internalSubgraphBySubgraphName, warnings, } = (0, normalization_factory_1.batchNormalize)(subgraphs);
1521
910
  if (errors) {
1522
911
  return { errors };
1523
912
  }
@@ -1528,7 +917,7 @@ function federateSubgraphs(subgraphs) {
1528
917
  for (const [typeName, entityInterfaceData] of internalSubgraph.entityInterfaces) {
1529
918
  // Always add each entity interface to the invalid entity interfaces map
1530
919
  // If not, earlier checks would not account for implementations not yet seen
1531
- const invalidEntityInterfaces = (0, utils_3.getValueOrDefault)(invalidEntityInterfacesByTypeName, typeName, () => []);
920
+ const invalidEntityInterfaces = (0, utils_2.getValueOrDefault)(invalidEntityInterfacesByTypeName, typeName, () => []);
1532
921
  invalidEntityInterfaces.push({
1533
922
  subgraphName,
1534
923
  concreteTypeNames: entityInterfaceData.concreteTypeNames || new Set(),
@@ -1536,10 +925,10 @@ function federateSubgraphs(subgraphs) {
1536
925
  const existingData = entityInterfaceFederationDataByTypeName.get(typeName);
1537
926
  if (!existingData) {
1538
927
  validEntityInterfaceTypeNames.add(typeName);
1539
- entityInterfaceFederationDataByTypeName.set(typeName, (0, utils_3.newEntityInterfaceFederationData)(entityInterfaceData, subgraphName));
928
+ entityInterfaceFederationDataByTypeName.set(typeName, (0, utils_2.newEntityInterfaceFederationData)(entityInterfaceData, subgraphName));
1540
929
  continue;
1541
930
  }
1542
- const areAnyImplementationsUndefined = (0, utils_3.upsertEntityInterfaceFederationData)(existingData, entityInterfaceData, subgraphName);
931
+ const areAnyImplementationsUndefined = (0, utils_2.upsertEntityInterfaceFederationData)(existingData, entityInterfaceData, subgraphName);
1543
932
  if (areAnyImplementationsUndefined) {
1544
933
  validEntityInterfaceTypeNames.delete(typeName);
1545
934
  }
@@ -1556,7 +945,7 @@ function federateSubgraphs(subgraphs) {
1556
945
  ],
1557
946
  };
1558
947
  }
1559
- return new FederationFactory(authorizationDataByParentTypeName, entityContainerByTypeName, entityInterfaceFederationDataByTypeName, internalSubgraphBySubgraphName, warnings).federate();
948
+ return new FederationFactory(authorizationDataByParentTypeName, concreteTypeNamesByAbstractTypeName, entityContainerByTypeName, entityInterfaceFederationDataByTypeName, graph, internalSubgraphBySubgraphName, warnings).federate();
1560
949
  }
1561
950
  exports.federateSubgraphs = federateSubgraphs;
1562
951
  //# sourceMappingURL=federation-factory.js.map