@wundergraph/composition 0.22.1 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,48 +1,44 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.federateSubgraphs = exports.FederationFactory = void 0;
3
+ exports.federateSubgraphsContract = exports.federateSubgraphsWithContracts = exports.federateSubgraphs = exports.FederationFactory = void 0;
4
4
  const graphql_1 = require("graphql");
5
5
  const ast_1 = require("../schema-building/ast");
6
6
  const utils_1 = require("../ast/utils");
7
7
  const errors_1 = require("../errors/errors");
8
+ const utils_2 = require("./utils");
8
9
  const string_constants_1 = require("../utils/string-constants");
9
- const utils_2 = require("../utils/utils");
10
+ const utils_3 = require("../utils/utils");
10
11
  const merge_1 = require("@graphql-tools/merge");
11
12
  const constants_1 = require("../utils/constants");
12
13
  const normalization_factory_1 = require("../normalization/normalization-factory");
13
- const utils_3 = require("../normalization/utils");
14
- const utils_4 = require("../schema-building/utils");
14
+ const utils_4 = require("../normalization/utils");
15
+ const utils_5 = require("../schema-building/utils");
15
16
  const walkers_1 = require("./walkers");
17
+ const lodash_1 = require("lodash");
18
+ const type_merging_1 = require("../schema-building/type-merging");
16
19
  class FederationFactory {
17
20
  authorizationDataByParentTypeName;
18
- areFieldsExternal = false;
19
- areFieldsShareable = false;
20
21
  concreteTypeNamesByAbstractTypeName;
21
- fieldConfigurationByFieldPath = new Map();
22
- namedInputValueTypeNames = new Set();
23
- namedOutputTypeNames = new Set();
24
- entityInterfaceFederationDataByTypeName;
25
- executableDirectives = new Set();
26
- parentTypeName = '';
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]);
22
+ clientDefinitions = [constants_1.DEPRECATED_DEFINITION];
28
23
  currentSubgraphName = '';
29
- childName = '';
30
24
  entityDataByTypeName;
25
+ entityInterfaceFederationDataByTypeName;
31
26
  errors = [];
32
27
  evaluatedObjectLikesBySubgraph = new Map();
28
+ fieldConfigurationByFieldPath = new Map();
33
29
  graph;
34
30
  graphEdges = new Set();
35
31
  graphPaths = new Map();
32
+ inaccessiblePaths = new Set();
33
+ internalSubgraphBySubgraphName;
36
34
  invalidOrScopesHostPaths = new Set();
37
- isCurrentParentEntity = false;
38
- isCurrentParentInterface = false;
39
- isCurrentSubgraphVersionTwo = false;
40
- isCurrentParentExtensionType = false;
41
- isParentRootType = false;
42
- isParentInputObject = false;
43
- outputFieldTypeNames = new Set();
44
- parentDefinitionDataByTypeName = new Map();
35
+ isVersionTwo = false;
36
+ namedInputValueTypeNames = new Set();
37
+ namedOutputTypeNames = new Set();
45
38
  objectExtensionDataByTypeName = new Map();
39
+ parentDefinitionDataByTypeName = new Map();
40
+ parentTagDataByTypeName = new Map();
41
+ pathsByNamedTypeName = new Map();
46
42
  persistedDirectiveDefinitionByDirectiveName = new Map([
47
43
  [string_constants_1.AUTHENTICATED, constants_1.AUTHENTICATED_DEFINITION],
48
44
  [string_constants_1.DEPRECATED, constants_1.DEPRECATED_DEFINITION],
@@ -50,9 +46,11 @@ class FederationFactory {
50
46
  [string_constants_1.REQUIRES_SCOPES, constants_1.REQUIRES_SCOPES_DEFINITION],
51
47
  [string_constants_1.TAG, constants_1.TAG_DEFINITION],
52
48
  ]);
53
- rootTypeNames = new Set([string_constants_1.DEFAULT_MUTATION, string_constants_1.DEFAULT_QUERY, string_constants_1.DEFAULT_SUBSCRIPTION]);
54
- internalSubgraphBySubgraphName;
49
+ persistedDirectiveDefinitions = new Set([string_constants_1.AUTHENTICATED, string_constants_1.DEPRECATED, string_constants_1.INACCESSIBLE, string_constants_1.TAG, string_constants_1.REQUIRES_SCOPES]);
50
+ potentialPersistedDirectiveDefinitionDataByDirectiveName = new Map();
51
+ routerDefinitions = [constants_1.DEPRECATED_DEFINITION, constants_1.TAG_DEFINITION];
55
52
  shareableErrorTypeNames = new Map();
53
+ tagNamesByPath = new Map();
56
54
  warnings;
57
55
  constructor(authorizationDataByParentTypeName, concreteTypeNamesByAbstractTypeName, entityContainersByTypeName, entityInterfaceFederationDataByTypeName, graph, internalSubgraphBySubgraphName, warnings) {
58
56
  this.authorizationDataByParentTypeName = authorizationDataByParentTypeName;
@@ -68,13 +66,14 @@ class FederationFactory {
68
66
  if (data.implementedInterfaceTypeNames.size < 1) {
69
67
  return interfaces;
70
68
  }
69
+ const isParentInaccessible = (0, utils_5.isNodeDataInaccessible)(data);
71
70
  const implementationErrorsMap = new Map();
72
71
  const invalidImplementationTypeStringByTypeName = new Map();
73
72
  for (const interfaceName of data.implementedInterfaceTypeNames) {
74
73
  interfaces.push((0, utils_1.stringToNamedTypeNode)(interfaceName));
75
- const implementationData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, interfaceName, string_constants_1.PARENT_DEFINITION_DATA);
74
+ const implementationData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, interfaceName, string_constants_1.PARENT_DEFINITION_DATA);
76
75
  if (implementationData.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION) {
77
- invalidImplementationTypeStringByTypeName.set(implementationData.name, (0, utils_2.kindToTypeString)(implementationData.kind));
76
+ invalidImplementationTypeStringByTypeName.set(implementationData.name, (0, utils_3.kindToTypeString)(implementationData.kind));
78
77
  continue;
79
78
  }
80
79
  const implementationErrors = {
@@ -93,11 +92,12 @@ class FederationFactory {
93
92
  const invalidFieldImplementation = {
94
93
  invalidAdditionalArguments: new Set(),
95
94
  invalidImplementedArguments: [],
95
+ isInaccessible: false,
96
96
  originalResponseType: (0, merge_1.printTypeNode)(interfaceField.node.type),
97
97
  unimplementedArguments: new Set(),
98
98
  };
99
99
  // The implemented field type must be equally or more restrictive than the original interface field type
100
- if (!(0, utils_4.isTypeValidImplementation)(interfaceField.node.type, fieldData.node.type, this.concreteTypeNamesByAbstractTypeName)) {
100
+ if (!(0, utils_5.isTypeValidImplementation)(interfaceField.node.type, fieldData.node.type, this.concreteTypeNamesByAbstractTypeName)) {
101
101
  hasErrors = true;
102
102
  hasNestedErrors = true;
103
103
  invalidFieldImplementation.implementedResponseType = (0, merge_1.printTypeNode)(fieldData.node.type);
@@ -136,6 +136,11 @@ class FederationFactory {
136
136
  hasNestedErrors = true;
137
137
  invalidFieldImplementation.invalidAdditionalArguments.add(argumentName);
138
138
  }
139
+ if (!isParentInaccessible && fieldData.isInaccessible && !interfaceField.isInaccessible) {
140
+ hasErrors = true;
141
+ hasNestedErrors = true;
142
+ invalidFieldImplementation.isInaccessible = true;
143
+ }
139
144
  if (hasNestedErrors) {
140
145
  implementationErrors.invalidFieldImplementations.set(fieldName, invalidFieldImplementation);
141
146
  }
@@ -148,7 +153,7 @@ class FederationFactory {
148
153
  this.errors.push((0, errors_1.invalidImplementedTypeError)(data.name, invalidImplementationTypeStringByTypeName));
149
154
  }
150
155
  if (implementationErrorsMap.size) {
151
- this.errors.push((0, errors_1.unimplementedInterfaceFieldsError)(data.node.name.value, (0, utils_2.kindToTypeString)(data.kind), implementationErrorsMap));
156
+ this.errors.push((0, errors_1.invalidInterfaceImplementationError)(data.node.name.value, (0, utils_3.kindToTypeString)(data.kind), implementationErrorsMap));
152
157
  }
153
158
  return interfaces;
154
159
  }
@@ -162,11 +167,11 @@ class FederationFactory {
162
167
  return true;
163
168
  }
164
169
  if (entityAncestorName === parentTypeName) {
165
- const hasOverlap = (0, utils_2.doSetsHaveAnyOverlap)(fieldSubgraphs, (0, utils_2.getOrThrowError)(this.entityDataByTypeName, entityAncestorName, string_constants_1.ENTITIES).subgraphNames);
170
+ const hasOverlap = (0, utils_3.doSetsHaveAnyOverlap)(fieldSubgraphs, (0, utils_3.getOrThrowError)(this.entityDataByTypeName, entityAncestorName, string_constants_1.ENTITIES).subgraphNames);
166
171
  this.graphPaths.set(path, hasOverlap);
167
172
  return hasOverlap;
168
173
  }
169
- if ((0, utils_2.hasSimplePath)(this.graph, entityAncestorName, parentTypeName)) {
174
+ if ((0, utils_3.hasSimplePath)(this.graph, entityAncestorName, parentTypeName)) {
170
175
  this.graphPaths.set(path, true);
171
176
  return true;
172
177
  }
@@ -185,7 +190,7 @@ class FederationFactory {
185
190
  return false;
186
191
  }
187
192
  updateEvaluatedSubgraphOccurrences(rootTypeFieldSubgraphs, objectSubgraphs, entityAncestors, parentTypeName) {
188
- const mutualSubgraphs = (0, utils_2.getAllMutualEntries)(rootTypeFieldSubgraphs, objectSubgraphs);
193
+ const mutualSubgraphs = (0, utils_3.getAllMutualEntries)(rootTypeFieldSubgraphs, objectSubgraphs);
189
194
  if (mutualSubgraphs.size > 0) {
190
195
  for (const mutualSubgraph of mutualSubgraphs) {
191
196
  const evaluatedObjects = this.evaluatedObjectLikesBySubgraph.get(mutualSubgraph);
@@ -198,9 +203,9 @@ class FederationFactory {
198
203
  }
199
204
  }
200
205
  for (const entityAncestorTypeName of entityAncestors) {
201
- const entityObjectData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, entityAncestorTypeName, 'parentDefinitionDataByTypeName');
202
- const mutualEntityAncestorRootTypeFieldSubgraphs = (0, utils_2.getAllMutualEntries)(rootTypeFieldSubgraphs, entityObjectData.subgraphNames);
203
- const mutualEntityAncestorSubgraphsNames = (0, utils_2.getAllMutualEntries)(mutualEntityAncestorRootTypeFieldSubgraphs, objectSubgraphs);
206
+ const entityObjectData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, entityAncestorTypeName, 'parentDefinitionDataByTypeName');
207
+ const mutualEntityAncestorRootTypeFieldSubgraphs = (0, utils_3.getAllMutualEntries)(rootTypeFieldSubgraphs, entityObjectData.subgraphNames);
208
+ const mutualEntityAncestorSubgraphsNames = (0, utils_3.getAllMutualEntries)(mutualEntityAncestorRootTypeFieldSubgraphs, objectSubgraphs);
204
209
  for (const mutualSubgraphName of mutualEntityAncestorSubgraphsNames) {
205
210
  const objects = this.evaluatedObjectLikesBySubgraph.get(mutualSubgraphName);
206
211
  if (objects) {
@@ -222,6 +227,10 @@ class FederationFactory {
222
227
  return;
223
228
  }
224
229
  for (const [fieldName, fieldData] of objectData.fieldDataByFieldName) {
230
+ const fieldPath = `${fieldData.renamedParentTypeName}.${fieldName}`;
231
+ if (this.inaccessiblePaths.has(fieldPath)) {
232
+ continue;
233
+ }
225
234
  const namedFieldTypeName = fieldData.namedTypeName;
226
235
  if (string_constants_1.ROOT_TYPES.has(namedFieldTypeName)) {
227
236
  continue;
@@ -230,12 +239,12 @@ class FederationFactory {
230
239
  if (evaluatedObjectLikes.has(namedFieldTypeName)) {
231
240
  continue;
232
241
  }
233
- if ((0, utils_4.isFieldExternalInAllMutualSubgraphs)(rootTypeFieldData.subgraphs, fieldData)) {
242
+ if ((0, utils_5.isFieldExternalInAllMutualSubgraphs)(rootTypeFieldData.subgraphs, fieldData)) {
234
243
  continue;
235
244
  }
236
245
  this.updateEvaluatedSubgraphOccurrences(rootTypeFieldData.subgraphs, objectData.subgraphNames, entityAncestors, parentTypeName);
237
246
  evaluatedObjectLikes.add(parentTypeName);
238
- const isFieldResolvable = (0, utils_2.doSetsHaveAnyOverlap)(rootTypeFieldData.subgraphs, fieldData.subgraphNames) ||
247
+ const isFieldResolvable = (0, utils_3.doSetsHaveAnyOverlap)(rootTypeFieldData.subgraphs, fieldData.subgraphNames) ||
239
248
  this.isFieldResolvableByEntityAncestor(entityAncestors, fieldData.subgraphNames, parentTypeName);
240
249
  const newCurrentFieldPath = currentFieldPath + (isParentAbstract ? ' ' : '.') + fieldName;
241
250
  const entity = this.entityDataByTypeName.get(namedFieldTypeName);
@@ -244,7 +253,7 @@ class FederationFactory {
244
253
  if (constants_1.BASE_SCALARS.has(namedFieldTypeName)) {
245
254
  continue;
246
255
  }
247
- const namedTypeData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, namedFieldTypeName, 'parentDefinitionDataByTypeName');
256
+ const namedTypeData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, namedFieldTypeName, string_constants_1.PARENT_DEFINITION_DATA);
248
257
  switch (namedTypeData.kind) {
249
258
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
250
259
  // intentional fallthrough
@@ -259,7 +268,7 @@ class FederationFactory {
259
268
  this.evaluateResolvabilityOfAbstractType(namedFieldTypeName, namedTypeData.kind, rootTypeFieldData, newCurrentFieldPath, evaluatedObjectLikes, entity ? [...entityAncestors, namedFieldTypeName] : [...entityAncestors]);
260
269
  continue;
261
270
  default:
262
- this.errors.push((0, errors_1.unexpectedObjectResponseType)(newCurrentFieldPath, (0, utils_2.kindToTypeString)(namedTypeData.kind)));
271
+ this.errors.push((0, errors_1.unexpectedObjectResponseType)(newCurrentFieldPath, (0, utils_3.kindToTypeString)(namedTypeData.kind)));
263
272
  continue;
264
273
  }
265
274
  }
@@ -267,7 +276,7 @@ class FederationFactory {
267
276
  this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldData.subgraphNames], newCurrentFieldPath, parentTypeName));
268
277
  continue;
269
278
  }
270
- const namedTypeData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, namedFieldTypeName, 'parentDefinitionDataByTypeName');
279
+ const namedTypeData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, namedFieldTypeName, 'parentDefinitionDataByTypeName');
271
280
  switch (namedTypeData.kind) {
272
281
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
273
282
  // intentional fallthrough
@@ -282,7 +291,7 @@ class FederationFactory {
282
291
  this.errors.push((0, errors_1.unresolvableFieldError)(rootTypeFieldData, fieldName, [...fieldData.subgraphNames], newCurrentFieldPath + string_constants_1.SELECTION_REPRESENTATION, parentTypeName));
283
292
  continue;
284
293
  default:
285
- this.errors.push((0, errors_1.unexpectedObjectResponseType)(newCurrentFieldPath, (0, utils_2.kindToTypeString)(namedTypeData.kind)));
294
+ this.errors.push((0, errors_1.unexpectedObjectResponseType)(newCurrentFieldPath, (0, utils_3.kindToTypeString)(namedTypeData.kind)));
286
295
  }
287
296
  }
288
297
  }
@@ -293,19 +302,19 @@ class FederationFactory {
293
302
  evaluatedObjectLikes.add(abstractTypeName);
294
303
  const concreteTypeNames = this.concreteTypeNamesByAbstractTypeName.get(abstractTypeName);
295
304
  if (!concreteTypeNames) {
296
- (0, errors_1.noConcreteTypesForAbstractTypeError)((0, utils_2.kindToTypeString)(abstractKind), abstractTypeName);
305
+ (0, errors_1.noConcreteTypesForAbstractTypeError)((0, utils_3.kindToTypeString)(abstractKind), abstractTypeName);
297
306
  return;
298
307
  }
299
308
  for (const concreteTypeName of concreteTypeNames) {
300
309
  if (evaluatedObjectLikes.has(concreteTypeName)) {
301
310
  continue;
302
311
  }
303
- const concreteTypeData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, concreteTypeName, 'parentDefinitionDataByTypeName');
312
+ const concreteTypeData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, concreteTypeName, 'parentDefinitionDataByTypeName');
304
313
  if (concreteTypeData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
305
- throw (0, errors_1.unexpectedParentKindErrorMessage)(concreteTypeName, 'Object', (0, utils_2.kindToTypeString)(concreteTypeData.kind));
314
+ throw (0, errors_1.unexpectedParentKindErrorMessage)(concreteTypeName, 'Object', (0, utils_3.kindToTypeString)(concreteTypeData.kind));
306
315
  }
307
316
  // If the concrete type is unreachable through an inline fragment, it is not an error
308
- if (!(0, utils_2.doSetsHaveAnyOverlap)(concreteTypeData.subgraphNames, rootTypeFieldData.subgraphs)) {
317
+ if (!(0, utils_3.doSetsHaveAnyOverlap)(concreteTypeData.subgraphNames, rootTypeFieldData.subgraphs)) {
309
318
  continue;
310
319
  }
311
320
  const entity = this.entityDataByTypeName.get(concreteTypeName);
@@ -316,7 +325,7 @@ class FederationFactory {
316
325
  if (!entityData) {
317
326
  return;
318
327
  }
319
- const internalSubgraph = (0, utils_2.getOrThrowError)(this.internalSubgraphBySubgraphName, this.currentSubgraphName, 'internalSubgraphBySubgraphName');
328
+ const internalSubgraph = (0, utils_3.getOrThrowError)(this.internalSubgraphBySubgraphName, this.currentSubgraphName, 'internalSubgraphBySubgraphName');
320
329
  const parentDefinitionDataByTypeName = internalSubgraph.parentDefinitionDataByTypeName;
321
330
  const parentExtensionDataByTypeName = internalSubgraph.parentExtensionDataByTypeName;
322
331
  const objectData = parentDefinitionDataByTypeName.get(entityData.typeName) || parentExtensionDataByTypeName.get(entityData.typeName);
@@ -324,7 +333,7 @@ class FederationFactory {
324
333
  (objectData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION && objectData.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION)) {
325
334
  throw (0, errors_1.incompatibleParentKindFatalError)(entityData.typeName, graphql_1.Kind.OBJECT_TYPE_DEFINITION, objectData?.kind || graphql_1.Kind.NULL);
326
335
  }
327
- const configurationData = (0, utils_2.getOrThrowError)(internalSubgraph.configurationDataByParentTypeName, entityData.typeName, 'internalSubgraph.configurationDataMap');
336
+ const configurationData = (0, utils_3.getOrThrowError)(internalSubgraph.configurationDataByParentTypeName, entityData.typeName, 'internalSubgraph.configurationDataMap');
328
337
  const keyFieldNames = new Set();
329
338
  const implicitKeys = [];
330
339
  // Any errors in the field sets would be caught when evaluating the explicit entities, so they are ignored here
@@ -430,10 +439,10 @@ class FederationFactory {
430
439
  continue;
431
440
  }
432
441
  // Add any top-level fields that compose the key in case they are external
433
- (0, utils_2.addIterableValuesToSet)(keyFieldNames, configurationData.fieldNames);
442
+ (0, utils_3.addIterableValuesToSet)(keyFieldNames, configurationData.fieldNames);
434
443
  implicitKeys.push({
435
444
  fieldName: '',
436
- selectionSet: (0, utils_3.getNormalizedFieldSet)(documentNode),
445
+ selectionSet: (0, utils_4.getNormalizedFieldSet)(documentNode),
437
446
  disableEntityResolver: true,
438
447
  });
439
448
  }
@@ -457,27 +466,599 @@ class FederationFactory {
457
466
  getEnumValueMergeMethod(enumTypeName) {
458
467
  if (this.namedInputValueTypeNames.has(enumTypeName)) {
459
468
  if (this.namedOutputTypeNames.has(enumTypeName)) {
460
- return utils_4.MergeMethod.CONSISTENT;
469
+ return utils_5.MergeMethod.CONSISTENT;
461
470
  }
462
- return utils_4.MergeMethod.INTERSECTION;
471
+ return utils_5.MergeMethod.INTERSECTION;
463
472
  }
464
- return utils_4.MergeMethod.UNION;
473
+ return utils_5.MergeMethod.UNION;
465
474
  }
466
- federate() {
467
- const persistedDirectiveDefinitionDataByDirectiveName = new Map();
468
- let shouldSkipPersistedExecutableDirectives = false;
475
+ generateTagData() {
476
+ for (const [path, tagNames] of this.tagNamesByPath) {
477
+ const paths = path.split('.');
478
+ if (paths.length < 1) {
479
+ continue;
480
+ }
481
+ const parentTagData = (0, utils_3.getValueOrDefault)(this.parentTagDataByTypeName, paths[0], () => (0, utils_2.newParentTagData)(paths[0]));
482
+ switch (paths.length) {
483
+ // parent type
484
+ case 1:
485
+ for (const tagName of tagNames) {
486
+ parentTagData.tagNames.add(tagName);
487
+ }
488
+ break;
489
+ // child type
490
+ case 2:
491
+ const childTagData = (0, utils_3.getValueOrDefault)(parentTagData.childTagDataByChildName, paths[1], () => (0, utils_2.newChildTagData)(paths[1]));
492
+ for (const tagName of tagNames) {
493
+ childTagData.tagNames.add(tagName);
494
+ }
495
+ break;
496
+ // field argument
497
+ case 3:
498
+ const fieldTagData = (0, utils_3.getValueOrDefault)(parentTagData.childTagDataByChildName, paths[1], () => (0, utils_2.newChildTagData)(paths[1]));
499
+ const argumentTagData = (0, utils_3.getValueOrDefault)(fieldTagData.tagNamesByArgumentName, paths[2], () => new Set());
500
+ for (const tagName of tagNames) {
501
+ argumentTagData.add(tagName);
502
+ }
503
+ break;
504
+ default:
505
+ break;
506
+ }
507
+ }
508
+ }
509
+ evaluateRootNodeFieldsResolvability() {
510
+ for (const rootTypeName of string_constants_1.ROOT_TYPES) {
511
+ const rootTypeData = this.parentDefinitionDataByTypeName.get(rootTypeName);
512
+ if (!rootTypeData || rootTypeData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
513
+ continue;
514
+ }
515
+ // After evaluating all of a root type's fields, break and return if there are errors
516
+ if (this.errors.length > 0) {
517
+ break;
518
+ }
519
+ // If a root type field returns a Scalar or Enum, track it so that it is not evaluated it again
520
+ const evaluatedRootScalarsAndEnums = new Set(constants_1.BASE_SCALARS);
521
+ for (const [rootTypeFieldName, fieldData] of rootTypeData.fieldDataByFieldName) {
522
+ const namedRootFieldTypeName = fieldData.namedTypeName;
523
+ if (evaluatedRootScalarsAndEnums.has(namedRootFieldTypeName)) {
524
+ continue;
525
+ }
526
+ if (!this.shouldEvaluateObjectLike(fieldData.subgraphNames, namedRootFieldTypeName)) {
527
+ continue;
528
+ }
529
+ const namedTypeData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, namedRootFieldTypeName, 'parentDefinitionDataByTypeName');
530
+ const fieldPath = `${rootTypeName}.${rootTypeFieldName}`;
531
+ if (this.inaccessiblePaths.has(fieldPath)) {
532
+ continue;
533
+ }
534
+ const rootTypeFieldData = {
535
+ fieldName: rootTypeFieldName,
536
+ fieldTypeNodeString: (0, merge_1.printTypeNode)(fieldData.node.type),
537
+ path: fieldPath,
538
+ typeName: rootTypeName,
539
+ subgraphs: fieldData.subgraphNames,
540
+ };
541
+ switch (namedTypeData.kind) {
542
+ case graphql_1.Kind.ENUM_TYPE_DEFINITION:
543
+ // intentional fallthrough
544
+ case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
545
+ // Root type fields whose response type is an Enums and Scalars will always be resolvable
546
+ // Consequently, subsequent checks can be skipped
547
+ evaluatedRootScalarsAndEnums.add(namedRootFieldTypeName);
548
+ continue;
549
+ case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
550
+ this.evaluateResolvabilityOfObject(namedTypeData, rootTypeFieldData, fieldPath, new Set(), this.entityDataByTypeName.has(namedRootFieldTypeName) ? [namedRootFieldTypeName] : []);
551
+ continue;
552
+ case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
553
+ // intentional fallthrough
554
+ case graphql_1.Kind.UNION_TYPE_DEFINITION:
555
+ this.evaluateResolvabilityOfAbstractType(namedRootFieldTypeName, namedTypeData.kind, rootTypeFieldData, fieldPath, new Set(), this.entityDataByTypeName.has(namedRootFieldTypeName) ? [namedRootFieldTypeName] : []);
556
+ continue;
557
+ default:
558
+ this.errors.push((0, errors_1.unexpectedObjectResponseType)(fieldPath, (0, utils_3.kindToTypeString)(namedTypeData.kind)));
559
+ }
560
+ }
561
+ }
562
+ }
563
+ upsertEnumValueData(enumValueDataByValueName, incomingData) {
564
+ const existingData = enumValueDataByValueName.get(incomingData.name);
565
+ (0, utils_5.extractPersistedDirectives)(existingData?.persistedDirectivesData || incomingData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
566
+ if (!existingData) {
567
+ incomingData.node = {
568
+ directives: [],
569
+ kind: incomingData.node.kind,
570
+ name: (0, utils_1.stringToNameNode)(incomingData.name),
571
+ };
572
+ enumValueDataByValueName.set(incomingData.name, incomingData);
573
+ return;
574
+ }
575
+ existingData.appearances += 1;
576
+ (0, utils_5.setLongestDescription)(existingData, incomingData);
577
+ }
578
+ upsertInputValueData(inputValueDataByValueName, incomingData) {
579
+ const existingData = inputValueDataByValueName.get(incomingData.name);
580
+ (0, utils_5.extractPersistedDirectives)(existingData?.persistedDirectivesData || incomingData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
581
+ if (!existingData) {
582
+ incomingData.node = {
583
+ directives: [],
584
+ kind: incomingData.node.kind,
585
+ name: (0, utils_1.stringToNameNode)(incomingData.name),
586
+ type: incomingData.type,
587
+ };
588
+ inputValueDataByValueName.set(incomingData.name, incomingData);
589
+ return;
590
+ }
591
+ (0, utils_5.setLongestDescription)(existingData, incomingData);
592
+ (0, utils_3.addIterableValuesToSet)(incomingData.requiredSubgraphNames, existingData.requiredSubgraphNames);
593
+ (0, utils_3.addIterableValuesToSet)(incomingData.subgraphNames, existingData.subgraphNames);
594
+ // TODO refactor type merging
595
+ const { typeErrors, typeNode } = (0, type_merging_1.getMostRestrictiveMergedTypeNode)(existingData.type, incomingData.type, existingData.originalPath, this.errors);
596
+ if (typeNode) {
597
+ existingData.type = typeNode;
598
+ }
599
+ else {
600
+ if (!typeErrors || typeErrors.length < 2) {
601
+ throw (0, errors_1.fieldTypeMergeFatalError)(existingData.name);
602
+ }
603
+ existingData.isArgument
604
+ ? this.errors.push((0, errors_1.incompatibleArgumentTypesError)(existingData.name, existingData.renamedPath, typeErrors[0], typeErrors[1]))
605
+ : this.errors.push((0, errors_1.incompatibleChildTypesError)(existingData.renamedPath, typeErrors[0], typeErrors[1]));
606
+ }
607
+ (0, utils_5.compareAndValidateInputValueDefaultValues)(existingData, incomingData, this.errors);
608
+ }
609
+ handleArgumentInaccessibility(isParentInaccessible, inputValueData, argumentPath, fieldPath) {
610
+ /* If either the parent or the field to which the field belongs are declared inaccessible, the nullability
611
+ ** of the argument is not considered. However, if only the argument is declared inaccessible, it is an
612
+ ** error. */
613
+ if (isParentInaccessible) {
614
+ this.inaccessiblePaths.add(argumentPath);
615
+ return;
616
+ }
617
+ if (!(0, utils_5.isNodeDataInaccessible)(inputValueData)) {
618
+ return;
619
+ }
620
+ if ((0, utils_5.isTypeRequired)(inputValueData.type)) {
621
+ this.errors.push((0, errors_1.inaccessibleRequiredArgumentError)(inputValueData.name, argumentPath, fieldPath));
622
+ }
623
+ else {
624
+ this.inaccessiblePaths.add(argumentPath);
625
+ }
626
+ }
627
+ upsertFieldData(fieldDataByFieldName, incomingData, isParentInaccessible) {
628
+ const fieldPath = `${incomingData.renamedParentTypeName}.${incomingData.name}`;
629
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, incomingData.namedTypeName, () => new Set()).add(fieldPath);
630
+ this.namedOutputTypeNames.add(incomingData.namedTypeName);
631
+ const existingData = fieldDataByFieldName.get(incomingData.name);
632
+ (0, utils_5.extractPersistedDirectives)(existingData?.persistedDirectivesData || incomingData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
633
+ const isFieldInaccessible = (0, utils_5.isNodeDataInaccessible)(incomingData);
634
+ if (isParentInaccessible || isFieldInaccessible) {
635
+ this.inaccessiblePaths.add(fieldPath);
636
+ }
637
+ if (incomingData.persistedDirectivesData.tags.size > 0) {
638
+ const tagNames = (0, utils_3.getValueOrDefault)(this.tagNamesByPath, fieldPath, () => new Set());
639
+ for (const tagName of incomingData.persistedDirectivesData.tags.keys()) {
640
+ tagNames.add(tagName);
641
+ }
642
+ }
643
+ if (!existingData) {
644
+ fieldDataByFieldName.set(incomingData.name, incomingData);
645
+ incomingData.node = {
646
+ arguments: [],
647
+ directives: [],
648
+ kind: incomingData.node.kind,
649
+ name: (0, utils_1.stringToNameNode)(incomingData.name),
650
+ type: incomingData.type,
651
+ };
652
+ for (const [argumentName, inputValueData] of incomingData.argumentDataByArgumentName) {
653
+ inputValueData.node = {
654
+ directives: [],
655
+ kind: inputValueData.node.kind,
656
+ name: (0, utils_1.stringToNameNode)(inputValueData.name),
657
+ type: inputValueData.type,
658
+ };
659
+ const argumentPath = `${fieldPath}(${argumentName}: ... )`;
660
+ const namedArgumentTypeName = (0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type);
661
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(argumentPath);
662
+ this.namedInputValueTypeNames.add(namedArgumentTypeName);
663
+ (0, utils_5.extractPersistedDirectives)(inputValueData.persistedDirectivesData, inputValueData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
664
+ /* If either the parent or the field to which the field belongs are declared inaccessible, the nullability
665
+ ** of the argument is not considered. However, if only the argument is declared inaccessible, it is an
666
+ ** error. */
667
+ this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, argumentPath, fieldPath);
668
+ if (inputValueData.persistedDirectivesData.tags.size > 0) {
669
+ const tagArgumentPath = `${fieldPath}.${argumentName}`;
670
+ const tagNames = (0, utils_3.getValueOrDefault)(this.tagNamesByPath, tagArgumentPath, () => new Set());
671
+ for (const tagName of inputValueData.persistedDirectivesData.tags.keys()) {
672
+ tagNames.add(tagName);
673
+ }
674
+ }
675
+ }
676
+ return;
677
+ }
678
+ const { typeErrors, typeNode } = (0, type_merging_1.getLeastRestrictiveMergedTypeNode)(existingData.type, incomingData.type, fieldPath, this.errors);
679
+ if (typeNode) {
680
+ existingData.type = typeNode;
681
+ }
682
+ else {
683
+ if (!typeErrors || typeErrors.length < 2) {
684
+ throw (0, errors_1.fieldTypeMergeFatalError)(existingData.name);
685
+ }
686
+ this.errors.push((0, errors_1.incompatibleChildTypesError)(fieldPath, typeErrors[0], typeErrors[1]));
687
+ }
688
+ for (const [argumentName, inputValueData] of incomingData.argumentDataByArgumentName) {
689
+ const argumentPath = `${fieldPath}(${argumentName}: ... )`;
690
+ const namedArgumentTypeName = (0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type);
691
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(argumentPath);
692
+ this.namedInputValueTypeNames.add(namedArgumentTypeName);
693
+ /* If either the parent or the field to which the field belongs are declared inaccessible, the nullability
694
+ ** of the argument is not considered. However, if only the argument is declared inaccessible, it is an
695
+ ** error. */
696
+ this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, argumentPath, fieldPath);
697
+ if (inputValueData.persistedDirectivesData.tags.size > 0) {
698
+ const tagArgumentPath = `${fieldPath}.${argumentName}`;
699
+ const tagNames = (0, utils_3.getValueOrDefault)(this.tagNamesByPath, tagArgumentPath, () => new Set());
700
+ for (const tagName of inputValueData.persistedDirectivesData.tags.keys()) {
701
+ tagNames.add(tagName);
702
+ }
703
+ }
704
+ this.upsertInputValueData(existingData.argumentDataByArgumentName, inputValueData);
705
+ }
706
+ (0, utils_5.setLongestDescription)(existingData, incomingData);
707
+ existingData.isInaccessible ||= incomingData.isInaccessible;
708
+ (0, utils_3.addMapEntries)(incomingData.isExternalBySubgraphName, existingData.isExternalBySubgraphName);
709
+ (0, utils_3.addMapEntries)(incomingData.isShareableBySubgraphName, existingData.isShareableBySubgraphName);
710
+ (0, utils_3.addIterableValuesToSet)(incomingData.subgraphNames, existingData.subgraphNames);
711
+ }
712
+ getClientSchemaUnionMembers(unionData) {
713
+ const members = [];
714
+ for (const [memberName, namedTypeNode] of unionData.memberByMemberTypeName) {
715
+ if (!this.inaccessiblePaths.has(memberName)) {
716
+ members.push(namedTypeNode);
717
+ }
718
+ }
719
+ return members;
720
+ }
721
+ upsertParentDefinitionData(incomingData, subgraphName) {
722
+ const entityInterfaceData = this.entityInterfaceFederationDataByTypeName.get(incomingData.name);
723
+ const existingData = this.parentDefinitionDataByTypeName.get(incomingData.name);
724
+ const baseData = existingData || incomingData;
725
+ (0, utils_5.extractPersistedDirectives)(baseData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
726
+ const isParentInaccessible = (0, utils_5.isNodeDataInaccessible)(baseData);
727
+ if (isParentInaccessible) {
728
+ this.inaccessiblePaths.add(incomingData.name);
729
+ }
730
+ if (incomingData.persistedDirectivesData.tags.size > 0) {
731
+ const tagNames = (0, utils_3.getValueOrDefault)(this.tagNamesByPath, incomingData.name, () => new Set());
732
+ for (const tagName of incomingData.persistedDirectivesData.tags.keys()) {
733
+ tagNames.add(tagName);
734
+ }
735
+ }
736
+ if (!existingData) {
737
+ if (entityInterfaceData && entityInterfaceData.interfaceObjectSubgraphs.has(subgraphName)) {
738
+ incomingData.kind = graphql_1.Kind.INTERFACE_TYPE_DEFINITION;
739
+ }
740
+ incomingData.node = {
741
+ kind: incomingData.kind,
742
+ name: (0, utils_1.stringToNameNode)(incomingData.name),
743
+ };
744
+ this.parentDefinitionDataByTypeName.set(incomingData.name, incomingData);
745
+ switch (incomingData.kind) {
746
+ case graphql_1.Kind.ENUM_TYPE_DEFINITION:
747
+ for (const [enumValueName, enumValueData] of incomingData.enumValueDataByValueName) {
748
+ enumValueData.node = {
749
+ directives: [],
750
+ kind: enumValueData.node.kind,
751
+ name: (0, utils_1.stringToNameNode)(enumValueData.name),
752
+ };
753
+ (0, utils_5.extractPersistedDirectives)(enumValueData.persistedDirectivesData, enumValueData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
754
+ if ((0, utils_5.isNodeDataInaccessible)(enumValueData)) {
755
+ this.inaccessiblePaths.add(`${incomingData.name}.${enumValueName}`);
756
+ }
757
+ }
758
+ return;
759
+ case graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
760
+ for (const [inputFieldName, inputValueData] of incomingData.inputValueDataByValueName) {
761
+ inputValueData.node = {
762
+ directives: [],
763
+ kind: inputValueData.node.kind,
764
+ name: (0, utils_1.stringToNameNode)(inputValueData.name),
765
+ type: inputValueData.type,
766
+ };
767
+ const namedInputFieldTypeName = (0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type);
768
+ const inputFieldPath = `${incomingData.name}.${inputFieldName}`;
769
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedInputFieldTypeName, () => new Set()).add(inputFieldPath);
770
+ this.namedInputValueTypeNames.add(namedInputFieldTypeName);
771
+ (0, utils_5.extractPersistedDirectives)(inputValueData.persistedDirectivesData, inputValueData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
772
+ if (isParentInaccessible || (0, utils_5.isNodeDataInaccessible)(inputValueData)) {
773
+ this.inaccessiblePaths.add(inputFieldPath);
774
+ }
775
+ }
776
+ return;
777
+ case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
778
+ // intentional fallthrough
779
+ case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
780
+ for (const fieldData of incomingData.fieldDataByFieldName.values()) {
781
+ fieldData.node = {
782
+ arguments: [],
783
+ directives: [],
784
+ kind: fieldData.node.kind,
785
+ name: (0, utils_1.stringToNameNode)(fieldData.name),
786
+ type: fieldData.type,
787
+ };
788
+ const fieldPath = `${fieldData.renamedParentTypeName}.${fieldData.name}`;
789
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, fieldData.namedTypeName, () => new Set()).add(fieldPath);
790
+ this.namedOutputTypeNames.add(fieldData.namedTypeName);
791
+ (0, utils_5.extractPersistedDirectives)(fieldData.persistedDirectivesData, fieldData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
792
+ const isFieldInaccessible = (0, utils_5.isNodeDataInaccessible)(fieldData);
793
+ if (isParentInaccessible || isFieldInaccessible) {
794
+ this.inaccessiblePaths.add(fieldPath);
795
+ }
796
+ for (const [argumentName, inputValueData] of fieldData.argumentDataByArgumentName) {
797
+ inputValueData.node = {
798
+ directives: [],
799
+ kind: inputValueData.node.kind,
800
+ name: (0, utils_1.stringToNameNode)(inputValueData.name),
801
+ type: inputValueData.type,
802
+ };
803
+ const namedArgumentTypeName = (0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type);
804
+ const argumentPath = `${fieldPath}(${argumentName}: ... )`;
805
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(argumentPath);
806
+ this.namedInputValueTypeNames.add(namedArgumentTypeName);
807
+ (0, utils_5.extractPersistedDirectives)(inputValueData.persistedDirectivesData, inputValueData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
808
+ /* If either the parent or the field to which the field belongs are declared inaccessible, the nullability
809
+ ** of the argument is not considered. However, if only the argument is declared inaccessible, it is an
810
+ ** error. */
811
+ this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, argumentPath, fieldPath);
812
+ }
813
+ }
814
+ return;
815
+ default:
816
+ // Scalar and Union
817
+ return;
818
+ }
819
+ }
820
+ (0, utils_5.setLongestDescription)(existingData, incomingData);
821
+ if (existingData.kind !== incomingData.kind) {
822
+ if (!entityInterfaceData ||
823
+ !entityInterfaceData.interfaceObjectSubgraphs.has(subgraphName) ||
824
+ existingData.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION ||
825
+ incomingData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
826
+ this.errors.push((0, errors_1.incompatibleParentKindMergeError)(existingData.name, (0, utils_3.kindToTypeString)(existingData.kind), (0, utils_3.kindToTypeString)(incomingData.kind)));
827
+ return;
828
+ }
829
+ }
830
+ switch (existingData.kind) {
831
+ case graphql_1.Kind.ENUM_TYPE_DEFINITION:
832
+ existingData.appearances += 1;
833
+ for (const data of incomingData.enumValueDataByValueName.values()) {
834
+ this.upsertEnumValueData(existingData.enumValueDataByValueName, data);
835
+ }
836
+ return;
837
+ case graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
838
+ if (isParentInaccessible && !existingData.isInaccessible) {
839
+ this.propagateInaccessibilityToExistingChildren(existingData);
840
+ }
841
+ (0, utils_3.addIterableValuesToSet)(incomingData.subgraphNames, existingData.subgraphNames);
842
+ for (const [inputFieldName, inputValueData] of incomingData
843
+ .inputValueDataByValueName) {
844
+ const inputFieldPath = `${incomingData.name}.${inputFieldName}`;
845
+ const namedInputFieldTypeName = (0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type);
846
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedInputFieldTypeName, () => new Set()).add(inputFieldPath);
847
+ this.namedInputValueTypeNames.add(namedInputFieldTypeName);
848
+ this.upsertInputValueData(existingData.inputValueDataByValueName, inputValueData);
849
+ if (isParentInaccessible || (0, utils_5.isNodeDataInaccessible)(inputValueData)) {
850
+ this.inaccessiblePaths.add(inputFieldPath);
851
+ }
852
+ }
853
+ return;
854
+ case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
855
+ // intentional fallthrough
856
+ case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
857
+ if (isParentInaccessible && !existingData.isInaccessible) {
858
+ this.propagateInaccessibilityToExistingChildren(existingData);
859
+ }
860
+ const objectData = incomingData;
861
+ if (objectData.persistedDirectivesData.tags.size > 0) {
862
+ const tagNames = (0, utils_3.getValueOrDefault)(this.tagNamesByPath, incomingData.name, () => new Set());
863
+ for (const tagName of objectData.persistedDirectivesData.tags.keys()) {
864
+ tagNames.add(tagName);
865
+ }
866
+ }
867
+ (0, utils_3.addIterableValuesToSet)(objectData.implementedInterfaceTypeNames, existingData.implementedInterfaceTypeNames);
868
+ (0, utils_3.addIterableValuesToSet)(objectData.subgraphNames, existingData.subgraphNames);
869
+ for (const fieldData of objectData.fieldDataByFieldName.values()) {
870
+ this.upsertFieldData(existingData.fieldDataByFieldName, fieldData, isParentInaccessible || existingData.isInaccessible);
871
+ }
872
+ return;
873
+ case graphql_1.Kind.UNION_TYPE_DEFINITION:
874
+ (0, utils_3.addMapEntries)(incomingData.memberByMemberTypeName, existingData.memberByMemberTypeName);
875
+ return;
876
+ default:
877
+ // Scalar type
878
+ return;
879
+ }
880
+ }
881
+ upsertObjectExtensionData(incomingData) {
882
+ const existingData = this.objectExtensionDataByTypeName.get(incomingData.name);
883
+ const baseData = existingData || incomingData;
884
+ (0, utils_5.extractPersistedDirectives)(baseData.persistedDirectivesData, incomingData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
885
+ const isParentInaccessible = (0, utils_5.isNodeDataInaccessible)(baseData);
886
+ if (isParentInaccessible) {
887
+ this.inaccessiblePaths.add(incomingData.name);
888
+ }
889
+ if (!existingData) {
890
+ incomingData.node = {
891
+ kind: incomingData.kind,
892
+ name: (0, utils_1.stringToNameNode)(incomingData.name),
893
+ };
894
+ for (const fieldData of incomingData.fieldDataByFieldName.values()) {
895
+ fieldData.node = {
896
+ arguments: [],
897
+ directives: [],
898
+ kind: fieldData.node.kind,
899
+ name: (0, utils_1.stringToNameNode)(fieldData.name),
900
+ type: fieldData.type,
901
+ };
902
+ const fieldPath = `${fieldData.renamedParentTypeName}.${fieldData.name}`;
903
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, fieldData.namedTypeName, () => new Set()).add(fieldPath);
904
+ this.namedOutputTypeNames.add(fieldData.namedTypeName);
905
+ (0, utils_5.extractPersistedDirectives)(fieldData.persistedDirectivesData, fieldData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
906
+ const isFieldInaccessible = (0, utils_5.isNodeDataInaccessible)(fieldData);
907
+ if (isParentInaccessible || isFieldInaccessible) {
908
+ this.inaccessiblePaths.add(fieldPath);
909
+ }
910
+ for (const [argumentName, inputValueData] of fieldData.argumentDataByArgumentName) {
911
+ inputValueData.node = {
912
+ directives: [],
913
+ kind: inputValueData.node.kind,
914
+ name: (0, utils_1.stringToNameNode)(inputValueData.name),
915
+ type: inputValueData.type,
916
+ };
917
+ const namedArgumentTypeName = (0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type);
918
+ const argumentPath = `${fieldPath}(${argumentName}: ... )`;
919
+ (0, utils_3.getValueOrDefault)(this.pathsByNamedTypeName, namedArgumentTypeName, () => new Set()).add(argumentPath);
920
+ this.namedInputValueTypeNames.add(namedArgumentTypeName);
921
+ (0, utils_5.extractPersistedDirectives)(inputValueData.persistedDirectivesData, inputValueData.directivesByDirectiveName, this.persistedDirectiveDefinitionByDirectiveName);
922
+ this.handleArgumentInaccessibility(isParentInaccessible || isFieldInaccessible, inputValueData, argumentPath, fieldPath);
923
+ }
924
+ }
925
+ this.objectExtensionDataByTypeName.set(incomingData.name, incomingData);
926
+ return;
927
+ }
928
+ if (isParentInaccessible && !existingData.isInaccessible) {
929
+ this.propagateInaccessibilityToExistingChildren(existingData);
930
+ }
931
+ (0, utils_3.addIterableValuesToSet)(incomingData.implementedInterfaceTypeNames, existingData.implementedInterfaceTypeNames);
932
+ (0, utils_3.addIterableValuesToSet)(incomingData.subgraphNames, existingData.subgraphNames);
933
+ for (const fieldData of incomingData.fieldDataByFieldName.values()) {
934
+ this.upsertFieldData(existingData.fieldDataByFieldName, fieldData, isParentInaccessible);
935
+ }
936
+ }
937
+ propagateInaccessibilityToExistingChildren(data) {
938
+ data.isInaccessible = true;
939
+ switch (data.kind) {
940
+ case graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
941
+ for (const inputFieldName of data.inputValueDataByValueName.keys()) {
942
+ this.inaccessiblePaths.add(`${data.name}.${inputFieldName}`);
943
+ }
944
+ break;
945
+ default:
946
+ for (const [fieldName, fieldData] of data.fieldDataByFieldName) {
947
+ const fieldPath = `${fieldData.renamedParentTypeName}.${fieldName}`;
948
+ this.inaccessiblePaths.add(fieldPath);
949
+ for (const [argumentName, inputValueData] of fieldData.argumentDataByArgumentName) {
950
+ const argumentPath = `${fieldPath}(${argumentName}: ... )`;
951
+ this.inaccessiblePaths.add(argumentPath);
952
+ }
953
+ }
954
+ }
955
+ }
956
+ upsertValidObjectExtensionData(incomingData) {
957
+ const isParentInaccessible = (0, utils_5.isNodeDataInaccessible)(incomingData);
958
+ const existingData = this.parentDefinitionDataByTypeName.get(incomingData.name);
959
+ if (!existingData) {
960
+ if (incomingData.isRootType) {
961
+ const authorizationData = this.authorizationDataByParentTypeName.get(incomingData.name);
962
+ for (const fieldData of incomingData.fieldDataByFieldName.values()) {
963
+ (0, utils_5.pushAuthorizationDirectives)(fieldData, authorizationData);
964
+ }
965
+ this.parentDefinitionDataByTypeName.set(incomingData.name, {
966
+ directivesByDirectiveName: incomingData.directivesByDirectiveName,
967
+ fieldDataByFieldName: incomingData.fieldDataByFieldName,
968
+ implementedInterfaceTypeNames: incomingData.implementedInterfaceTypeNames,
969
+ isRootType: true,
970
+ isInaccessible: isParentInaccessible,
971
+ isEntity: false,
972
+ kind: graphql_1.Kind.OBJECT_TYPE_DEFINITION,
973
+ name: incomingData.name,
974
+ node: {
975
+ kind: graphql_1.Kind.OBJECT_TYPE_DEFINITION,
976
+ name: (0, utils_1.stringToNameNode)(incomingData.name),
977
+ },
978
+ persistedDirectivesData: incomingData.persistedDirectivesData,
979
+ renamedTypeName: incomingData.renamedTypeName,
980
+ subgraphNames: incomingData.subgraphNames,
981
+ });
982
+ return;
983
+ }
984
+ this.errors.push((0, errors_1.noBaseTypeExtensionError)(incomingData.name));
985
+ return;
986
+ }
987
+ if (existingData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
988
+ this.errors.push((0, errors_1.incompatibleObjectExtensionOrphanBaseTypeError)(existingData.name, (0, utils_3.kindToTypeString)(existingData.kind)));
989
+ return;
990
+ }
991
+ (0, utils_5.upsertPersistedDirectivesData)(existingData.persistedDirectivesData, incomingData.persistedDirectivesData);
992
+ if (isParentInaccessible) {
993
+ this.inaccessiblePaths.add(incomingData.name);
994
+ // If the type was not previously known to be inaccessible, the existing children and arguments must be updated
995
+ if (!existingData.isInaccessible) {
996
+ this.propagateInaccessibilityToExistingChildren(existingData);
997
+ }
998
+ }
999
+ (0, utils_3.addIterableValuesToSet)(incomingData.implementedInterfaceTypeNames, existingData.implementedInterfaceTypeNames);
1000
+ for (const fieldData of incomingData.fieldDataByFieldName.values()) {
1001
+ this.upsertFieldData(existingData.fieldDataByFieldName, fieldData, isParentInaccessible);
1002
+ }
1003
+ }
1004
+ upsertPersistedDirectiveDefinitionData(incomingData, subgraphNumber) {
1005
+ const name = incomingData.name;
1006
+ const existingData = this.potentialPersistedDirectiveDefinitionDataByDirectiveName.get(name);
1007
+ if (!existingData) {
1008
+ // The executable directive must be defined in all subgraphs to be persisted.
1009
+ if (subgraphNumber > 1) {
1010
+ return;
1011
+ }
1012
+ const argumentDataByArgumentName = new Map();
1013
+ for (const inputValueData of incomingData.argumentDataByArgumentName.values()) {
1014
+ this.namedInputValueTypeNames.add((0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type));
1015
+ this.upsertInputValueData(argumentDataByArgumentName, inputValueData);
1016
+ }
1017
+ this.potentialPersistedDirectiveDefinitionDataByDirectiveName.set(name, {
1018
+ argumentDataByArgumentName,
1019
+ executableLocations: new Set(incomingData.executableLocations),
1020
+ name,
1021
+ repeatable: incomingData.repeatable,
1022
+ subgraphNames: new Set(incomingData.subgraphNames),
1023
+ description: incomingData.description,
1024
+ });
1025
+ return;
1026
+ }
1027
+ // If the executable directive has not been defined in at least one graph, the definition should not be persisted
1028
+ if (existingData.subgraphNames.size + 1 !== subgraphNumber) {
1029
+ this.potentialPersistedDirectiveDefinitionDataByDirectiveName.delete(name);
1030
+ return;
1031
+ }
1032
+ (0, utils_5.setMutualExecutableLocations)(existingData, incomingData.executableLocations);
1033
+ // If there are no mutually defined executable locations, the definition should not be persisted
1034
+ if (existingData.executableLocations.size < 1) {
1035
+ this.potentialPersistedDirectiveDefinitionDataByDirectiveName.delete(name);
1036
+ return;
1037
+ }
1038
+ for (const inputValueData of incomingData.argumentDataByArgumentName.values()) {
1039
+ this.namedInputValueTypeNames.add((0, ast_1.getTypeNodeNamedTypeName)(inputValueData.type));
1040
+ this.upsertInputValueData(existingData.argumentDataByArgumentName, inputValueData);
1041
+ }
1042
+ (0, utils_5.setLongestDescription)(existingData, incomingData);
1043
+ existingData.repeatable &&= incomingData.repeatable;
1044
+ (0, utils_3.addIterableValuesToSet)(incomingData.subgraphNames, existingData.subgraphNames);
1045
+ }
1046
+ /* federateInternalSubgraphData is responsible for merging each subgraph TypeScript representation of a GraphQL type
1047
+ ** into a single representation.
1048
+ ** This method is always necessary, regardless of whether federating a source graph or contract graph. */
1049
+ federateInternalSubgraphData() {
469
1050
  let subgraphNumber = 0;
470
- let isVersionTwo = false;
1051
+ let shouldSkipPersistedExecutableDirectives = false;
471
1052
  for (const internalSubgraph of this.internalSubgraphBySubgraphName.values()) {
472
1053
  subgraphNumber += 1;
473
1054
  this.currentSubgraphName = internalSubgraph.name;
474
- isVersionTwo ||= internalSubgraph.isVersionTwo;
1055
+ this.isVersionTwo ||= internalSubgraph.isVersionTwo;
475
1056
  (0, walkers_1.createMultiGraphAndRenameRootTypes)(this, internalSubgraph);
476
1057
  for (const parentDefinitionData of internalSubgraph.parentDefinitionDataByTypeName.values()) {
477
- (0, utils_4.upsertParentDefinitionData)(this.parentDefinitionDataByTypeName, parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.entityInterfaceFederationDataByTypeName, this.namedOutputTypeNames, this.namedInputValueTypeNames, internalSubgraph.name, this.errors);
1058
+ this.upsertParentDefinitionData(parentDefinitionData, internalSubgraph.name);
478
1059
  }
479
1060
  for (const objectExtensionData of internalSubgraph.parentExtensionDataByTypeName.values()) {
480
- (0, utils_4.upsertObjectExtensionData)(this.objectExtensionDataByTypeName, objectExtensionData, this.persistedDirectiveDefinitionByDirectiveName, this.namedOutputTypeNames, this.namedInputValueTypeNames, this.errors);
1061
+ this.upsertObjectExtensionData(objectExtensionData);
481
1062
  }
482
1063
  if (shouldSkipPersistedExecutableDirectives) {
483
1064
  continue;
@@ -489,41 +1070,30 @@ class FederationFactory {
489
1070
  continue;
490
1071
  }
491
1072
  for (const persistedDirectiveDefinitionData of internalSubgraph.persistedDirectiveDefinitionDataByDirectiveName.values()) {
492
- (0, utils_4.upsertPersistedDirectiveDefinitionData)(persistedDirectiveDefinitionDataByDirectiveName, persistedDirectiveDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.namedInputValueTypeNames, subgraphNumber, this.errors);
1073
+ this.upsertPersistedDirectiveDefinitionData(persistedDirectiveDefinitionData, subgraphNumber);
493
1074
  }
494
- /* Invalid directives keys are deleted; if there are no entries left, it is no longer necessary to evaluate more
1075
+ /* Invalid directive keys are deleted; if there are no entries left, it is no longer necessary to evaluate more
495
1076
  executable directives. */
496
- if (!persistedDirectiveDefinitionDataByDirectiveName.size) {
1077
+ if (this.potentialPersistedDirectiveDefinitionDataByDirectiveName.size < 1) {
497
1078
  shouldSkipPersistedExecutableDirectives = true;
498
1079
  }
499
1080
  }
500
- const definitions = isVersionTwo
501
- ? [
502
- constants_1.AUTHENTICATED_DEFINITION,
503
- constants_1.DEPRECATED_DEFINITION,
504
- constants_1.INACCESSIBLE_DEFINITION,
505
- constants_1.REQUIRES_SCOPES_DEFINITION,
506
- constants_1.TAG_DEFINITION,
507
- constants_1.SCOPE_SCALAR_DEFINITION,
508
- ]
509
- : [constants_1.DEPRECATED_DEFINITION, constants_1.TAG_DEFINITION];
510
- for (const data of persistedDirectiveDefinitionDataByDirectiveName.values()) {
511
- (0, utils_4.addValidPersistedDirectiveDefinitionNodeByData)(definitions, data, this.persistedDirectiveDefinitionByDirectiveName, this.errors);
512
- }
1081
+ }
1082
+ handleEntityInterfaces() {
513
1083
  for (const [typeName, entityInterfaceData] of this.entityInterfaceFederationDataByTypeName) {
514
- (0, utils_2.subtractSourceSetFromTargetSet)(entityInterfaceData.interfaceFieldNames, entityInterfaceData.interfaceObjectFieldNames);
515
- const entityInterface = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, typeName, 'parentDefinitionDataByTypeName');
1084
+ (0, utils_3.subtractSourceSetFromTargetSet)(entityInterfaceData.interfaceFieldNames, entityInterfaceData.interfaceObjectFieldNames);
1085
+ const entityInterface = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, typeName, string_constants_1.PARENT_DEFINITION_DATA);
516
1086
  if (entityInterface.kind !== graphql_1.Kind.INTERFACE_TYPE_DEFINITION) {
517
1087
  // TODO error
518
1088
  continue;
519
1089
  }
520
1090
  for (const subgraphName of entityInterfaceData.interfaceObjectSubgraphs) {
521
- const configurationDataMap = (0, utils_2.getOrThrowError)(this.internalSubgraphBySubgraphName, subgraphName, 'internalSubgraphBySubgraphName').configurationDataByParentTypeName;
1091
+ const configurationDataMap = (0, utils_3.getOrThrowError)(this.internalSubgraphBySubgraphName, subgraphName, 'internalSubgraphBySubgraphName').configurationDataByParentTypeName;
522
1092
  const concreteTypeNames = this.concreteTypeNamesByAbstractTypeName.get(typeName);
523
1093
  if (!concreteTypeNames) {
524
1094
  continue;
525
1095
  }
526
- const interfaceObjectConfiguration = (0, utils_2.getOrThrowError)(configurationDataMap, typeName, 'configurationDataMap');
1096
+ const interfaceObjectConfiguration = (0, utils_3.getOrThrowError)(configurationDataMap, typeName, 'configurationDataMap');
527
1097
  const keys = interfaceObjectConfiguration.keys;
528
1098
  if (!keys) {
529
1099
  // TODO no keys error
@@ -538,14 +1108,14 @@ class FederationFactory {
538
1108
  continue;
539
1109
  }
540
1110
  if (authorizationData) {
541
- const concreteAuthorizationData = (0, utils_2.getValueOrDefault)(this.authorizationDataByParentTypeName, concreteTypeName, () => (0, utils_2.newAuthorizationData)(concreteTypeName));
1111
+ const concreteAuthorizationData = (0, utils_3.getValueOrDefault)(this.authorizationDataByParentTypeName, concreteTypeName, () => (0, utils_3.newAuthorizationData)(concreteTypeName));
542
1112
  for (const fieldAuthorizationData of authorizationData.fieldAuthorizationDataByFieldName.values()) {
543
- if (!(0, utils_2.upsertFieldAuthorizationData)(concreteAuthorizationData.fieldAuthorizationDataByFieldName, fieldAuthorizationData)) {
1113
+ if (!(0, utils_3.upsertFieldAuthorizationData)(concreteAuthorizationData.fieldAuthorizationDataByFieldName, fieldAuthorizationData)) {
544
1114
  this.invalidOrScopesHostPaths.add(`${concreteTypeName}.${fieldAuthorizationData.fieldName}`);
545
1115
  }
546
1116
  }
547
1117
  }
548
- const concreteTypeData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, concreteTypeName, 'parentDefinitionDataByTypeName');
1118
+ const concreteTypeData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, concreteTypeName, string_constants_1.PARENT_DEFINITION_DATA);
549
1119
  if (concreteTypeData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
550
1120
  continue;
551
1121
  }
@@ -567,103 +1137,89 @@ class FederationFactory {
567
1137
  // TODO handle shareability
568
1138
  continue;
569
1139
  }
570
- const interfaceFieldData = (0, utils_2.getOrThrowError)(entityInterface.fieldDataByFieldName, fieldName, `${typeName}.fieldDataByFieldName`);
1140
+ const interfaceFieldData = (0, utils_3.getOrThrowError)(entityInterface.fieldDataByFieldName, fieldName, `${typeName}.fieldDataByFieldName`);
571
1141
  concreteTypeData.fieldDataByFieldName.set(fieldName, { ...interfaceFieldData });
572
1142
  }
573
1143
  configurationDataMap.set(concreteTypeName, configurationData);
574
1144
  }
575
1145
  }
576
1146
  }
577
- if (this.invalidOrScopesHostPaths.size > 0) {
578
- this.errors.push((0, errors_1.orScopesLimitError)(utils_2.maxOrScopes, [...this.invalidOrScopesHostPaths]));
579
- }
580
- for (const [parentTypeName, objectExtensionData] of this.objectExtensionDataByTypeName) {
581
- (0, utils_4.upsertValidObjectExtensionData)(this.parentDefinitionDataByTypeName, objectExtensionData, this.persistedDirectiveDefinitionByDirectiveName, this.namedOutputTypeNames, this.namedInputValueTypeNames, this.errors, this.authorizationDataByParentTypeName.get(parentTypeName));
582
- }
583
- // for (const [typeName, extension] of this.extensions) {
584
- // this.parentTypeName = typeName;
585
- // if (extension.isRootType && !this.parents.has(typeName)) {
586
- // this.upsertParentNode(objectTypeExtensionNodeToMutableDefinitionNode(extension.node));
587
- // }
588
- // const baseObject = this.parents.get(typeName);
589
- // if (!baseObject) {
590
- // this.errors.push(noBaseTypeExtensionError(typeName));
591
- // continue;
592
- // }
593
- //
594
- // if (baseObject.kind !== Kind.OBJECT_TYPE_DEFINITION) {
595
- // throw incompatibleParentKindFatalError(typeName, Kind.OBJECT_TYPE_DEFINITION, baseObject.kind);
596
- // }
597
- // this.upsertExtensionPersistedDirectives(extension.directives, baseObject.directives);
598
- // for (const [extensionFieldName, extensionFieldContainer] of extension.fields) {
599
- // const baseFieldContainer = baseObject.fields.get(extensionFieldName);
600
- // if (!baseFieldContainer) {
601
- // baseObject.fields.set(extensionFieldName, extensionFieldContainer);
602
- // continue;
603
- // }
604
- // if (baseFieldContainer.isShareable && extensionFieldContainer.isShareable) {
605
- // this.childName = extensionFieldName;
606
- // this.upsertExtensionFieldArguments(extensionFieldContainer.arguments, baseFieldContainer.arguments);
607
- // addIterableValuesToSet(extensionFieldContainer.subgraphNames, baseFieldContainer.subgraphNames);
608
- // continue;
609
- // }
610
- // const parent = this.shareableErrorTypeNames.get(typeName);
611
- // if (parent) {
612
- // parent.add(extensionFieldName);
613
- // continue;
614
- // }
615
- // this.shareableErrorTypeNames.set(typeName, new Set<string>([extensionFieldName]));
616
- // }
617
- // for (const interfaceName of extension.interfaces) {
618
- // baseObject.interfaces.add(interfaceName);
619
- // }
620
- // }
621
- // for (const [parentTypeName, children] of this.shareableErrorTypeNames) {
622
- // const parent = getOrThrowError(this.parents, parentTypeName, PARENTS);
623
- // if (parent.kind !== Kind.OBJECT_TYPE_DEFINITION) {
624
- // throw incompatibleParentKindFatalError(parentTypeName, Kind.OBJECT_TYPE_DEFINITION, parent.kind);
625
- // }
626
- // this.errors.push(shareableFieldDefinitionsError(parent, children));
627
- // }
628
- const definitionsWithInterfaces = [];
1147
+ }
1148
+ pushParentDefinitionDataToDocumentDefinitions(interfaceImplementations) {
629
1149
  for (const [parentTypeName, parentDefinitionData] of this.parentDefinitionDataByTypeName) {
630
1150
  switch (parentDefinitionData.kind) {
631
1151
  case graphql_1.Kind.ENUM_TYPE_DEFINITION:
632
1152
  const enumValueNodes = [];
1153
+ const clientEnumValueNodes = [];
633
1154
  const mergeMethod = this.getEnumValueMergeMethod(parentTypeName);
634
1155
  for (const enumValueData of parentDefinitionData.enumValueDataByValueName.values()) {
635
- const enumValueNode = (0, utils_4.getNodeWithPersistedDirectivesByData)(enumValueData, this.persistedDirectiveDefinitionByDirectiveName, this.errors);
1156
+ const enumValueNode = (0, utils_5.getNodeForRouterSchemaByData)(enumValueData, this.persistedDirectiveDefinitionByDirectiveName, this.errors);
1157
+ const isValueInaccessible = (0, utils_5.isNodeDataInaccessible)(enumValueData);
1158
+ const clientEnumValueNode = {
1159
+ ...enumValueData.node,
1160
+ directives: (0, utils_5.getClientPersistedDirectiveNodes)(enumValueData),
1161
+ };
636
1162
  switch (mergeMethod) {
637
- case utils_4.MergeMethod.CONSISTENT:
1163
+ case utils_5.MergeMethod.CONSISTENT:
638
1164
  if (parentDefinitionData.appearances > enumValueData.appearances) {
639
1165
  this.errors.push((0, errors_1.incompatibleSharedEnumError)(parentTypeName));
640
1166
  }
641
1167
  enumValueNodes.push(enumValueNode);
1168
+ if (!isValueInaccessible) {
1169
+ clientEnumValueNodes.push(clientEnumValueNode);
1170
+ }
642
1171
  break;
643
- case utils_4.MergeMethod.INTERSECTION:
1172
+ case utils_5.MergeMethod.INTERSECTION:
644
1173
  if (parentDefinitionData.appearances === enumValueData.appearances) {
645
1174
  enumValueNodes.push(enumValueNode);
1175
+ if (!isValueInaccessible) {
1176
+ clientEnumValueNodes.push(clientEnumValueNode);
1177
+ }
646
1178
  }
647
1179
  break;
648
1180
  default:
649
1181
  enumValueNodes.push(enumValueNode);
1182
+ if (!isValueInaccessible) {
1183
+ clientEnumValueNodes.push(clientEnumValueNode);
1184
+ }
650
1185
  break;
651
1186
  }
652
1187
  }
653
1188
  parentDefinitionData.node.values = enumValueNodes;
654
- definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1189
+ this.routerDefinitions.push((0, utils_5.getNodeForRouterSchemaByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1190
+ if ((0, utils_5.isNodeDataInaccessible)(parentDefinitionData)) {
1191
+ this.validateReferencesOfInaccessibleType(parentDefinitionData);
1192
+ break;
1193
+ }
1194
+ if (clientEnumValueNodes.length < 1) {
1195
+ this.errors.push((0, errors_1.allChildDefinitionsAreInaccessibleError)((0, utils_3.kindToTypeString)(parentDefinitionData.kind), parentTypeName, 'enum value'));
1196
+ break;
1197
+ }
1198
+ this.clientDefinitions.push({
1199
+ ...parentDefinitionData.node,
1200
+ directives: (0, utils_5.getClientPersistedDirectiveNodes)(parentDefinitionData),
1201
+ values: clientEnumValueNodes,
1202
+ });
655
1203
  break;
656
1204
  case graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
657
1205
  const invalidRequiredInputs = [];
658
1206
  const inputValueNodes = [];
1207
+ const clientInputValueNodes = [];
659
1208
  for (const [inputValueName, inputValueData] of parentDefinitionData.inputValueDataByValueName) {
660
1209
  if (parentDefinitionData.subgraphNames.size === inputValueData.subgraphNames.size) {
661
- inputValueNodes.push((0, utils_4.getNodeWithPersistedDirectivesByInputValueData)(inputValueData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1210
+ inputValueNodes.push((0, utils_5.getNodeWithPersistedDirectivesByInputValueData)(inputValueData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1211
+ if ((0, utils_5.isNodeDataInaccessible)(inputValueData)) {
1212
+ continue;
1213
+ }
1214
+ clientInputValueNodes.push({
1215
+ ...inputValueData.node,
1216
+ directives: (0, utils_5.getClientPersistedDirectiveNodes)(inputValueData),
1217
+ });
662
1218
  }
663
- else if ((0, utils_4.isTypeRequired)(inputValueData.type)) {
1219
+ else if ((0, utils_5.isTypeRequired)(inputValueData.type)) {
664
1220
  invalidRequiredInputs.push({
665
1221
  inputValueName,
666
- missingSubgraphs: (0, utils_2.getEntriesNotInHashSet)(parentDefinitionData.subgraphNames, inputValueData.subgraphNames),
1222
+ missingSubgraphs: (0, utils_3.getEntriesNotInHashSet)(parentDefinitionData.subgraphNames, inputValueData.subgraphNames),
667
1223
  requiredSubgraphs: [...inputValueData.requiredSubgraphNames],
668
1224
  });
669
1225
  }
@@ -673,24 +1229,39 @@ class FederationFactory {
673
1229
  break;
674
1230
  }
675
1231
  parentDefinitionData.node.fields = inputValueNodes;
676
- definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1232
+ this.routerDefinitions.push((0, utils_5.getNodeForRouterSchemaByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1233
+ if ((0, utils_5.isNodeDataInaccessible)(parentDefinitionData)) {
1234
+ this.validateReferencesOfInaccessibleType(parentDefinitionData);
1235
+ break;
1236
+ }
1237
+ if (clientInputValueNodes.length < 1) {
1238
+ this.errors.push((0, errors_1.allChildDefinitionsAreInaccessibleError)((0, utils_3.kindToTypeString)(parentDefinitionData.kind), parentTypeName, 'input field'));
1239
+ break;
1240
+ }
1241
+ this.clientDefinitions.push({
1242
+ ...parentDefinitionData.node,
1243
+ directives: (0, utils_5.getClientPersistedDirectiveNodes)(parentDefinitionData),
1244
+ fields: clientInputValueNodes,
1245
+ });
677
1246
  break;
678
1247
  case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
679
1248
  // intentional fallthrough
680
1249
  case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
681
1250
  const fieldNodes = [];
1251
+ const clientSchemaFieldNodes = [];
682
1252
  const invalidFieldNames = new Set();
683
1253
  const isObject = parentDefinitionData.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION;
684
1254
  for (const [fieldName, fieldData] of parentDefinitionData.fieldDataByFieldName) {
685
- (0, utils_4.pushAuthorizationDirectives)(fieldData, this.authorizationDataByParentTypeName.get(parentTypeName));
686
- const argumentNodes = (0, utils_4.getValidFieldArgumentNodes)(fieldData, this.persistedDirectiveDefinitionByDirectiveName, this.fieldConfigurationByFieldPath, this.errors);
687
- if (isObject && !(0, utils_4.isShareabilityOfAllFieldInstancesValid)(fieldData)) {
1255
+ (0, utils_5.pushAuthorizationDirectives)(fieldData, this.authorizationDataByParentTypeName.get(parentTypeName));
1256
+ const argumentNodes = (0, utils_5.getValidFieldArgumentNodes)(fieldData, this.persistedDirectiveDefinitionByDirectiveName, this.fieldConfigurationByFieldPath, this.errors);
1257
+ if (isObject && !(0, utils_5.isShareabilityOfAllFieldInstancesValid)(fieldData)) {
688
1258
  invalidFieldNames.add(fieldName);
689
1259
  }
1260
+ fieldNodes.push((0, utils_5.getNodeWithPersistedDirectivesByFieldData)(fieldData, this.persistedDirectiveDefinitionByDirectiveName, argumentNodes, this.errors));
690
1261
  if (fieldData.isInaccessible) {
691
1262
  continue;
692
1263
  }
693
- fieldNodes.push((0, utils_4.getNodeWithPersistedDirectivesByFieldData)(fieldData, this.persistedDirectiveDefinitionByDirectiveName, argumentNodes, this.errors));
1264
+ clientSchemaFieldNodes.push((0, utils_5.getClientSchemaFieldNodeByFieldData)(fieldData));
694
1265
  }
695
1266
  if (isObject && invalidFieldNames.size > 0) {
696
1267
  this.errors.push((0, errors_1.invalidFieldShareabilityError)(parentDefinitionData, invalidFieldNames));
@@ -698,201 +1269,269 @@ class FederationFactory {
698
1269
  parentDefinitionData.node.fields = fieldNodes;
699
1270
  // Implemented interfaces can only be validated after all fields are merged
700
1271
  if (parentDefinitionData.implementedInterfaceTypeNames.size > 0) {
701
- definitionsWithInterfaces.push(parentDefinitionData);
702
- }
703
- else {
704
- definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1272
+ interfaceImplementations.push({ data: parentDefinitionData, clientSchemaFieldNodes });
1273
+ break;
705
1274
  }
706
- if (fieldNodes.length < 1) {
707
- if ((0, utils_3.isNodeQuery)(parentTypeName)) {
708
- this.errors.push(errors_1.noQueryRootTypeError);
709
- }
710
- else {
711
- this.errors.push((0, errors_1.allFieldDefinitionsAreInaccessibleError)((0, utils_2.kindToTypeString)(parentDefinitionData.kind), parentTypeName));
1275
+ this.routerDefinitions.push((0, utils_5.getNodeForRouterSchemaByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1276
+ const isQuery = (0, utils_4.isNodeQuery)(parentTypeName);
1277
+ if ((0, utils_5.isNodeDataInaccessible)(parentDefinitionData)) {
1278
+ if (isQuery) {
1279
+ this.errors.push(errors_1.inaccessibleQueryRootTypeError);
1280
+ break;
712
1281
  }
1282
+ this.validateReferencesOfInaccessibleType(parentDefinitionData);
1283
+ break;
1284
+ }
1285
+ if (clientSchemaFieldNodes.length < 1) {
1286
+ const error = isQuery
1287
+ ? errors_1.noQueryRootTypeError
1288
+ : (0, errors_1.allChildDefinitionsAreInaccessibleError)((0, utils_3.kindToTypeString)(parentDefinitionData.kind), parentTypeName, string_constants_1.FIELD);
1289
+ this.errors.push(error);
1290
+ break;
713
1291
  }
1292
+ this.clientDefinitions.push({
1293
+ ...parentDefinitionData.node,
1294
+ directives: (0, utils_5.getClientPersistedDirectiveNodes)(parentDefinitionData),
1295
+ fields: clientSchemaFieldNodes,
1296
+ });
714
1297
  break;
715
1298
  case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
716
- if (!constants_1.BASE_SCALARS.has(parentTypeName)) {
717
- definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1299
+ if (constants_1.BASE_SCALARS.has(parentTypeName)) {
1300
+ break;
1301
+ }
1302
+ this.routerDefinitions.push((0, utils_5.getNodeForRouterSchemaByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1303
+ if ((0, utils_5.isNodeDataInaccessible)(parentDefinitionData)) {
1304
+ this.validateReferencesOfInaccessibleType(parentDefinitionData);
1305
+ break;
718
1306
  }
1307
+ this.clientDefinitions.push({
1308
+ ...parentDefinitionData.node,
1309
+ directives: (0, utils_5.getClientPersistedDirectiveNodes)(parentDefinitionData),
1310
+ });
719
1311
  break;
720
1312
  case graphql_1.Kind.UNION_TYPE_DEFINITION:
721
- parentDefinitionData.node.types = (0, utils_2.mapToArrayOfValues)(parentDefinitionData.memberByMemberTypeName);
722
- definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1313
+ parentDefinitionData.node.types = (0, utils_3.mapToArrayOfValues)(parentDefinitionData.memberByMemberTypeName);
1314
+ this.routerDefinitions.push((0, utils_5.getNodeForRouterSchemaByData)(parentDefinitionData, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1315
+ if ((0, utils_5.isNodeDataInaccessible)(parentDefinitionData)) {
1316
+ this.validateReferencesOfInaccessibleType(parentDefinitionData);
1317
+ break;
1318
+ }
1319
+ const clientMembers = this.getClientSchemaUnionMembers(parentDefinitionData);
1320
+ if (clientMembers.length < 1) {
1321
+ this.errors.push((0, errors_1.allChildDefinitionsAreInaccessibleError)(string_constants_1.UNION, parentTypeName, 'union member type'));
1322
+ break;
1323
+ }
1324
+ this.clientDefinitions.push({
1325
+ ...parentDefinitionData.node,
1326
+ directives: (0, utils_5.getClientPersistedDirectiveNodes)(parentDefinitionData),
1327
+ types: clientMembers,
1328
+ });
723
1329
  break;
724
1330
  }
725
1331
  }
726
- // for (const [parentTypeName, parentContainer] of this.parents) {
727
- // switch (parentContainer.kind) {
728
- // case Kind.ENUM_TYPE_DEFINITION:
729
- // const values: MutableEnumValueDefinitionNode[] = [];
730
- // const mergeMethod = this.getEnumMergeMethod(parentTypeName);
731
- // for (const enumValueContainer of parentContainer.values.values()) {
732
- // pushPersistedDirectivesAndGetNode(enumValueContainer);
733
- // switch (mergeMethod) {
734
- // case MergeMethod.CONSISTENT:
735
- // if (enumValueContainer.appearances < parentContainer.appearances) {
736
- // this.errors.push(incompatibleSharedEnumError(parentTypeName));
737
- // }
738
- // values.push(enumValueContainer.node);
739
- // break;
740
- // case MergeMethod.INTERSECTION:
741
- // if (enumValueContainer.appearances === parentContainer.appearances) {
742
- // values.push(enumValueContainer.node);
743
- // }
744
- // break;
745
- // default:
746
- // values.push(enumValueContainer.node);
747
- // break;
748
- // }
749
- // }
750
- // parentContainer.node.values = values;
751
- // definitions.push(pushPersistedDirectivesAndGetNode(parentContainer));
752
- // break;
753
- // case Kind.INPUT_OBJECT_TYPE_DEFINITION:
754
- // const inputValues: InputValueDefinitionNode[] = [];
755
- // for (const inputValueContainer of parentContainer.fields.values()) {
756
- // pushPersistedDirectivesAndGetNode(inputValueContainer);
757
- // if (parentContainer.appearances === inputValueContainer.appearances) {
758
- // inputValues.push(inputValueContainer.node);
759
- // } else if (isTypeRequired(inputValueContainer.node.type)) {
760
- // this.errors.push(federationRequiredInputFieldError(parentTypeName, inputValueContainer.node.name.value));
761
- // break;
762
- // }
763
- // }
764
- // parentContainer.node.fields = inputValues;
765
- // definitions.push(pushPersistedDirectivesAndGetNode(parentContainer));
766
- // break;
767
- // case Kind.INTERFACE_TYPE_DEFINITION:
768
- // const interfaceFields: FieldDefinitionNode[] = [];
769
- // for (const fieldContainer of parentContainer.fields.values()) {
770
- // if (isFieldInaccessible(fieldContainer)) {
771
- // continue;
772
- // }
773
- // interfaceFields.push(this.getMergedFieldDefinitionNode(fieldContainer, parentTypeName));
774
- // }
775
- // parentContainer.node.fields = interfaceFields;
776
- // pushPersistedDirectivesAndGetNode(parentContainer);
777
- // // Interface implementations can only be evaluated after they've been fully merged
778
- // if (parentContainer.interfaces.size > 0) {
779
- // definitionsWithInterfaces.push(parentContainer);
780
- // } else {
781
- // definitions.push(parentContainer.node);
782
- // }
783
- // if (interfaceFields.length < 1) {
784
- // this.errors.push(allFieldDefinitionsAreInaccessibleError('interface', parentTypeName));
785
- // }
786
- // break;
787
- // case Kind.OBJECT_TYPE_DEFINITION:
788
- // const fields: FieldDefinitionNode[] = [];
789
- // for (const fieldContainer of parentContainer.fields.values()) {
790
- // if (isFieldInaccessible(fieldContainer)) {
791
- // continue;
792
- // }
793
- // fields.push(this.getMergedFieldDefinitionNode(fieldContainer, parentTypeName));
794
- // }
795
- // parentContainer.node.fields = fields;
796
- // pushPersistedDirectivesAndGetNode(parentContainer);
797
- // // Interface implementations can only be evaluated after they've been fully merged
798
- // if (parentContainer.interfaces.size > 0) {
799
- // definitionsWithInterfaces.push(parentContainer);
800
- // }
801
- // } else {
802
- // definitions.push(parentContainer.node);
803
- // }
804
- // if (fields.length < 1) {
805
- // if (isNodeQuery(parentTypeName)) {
806
- // this.errors.push(noQueryRootTypeError);
807
- // } else {
808
- // this.errors.push(allFieldDefinitionsAreInaccessibleError('object', parentTypeName));
809
- // }
810
- // }
811
- // break;
812
- // case Kind.SCALAR_TYPE_DEFINITION:
813
- // if (!BASE_SCALARS.has(parentTypeName)) {
814
- // definitions.push(pushPersistedDirectivesAndGetNode(parentContainer));
815
- // }
816
- // break;
817
- // case Kind.UNION_TYPE_DEFINITION:
818
- // const types: NamedTypeNode[] = [];
819
- // for (const memberName of parentContainer.members) {
820
- // types.push(stringToNamedTypeNode(memberName));
821
- // }
822
- // parentContainer.node.types = types;
823
- // definitions.push(pushPersistedDirectivesAndGetNode(parentContainer));
824
- // break;
825
- // }
826
- // }
827
- for (const data of definitionsWithInterfaces) {
828
- data.node.interfaces = this.getValidImplementedInterfaces(data);
829
- definitions.push((0, utils_4.getNodeWithPersistedDirectivesByData)(data, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1332
+ }
1333
+ federateSubgraphData() {
1334
+ this.federateInternalSubgraphData();
1335
+ this.handleEntityInterfaces();
1336
+ for (const [parentTypeName, objectExtensionData] of this.objectExtensionDataByTypeName) {
1337
+ this.upsertValidObjectExtensionData(objectExtensionData);
1338
+ }
1339
+ // generate the map of tag data that is used by contracts
1340
+ this.generateTagData();
1341
+ this.pushVersionTwoDirectiveDefinitionsToDocumentDefinitions();
1342
+ }
1343
+ validateInterfaceImplementationsAndPushToDocumentDefinitions(interfaceImplementations) {
1344
+ for (const { data, clientSchemaFieldNodes } of interfaceImplementations) {
1345
+ const validInterfaces = this.getValidImplementedInterfaces(data);
1346
+ data.node.interfaces = validInterfaces;
1347
+ this.routerDefinitions.push((0, utils_5.getNodeForRouterSchemaByData)(data, this.persistedDirectiveDefinitionByDirectiveName, this.errors));
1348
+ if ((0, utils_5.isNodeDataInaccessible)(data)) {
1349
+ this.validateReferencesOfInaccessibleType(data);
1350
+ continue;
1351
+ }
1352
+ const clientInterfaces = [];
1353
+ for (const interfaceTypeName of data.implementedInterfaceTypeNames) {
1354
+ if (!this.inaccessiblePaths.has(interfaceTypeName)) {
1355
+ clientInterfaces.push((0, utils_1.stringToNamedTypeNode)(interfaceTypeName));
1356
+ }
1357
+ }
1358
+ this.clientDefinitions.push({
1359
+ ...data.node,
1360
+ directives: (0, utils_5.getClientPersistedDirectiveNodes)(data),
1361
+ fields: clientSchemaFieldNodes,
1362
+ interfaces: clientInterfaces,
1363
+ });
1364
+ }
1365
+ }
1366
+ pushVersionTwoDirectiveDefinitionsToDocumentDefinitions() {
1367
+ if (!this.isVersionTwo) {
1368
+ return;
1369
+ }
1370
+ this.routerDefinitions = [
1371
+ constants_1.AUTHENTICATED_DEFINITION,
1372
+ constants_1.DEPRECATED_DEFINITION,
1373
+ constants_1.INACCESSIBLE_DEFINITION,
1374
+ constants_1.REQUIRES_SCOPES_DEFINITION,
1375
+ constants_1.TAG_DEFINITION,
1376
+ constants_1.SCOPE_SCALAR_DEFINITION,
1377
+ ];
1378
+ this.clientDefinitions = [
1379
+ constants_1.AUTHENTICATED_DEFINITION,
1380
+ constants_1.DEPRECATED_DEFINITION,
1381
+ constants_1.REQUIRES_SCOPES_DEFINITION,
1382
+ constants_1.SCOPE_SCALAR_DEFINITION,
1383
+ ];
1384
+ }
1385
+ validateReferencesOfInaccessibleType(data) {
1386
+ const paths = this.pathsByNamedTypeName.get(data.name);
1387
+ if (!paths || paths.size < 1) {
1388
+ return;
1389
+ }
1390
+ const invalidPaths = [];
1391
+ for (const path of paths) {
1392
+ if (!this.inaccessiblePaths.has(path)) {
1393
+ invalidPaths.push(path);
1394
+ }
1395
+ }
1396
+ if (invalidPaths.length > 0) {
1397
+ this.errors.push((0, errors_1.invalidReferencesOfInaccessibleTypeError)((0, utils_3.kindToTypeString)(data.kind), data.name, invalidPaths));
830
1398
  }
1399
+ }
1400
+ validateQueryRootType() {
831
1401
  const query = this.parentDefinitionDataByTypeName.get(string_constants_1.QUERY);
832
1402
  if (!query || query.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION || query.fieldDataByFieldName.size < 1) {
833
1403
  this.errors.push(errors_1.noQueryRootTypeError);
1404
+ return;
1405
+ }
1406
+ for (const fieldData of query.fieldDataByFieldName.values()) {
1407
+ if (!(0, utils_5.isNodeDataInaccessible)(fieldData)) {
1408
+ return;
1409
+ }
1410
+ }
1411
+ this.errors.push(errors_1.noQueryRootTypeError);
1412
+ }
1413
+ buildFederationResult() {
1414
+ if (this.invalidOrScopesHostPaths.size > 0) {
1415
+ this.errors.push((0, errors_1.orScopesLimitError)(utils_3.maxOrScopes, [...this.invalidOrScopesHostPaths]));
1416
+ }
1417
+ for (const data of this.potentialPersistedDirectiveDefinitionDataByDirectiveName.values()) {
1418
+ (0, utils_5.addValidPersistedDirectiveDefinitionNodeByData)(this.routerDefinitions, data, this.persistedDirectiveDefinitionByDirectiveName, this.errors);
834
1419
  }
1420
+ const definitionsWithInterfaces = [];
1421
+ this.pushParentDefinitionDataToDocumentDefinitions(definitionsWithInterfaces);
1422
+ this.validateInterfaceImplementationsAndPushToDocumentDefinitions(definitionsWithInterfaces);
1423
+ this.validateQueryRootType();
835
1424
  // return any composition errors before checking whether all fields are resolvable
836
1425
  if (this.errors.length > 0) {
837
1426
  return { errors: this.errors };
838
1427
  }
839
- // TODO add back resolvability check
840
- for (const rootTypeName of string_constants_1.ROOT_TYPES) {
841
- const rootTypeData = this.parentDefinitionDataByTypeName.get(rootTypeName);
842
- if (!rootTypeData || rootTypeData.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION) {
843
- continue;
1428
+ /* Resolvability evaluations are not necessary for contracts because the source graph resolvability checks must
1429
+ ** have already completed without error. */
1430
+ const warnings = this.warnings.length > 0 ? { warnings: this.warnings } : {};
1431
+ this.evaluateRootNodeFieldsResolvability();
1432
+ if (this.errors.length > 0) {
1433
+ return { errors: this.errors, ...warnings };
1434
+ }
1435
+ const newRouterAST = {
1436
+ kind: graphql_1.Kind.DOCUMENT,
1437
+ definitions: this.routerDefinitions,
1438
+ };
1439
+ const newClientAST = {
1440
+ kind: graphql_1.Kind.DOCUMENT,
1441
+ definitions: this.clientDefinitions,
1442
+ };
1443
+ const subgraphConfigBySubgraphName = new Map();
1444
+ for (const subgraph of this.internalSubgraphBySubgraphName.values()) {
1445
+ subgraphConfigBySubgraphName.set(subgraph.name, {
1446
+ configurationDataMap: subgraph.configurationDataByParentTypeName,
1447
+ schema: subgraph.schema,
1448
+ });
1449
+ }
1450
+ for (const authorizationData of this.authorizationDataByParentTypeName.values()) {
1451
+ (0, utils_3.upsertAuthorizationConfiguration)(this.fieldConfigurationByFieldPath, authorizationData);
1452
+ }
1453
+ return {
1454
+ federationResult: {
1455
+ fieldConfigurations: Array.from(this.fieldConfigurationByFieldPath.values()),
1456
+ subgraphConfigBySubgraphName,
1457
+ federatedGraphAST: newRouterAST,
1458
+ federatedGraphSchema: (0, graphql_1.buildASTSchema)(newRouterAST),
1459
+ federatedGraphClientSchema: (0, graphql_1.buildASTSchema)(newClientAST),
1460
+ },
1461
+ ...warnings,
1462
+ };
1463
+ }
1464
+ buildFederationContractResult(tagExclusions) {
1465
+ if (!this.isVersionTwo) {
1466
+ /* If all the subgraphs are version one, the @inaccessible directive won't be present.
1467
+ ** However, contracts require @inaccessible to exclude applicable tagged types. */
1468
+ this.routerDefinitions.push(constants_1.INACCESSIBLE_DEFINITION);
1469
+ }
1470
+ for (const [typeName, parentTagData] of this.parentTagDataByTypeName) {
1471
+ // TODO assess children
1472
+ const parentDefinitionData = (0, utils_3.getOrThrowError)(this.parentDefinitionDataByTypeName, typeName, string_constants_1.PARENT_DEFINITION_DATA);
1473
+ if ((0, utils_3.doSetsHaveAnyOverlap)(tagExclusions, parentTagData.tagNames)) {
1474
+ (0, utils_3.getValueOrDefault)(parentDefinitionData.persistedDirectivesData.directives, string_constants_1.INACCESSIBLE, () => [
1475
+ (0, utils_3.generateSimpleDirective)(string_constants_1.INACCESSIBLE),
1476
+ ]);
844
1477
  }
845
- // After evaluating all of a root type's fields, break and return if there are errors
846
- if (this.errors.length > 0) {
847
- break;
1478
+ if (parentTagData.childTagDataByChildName.size < 1) {
1479
+ continue;
848
1480
  }
849
- // If a root type field returns a Scalar or Enum, track it so that it is not evaluated it again
850
- const evaluatedRootScalarsAndEnums = new Set(constants_1.BASE_SCALARS);
851
- for (const [rootTypeFieldName, fieldData] of rootTypeData.fieldDataByFieldName) {
852
- const namedRootFieldTypeName = fieldData.namedTypeName;
853
- if (evaluatedRootScalarsAndEnums.has(namedRootFieldTypeName)) {
854
- continue;
855
- }
856
- if (!this.shouldEvaluateObjectLike(fieldData.subgraphNames, namedRootFieldTypeName)) {
1481
+ switch (parentDefinitionData.kind) {
1482
+ case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
1483
+ // intentional fallthrough
1484
+ case graphql_1.Kind.ENUM_TYPE_DEFINITION:
1485
+ // intentional fallthrough
1486
+ case graphql_1.Kind.UNION_TYPE_DEFINITION:
857
1487
  continue;
858
- }
859
- const namedTypeData = (0, utils_2.getOrThrowError)(this.parentDefinitionDataByTypeName, namedRootFieldTypeName, 'parentDefinitionDataByTypeName');
860
- const fieldPath = `${rootTypeName}.${rootTypeFieldName}`;
861
- const rootTypeFieldData = {
862
- fieldName: rootTypeFieldName,
863
- fieldTypeNodeString: (0, merge_1.printTypeNode)(fieldData.node.type),
864
- path: fieldPath,
865
- typeName: rootTypeName,
866
- subgraphs: fieldData.subgraphNames,
867
- };
868
- switch (namedTypeData.kind) {
869
- case graphql_1.Kind.ENUM_TYPE_DEFINITION:
870
- // intentional fallthrough
871
- case graphql_1.Kind.SCALAR_TYPE_DEFINITION:
872
- // Root type fields whose response type is an Enums and Scalars will always be resolvable
873
- // Consequently, subsequent checks can be skipped
874
- evaluatedRootScalarsAndEnums.add(namedRootFieldTypeName);
875
- continue;
876
- case graphql_1.Kind.OBJECT_TYPE_DEFINITION:
877
- this.evaluateResolvabilityOfObject(namedTypeData, rootTypeFieldData, fieldPath, new Set(), this.entityDataByTypeName.has(namedRootFieldTypeName) ? [namedRootFieldTypeName] : []);
878
- continue;
879
- case graphql_1.Kind.INTERFACE_TYPE_DEFINITION:
880
- // intentional fallthrough
881
- case graphql_1.Kind.UNION_TYPE_DEFINITION:
882
- this.evaluateResolvabilityOfAbstractType(namedRootFieldTypeName, namedTypeData.kind, rootTypeFieldData, fieldPath, new Set(), this.entityDataByTypeName.has(namedRootFieldTypeName) ? [namedRootFieldTypeName] : []);
883
- continue;
884
- default:
885
- this.errors.push((0, errors_1.unexpectedObjectResponseType)(fieldPath, (0, utils_2.kindToTypeString)(namedTypeData.kind)));
886
- }
1488
+ case graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION:
1489
+ for (const [inputFieldName, childTagData] of parentTagData.childTagDataByChildName) {
1490
+ const inputValueData = (0, utils_3.getOrThrowError)(parentDefinitionData.inputValueDataByValueName, inputFieldName, 'parentDefinitionData.inputValueDataByValueName');
1491
+ if ((0, utils_3.doSetsHaveAnyOverlap)(tagExclusions, childTagData.tagNames)) {
1492
+ (0, utils_3.getValueOrDefault)(inputValueData.persistedDirectivesData.directives, string_constants_1.INACCESSIBLE, () => [
1493
+ (0, utils_3.generateSimpleDirective)(string_constants_1.INACCESSIBLE),
1494
+ ]);
1495
+ }
1496
+ }
1497
+ break;
1498
+ default:
1499
+ for (const [fieldName, childTagData] of parentTagData.childTagDataByChildName) {
1500
+ const fieldData = (0, utils_3.getOrThrowError)(parentDefinitionData.fieldDataByFieldName, fieldName, 'parentDefinitionData.fieldDataByFieldName');
1501
+ if ((0, utils_3.doSetsHaveAnyOverlap)(tagExclusions, childTagData.tagNames)) {
1502
+ (0, utils_3.getValueOrDefault)(fieldData.persistedDirectivesData.directives, string_constants_1.INACCESSIBLE, () => [
1503
+ (0, utils_3.generateSimpleDirective)(string_constants_1.INACCESSIBLE),
1504
+ ]);
1505
+ }
1506
+ for (const [argumentName, tagNames] of childTagData.tagNamesByArgumentName) {
1507
+ const inputValueData = (0, utils_3.getOrThrowError)(fieldData.argumentDataByArgumentName, argumentName, 'fieldData.argumentDataByArgumentName');
1508
+ if ((0, utils_3.doSetsHaveAnyOverlap)(tagExclusions, tagNames)) {
1509
+ (0, utils_3.getValueOrDefault)(inputValueData.persistedDirectivesData.directives, string_constants_1.INACCESSIBLE, () => [
1510
+ (0, utils_3.generateSimpleDirective)(string_constants_1.INACCESSIBLE),
1511
+ ]);
1512
+ }
1513
+ }
1514
+ }
887
1515
  }
888
1516
  }
1517
+ for (const data of this.potentialPersistedDirectiveDefinitionDataByDirectiveName.values()) {
1518
+ (0, utils_5.addValidPersistedDirectiveDefinitionNodeByData)(this.routerDefinitions, data, this.persistedDirectiveDefinitionByDirectiveName, this.errors);
1519
+ }
1520
+ const interfaceImplementations = [];
1521
+ this.pushParentDefinitionDataToDocumentDefinitions(interfaceImplementations);
1522
+ this.validateInterfaceImplementationsAndPushToDocumentDefinitions(interfaceImplementations);
1523
+ this.validateQueryRootType();
889
1524
  const warnings = this.warnings.length > 0 ? this.warnings : undefined;
890
1525
  if (this.errors.length > 0) {
891
1526
  return { errors: this.errors, warnings };
892
1527
  }
893
- const newAst = {
1528
+ const newRouterAST = {
894
1529
  kind: graphql_1.Kind.DOCUMENT,
895
- definitions,
1530
+ definitions: this.routerDefinitions,
1531
+ };
1532
+ const newClientAST = {
1533
+ kind: graphql_1.Kind.DOCUMENT,
1534
+ definitions: this.clientDefinitions,
896
1535
  };
897
1536
  const subgraphConfigBySubgraphName = new Map();
898
1537
  for (const subgraph of this.internalSubgraphBySubgraphName.values()) {
@@ -902,21 +1541,26 @@ class FederationFactory {
902
1541
  });
903
1542
  }
904
1543
  for (const authorizationData of this.authorizationDataByParentTypeName.values()) {
905
- (0, utils_2.upsertAuthorizationConfiguration)(this.fieldConfigurationByFieldPath, authorizationData);
1544
+ (0, utils_3.upsertAuthorizationConfiguration)(this.fieldConfigurationByFieldPath, authorizationData);
906
1545
  }
907
1546
  return {
908
1547
  federationResult: {
909
1548
  fieldConfigurations: Array.from(this.fieldConfigurationByFieldPath.values()),
910
1549
  subgraphConfigBySubgraphName,
911
- federatedGraphAST: newAst,
912
- federatedGraphSchema: (0, graphql_1.buildASTSchema)(newAst),
1550
+ federatedGraphAST: newRouterAST,
1551
+ federatedGraphSchema: (0, graphql_1.buildASTSchema)(newRouterAST),
1552
+ federatedGraphClientSchema: (0, graphql_1.buildASTSchema)(newClientAST),
913
1553
  },
914
1554
  warnings,
915
1555
  };
916
1556
  }
1557
+ federateSubgraphsInternal() {
1558
+ this.federateSubgraphData();
1559
+ return this.buildFederationResult();
1560
+ }
917
1561
  }
918
1562
  exports.FederationFactory = FederationFactory;
919
- function federateSubgraphs(subgraphs) {
1563
+ function initializeFederationFactory(subgraphs) {
920
1564
  if (subgraphs.length < 1) {
921
1565
  return { errors: [errors_1.minimumSubgraphRequirementError] };
922
1566
  }
@@ -931,7 +1575,7 @@ function federateSubgraphs(subgraphs) {
931
1575
  for (const [typeName, entityInterfaceData] of internalSubgraph.entityInterfaces) {
932
1576
  // Always add each entity interface to the invalid entity interfaces map
933
1577
  // If not, earlier checks would not account for implementations not yet seen
934
- const invalidEntityInterfaces = (0, utils_2.getValueOrDefault)(invalidEntityInterfacesByTypeName, typeName, () => []);
1578
+ const invalidEntityInterfaces = (0, utils_3.getValueOrDefault)(invalidEntityInterfacesByTypeName, typeName, () => []);
935
1579
  invalidEntityInterfaces.push({
936
1580
  subgraphName,
937
1581
  concreteTypeNames: entityInterfaceData.concreteTypeNames || new Set(),
@@ -939,10 +1583,10 @@ function federateSubgraphs(subgraphs) {
939
1583
  const existingData = entityInterfaceFederationDataByTypeName.get(typeName);
940
1584
  if (!existingData) {
941
1585
  validEntityInterfaceTypeNames.add(typeName);
942
- entityInterfaceFederationDataByTypeName.set(typeName, (0, utils_2.newEntityInterfaceFederationData)(entityInterfaceData, subgraphName));
1586
+ entityInterfaceFederationDataByTypeName.set(typeName, (0, utils_3.newEntityInterfaceFederationData)(entityInterfaceData, subgraphName));
943
1587
  continue;
944
1588
  }
945
- const areAnyImplementationsUndefined = (0, utils_2.upsertEntityInterfaceFederationData)(existingData, entityInterfaceData, subgraphName);
1589
+ const areAnyImplementationsUndefined = (0, utils_3.upsertEntityInterfaceFederationData)(existingData, entityInterfaceData, subgraphName);
946
1590
  if (areAnyImplementationsUndefined) {
947
1591
  validEntityInterfaceTypeNames.delete(typeName);
948
1592
  }
@@ -959,7 +1603,55 @@ function federateSubgraphs(subgraphs) {
959
1603
  ],
960
1604
  };
961
1605
  }
962
- return new FederationFactory(authorizationDataByParentTypeName, concreteTypeNamesByAbstractTypeName, entityContainerByTypeName, entityInterfaceFederationDataByTypeName, graph, internalSubgraphBySubgraphName, warnings).federate();
1606
+ return {
1607
+ federationFactory: new FederationFactory(authorizationDataByParentTypeName, concreteTypeNamesByAbstractTypeName, entityContainerByTypeName, entityInterfaceFederationDataByTypeName, graph, internalSubgraphBySubgraphName, warnings),
1608
+ };
1609
+ }
1610
+ function federateSubgraphs(subgraphs) {
1611
+ const { errors, federationFactory } = initializeFederationFactory(subgraphs);
1612
+ if (errors || !federationFactory) {
1613
+ return { errors: errors || [errors_1.federationFactoryInitializationFatalError] };
1614
+ }
1615
+ return federationFactory.federateSubgraphsInternal();
963
1616
  }
964
1617
  exports.federateSubgraphs = federateSubgraphs;
1618
+ // the flow when publishing a subgraph that also has contracts
1619
+ function federateSubgraphsWithContracts(subgraphs, tagExclusionsByContractName) {
1620
+ const { errors: normalizationErrors, federationFactory } = initializeFederationFactory(subgraphs);
1621
+ if (normalizationErrors || !federationFactory) {
1622
+ return { errors: normalizationErrors || [errors_1.federationFactoryInitializationFatalError] };
1623
+ }
1624
+ federationFactory.federateSubgraphData();
1625
+ const federationFactories = [(0, lodash_1.cloneDeep)(federationFactory)];
1626
+ const { errors, federationResult, warnings } = federationFactory.buildFederationResult();
1627
+ // if the base graph fails composition, no contracts will be attempted
1628
+ if (errors) {
1629
+ return { errors, warnings };
1630
+ }
1631
+ const lastContractIndex = tagExclusionsByContractName.size - 1;
1632
+ const federationResultContainerByContractName = new Map();
1633
+ let i = 0;
1634
+ for (const [contractName, tagExclusions] of tagExclusionsByContractName) {
1635
+ // deep copy the current FederationFactory before it is mutated if it is not the last one required
1636
+ if (i !== lastContractIndex) {
1637
+ federationFactories.push((0, lodash_1.cloneDeep)(federationFactories[i]));
1638
+ }
1639
+ // note that any one contract could have its own errors
1640
+ const federationResultContainer = federationFactories[i].buildFederationContractResult(tagExclusions);
1641
+ federationResultContainerByContractName.set(contractName, federationResultContainer);
1642
+ i++;
1643
+ }
1644
+ return { federationResult, federationResultContainerByContractName };
1645
+ }
1646
+ exports.federateSubgraphsWithContracts = federateSubgraphsWithContracts;
1647
+ // the flow when adding a completely new contract
1648
+ function federateSubgraphsContract(subgraphs, tagExclusions) {
1649
+ const { errors, federationFactory } = initializeFederationFactory(subgraphs);
1650
+ if (errors || !federationFactory) {
1651
+ return { errors: errors || [errors_1.federationFactoryInitializationFatalError] };
1652
+ }
1653
+ federationFactory.federateSubgraphData();
1654
+ return federationFactory.buildFederationContractResult(tagExclusions);
1655
+ }
1656
+ exports.federateSubgraphsContract = federateSubgraphsContract;
965
1657
  //# sourceMappingURL=federation-factory.js.map