@depup/graphql-tools__delegate 12.0.12-depup.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/README.md +32 -0
- package/changes.json +14 -0
- package/dist/index.cjs +3091 -0
- package/dist/index.d.cts +240 -0
- package/dist/index.d.ts +240 -0
- package/dist/index.js +3050 -0
- package/package.json +80 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3050 @@
|
|
|
1
|
+
import { memoize2, memoize1, collectFields, relocatedError, mergeDeep, promiseReduce, pathToArray, getResponseKeyFromInfo, memoize3, getDefinedRootType, createGraphQLError, implementsAbstractType, getRootTypeNames, astFromArg, astFromValueUntyped, asArray, isAsyncIterable, getOperationASTFromRequest } from '@graphql-tools/utils';
|
|
2
|
+
export { createDeferred } from '@graphql-tools/utils';
|
|
3
|
+
import { GraphQLError, locatedError, isAbstractType, getNullableType, isLeafType, isCompositeType, isListType, responsePathAsArray, Kind, TypeInfo, versionInfo, visit, visitWithTypeInfo, isNullableType, isUnionType, getNamedType, isObjectType, isInterfaceType, isNonNullType, isInputObjectType, defaultFieldResolver, isSchema, validate } from 'graphql';
|
|
4
|
+
import { handleMaybePromise, isPromise, createDeferredPromise, mapAsyncIterator } from '@whatwg-node/promise-helpers';
|
|
5
|
+
import { CRITICAL_ERROR, executorFromSchema } from '@graphql-tools/executor';
|
|
6
|
+
export { executorFromSchema as createDefaultExecutor } from '@graphql-tools/executor';
|
|
7
|
+
import { getBatchingExecutor } from '@graphql-tools/batch-execute';
|
|
8
|
+
import { Repeater } from '@repeaterjs/repeater';
|
|
9
|
+
|
|
10
|
+
const applySchemaTransforms = memoize2(function applySchemaTransforms2(originalWrappingSchema, subschemaConfig) {
|
|
11
|
+
const schemaTransforms = subschemaConfig.transforms;
|
|
12
|
+
if (schemaTransforms == null) {
|
|
13
|
+
return originalWrappingSchema;
|
|
14
|
+
}
|
|
15
|
+
return schemaTransforms.reduce(
|
|
16
|
+
(schema, transform) => transform.transformSchema?.(schema, subschemaConfig) || schema,
|
|
17
|
+
originalWrappingSchema
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
function isSubschema(value) {
|
|
22
|
+
return Boolean(value.transformedSchema);
|
|
23
|
+
}
|
|
24
|
+
class Subschema {
|
|
25
|
+
name;
|
|
26
|
+
schema;
|
|
27
|
+
executor;
|
|
28
|
+
batch;
|
|
29
|
+
batchingOptions;
|
|
30
|
+
createProxyingResolver;
|
|
31
|
+
transforms;
|
|
32
|
+
_transformedSchema;
|
|
33
|
+
merge;
|
|
34
|
+
constructor(config) {
|
|
35
|
+
this.name = config.name;
|
|
36
|
+
this.schema = config.schema;
|
|
37
|
+
this.executor = config.executor;
|
|
38
|
+
this.batch = config.batch;
|
|
39
|
+
this.batchingOptions = config.batchingOptions;
|
|
40
|
+
this.createProxyingResolver = config.createProxyingResolver;
|
|
41
|
+
this.transforms = config.transforms ?? [];
|
|
42
|
+
this.merge = config.merge;
|
|
43
|
+
}
|
|
44
|
+
get transformedSchema() {
|
|
45
|
+
if (!this._transformedSchema) {
|
|
46
|
+
if (globalThis.process?.env?.["DEBUG"] != null) {
|
|
47
|
+
console.warn(
|
|
48
|
+
"Transformed schema is not set yet. Returning a dummy one."
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
this._transformedSchema = applySchemaTransforms(this.schema, this);
|
|
52
|
+
}
|
|
53
|
+
return this._transformedSchema;
|
|
54
|
+
}
|
|
55
|
+
set transformedSchema(value) {
|
|
56
|
+
this._transformedSchema = value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const prototypePollutingKeys = [
|
|
61
|
+
"__proto__",
|
|
62
|
+
"constructor",
|
|
63
|
+
"prototype"
|
|
64
|
+
];
|
|
65
|
+
function isPrototypePollutingKey(key) {
|
|
66
|
+
return prototypePollutingKeys.includes(key);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const leftOverByDelegationPlan = /* @__PURE__ */ new WeakMap();
|
|
70
|
+
const PLAN_LEFT_OVER = Symbol("PLAN_LEFT_OVER");
|
|
71
|
+
function getPlanLeftOverFromParent(parent) {
|
|
72
|
+
if (parent != null && typeof parent === "object") {
|
|
73
|
+
return parent[PLAN_LEFT_OVER];
|
|
74
|
+
}
|
|
75
|
+
return void 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const UNPATHED_ERRORS_SYMBOL = Symbol.for("subschemaErrors");
|
|
79
|
+
const OBJECT_SUBSCHEMA_SYMBOL = Symbol.for("initialSubschema");
|
|
80
|
+
const FIELD_SUBSCHEMA_MAP_SYMBOL = Symbol.for("subschemaMap");
|
|
81
|
+
|
|
82
|
+
function isExternalObject(data) {
|
|
83
|
+
return data[UNPATHED_ERRORS_SYMBOL] !== void 0;
|
|
84
|
+
}
|
|
85
|
+
function annotateExternalObject(object, errors, subschema, subschemaMap) {
|
|
86
|
+
Object.defineProperties(object, {
|
|
87
|
+
[OBJECT_SUBSCHEMA_SYMBOL]: { value: subschema, writable: true },
|
|
88
|
+
[FIELD_SUBSCHEMA_MAP_SYMBOL]: { value: subschemaMap, writable: true },
|
|
89
|
+
[UNPATHED_ERRORS_SYMBOL]: { value: errors, writable: true }
|
|
90
|
+
});
|
|
91
|
+
return object;
|
|
92
|
+
}
|
|
93
|
+
function getSubschema(object, responseKey) {
|
|
94
|
+
return object[FIELD_SUBSCHEMA_MAP_SYMBOL]?.[responseKey] ?? object[OBJECT_SUBSCHEMA_SYMBOL];
|
|
95
|
+
}
|
|
96
|
+
function getUnpathedErrors(object) {
|
|
97
|
+
return object[UNPATHED_ERRORS_SYMBOL];
|
|
98
|
+
}
|
|
99
|
+
const EMPTY_ARRAY = [];
|
|
100
|
+
const EMPTY_OBJECT = /* @__PURE__ */ Object.create(null);
|
|
101
|
+
const getActualFieldNodes = memoize1(function(fieldNode) {
|
|
102
|
+
return [fieldNode];
|
|
103
|
+
});
|
|
104
|
+
function mergeFields(mergedTypeInfo, object, sourceSubschema, context, info) {
|
|
105
|
+
const delegationMaps = mergedTypeInfo.delegationPlanBuilder(
|
|
106
|
+
info.schema,
|
|
107
|
+
sourceSubschema,
|
|
108
|
+
info.variableValues != null && Object.keys(info.variableValues).length > 0 ? info.variableValues : EMPTY_OBJECT,
|
|
109
|
+
info.fragments != null && Object.keys(info.fragments).length > 0 ? info.fragments : EMPTY_OBJECT,
|
|
110
|
+
info.fieldNodes?.length ? info.fieldNodes.length === 1 && info.fieldNodes[0] ? getActualFieldNodes(info.fieldNodes[0]) : info.fieldNodes : EMPTY_ARRAY,
|
|
111
|
+
context,
|
|
112
|
+
info
|
|
113
|
+
);
|
|
114
|
+
const leftOver = leftOverByDelegationPlan.get(delegationMaps);
|
|
115
|
+
if (leftOver) {
|
|
116
|
+
object[PLAN_LEFT_OVER] = leftOver;
|
|
117
|
+
}
|
|
118
|
+
return handleMaybePromise(
|
|
119
|
+
() => promiseReduce(
|
|
120
|
+
delegationMaps,
|
|
121
|
+
(_, delegationMap) => executeDelegationStage(
|
|
122
|
+
mergedTypeInfo,
|
|
123
|
+
delegationMap,
|
|
124
|
+
object,
|
|
125
|
+
context,
|
|
126
|
+
info
|
|
127
|
+
),
|
|
128
|
+
void 0
|
|
129
|
+
),
|
|
130
|
+
() => object
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
function handleResolverResult(resolverResult, subschema, selectionSet, object, combinedFieldSubschemaMap, info, path, combinedErrors) {
|
|
134
|
+
if (resolverResult instanceof Error || resolverResult == null) {
|
|
135
|
+
const schema = subschema.transformedSchema || info.schema;
|
|
136
|
+
const type = schema.getType(object.__typename);
|
|
137
|
+
const { fields } = collectFields(
|
|
138
|
+
schema,
|
|
139
|
+
info.fragments,
|
|
140
|
+
info.variableValues,
|
|
141
|
+
type,
|
|
142
|
+
selectionSet
|
|
143
|
+
);
|
|
144
|
+
const nullResult = {};
|
|
145
|
+
for (const [responseKey, fieldNodes] of fields) {
|
|
146
|
+
const combinedPath = [...path, responseKey];
|
|
147
|
+
if (resolverResult instanceof GraphQLError) {
|
|
148
|
+
if (resolverResult.message.includes(
|
|
149
|
+
"Cannot return null for non-nullable field"
|
|
150
|
+
)) {
|
|
151
|
+
nullResult[responseKey] = null;
|
|
152
|
+
} else {
|
|
153
|
+
nullResult[responseKey] = relocatedError(
|
|
154
|
+
resolverResult,
|
|
155
|
+
combinedPath
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
} else if (resolverResult instanceof Error) {
|
|
159
|
+
nullResult[responseKey] = locatedError(
|
|
160
|
+
resolverResult,
|
|
161
|
+
fieldNodes,
|
|
162
|
+
combinedPath
|
|
163
|
+
);
|
|
164
|
+
} else {
|
|
165
|
+
nullResult[responseKey] = null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
resolverResult = nullResult;
|
|
169
|
+
} else {
|
|
170
|
+
if (resolverResult[UNPATHED_ERRORS_SYMBOL]) {
|
|
171
|
+
combinedErrors.push(...resolverResult[UNPATHED_ERRORS_SYMBOL]);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const objectSubschema = resolverResult[OBJECT_SUBSCHEMA_SYMBOL];
|
|
175
|
+
const fieldSubschemaMap = resolverResult[FIELD_SUBSCHEMA_MAP_SYMBOL];
|
|
176
|
+
for (const responseKey in resolverResult) {
|
|
177
|
+
if (isPrototypePollutingKey(responseKey)) {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const existingPropValue = object[responseKey];
|
|
181
|
+
const sourcePropValue = resolverResult[responseKey];
|
|
182
|
+
if (responseKey === "__typename" && existingPropValue !== sourcePropValue && isAbstractType(subschema.transformedSchema.getType(sourcePropValue))) {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (sourcePropValue != null || existingPropValue == null) {
|
|
186
|
+
if (existingPropValue != null && typeof existingPropValue === "object" && !(existingPropValue instanceof Error) && Object.keys(existingPropValue).length > 0) {
|
|
187
|
+
if (Array.isArray(existingPropValue) && Array.isArray(sourcePropValue) && existingPropValue.length === sourcePropValue.length) {
|
|
188
|
+
object[responseKey] = existingPropValue.map(
|
|
189
|
+
(existingElement, index) => sourcePropValue instanceof Error ? existingElement : mergeDeep(
|
|
190
|
+
[existingElement, sourcePropValue[index]],
|
|
191
|
+
void 0,
|
|
192
|
+
true,
|
|
193
|
+
true
|
|
194
|
+
)
|
|
195
|
+
);
|
|
196
|
+
} else if (!(sourcePropValue instanceof Error)) {
|
|
197
|
+
object[responseKey] = mergeDeep(
|
|
198
|
+
[existingPropValue, sourcePropValue],
|
|
199
|
+
void 0,
|
|
200
|
+
true,
|
|
201
|
+
true
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
} else {
|
|
205
|
+
object[responseKey] = sourcePropValue;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
combinedFieldSubschemaMap[responseKey] = fieldSubschemaMap?.[responseKey] ?? objectSubschema ?? subschema;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function executeDelegationStage(mergedTypeInfo, delegationMap, object, context, info) {
|
|
212
|
+
const combinedErrors = object[UNPATHED_ERRORS_SYMBOL];
|
|
213
|
+
const path = pathToArray(info.path);
|
|
214
|
+
const combinedFieldSubschemaMap = object[FIELD_SUBSCHEMA_MAP_SYMBOL];
|
|
215
|
+
const jobs = [];
|
|
216
|
+
for (const [subschema, selectionSet] of delegationMap) {
|
|
217
|
+
const schema = subschema.transformedSchema || info.schema;
|
|
218
|
+
const type = schema.getType(object.__typename);
|
|
219
|
+
const resolver = mergedTypeInfo.resolvers.get(subschema);
|
|
220
|
+
if (resolver) {
|
|
221
|
+
try {
|
|
222
|
+
const resolverResult$ = resolver(
|
|
223
|
+
object,
|
|
224
|
+
context,
|
|
225
|
+
info,
|
|
226
|
+
subschema,
|
|
227
|
+
selectionSet,
|
|
228
|
+
void 0,
|
|
229
|
+
type
|
|
230
|
+
);
|
|
231
|
+
if (isPromise(resolverResult$)) {
|
|
232
|
+
jobs.push(
|
|
233
|
+
resolverResult$.then(
|
|
234
|
+
(resolverResult) => handleResolverResult(
|
|
235
|
+
resolverResult,
|
|
236
|
+
subschema,
|
|
237
|
+
selectionSet,
|
|
238
|
+
object,
|
|
239
|
+
combinedFieldSubschemaMap,
|
|
240
|
+
info,
|
|
241
|
+
path,
|
|
242
|
+
combinedErrors
|
|
243
|
+
),
|
|
244
|
+
(error) => handleResolverResult(
|
|
245
|
+
error,
|
|
246
|
+
subschema,
|
|
247
|
+
selectionSet,
|
|
248
|
+
object,
|
|
249
|
+
combinedFieldSubschemaMap,
|
|
250
|
+
info,
|
|
251
|
+
path,
|
|
252
|
+
combinedErrors
|
|
253
|
+
)
|
|
254
|
+
)
|
|
255
|
+
);
|
|
256
|
+
} else {
|
|
257
|
+
handleResolverResult(
|
|
258
|
+
resolverResult$,
|
|
259
|
+
subschema,
|
|
260
|
+
selectionSet,
|
|
261
|
+
object,
|
|
262
|
+
combinedFieldSubschemaMap,
|
|
263
|
+
info,
|
|
264
|
+
path,
|
|
265
|
+
combinedErrors
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
} catch (error) {
|
|
269
|
+
handleResolverResult(
|
|
270
|
+
error,
|
|
271
|
+
subschema,
|
|
272
|
+
selectionSet,
|
|
273
|
+
object,
|
|
274
|
+
combinedFieldSubschemaMap,
|
|
275
|
+
info,
|
|
276
|
+
path,
|
|
277
|
+
combinedErrors
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (jobs.length) {
|
|
283
|
+
if (jobs.length === 1) {
|
|
284
|
+
return jobs[0];
|
|
285
|
+
}
|
|
286
|
+
return Promise.all(jobs);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function resolveExternalValue(result, unpathedErrors, subschema, context, info, returnType = getReturnType$1(info), skipTypeMerging) {
|
|
291
|
+
const type = getNullableType(returnType);
|
|
292
|
+
if (result instanceof Error) {
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
295
|
+
if (result == null) {
|
|
296
|
+
return reportUnpathedErrorsViaNull(unpathedErrors);
|
|
297
|
+
}
|
|
298
|
+
if (isLeafType(type)) {
|
|
299
|
+
try {
|
|
300
|
+
return type.parseValue(result);
|
|
301
|
+
} catch {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
} else if (isCompositeType(type)) {
|
|
305
|
+
return handleMaybePromise(
|
|
306
|
+
() => resolveExternalObject(
|
|
307
|
+
type,
|
|
308
|
+
result,
|
|
309
|
+
unpathedErrors,
|
|
310
|
+
subschema,
|
|
311
|
+
context,
|
|
312
|
+
info,
|
|
313
|
+
skipTypeMerging
|
|
314
|
+
),
|
|
315
|
+
(result2) => {
|
|
316
|
+
if (info && isAbstractType(type)) {
|
|
317
|
+
if (result2.__typename != null) {
|
|
318
|
+
const resolvedType = info.schema.getType(result2.__typename);
|
|
319
|
+
if (!resolvedType) {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return result2;
|
|
324
|
+
}
|
|
325
|
+
return result2;
|
|
326
|
+
}
|
|
327
|
+
);
|
|
328
|
+
} else if (isListType(type)) {
|
|
329
|
+
if (Array.isArray(result)) {
|
|
330
|
+
return resolveExternalList(
|
|
331
|
+
type,
|
|
332
|
+
result,
|
|
333
|
+
unpathedErrors,
|
|
334
|
+
subschema,
|
|
335
|
+
context,
|
|
336
|
+
info,
|
|
337
|
+
skipTypeMerging
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
return resolveExternalValue(
|
|
341
|
+
result,
|
|
342
|
+
unpathedErrors,
|
|
343
|
+
subschema,
|
|
344
|
+
context,
|
|
345
|
+
info,
|
|
346
|
+
type.ofType,
|
|
347
|
+
skipTypeMerging
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function resolveExternalObject(type, object, unpathedErrors, subschema, context, info, skipTypeMerging) {
|
|
352
|
+
if (!isExternalObject(object)) {
|
|
353
|
+
annotateExternalObject(
|
|
354
|
+
object,
|
|
355
|
+
unpathedErrors,
|
|
356
|
+
subschema,
|
|
357
|
+
/* @__PURE__ */ Object.create(null)
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
if (skipTypeMerging || info == null) {
|
|
361
|
+
return object;
|
|
362
|
+
}
|
|
363
|
+
const stitchingInfo = info.schema.extensions?.["stitchingInfo"];
|
|
364
|
+
if (stitchingInfo == null) {
|
|
365
|
+
return object;
|
|
366
|
+
}
|
|
367
|
+
let mergedTypeInfo;
|
|
368
|
+
const possibleTypeNames = [object.__typename, type.name];
|
|
369
|
+
for (const possibleTypeName of possibleTypeNames) {
|
|
370
|
+
if (possibleTypeName != null && stitchingInfo.mergedTypes[possibleTypeName]?.targetSubschemas?.get(
|
|
371
|
+
subschema
|
|
372
|
+
)?.length) {
|
|
373
|
+
mergedTypeInfo = stitchingInfo.mergedTypes[possibleTypeName];
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if (!mergedTypeInfo) {
|
|
378
|
+
for (const possibleTypeName of possibleTypeNames) {
|
|
379
|
+
const potentialMergedTypeInfo = stitchingInfo.mergedTypes[possibleTypeName];
|
|
380
|
+
if (potentialMergedTypeInfo != null) {
|
|
381
|
+
for (const [
|
|
382
|
+
sourceSubschema,
|
|
383
|
+
targetSubschemas
|
|
384
|
+
] of potentialMergedTypeInfo.targetSubschemas) {
|
|
385
|
+
if (targetSubschemas.length && sourceSubschema.name === subschema.name) {
|
|
386
|
+
subschema = sourceSubschema;
|
|
387
|
+
mergedTypeInfo = potentialMergedTypeInfo;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (!mergedTypeInfo) {
|
|
395
|
+
return object;
|
|
396
|
+
}
|
|
397
|
+
return mergeFields(
|
|
398
|
+
mergedTypeInfo,
|
|
399
|
+
object,
|
|
400
|
+
subschema,
|
|
401
|
+
context,
|
|
402
|
+
info
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
function resolveExternalList(type, list, unpathedErrors, subschema, context, info, skipTypeMerging) {
|
|
406
|
+
return list.map(
|
|
407
|
+
(listMember) => resolveExternalValue(
|
|
408
|
+
listMember,
|
|
409
|
+
unpathedErrors,
|
|
410
|
+
subschema,
|
|
411
|
+
context,
|
|
412
|
+
info,
|
|
413
|
+
type.ofType,
|
|
414
|
+
skipTypeMerging
|
|
415
|
+
)
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
const reportedErrors = /* @__PURE__ */ new WeakSet();
|
|
419
|
+
function reportUnpathedErrorsViaNull(unpathedErrors) {
|
|
420
|
+
if (unpathedErrors.length) {
|
|
421
|
+
const unreportedErrors = [];
|
|
422
|
+
for (const error of unpathedErrors) {
|
|
423
|
+
if (!reportedErrors.has(error)) {
|
|
424
|
+
unreportedErrors.push(error);
|
|
425
|
+
reportedErrors.add(error);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (unreportedErrors.length) {
|
|
429
|
+
const unreportedError = unreportedErrors[0];
|
|
430
|
+
if (unreportedErrors.length === 1 && unreportedError) {
|
|
431
|
+
return locatedError(
|
|
432
|
+
unreportedError,
|
|
433
|
+
void 0,
|
|
434
|
+
unreportedError.path
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
return new AggregateError(
|
|
438
|
+
unreportedErrors.map(
|
|
439
|
+
(e) => (
|
|
440
|
+
// We cast path as any for GraphQL.js 14 compat
|
|
441
|
+
// locatedError path argument must be defined, but it is just forwarded to a constructor that allows a undefined value
|
|
442
|
+
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/locatedError.js#L25
|
|
443
|
+
// https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/GraphQLError.js#L19
|
|
444
|
+
locatedError(e, void 0, unreportedError?.path)
|
|
445
|
+
)
|
|
446
|
+
),
|
|
447
|
+
unreportedErrors.map((error) => error.message).join(", \n")
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
function getReturnType$1(info) {
|
|
454
|
+
if (info == null) {
|
|
455
|
+
throw new Error(`Return type cannot be inferred without a source schema.`);
|
|
456
|
+
}
|
|
457
|
+
return info.returnType;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function checkResultAndHandleErrors(result = {
|
|
461
|
+
data: null,
|
|
462
|
+
errors: []
|
|
463
|
+
}, delegationContext) {
|
|
464
|
+
const {
|
|
465
|
+
context,
|
|
466
|
+
info,
|
|
467
|
+
fieldName: responseKey = getResponseKey(info),
|
|
468
|
+
subschema,
|
|
469
|
+
returnType = getReturnType(info),
|
|
470
|
+
skipTypeMerging,
|
|
471
|
+
onLocatedError
|
|
472
|
+
} = delegationContext;
|
|
473
|
+
const { data, unpathedErrors } = mergeDataAndErrors(
|
|
474
|
+
result.data == null ? void 0 : result.data[responseKey],
|
|
475
|
+
result.errors == null ? [] : result.errors,
|
|
476
|
+
info != null && info.path ? responsePathAsArray(info.path) : void 0,
|
|
477
|
+
onLocatedError
|
|
478
|
+
);
|
|
479
|
+
return resolveExternalValue(
|
|
480
|
+
data,
|
|
481
|
+
unpathedErrors,
|
|
482
|
+
subschema,
|
|
483
|
+
context,
|
|
484
|
+
info,
|
|
485
|
+
returnType,
|
|
486
|
+
skipTypeMerging
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
function mergeDataAndErrors(data, errors, path, onLocatedError, index = 1) {
|
|
490
|
+
if (data == null) {
|
|
491
|
+
if (!errors.length) {
|
|
492
|
+
return { data: null, unpathedErrors: [] };
|
|
493
|
+
}
|
|
494
|
+
if (errors.length === 1 && errors[0]) {
|
|
495
|
+
const error = onLocatedError ? onLocatedError(errors[0]) : errors[0];
|
|
496
|
+
const newPath = path === void 0 ? error.path : !error.path ? path : path.concat(error.path.slice(1));
|
|
497
|
+
return { data: relocatedError(errors[0], newPath), unpathedErrors: [] };
|
|
498
|
+
}
|
|
499
|
+
const combinedError = new AggregateError(
|
|
500
|
+
errors.map((e) => {
|
|
501
|
+
const error = onLocatedError ? onLocatedError(e) : e;
|
|
502
|
+
const newPath = path === void 0 ? error.path : !error.path ? path : path.concat(error.path.slice(1));
|
|
503
|
+
return relocatedError(error, newPath);
|
|
504
|
+
}),
|
|
505
|
+
errors.map((error) => error.message).join(",\n")
|
|
506
|
+
);
|
|
507
|
+
return { data: combinedError, unpathedErrors: [] };
|
|
508
|
+
}
|
|
509
|
+
if (!errors.length) {
|
|
510
|
+
return { data, unpathedErrors: [] };
|
|
511
|
+
}
|
|
512
|
+
const unpathedErrors = [];
|
|
513
|
+
const errorMap = /* @__PURE__ */ new Map();
|
|
514
|
+
for (const error of errors) {
|
|
515
|
+
const pathSegment = error.path?.[index];
|
|
516
|
+
if (pathSegment != null) {
|
|
517
|
+
let pathSegmentErrors = errorMap.get(pathSegment);
|
|
518
|
+
if (pathSegmentErrors === void 0) {
|
|
519
|
+
pathSegmentErrors = [error];
|
|
520
|
+
errorMap.set(pathSegment, pathSegmentErrors);
|
|
521
|
+
} else {
|
|
522
|
+
pathSegmentErrors.push(error);
|
|
523
|
+
}
|
|
524
|
+
} else {
|
|
525
|
+
unpathedErrors.push(error);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
for (const [pathSegment, pathSegmentErrors] of errorMap) {
|
|
529
|
+
if (data[pathSegment] !== void 0) {
|
|
530
|
+
const { data: newData, unpathedErrors: newErrors } = mergeDataAndErrors(
|
|
531
|
+
data[pathSegment],
|
|
532
|
+
pathSegmentErrors,
|
|
533
|
+
path,
|
|
534
|
+
onLocatedError,
|
|
535
|
+
index + 1
|
|
536
|
+
);
|
|
537
|
+
data[pathSegment] = newData;
|
|
538
|
+
unpathedErrors.push(...newErrors);
|
|
539
|
+
} else {
|
|
540
|
+
unpathedErrors.push(...pathSegmentErrors);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return { data, unpathedErrors };
|
|
544
|
+
}
|
|
545
|
+
function getResponseKey(info) {
|
|
546
|
+
if (info == null) {
|
|
547
|
+
throw new Error(
|
|
548
|
+
`Data cannot be extracted from result without an explicit key or source schema.`
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
return getResponseKeyFromInfo(info);
|
|
552
|
+
}
|
|
553
|
+
function getReturnType(info) {
|
|
554
|
+
if (info == null) {
|
|
555
|
+
throw new Error(`Return type cannot be inferred without a source schema.`);
|
|
556
|
+
}
|
|
557
|
+
return info.returnType;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
function getDocumentMetadata(document) {
|
|
561
|
+
const operations = [];
|
|
562
|
+
const fragments = [];
|
|
563
|
+
const fragmentNames = /* @__PURE__ */ new Set();
|
|
564
|
+
for (let i = 0; i < document.definitions.length; i++) {
|
|
565
|
+
const def = document.definitions[i];
|
|
566
|
+
if (def?.kind === Kind.FRAGMENT_DEFINITION) {
|
|
567
|
+
fragments.push(def);
|
|
568
|
+
fragmentNames.add(def.name.value);
|
|
569
|
+
} else if (def?.kind === Kind.OPERATION_DEFINITION) {
|
|
570
|
+
operations.push(def);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
return {
|
|
574
|
+
operations,
|
|
575
|
+
fragments,
|
|
576
|
+
fragmentNames
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const getTypeInfo = memoize1(function getTypeInfo2(schema) {
|
|
581
|
+
return new TypeInfo(schema);
|
|
582
|
+
});
|
|
583
|
+
const getTypeInfoWithType = memoize2(function getTypeInfoWithType2(schema, type) {
|
|
584
|
+
return versionInfo.major < 16 ? new TypeInfo(schema, void 0, type) : new TypeInfo(schema, type);
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
const handleOverrideByDelegation = memoize3(
|
|
588
|
+
function handleOverrideByDelegation2(info, context, overrideHandler) {
|
|
589
|
+
return overrideHandler(context, info);
|
|
590
|
+
}
|
|
591
|
+
);
|
|
592
|
+
|
|
593
|
+
function finalizeGatewayDocument(targetSchema, fragments, operations, onOverlappingAliases, delegationContext) {
|
|
594
|
+
let usedVariables = [];
|
|
595
|
+
let usedFragments = [];
|
|
596
|
+
const newOperations = [];
|
|
597
|
+
let newFragments = [];
|
|
598
|
+
const validFragments = [];
|
|
599
|
+
const validFragmentsWithType = /* @__PURE__ */ Object.create(null);
|
|
600
|
+
for (const fragment of fragments) {
|
|
601
|
+
if (fragment.selectionSet.selections.length === 0) {
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
const typeName = fragment.typeCondition.name.value;
|
|
605
|
+
const type = targetSchema.getType(typeName);
|
|
606
|
+
if (type != null) {
|
|
607
|
+
validFragments.push(fragment);
|
|
608
|
+
validFragmentsWithType[fragment.name.value] = type;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
let fragmentSet = /* @__PURE__ */ Object.create(null);
|
|
612
|
+
let selectionCnt = 0;
|
|
613
|
+
for (const operation of operations) {
|
|
614
|
+
const type = getDefinedRootType(targetSchema, operation.operation);
|
|
615
|
+
const {
|
|
616
|
+
selectionSet,
|
|
617
|
+
usedFragments: operationUsedFragments,
|
|
618
|
+
usedVariables: operationUsedVariables
|
|
619
|
+
} = finalizeSelectionSet(
|
|
620
|
+
targetSchema,
|
|
621
|
+
type,
|
|
622
|
+
validFragmentsWithType,
|
|
623
|
+
operation.selectionSet,
|
|
624
|
+
onOverlappingAliases,
|
|
625
|
+
delegationContext
|
|
626
|
+
);
|
|
627
|
+
usedFragments = union(usedFragments, operationUsedFragments);
|
|
628
|
+
const {
|
|
629
|
+
usedVariables: collectedUsedVariables,
|
|
630
|
+
newFragments: collectedNewFragments,
|
|
631
|
+
fragmentSet: collectedFragmentSet
|
|
632
|
+
} = collectFragmentVariables(
|
|
633
|
+
targetSchema,
|
|
634
|
+
fragmentSet,
|
|
635
|
+
validFragments,
|
|
636
|
+
validFragmentsWithType,
|
|
637
|
+
usedFragments,
|
|
638
|
+
onOverlappingAliases,
|
|
639
|
+
delegationContext
|
|
640
|
+
);
|
|
641
|
+
const operationOrFragmentVariables = union(
|
|
642
|
+
operationUsedVariables,
|
|
643
|
+
collectedUsedVariables
|
|
644
|
+
);
|
|
645
|
+
usedVariables = union(usedVariables, operationOrFragmentVariables);
|
|
646
|
+
newFragments = collectedNewFragments;
|
|
647
|
+
fragmentSet = collectedFragmentSet;
|
|
648
|
+
const variableDefinitions = [];
|
|
649
|
+
for (const variableName of operationOrFragmentVariables) {
|
|
650
|
+
const variableDef = operation.variableDefinitions?.find(
|
|
651
|
+
(varDef) => varDef.variable.name.value === variableName
|
|
652
|
+
);
|
|
653
|
+
if (variableDef != null) {
|
|
654
|
+
variableDefinitions.push(variableDef);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
if (operation.operation === "subscription") {
|
|
658
|
+
selectionSet.selections = selectionSet.selections.filter(
|
|
659
|
+
(selection) => selection.kind !== Kind.FIELD || selection.name.value !== "__typename"
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
if (selectionSet.selections.length === 1 && selectionSet.selections[0] && selectionSet.selections[0].kind === Kind.FIELD && selectionSet.selections[0].name.value === "__typename") {
|
|
663
|
+
continue;
|
|
664
|
+
}
|
|
665
|
+
selectionCnt += selectionSet.selections.length;
|
|
666
|
+
newOperations.push({
|
|
667
|
+
kind: Kind.OPERATION_DEFINITION,
|
|
668
|
+
operation: operation.operation,
|
|
669
|
+
name: operation.name,
|
|
670
|
+
directives: operation.directives,
|
|
671
|
+
variableDefinitions,
|
|
672
|
+
selectionSet
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
if (!newOperations.length || selectionCnt === 0) {
|
|
676
|
+
throw createGraphQLError(
|
|
677
|
+
"Failed to create a gateway request. The request must contain at least one operation.",
|
|
678
|
+
{
|
|
679
|
+
extensions: {
|
|
680
|
+
[CRITICAL_ERROR]: true
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
let newDocument = {
|
|
686
|
+
kind: Kind.DOCUMENT,
|
|
687
|
+
definitions: [...newOperations, ...newFragments]
|
|
688
|
+
};
|
|
689
|
+
const stitchingInfo = delegationContext.info?.schema?.extensions?.["stitchingInfo"];
|
|
690
|
+
if (stitchingInfo != null) {
|
|
691
|
+
const typeInfo = getTypeInfo(targetSchema);
|
|
692
|
+
newDocument = visit(
|
|
693
|
+
newDocument,
|
|
694
|
+
visitWithTypeInfo(typeInfo, {
|
|
695
|
+
[Kind.FIELD](fieldNode) {
|
|
696
|
+
const parentType = typeInfo.getParentType();
|
|
697
|
+
if (parentType) {
|
|
698
|
+
const parentTypeName = parentType.name;
|
|
699
|
+
const typeConfig = stitchingInfo?.mergedTypes?.[parentTypeName];
|
|
700
|
+
if (typeConfig) {
|
|
701
|
+
const providedSelectionsByField = typeConfig?.providedSelectionsByField?.get(
|
|
702
|
+
delegationContext.subschema
|
|
703
|
+
);
|
|
704
|
+
if (providedSelectionsByField) {
|
|
705
|
+
const providedSelection = providedSelectionsByField[fieldNode.name.value];
|
|
706
|
+
if (providedSelection) {
|
|
707
|
+
return {
|
|
708
|
+
...fieldNode,
|
|
709
|
+
selectionSet: {
|
|
710
|
+
kind: Kind.SELECTION_SET,
|
|
711
|
+
selections: [
|
|
712
|
+
...providedSelection.selections,
|
|
713
|
+
...fieldNode.selectionSet?.selections ?? []
|
|
714
|
+
]
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return fieldNode;
|
|
722
|
+
}
|
|
723
|
+
})
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
return {
|
|
727
|
+
usedVariables,
|
|
728
|
+
newDocument
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
function finalizeGatewayRequest(originalRequest, delegationContext, onOverlappingAliases) {
|
|
732
|
+
let { operations, fragments } = getDocumentMetadata(originalRequest.document);
|
|
733
|
+
const { targetSchema } = delegationContext;
|
|
734
|
+
const { usedVariables, newDocument } = finalizeGatewayDocument(
|
|
735
|
+
targetSchema,
|
|
736
|
+
fragments,
|
|
737
|
+
operations,
|
|
738
|
+
onOverlappingAliases,
|
|
739
|
+
delegationContext
|
|
740
|
+
);
|
|
741
|
+
const newVariables = {};
|
|
742
|
+
const outerVariables = delegationContext.info?.variableValues;
|
|
743
|
+
for (const varName of usedVariables) {
|
|
744
|
+
const existingVar = originalRequest.variables?.[varName];
|
|
745
|
+
const outerVar = outerVariables?.[varName];
|
|
746
|
+
if (existingVar != null) {
|
|
747
|
+
newVariables[varName] = existingVar;
|
|
748
|
+
} else if (outerVar != null) {
|
|
749
|
+
newVariables[varName] = outerVar;
|
|
750
|
+
}
|
|
751
|
+
if (existingVar === null || outerVar === null) {
|
|
752
|
+
newVariables[varName] = null;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
return {
|
|
756
|
+
...originalRequest,
|
|
757
|
+
document: newDocument,
|
|
758
|
+
variables: newVariables
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
function isTypeNameField(selection) {
|
|
762
|
+
return selection.kind === Kind.FIELD && !selection.alias && selection.name.value === "__typename";
|
|
763
|
+
}
|
|
764
|
+
function filterTypenameFields(selections) {
|
|
765
|
+
let hasTypeNameField = false;
|
|
766
|
+
const filteredSelections = selections.filter((selection) => {
|
|
767
|
+
if (isTypeNameField(selection)) {
|
|
768
|
+
hasTypeNameField = true;
|
|
769
|
+
return false;
|
|
770
|
+
}
|
|
771
|
+
return true;
|
|
772
|
+
});
|
|
773
|
+
return {
|
|
774
|
+
hasTypeNameField,
|
|
775
|
+
selections: filteredSelections
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
function collectFragmentVariables(targetSchema, fragmentSet, validFragments, validFragmentsWithType, usedFragments, onOverlappingAliases, delegationContext) {
|
|
779
|
+
let remainingFragments = usedFragments.slice();
|
|
780
|
+
let usedVariables = [];
|
|
781
|
+
const newFragments = [];
|
|
782
|
+
while (remainingFragments.length !== 0) {
|
|
783
|
+
const nextFragmentName = remainingFragments.pop();
|
|
784
|
+
const fragment = validFragments.find(
|
|
785
|
+
(fr) => fr.name.value === nextFragmentName
|
|
786
|
+
);
|
|
787
|
+
if (fragment != null) {
|
|
788
|
+
const name = nextFragmentName;
|
|
789
|
+
const typeName = fragment.typeCondition.name.value;
|
|
790
|
+
const type = targetSchema.getType(typeName);
|
|
791
|
+
if (type == null) {
|
|
792
|
+
throw new Error(
|
|
793
|
+
`Fragment reference type "${typeName}", but the type is not contained within the target schema.`
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
const {
|
|
797
|
+
selectionSet,
|
|
798
|
+
usedFragments: fragmentUsedFragments,
|
|
799
|
+
usedVariables: fragmentUsedVariables
|
|
800
|
+
} = finalizeSelectionSet(
|
|
801
|
+
targetSchema,
|
|
802
|
+
type,
|
|
803
|
+
validFragmentsWithType,
|
|
804
|
+
fragment.selectionSet,
|
|
805
|
+
onOverlappingAliases,
|
|
806
|
+
delegationContext
|
|
807
|
+
);
|
|
808
|
+
remainingFragments = union(remainingFragments, fragmentUsedFragments);
|
|
809
|
+
usedVariables = union(usedVariables, fragmentUsedVariables);
|
|
810
|
+
if (name && !(name in fragmentSet)) {
|
|
811
|
+
fragmentSet[name] = true;
|
|
812
|
+
newFragments.push({
|
|
813
|
+
kind: Kind.FRAGMENT_DEFINITION,
|
|
814
|
+
name: {
|
|
815
|
+
kind: Kind.NAME,
|
|
816
|
+
value: name
|
|
817
|
+
},
|
|
818
|
+
typeCondition: fragment.typeCondition,
|
|
819
|
+
selectionSet
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
return {
|
|
825
|
+
usedVariables,
|
|
826
|
+
newFragments,
|
|
827
|
+
fragmentSet
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
const filteredSelectionSetVisitorKeys = {
|
|
831
|
+
SelectionSet: ["selections"],
|
|
832
|
+
Field: ["selectionSet"],
|
|
833
|
+
InlineFragment: ["selectionSet"],
|
|
834
|
+
FragmentDefinition: ["selectionSet"]
|
|
835
|
+
};
|
|
836
|
+
const variablesVisitorKeys = {
|
|
837
|
+
SelectionSet: ["selections"],
|
|
838
|
+
Field: ["arguments", "directives", "selectionSet"],
|
|
839
|
+
Argument: ["value"],
|
|
840
|
+
InlineFragment: ["directives", "selectionSet"],
|
|
841
|
+
FragmentSpread: ["directives"],
|
|
842
|
+
FragmentDefinition: ["selectionSet"],
|
|
843
|
+
ObjectValue: ["fields"],
|
|
844
|
+
ObjectField: ["name", "value"],
|
|
845
|
+
Directive: ["arguments"],
|
|
846
|
+
ListValue: ["values"]
|
|
847
|
+
};
|
|
848
|
+
function finalizeSelectionSet(schema, type, validFragments, selectionSet, onOverlappingAliases, delegationContext) {
|
|
849
|
+
const usedFragments = [];
|
|
850
|
+
const usedVariables = [];
|
|
851
|
+
const typeInfo = getTypeInfoWithType(schema, type);
|
|
852
|
+
const seenNonNullableMap = /* @__PURE__ */ new WeakMap();
|
|
853
|
+
const seenNullableMap = /* @__PURE__ */ new WeakMap();
|
|
854
|
+
const filteredSelectionSet = filterSelectionSet(
|
|
855
|
+
schema,
|
|
856
|
+
typeInfo,
|
|
857
|
+
validFragments,
|
|
858
|
+
selectionSet,
|
|
859
|
+
onOverlappingAliases,
|
|
860
|
+
usedFragments,
|
|
861
|
+
seenNonNullableMap,
|
|
862
|
+
seenNullableMap,
|
|
863
|
+
delegationContext
|
|
864
|
+
);
|
|
865
|
+
visit(
|
|
866
|
+
filteredSelectionSet,
|
|
867
|
+
{
|
|
868
|
+
[Kind.VARIABLE]: (variableNode) => {
|
|
869
|
+
usedVariables.push(variableNode.name.value);
|
|
870
|
+
}
|
|
871
|
+
},
|
|
872
|
+
// visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
873
|
+
// empty keys cannot be removed only because of typescript errors
|
|
874
|
+
// will hopefully be fixed in future version of graphql-js to be optional
|
|
875
|
+
variablesVisitorKeys
|
|
876
|
+
);
|
|
877
|
+
return {
|
|
878
|
+
selectionSet: filteredSelectionSet,
|
|
879
|
+
usedFragments,
|
|
880
|
+
usedVariables
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
function filterSelectionSet(schema, typeInfo, validFragments, selectionSet, onOverlappingAliases, usedFragments, seenNonNullableMap, seenNullableMap, delegationContext) {
|
|
884
|
+
return visit(
|
|
885
|
+
selectionSet,
|
|
886
|
+
visitWithTypeInfo(typeInfo, {
|
|
887
|
+
[Kind.FIELD]: {
|
|
888
|
+
enter: (node) => {
|
|
889
|
+
const parentType = typeInfo.getParentType();
|
|
890
|
+
const field = typeInfo.getFieldDef();
|
|
891
|
+
if (delegationContext.context != null && delegationContext.info != null && parentType != null && field != null) {
|
|
892
|
+
const parentTypeName = parentType.name;
|
|
893
|
+
const overrideHandler = delegationContext.subschemaConfig?.merge?.[parentTypeName]?.fields?.[field.name]?.override;
|
|
894
|
+
if (overrideHandler != null) {
|
|
895
|
+
const overridden = handleOverrideByDelegation(
|
|
896
|
+
delegationContext.info,
|
|
897
|
+
delegationContext.context,
|
|
898
|
+
overrideHandler
|
|
899
|
+
);
|
|
900
|
+
if (!overridden) {
|
|
901
|
+
return null;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
if (isObjectType(parentType) || isInterfaceType(parentType)) {
|
|
906
|
+
if (!field) {
|
|
907
|
+
return null;
|
|
908
|
+
}
|
|
909
|
+
const args = field.args != null ? field.args : [];
|
|
910
|
+
const argsMap = /* @__PURE__ */ Object.create(null);
|
|
911
|
+
for (const arg of args) {
|
|
912
|
+
argsMap[arg.name] = arg;
|
|
913
|
+
}
|
|
914
|
+
if (node.arguments != null) {
|
|
915
|
+
const newArgs = [];
|
|
916
|
+
for (const arg of node.arguments) {
|
|
917
|
+
if (arg.name.value in argsMap) {
|
|
918
|
+
newArgs.push(arg);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
if (newArgs.length !== node.arguments.length) {
|
|
922
|
+
return {
|
|
923
|
+
...node,
|
|
924
|
+
arguments: newArgs
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
if (isUnionType(parentType) && typeInfo.getType() == null) {
|
|
930
|
+
const possibleTypeNames = [];
|
|
931
|
+
const fieldName = node.name.value;
|
|
932
|
+
for (const memberType of parentType.getTypes()) {
|
|
933
|
+
const memberFields = memberType.getFields();
|
|
934
|
+
const possibleField = memberFields[fieldName];
|
|
935
|
+
if (possibleField != null) {
|
|
936
|
+
const namedType = getNamedType(possibleField.type);
|
|
937
|
+
if (node.selectionSet?.selections?.length && isLeafType(namedType)) {
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
if (!node.selectionSet?.selections?.length && isCompositeType(namedType)) {
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
943
|
+
possibleTypeNames.push(memberType.name);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
if (possibleTypeNames.length > 0) {
|
|
947
|
+
const spreads = possibleTypeNames.map((possibleTypeName) => {
|
|
948
|
+
if (!node.selectionSet?.selections) {
|
|
949
|
+
return {
|
|
950
|
+
kind: Kind.INLINE_FRAGMENT,
|
|
951
|
+
typeCondition: {
|
|
952
|
+
kind: Kind.NAMED_TYPE,
|
|
953
|
+
name: {
|
|
954
|
+
kind: Kind.NAME,
|
|
955
|
+
value: possibleTypeName
|
|
956
|
+
}
|
|
957
|
+
},
|
|
958
|
+
selectionSet: {
|
|
959
|
+
kind: Kind.SELECTION_SET,
|
|
960
|
+
selections: [node]
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
const possibleType = schema.getType(
|
|
965
|
+
possibleTypeName
|
|
966
|
+
);
|
|
967
|
+
const possibleField = possibleType.getFields()[node.name.value];
|
|
968
|
+
if (!possibleField) {
|
|
969
|
+
return void 0;
|
|
970
|
+
}
|
|
971
|
+
const fieldFilteredSelectionSet = filterSelectionSet(
|
|
972
|
+
schema,
|
|
973
|
+
getTypeInfoWithType(schema, possibleField.type),
|
|
974
|
+
validFragments,
|
|
975
|
+
node.selectionSet,
|
|
976
|
+
onOverlappingAliases,
|
|
977
|
+
usedFragments,
|
|
978
|
+
seenNonNullableMap,
|
|
979
|
+
seenNullableMap,
|
|
980
|
+
delegationContext
|
|
981
|
+
);
|
|
982
|
+
if (!fieldFilteredSelectionSet.selections.length) {
|
|
983
|
+
return void 0;
|
|
984
|
+
}
|
|
985
|
+
return {
|
|
986
|
+
kind: Kind.INLINE_FRAGMENT,
|
|
987
|
+
typeCondition: {
|
|
988
|
+
kind: Kind.NAMED_TYPE,
|
|
989
|
+
name: {
|
|
990
|
+
kind: Kind.NAME,
|
|
991
|
+
value: possibleTypeName
|
|
992
|
+
}
|
|
993
|
+
},
|
|
994
|
+
selectionSet: {
|
|
995
|
+
kind: Kind.SELECTION_SET,
|
|
996
|
+
selections: [
|
|
997
|
+
{
|
|
998
|
+
...node,
|
|
999
|
+
selectionSet: fieldFilteredSelectionSet
|
|
1000
|
+
}
|
|
1001
|
+
]
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
});
|
|
1005
|
+
const nonEmptySpreads = spreads.filter(Boolean);
|
|
1006
|
+
if (!nonEmptySpreads.length) {
|
|
1007
|
+
return void 0;
|
|
1008
|
+
}
|
|
1009
|
+
return nonEmptySpreads;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
return void 0;
|
|
1013
|
+
},
|
|
1014
|
+
leave: (node) => {
|
|
1015
|
+
const type = typeInfo.getType();
|
|
1016
|
+
if (type == null) {
|
|
1017
|
+
return null;
|
|
1018
|
+
}
|
|
1019
|
+
const namedType = getNamedType(type);
|
|
1020
|
+
if (schema.getType(namedType.name) == null) {
|
|
1021
|
+
return null;
|
|
1022
|
+
}
|
|
1023
|
+
if (isObjectType(namedType) || isInterfaceType(namedType)) {
|
|
1024
|
+
const selections = node.selectionSet != null ? node.selectionSet.selections : null;
|
|
1025
|
+
if (selections == null || selections.length === 0) {
|
|
1026
|
+
return null;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
return void 0;
|
|
1030
|
+
}
|
|
1031
|
+
},
|
|
1032
|
+
[Kind.FRAGMENT_SPREAD]: {
|
|
1033
|
+
enter: (node) => {
|
|
1034
|
+
if (!(node.name.value in validFragments)) {
|
|
1035
|
+
return null;
|
|
1036
|
+
}
|
|
1037
|
+
const parentType = typeInfo.getParentType();
|
|
1038
|
+
const innerType = validFragments[node.name.value];
|
|
1039
|
+
if (!implementsAbstractType(schema, parentType, innerType)) {
|
|
1040
|
+
return null;
|
|
1041
|
+
}
|
|
1042
|
+
usedFragments.push(node.name.value);
|
|
1043
|
+
return void 0;
|
|
1044
|
+
}
|
|
1045
|
+
},
|
|
1046
|
+
[Kind.SELECTION_SET]: {
|
|
1047
|
+
enter: (node, _key, _parent, _path) => {
|
|
1048
|
+
const parentType = typeInfo.getParentType();
|
|
1049
|
+
const { hasTypeNameField, selections } = filterTypenameFields(
|
|
1050
|
+
node.selections
|
|
1051
|
+
);
|
|
1052
|
+
if (hasTypeNameField || parentType != null && isAbstractType(parentType)) {
|
|
1053
|
+
selections.unshift({
|
|
1054
|
+
kind: Kind.FIELD,
|
|
1055
|
+
name: {
|
|
1056
|
+
kind: Kind.NAME,
|
|
1057
|
+
value: "__typename"
|
|
1058
|
+
}
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
return {
|
|
1062
|
+
...node,
|
|
1063
|
+
selections
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
},
|
|
1067
|
+
[Kind.INLINE_FRAGMENT]: {
|
|
1068
|
+
enter: (node) => {
|
|
1069
|
+
if (node.typeCondition != null) {
|
|
1070
|
+
const parentType = typeInfo.getParentType();
|
|
1071
|
+
const innerType = schema.getType(node.typeCondition.name.value);
|
|
1072
|
+
if (isUnionType(parentType) && parentType.getTypes().some((t) => t.name === innerType?.name)) {
|
|
1073
|
+
return node;
|
|
1074
|
+
}
|
|
1075
|
+
if (!implementsAbstractType(schema, parentType, innerType)) {
|
|
1076
|
+
return null;
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
return void 0;
|
|
1080
|
+
},
|
|
1081
|
+
leave: (selection, _key, parent) => {
|
|
1082
|
+
if (!selection.selectionSet?.selections?.length) {
|
|
1083
|
+
return null;
|
|
1084
|
+
}
|
|
1085
|
+
if (Array.isArray(parent)) {
|
|
1086
|
+
const selectionTypeName = selection.typeCondition?.name.value;
|
|
1087
|
+
if (selectionTypeName) {
|
|
1088
|
+
const selectionType = schema.getType(selectionTypeName);
|
|
1089
|
+
if (selectionType && "getFields" in selectionType) {
|
|
1090
|
+
const selectionTypeFields = selectionType.getFields();
|
|
1091
|
+
let seenNonNullable = seenNonNullableMap.get(parent);
|
|
1092
|
+
if (!seenNonNullable) {
|
|
1093
|
+
seenNonNullable = /* @__PURE__ */ new Set();
|
|
1094
|
+
seenNonNullableMap.set(parent, seenNonNullable);
|
|
1095
|
+
}
|
|
1096
|
+
let seenNullable = seenNullableMap.get(parent);
|
|
1097
|
+
if (!seenNullable) {
|
|
1098
|
+
seenNullable = /* @__PURE__ */ new Set();
|
|
1099
|
+
seenNullableMap.set(parent, seenNullable);
|
|
1100
|
+
}
|
|
1101
|
+
selection = {
|
|
1102
|
+
...selection,
|
|
1103
|
+
selectionSet: {
|
|
1104
|
+
...selection.selectionSet,
|
|
1105
|
+
selections: selection.selectionSet.selections.map(
|
|
1106
|
+
(subSelection) => {
|
|
1107
|
+
if (subSelection.kind === Kind.FIELD) {
|
|
1108
|
+
const fieldName = subSelection.name.value;
|
|
1109
|
+
if (!subSelection.alias) {
|
|
1110
|
+
const field = selectionTypeFields[fieldName];
|
|
1111
|
+
if (field) {
|
|
1112
|
+
let currentNullable;
|
|
1113
|
+
if (isNullableType(field.type)) {
|
|
1114
|
+
seenNullable.add(fieldName);
|
|
1115
|
+
currentNullable = true;
|
|
1116
|
+
} else {
|
|
1117
|
+
seenNonNullable.add(fieldName);
|
|
1118
|
+
currentNullable = false;
|
|
1119
|
+
}
|
|
1120
|
+
if (seenNullable.has(fieldName) && seenNonNullable.has(fieldName)) {
|
|
1121
|
+
onOverlappingAliases();
|
|
1122
|
+
return {
|
|
1123
|
+
...subSelection,
|
|
1124
|
+
alias: {
|
|
1125
|
+
kind: Kind.NAME,
|
|
1126
|
+
value: currentNullable ? `_nullable_${fieldName}` : `_nonNullable_${fieldName}`
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
return subSelection;
|
|
1134
|
+
}
|
|
1135
|
+
)
|
|
1136
|
+
}
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
const { selections } = filterTypenameFields(
|
|
1142
|
+
selection.selectionSet.selections
|
|
1143
|
+
);
|
|
1144
|
+
if (selections.length === 0) {
|
|
1145
|
+
return null;
|
|
1146
|
+
}
|
|
1147
|
+
return {
|
|
1148
|
+
...selection,
|
|
1149
|
+
selectionSet: {
|
|
1150
|
+
...selection.selectionSet,
|
|
1151
|
+
selections
|
|
1152
|
+
},
|
|
1153
|
+
// @defer is not available for the communication between the gw and subgraph
|
|
1154
|
+
directives: selection.directives?.filter?.(
|
|
1155
|
+
(directive) => directive.name.value !== "defer"
|
|
1156
|
+
)
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
}),
|
|
1161
|
+
// visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
1162
|
+
// empty keys cannot be removed only because of typescript errors
|
|
1163
|
+
// will hopefully be fixed in future version of graphql-js to be optional
|
|
1164
|
+
filteredSelectionSetVisitorKeys
|
|
1165
|
+
);
|
|
1166
|
+
}
|
|
1167
|
+
function union(...arrays) {
|
|
1168
|
+
const cache = /* @__PURE__ */ Object.create(null);
|
|
1169
|
+
const result = [];
|
|
1170
|
+
for (const array of arrays) {
|
|
1171
|
+
for (const item of array) {
|
|
1172
|
+
if (!(item in cache)) {
|
|
1173
|
+
cache[item] = true;
|
|
1174
|
+
result.push(item);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
return result;
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
function prepareGatewayDocument(originalDocument, delegationContext) {
|
|
1182
|
+
const transformedSchema = delegationContext.transformedSchema;
|
|
1183
|
+
const returnType = delegationContext.returnType;
|
|
1184
|
+
const infoSchema = delegationContext.info?.schema;
|
|
1185
|
+
const wrappedConcreteTypesDocument = wrapConcreteTypes(
|
|
1186
|
+
returnType,
|
|
1187
|
+
transformedSchema,
|
|
1188
|
+
originalDocument
|
|
1189
|
+
);
|
|
1190
|
+
if (infoSchema == null) {
|
|
1191
|
+
return wrappedConcreteTypesDocument;
|
|
1192
|
+
}
|
|
1193
|
+
const visitedSelections = /* @__PURE__ */ new WeakSet();
|
|
1194
|
+
const {
|
|
1195
|
+
possibleTypesMap,
|
|
1196
|
+
reversePossibleTypesMap: reversePossibleTypesMap2,
|
|
1197
|
+
interfaceExtensionsMap,
|
|
1198
|
+
fieldNodesByType,
|
|
1199
|
+
fieldNodesByField,
|
|
1200
|
+
dynamicSelectionSetsByField
|
|
1201
|
+
} = getSchemaMetaData(infoSchema, transformedSchema);
|
|
1202
|
+
const { operations, fragments, fragmentNames } = getDocumentMetadata(
|
|
1203
|
+
wrappedConcreteTypesDocument
|
|
1204
|
+
);
|
|
1205
|
+
const { expandedFragments, fragmentReplacements } = getExpandedFragments(
|
|
1206
|
+
fragments,
|
|
1207
|
+
fragmentNames,
|
|
1208
|
+
possibleTypesMap
|
|
1209
|
+
);
|
|
1210
|
+
const typeInfo = getTypeInfo(transformedSchema);
|
|
1211
|
+
const expandedDocument = {
|
|
1212
|
+
kind: Kind.DOCUMENT,
|
|
1213
|
+
definitions: [...operations, ...fragments, ...expandedFragments]
|
|
1214
|
+
};
|
|
1215
|
+
const fragmentMap = /* @__PURE__ */ Object.create(null);
|
|
1216
|
+
for (const fragment of expandedDocument.definitions) {
|
|
1217
|
+
if (fragment.kind === Kind.FRAGMENT_DEFINITION) {
|
|
1218
|
+
fragmentMap[fragment.name.value] = fragment;
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
const visitorKeyMap = {
|
|
1222
|
+
Document: ["definitions"],
|
|
1223
|
+
OperationDefinition: ["selectionSet"],
|
|
1224
|
+
SelectionSet: ["selections"],
|
|
1225
|
+
Field: ["selectionSet"],
|
|
1226
|
+
InlineFragment: ["selectionSet"],
|
|
1227
|
+
FragmentDefinition: ["selectionSet"]
|
|
1228
|
+
};
|
|
1229
|
+
return visit(
|
|
1230
|
+
expandedDocument,
|
|
1231
|
+
visitWithTypeInfo(typeInfo, {
|
|
1232
|
+
[Kind.SELECTION_SET]: (node) => visitSelectionSet(
|
|
1233
|
+
node,
|
|
1234
|
+
fragmentReplacements,
|
|
1235
|
+
transformedSchema,
|
|
1236
|
+
typeInfo,
|
|
1237
|
+
possibleTypesMap,
|
|
1238
|
+
reversePossibleTypesMap2,
|
|
1239
|
+
interfaceExtensionsMap,
|
|
1240
|
+
fieldNodesByType,
|
|
1241
|
+
fieldNodesByField,
|
|
1242
|
+
dynamicSelectionSetsByField,
|
|
1243
|
+
infoSchema,
|
|
1244
|
+
visitedSelections,
|
|
1245
|
+
fragmentMap,
|
|
1246
|
+
delegationContext
|
|
1247
|
+
)
|
|
1248
|
+
}),
|
|
1249
|
+
// visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
1250
|
+
// empty keys cannot be removed only because of typescript errors
|
|
1251
|
+
// will hopefully be fixed in future version of graphql-js to be optional
|
|
1252
|
+
visitorKeyMap
|
|
1253
|
+
);
|
|
1254
|
+
}
|
|
1255
|
+
const getExtraPossibleTypesFn = memoize2(function getExtraPossibleTypes(transformedSchema, infoSchema) {
|
|
1256
|
+
const extraPossiblesTypesMap = /* @__PURE__ */ new Map();
|
|
1257
|
+
return function getExtraPossibleTypes2(typeName) {
|
|
1258
|
+
let extraTypesForSubschema = extraPossiblesTypesMap.get(typeName);
|
|
1259
|
+
if (!extraTypesForSubschema) {
|
|
1260
|
+
extraTypesForSubschema = /* @__PURE__ */ new Set();
|
|
1261
|
+
const gatewayType = infoSchema.getType(typeName);
|
|
1262
|
+
const subschemaType = transformedSchema.getType(typeName);
|
|
1263
|
+
if (isAbstractType(gatewayType) && isAbstractType(subschemaType)) {
|
|
1264
|
+
const possibleTypes = infoSchema.getPossibleTypes(gatewayType);
|
|
1265
|
+
const possibleTypesInSubschema = transformedSchema.getPossibleTypes(subschemaType);
|
|
1266
|
+
for (const possibleType of possibleTypes) {
|
|
1267
|
+
const possibleTypeInSubschema = transformedSchema.getType(
|
|
1268
|
+
possibleType.name
|
|
1269
|
+
);
|
|
1270
|
+
if (!possibleTypeInSubschema) {
|
|
1271
|
+
continue;
|
|
1272
|
+
}
|
|
1273
|
+
if (possibleTypeInSubschema && possibleTypesInSubschema.some((t) => t.name === possibleType.name)) {
|
|
1274
|
+
continue;
|
|
1275
|
+
}
|
|
1276
|
+
extraTypesForSubschema.add(possibleType.name);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
extraPossiblesTypesMap.set(typeName, extraTypesForSubschema);
|
|
1280
|
+
}
|
|
1281
|
+
return extraTypesForSubschema;
|
|
1282
|
+
};
|
|
1283
|
+
});
|
|
1284
|
+
function visitSelectionSet(node, fragmentReplacements, transformedSchema, typeInfo, possibleTypesMap, reversePossibleTypesMap2, interfaceExtensionsMap, fieldNodesByType, fieldNodesByField, dynamicSelectionSetsByField, infoSchema, visitedSelections, fragmentMap, delegationContext) {
|
|
1285
|
+
const newSelections = /* @__PURE__ */ new Set();
|
|
1286
|
+
const maybeType = typeInfo.getParentType();
|
|
1287
|
+
if (maybeType != null) {
|
|
1288
|
+
const parentType = getNamedType(maybeType);
|
|
1289
|
+
if (isSelectionSetSatisfiedBySchema(
|
|
1290
|
+
transformedSchema,
|
|
1291
|
+
parentType,
|
|
1292
|
+
node,
|
|
1293
|
+
fragmentMap,
|
|
1294
|
+
infoSchema,
|
|
1295
|
+
delegationContext
|
|
1296
|
+
)) {
|
|
1297
|
+
if (isAbstractType(delegationContext.returnType)) {
|
|
1298
|
+
addSelectionNodeToSelections(newSelections, {
|
|
1299
|
+
kind: Kind.FIELD,
|
|
1300
|
+
name: {
|
|
1301
|
+
kind: Kind.NAME,
|
|
1302
|
+
value: "__typename"
|
|
1303
|
+
}
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
for (const selection of node.selections) {
|
|
1307
|
+
addSelectionNodeToSelections(newSelections, selection);
|
|
1308
|
+
}
|
|
1309
|
+
return {
|
|
1310
|
+
...node,
|
|
1311
|
+
selections: Array.from(newSelections)
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
const parentTypeName = parentType.name;
|
|
1315
|
+
const fieldNodes = fieldNodesByType[parentTypeName];
|
|
1316
|
+
if (fieldNodes) {
|
|
1317
|
+
for (const fieldNode of fieldNodes) {
|
|
1318
|
+
addSelectionNodeToSelections(newSelections, fieldNode);
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
const interfaceExtensions = interfaceExtensionsMap[parentType.name];
|
|
1322
|
+
const interfaceExtensionFields = [];
|
|
1323
|
+
for (const selection of node.selections) {
|
|
1324
|
+
if (selection.kind === Kind.INLINE_FRAGMENT) {
|
|
1325
|
+
if (selection.typeCondition != null) {
|
|
1326
|
+
if (!visitedSelections.has(selection)) {
|
|
1327
|
+
visitedSelections.add(selection);
|
|
1328
|
+
const typeName = selection.typeCondition.name.value;
|
|
1329
|
+
const getExtraPossibleTypes2 = getExtraPossibleTypesFn(
|
|
1330
|
+
transformedSchema,
|
|
1331
|
+
infoSchema
|
|
1332
|
+
);
|
|
1333
|
+
const extraPossibleTypes = getExtraPossibleTypes2(typeName);
|
|
1334
|
+
for (const extraPossibleTypeName of extraPossibleTypes) {
|
|
1335
|
+
addSelectionNodeToSelections(newSelections, {
|
|
1336
|
+
...selection,
|
|
1337
|
+
typeCondition: {
|
|
1338
|
+
kind: Kind.NAMED_TYPE,
|
|
1339
|
+
name: {
|
|
1340
|
+
kind: Kind.NAME,
|
|
1341
|
+
value: extraPossibleTypeName
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
const typeInSubschema = transformedSchema.getType(typeName);
|
|
1347
|
+
if (isObjectType(typeInSubschema) || isInterfaceType(typeInSubschema)) {
|
|
1348
|
+
const fieldMap = typeInSubschema.getFields();
|
|
1349
|
+
for (const subSelection of selection.selectionSet.selections) {
|
|
1350
|
+
if (subSelection.kind === Kind.FIELD) {
|
|
1351
|
+
const fieldName = subSelection.name.value;
|
|
1352
|
+
const field = fieldMap[fieldName];
|
|
1353
|
+
if (!field) {
|
|
1354
|
+
addSelectionNodeToSelections(newSelections, subSelection);
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
} else if (!typeInSubschema) {
|
|
1359
|
+
for (const subSelection of selection.selectionSet.selections) {
|
|
1360
|
+
addSelectionNodeToSelections(newSelections, subSelection);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
const possibleTypes = possibleTypesMap[selection.typeCondition.name.value];
|
|
1365
|
+
if (possibleTypes == null) {
|
|
1366
|
+
const fieldNodesForTypeName = fieldNodesByField[parentTypeName]?.["__typename"];
|
|
1367
|
+
if (fieldNodesForTypeName) {
|
|
1368
|
+
for (const fieldNode of fieldNodesForTypeName) {
|
|
1369
|
+
addSelectionNodeToSelections(newSelections, fieldNode);
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
addSelectionNodeToSelections(newSelections, selection);
|
|
1373
|
+
continue;
|
|
1374
|
+
}
|
|
1375
|
+
for (const possibleTypeName of possibleTypes) {
|
|
1376
|
+
const maybePossibleType = transformedSchema.getType(possibleTypeName);
|
|
1377
|
+
if (maybePossibleType != null && implementsAbstractType(
|
|
1378
|
+
transformedSchema,
|
|
1379
|
+
parentType,
|
|
1380
|
+
maybePossibleType
|
|
1381
|
+
)) {
|
|
1382
|
+
addSelectionNodeToSelections(
|
|
1383
|
+
newSelections,
|
|
1384
|
+
generateInlineFragment(
|
|
1385
|
+
possibleTypeName,
|
|
1386
|
+
selection.selectionSet
|
|
1387
|
+
)
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
if (possibleTypes.length === 0) {
|
|
1392
|
+
addSelectionNodeToSelections(newSelections, selection);
|
|
1393
|
+
}
|
|
1394
|
+
} else {
|
|
1395
|
+
addSelectionNodeToSelections(newSelections, selection);
|
|
1396
|
+
}
|
|
1397
|
+
} else if (selection.kind === Kind.FRAGMENT_SPREAD) {
|
|
1398
|
+
const fragmentName = selection.name.value;
|
|
1399
|
+
if (!fragmentReplacements[fragmentName]) {
|
|
1400
|
+
addSelectionNodeToSelections(newSelections, selection);
|
|
1401
|
+
continue;
|
|
1402
|
+
}
|
|
1403
|
+
for (const replacement of fragmentReplacements[fragmentName]) {
|
|
1404
|
+
const typeName = replacement.typeName;
|
|
1405
|
+
const maybeReplacementType = transformedSchema.getType(typeName);
|
|
1406
|
+
if (maybeReplacementType != null && implementsAbstractType(transformedSchema, parentType, maybeType)) {
|
|
1407
|
+
addSelectionNodeToSelections(newSelections, {
|
|
1408
|
+
kind: Kind.FRAGMENT_SPREAD,
|
|
1409
|
+
name: {
|
|
1410
|
+
kind: Kind.NAME,
|
|
1411
|
+
value: replacement.fragmentName
|
|
1412
|
+
}
|
|
1413
|
+
});
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
} else {
|
|
1417
|
+
const fieldName = selection.name.value;
|
|
1418
|
+
if (interfaceExtensions?.[fieldName]) {
|
|
1419
|
+
interfaceExtensionFields.push(selection);
|
|
1420
|
+
} else {
|
|
1421
|
+
addSelectionNodeToSelections(newSelections, selection);
|
|
1422
|
+
}
|
|
1423
|
+
if (isAbstractType(parentType)) {
|
|
1424
|
+
const fieldNodesForTypeName = fieldNodesByField[parentTypeName]?.["__typename"];
|
|
1425
|
+
if (fieldNodesForTypeName) {
|
|
1426
|
+
for (const fieldNode of fieldNodesForTypeName) {
|
|
1427
|
+
addSelectionNodeToSelections(newSelections, fieldNode);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
const fieldNodesMapForType = fieldNodesByField[parentTypeName];
|
|
1432
|
+
if (fieldNodesMapForType) {
|
|
1433
|
+
addDependenciesNestedly(
|
|
1434
|
+
selection,
|
|
1435
|
+
/* @__PURE__ */ new Set(),
|
|
1436
|
+
fieldNodesMapForType,
|
|
1437
|
+
newSelections
|
|
1438
|
+
);
|
|
1439
|
+
}
|
|
1440
|
+
const dynamicSelectionSets = dynamicSelectionSetsByField[parentTypeName]?.[fieldName];
|
|
1441
|
+
if (dynamicSelectionSets != null) {
|
|
1442
|
+
for (const selectionSetFn of dynamicSelectionSets) {
|
|
1443
|
+
const selectionSet = selectionSetFn(selection);
|
|
1444
|
+
if (selectionSet != null) {
|
|
1445
|
+
for (const selection2 of selectionSet.selections) {
|
|
1446
|
+
addSelectionNodeToSelections(newSelections, selection2);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
if (reversePossibleTypesMap2[parentType.name]) {
|
|
1454
|
+
addSelectionNodeToSelections(newSelections, {
|
|
1455
|
+
kind: Kind.FIELD,
|
|
1456
|
+
name: {
|
|
1457
|
+
kind: Kind.NAME,
|
|
1458
|
+
value: "__typename"
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
if (interfaceExtensionFields.length) {
|
|
1463
|
+
const possibleTypes = possibleTypesMap[parentType.name];
|
|
1464
|
+
if (possibleTypes != null) {
|
|
1465
|
+
for (const possibleType of possibleTypes) {
|
|
1466
|
+
addSelectionNodeToSelections(
|
|
1467
|
+
newSelections,
|
|
1468
|
+
generateInlineFragment(possibleType, {
|
|
1469
|
+
kind: Kind.SELECTION_SET,
|
|
1470
|
+
selections: interfaceExtensionFields
|
|
1471
|
+
})
|
|
1472
|
+
);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
return {
|
|
1477
|
+
...node,
|
|
1478
|
+
selections: Array.from(newSelections)
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
return node;
|
|
1482
|
+
}
|
|
1483
|
+
function isFieldNodeSatisfiedBySelections(fieldNode, existing) {
|
|
1484
|
+
for (const existingSelection of existing) {
|
|
1485
|
+
if (existingSelection.kind === Kind.FIELD && existingSelection.name.value === fieldNode.name.value && existingSelection.alias?.value === fieldNode.alias?.value) {
|
|
1486
|
+
if (fieldNode.selectionSet && !existingSelection.selectionSet) {
|
|
1487
|
+
return false;
|
|
1488
|
+
}
|
|
1489
|
+
if (fieldNode.selectionSet && existingSelection.selectionSet) {
|
|
1490
|
+
const satisfied = isSelectionSetSatisfied({
|
|
1491
|
+
incoming: fieldNode.selectionSet,
|
|
1492
|
+
existing: existingSelection.selectionSet.selections
|
|
1493
|
+
});
|
|
1494
|
+
if (!satisfied) {
|
|
1495
|
+
return false;
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
return true;
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
return false;
|
|
1502
|
+
}
|
|
1503
|
+
function isSelectionSetSatisfiedBySchema(schema, type, selectionSet, fragmentsMap, infoSchema, delegationContext) {
|
|
1504
|
+
const namedType = getNamedType(type);
|
|
1505
|
+
if (isLeafType(namedType)) {
|
|
1506
|
+
return true;
|
|
1507
|
+
}
|
|
1508
|
+
const fields = isObjectType(namedType) || isInterfaceType(namedType) ? namedType.getFields() : null;
|
|
1509
|
+
for (const selection of selectionSet.selections) {
|
|
1510
|
+
if (selection.kind === Kind.FIELD) {
|
|
1511
|
+
if (isAbstractType(namedType)) {
|
|
1512
|
+
return false;
|
|
1513
|
+
}
|
|
1514
|
+
const fieldName = selection.name.value;
|
|
1515
|
+
if (fieldName === "__typename") {
|
|
1516
|
+
continue;
|
|
1517
|
+
}
|
|
1518
|
+
if (fields) {
|
|
1519
|
+
const field = fields[fieldName];
|
|
1520
|
+
if (!field) {
|
|
1521
|
+
return false;
|
|
1522
|
+
}
|
|
1523
|
+
const typeInInfoSchema = infoSchema.getType(namedType.name);
|
|
1524
|
+
const fieldInInfoSchema = typeInInfoSchema?.getFields?.()?.[fieldName];
|
|
1525
|
+
const resolverInInfoSchema = fieldInInfoSchema?.resolve;
|
|
1526
|
+
if (resolverInInfoSchema != null && resolverInInfoSchema.name !== "defaultMergedResolver" && resolverInInfoSchema.name !== "defaultFieldResolver") {
|
|
1527
|
+
return false;
|
|
1528
|
+
}
|
|
1529
|
+
if (delegationContext.info) {
|
|
1530
|
+
const overrideHandler = delegationContext.subschemaConfig?.merge?.[namedType.name]?.fields?.[field.name]?.override;
|
|
1531
|
+
if (overrideHandler != null) {
|
|
1532
|
+
const overridden = handleOverrideByDelegation(
|
|
1533
|
+
delegationContext.info,
|
|
1534
|
+
delegationContext.context,
|
|
1535
|
+
overrideHandler
|
|
1536
|
+
);
|
|
1537
|
+
if (!overridden) {
|
|
1538
|
+
return false;
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
if (selection.selectionSet) {
|
|
1543
|
+
const fieldType = getNamedType(field.type);
|
|
1544
|
+
const satisfied = isSelectionSetSatisfiedBySchema(
|
|
1545
|
+
schema,
|
|
1546
|
+
fieldType,
|
|
1547
|
+
selection.selectionSet,
|
|
1548
|
+
fragmentsMap,
|
|
1549
|
+
infoSchema,
|
|
1550
|
+
delegationContext
|
|
1551
|
+
);
|
|
1552
|
+
if (!satisfied) {
|
|
1553
|
+
return false;
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
} else {
|
|
1557
|
+
return false;
|
|
1558
|
+
}
|
|
1559
|
+
} else if (selection.kind === Kind.INLINE_FRAGMENT) {
|
|
1560
|
+
if (selection.typeCondition) {
|
|
1561
|
+
const typeConditionName = selection.typeCondition.name.value;
|
|
1562
|
+
const typeCondition = schema.getType(typeConditionName);
|
|
1563
|
+
if (!typeCondition) {
|
|
1564
|
+
return false;
|
|
1565
|
+
}
|
|
1566
|
+
const satisfied = isSelectionSetSatisfiedBySchema(
|
|
1567
|
+
schema,
|
|
1568
|
+
typeCondition,
|
|
1569
|
+
selection.selectionSet,
|
|
1570
|
+
fragmentsMap,
|
|
1571
|
+
infoSchema,
|
|
1572
|
+
delegationContext
|
|
1573
|
+
);
|
|
1574
|
+
if (!satisfied) {
|
|
1575
|
+
return false;
|
|
1576
|
+
}
|
|
1577
|
+
} else {
|
|
1578
|
+
const satisfied = isSelectionSetSatisfiedBySchema(
|
|
1579
|
+
schema,
|
|
1580
|
+
type,
|
|
1581
|
+
selection.selectionSet,
|
|
1582
|
+
fragmentsMap,
|
|
1583
|
+
infoSchema,
|
|
1584
|
+
delegationContext
|
|
1585
|
+
);
|
|
1586
|
+
if (!satisfied) {
|
|
1587
|
+
return false;
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
} else if (selection.kind === Kind.FRAGMENT_SPREAD) {
|
|
1591
|
+
const fragmentName = selection.name.value;
|
|
1592
|
+
const fragment = fragmentsMap[fragmentName];
|
|
1593
|
+
if (!fragment) {
|
|
1594
|
+
return false;
|
|
1595
|
+
}
|
|
1596
|
+
const typeConditionName = fragment.typeCondition.name.value;
|
|
1597
|
+
const typeCondition = schema.getType(typeConditionName);
|
|
1598
|
+
if (!typeCondition) {
|
|
1599
|
+
return false;
|
|
1600
|
+
}
|
|
1601
|
+
const satisfied = isSelectionSetSatisfiedBySchema(
|
|
1602
|
+
schema,
|
|
1603
|
+
typeCondition,
|
|
1604
|
+
fragment.selectionSet,
|
|
1605
|
+
fragmentsMap,
|
|
1606
|
+
infoSchema,
|
|
1607
|
+
delegationContext
|
|
1608
|
+
);
|
|
1609
|
+
if (!satisfied) {
|
|
1610
|
+
return false;
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
return true;
|
|
1615
|
+
}
|
|
1616
|
+
function isSelectionSetSatisfied({
|
|
1617
|
+
incoming,
|
|
1618
|
+
existing
|
|
1619
|
+
}) {
|
|
1620
|
+
for (const incomingSelection of incoming.selections) {
|
|
1621
|
+
if (incomingSelection.kind === Kind.FIELD) {
|
|
1622
|
+
const existingField = existing.find((selection) => {
|
|
1623
|
+
return selection.kind === Kind.FIELD && selection.name.value === incomingSelection.name.value && selection.alias?.value === incomingSelection.alias?.value;
|
|
1624
|
+
});
|
|
1625
|
+
if (!existingField) {
|
|
1626
|
+
return false;
|
|
1627
|
+
}
|
|
1628
|
+
if (incomingSelection.selectionSet && !existingField.selectionSet) {
|
|
1629
|
+
return false;
|
|
1630
|
+
}
|
|
1631
|
+
if (incomingSelection.selectionSet && existingField.selectionSet) {
|
|
1632
|
+
const satisfied = isSelectionSetSatisfied({
|
|
1633
|
+
incoming: incomingSelection.selectionSet,
|
|
1634
|
+
existing: existingField.selectionSet.selections
|
|
1635
|
+
});
|
|
1636
|
+
if (!satisfied) {
|
|
1637
|
+
return false;
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
} else {
|
|
1641
|
+
return false;
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
return true;
|
|
1645
|
+
}
|
|
1646
|
+
function addSelectionNodeToSelections(selections, selectionNode) {
|
|
1647
|
+
if (selectionNode.kind === Kind.FIELD && isFieldNodeSatisfiedBySelections(selectionNode, selections)) {
|
|
1648
|
+
return;
|
|
1649
|
+
}
|
|
1650
|
+
selections.add(selectionNode);
|
|
1651
|
+
}
|
|
1652
|
+
function addDependenciesNestedly(fieldNode, seenFieldNames, fieldNodesByField, newSelections) {
|
|
1653
|
+
if (seenFieldNames.has(fieldNode.name.value)) {
|
|
1654
|
+
return;
|
|
1655
|
+
}
|
|
1656
|
+
seenFieldNames.add(fieldNode.name.value);
|
|
1657
|
+
const fieldNodes = fieldNodesByField[fieldNode.name.value];
|
|
1658
|
+
if (fieldNodes != null) {
|
|
1659
|
+
for (const nestedFieldNode of fieldNodes) {
|
|
1660
|
+
addSelectionNodeToSelections(newSelections, nestedFieldNode);
|
|
1661
|
+
addDependenciesNestedly(
|
|
1662
|
+
nestedFieldNode,
|
|
1663
|
+
seenFieldNames,
|
|
1664
|
+
fieldNodesByField,
|
|
1665
|
+
newSelections
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
function generateInlineFragment(typeName, selectionSet) {
|
|
1671
|
+
return {
|
|
1672
|
+
kind: Kind.INLINE_FRAGMENT,
|
|
1673
|
+
typeCondition: {
|
|
1674
|
+
kind: Kind.NAMED_TYPE,
|
|
1675
|
+
name: {
|
|
1676
|
+
kind: Kind.NAME,
|
|
1677
|
+
value: typeName
|
|
1678
|
+
}
|
|
1679
|
+
},
|
|
1680
|
+
selectionSet
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
const getSchemaMetaData = memoize2(
|
|
1684
|
+
(sourceSchema, targetSchema) => {
|
|
1685
|
+
const typeMap = sourceSchema.getTypeMap();
|
|
1686
|
+
const targetTypeMap = targetSchema.getTypeMap();
|
|
1687
|
+
const possibleTypesMap = /* @__PURE__ */ Object.create(null);
|
|
1688
|
+
const interfaceExtensionsMap = /* @__PURE__ */ Object.create(null);
|
|
1689
|
+
for (const typeName in typeMap) {
|
|
1690
|
+
const type = typeMap[typeName];
|
|
1691
|
+
if (isAbstractType(type)) {
|
|
1692
|
+
const targetType = targetTypeMap[typeName];
|
|
1693
|
+
if (isInterfaceType(type) && isInterfaceType(targetType)) {
|
|
1694
|
+
const targetTypeFields = targetType.getFields();
|
|
1695
|
+
const sourceTypeFields = type.getFields();
|
|
1696
|
+
const extensionFields = /* @__PURE__ */ Object.create(null);
|
|
1697
|
+
let isExtensionFieldsEmpty = true;
|
|
1698
|
+
for (const fieldName in sourceTypeFields) {
|
|
1699
|
+
if (!targetTypeFields[fieldName]) {
|
|
1700
|
+
extensionFields[fieldName] = true;
|
|
1701
|
+
isExtensionFieldsEmpty = false;
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
if (!isExtensionFieldsEmpty) {
|
|
1705
|
+
interfaceExtensionsMap[typeName] = extensionFields;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
if (interfaceExtensionsMap[typeName] || !isAbstractType(targetType)) {
|
|
1709
|
+
const implementations = sourceSchema.getPossibleTypes(type);
|
|
1710
|
+
possibleTypesMap[typeName] = [];
|
|
1711
|
+
for (const impl of implementations) {
|
|
1712
|
+
if (targetTypeMap[impl.name]) {
|
|
1713
|
+
possibleTypesMap[typeName].push(impl.name);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
const stitchingInfo = sourceSchema.extensions?.["stitchingInfo"];
|
|
1720
|
+
return {
|
|
1721
|
+
possibleTypesMap,
|
|
1722
|
+
reversePossibleTypesMap: reversePossibleTypesMap(possibleTypesMap),
|
|
1723
|
+
interfaceExtensionsMap,
|
|
1724
|
+
fieldNodesByType: stitchingInfo?.fieldNodesByType ?? {},
|
|
1725
|
+
fieldNodesByField: stitchingInfo?.fieldNodesByField ?? {},
|
|
1726
|
+
dynamicSelectionSetsByField: stitchingInfo?.dynamicSelectionSetsByField ?? {}
|
|
1727
|
+
};
|
|
1728
|
+
}
|
|
1729
|
+
);
|
|
1730
|
+
function reversePossibleTypesMap(possibleTypesMap) {
|
|
1731
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
1732
|
+
for (const typeName in possibleTypesMap) {
|
|
1733
|
+
const toTypeNames = possibleTypesMap[typeName];
|
|
1734
|
+
if (toTypeNames) {
|
|
1735
|
+
for (const toTypeName of toTypeNames) {
|
|
1736
|
+
if (!result[toTypeName]) {
|
|
1737
|
+
result[toTypeName] = [];
|
|
1738
|
+
}
|
|
1739
|
+
result[toTypeName].push(typeName);
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
return result;
|
|
1744
|
+
}
|
|
1745
|
+
function getExpandedFragments(fragments, fragmentNames, possibleTypesMap) {
|
|
1746
|
+
let fragmentCounter = 0;
|
|
1747
|
+
function generateFragmentName(typeName) {
|
|
1748
|
+
let fragmentName;
|
|
1749
|
+
do {
|
|
1750
|
+
fragmentName = `_${typeName}_Fragment${fragmentCounter.toString()}`;
|
|
1751
|
+
fragmentCounter++;
|
|
1752
|
+
} while (fragmentNames.has(fragmentName));
|
|
1753
|
+
return fragmentName;
|
|
1754
|
+
}
|
|
1755
|
+
const expandedFragments = [];
|
|
1756
|
+
const fragmentReplacements = /* @__PURE__ */ Object.create(null);
|
|
1757
|
+
for (const fragment of fragments) {
|
|
1758
|
+
const possibleTypes = possibleTypesMap[fragment.typeCondition.name.value];
|
|
1759
|
+
if (possibleTypes != null) {
|
|
1760
|
+
const fragmentName = fragment.name.value;
|
|
1761
|
+
fragmentReplacements[fragmentName] = [];
|
|
1762
|
+
for (const possibleTypeName of possibleTypes) {
|
|
1763
|
+
const name = generateFragmentName(possibleTypeName);
|
|
1764
|
+
fragmentNames.add(name);
|
|
1765
|
+
expandedFragments.push({
|
|
1766
|
+
kind: Kind.FRAGMENT_DEFINITION,
|
|
1767
|
+
name: {
|
|
1768
|
+
kind: Kind.NAME,
|
|
1769
|
+
value: name
|
|
1770
|
+
},
|
|
1771
|
+
typeCondition: {
|
|
1772
|
+
kind: Kind.NAMED_TYPE,
|
|
1773
|
+
name: {
|
|
1774
|
+
kind: Kind.NAME,
|
|
1775
|
+
value: possibleTypeName
|
|
1776
|
+
}
|
|
1777
|
+
},
|
|
1778
|
+
selectionSet: fragment.selectionSet
|
|
1779
|
+
});
|
|
1780
|
+
fragmentReplacements[fragmentName].push({
|
|
1781
|
+
fragmentName: name,
|
|
1782
|
+
typeName: possibleTypeName
|
|
1783
|
+
});
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
return {
|
|
1788
|
+
expandedFragments,
|
|
1789
|
+
fragmentReplacements
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
function wrapConcreteTypes(returnType, targetSchema, document) {
|
|
1793
|
+
const namedType = getNamedType(returnType);
|
|
1794
|
+
if (isLeafType(namedType)) {
|
|
1795
|
+
return document;
|
|
1796
|
+
}
|
|
1797
|
+
let possibleTypes = isAbstractType(
|
|
1798
|
+
namedType
|
|
1799
|
+
) ? targetSchema.getPossibleTypes(namedType) : [namedType];
|
|
1800
|
+
if (possibleTypes.length === 0) {
|
|
1801
|
+
possibleTypes = [namedType];
|
|
1802
|
+
}
|
|
1803
|
+
const rootTypeNames = getRootTypeNames(targetSchema);
|
|
1804
|
+
const typeInfo = getTypeInfo(targetSchema);
|
|
1805
|
+
const visitorKeys = {
|
|
1806
|
+
Document: ["definitions"],
|
|
1807
|
+
OperationDefinition: ["selectionSet"],
|
|
1808
|
+
SelectionSet: ["selections"],
|
|
1809
|
+
InlineFragment: ["selectionSet"],
|
|
1810
|
+
FragmentDefinition: ["selectionSet"]
|
|
1811
|
+
};
|
|
1812
|
+
return visit(
|
|
1813
|
+
document,
|
|
1814
|
+
visitWithTypeInfo(typeInfo, {
|
|
1815
|
+
[Kind.FRAGMENT_DEFINITION]: (node) => {
|
|
1816
|
+
const typeName = node.typeCondition.name.value;
|
|
1817
|
+
if (!rootTypeNames.has(typeName)) {
|
|
1818
|
+
return false;
|
|
1819
|
+
}
|
|
1820
|
+
return void 0;
|
|
1821
|
+
},
|
|
1822
|
+
[Kind.FIELD]: (node) => {
|
|
1823
|
+
const fieldType = typeInfo.getType();
|
|
1824
|
+
if (fieldType) {
|
|
1825
|
+
const fieldNamedType = getNamedType(fieldType);
|
|
1826
|
+
if (isAbstractType(fieldNamedType) && fieldNamedType.name !== namedType.name && possibleTypes.length > 0) {
|
|
1827
|
+
return {
|
|
1828
|
+
...node,
|
|
1829
|
+
selectionSet: {
|
|
1830
|
+
kind: Kind.SELECTION_SET,
|
|
1831
|
+
selections: possibleTypes.map((possibleType) => ({
|
|
1832
|
+
kind: Kind.INLINE_FRAGMENT,
|
|
1833
|
+
typeCondition: {
|
|
1834
|
+
kind: Kind.NAMED_TYPE,
|
|
1835
|
+
name: {
|
|
1836
|
+
kind: Kind.NAME,
|
|
1837
|
+
value: possibleType.name
|
|
1838
|
+
}
|
|
1839
|
+
},
|
|
1840
|
+
selectionSet: node.selectionSet
|
|
1841
|
+
}))
|
|
1842
|
+
}
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
return void 0;
|
|
1847
|
+
}
|
|
1848
|
+
}),
|
|
1849
|
+
// visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
|
|
1850
|
+
// empty keys cannot be removed only because of typescript errors
|
|
1851
|
+
// will hopefully be fixed in future version of graphql-js to be optional
|
|
1852
|
+
visitorKeys
|
|
1853
|
+
);
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
class Transformer {
|
|
1857
|
+
transformations = [];
|
|
1858
|
+
delegationContext;
|
|
1859
|
+
hasOverlappingAliases = false;
|
|
1860
|
+
constructor(context) {
|
|
1861
|
+
this.delegationContext = context;
|
|
1862
|
+
const transforms = context.transforms;
|
|
1863
|
+
const delegationTransforms = transforms.slice().reverse();
|
|
1864
|
+
for (const transform of delegationTransforms) {
|
|
1865
|
+
this.addTransform(transform);
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
addTransform(transform, context = {}) {
|
|
1869
|
+
this.transformations.push({ transform, context });
|
|
1870
|
+
}
|
|
1871
|
+
transformRequest(originalRequest) {
|
|
1872
|
+
let request = {
|
|
1873
|
+
...originalRequest,
|
|
1874
|
+
document: prepareGatewayDocument(
|
|
1875
|
+
originalRequest.document,
|
|
1876
|
+
this.delegationContext
|
|
1877
|
+
)
|
|
1878
|
+
};
|
|
1879
|
+
for (const transformation of this.transformations) {
|
|
1880
|
+
if (transformation.transform.transformRequest) {
|
|
1881
|
+
request = transformation.transform.transformRequest(
|
|
1882
|
+
request,
|
|
1883
|
+
this.delegationContext,
|
|
1884
|
+
transformation.context
|
|
1885
|
+
);
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
return finalizeGatewayRequest(request, this.delegationContext, () => {
|
|
1889
|
+
this.hasOverlappingAliases = true;
|
|
1890
|
+
});
|
|
1891
|
+
}
|
|
1892
|
+
transformResult(originalResult) {
|
|
1893
|
+
let result = originalResult;
|
|
1894
|
+
for (let i = this.transformations.length - 1; i >= 0; i--) {
|
|
1895
|
+
const transformation = this.transformations[i];
|
|
1896
|
+
if (transformation?.transform.transformResult) {
|
|
1897
|
+
result = transformation.transform.transformResult(
|
|
1898
|
+
result,
|
|
1899
|
+
this.delegationContext,
|
|
1900
|
+
transformation.context
|
|
1901
|
+
);
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
if (this.hasOverlappingAliases) {
|
|
1905
|
+
result = removeOverlappingAliases(result);
|
|
1906
|
+
}
|
|
1907
|
+
return checkResultAndHandleErrors(result, this.delegationContext);
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
function removeOverlappingAliases(result) {
|
|
1911
|
+
if (result != null) {
|
|
1912
|
+
if (Array.isArray(result)) {
|
|
1913
|
+
return result.map(removeOverlappingAliases);
|
|
1914
|
+
} else if (typeof result === "object") {
|
|
1915
|
+
const newResult = {};
|
|
1916
|
+
for (const key in result) {
|
|
1917
|
+
if (key.startsWith("_nullable_") || key.startsWith("_nonNullable_")) {
|
|
1918
|
+
const newKey = key.replace(/^_nullable_/, "").replace(/^_nonNullable_/, "");
|
|
1919
|
+
newResult[newKey] = removeOverlappingAliases(result[key]);
|
|
1920
|
+
} else {
|
|
1921
|
+
newResult[key] = removeOverlappingAliases(result[key]);
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
return newResult;
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
return result;
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
function getDelegatingOperation(parentType, schema) {
|
|
1931
|
+
if (parentType === schema.getMutationType()) {
|
|
1932
|
+
return "mutation";
|
|
1933
|
+
} else if (parentType === schema.getSubscriptionType()) {
|
|
1934
|
+
return "subscription";
|
|
1935
|
+
}
|
|
1936
|
+
return "query";
|
|
1937
|
+
}
|
|
1938
|
+
function createRequest({
|
|
1939
|
+
subgraphName,
|
|
1940
|
+
fragments,
|
|
1941
|
+
rootValue,
|
|
1942
|
+
targetOperationName,
|
|
1943
|
+
targetOperation,
|
|
1944
|
+
targetSchema,
|
|
1945
|
+
targetFieldName,
|
|
1946
|
+
selectionSet,
|
|
1947
|
+
fieldNodes,
|
|
1948
|
+
context,
|
|
1949
|
+
info,
|
|
1950
|
+
args
|
|
1951
|
+
}) {
|
|
1952
|
+
let newSelectionSet;
|
|
1953
|
+
if (selectionSet != null) {
|
|
1954
|
+
newSelectionSet = selectionSet;
|
|
1955
|
+
} else {
|
|
1956
|
+
const selections = [];
|
|
1957
|
+
for (const fieldNode2 of fieldNodes || []) {
|
|
1958
|
+
if (fieldNode2.selectionSet) {
|
|
1959
|
+
for (const selection of fieldNode2.selectionSet.selections) {
|
|
1960
|
+
selections.push(selection);
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
newSelectionSet = selections.length ? {
|
|
1965
|
+
kind: Kind.SELECTION_SET,
|
|
1966
|
+
selections
|
|
1967
|
+
} : void 0;
|
|
1968
|
+
}
|
|
1969
|
+
const fieldNode = fieldNodes?.[0];
|
|
1970
|
+
const rootFieldName = targetFieldName ?? fieldNode?.name.value;
|
|
1971
|
+
if (rootFieldName === void 0) {
|
|
1972
|
+
throw new Error(
|
|
1973
|
+
`Either "targetFieldName" or a non empty "fieldNodes" array must be provided.`
|
|
1974
|
+
);
|
|
1975
|
+
}
|
|
1976
|
+
const newVariables = info?.variableValues ? { ...info.variableValues } : {};
|
|
1977
|
+
const variableDefinitions = info?.operation.variableDefinitions ? [...info.operation.variableDefinitions] : [];
|
|
1978
|
+
const argNodes = [];
|
|
1979
|
+
if (args != null) {
|
|
1980
|
+
const rootType = targetSchema != null ? getDefinedRootType(targetSchema, targetOperation) : void 0;
|
|
1981
|
+
const rootField = rootType?.getFields()[rootFieldName];
|
|
1982
|
+
const rootFieldArgs = rootField?.args;
|
|
1983
|
+
for (const argName in args) {
|
|
1984
|
+
const argValue = args[argName];
|
|
1985
|
+
const argInstance = rootFieldArgs?.find((arg) => arg.name === argName);
|
|
1986
|
+
const existingArgNode = fieldNode?.arguments?.find(
|
|
1987
|
+
(argNode) => argNode.name.value === argName
|
|
1988
|
+
);
|
|
1989
|
+
if (existingArgNode?.value.kind === Kind.VARIABLE) {
|
|
1990
|
+
const varName = existingArgNode.value.name.value;
|
|
1991
|
+
const varValue = newVariables[varName];
|
|
1992
|
+
if (varValue === argValue) {
|
|
1993
|
+
argNodes.push(existingArgNode);
|
|
1994
|
+
continue;
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
if (argInstance) {
|
|
1998
|
+
const argAst = astFromArg(argInstance, targetSchema);
|
|
1999
|
+
const varExists = (varName2) => variableDefinitions.some(
|
|
2000
|
+
(varDef) => varDef.variable.name.value === varName2
|
|
2001
|
+
) || // It should not conflict with the variable on the gateway request
|
|
2002
|
+
// Because the gateway request can have a variable that has nothing to do with
|
|
2003
|
+
// this argument
|
|
2004
|
+
info?.variableValues?.[varName2] != null;
|
|
2005
|
+
let varName = argName;
|
|
2006
|
+
if (varExists(varName)) {
|
|
2007
|
+
varName = `_${rootFieldName}_${argName}`;
|
|
2008
|
+
let i = 0;
|
|
2009
|
+
while (varExists(varName)) {
|
|
2010
|
+
varName = `_${i++}_${rootFieldName}_${argName}`;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
variableDefinitions.push({
|
|
2014
|
+
kind: Kind.VARIABLE_DEFINITION,
|
|
2015
|
+
variable: {
|
|
2016
|
+
kind: Kind.VARIABLE,
|
|
2017
|
+
name: {
|
|
2018
|
+
kind: Kind.NAME,
|
|
2019
|
+
value: varName
|
|
2020
|
+
}
|
|
2021
|
+
},
|
|
2022
|
+
type: argAst.type
|
|
2023
|
+
});
|
|
2024
|
+
const varValue = projectArgumentValue(argValue, argInstance.type);
|
|
2025
|
+
if (varValue !== void 0) {
|
|
2026
|
+
newVariables[varName] = varValue;
|
|
2027
|
+
}
|
|
2028
|
+
argNodes.push({
|
|
2029
|
+
kind: Kind.ARGUMENT,
|
|
2030
|
+
name: {
|
|
2031
|
+
kind: Kind.NAME,
|
|
2032
|
+
value: argName
|
|
2033
|
+
},
|
|
2034
|
+
value: {
|
|
2035
|
+
kind: Kind.VARIABLE,
|
|
2036
|
+
name: {
|
|
2037
|
+
kind: Kind.NAME,
|
|
2038
|
+
value: varName
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
});
|
|
2042
|
+
} else {
|
|
2043
|
+
const valueNode = astFromValueUntyped(argValue);
|
|
2044
|
+
if (valueNode != null) {
|
|
2045
|
+
argNodes.push({
|
|
2046
|
+
kind: Kind.ARGUMENT,
|
|
2047
|
+
name: {
|
|
2048
|
+
kind: Kind.NAME,
|
|
2049
|
+
value: argName
|
|
2050
|
+
},
|
|
2051
|
+
value: valueNode
|
|
2052
|
+
});
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
const rootfieldNode = {
|
|
2058
|
+
kind: Kind.FIELD,
|
|
2059
|
+
arguments: argNodes,
|
|
2060
|
+
name: {
|
|
2061
|
+
kind: Kind.NAME,
|
|
2062
|
+
value: rootFieldName
|
|
2063
|
+
},
|
|
2064
|
+
selectionSet: newSelectionSet,
|
|
2065
|
+
directives: fieldNode?.directives
|
|
2066
|
+
};
|
|
2067
|
+
const operationName = targetOperationName ? {
|
|
2068
|
+
kind: Kind.NAME,
|
|
2069
|
+
value: targetOperationName
|
|
2070
|
+
} : void 0;
|
|
2071
|
+
const operationDefinition = {
|
|
2072
|
+
kind: Kind.OPERATION_DEFINITION,
|
|
2073
|
+
name: operationName,
|
|
2074
|
+
operation: targetOperation,
|
|
2075
|
+
variableDefinitions,
|
|
2076
|
+
selectionSet: {
|
|
2077
|
+
kind: Kind.SELECTION_SET,
|
|
2078
|
+
selections: [rootfieldNode]
|
|
2079
|
+
}
|
|
2080
|
+
};
|
|
2081
|
+
const definitions = [operationDefinition];
|
|
2082
|
+
if (fragments != null) {
|
|
2083
|
+
definitions.push(...fragments);
|
|
2084
|
+
}
|
|
2085
|
+
const document = {
|
|
2086
|
+
kind: Kind.DOCUMENT,
|
|
2087
|
+
definitions
|
|
2088
|
+
};
|
|
2089
|
+
return {
|
|
2090
|
+
subgraphName,
|
|
2091
|
+
document,
|
|
2092
|
+
variables: newVariables,
|
|
2093
|
+
rootValue,
|
|
2094
|
+
operationName: targetOperationName,
|
|
2095
|
+
context,
|
|
2096
|
+
info,
|
|
2097
|
+
operationType: targetOperation
|
|
2098
|
+
};
|
|
2099
|
+
}
|
|
2100
|
+
function projectArgumentValue(argValue, argType) {
|
|
2101
|
+
if (argValue == null) {
|
|
2102
|
+
return argValue;
|
|
2103
|
+
}
|
|
2104
|
+
if (isNonNullType(argType)) {
|
|
2105
|
+
return projectArgumentValue(argValue, argType.ofType);
|
|
2106
|
+
}
|
|
2107
|
+
if (isListType(argType)) {
|
|
2108
|
+
return asArray(argValue).map(
|
|
2109
|
+
(item) => projectArgumentValue(item, argType.ofType)
|
|
2110
|
+
);
|
|
2111
|
+
}
|
|
2112
|
+
if (isInputObjectType(argType) && typeof argValue === "object") {
|
|
2113
|
+
const projectedValue = {};
|
|
2114
|
+
const fields = argType.getFields();
|
|
2115
|
+
for (const key in argValue) {
|
|
2116
|
+
const field = fields[key];
|
|
2117
|
+
if (field) {
|
|
2118
|
+
const varValue = projectArgumentValue(argValue[key], field.type);
|
|
2119
|
+
if (varValue !== void 0) {
|
|
2120
|
+
projectedValue[key] = varValue;
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
return projectedValue;
|
|
2125
|
+
}
|
|
2126
|
+
if (argType.name === "Boolean") {
|
|
2127
|
+
return Boolean(argValue);
|
|
2128
|
+
}
|
|
2129
|
+
if (argType.name === "Int" || argType.name === "Float") {
|
|
2130
|
+
return Number(argValue);
|
|
2131
|
+
}
|
|
2132
|
+
if (argType.name === "String") {
|
|
2133
|
+
return String(argValue);
|
|
2134
|
+
}
|
|
2135
|
+
return argValue;
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
function defaultMergedResolver(parent, args, context, info) {
|
|
2139
|
+
if (!parent) {
|
|
2140
|
+
return null;
|
|
2141
|
+
}
|
|
2142
|
+
const responseKey = getResponseKeyFromInfo(info);
|
|
2143
|
+
if (!isExternalObject(parent)) {
|
|
2144
|
+
return defaultFieldResolver(parent, args, context, info);
|
|
2145
|
+
}
|
|
2146
|
+
if (!Object.prototype.hasOwnProperty.call(parent, responseKey)) {
|
|
2147
|
+
const leftOver = getPlanLeftOverFromParent(parent);
|
|
2148
|
+
if (leftOver) {
|
|
2149
|
+
let missingFieldNodes = leftOver.missingFieldsParentMap.get(parent);
|
|
2150
|
+
if (!missingFieldNodes) {
|
|
2151
|
+
missingFieldNodes = [];
|
|
2152
|
+
leftOver.missingFieldsParentMap.set(parent, missingFieldNodes);
|
|
2153
|
+
}
|
|
2154
|
+
missingFieldNodes.push(
|
|
2155
|
+
...info.fieldNodes.filter(
|
|
2156
|
+
(fieldNode) => leftOver.unproxiableFieldNodes.some(
|
|
2157
|
+
(unproxiableFieldNode) => unproxiableFieldNode === fieldNode
|
|
2158
|
+
)
|
|
2159
|
+
)
|
|
2160
|
+
);
|
|
2161
|
+
let missingDeferredFields = leftOver.missingFieldsParentDeferredMap.get(parent);
|
|
2162
|
+
if (!missingDeferredFields) {
|
|
2163
|
+
missingDeferredFields = /* @__PURE__ */ new Map();
|
|
2164
|
+
leftOver.missingFieldsParentDeferredMap.set(
|
|
2165
|
+
parent,
|
|
2166
|
+
missingDeferredFields
|
|
2167
|
+
);
|
|
2168
|
+
}
|
|
2169
|
+
const deferred = createDeferredPromise();
|
|
2170
|
+
missingDeferredFields.set(responseKey, deferred);
|
|
2171
|
+
const stitchingInfo = info.schema.extensions?.["stitchingInfo"];
|
|
2172
|
+
const parentTypeName = parent?.__typename || info.parentType.name;
|
|
2173
|
+
const fieldNodesByType = stitchingInfo?.fieldNodesByField?.[parentTypeName]?.[info.fieldName];
|
|
2174
|
+
if (fieldNodesByType?.every((fieldNode) => {
|
|
2175
|
+
const responseKey2 = fieldNode.alias?.value ?? fieldNode.name.value;
|
|
2176
|
+
return Object.prototype.hasOwnProperty.call(parent, responseKey2);
|
|
2177
|
+
})) {
|
|
2178
|
+
handleResult(parent, responseKey, context, info);
|
|
2179
|
+
} else {
|
|
2180
|
+
handleLeftOver(parent, context, info, leftOver);
|
|
2181
|
+
}
|
|
2182
|
+
return deferred.promise;
|
|
2183
|
+
}
|
|
2184
|
+
return void 0;
|
|
2185
|
+
}
|
|
2186
|
+
return handleResult(parent, responseKey, context, info);
|
|
2187
|
+
}
|
|
2188
|
+
function handleResult(parent, responseKey, context, info) {
|
|
2189
|
+
const subschema = getSubschema(parent, responseKey);
|
|
2190
|
+
const data = parent[responseKey];
|
|
2191
|
+
const unpathedErrors = getUnpathedErrors(parent);
|
|
2192
|
+
const resolvedData$ = resolveExternalValue(
|
|
2193
|
+
data,
|
|
2194
|
+
unpathedErrors,
|
|
2195
|
+
subschema,
|
|
2196
|
+
context,
|
|
2197
|
+
info
|
|
2198
|
+
);
|
|
2199
|
+
const leftOver = getPlanLeftOverFromParent(parent);
|
|
2200
|
+
if (leftOver) {
|
|
2201
|
+
return handleMaybePromise(
|
|
2202
|
+
() => resolvedData$,
|
|
2203
|
+
(resolvedData) => {
|
|
2204
|
+
parent[responseKey] = resolvedData;
|
|
2205
|
+
handleLeftOver(parent, context, info, leftOver);
|
|
2206
|
+
return resolvedData;
|
|
2207
|
+
}
|
|
2208
|
+
);
|
|
2209
|
+
}
|
|
2210
|
+
return resolvedData$;
|
|
2211
|
+
}
|
|
2212
|
+
function handleLeftOver(parent, context, info, leftOver) {
|
|
2213
|
+
const stitchingInfo = info.schema.extensions?.["stitchingInfo"];
|
|
2214
|
+
if (stitchingInfo) {
|
|
2215
|
+
for (const possibleSubschema of leftOver.nonProxiableSubschemas) {
|
|
2216
|
+
const parentTypeName = info.parentType.name;
|
|
2217
|
+
const selectionSets = /* @__PURE__ */ new Set();
|
|
2218
|
+
const mainSelectionSet = stitchingInfo.mergedTypes[parentTypeName]?.selectionSets.get(
|
|
2219
|
+
possibleSubschema
|
|
2220
|
+
);
|
|
2221
|
+
if (mainSelectionSet) {
|
|
2222
|
+
selectionSets.add(mainSelectionSet);
|
|
2223
|
+
}
|
|
2224
|
+
for (const fieldNode of leftOver.unproxiableFieldNodes) {
|
|
2225
|
+
const fieldName = fieldNode.name.value;
|
|
2226
|
+
const fieldSelectionSet = stitchingInfo.mergedTypes[parentTypeName]?.fieldSelectionSets.get(
|
|
2227
|
+
possibleSubschema
|
|
2228
|
+
)?.[fieldName];
|
|
2229
|
+
if (fieldSelectionSet) {
|
|
2230
|
+
selectionSets.add(fieldSelectionSet);
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
if (selectionSets.size) {
|
|
2234
|
+
const selectionSet = {
|
|
2235
|
+
kind: Kind.SELECTION_SET,
|
|
2236
|
+
selections: Array.from(selectionSets).flatMap(
|
|
2237
|
+
(selectionSet2) => selectionSet2.selections
|
|
2238
|
+
)
|
|
2239
|
+
};
|
|
2240
|
+
handleMaybePromise(
|
|
2241
|
+
() => flattenPromise(parent),
|
|
2242
|
+
(flattenedParent) => {
|
|
2243
|
+
handleFlattenedParent(
|
|
2244
|
+
flattenedParent,
|
|
2245
|
+
parent,
|
|
2246
|
+
possibleSubschema,
|
|
2247
|
+
selectionSet,
|
|
2248
|
+
leftOver,
|
|
2249
|
+
stitchingInfo,
|
|
2250
|
+
parentTypeName,
|
|
2251
|
+
context,
|
|
2252
|
+
info
|
|
2253
|
+
);
|
|
2254
|
+
}
|
|
2255
|
+
);
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
function handleFlattenedParent(flattenedParent, leftOverParent, possibleSubschema, selectionSet, leftOver, stitchingInfo, parentTypeName, context, info) {
|
|
2261
|
+
if (parentSatisfiedSelectionSet(flattenedParent, selectionSet)) {
|
|
2262
|
+
const missingFieldNodes = leftOver.missingFieldsParentMap.get(leftOverParent);
|
|
2263
|
+
if (missingFieldNodes) {
|
|
2264
|
+
const resolver = stitchingInfo.mergedTypes[parentTypeName]?.resolvers.get(
|
|
2265
|
+
possibleSubschema
|
|
2266
|
+
);
|
|
2267
|
+
if (resolver) {
|
|
2268
|
+
Object.assign(leftOverParent, flattenedParent);
|
|
2269
|
+
const selectionSet2 = {
|
|
2270
|
+
kind: Kind.SELECTION_SET,
|
|
2271
|
+
selections: missingFieldNodes
|
|
2272
|
+
};
|
|
2273
|
+
handleMaybePromise(
|
|
2274
|
+
() => resolver(
|
|
2275
|
+
leftOverParent,
|
|
2276
|
+
context,
|
|
2277
|
+
info,
|
|
2278
|
+
possibleSubschema,
|
|
2279
|
+
selectionSet2,
|
|
2280
|
+
info.parentType,
|
|
2281
|
+
info.parentType
|
|
2282
|
+
),
|
|
2283
|
+
(resolverResult) => {
|
|
2284
|
+
handleDeferredResolverResult(
|
|
2285
|
+
resolverResult,
|
|
2286
|
+
possibleSubschema,
|
|
2287
|
+
selectionSet2,
|
|
2288
|
+
leftOverParent,
|
|
2289
|
+
leftOver,
|
|
2290
|
+
context,
|
|
2291
|
+
info
|
|
2292
|
+
);
|
|
2293
|
+
},
|
|
2294
|
+
(error) => handleDeferredResolverFailure(leftOver, leftOverParent, error)
|
|
2295
|
+
);
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
} else {
|
|
2299
|
+
for (const selectionNode of selectionSet.selections) {
|
|
2300
|
+
if (selectionNode.kind === Kind.FIELD && selectionNode.selectionSet?.selections?.length) {
|
|
2301
|
+
const responseKey = selectionNode.alias?.value ?? selectionNode.name.value;
|
|
2302
|
+
const nestedParent = flattenedParent[responseKey];
|
|
2303
|
+
const nestedSelectionSet = selectionNode.selectionSet;
|
|
2304
|
+
if (nestedParent != null) {
|
|
2305
|
+
if (!parentSatisfiedSelectionSet(nestedParent, nestedSelectionSet)) {
|
|
2306
|
+
async function handleNestedParentItem(nestedParentItem, fieldNode) {
|
|
2307
|
+
const nestedTypeName = nestedParentItem["__typename"];
|
|
2308
|
+
const sourceSubschema = getSubschema(
|
|
2309
|
+
flattenedParent,
|
|
2310
|
+
responseKey
|
|
2311
|
+
);
|
|
2312
|
+
if (sourceSubschema && nestedTypeName) {
|
|
2313
|
+
const delegationPlan = stitchingInfo.mergedTypes[nestedTypeName]?.delegationPlanBuilder(
|
|
2314
|
+
info.schema,
|
|
2315
|
+
sourceSubschema,
|
|
2316
|
+
info.variableValues != null && Object.keys(info.variableValues).length > 0 ? info.variableValues : EMPTY_OBJECT,
|
|
2317
|
+
info.fragments != null && Object.keys(info.fragments).length > 0 ? info.fragments : EMPTY_OBJECT,
|
|
2318
|
+
getActualFieldNodes(fieldNode),
|
|
2319
|
+
context,
|
|
2320
|
+
info
|
|
2321
|
+
);
|
|
2322
|
+
if (delegationPlan?.length) {
|
|
2323
|
+
for (const delegationMap of delegationPlan) {
|
|
2324
|
+
for (const [subschema, selectionSet2] of delegationMap) {
|
|
2325
|
+
const resolver = stitchingInfo.mergedTypes[nestedTypeName]?.resolvers.get(subschema);
|
|
2326
|
+
if (resolver) {
|
|
2327
|
+
const subschemaTypes = stitchingInfo.mergedTypes[nestedTypeName].typeMaps.get(subschema);
|
|
2328
|
+
const returnType = subschemaTypes[nestedTypeName];
|
|
2329
|
+
const res = await resolver(
|
|
2330
|
+
nestedParentItem,
|
|
2331
|
+
context,
|
|
2332
|
+
info,
|
|
2333
|
+
subschema,
|
|
2334
|
+
selectionSet2,
|
|
2335
|
+
returnType,
|
|
2336
|
+
// returnType
|
|
2337
|
+
info.parentType
|
|
2338
|
+
);
|
|
2339
|
+
if (res) {
|
|
2340
|
+
handleResolverResult(
|
|
2341
|
+
res,
|
|
2342
|
+
subschema,
|
|
2343
|
+
selectionSet2,
|
|
2344
|
+
nestedParentItem,
|
|
2345
|
+
nestedParentItem[FIELD_SUBSCHEMA_MAP_SYMBOL] ||= /* @__PURE__ */ new Map(),
|
|
2346
|
+
info,
|
|
2347
|
+
responsePathAsArray(info.path),
|
|
2348
|
+
nestedParentItem[UNPATHED_ERRORS_SYMBOL] ||= []
|
|
2349
|
+
);
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
if (parentSatisfiedSelectionSet(nestedParent, nestedSelectionSet)) {
|
|
2356
|
+
handleFlattenedParent(
|
|
2357
|
+
flattenedParent,
|
|
2358
|
+
leftOverParent,
|
|
2359
|
+
possibleSubschema,
|
|
2360
|
+
selectionSet,
|
|
2361
|
+
leftOver,
|
|
2362
|
+
stitchingInfo,
|
|
2363
|
+
parentTypeName,
|
|
2364
|
+
context,
|
|
2365
|
+
info
|
|
2366
|
+
);
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
if (Array.isArray(nestedParent)) {
|
|
2371
|
+
nestedParent.forEach(
|
|
2372
|
+
(nestedParentItem) => handleNestedParentItem(nestedParentItem, selectionNode)
|
|
2373
|
+
);
|
|
2374
|
+
} else {
|
|
2375
|
+
handleNestedParentItem(nestedParent, selectionNode);
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
function handleDeferredResolverResult(resolverResult, possibleSubschema, selectionSet, leftOverParent, leftOver, context, info) {
|
|
2384
|
+
handleResolverResult(
|
|
2385
|
+
resolverResult,
|
|
2386
|
+
possibleSubschema,
|
|
2387
|
+
selectionSet,
|
|
2388
|
+
leftOverParent,
|
|
2389
|
+
leftOverParent[FIELD_SUBSCHEMA_MAP_SYMBOL],
|
|
2390
|
+
info,
|
|
2391
|
+
responsePathAsArray(info.path),
|
|
2392
|
+
leftOverParent[UNPATHED_ERRORS_SYMBOL]
|
|
2393
|
+
);
|
|
2394
|
+
const deferredFields = leftOver.missingFieldsParentDeferredMap.get(leftOverParent);
|
|
2395
|
+
if (deferredFields) {
|
|
2396
|
+
const stitchingInfo = info.schema.extensions?.["stitchingInfo"];
|
|
2397
|
+
const parentTypeName = leftOverParent?.__typename || info.parentType.name;
|
|
2398
|
+
const resolvedKeys = /* @__PURE__ */ new Set();
|
|
2399
|
+
for (const [responseKey, deferred] of deferredFields) {
|
|
2400
|
+
if (Object.prototype.hasOwnProperty.call(leftOverParent, responseKey)) {
|
|
2401
|
+
deferred.resolve(
|
|
2402
|
+
handleResult(leftOverParent, responseKey, context, info)
|
|
2403
|
+
);
|
|
2404
|
+
resolvedKeys.add(responseKey);
|
|
2405
|
+
} else {
|
|
2406
|
+
const fieldNodesByType = stitchingInfo?.fieldNodesByField?.[parentTypeName]?.[responseKey];
|
|
2407
|
+
if (fieldNodesByType) {
|
|
2408
|
+
if (fieldNodesByType.every((fieldNode) => {
|
|
2409
|
+
const requiredKey = fieldNode.alias?.value ?? fieldNode.name.value;
|
|
2410
|
+
return Object.prototype.hasOwnProperty.call(
|
|
2411
|
+
leftOverParent,
|
|
2412
|
+
requiredKey
|
|
2413
|
+
);
|
|
2414
|
+
})) {
|
|
2415
|
+
setTimeout(() => {
|
|
2416
|
+
handleLeftOver(leftOverParent, context, info, leftOver);
|
|
2417
|
+
}, 0);
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
for (const key of resolvedKeys) {
|
|
2423
|
+
deferredFields.delete(key);
|
|
2424
|
+
}
|
|
2425
|
+
if (deferredFields.size === 0) {
|
|
2426
|
+
leftOver.missingFieldsParentDeferredMap.delete(leftOverParent);
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
function handleDeferredResolverFailure(leftOver, leftOverParent, error) {
|
|
2431
|
+
const deferredFields = leftOver.missingFieldsParentDeferredMap.get(leftOverParent);
|
|
2432
|
+
if (deferredFields) {
|
|
2433
|
+
for (const [_responseKey, deferred] of deferredFields) {
|
|
2434
|
+
deferred.reject(error);
|
|
2435
|
+
}
|
|
2436
|
+
leftOver.missingFieldsParentDeferredMap.delete(leftOverParent);
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
function parentSatisfiedSelectionSet(parent, selectionSet) {
|
|
2440
|
+
if (Array.isArray(parent)) {
|
|
2441
|
+
const subschemas2 = /* @__PURE__ */ new Set();
|
|
2442
|
+
for (const item of parent) {
|
|
2443
|
+
const satisfied = parentSatisfiedSelectionSet(item, selectionSet);
|
|
2444
|
+
if (satisfied === void 0) {
|
|
2445
|
+
return void 0;
|
|
2446
|
+
}
|
|
2447
|
+
for (const subschema of satisfied) {
|
|
2448
|
+
subschemas2.add(subschema);
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
return subschemas2;
|
|
2452
|
+
}
|
|
2453
|
+
if (parent === null) {
|
|
2454
|
+
return /* @__PURE__ */ new Set();
|
|
2455
|
+
}
|
|
2456
|
+
if (parent === void 0) {
|
|
2457
|
+
return void 0;
|
|
2458
|
+
}
|
|
2459
|
+
const subschemas = /* @__PURE__ */ new Set();
|
|
2460
|
+
for (const selection of selectionSet.selections) {
|
|
2461
|
+
if (selection.kind === Kind.FIELD) {
|
|
2462
|
+
const responseKey = selection.alias?.value ?? selection.name.value;
|
|
2463
|
+
if (parent[responseKey] === void 0) {
|
|
2464
|
+
return void 0;
|
|
2465
|
+
}
|
|
2466
|
+
if (isExternalObject(parent)) {
|
|
2467
|
+
const subschema = getSubschema(parent, responseKey);
|
|
2468
|
+
if (subschema) {
|
|
2469
|
+
subschemas.add(subschema);
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
if (parent[responseKey] === null) {
|
|
2473
|
+
continue;
|
|
2474
|
+
}
|
|
2475
|
+
if (selection.selectionSet != null) {
|
|
2476
|
+
const satisfied = parentSatisfiedSelectionSet(
|
|
2477
|
+
parent[responseKey],
|
|
2478
|
+
selection.selectionSet
|
|
2479
|
+
);
|
|
2480
|
+
if (satisfied === void 0) {
|
|
2481
|
+
return void 0;
|
|
2482
|
+
}
|
|
2483
|
+
for (const subschema of satisfied) {
|
|
2484
|
+
subschemas.add(subschema);
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
} else if (selection.kind === Kind.INLINE_FRAGMENT) {
|
|
2488
|
+
const inlineSatisfied = parentSatisfiedSelectionSet(
|
|
2489
|
+
parent,
|
|
2490
|
+
selection.selectionSet
|
|
2491
|
+
);
|
|
2492
|
+
if (inlineSatisfied === void 0) {
|
|
2493
|
+
return void 0;
|
|
2494
|
+
}
|
|
2495
|
+
for (const subschema of inlineSatisfied) {
|
|
2496
|
+
subschemas.add(subschema);
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
return subschemas;
|
|
2501
|
+
}
|
|
2502
|
+
function flattenPromise(data) {
|
|
2503
|
+
if (isPromise(data)) {
|
|
2504
|
+
return data.then(flattenPromise);
|
|
2505
|
+
}
|
|
2506
|
+
if (Array.isArray(data)) {
|
|
2507
|
+
return Promise.all(data.map(flattenPromise));
|
|
2508
|
+
}
|
|
2509
|
+
if (data != null && typeof data === "object") {
|
|
2510
|
+
const jobs = [];
|
|
2511
|
+
const newData = {};
|
|
2512
|
+
for (const key in data) {
|
|
2513
|
+
const keyResult = flattenPromise(data[key]);
|
|
2514
|
+
if (isPromise(keyResult)) {
|
|
2515
|
+
jobs.push(
|
|
2516
|
+
keyResult.then((resolvedKeyResult) => {
|
|
2517
|
+
newData[key] = resolvedKeyResult;
|
|
2518
|
+
})
|
|
2519
|
+
);
|
|
2520
|
+
} else {
|
|
2521
|
+
newData[key] = keyResult;
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
if (OBJECT_SUBSCHEMA_SYMBOL in data) {
|
|
2525
|
+
newData[OBJECT_SUBSCHEMA_SYMBOL] = data[OBJECT_SUBSCHEMA_SYMBOL];
|
|
2526
|
+
}
|
|
2527
|
+
if (FIELD_SUBSCHEMA_MAP_SYMBOL in data) {
|
|
2528
|
+
newData[FIELD_SUBSCHEMA_MAP_SYMBOL] = data[FIELD_SUBSCHEMA_MAP_SYMBOL];
|
|
2529
|
+
}
|
|
2530
|
+
if (UNPATHED_ERRORS_SYMBOL in data) {
|
|
2531
|
+
newData[UNPATHED_ERRORS_SYMBOL] = data[UNPATHED_ERRORS_SYMBOL];
|
|
2532
|
+
}
|
|
2533
|
+
if (jobs.length) {
|
|
2534
|
+
return Promise.all(jobs).then(() => newData);
|
|
2535
|
+
}
|
|
2536
|
+
return newData;
|
|
2537
|
+
}
|
|
2538
|
+
return data;
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
function isSubschemaConfig(value) {
|
|
2542
|
+
return Boolean(value?.schema);
|
|
2543
|
+
}
|
|
2544
|
+
function cloneSubschemaConfig(subschemaConfig) {
|
|
2545
|
+
const newSubschemaConfig = {
|
|
2546
|
+
...subschemaConfig,
|
|
2547
|
+
transforms: subschemaConfig.transforms != null ? [...subschemaConfig.transforms] : void 0
|
|
2548
|
+
};
|
|
2549
|
+
if (newSubschemaConfig.merge != null) {
|
|
2550
|
+
newSubschemaConfig.merge = { ...subschemaConfig.merge };
|
|
2551
|
+
for (const typeName in newSubschemaConfig.merge) {
|
|
2552
|
+
const mergedTypeConfig = newSubschemaConfig.merge[typeName] = {
|
|
2553
|
+
...subschemaConfig.merge?.[typeName] ?? {}
|
|
2554
|
+
};
|
|
2555
|
+
if (mergedTypeConfig.entryPoints != null) {
|
|
2556
|
+
mergedTypeConfig.entryPoints = mergedTypeConfig.entryPoints.map(
|
|
2557
|
+
(entryPoint) => ({
|
|
2558
|
+
...entryPoint
|
|
2559
|
+
})
|
|
2560
|
+
);
|
|
2561
|
+
}
|
|
2562
|
+
if (mergedTypeConfig.fields != null) {
|
|
2563
|
+
const fields = mergedTypeConfig.fields = {
|
|
2564
|
+
...mergedTypeConfig.fields
|
|
2565
|
+
};
|
|
2566
|
+
for (const fieldName in fields) {
|
|
2567
|
+
fields[fieldName] = { ...fields[fieldName] };
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
return newSubschemaConfig;
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
const getFragmentDefinitions = memoize1(
|
|
2576
|
+
(info) => {
|
|
2577
|
+
const fragmentMap = info.fragments;
|
|
2578
|
+
return Object.values(fragmentMap);
|
|
2579
|
+
}
|
|
2580
|
+
);
|
|
2581
|
+
function delegateToSchema(options) {
|
|
2582
|
+
const {
|
|
2583
|
+
info,
|
|
2584
|
+
schema,
|
|
2585
|
+
rootValue = schema.rootValue ?? info.rootValue,
|
|
2586
|
+
operationName = info.operation.name?.value,
|
|
2587
|
+
operation = getDelegatingOperation(info.parentType, info.schema),
|
|
2588
|
+
fieldName = info.fieldName,
|
|
2589
|
+
selectionSet,
|
|
2590
|
+
fieldNodes = info.fieldNodes,
|
|
2591
|
+
context,
|
|
2592
|
+
args
|
|
2593
|
+
} = options;
|
|
2594
|
+
let targetSchema;
|
|
2595
|
+
if (isSubschema(schema)) {
|
|
2596
|
+
targetSchema = schema.transformedSchema;
|
|
2597
|
+
} else if (isSchema(schema)) {
|
|
2598
|
+
targetSchema = schema;
|
|
2599
|
+
} else {
|
|
2600
|
+
const stitchingInfo = info.schema.extensions?.["stitchingInfo"];
|
|
2601
|
+
const subschema = stitchingInfo?.subschemaMap.get(schema);
|
|
2602
|
+
if (subschema != null) {
|
|
2603
|
+
targetSchema = subschema.transformedSchema;
|
|
2604
|
+
} else {
|
|
2605
|
+
targetSchema = applySchemaTransforms(schema.schema, schema);
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
const fragments = info ? getFragmentDefinitions(info) : void 0;
|
|
2609
|
+
const request = createRequest({
|
|
2610
|
+
subgraphName: schema.name,
|
|
2611
|
+
fragments,
|
|
2612
|
+
targetSchema,
|
|
2613
|
+
rootValue,
|
|
2614
|
+
targetOperationName: operationName,
|
|
2615
|
+
targetOperation: operation,
|
|
2616
|
+
targetFieldName: fieldName,
|
|
2617
|
+
selectionSet,
|
|
2618
|
+
fieldNodes,
|
|
2619
|
+
context,
|
|
2620
|
+
info,
|
|
2621
|
+
args
|
|
2622
|
+
});
|
|
2623
|
+
return delegateRequest({
|
|
2624
|
+
...options,
|
|
2625
|
+
targetSchema,
|
|
2626
|
+
request
|
|
2627
|
+
});
|
|
2628
|
+
}
|
|
2629
|
+
function getDelegationReturnType(targetSchema, operation, fieldName) {
|
|
2630
|
+
const rootType = getDefinedRootType(targetSchema, operation);
|
|
2631
|
+
const rootFieldType = rootType.getFields()[fieldName];
|
|
2632
|
+
if (!rootFieldType) {
|
|
2633
|
+
throw new Error(
|
|
2634
|
+
`Unable to find field '${fieldName}' in type '${rootType}'.`
|
|
2635
|
+
);
|
|
2636
|
+
}
|
|
2637
|
+
return rootFieldType.type;
|
|
2638
|
+
}
|
|
2639
|
+
function delegateRequest(options) {
|
|
2640
|
+
const delegationContext = getDelegationContext(options);
|
|
2641
|
+
const transformer = new Transformer(delegationContext);
|
|
2642
|
+
const processedRequest = transformer.transformRequest(options.request);
|
|
2643
|
+
if (options.validateRequest) {
|
|
2644
|
+
validateRequest(delegationContext, processedRequest.document);
|
|
2645
|
+
}
|
|
2646
|
+
return handleMaybePromise(
|
|
2647
|
+
() => getExecutor(delegationContext)(processedRequest),
|
|
2648
|
+
function handleExecutorResult(executorResult) {
|
|
2649
|
+
if (isAsyncIterable(executorResult)) {
|
|
2650
|
+
if (delegationContext.operation === "query" && isListType(delegationContext.returnType)) {
|
|
2651
|
+
return new Repeater(async (push, stop) => {
|
|
2652
|
+
const pushed = /* @__PURE__ */ new WeakSet();
|
|
2653
|
+
let stopped = false;
|
|
2654
|
+
stop.finally(() => {
|
|
2655
|
+
stopped = true;
|
|
2656
|
+
});
|
|
2657
|
+
try {
|
|
2658
|
+
for await (const result of executorResult) {
|
|
2659
|
+
if (stopped) {
|
|
2660
|
+
break;
|
|
2661
|
+
}
|
|
2662
|
+
if (result.incremental) {
|
|
2663
|
+
const data = {};
|
|
2664
|
+
for (const incrementalRes of result.incremental) {
|
|
2665
|
+
if (incrementalRes.items?.length) {
|
|
2666
|
+
for (const item of incrementalRes.items) {
|
|
2667
|
+
setObjectKeyPath(
|
|
2668
|
+
data,
|
|
2669
|
+
(incrementalRes.path || []).slice(0, -1),
|
|
2670
|
+
item
|
|
2671
|
+
);
|
|
2672
|
+
}
|
|
2673
|
+
await push(await transformer.transformResult({ data }));
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
if (result.hasNext === false) {
|
|
2677
|
+
break;
|
|
2678
|
+
} else {
|
|
2679
|
+
continue;
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
const transformedResult = await transformer.transformResult(result);
|
|
2683
|
+
if (Array.isArray(transformedResult)) {
|
|
2684
|
+
for (const individualResult$ of transformedResult) {
|
|
2685
|
+
if (stopped) {
|
|
2686
|
+
break;
|
|
2687
|
+
}
|
|
2688
|
+
const individualResult = await individualResult$;
|
|
2689
|
+
if (!pushed.has(individualResult)) {
|
|
2690
|
+
pushed.add(individualResult);
|
|
2691
|
+
await push(individualResult);
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
} else {
|
|
2695
|
+
await push(await transformedResult);
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
stop();
|
|
2699
|
+
} catch (error) {
|
|
2700
|
+
stop(error);
|
|
2701
|
+
}
|
|
2702
|
+
});
|
|
2703
|
+
}
|
|
2704
|
+
return mapAsyncIterator(
|
|
2705
|
+
executorResult,
|
|
2706
|
+
(result) => transformer.transformResult(result)
|
|
2707
|
+
);
|
|
2708
|
+
}
|
|
2709
|
+
return transformer.transformResult(executorResult);
|
|
2710
|
+
}
|
|
2711
|
+
);
|
|
2712
|
+
}
|
|
2713
|
+
function getDelegationContext({
|
|
2714
|
+
request,
|
|
2715
|
+
schema,
|
|
2716
|
+
fieldName,
|
|
2717
|
+
returnType,
|
|
2718
|
+
info,
|
|
2719
|
+
args,
|
|
2720
|
+
transforms = [],
|
|
2721
|
+
targetSchema: transformedSchema,
|
|
2722
|
+
skipTypeMerging = false,
|
|
2723
|
+
onLocatedError
|
|
2724
|
+
}) {
|
|
2725
|
+
const operationDefinition = getOperationASTFromRequest(request);
|
|
2726
|
+
let targetFieldName;
|
|
2727
|
+
if (fieldName == null) {
|
|
2728
|
+
targetFieldName = operationDefinition.selectionSet.selections[0].name.value;
|
|
2729
|
+
} else {
|
|
2730
|
+
targetFieldName = fieldName;
|
|
2731
|
+
}
|
|
2732
|
+
const stitchingInfo = info?.schema.extensions?.["stitchingInfo"];
|
|
2733
|
+
const subschemaOrSubschemaConfig = stitchingInfo?.subschemaMap.get(schema) ?? schema;
|
|
2734
|
+
const operation = operationDefinition.operation;
|
|
2735
|
+
if (isSubschemaConfig(subschemaOrSubschemaConfig)) {
|
|
2736
|
+
const targetSchema = subschemaOrSubschemaConfig.schema;
|
|
2737
|
+
return {
|
|
2738
|
+
subschema: schema,
|
|
2739
|
+
subschemaConfig: subschemaOrSubschemaConfig,
|
|
2740
|
+
targetSchema,
|
|
2741
|
+
operation,
|
|
2742
|
+
fieldName: targetFieldName,
|
|
2743
|
+
context: request.context,
|
|
2744
|
+
info,
|
|
2745
|
+
returnType: returnType ?? info?.returnType ?? getDelegationReturnType(targetSchema, operation, targetFieldName),
|
|
2746
|
+
transforms: subschemaOrSubschemaConfig.transforms != null ? subschemaOrSubschemaConfig.transforms.concat(transforms) : transforms,
|
|
2747
|
+
transformedSchema,
|
|
2748
|
+
skipTypeMerging,
|
|
2749
|
+
onLocatedError,
|
|
2750
|
+
args
|
|
2751
|
+
};
|
|
2752
|
+
}
|
|
2753
|
+
return {
|
|
2754
|
+
subschema: schema,
|
|
2755
|
+
subschemaConfig: void 0,
|
|
2756
|
+
targetSchema: subschemaOrSubschemaConfig,
|
|
2757
|
+
operation,
|
|
2758
|
+
fieldName: targetFieldName,
|
|
2759
|
+
context: request.context,
|
|
2760
|
+
info,
|
|
2761
|
+
returnType: returnType ?? info?.returnType ?? getDelegationReturnType(
|
|
2762
|
+
subschemaOrSubschemaConfig,
|
|
2763
|
+
operation,
|
|
2764
|
+
targetFieldName
|
|
2765
|
+
),
|
|
2766
|
+
transforms,
|
|
2767
|
+
transformedSchema: transformedSchema ?? subschemaOrSubschemaConfig,
|
|
2768
|
+
skipTypeMerging
|
|
2769
|
+
};
|
|
2770
|
+
}
|
|
2771
|
+
function validateRequest(delegationContext, document) {
|
|
2772
|
+
const errors = validate(delegationContext.targetSchema, document);
|
|
2773
|
+
if (errors.length > 0) {
|
|
2774
|
+
if (errors.length > 1) {
|
|
2775
|
+
const combinedError = new AggregateError(
|
|
2776
|
+
errors,
|
|
2777
|
+
errors.map((error2) => error2.message).join(", \n")
|
|
2778
|
+
);
|
|
2779
|
+
throw combinedError;
|
|
2780
|
+
}
|
|
2781
|
+
const error = errors[0];
|
|
2782
|
+
if (error) {
|
|
2783
|
+
throw error.originalError || error;
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
const GLOBAL_CONTEXT = {};
|
|
2788
|
+
function getExecutor(delegationContext) {
|
|
2789
|
+
const { subschemaConfig, targetSchema, context } = delegationContext;
|
|
2790
|
+
let executor = subschemaConfig?.executor || executorFromSchema(targetSchema);
|
|
2791
|
+
if (subschemaConfig?.batch) {
|
|
2792
|
+
const batchingOptions = subschemaConfig?.batchingOptions;
|
|
2793
|
+
executor = getBatchingExecutor(
|
|
2794
|
+
context ?? GLOBAL_CONTEXT,
|
|
2795
|
+
executor,
|
|
2796
|
+
batchingOptions?.dataLoaderOptions,
|
|
2797
|
+
batchingOptions?.extensionsReducer
|
|
2798
|
+
);
|
|
2799
|
+
}
|
|
2800
|
+
return executor;
|
|
2801
|
+
}
|
|
2802
|
+
function setObjectKeyPath(obj, path, value) {
|
|
2803
|
+
let current = obj;
|
|
2804
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
2805
|
+
const key = path[i];
|
|
2806
|
+
if (key == null || key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
2807
|
+
return;
|
|
2808
|
+
}
|
|
2809
|
+
if (current[key] == null) {
|
|
2810
|
+
current[key] = typeof path[i + 1] === "number" ? [] : {};
|
|
2811
|
+
}
|
|
2812
|
+
current = current[key];
|
|
2813
|
+
}
|
|
2814
|
+
const lastKey = path[path.length - 1];
|
|
2815
|
+
if (lastKey == null || lastKey === "__proto__" || lastKey === "constructor" || lastKey === "prototype") {
|
|
2816
|
+
return;
|
|
2817
|
+
}
|
|
2818
|
+
const existingValue = current[lastKey];
|
|
2819
|
+
current[lastKey] = existingValue ? mergeDeep([existingValue, value]) : value;
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2822
|
+
function extractUnavailableFieldsFromSelectionSet(schema, fieldType, fieldSelectionSet, shouldAdd, fragments = {}) {
|
|
2823
|
+
if (isLeafType(fieldType)) {
|
|
2824
|
+
return [];
|
|
2825
|
+
}
|
|
2826
|
+
if (isUnionType(fieldType)) {
|
|
2827
|
+
const unavailableSelections2 = [];
|
|
2828
|
+
for (const type of fieldType.getTypes()) {
|
|
2829
|
+
const fieldSelectionExcluded = {
|
|
2830
|
+
...fieldSelectionSet,
|
|
2831
|
+
selections: fieldSelectionSet.selections.filter(
|
|
2832
|
+
(selection) => selection.kind === Kind.INLINE_FRAGMENT ? selection.typeCondition ? selection.typeCondition.name.value === type.name : false : true
|
|
2833
|
+
)
|
|
2834
|
+
};
|
|
2835
|
+
unavailableSelections2.push(
|
|
2836
|
+
...extractUnavailableFieldsFromSelectionSet(
|
|
2837
|
+
schema,
|
|
2838
|
+
type,
|
|
2839
|
+
fieldSelectionExcluded,
|
|
2840
|
+
shouldAdd,
|
|
2841
|
+
fragments
|
|
2842
|
+
)
|
|
2843
|
+
);
|
|
2844
|
+
}
|
|
2845
|
+
return unavailableSelections2;
|
|
2846
|
+
}
|
|
2847
|
+
const subFields = fieldType.getFields();
|
|
2848
|
+
const unavailableSelections = [];
|
|
2849
|
+
for (const selection of fieldSelectionSet.selections) {
|
|
2850
|
+
if (selection.kind === Kind.FIELD) {
|
|
2851
|
+
if (selection.name.value === "__typename") {
|
|
2852
|
+
continue;
|
|
2853
|
+
}
|
|
2854
|
+
const fieldName = selection.name.value;
|
|
2855
|
+
const selectionField = subFields[fieldName];
|
|
2856
|
+
if (!selectionField) {
|
|
2857
|
+
if (shouldAdd(fieldType, selection)) {
|
|
2858
|
+
unavailableSelections.push(selection);
|
|
2859
|
+
}
|
|
2860
|
+
} else {
|
|
2861
|
+
const unavailableSubFields = extractUnavailableFields(
|
|
2862
|
+
schema,
|
|
2863
|
+
selectionField,
|
|
2864
|
+
selection,
|
|
2865
|
+
shouldAdd,
|
|
2866
|
+
fragments
|
|
2867
|
+
);
|
|
2868
|
+
if (unavailableSubFields.length) {
|
|
2869
|
+
unavailableSelections.push({
|
|
2870
|
+
...selection,
|
|
2871
|
+
selectionSet: {
|
|
2872
|
+
kind: Kind.SELECTION_SET,
|
|
2873
|
+
selections: unavailableSubFields
|
|
2874
|
+
}
|
|
2875
|
+
});
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
} else if (selection.kind === Kind.INLINE_FRAGMENT) {
|
|
2879
|
+
const subFieldName = selection.typeCondition?.name.value || fieldType.name;
|
|
2880
|
+
const subFieldType = selection.typeCondition && schema.getType(subFieldName) || fieldType;
|
|
2881
|
+
if (subFieldName === fieldType.name || (isObjectType(subFieldType) || isInterfaceType(subFieldType)) && isAbstractType(fieldType) && schema.isSubType(fieldType, subFieldType)) {
|
|
2882
|
+
const unavailableFields = extractUnavailableFieldsFromSelectionSet(
|
|
2883
|
+
schema,
|
|
2884
|
+
subFieldType,
|
|
2885
|
+
selection.selectionSet,
|
|
2886
|
+
shouldAdd,
|
|
2887
|
+
fragments
|
|
2888
|
+
);
|
|
2889
|
+
if (unavailableFields.length) {
|
|
2890
|
+
unavailableSelections.push({
|
|
2891
|
+
...selection,
|
|
2892
|
+
selectionSet: {
|
|
2893
|
+
kind: Kind.SELECTION_SET,
|
|
2894
|
+
selections: unavailableFields
|
|
2895
|
+
}
|
|
2896
|
+
});
|
|
2897
|
+
}
|
|
2898
|
+
} else if (isObjectType(subFieldType) || isInterfaceType(subFieldType)) {
|
|
2899
|
+
const subFieldTypeFields = subFieldType.getFields();
|
|
2900
|
+
for (const subSelection of selection.selectionSet.selections) {
|
|
2901
|
+
if (subSelection.kind === Kind.FIELD) {
|
|
2902
|
+
const subSelectionFieldName = subSelection.name.value;
|
|
2903
|
+
if (subSelectionFieldName === "__typename") {
|
|
2904
|
+
continue;
|
|
2905
|
+
}
|
|
2906
|
+
const subSelectionField = subFieldTypeFields[subSelection.name.value];
|
|
2907
|
+
if (!subSelectionField) {
|
|
2908
|
+
if (shouldAdd(subFieldType, subSelection)) {
|
|
2909
|
+
unavailableSelections.push(subSelection);
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
} else if (selection.kind === Kind.FRAGMENT_SPREAD) {
|
|
2916
|
+
const fragment = fragments[selection.name.value];
|
|
2917
|
+
if (fragment) {
|
|
2918
|
+
const fragmentUnavailableFields = extractUnavailableFieldsFromSelectionSet(
|
|
2919
|
+
schema,
|
|
2920
|
+
fieldType,
|
|
2921
|
+
{
|
|
2922
|
+
kind: Kind.SELECTION_SET,
|
|
2923
|
+
selections: [
|
|
2924
|
+
{
|
|
2925
|
+
kind: Kind.INLINE_FRAGMENT,
|
|
2926
|
+
typeCondition: {
|
|
2927
|
+
kind: Kind.NAMED_TYPE,
|
|
2928
|
+
name: {
|
|
2929
|
+
kind: Kind.NAME,
|
|
2930
|
+
value: fragment.typeCondition.name.value
|
|
2931
|
+
}
|
|
2932
|
+
},
|
|
2933
|
+
selectionSet: fragment.selectionSet
|
|
2934
|
+
}
|
|
2935
|
+
]
|
|
2936
|
+
},
|
|
2937
|
+
shouldAdd,
|
|
2938
|
+
fragments
|
|
2939
|
+
);
|
|
2940
|
+
if (fragmentUnavailableFields.length) {
|
|
2941
|
+
unavailableSelections.push(...fragmentUnavailableFields);
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
return unavailableSelections;
|
|
2947
|
+
}
|
|
2948
|
+
function extractUnavailableFields(schema, field, fieldNode, shouldAdd, fragments = {}) {
|
|
2949
|
+
if (fieldNode.selectionSet) {
|
|
2950
|
+
const fieldType = getNamedType(field.type);
|
|
2951
|
+
return extractUnavailableFieldsFromSelectionSet(
|
|
2952
|
+
schema,
|
|
2953
|
+
fieldType,
|
|
2954
|
+
fieldNode.selectionSet,
|
|
2955
|
+
shouldAdd,
|
|
2956
|
+
fragments
|
|
2957
|
+
);
|
|
2958
|
+
}
|
|
2959
|
+
return [];
|
|
2960
|
+
}
|
|
2961
|
+
function subtractSelectionSets(selectionSetA, selectionSetB) {
|
|
2962
|
+
const newSelections = [];
|
|
2963
|
+
for (const selectionA of selectionSetA.selections) {
|
|
2964
|
+
switch (selectionA.kind) {
|
|
2965
|
+
case Kind.FIELD: {
|
|
2966
|
+
const fieldA = selectionA;
|
|
2967
|
+
const fieldsInOtherSelectionSet = selectionSetB.selections.filter(
|
|
2968
|
+
(subselectionB) => {
|
|
2969
|
+
if (subselectionB.kind !== Kind.FIELD) {
|
|
2970
|
+
return false;
|
|
2971
|
+
}
|
|
2972
|
+
return fieldA.name.value === subselectionB.name.value;
|
|
2973
|
+
}
|
|
2974
|
+
);
|
|
2975
|
+
if (fieldsInOtherSelectionSet.length > 0 && fieldA.selectionSet?.selections?.length) {
|
|
2976
|
+
const newSubSelection = fieldsInOtherSelectionSet.reduce(
|
|
2977
|
+
(acc, fieldB) => fieldB.selectionSet ? subtractSelectionSets(acc, fieldB.selectionSet) : acc,
|
|
2978
|
+
{
|
|
2979
|
+
kind: Kind.SELECTION_SET,
|
|
2980
|
+
selections: fieldA.selectionSet.selections
|
|
2981
|
+
}
|
|
2982
|
+
);
|
|
2983
|
+
if (newSubSelection.selections.length) {
|
|
2984
|
+
newSelections.push({
|
|
2985
|
+
...fieldA,
|
|
2986
|
+
selectionSet: newSubSelection
|
|
2987
|
+
});
|
|
2988
|
+
}
|
|
2989
|
+
} else if (fieldsInOtherSelectionSet.length === 0) {
|
|
2990
|
+
newSelections.push(selectionA);
|
|
2991
|
+
}
|
|
2992
|
+
break;
|
|
2993
|
+
}
|
|
2994
|
+
case Kind.INLINE_FRAGMENT: {
|
|
2995
|
+
const inlineFragmentA = selectionA;
|
|
2996
|
+
const inlineFragmentsFromB = selectionSetB.selections.filter(
|
|
2997
|
+
(subselectionB) => {
|
|
2998
|
+
if (subselectionB.kind !== Kind.INLINE_FRAGMENT) {
|
|
2999
|
+
return false;
|
|
3000
|
+
}
|
|
3001
|
+
const inlineFragmentB = subselectionB;
|
|
3002
|
+
return inlineFragmentA.typeCondition?.name.value === inlineFragmentB.typeCondition?.name.value;
|
|
3003
|
+
}
|
|
3004
|
+
);
|
|
3005
|
+
if (inlineFragmentsFromB.length > 0) {
|
|
3006
|
+
const newSubSelection = inlineFragmentsFromB.reduce(
|
|
3007
|
+
(acc, subselectionB) => subselectionB.selectionSet ? subtractSelectionSets(acc, subselectionB.selectionSet) : acc,
|
|
3008
|
+
{
|
|
3009
|
+
kind: Kind.SELECTION_SET,
|
|
3010
|
+
selections: inlineFragmentA.selectionSet.selections
|
|
3011
|
+
}
|
|
3012
|
+
);
|
|
3013
|
+
if (newSubSelection.selections.length) {
|
|
3014
|
+
if (newSubSelection.selections.length === 1) {
|
|
3015
|
+
const onlySelection = newSubSelection.selections[0];
|
|
3016
|
+
if (onlySelection?.kind === Kind.FIELD) {
|
|
3017
|
+
const responseKey = onlySelection.alias?.value || onlySelection.name.value;
|
|
3018
|
+
if (responseKey === "__typename") {
|
|
3019
|
+
continue;
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
newSelections.push({
|
|
3024
|
+
...inlineFragmentA,
|
|
3025
|
+
selectionSet: newSubSelection
|
|
3026
|
+
});
|
|
3027
|
+
}
|
|
3028
|
+
} else {
|
|
3029
|
+
newSelections.push(selectionA);
|
|
3030
|
+
}
|
|
3031
|
+
break;
|
|
3032
|
+
}
|
|
3033
|
+
case Kind.FRAGMENT_SPREAD: {
|
|
3034
|
+
const fragmentSpreadA = selectionA;
|
|
3035
|
+
if (!selectionSetB.selections.some(
|
|
3036
|
+
(subselectionB) => subselectionB.kind === Kind.FRAGMENT_SPREAD && subselectionB.name.value === fragmentSpreadA.name.value
|
|
3037
|
+
)) {
|
|
3038
|
+
newSelections.push(selectionA);
|
|
3039
|
+
}
|
|
3040
|
+
break;
|
|
3041
|
+
}
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
return {
|
|
3045
|
+
kind: Kind.SELECTION_SET,
|
|
3046
|
+
selections: newSelections
|
|
3047
|
+
};
|
|
3048
|
+
}
|
|
3049
|
+
|
|
3050
|
+
export { EMPTY_ARRAY, EMPTY_OBJECT, FIELD_SUBSCHEMA_MAP_SYMBOL, OBJECT_SUBSCHEMA_SYMBOL, PLAN_LEFT_OVER, Subschema, Transformer, UNPATHED_ERRORS_SYMBOL, annotateExternalObject, applySchemaTransforms, cloneSubschemaConfig, createRequest, defaultMergedResolver, delegateRequest, delegateToSchema, extractUnavailableFields, extractUnavailableFieldsFromSelectionSet, getActualFieldNodes, getDelegatingOperation, getPlanLeftOverFromParent, getSubschema, getTypeInfo, getTypeInfoWithType, getUnpathedErrors, handleOverrideByDelegation, handleResolverResult, isExternalObject, isPrototypePollutingKey, isSubschema, isSubschemaConfig, leftOverByDelegationPlan, mergeFields, resolveExternalValue, subtractSelectionSets };
|