@graphql-tools/stitching-directives 3.0.0-rc-20230519015308-f93ea91d → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/cjs/federationToStitchingSDL.js +5 -8
- package/cjs/pathsFromSelectionSet.js +2 -4
- package/cjs/stitchingDirectivesTransformer.js +28 -36
- package/cjs/stitchingDirectivesValidator.js +6 -9
- package/esm/federationToStitchingSDL.js +5 -8
- package/esm/pathsFromSelectionSet.js +2 -4
- package/esm/stitchingDirectivesTransformer.js +28 -36
- package/esm/stitchingDirectivesValidator.js +6 -9
- package/package.json +3 -3
@@ -15,10 +15,9 @@ function isEntityKind(def) {
|
|
15
15
|
return entityKinds.includes(def.kind);
|
16
16
|
}
|
17
17
|
function getQueryTypeDef(definitions) {
|
18
|
-
var _a;
|
19
18
|
const schemaDef = definitions.find(def => def.kind === graphql_1.Kind.SCHEMA_DEFINITION);
|
20
19
|
const typeName = schemaDef
|
21
|
-
?
|
20
|
+
? schemaDef.operationTypes.find(({ operation }) => operation === 'query')?.type.name.value
|
22
21
|
: 'Query';
|
23
22
|
return definitions.find(def => def.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION && def.name.value === typeName);
|
24
23
|
}
|
@@ -36,7 +35,6 @@ function federationToStitchingSDL(federationSDL, stitchingConfig = (0, stitching
|
|
36
35
|
return memo;
|
37
36
|
}, {});
|
38
37
|
doc.definitions.forEach(typeDef => {
|
39
|
-
var _a, _b, _c;
|
40
38
|
// Un-extend all types (remove "extends" keywords)...
|
41
39
|
// extended types are invalid GraphQL without a local base type to extend from.
|
42
40
|
// Stitching merges flat types in lieu of hierarchical extensions.
|
@@ -49,7 +47,7 @@ function federationToStitchingSDL(federationSDL, stitchingConfig = (0, stitching
|
|
49
47
|
// these are federated entities that get turned into merged types.
|
50
48
|
const keyDirs = [];
|
51
49
|
const otherDirs = [];
|
52
|
-
|
50
|
+
typeDef.directives?.forEach(dir => {
|
53
51
|
if (dir.name.value === 'key') {
|
54
52
|
keyDirs.push(dir);
|
55
53
|
}
|
@@ -70,12 +68,11 @@ function federationToStitchingSDL(federationSDL, stitchingConfig = (0, stitching
|
|
70
68
|
// Remove non-key "@external" fields from the type...
|
71
69
|
// the stitching query planner expects services to only publish their own fields.
|
72
70
|
// This makes "@provides" moot because the query planner can automate the logic.
|
73
|
-
typeDef.fields =
|
74
|
-
|
75
|
-
return (keyFields.includes(fieldDef.name.value) || !((_a = fieldDef.directives) === null || _a === void 0 ? void 0 : _a.find(dir => dir.name.value === 'external')));
|
71
|
+
typeDef.fields = typeDef.fields?.filter(fieldDef => {
|
72
|
+
return (keyFields.includes(fieldDef.name.value) || !fieldDef.directives?.find(dir => dir.name.value === 'external'));
|
76
73
|
});
|
77
74
|
// Discard remaining "@external" directives and any "@provides" directives
|
78
|
-
|
75
|
+
typeDef.fields?.forEach((fieldDef) => {
|
79
76
|
fieldDef.directives = fieldDef.directives.filter((dir) => !/^(external|provides)$/.test(dir.name.value));
|
80
77
|
fieldDef.directives.forEach((dir) => {
|
81
78
|
if (dir.name.value === 'requires') {
|
@@ -3,10 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.pathsFromSelectionSet = void 0;
|
4
4
|
const graphql_1 = require("graphql");
|
5
5
|
function pathsFromSelectionSet(selectionSet, path = []) {
|
6
|
-
var _a;
|
7
6
|
const paths = [];
|
8
7
|
for (const selection of selectionSet.selections) {
|
9
|
-
const additions =
|
8
|
+
const additions = pathsFromSelection(selection, path) ?? [];
|
10
9
|
for (const addition of additions) {
|
11
10
|
paths.push(addition);
|
12
11
|
}
|
@@ -15,9 +14,8 @@ function pathsFromSelectionSet(selectionSet, path = []) {
|
|
15
14
|
}
|
16
15
|
exports.pathsFromSelectionSet = pathsFromSelectionSet;
|
17
16
|
function pathsFromSelection(selection, path) {
|
18
|
-
var _a, _b;
|
19
17
|
if (selection.kind === graphql_1.Kind.FIELD) {
|
20
|
-
const responseKey =
|
18
|
+
const responseKey = selection.alias?.value ?? selection.name.value;
|
21
19
|
if (selection.selectionSet) {
|
22
20
|
return pathsFromSelectionSet(selection.selectionSet, path.concat([responseKey]));
|
23
21
|
}
|
@@ -14,7 +14,6 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
14
14
|
...options,
|
15
15
|
};
|
16
16
|
return (subschemaConfig) => {
|
17
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
18
17
|
const newSubschemaConfig = (0, delegate_1.cloneSubschemaConfig)(subschemaConfig);
|
19
18
|
const selectionSetsByType = Object.create(null);
|
20
19
|
const computedFieldSelectionSets = Object.create(null);
|
@@ -24,10 +23,9 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
24
23
|
// gateway should also run validation
|
25
24
|
(0, stitchingDirectivesValidator_js_1.stitchingDirectivesValidator)(options)(schema);
|
26
25
|
function setCanonicalDefinition(typeName, fieldName) {
|
27
|
-
var _a;
|
28
26
|
canonicalTypesInfo[typeName] = canonicalTypesInfo[typeName] || Object.create(null);
|
29
27
|
if (fieldName) {
|
30
|
-
const fields =
|
28
|
+
const fields = canonicalTypesInfo[typeName].fields ?? Object.create(null);
|
31
29
|
canonicalTypesInfo[typeName].fields = fields;
|
32
30
|
fields[fieldName] = true;
|
33
31
|
}
|
@@ -37,21 +35,19 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
37
35
|
}
|
38
36
|
(0, utils_1.mapSchema)(schema, {
|
39
37
|
[utils_1.MapperKind.OBJECT_TYPE]: type => {
|
40
|
-
|
41
|
-
const keyDirective = (_a = (0, utils_1.getDirective)(schema, type, keyDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
38
|
+
const keyDirective = (0, utils_1.getDirective)(schema, type, keyDirectiveName, pathToDirectivesInExtensions)?.[0];
|
42
39
|
if (keyDirective != null) {
|
43
40
|
const selectionSet = (0, utils_1.parseSelectionSet)(keyDirective['selectionSet'], { noLocation: true });
|
44
41
|
selectionSetsByType[type.name] = selectionSet;
|
45
42
|
}
|
46
|
-
const canonicalDirective = (
|
43
|
+
const canonicalDirective = (0, utils_1.getDirective)(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
47
44
|
if (canonicalDirective != null) {
|
48
45
|
setCanonicalDefinition(type.name);
|
49
46
|
}
|
50
47
|
return undefined;
|
51
48
|
},
|
52
49
|
[utils_1.MapperKind.OBJECT_FIELD]: (fieldConfig, fieldName, typeName) => {
|
53
|
-
|
54
|
-
const computedDirective = (_a = (0, utils_1.getDirective)(schema, fieldConfig, computedDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
50
|
+
const computedDirective = (0, utils_1.getDirective)(schema, fieldConfig, computedDirectiveName, pathToDirectivesInExtensions)?.[0];
|
55
51
|
if (computedDirective != null) {
|
56
52
|
const selectionSet = (0, utils_1.parseSelectionSet)(computedDirective['selectionSet'], { noLocation: true });
|
57
53
|
if (!computedFieldSelectionSets[typeName]) {
|
@@ -59,8 +55,8 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
59
55
|
}
|
60
56
|
computedFieldSelectionSets[typeName][fieldName] = selectionSet;
|
61
57
|
}
|
62
|
-
const mergeDirective = (
|
63
|
-
if (
|
58
|
+
const mergeDirective = (0, utils_1.getDirective)(schema, fieldConfig, mergeDirectiveName, pathToDirectivesInExtensions)?.[0];
|
59
|
+
if (mergeDirective?.['keyField'] != null) {
|
64
60
|
const mergeDirectiveKeyField = mergeDirective['keyField'];
|
65
61
|
const selectionSet = (0, utils_1.parseSelectionSet)(`{ ${mergeDirectiveKeyField}}`, { noLocation: true });
|
66
62
|
const typeNames = mergeDirective['types'];
|
@@ -74,63 +70,56 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
74
70
|
}
|
75
71
|
});
|
76
72
|
}
|
77
|
-
const canonicalDirective = (
|
73
|
+
const canonicalDirective = (0, utils_1.getDirective)(schema, fieldConfig, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
78
74
|
if (canonicalDirective != null) {
|
79
75
|
setCanonicalDefinition(typeName, fieldName);
|
80
76
|
}
|
81
77
|
return undefined;
|
82
78
|
},
|
83
79
|
[utils_1.MapperKind.INTERFACE_TYPE]: type => {
|
84
|
-
|
85
|
-
const canonicalDirective = (_a = (0, utils_1.getDirective)(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
80
|
+
const canonicalDirective = (0, utils_1.getDirective)(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
86
81
|
if (canonicalDirective) {
|
87
82
|
setCanonicalDefinition(type.name);
|
88
83
|
}
|
89
84
|
return undefined;
|
90
85
|
},
|
91
86
|
[utils_1.MapperKind.INTERFACE_FIELD]: (fieldConfig, fieldName, typeName) => {
|
92
|
-
|
93
|
-
const canonicalDirective = (_a = (0, utils_1.getDirective)(schema, fieldConfig, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
87
|
+
const canonicalDirective = (0, utils_1.getDirective)(schema, fieldConfig, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
94
88
|
if (canonicalDirective) {
|
95
89
|
setCanonicalDefinition(typeName, fieldName);
|
96
90
|
}
|
97
91
|
return undefined;
|
98
92
|
},
|
99
93
|
[utils_1.MapperKind.INPUT_OBJECT_TYPE]: type => {
|
100
|
-
|
101
|
-
const canonicalDirective = (_a = (0, utils_1.getDirective)(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
94
|
+
const canonicalDirective = (0, utils_1.getDirective)(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
102
95
|
if (canonicalDirective) {
|
103
96
|
setCanonicalDefinition(type.name);
|
104
97
|
}
|
105
98
|
return undefined;
|
106
99
|
},
|
107
100
|
[utils_1.MapperKind.INPUT_OBJECT_FIELD]: (inputFieldConfig, fieldName, typeName) => {
|
108
|
-
|
109
|
-
const canonicalDirective = (_a = (0, utils_1.getDirective)(schema, inputFieldConfig, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
101
|
+
const canonicalDirective = (0, utils_1.getDirective)(schema, inputFieldConfig, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
110
102
|
if (canonicalDirective != null) {
|
111
103
|
setCanonicalDefinition(typeName, fieldName);
|
112
104
|
}
|
113
105
|
return undefined;
|
114
106
|
},
|
115
107
|
[utils_1.MapperKind.UNION_TYPE]: type => {
|
116
|
-
|
117
|
-
const canonicalDirective = (_a = (0, utils_1.getDirective)(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
108
|
+
const canonicalDirective = (0, utils_1.getDirective)(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
118
109
|
if (canonicalDirective != null) {
|
119
110
|
setCanonicalDefinition(type.name);
|
120
111
|
}
|
121
112
|
return undefined;
|
122
113
|
},
|
123
114
|
[utils_1.MapperKind.ENUM_TYPE]: type => {
|
124
|
-
|
125
|
-
const canonicalDirective = (_a = (0, utils_1.getDirective)(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
115
|
+
const canonicalDirective = (0, utils_1.getDirective)(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
126
116
|
if (canonicalDirective != null) {
|
127
117
|
setCanonicalDefinition(type.name);
|
128
118
|
}
|
129
119
|
return undefined;
|
130
120
|
},
|
131
121
|
[utils_1.MapperKind.SCALAR_TYPE]: type => {
|
132
|
-
|
133
|
-
const canonicalDirective = (_a = (0, utils_1.getDirective)(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
122
|
+
const canonicalDirective = (0, utils_1.getDirective)(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
134
123
|
if (canonicalDirective != null) {
|
135
124
|
setCanonicalDefinition(type.name);
|
136
125
|
}
|
@@ -158,7 +147,7 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
158
147
|
continue;
|
159
148
|
const selectionSet = (0, utils_1.parseSelectionSet)(fieldConfig.selectionSet, { noLocation: true });
|
160
149
|
if (selectionSet) {
|
161
|
-
if (
|
150
|
+
if (computedFieldSelectionSets[typeName]?.[fieldName]) {
|
162
151
|
computedFieldSelectionSets[typeName][fieldName] = mergeSelectionSets(computedFieldSelectionSets[typeName][fieldName], selectionSet);
|
163
152
|
}
|
164
153
|
else {
|
@@ -188,8 +177,7 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
188
177
|
}
|
189
178
|
(0, utils_1.mapSchema)(schema, {
|
190
179
|
[utils_1.MapperKind.OBJECT_FIELD]: function objectFieldMapper(fieldConfig, fieldName) {
|
191
|
-
|
192
|
-
const mergeDirective = (_a = (0, utils_1.getDirective)(schema, fieldConfig, mergeDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
180
|
+
const mergeDirective = (0, utils_1.getDirective)(schema, fieldConfig, mergeDirectiveName, pathToDirectivesInExtensions)?.[0];
|
193
181
|
if (mergeDirective != null) {
|
194
182
|
const returnType = (0, graphql_1.getNullableType)(fieldConfig.type);
|
195
183
|
const returnsList = (0, graphql_1.isListType)(returnType);
|
@@ -200,7 +188,7 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
200
188
|
const keyField = mergeDirective['keyField'];
|
201
189
|
const keyExpr = key != null ? buildKeyExpr(key) : keyField != null ? `$key.${keyField}` : '$key';
|
202
190
|
const keyArg = mergeDirective['keyArg'];
|
203
|
-
const argNames = keyArg == null ? [Object.keys(
|
191
|
+
const argNames = keyArg == null ? [Object.keys(fieldConfig.args ?? {})[0]] : keyArg.split('.');
|
204
192
|
const lastArgName = argNames.pop();
|
205
193
|
mergeArgsExpr = returnsList ? `${lastArgName}: [[${keyExpr}]]` : `${lastArgName}: ${keyExpr}`;
|
206
194
|
for (const argName of argNames.reverse()) {
|
@@ -231,7 +219,8 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
231
219
|
});
|
232
220
|
for (const typeName in selectionSetsByType) {
|
233
221
|
const selectionSet = selectionSetsByType[typeName];
|
234
|
-
const mergeConfig =
|
222
|
+
const mergeConfig = newSubschemaConfig.merge ??
|
223
|
+
Object.create(null);
|
235
224
|
newSubschemaConfig.merge = mergeConfig;
|
236
225
|
if (mergeConfig[typeName] == null) {
|
237
226
|
newSubschemaConfig.merge[typeName] = Object.create(null);
|
@@ -241,17 +230,18 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
241
230
|
}
|
242
231
|
for (const typeName in computedFieldSelectionSets) {
|
243
232
|
const selectionSets = computedFieldSelectionSets[typeName];
|
244
|
-
const mergeConfig =
|
233
|
+
const mergeConfig = newSubschemaConfig.merge ??
|
234
|
+
Object.create(null);
|
245
235
|
newSubschemaConfig.merge = mergeConfig;
|
246
236
|
if (mergeConfig[typeName] == null) {
|
247
237
|
mergeConfig[typeName] = Object.create(null);
|
248
238
|
}
|
249
239
|
const mergeTypeConfig = newSubschemaConfig.merge[typeName];
|
250
|
-
const mergeTypeConfigFields =
|
240
|
+
const mergeTypeConfigFields = mergeTypeConfig.fields ?? Object.create(null);
|
251
241
|
mergeTypeConfig.fields = mergeTypeConfigFields;
|
252
242
|
for (const fieldName in selectionSets) {
|
253
243
|
const selectionSet = selectionSets[fieldName];
|
254
|
-
const fieldConfig =
|
244
|
+
const fieldConfig = mergeTypeConfigFields[fieldName] ?? Object.create(null);
|
255
245
|
mergeTypeConfigFields[fieldName] = fieldConfig;
|
256
246
|
fieldConfig.selectionSet = (0, graphql_1.print)(selectionSet);
|
257
247
|
fieldConfig.computed = true;
|
@@ -259,7 +249,8 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
259
249
|
}
|
260
250
|
for (const typeName in mergedTypesResolversInfo) {
|
261
251
|
const mergedTypeResolverInfo = mergedTypesResolversInfo[typeName];
|
262
|
-
const mergeConfig =
|
252
|
+
const mergeConfig = newSubschemaConfig.merge ??
|
253
|
+
Object.create(null);
|
263
254
|
newSubschemaConfig.merge = mergeConfig;
|
264
255
|
if (newSubschemaConfig.merge[typeName] == null) {
|
265
256
|
newSubschemaConfig.merge[typeName] = Object.create(null);
|
@@ -276,7 +267,8 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
276
267
|
}
|
277
268
|
for (const typeName in canonicalTypesInfo) {
|
278
269
|
const canonicalTypeInfo = canonicalTypesInfo[typeName];
|
279
|
-
const mergeConfig =
|
270
|
+
const mergeConfig = newSubschemaConfig.merge ??
|
271
|
+
Object.create(null);
|
280
272
|
newSubschemaConfig.merge = mergeConfig;
|
281
273
|
if (newSubschemaConfig.merge[typeName] == null) {
|
282
274
|
newSubschemaConfig.merge[typeName] = Object.create(null);
|
@@ -286,7 +278,7 @@ function stitchingDirectivesTransformer(options = {}) {
|
|
286
278
|
mergeTypeConfig.canonical = true;
|
287
279
|
}
|
288
280
|
if (canonicalTypeInfo.fields) {
|
289
|
-
const mergeTypeConfigFields =
|
281
|
+
const mergeTypeConfigFields = mergeTypeConfig.fields ?? Object.create(null);
|
290
282
|
mergeTypeConfig.fields = mergeTypeConfigFields;
|
291
283
|
for (const fieldName in canonicalTypeInfo.fields) {
|
292
284
|
if (mergeTypeConfigFields[fieldName] == null) {
|
@@ -12,24 +12,21 @@ function stitchingDirectivesValidator(options = {}) {
|
|
12
12
|
...options,
|
13
13
|
};
|
14
14
|
return (schema) => {
|
15
|
-
|
16
|
-
const queryTypeName = (_a = schema.getQueryType()) === null || _a === void 0 ? void 0 : _a.name;
|
15
|
+
const queryTypeName = schema.getQueryType()?.name;
|
17
16
|
(0, utils_1.mapSchema)(schema, {
|
18
17
|
[utils_1.MapperKind.OBJECT_TYPE]: type => {
|
19
|
-
|
20
|
-
const keyDirective = (_a = (0, utils_1.getDirective)(schema, type, keyDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
18
|
+
const keyDirective = (0, utils_1.getDirective)(schema, type, keyDirectiveName, pathToDirectivesInExtensions)?.[0];
|
21
19
|
if (keyDirective != null) {
|
22
20
|
(0, utils_1.parseSelectionSet)(keyDirective['selectionSet']);
|
23
21
|
}
|
24
22
|
return undefined;
|
25
23
|
},
|
26
24
|
[utils_1.MapperKind.OBJECT_FIELD]: (fieldConfig, _fieldName, typeName) => {
|
27
|
-
|
28
|
-
const computedDirective = (_a = (0, utils_1.getDirective)(schema, fieldConfig, computedDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
25
|
+
const computedDirective = (0, utils_1.getDirective)(schema, fieldConfig, computedDirectiveName, pathToDirectivesInExtensions)?.[0];
|
29
26
|
if (computedDirective != null) {
|
30
27
|
(0, utils_1.parseSelectionSet)(computedDirective['selectionSet']);
|
31
28
|
}
|
32
|
-
const mergeDirective = (
|
29
|
+
const mergeDirective = (0, utils_1.getDirective)(schema, fieldConfig, mergeDirectiveName, pathToDirectivesInExtensions)?.[0];
|
33
30
|
if (mergeDirective != null) {
|
34
31
|
if (typeName !== queryTypeName) {
|
35
32
|
throw new Error('@merge directive may be used only for root fields of the root Query type.');
|
@@ -45,7 +42,7 @@ function stitchingDirectivesValidator(options = {}) {
|
|
45
42
|
if (mergeArgsExpr != null) {
|
46
43
|
(0, parseMergeArgsExpr_js_1.parseMergeArgsExpr)(mergeArgsExpr);
|
47
44
|
}
|
48
|
-
const args = Object.keys(
|
45
|
+
const args = Object.keys(fieldConfig.args ?? {});
|
49
46
|
const keyArg = mergeDirective['keyArg'];
|
50
47
|
if (keyArg == null) {
|
51
48
|
if (!mergeArgsExpr && args.length !== 1) {
|
@@ -103,7 +100,7 @@ function stitchingDirectivesValidator(options = {}) {
|
|
103
100
|
const implementingTypes = (0, graphql_1.isInterfaceType)(returnType)
|
104
101
|
? (0, utils_1.getImplementingTypes)(returnType.name, schema).map(typeName => schema.getType(typeName))
|
105
102
|
: returnType.getTypes();
|
106
|
-
const implementingTypeNames = implementingTypes.map(type => type
|
103
|
+
const implementingTypeNames = implementingTypes.map(type => type?.name).filter(utils_1.isSome);
|
107
104
|
for (const typeName of typeNames) {
|
108
105
|
if (!implementingTypeNames.includes(typeName)) {
|
109
106
|
throw new Error(`Types argument can only include only type names that implement the field return type's abstract type.`);
|
@@ -12,10 +12,9 @@ function isEntityKind(def) {
|
|
12
12
|
return entityKinds.includes(def.kind);
|
13
13
|
}
|
14
14
|
function getQueryTypeDef(definitions) {
|
15
|
-
var _a;
|
16
15
|
const schemaDef = definitions.find(def => def.kind === Kind.SCHEMA_DEFINITION);
|
17
16
|
const typeName = schemaDef
|
18
|
-
?
|
17
|
+
? schemaDef.operationTypes.find(({ operation }) => operation === 'query')?.type.name.value
|
19
18
|
: 'Query';
|
20
19
|
return definitions.find(def => def.kind === Kind.OBJECT_TYPE_DEFINITION && def.name.value === typeName);
|
21
20
|
}
|
@@ -33,7 +32,6 @@ export function federationToStitchingSDL(federationSDL, stitchingConfig = stitch
|
|
33
32
|
return memo;
|
34
33
|
}, {});
|
35
34
|
doc.definitions.forEach(typeDef => {
|
36
|
-
var _a, _b, _c;
|
37
35
|
// Un-extend all types (remove "extends" keywords)...
|
38
36
|
// extended types are invalid GraphQL without a local base type to extend from.
|
39
37
|
// Stitching merges flat types in lieu of hierarchical extensions.
|
@@ -46,7 +44,7 @@ export function federationToStitchingSDL(federationSDL, stitchingConfig = stitch
|
|
46
44
|
// these are federated entities that get turned into merged types.
|
47
45
|
const keyDirs = [];
|
48
46
|
const otherDirs = [];
|
49
|
-
|
47
|
+
typeDef.directives?.forEach(dir => {
|
50
48
|
if (dir.name.value === 'key') {
|
51
49
|
keyDirs.push(dir);
|
52
50
|
}
|
@@ -67,12 +65,11 @@ export function federationToStitchingSDL(federationSDL, stitchingConfig = stitch
|
|
67
65
|
// Remove non-key "@external" fields from the type...
|
68
66
|
// the stitching query planner expects services to only publish their own fields.
|
69
67
|
// This makes "@provides" moot because the query planner can automate the logic.
|
70
|
-
typeDef.fields =
|
71
|
-
|
72
|
-
return (keyFields.includes(fieldDef.name.value) || !((_a = fieldDef.directives) === null || _a === void 0 ? void 0 : _a.find(dir => dir.name.value === 'external')));
|
68
|
+
typeDef.fields = typeDef.fields?.filter(fieldDef => {
|
69
|
+
return (keyFields.includes(fieldDef.name.value) || !fieldDef.directives?.find(dir => dir.name.value === 'external'));
|
73
70
|
});
|
74
71
|
// Discard remaining "@external" directives and any "@provides" directives
|
75
|
-
|
72
|
+
typeDef.fields?.forEach((fieldDef) => {
|
76
73
|
fieldDef.directives = fieldDef.directives.filter((dir) => !/^(external|provides)$/.test(dir.name.value));
|
77
74
|
fieldDef.directives.forEach((dir) => {
|
78
75
|
if (dir.name.value === 'requires') {
|
@@ -1,9 +1,8 @@
|
|
1
1
|
import { Kind } from 'graphql';
|
2
2
|
export function pathsFromSelectionSet(selectionSet, path = []) {
|
3
|
-
var _a;
|
4
3
|
const paths = [];
|
5
4
|
for (const selection of selectionSet.selections) {
|
6
|
-
const additions =
|
5
|
+
const additions = pathsFromSelection(selection, path) ?? [];
|
7
6
|
for (const addition of additions) {
|
8
7
|
paths.push(addition);
|
9
8
|
}
|
@@ -11,9 +10,8 @@ export function pathsFromSelectionSet(selectionSet, path = []) {
|
|
11
10
|
return paths;
|
12
11
|
}
|
13
12
|
function pathsFromSelection(selection, path) {
|
14
|
-
var _a, _b;
|
15
13
|
if (selection.kind === Kind.FIELD) {
|
16
|
-
const responseKey =
|
14
|
+
const responseKey = selection.alias?.value ?? selection.name.value;
|
17
15
|
if (selection.selectionSet) {
|
18
16
|
return pathsFromSelectionSet(selection.selectionSet, path.concat([responseKey]));
|
19
17
|
}
|
@@ -11,7 +11,6 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
11
11
|
...options,
|
12
12
|
};
|
13
13
|
return (subschemaConfig) => {
|
14
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
15
14
|
const newSubschemaConfig = cloneSubschemaConfig(subschemaConfig);
|
16
15
|
const selectionSetsByType = Object.create(null);
|
17
16
|
const computedFieldSelectionSets = Object.create(null);
|
@@ -21,10 +20,9 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
21
20
|
// gateway should also run validation
|
22
21
|
stitchingDirectivesValidator(options)(schema);
|
23
22
|
function setCanonicalDefinition(typeName, fieldName) {
|
24
|
-
var _a;
|
25
23
|
canonicalTypesInfo[typeName] = canonicalTypesInfo[typeName] || Object.create(null);
|
26
24
|
if (fieldName) {
|
27
|
-
const fields =
|
25
|
+
const fields = canonicalTypesInfo[typeName].fields ?? Object.create(null);
|
28
26
|
canonicalTypesInfo[typeName].fields = fields;
|
29
27
|
fields[fieldName] = true;
|
30
28
|
}
|
@@ -34,21 +32,19 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
34
32
|
}
|
35
33
|
mapSchema(schema, {
|
36
34
|
[MapperKind.OBJECT_TYPE]: type => {
|
37
|
-
|
38
|
-
const keyDirective = (_a = getDirective(schema, type, keyDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
35
|
+
const keyDirective = getDirective(schema, type, keyDirectiveName, pathToDirectivesInExtensions)?.[0];
|
39
36
|
if (keyDirective != null) {
|
40
37
|
const selectionSet = parseSelectionSet(keyDirective['selectionSet'], { noLocation: true });
|
41
38
|
selectionSetsByType[type.name] = selectionSet;
|
42
39
|
}
|
43
|
-
const canonicalDirective =
|
40
|
+
const canonicalDirective = getDirective(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
44
41
|
if (canonicalDirective != null) {
|
45
42
|
setCanonicalDefinition(type.name);
|
46
43
|
}
|
47
44
|
return undefined;
|
48
45
|
},
|
49
46
|
[MapperKind.OBJECT_FIELD]: (fieldConfig, fieldName, typeName) => {
|
50
|
-
|
51
|
-
const computedDirective = (_a = getDirective(schema, fieldConfig, computedDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
47
|
+
const computedDirective = getDirective(schema, fieldConfig, computedDirectiveName, pathToDirectivesInExtensions)?.[0];
|
52
48
|
if (computedDirective != null) {
|
53
49
|
const selectionSet = parseSelectionSet(computedDirective['selectionSet'], { noLocation: true });
|
54
50
|
if (!computedFieldSelectionSets[typeName]) {
|
@@ -56,8 +52,8 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
56
52
|
}
|
57
53
|
computedFieldSelectionSets[typeName][fieldName] = selectionSet;
|
58
54
|
}
|
59
|
-
const mergeDirective =
|
60
|
-
if (
|
55
|
+
const mergeDirective = getDirective(schema, fieldConfig, mergeDirectiveName, pathToDirectivesInExtensions)?.[0];
|
56
|
+
if (mergeDirective?.['keyField'] != null) {
|
61
57
|
const mergeDirectiveKeyField = mergeDirective['keyField'];
|
62
58
|
const selectionSet = parseSelectionSet(`{ ${mergeDirectiveKeyField}}`, { noLocation: true });
|
63
59
|
const typeNames = mergeDirective['types'];
|
@@ -71,63 +67,56 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
71
67
|
}
|
72
68
|
});
|
73
69
|
}
|
74
|
-
const canonicalDirective =
|
70
|
+
const canonicalDirective = getDirective(schema, fieldConfig, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
75
71
|
if (canonicalDirective != null) {
|
76
72
|
setCanonicalDefinition(typeName, fieldName);
|
77
73
|
}
|
78
74
|
return undefined;
|
79
75
|
},
|
80
76
|
[MapperKind.INTERFACE_TYPE]: type => {
|
81
|
-
|
82
|
-
const canonicalDirective = (_a = getDirective(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
77
|
+
const canonicalDirective = getDirective(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
83
78
|
if (canonicalDirective) {
|
84
79
|
setCanonicalDefinition(type.name);
|
85
80
|
}
|
86
81
|
return undefined;
|
87
82
|
},
|
88
83
|
[MapperKind.INTERFACE_FIELD]: (fieldConfig, fieldName, typeName) => {
|
89
|
-
|
90
|
-
const canonicalDirective = (_a = getDirective(schema, fieldConfig, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
84
|
+
const canonicalDirective = getDirective(schema, fieldConfig, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
91
85
|
if (canonicalDirective) {
|
92
86
|
setCanonicalDefinition(typeName, fieldName);
|
93
87
|
}
|
94
88
|
return undefined;
|
95
89
|
},
|
96
90
|
[MapperKind.INPUT_OBJECT_TYPE]: type => {
|
97
|
-
|
98
|
-
const canonicalDirective = (_a = getDirective(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
91
|
+
const canonicalDirective = getDirective(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
99
92
|
if (canonicalDirective) {
|
100
93
|
setCanonicalDefinition(type.name);
|
101
94
|
}
|
102
95
|
return undefined;
|
103
96
|
},
|
104
97
|
[MapperKind.INPUT_OBJECT_FIELD]: (inputFieldConfig, fieldName, typeName) => {
|
105
|
-
|
106
|
-
const canonicalDirective = (_a = getDirective(schema, inputFieldConfig, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
98
|
+
const canonicalDirective = getDirective(schema, inputFieldConfig, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
107
99
|
if (canonicalDirective != null) {
|
108
100
|
setCanonicalDefinition(typeName, fieldName);
|
109
101
|
}
|
110
102
|
return undefined;
|
111
103
|
},
|
112
104
|
[MapperKind.UNION_TYPE]: type => {
|
113
|
-
|
114
|
-
const canonicalDirective = (_a = getDirective(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
105
|
+
const canonicalDirective = getDirective(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
115
106
|
if (canonicalDirective != null) {
|
116
107
|
setCanonicalDefinition(type.name);
|
117
108
|
}
|
118
109
|
return undefined;
|
119
110
|
},
|
120
111
|
[MapperKind.ENUM_TYPE]: type => {
|
121
|
-
|
122
|
-
const canonicalDirective = (_a = getDirective(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
112
|
+
const canonicalDirective = getDirective(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
123
113
|
if (canonicalDirective != null) {
|
124
114
|
setCanonicalDefinition(type.name);
|
125
115
|
}
|
126
116
|
return undefined;
|
127
117
|
},
|
128
118
|
[MapperKind.SCALAR_TYPE]: type => {
|
129
|
-
|
130
|
-
const canonicalDirective = (_a = getDirective(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
119
|
+
const canonicalDirective = getDirective(schema, type, canonicalDirectiveName, pathToDirectivesInExtensions)?.[0];
|
131
120
|
if (canonicalDirective != null) {
|
132
121
|
setCanonicalDefinition(type.name);
|
133
122
|
}
|
@@ -155,7 +144,7 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
155
144
|
continue;
|
156
145
|
const selectionSet = parseSelectionSet(fieldConfig.selectionSet, { noLocation: true });
|
157
146
|
if (selectionSet) {
|
158
|
-
if (
|
147
|
+
if (computedFieldSelectionSets[typeName]?.[fieldName]) {
|
159
148
|
computedFieldSelectionSets[typeName][fieldName] = mergeSelectionSets(computedFieldSelectionSets[typeName][fieldName], selectionSet);
|
160
149
|
}
|
161
150
|
else {
|
@@ -185,8 +174,7 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
185
174
|
}
|
186
175
|
mapSchema(schema, {
|
187
176
|
[MapperKind.OBJECT_FIELD]: function objectFieldMapper(fieldConfig, fieldName) {
|
188
|
-
|
189
|
-
const mergeDirective = (_a = getDirective(schema, fieldConfig, mergeDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
177
|
+
const mergeDirective = getDirective(schema, fieldConfig, mergeDirectiveName, pathToDirectivesInExtensions)?.[0];
|
190
178
|
if (mergeDirective != null) {
|
191
179
|
const returnType = getNullableType(fieldConfig.type);
|
192
180
|
const returnsList = isListType(returnType);
|
@@ -197,7 +185,7 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
197
185
|
const keyField = mergeDirective['keyField'];
|
198
186
|
const keyExpr = key != null ? buildKeyExpr(key) : keyField != null ? `$key.${keyField}` : '$key';
|
199
187
|
const keyArg = mergeDirective['keyArg'];
|
200
|
-
const argNames = keyArg == null ? [Object.keys(
|
188
|
+
const argNames = keyArg == null ? [Object.keys(fieldConfig.args ?? {})[0]] : keyArg.split('.');
|
201
189
|
const lastArgName = argNames.pop();
|
202
190
|
mergeArgsExpr = returnsList ? `${lastArgName}: [[${keyExpr}]]` : `${lastArgName}: ${keyExpr}`;
|
203
191
|
for (const argName of argNames.reverse()) {
|
@@ -228,7 +216,8 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
228
216
|
});
|
229
217
|
for (const typeName in selectionSetsByType) {
|
230
218
|
const selectionSet = selectionSetsByType[typeName];
|
231
|
-
const mergeConfig =
|
219
|
+
const mergeConfig = newSubschemaConfig.merge ??
|
220
|
+
Object.create(null);
|
232
221
|
newSubschemaConfig.merge = mergeConfig;
|
233
222
|
if (mergeConfig[typeName] == null) {
|
234
223
|
newSubschemaConfig.merge[typeName] = Object.create(null);
|
@@ -238,17 +227,18 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
238
227
|
}
|
239
228
|
for (const typeName in computedFieldSelectionSets) {
|
240
229
|
const selectionSets = computedFieldSelectionSets[typeName];
|
241
|
-
const mergeConfig =
|
230
|
+
const mergeConfig = newSubschemaConfig.merge ??
|
231
|
+
Object.create(null);
|
242
232
|
newSubschemaConfig.merge = mergeConfig;
|
243
233
|
if (mergeConfig[typeName] == null) {
|
244
234
|
mergeConfig[typeName] = Object.create(null);
|
245
235
|
}
|
246
236
|
const mergeTypeConfig = newSubschemaConfig.merge[typeName];
|
247
|
-
const mergeTypeConfigFields =
|
237
|
+
const mergeTypeConfigFields = mergeTypeConfig.fields ?? Object.create(null);
|
248
238
|
mergeTypeConfig.fields = mergeTypeConfigFields;
|
249
239
|
for (const fieldName in selectionSets) {
|
250
240
|
const selectionSet = selectionSets[fieldName];
|
251
|
-
const fieldConfig =
|
241
|
+
const fieldConfig = mergeTypeConfigFields[fieldName] ?? Object.create(null);
|
252
242
|
mergeTypeConfigFields[fieldName] = fieldConfig;
|
253
243
|
fieldConfig.selectionSet = print(selectionSet);
|
254
244
|
fieldConfig.computed = true;
|
@@ -256,7 +246,8 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
256
246
|
}
|
257
247
|
for (const typeName in mergedTypesResolversInfo) {
|
258
248
|
const mergedTypeResolverInfo = mergedTypesResolversInfo[typeName];
|
259
|
-
const mergeConfig =
|
249
|
+
const mergeConfig = newSubschemaConfig.merge ??
|
250
|
+
Object.create(null);
|
260
251
|
newSubschemaConfig.merge = mergeConfig;
|
261
252
|
if (newSubschemaConfig.merge[typeName] == null) {
|
262
253
|
newSubschemaConfig.merge[typeName] = Object.create(null);
|
@@ -273,7 +264,8 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
273
264
|
}
|
274
265
|
for (const typeName in canonicalTypesInfo) {
|
275
266
|
const canonicalTypeInfo = canonicalTypesInfo[typeName];
|
276
|
-
const mergeConfig =
|
267
|
+
const mergeConfig = newSubschemaConfig.merge ??
|
268
|
+
Object.create(null);
|
277
269
|
newSubschemaConfig.merge = mergeConfig;
|
278
270
|
if (newSubschemaConfig.merge[typeName] == null) {
|
279
271
|
newSubschemaConfig.merge[typeName] = Object.create(null);
|
@@ -283,7 +275,7 @@ export function stitchingDirectivesTransformer(options = {}) {
|
|
283
275
|
mergeTypeConfig.canonical = true;
|
284
276
|
}
|
285
277
|
if (canonicalTypeInfo.fields) {
|
286
|
-
const mergeTypeConfigFields =
|
278
|
+
const mergeTypeConfigFields = mergeTypeConfig.fields ?? Object.create(null);
|
287
279
|
mergeTypeConfig.fields = mergeTypeConfigFields;
|
288
280
|
for (const fieldName in canonicalTypeInfo.fields) {
|
289
281
|
if (mergeTypeConfigFields[fieldName] == null) {
|
@@ -9,24 +9,21 @@ export function stitchingDirectivesValidator(options = {}) {
|
|
9
9
|
...options,
|
10
10
|
};
|
11
11
|
return (schema) => {
|
12
|
-
|
13
|
-
const queryTypeName = (_a = schema.getQueryType()) === null || _a === void 0 ? void 0 : _a.name;
|
12
|
+
const queryTypeName = schema.getQueryType()?.name;
|
14
13
|
mapSchema(schema, {
|
15
14
|
[MapperKind.OBJECT_TYPE]: type => {
|
16
|
-
|
17
|
-
const keyDirective = (_a = getDirective(schema, type, keyDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
15
|
+
const keyDirective = getDirective(schema, type, keyDirectiveName, pathToDirectivesInExtensions)?.[0];
|
18
16
|
if (keyDirective != null) {
|
19
17
|
parseSelectionSet(keyDirective['selectionSet']);
|
20
18
|
}
|
21
19
|
return undefined;
|
22
20
|
},
|
23
21
|
[MapperKind.OBJECT_FIELD]: (fieldConfig, _fieldName, typeName) => {
|
24
|
-
|
25
|
-
const computedDirective = (_a = getDirective(schema, fieldConfig, computedDirectiveName, pathToDirectivesInExtensions)) === null || _a === void 0 ? void 0 : _a[0];
|
22
|
+
const computedDirective = getDirective(schema, fieldConfig, computedDirectiveName, pathToDirectivesInExtensions)?.[0];
|
26
23
|
if (computedDirective != null) {
|
27
24
|
parseSelectionSet(computedDirective['selectionSet']);
|
28
25
|
}
|
29
|
-
const mergeDirective =
|
26
|
+
const mergeDirective = getDirective(schema, fieldConfig, mergeDirectiveName, pathToDirectivesInExtensions)?.[0];
|
30
27
|
if (mergeDirective != null) {
|
31
28
|
if (typeName !== queryTypeName) {
|
32
29
|
throw new Error('@merge directive may be used only for root fields of the root Query type.');
|
@@ -42,7 +39,7 @@ export function stitchingDirectivesValidator(options = {}) {
|
|
42
39
|
if (mergeArgsExpr != null) {
|
43
40
|
parseMergeArgsExpr(mergeArgsExpr);
|
44
41
|
}
|
45
|
-
const args = Object.keys(
|
42
|
+
const args = Object.keys(fieldConfig.args ?? {});
|
46
43
|
const keyArg = mergeDirective['keyArg'];
|
47
44
|
if (keyArg == null) {
|
48
45
|
if (!mergeArgsExpr && args.length !== 1) {
|
@@ -100,7 +97,7 @@ export function stitchingDirectivesValidator(options = {}) {
|
|
100
97
|
const implementingTypes = isInterfaceType(returnType)
|
101
98
|
? getImplementingTypes(returnType.name, schema).map(typeName => schema.getType(typeName))
|
102
99
|
: returnType.getTypes();
|
103
|
-
const implementingTypeNames = implementingTypes.map(type => type
|
100
|
+
const implementingTypeNames = implementingTypes.map(type => type?.name).filter(isSome);
|
104
101
|
for (const typeName of typeNames) {
|
105
102
|
if (!implementingTypeNames.includes(typeName)) {
|
106
103
|
throw new Error(`Types argument can only include only type names that implement the field return type's abstract type.`);
|
package/package.json
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
{
|
2
2
|
"name": "@graphql-tools/stitching-directives",
|
3
|
-
"version": "3.0.0
|
3
|
+
"version": "3.0.0",
|
4
4
|
"description": "A set of utils for faster development of GraphQL tools",
|
5
5
|
"sideEffects": false,
|
6
6
|
"peerDependencies": {
|
7
7
|
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
|
8
8
|
},
|
9
9
|
"dependencies": {
|
10
|
-
"@graphql-tools/delegate": "10.0.0
|
11
|
-
"@graphql-tools/utils": "10.0.0
|
10
|
+
"@graphql-tools/delegate": "^10.0.0",
|
11
|
+
"@graphql-tools/utils": "^10.0.0",
|
12
12
|
"tslib": "^2.4.0"
|
13
13
|
},
|
14
14
|
"repository": {
|