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