UNPKG

73.1 kBJavaScriptView Raw
1import { Kind, TypeInfo, visit, visitWithTypeInfo, getNamedType, isObjectType, isAbstractType, isInterfaceType, TypeNameMetaFieldDef, responsePathAsArray, GraphQLError, locatedError, getNullableType, isCompositeType, isListType, isLeafType, typeFromAST, defaultFieldResolver, getOperationAST, validate, subscribe, execute } from 'graphql';
2import { implementsAbstractType, getRootTypeNames, getDefinedRootType, createVariableNameGenerator, updateArgument, serializeInputValue, relocatedError, AggregateError, getResponseKeyFromInfo, isAsyncIterable, mapAsyncIterator } from '@graphql-tools/utils';
3import { collectFields } from 'graphql/execution/execute.js';
4import { ValueOrPromise } from 'value-or-promise';
5import { getBatchingExecutor } from '@graphql-tools/batch-execute';
6
7function applySchemaTransforms(originalWrappingSchema, subschemaConfig, transformedSchema) {
8 const schemaTransforms = subschemaConfig.transforms;
9 if (schemaTransforms == null) {
10 return originalWrappingSchema;
11 }
12 return schemaTransforms.reduce((schema, transform) => transform.transformSchema != null
13 ? transform.transformSchema(schema, subschemaConfig, transformedSchema)
14 : schema, originalWrappingSchema);
15}
16
17function isSubschema(value) {
18 return Boolean(value.transformedSchema);
19}
20class Subschema {
21 constructor(config) {
22 var _a;
23 this.schema = config.schema;
24 this.executor = config.executor;
25 this.batch = config.batch;
26 this.batchingOptions = config.batchingOptions;
27 this.createProxyingResolver = config.createProxyingResolver;
28 this.transforms = (_a = config.transforms) !== null && _a !== void 0 ? _a : [];
29 this.transformedSchema = applySchemaTransforms(this.schema, config);
30 this.merge = config.merge;
31 }
32}
33
34function memoizeInfoAnd2Objects(fn) {
35 let cache1;
36 function memoized(a1, a2, a3) {
37 if (!cache1) {
38 cache1 = new WeakMap();
39 const cache2 = new WeakMap();
40 cache1.set(a1.fieldNodes, cache2);
41 const cache3 = new WeakMap();
42 cache2.set(a2, cache3);
43 const newValue = fn(a1, a2, a3);
44 cache3.set(a3, newValue);
45 return newValue;
46 }
47 let cache2 = cache1.get(a1.fieldNodes);
48 if (!cache2) {
49 cache2 = new WeakMap();
50 cache1.set(a1.fieldNodes, cache2);
51 const cache3 = new WeakMap();
52 cache2.set(a2, cache3);
53 const newValue = fn(a1, a2, a3);
54 cache3.set(a3, newValue);
55 return newValue;
56 }
57 let cache3 = cache2.get(a2);
58 if (!cache3) {
59 cache3 = new WeakMap();
60 cache2.set(a2, cache3);
61 const newValue = fn(a1, a2, a3);
62 cache3.set(a3, newValue);
63 return newValue;
64 }
65 const cachedValue = cache3.get(a3);
66 if (cachedValue === undefined) {
67 const newValue = fn(a1, a2, a3);
68 cache3.set(a3, newValue);
69 return newValue;
70 }
71 return cachedValue;
72 }
73 return memoized;
74}
75function memoize4(fn) {
76 let cache1;
77 function memoized(a1, a2, a3, a4) {
78 if (!cache1) {
79 cache1 = new WeakMap();
80 const cache2 = new WeakMap();
81 cache1.set(a1, cache2);
82 const cache3 = new WeakMap();
83 cache2.set(a2, cache3);
84 const cache4 = new WeakMap();
85 cache3.set(a3, cache4);
86 const newValue = fn(a1, a2, a3, a4);
87 cache4.set(a4, newValue);
88 return newValue;
89 }
90 let cache2 = cache1.get(a1);
91 if (!cache2) {
92 cache2 = new WeakMap();
93 cache1.set(a1, cache2);
94 const cache3 = new WeakMap();
95 cache2.set(a2, cache3);
96 const cache4 = new WeakMap();
97 cache3.set(a3, cache4);
98 const newValue = fn(a1, a2, a3, a4);
99 cache4.set(a4, newValue);
100 return newValue;
101 }
102 let cache3 = cache2.get(a2);
103 if (!cache3) {
104 cache3 = new WeakMap();
105 cache2.set(a2, cache3);
106 const cache4 = new WeakMap();
107 cache3.set(a3, cache4);
108 const newValue = fn(a1, a2, a3, a4);
109 cache4.set(a4, newValue);
110 return newValue;
111 }
112 const cache4 = cache3.get(a3);
113 if (!cache4) {
114 const cache4 = new WeakMap();
115 cache3.set(a3, cache4);
116 const newValue = fn(a1, a2, a3, a4);
117 cache4.set(a4, newValue);
118 return newValue;
119 }
120 const cachedValue = cache4.get(a4);
121 if (cachedValue === undefined) {
122 const newValue = fn(a1, a2, a3, a4);
123 cache4.set(a4, newValue);
124 return newValue;
125 }
126 return cachedValue;
127 }
128 return memoized;
129}
130function memoize3(fn) {
131 let cache1;
132 function memoized(a1, a2, a3) {
133 if (!cache1) {
134 cache1 = new WeakMap();
135 const cache2 = new WeakMap();
136 cache1.set(a1, cache2);
137 const cache3 = new WeakMap();
138 cache2.set(a2, cache3);
139 const newValue = fn(a1, a2, a3);
140 cache3.set(a3, newValue);
141 return newValue;
142 }
143 let cache2 = cache1.get(a1);
144 if (!cache2) {
145 cache2 = new WeakMap();
146 cache1.set(a1, cache2);
147 const cache3 = new WeakMap();
148 cache2.set(a2, cache3);
149 const newValue = fn(a1, a2, a3);
150 cache3.set(a3, newValue);
151 return newValue;
152 }
153 let cache3 = cache2.get(a2);
154 if (!cache3) {
155 cache3 = new WeakMap();
156 cache2.set(a2, cache3);
157 const newValue = fn(a1, a2, a3);
158 cache3.set(a3, newValue);
159 return newValue;
160 }
161 const cachedValue = cache3.get(a3);
162 if (cachedValue === undefined) {
163 const newValue = fn(a1, a2, a3);
164 cache3.set(a3, newValue);
165 return newValue;
166 }
167 return cachedValue;
168 }
169 return memoized;
170}
171function memoize2(fn) {
172 let cache1;
173 function memoized(a1, a2) {
174 if (!cache1) {
175 cache1 = new WeakMap();
176 const cache2 = new WeakMap();
177 cache1.set(a1, cache2);
178 const newValue = fn(a1, a2);
179 cache2.set(a2, newValue);
180 return newValue;
181 }
182 let cache2 = cache1.get(a1);
183 if (!cache2) {
184 cache2 = new WeakMap();
185 cache1.set(a1, cache2);
186 const newValue = fn(a1, a2);
187 cache2.set(a2, newValue);
188 return newValue;
189 }
190 const cachedValue = cache2.get(a2);
191 if (cachedValue === undefined) {
192 const newValue = fn(a1, a2);
193 cache2.set(a2, newValue);
194 return newValue;
195 }
196 return cachedValue;
197 }
198 return memoized;
199}
200
201function getDocumentMetadata(document) {
202 const operations = [];
203 const fragments = [];
204 const fragmentNames = new Set();
205 for (let i = 0; i < document.definitions.length; i++) {
206 const def = document.definitions[i];
207 if (def.kind === Kind.FRAGMENT_DEFINITION) {
208 fragments.push(def);
209 fragmentNames.add(def.name.value);
210 }
211 else if (def.kind === Kind.OPERATION_DEFINITION) {
212 operations.push(def);
213 }
214 }
215 return {
216 operations,
217 fragments,
218 fragmentNames,
219 };
220}
221
222function prepareGatewayDocument(originalDocument, transformedSchema, returnType, infoSchema) {
223 const wrappedConcreteTypesDocument = wrapConcreteTypes(returnType, transformedSchema, originalDocument);
224 if (infoSchema == null) {
225 return wrappedConcreteTypesDocument;
226 }
227 const { possibleTypesMap, reversePossibleTypesMap, interfaceExtensionsMap, fieldNodesByType, fieldNodesByField, dynamicSelectionSetsByField, } = getSchemaMetaData(infoSchema, transformedSchema);
228 const { operations, fragments, fragmentNames } = getDocumentMetadata(wrappedConcreteTypesDocument);
229 const { expandedFragments, fragmentReplacements } = getExpandedFragments(fragments, fragmentNames, possibleTypesMap);
230 const typeInfo = new TypeInfo(transformedSchema);
231 const expandedDocument = {
232 kind: Kind.DOCUMENT,
233 definitions: [...operations, ...fragments, ...expandedFragments],
234 };
235 return visit(expandedDocument, visitWithTypeInfo(typeInfo, {
236 [Kind.SELECTION_SET]: node => visitSelectionSet(node, fragmentReplacements, transformedSchema, typeInfo, possibleTypesMap, reversePossibleTypesMap, interfaceExtensionsMap, fieldNodesByType, fieldNodesByField, dynamicSelectionSetsByField),
237 }),
238 // visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
239 // empty keys cannot be removed only because of typescript errors
240 // will hopefully be fixed in future version of graphql-js to be optional
241 {
242 Name: [],
243 Document: ['definitions'],
244 OperationDefinition: ['selectionSet'],
245 VariableDefinition: [],
246 Variable: [],
247 SelectionSet: ['selections'],
248 Field: ['selectionSet'],
249 Argument: [],
250 FragmentSpread: [],
251 InlineFragment: ['selectionSet'],
252 FragmentDefinition: ['selectionSet'],
253 IntValue: [],
254 FloatValue: [],
255 StringValue: [],
256 BooleanValue: [],
257 NullValue: [],
258 EnumValue: [],
259 ListValue: [],
260 ObjectValue: [],
261 ObjectField: [],
262 Directive: [],
263 NamedType: [],
264 ListType: [],
265 NonNullType: [],
266 SchemaDefinition: [],
267 OperationTypeDefinition: [],
268 ScalarTypeDefinition: [],
269 ObjectTypeDefinition: [],
270 FieldDefinition: [],
271 InputValueDefinition: [],
272 InterfaceTypeDefinition: [],
273 UnionTypeDefinition: [],
274 EnumTypeDefinition: [],
275 EnumValueDefinition: [],
276 InputObjectTypeDefinition: [],
277 DirectiveDefinition: [],
278 SchemaExtension: [],
279 ScalarTypeExtension: [],
280 ObjectTypeExtension: [],
281 InterfaceTypeExtension: [],
282 UnionTypeExtension: [],
283 EnumTypeExtension: [],
284 InputObjectTypeExtension: [],
285 });
286}
287function visitSelectionSet(node, fragmentReplacements, schema, typeInfo, possibleTypesMap, reversePossibleTypesMap, interfaceExtensionsMap, fieldNodesByType, fieldNodesByField, dynamicSelectionSetsByField) {
288 var _a, _b;
289 const newSelections = new Set();
290 const maybeType = typeInfo.getParentType();
291 if (maybeType != null) {
292 const parentType = getNamedType(maybeType);
293 const parentTypeName = parentType.name;
294 const fieldNodes = fieldNodesByType[parentTypeName];
295 if (fieldNodes) {
296 for (const fieldNode of fieldNodes) {
297 newSelections.add(fieldNode);
298 }
299 }
300 const interfaceExtensions = interfaceExtensionsMap[parentType.name];
301 const interfaceExtensionFields = [];
302 for (const selection of node.selections) {
303 if (selection.kind === Kind.INLINE_FRAGMENT) {
304 if (selection.typeCondition != null) {
305 const possibleTypes = possibleTypesMap[selection.typeCondition.name.value];
306 if (possibleTypes == null) {
307 newSelections.add(selection);
308 continue;
309 }
310 for (const possibleTypeName of possibleTypes) {
311 const maybePossibleType = schema.getType(possibleTypeName);
312 if (maybePossibleType != null && implementsAbstractType(schema, parentType, maybePossibleType)) {
313 newSelections.add(generateInlineFragment(possibleTypeName, selection.selectionSet));
314 }
315 }
316 }
317 }
318 else if (selection.kind === Kind.FRAGMENT_SPREAD) {
319 const fragmentName = selection.name.value;
320 if (!fragmentReplacements[fragmentName]) {
321 newSelections.add(selection);
322 continue;
323 }
324 for (const replacement of fragmentReplacements[fragmentName]) {
325 const typeName = replacement.typeName;
326 const maybeReplacementType = schema.getType(typeName);
327 if (maybeReplacementType != null && implementsAbstractType(schema, parentType, maybeType)) {
328 newSelections.add({
329 kind: Kind.FRAGMENT_SPREAD,
330 name: {
331 kind: Kind.NAME,
332 value: replacement.fragmentName,
333 },
334 });
335 }
336 }
337 }
338 else {
339 const fieldName = selection.name.value;
340 const fieldNodes = (_a = fieldNodesByField[parentTypeName]) === null || _a === void 0 ? void 0 : _a[fieldName];
341 if (fieldNodes != null) {
342 for (const fieldNode of fieldNodes) {
343 newSelections.add(fieldNode);
344 }
345 }
346 const dynamicSelectionSets = (_b = dynamicSelectionSetsByField[parentTypeName]) === null || _b === void 0 ? void 0 : _b[fieldName];
347 if (dynamicSelectionSets != null) {
348 for (const selectionSetFn of dynamicSelectionSets) {
349 const selectionSet = selectionSetFn(selection);
350 if (selectionSet != null) {
351 for (const selection of selectionSet.selections) {
352 newSelections.add(selection);
353 }
354 }
355 }
356 }
357 if (interfaceExtensions === null || interfaceExtensions === void 0 ? void 0 : interfaceExtensions[fieldName]) {
358 interfaceExtensionFields.push(selection);
359 }
360 else {
361 newSelections.add(selection);
362 }
363 }
364 }
365 if (reversePossibleTypesMap[parentType.name]) {
366 newSelections.add({
367 kind: Kind.FIELD,
368 name: {
369 kind: Kind.NAME,
370 value: '__typename',
371 },
372 });
373 }
374 if (interfaceExtensionFields.length) {
375 const possibleTypes = possibleTypesMap[parentType.name];
376 if (possibleTypes != null) {
377 for (const possibleType of possibleTypes) {
378 newSelections.add(generateInlineFragment(possibleType, {
379 kind: Kind.SELECTION_SET,
380 selections: interfaceExtensionFields,
381 }));
382 }
383 }
384 }
385 return {
386 ...node,
387 selections: Array.from(newSelections),
388 };
389 }
390 return node;
391}
392function generateInlineFragment(typeName, selectionSet) {
393 return {
394 kind: Kind.INLINE_FRAGMENT,
395 typeCondition: {
396 kind: Kind.NAMED_TYPE,
397 name: {
398 kind: Kind.NAME,
399 value: typeName,
400 },
401 },
402 selectionSet,
403 };
404}
405const getSchemaMetaData = memoize2((sourceSchema, targetSchema) => {
406 var _a, _b, _c, _d, _e, _f, _g, _h, _j;
407 const typeMap = sourceSchema.getTypeMap();
408 const targetTypeMap = targetSchema.getTypeMap();
409 const possibleTypesMap = Object.create(null);
410 const interfaceExtensionsMap = Object.create(null);
411 for (const typeName in typeMap) {
412 const type = typeMap[typeName];
413 if (isAbstractType(type)) {
414 const targetType = targetTypeMap[typeName];
415 if (isInterfaceType(type) && isInterfaceType(targetType)) {
416 const targetTypeFields = targetType.getFields();
417 const sourceTypeFields = type.getFields();
418 const extensionFields = Object.create(null);
419 let isExtensionFieldsEmpty = true;
420 for (const fieldName in sourceTypeFields) {
421 if (!targetTypeFields[fieldName]) {
422 extensionFields[fieldName] = true;
423 isExtensionFieldsEmpty = false;
424 }
425 }
426 if (!isExtensionFieldsEmpty) {
427 interfaceExtensionsMap[typeName] = extensionFields;
428 }
429 }
430 if (interfaceExtensionsMap[typeName] || !isAbstractType(targetType)) {
431 const implementations = sourceSchema.getPossibleTypes(type);
432 possibleTypesMap[typeName] = [];
433 for (const impl of implementations) {
434 if (targetTypeMap[impl.name]) {
435 possibleTypesMap[typeName].push(impl.name);
436 }
437 }
438 }
439 }
440 }
441 return {
442 possibleTypesMap,
443 reversePossibleTypesMap: reversePossibleTypesMap(possibleTypesMap),
444 interfaceExtensionsMap,
445 fieldNodesByType: (_c = (_b = (_a = sourceSchema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo']) === null || _b === void 0 ? void 0 : _b.fieldNodesByType) !== null && _c !== void 0 ? _c : {},
446 fieldNodesByField: (_f = (_e = (_d = sourceSchema.extensions) === null || _d === void 0 ? void 0 : _d['stitchingInfo']) === null || _e === void 0 ? void 0 : _e.fieldNodesByField) !== null && _f !== void 0 ? _f : {},
447 dynamicSelectionSetsByField: (_j = (_h = (_g = sourceSchema.extensions) === null || _g === void 0 ? void 0 : _g['stitchingInfo']) === null || _h === void 0 ? void 0 : _h.dynamicSelectionSetsByField) !== null && _j !== void 0 ? _j : {},
448 };
449});
450function reversePossibleTypesMap(possibleTypesMap) {
451 const result = Object.create(null);
452 for (const typeName in possibleTypesMap) {
453 const toTypeNames = possibleTypesMap[typeName];
454 for (const toTypeName of toTypeNames) {
455 if (!result[toTypeName]) {
456 result[toTypeName] = [];
457 }
458 result[toTypeName].push(typeName);
459 }
460 }
461 return result;
462}
463function getExpandedFragments(fragments, fragmentNames, possibleTypesMap) {
464 let fragmentCounter = 0;
465 function generateFragmentName(typeName) {
466 let fragmentName;
467 do {
468 fragmentName = `_${typeName}_Fragment${fragmentCounter.toString()}`;
469 fragmentCounter++;
470 } while (fragmentNames.has(fragmentName));
471 return fragmentName;
472 }
473 const expandedFragments = [];
474 const fragmentReplacements = Object.create(null);
475 for (const fragment of fragments) {
476 const possibleTypes = possibleTypesMap[fragment.typeCondition.name.value];
477 if (possibleTypes != null) {
478 const fragmentName = fragment.name.value;
479 fragmentReplacements[fragmentName] = [];
480 for (const possibleTypeName of possibleTypes) {
481 const name = generateFragmentName(possibleTypeName);
482 fragmentNames.add(name);
483 expandedFragments.push({
484 kind: Kind.FRAGMENT_DEFINITION,
485 name: {
486 kind: Kind.NAME,
487 value: name,
488 },
489 typeCondition: {
490 kind: Kind.NAMED_TYPE,
491 name: {
492 kind: Kind.NAME,
493 value: possibleTypeName,
494 },
495 },
496 selectionSet: fragment.selectionSet,
497 });
498 fragmentReplacements[fragmentName].push({
499 fragmentName: name,
500 typeName: possibleTypeName,
501 });
502 }
503 }
504 }
505 return {
506 expandedFragments,
507 fragmentReplacements,
508 };
509}
510function wrapConcreteTypes(returnType, targetSchema, document) {
511 const namedType = getNamedType(returnType);
512 if (!isObjectType(namedType)) {
513 return document;
514 }
515 const rootTypeNames = getRootTypeNames(targetSchema);
516 const typeInfo = new TypeInfo(targetSchema);
517 return visit(document, visitWithTypeInfo(typeInfo, {
518 [Kind.FRAGMENT_DEFINITION]: (node) => {
519 const typeName = node.typeCondition.name.value;
520 if (!rootTypeNames.has(typeName)) {
521 return false;
522 }
523 },
524 [Kind.FIELD]: (node) => {
525 const type = typeInfo.getType();
526 if (type != null && isAbstractType(getNamedType(type))) {
527 return {
528 ...node,
529 selectionSet: {
530 kind: Kind.SELECTION_SET,
531 selections: [
532 {
533 kind: Kind.INLINE_FRAGMENT,
534 typeCondition: {
535 kind: Kind.NAMED_TYPE,
536 name: {
537 kind: Kind.NAME,
538 value: namedType.name,
539 },
540 },
541 selectionSet: node.selectionSet,
542 },
543 ],
544 },
545 };
546 }
547 },
548 }),
549 // visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
550 // empty keys cannot be removed only because of typescript errors
551 // will hopefully be fixed in future version of graphql-js to be optional
552 {
553 Name: [],
554 Document: ['definitions'],
555 OperationDefinition: ['selectionSet'],
556 VariableDefinition: [],
557 Variable: [],
558 SelectionSet: ['selections'],
559 Field: [],
560 Argument: [],
561 FragmentSpread: [],
562 InlineFragment: ['selectionSet'],
563 FragmentDefinition: ['selectionSet'],
564 IntValue: [],
565 FloatValue: [],
566 StringValue: [],
567 BooleanValue: [],
568 NullValue: [],
569 EnumValue: [],
570 ListValue: [],
571 ObjectValue: [],
572 ObjectField: [],
573 Directive: [],
574 NamedType: [],
575 ListType: [],
576 NonNullType: [],
577 SchemaDefinition: [],
578 OperationTypeDefinition: [],
579 ScalarTypeDefinition: [],
580 ObjectTypeDefinition: [],
581 FieldDefinition: [],
582 InputValueDefinition: [],
583 InterfaceTypeDefinition: [],
584 UnionTypeDefinition: [],
585 EnumTypeDefinition: [],
586 EnumValueDefinition: [],
587 InputObjectTypeDefinition: [],
588 DirectiveDefinition: [],
589 SchemaExtension: [],
590 ScalarTypeExtension: [],
591 ObjectTypeExtension: [],
592 InterfaceTypeExtension: [],
593 UnionTypeExtension: [],
594 EnumTypeExtension: [],
595 InputObjectTypeExtension: [],
596 });
597}
598
599function finalizeGatewayDocument(targetSchema, fragments, operations) {
600 var _a;
601 let usedVariables = [];
602 let usedFragments = [];
603 const newOperations = [];
604 let newFragments = [];
605 const validFragments = [];
606 const validFragmentsWithType = Object.create(null);
607 for (const fragment of fragments) {
608 const typeName = fragment.typeCondition.name.value;
609 const type = targetSchema.getType(typeName);
610 if (type != null) {
611 validFragments.push(fragment);
612 validFragmentsWithType[fragment.name.value] = type;
613 }
614 }
615 let fragmentSet = Object.create(null);
616 for (const operation of operations) {
617 const type = getDefinedRootType(targetSchema, operation.operation);
618 const { selectionSet, usedFragments: operationUsedFragments, usedVariables: operationUsedVariables, } = finalizeSelectionSet(targetSchema, type, validFragmentsWithType, operation.selectionSet);
619 usedFragments = union(usedFragments, operationUsedFragments);
620 const { usedVariables: collectedUsedVariables, newFragments: collectedNewFragments, fragmentSet: collectedFragmentSet, } = collectFragmentVariables(targetSchema, fragmentSet, validFragments, validFragmentsWithType, usedFragments);
621 const operationOrFragmentVariables = union(operationUsedVariables, collectedUsedVariables);
622 usedVariables = union(usedVariables, operationOrFragmentVariables);
623 newFragments = collectedNewFragments;
624 fragmentSet = collectedFragmentSet;
625 const variableDefinitions = ((_a = operation.variableDefinitions) !== null && _a !== void 0 ? _a : []).filter((variable) => operationOrFragmentVariables.indexOf(variable.variable.name.value) !== -1);
626 newOperations.push({
627 kind: Kind.OPERATION_DEFINITION,
628 operation: operation.operation,
629 name: operation.name,
630 directives: operation.directives,
631 variableDefinitions,
632 selectionSet,
633 });
634 }
635 return {
636 usedVariables,
637 newDocument: {
638 kind: Kind.DOCUMENT,
639 definitions: [...newOperations, ...newFragments],
640 },
641 };
642}
643function finalizeGatewayRequest(originalRequest, delegationContext) {
644 let { document, variables } = originalRequest;
645 let { operations, fragments } = getDocumentMetadata(document);
646 const { targetSchema, args } = delegationContext;
647 if (args) {
648 const requestWithNewVariables = addVariablesToRootFields(targetSchema, operations, args);
649 operations = requestWithNewVariables.newOperations;
650 variables = Object.assign({}, variables !== null && variables !== void 0 ? variables : {}, requestWithNewVariables.newVariables);
651 }
652 const { usedVariables, newDocument } = finalizeGatewayDocument(targetSchema, fragments, operations);
653 const newVariables = {};
654 if (variables != null) {
655 for (const variableName of usedVariables) {
656 const variableValue = variables[variableName];
657 if (variableValue !== undefined) {
658 newVariables[variableName] = variableValue;
659 }
660 }
661 }
662 return {
663 ...originalRequest,
664 document: newDocument,
665 variables: newVariables,
666 };
667}
668function addVariablesToRootFields(targetSchema, operations, args) {
669 const newVariables = Object.create(null);
670 const newOperations = operations.map((operation) => {
671 var _a, _b;
672 const variableDefinitionMap = ((_a = operation.variableDefinitions) !== null && _a !== void 0 ? _a : []).reduce((prev, def) => ({
673 ...prev,
674 [def.variable.name.value]: def,
675 }), {});
676 const type = getDefinedRootType(targetSchema, operation.operation);
677 const newSelectionSet = [];
678 for (const selection of operation.selectionSet.selections) {
679 if (selection.kind === Kind.FIELD) {
680 const argumentNodes = (_b = selection.arguments) !== null && _b !== void 0 ? _b : [];
681 const argumentNodeMap = argumentNodes.reduce((prev, argument) => ({
682 ...prev,
683 [argument.name.value]: argument,
684 }), {});
685 const targetField = type.getFields()[selection.name.value];
686 // excludes __typename
687 if (targetField != null) {
688 updateArguments(targetField, argumentNodeMap, variableDefinitionMap, newVariables, args);
689 }
690 newSelectionSet.push({
691 ...selection,
692 arguments: Object.values(argumentNodeMap),
693 });
694 }
695 else {
696 newSelectionSet.push(selection);
697 }
698 }
699 return {
700 ...operation,
701 variableDefinitions: Object.values(variableDefinitionMap),
702 selectionSet: {
703 kind: Kind.SELECTION_SET,
704 selections: newSelectionSet,
705 },
706 };
707 });
708 return {
709 newOperations,
710 newVariables,
711 };
712}
713function updateArguments(targetField, argumentNodeMap, variableDefinitionMap, variableValues, newArgs) {
714 const generateVariableName = createVariableNameGenerator(variableDefinitionMap);
715 for (const argument of targetField.args) {
716 const argName = argument.name;
717 const argType = argument.type;
718 if (argName in newArgs) {
719 updateArgument(argumentNodeMap, variableDefinitionMap, variableValues, argName, generateVariableName(argName), argType, serializeInputValue(argType, newArgs[argName]));
720 }
721 }
722}
723function collectFragmentVariables(targetSchema, fragmentSet, validFragments, validFragmentsWithType, usedFragments) {
724 let remainingFragments = usedFragments.slice();
725 let usedVariables = [];
726 const newFragments = [];
727 while (remainingFragments.length !== 0) {
728 const nextFragmentName = remainingFragments.pop();
729 const fragment = validFragments.find(fr => fr.name.value === nextFragmentName);
730 if (fragment != null) {
731 const name = nextFragmentName;
732 const typeName = fragment.typeCondition.name.value;
733 const type = targetSchema.getType(typeName);
734 if (type == null) {
735 throw new Error(`Fragment reference type "${typeName}", but the type is not contained within the target schema.`);
736 }
737 const { selectionSet, usedFragments: fragmentUsedFragments, usedVariables: fragmentUsedVariables, } = finalizeSelectionSet(targetSchema, type, validFragmentsWithType, fragment.selectionSet);
738 remainingFragments = union(remainingFragments, fragmentUsedFragments);
739 usedVariables = union(usedVariables, fragmentUsedVariables);
740 if (name && !(name in fragmentSet)) {
741 fragmentSet[name] = true;
742 newFragments.push({
743 kind: Kind.FRAGMENT_DEFINITION,
744 name: {
745 kind: Kind.NAME,
746 value: name,
747 },
748 typeCondition: fragment.typeCondition,
749 selectionSet,
750 });
751 }
752 }
753 }
754 return {
755 usedVariables,
756 newFragments,
757 fragmentSet,
758 };
759}
760const filteredSelectionSetVisitorKeys = {
761 SelectionSet: ['selections'],
762 Field: ['selectionSet'],
763 InlineFragment: ['selectionSet'],
764 FragmentDefinition: ['selectionSet'],
765};
766const variablesVisitorKeys = {
767 SelectionSet: ['selections'],
768 Field: ['arguments', 'directives', 'selectionSet'],
769 Argument: ['value'],
770 InlineFragment: ['directives', 'selectionSet'],
771 FragmentSpread: ['directives'],
772 FragmentDefinition: ['selectionSet'],
773 ObjectValue: ['fields'],
774 ObjectField: ['name', 'value'],
775 Directive: ['arguments'],
776};
777function finalizeSelectionSet(schema, type, validFragments, selectionSet) {
778 const usedFragments = [];
779 const usedVariables = [];
780 const typeInfo = new TypeInfo(schema, undefined, type);
781 const filteredSelectionSet = visit(selectionSet, visitWithTypeInfo(typeInfo, {
782 [Kind.FIELD]: {
783 enter: node => {
784 const parentType = typeInfo.getParentType();
785 if (isObjectType(parentType) || isInterfaceType(parentType)) {
786 const fields = parentType.getFields();
787 const field = node.name.value === '__typename' ? TypeNameMetaFieldDef : fields[node.name.value];
788 if (!field) {
789 return null;
790 }
791 const args = field.args != null ? field.args : [];
792 const argsMap = Object.create(null);
793 for (const arg of args) {
794 argsMap[arg.name] = arg;
795 }
796 if (node.arguments != null) {
797 const newArgs = [];
798 for (const arg of node.arguments) {
799 if (arg.name.value in argsMap) {
800 newArgs.push(arg);
801 }
802 }
803 if (newArgs.length !== node.arguments.length) {
804 return {
805 ...node,
806 arguments: newArgs,
807 };
808 }
809 }
810 }
811 },
812 leave: node => {
813 const type = typeInfo.getType();
814 if (type == null) {
815 throw new Error(`No type was found for field node ${node}.`);
816 }
817 const namedType = getNamedType(type);
818 if (!schema.getType(namedType.name) == null) {
819 return null;
820 }
821 if (isObjectType(namedType) || isInterfaceType(namedType)) {
822 const selections = node.selectionSet != null ? node.selectionSet.selections : null;
823 if (selections == null || selections.length === 0) {
824 return null;
825 }
826 }
827 },
828 },
829 [Kind.FRAGMENT_SPREAD]: {
830 enter: node => {
831 if (!(node.name.value in validFragments)) {
832 return null;
833 }
834 const parentType = typeInfo.getParentType();
835 const innerType = validFragments[node.name.value];
836 if (!implementsAbstractType(schema, parentType, innerType)) {
837 return null;
838 }
839 usedFragments.push(node.name.value);
840 },
841 },
842 [Kind.INLINE_FRAGMENT]: {
843 enter: node => {
844 if (node.typeCondition != null) {
845 const parentType = typeInfo.getParentType();
846 const innerType = schema.getType(node.typeCondition.name.value);
847 if (!implementsAbstractType(schema, parentType, innerType)) {
848 return null;
849 }
850 }
851 },
852 },
853 [Kind.SELECTION_SET]: {
854 leave: node => {
855 const parentType = typeInfo.getParentType();
856 if (parentType != null && isAbstractType(parentType)) {
857 const selections = node.selections.concat([
858 {
859 kind: Kind.FIELD,
860 name: {
861 kind: Kind.NAME,
862 value: '__typename',
863 },
864 },
865 ]);
866 return {
867 ...node,
868 selections,
869 };
870 }
871 },
872 },
873 }),
874 // visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
875 // empty keys cannot be removed only because of typescript errors
876 // will hopefully be fixed in future version of graphql-js to be optional
877 filteredSelectionSetVisitorKeys);
878 visit(filteredSelectionSet, {
879 [Kind.VARIABLE]: variableNode => {
880 usedVariables.push(variableNode.name.value);
881 },
882 },
883 // visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
884 // empty keys cannot be removed only because of typescript errors
885 // will hopefully be fixed in future version of graphql-js to be optional
886 variablesVisitorKeys);
887 return {
888 selectionSet: filteredSelectionSet,
889 usedFragments,
890 usedVariables,
891 };
892}
893function union(...arrays) {
894 const cache = Object.create(null);
895 const result = [];
896 for (const array of arrays) {
897 for (const item of array) {
898 if (!(item in cache)) {
899 cache[item] = true;
900 result.push(item);
901 }
902 }
903 }
904 return result;
905}
906
907const UNPATHED_ERRORS_SYMBOL = Symbol('subschemaErrors');
908const OBJECT_SUBSCHEMA_SYMBOL = Symbol('initialSubschema');
909const FIELD_SUBSCHEMA_MAP_SYMBOL = Symbol('subschemaMap');
910
911const sortSubschemasByProxiability = memoize4(function sortSubschemasByProxiability(mergedTypeInfo, sourceSubschemaOrSourceSubschemas, targetSubschemas, fieldNodes) {
912 // 1. calculate if possible to delegate to given subschema
913 const proxiableSubschemas = [];
914 const nonProxiableSubschemas = [];
915 for (const t of targetSubschemas) {
916 const selectionSet = mergedTypeInfo.selectionSets.get(t);
917 const fieldSelectionSets = mergedTypeInfo.fieldSelectionSets.get(t);
918 if (selectionSet != null &&
919 !subschemaTypesContainSelectionSet(mergedTypeInfo, sourceSubschemaOrSourceSubschemas, selectionSet)) {
920 nonProxiableSubschemas.push(t);
921 }
922 else {
923 if (fieldSelectionSets == null ||
924 fieldNodes.every(fieldNode => {
925 const fieldName = fieldNode.name.value;
926 const fieldSelectionSet = fieldSelectionSets[fieldName];
927 return (fieldSelectionSet == null ||
928 subschemaTypesContainSelectionSet(mergedTypeInfo, sourceSubschemaOrSourceSubschemas, fieldSelectionSet));
929 })) {
930 proxiableSubschemas.push(t);
931 }
932 else {
933 nonProxiableSubschemas.push(t);
934 }
935 }
936 }
937 return {
938 proxiableSubschemas,
939 nonProxiableSubschemas,
940 };
941});
942const buildDelegationPlan = memoize3(function buildDelegationPlan(mergedTypeInfo, fieldNodes, proxiableSubschemas) {
943 var _a;
944 const { uniqueFields, nonUniqueFields } = mergedTypeInfo;
945 const unproxiableFieldNodes = [];
946 // 2. for each selection:
947 const delegationMap = new Map();
948 for (const fieldNode of fieldNodes) {
949 if (fieldNode.name.value === '__typename') {
950 continue;
951 }
952 // 2a. use uniqueFields map to assign fields to subschema if one of possible subschemas
953 const uniqueSubschema = uniqueFields[fieldNode.name.value];
954 if (uniqueSubschema != null) {
955 if (!proxiableSubschemas.includes(uniqueSubschema)) {
956 unproxiableFieldNodes.push(fieldNode);
957 continue;
958 }
959 const existingSubschema = (_a = delegationMap.get(uniqueSubschema)) === null || _a === void 0 ? void 0 : _a.selections;
960 if (existingSubschema != null) {
961 existingSubschema.push(fieldNode);
962 }
963 else {
964 delegationMap.set(uniqueSubschema, {
965 kind: Kind.SELECTION_SET,
966 selections: [fieldNode],
967 });
968 }
969 continue;
970 }
971 // 2b. use nonUniqueFields to assign to a possible subschema,
972 // preferring one of the subschemas already targets of delegation
973 let nonUniqueSubschemas = nonUniqueFields[fieldNode.name.value];
974 if (nonUniqueSubschemas == null) {
975 unproxiableFieldNodes.push(fieldNode);
976 continue;
977 }
978 nonUniqueSubschemas = nonUniqueSubschemas.filter(s => proxiableSubschemas.includes(s));
979 if (!nonUniqueSubschemas.length) {
980 unproxiableFieldNodes.push(fieldNode);
981 continue;
982 }
983 const existingSubschema = nonUniqueSubschemas.find(s => delegationMap.has(s));
984 if (existingSubschema != null) {
985 // It is okay we previously explicitly check whether the map has the element.
986 delegationMap.get(existingSubschema).selections.push(fieldNode);
987 }
988 else {
989 delegationMap.set(nonUniqueSubschemas[0], {
990 kind: Kind.SELECTION_SET,
991 selections: [fieldNode],
992 });
993 }
994 }
995 return {
996 delegationMap,
997 unproxiableFieldNodes,
998 };
999});
1000const combineSubschemas = memoize2(function combineSubschemas(subschemaOrSubschemas, additionalSubschemas) {
1001 return Array.isArray(subschemaOrSubschemas)
1002 ? subschemaOrSubschemas.concat(additionalSubschemas)
1003 : [subschemaOrSubschemas].concat(additionalSubschemas);
1004});
1005function isExternalObject(data) {
1006 return data[UNPATHED_ERRORS_SYMBOL] !== undefined;
1007}
1008function annotateExternalObject(object, errors, subschema) {
1009 Object.defineProperties(object, {
1010 [OBJECT_SUBSCHEMA_SYMBOL]: { value: subschema },
1011 [FIELD_SUBSCHEMA_MAP_SYMBOL]: { value: Object.create(null) },
1012 [UNPATHED_ERRORS_SYMBOL]: { value: errors },
1013 });
1014 return object;
1015}
1016function getSubschema(object, responseKey) {
1017 var _a;
1018 return (_a = object[FIELD_SUBSCHEMA_MAP_SYMBOL][responseKey]) !== null && _a !== void 0 ? _a : object[OBJECT_SUBSCHEMA_SYMBOL];
1019}
1020function getUnpathedErrors(object) {
1021 return object[UNPATHED_ERRORS_SYMBOL];
1022}
1023async function mergeFields(mergedTypeInfo, typeName, object, fieldNodes, sourceSubschemaOrSourceSubschemas, targetSubschemas, context, info) {
1024 var _a;
1025 if (!fieldNodes.length) {
1026 return object;
1027 }
1028 const { proxiableSubschemas, nonProxiableSubschemas } = sortSubschemasByProxiability(mergedTypeInfo, sourceSubschemaOrSourceSubschemas, targetSubschemas, fieldNodes);
1029 const { delegationMap, unproxiableFieldNodes } = buildDelegationPlan(mergedTypeInfo, fieldNodes, proxiableSubschemas);
1030 if (!delegationMap.size) {
1031 return object;
1032 }
1033 const combinedErrors = object[UNPATHED_ERRORS_SYMBOL] || [];
1034 const path = responsePathAsArray(info.path);
1035 const newFieldSubschemaMap = (_a = object[FIELD_SUBSCHEMA_MAP_SYMBOL]) !== null && _a !== void 0 ? _a : Object.create(null);
1036 const type = info.schema.getType(object.__typename);
1037 const results = await Promise.all([...delegationMap.entries()].map(async ([s, selectionSet]) => {
1038 var _a;
1039 const resolver = mergedTypeInfo.resolvers.get(s);
1040 if (resolver) {
1041 let source;
1042 try {
1043 source = await resolver(object, context, info, s, selectionSet);
1044 }
1045 catch (error) {
1046 source = error;
1047 }
1048 if (source instanceof Error || source === null) {
1049 const fieldNodes = collectFields({
1050 schema: info.schema,
1051 variableValues: {},
1052 fragments: {},
1053 }, type, selectionSet, Object.create(null), Object.create(null));
1054 const nullResult = {};
1055 for (const responseKey in fieldNodes) {
1056 const combinedPath = [...path, responseKey];
1057 if (source instanceof GraphQLError) {
1058 nullResult[responseKey] = relocatedError(source, combinedPath);
1059 }
1060 else if (source instanceof Error) {
1061 nullResult[responseKey] = locatedError(source, fieldNodes[responseKey], combinedPath);
1062 }
1063 else {
1064 nullResult[responseKey] = null;
1065 }
1066 }
1067 source = nullResult;
1068 }
1069 else {
1070 if (source[UNPATHED_ERRORS_SYMBOL]) {
1071 combinedErrors.push(...source[UNPATHED_ERRORS_SYMBOL]);
1072 }
1073 }
1074 const objectSubschema = source[OBJECT_SUBSCHEMA_SYMBOL];
1075 const fieldSubschemaMap = source[FIELD_SUBSCHEMA_MAP_SYMBOL];
1076 for (const responseKey in source) {
1077 newFieldSubschemaMap[responseKey] = (_a = fieldSubschemaMap === null || fieldSubschemaMap === void 0 ? void 0 : fieldSubschemaMap[responseKey]) !== null && _a !== void 0 ? _a : objectSubschema;
1078 }
1079 return source;
1080 }
1081 }));
1082 const combinedResult = Object.assign({}, object, ...results);
1083 combinedResult[FIELD_SUBSCHEMA_MAP_SYMBOL] = newFieldSubschemaMap;
1084 combinedResult[OBJECT_SUBSCHEMA_SYMBOL] = object[OBJECT_SUBSCHEMA_SYMBOL];
1085 combinedResult[UNPATHED_ERRORS_SYMBOL] = combinedErrors;
1086 return mergeFields(mergedTypeInfo, typeName, combinedResult, unproxiableFieldNodes, combineSubschemas(sourceSubschemaOrSourceSubschemas, proxiableSubschemas), nonProxiableSubschemas, context, info);
1087}
1088const subschemaTypesContainSelectionSet = memoize3(function subschemaTypesContainSelectionSetMemoized(mergedTypeInfo, sourceSubschemaOrSourceSubschemas, selectionSet) {
1089 if (Array.isArray(sourceSubschemaOrSourceSubschemas)) {
1090 return typesContainSelectionSet(sourceSubschemaOrSourceSubschemas.map(sourceSubschema => sourceSubschema.transformedSchema.getType(mergedTypeInfo.typeName)), selectionSet);
1091 }
1092 return typesContainSelectionSet([sourceSubschemaOrSourceSubschemas.transformedSchema.getType(mergedTypeInfo.typeName)], selectionSet);
1093});
1094function typesContainSelectionSet(types, selectionSet) {
1095 var _a;
1096 const fieldMaps = types.map(type => type.getFields());
1097 for (const selection of selectionSet.selections) {
1098 if (selection.kind === Kind.FIELD) {
1099 const fields = fieldMaps.map(fieldMap => fieldMap[selection.name.value]).filter(field => field != null);
1100 if (!fields.length) {
1101 return false;
1102 }
1103 if (selection.selectionSet != null) {
1104 return typesContainSelectionSet(fields.map(field => getNamedType(field.type)), selection.selectionSet);
1105 }
1106 }
1107 else if (selection.kind === Kind.INLINE_FRAGMENT && ((_a = selection.typeCondition) === null || _a === void 0 ? void 0 : _a.name.value) === types[0].name) {
1108 return typesContainSelectionSet(types, selection.selectionSet);
1109 }
1110 }
1111 return true;
1112}
1113
1114function isSubschemaConfig(value) {
1115 return Boolean(value === null || value === void 0 ? void 0 : value.schema);
1116}
1117function cloneSubschemaConfig(subschemaConfig) {
1118 var _a, _b;
1119 const newSubschemaConfig = {
1120 ...subschemaConfig,
1121 transforms: subschemaConfig.transforms != null ? [...subschemaConfig.transforms] : undefined,
1122 };
1123 if (newSubschemaConfig.merge != null) {
1124 newSubschemaConfig.merge = { ...subschemaConfig.merge };
1125 for (const typeName in newSubschemaConfig.merge) {
1126 const mergedTypeConfig = (newSubschemaConfig.merge[typeName] = { ...((_b = (_a = subschemaConfig.merge) === null || _a === void 0 ? void 0 : _a[typeName]) !== null && _b !== void 0 ? _b : {}) });
1127 if (mergedTypeConfig.entryPoints != null) {
1128 mergedTypeConfig.entryPoints = mergedTypeConfig.entryPoints.map(entryPoint => ({ ...entryPoint }));
1129 }
1130 if (mergedTypeConfig.fields != null) {
1131 const fields = (mergedTypeConfig.fields = { ...mergedTypeConfig.fields });
1132 for (const fieldName in fields) {
1133 fields[fieldName] = { ...fields[fieldName] };
1134 }
1135 }
1136 }
1137 }
1138 return newSubschemaConfig;
1139}
1140
1141function collectSubFields(info, typeName) {
1142 let subFieldNodes = Object.create(null);
1143 const visitedFragmentNames = Object.create(null);
1144 const type = info.schema.getType(typeName);
1145 const partialExecutionContext = {
1146 schema: info.schema,
1147 variableValues: info.variableValues,
1148 fragments: info.fragments,
1149 };
1150 for (const fieldNode of info.fieldNodes) {
1151 if (fieldNode.selectionSet) {
1152 subFieldNodes = collectFields(partialExecutionContext, type, fieldNode.selectionSet, subFieldNodes, visitedFragmentNames);
1153 }
1154 }
1155 return subFieldNodes;
1156}
1157const getFieldsNotInSubschema = memoizeInfoAnd2Objects(function getFieldsNotInSubschemaMemoized(info, subschema, mergedTypeInfo) {
1158 var _a, _b;
1159 const typeMap = isSubschemaConfig(subschema) ? mergedTypeInfo.typeMaps.get(subschema) : subschema.getTypeMap();
1160 if (!typeMap) {
1161 return [];
1162 }
1163 const typeName = mergedTypeInfo.typeName;
1164 const fields = typeMap[typeName].getFields();
1165 const subFieldNodes = collectSubFields(info, typeName);
1166 // TODO: Verify whether it is safe that extensions always exists.
1167 const stitchingInfo = (_a = info.schema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
1168 const fieldNodesByField = stitchingInfo === null || stitchingInfo === void 0 ? void 0 : stitchingInfo.fieldNodesByField;
1169 const fieldsNotInSchema = new Set();
1170 for (const responseKey in subFieldNodes) {
1171 const subFieldNodesForResponseKey = subFieldNodes[responseKey];
1172 const fieldName = subFieldNodesForResponseKey[0].name.value;
1173 if (!fields[fieldName]) {
1174 for (const subFieldNodeForResponseKey of subFieldNodesForResponseKey) {
1175 fieldsNotInSchema.add(subFieldNodeForResponseKey);
1176 }
1177 }
1178 const fieldNodesForField = (_b = fieldNodesByField === null || fieldNodesByField === void 0 ? void 0 : fieldNodesByField[typeName]) === null || _b === void 0 ? void 0 : _b[fieldName];
1179 if (fieldNodesForField) {
1180 for (const fieldNode of fieldNodesForField) {
1181 if (!fields[fieldNode.name.value]) {
1182 fieldsNotInSchema.add(fieldNode);
1183 }
1184 }
1185 }
1186 }
1187 return Array.from(fieldsNotInSchema);
1188});
1189
1190function resolveExternalValue(result, unpathedErrors, subschema, context, info, returnType = getReturnType(info), skipTypeMerging) {
1191 const type = getNullableType(returnType);
1192 if (result instanceof Error) {
1193 return result;
1194 }
1195 if (result == null) {
1196 return reportUnpathedErrorsViaNull(unpathedErrors);
1197 }
1198 if ('parseValue' in type) {
1199 return type.parseValue(result);
1200 }
1201 else if (isCompositeType(type)) {
1202 return resolveExternalObject(type, result, unpathedErrors, subschema, context, info, skipTypeMerging);
1203 }
1204 else if (isListType(type)) {
1205 return resolveExternalList(type, result, unpathedErrors, subschema, context, info, skipTypeMerging);
1206 }
1207}
1208function resolveExternalObject(type, object, unpathedErrors, subschema, context, info, skipTypeMerging) {
1209 var _a;
1210 // if we have already resolved this object, for example, when the identical object appears twice
1211 // in a list, see https://github.com/ardatan/graphql-tools/issues/2304
1212 if (isExternalObject(object)) {
1213 return object;
1214 }
1215 annotateExternalObject(object, unpathedErrors, subschema);
1216 if (skipTypeMerging || info == null) {
1217 return object;
1218 }
1219 const stitchingInfo = (_a = info.schema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
1220 if (stitchingInfo == null) {
1221 return object;
1222 }
1223 let typeName;
1224 if (isAbstractType(type)) {
1225 const resolvedType = info.schema.getType(object.__typename);
1226 if (resolvedType == null) {
1227 throw new Error(`Unable to resolve type '${object.__typename}'. Did you forget to include a transform that renames types? Did you delegate to the original subschema rather that the subschema config object containing the transform?`);
1228 }
1229 typeName = resolvedType.name;
1230 }
1231 else {
1232 typeName = type.name;
1233 }
1234 const mergedTypeInfo = stitchingInfo.mergedTypes[typeName];
1235 let targetSubschemas;
1236 // Within the stitching context, delegation to a stitched GraphQLSchema or SubschemaConfig
1237 // will be redirected to the appropriate Subschema object, from which merge targets can be queried.
1238 if (mergedTypeInfo != null) {
1239 targetSubschemas = mergedTypeInfo.targetSubschemas.get(subschema);
1240 }
1241 // If there are no merge targets from the subschema, return.
1242 if (!targetSubschemas) {
1243 return object;
1244 }
1245 const fieldNodes = getFieldsNotInSubschema(info, subschema, mergedTypeInfo);
1246 return mergeFields(mergedTypeInfo, typeName, object, fieldNodes, subschema, targetSubschemas, context, info);
1247}
1248function resolveExternalList(type, list, unpathedErrors, subschema, context, info, skipTypeMerging) {
1249 return list.map(listMember => resolveExternalListMember(getNullableType(type.ofType), listMember, unpathedErrors, subschema, context, info, skipTypeMerging));
1250}
1251function resolveExternalListMember(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging) {
1252 if (listMember instanceof Error) {
1253 return listMember;
1254 }
1255 if (listMember == null) {
1256 return reportUnpathedErrorsViaNull(unpathedErrors);
1257 }
1258 if (isLeafType(type)) {
1259 return type.parseValue(listMember);
1260 }
1261 else if (isCompositeType(type)) {
1262 return resolveExternalObject(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging);
1263 }
1264 else if (isListType(type)) {
1265 return resolveExternalList(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging);
1266 }
1267}
1268const reportedErrors = new WeakMap();
1269function reportUnpathedErrorsViaNull(unpathedErrors) {
1270 if (unpathedErrors.length) {
1271 const unreportedErrors = [];
1272 for (const error of unpathedErrors) {
1273 if (!reportedErrors.has(error)) {
1274 unreportedErrors.push(error);
1275 reportedErrors.set(error, true);
1276 }
1277 }
1278 if (unreportedErrors.length) {
1279 if (unreportedErrors.length === 1) {
1280 return unreportedErrors[0];
1281 }
1282 const combinedError = new AggregateError(unreportedErrors);
1283 // We cast path as any for GraphQL.js 14 compat
1284 // locatedError path argument must be defined, but it is just forwarded to a constructor that allows a undefined value
1285 // https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/locatedError.js#L25
1286 // https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/GraphQLError.js#L19
1287 return locatedError(combinedError, undefined, unreportedErrors[0].path);
1288 }
1289 }
1290 return null;
1291}
1292function getReturnType(info) {
1293 if (info == null) {
1294 throw new Error(`Return type cannot be inferred without a source schema.`);
1295 }
1296 return info.returnType;
1297}
1298
1299function checkResultAndHandleErrors(result, delegationContext) {
1300 const { context, info, fieldName: responseKey = getResponseKey(info), subschema, returnType = getReturnType$1(info), skipTypeMerging, onLocatedError, } = delegationContext;
1301 const { data, unpathedErrors } = mergeDataAndErrors(result.data == null ? undefined : result.data[responseKey], result.errors == null ? [] : result.errors, info != null && info.path ? responsePathAsArray(info.path) : undefined, onLocatedError);
1302 return resolveExternalValue(data, unpathedErrors, subschema, context, info, returnType, skipTypeMerging);
1303}
1304function mergeDataAndErrors(data, errors, path, onLocatedError, index = 1) {
1305 var _a;
1306 if (data == null) {
1307 if (!errors.length) {
1308 return { data: null, unpathedErrors: [] };
1309 }
1310 if (errors.length === 1) {
1311 const error = onLocatedError ? onLocatedError(errors[0]) : errors[0];
1312 const newPath = path === undefined ? error.path : error.path === undefined ? path : path.concat(error.path.slice(1));
1313 return { data: relocatedError(errors[0], newPath), unpathedErrors: [] };
1314 }
1315 // We cast path as any for GraphQL.js 14 compat
1316 // locatedError path argument must be defined, but it is just forwarded to a constructor that allows a undefined value
1317 // https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/locatedError.js#L25
1318 // https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/GraphQLError.js#L19
1319 const newError = locatedError(new AggregateError(errors), undefined, path);
1320 return { data: newError, unpathedErrors: [] };
1321 }
1322 if (!errors.length) {
1323 return { data, unpathedErrors: [] };
1324 }
1325 const unpathedErrors = [];
1326 const errorMap = new Map();
1327 for (const error of errors) {
1328 const pathSegment = (_a = error.path) === null || _a === void 0 ? void 0 : _a[index];
1329 if (pathSegment != null) {
1330 let pathSegmentErrors = errorMap.get(pathSegment);
1331 if (pathSegmentErrors === undefined) {
1332 pathSegmentErrors = [error];
1333 errorMap.set(pathSegment, pathSegmentErrors);
1334 }
1335 else {
1336 pathSegmentErrors.push(error);
1337 }
1338 }
1339 else {
1340 unpathedErrors.push(error);
1341 }
1342 }
1343 for (const [pathSegment, pathSegmentErrors] of errorMap) {
1344 if (data[pathSegment] !== undefined) {
1345 const { data: newData, unpathedErrors: newErrors } = mergeDataAndErrors(data[pathSegment], pathSegmentErrors, path, onLocatedError, index + 1);
1346 data[pathSegment] = newData;
1347 unpathedErrors.push(...newErrors);
1348 }
1349 else {
1350 unpathedErrors.push(...pathSegmentErrors);
1351 }
1352 }
1353 return { data, unpathedErrors };
1354}
1355function getResponseKey(info) {
1356 if (info == null) {
1357 throw new Error(`Data cannot be extracted from result without an explicit key or source schema.`);
1358 }
1359 return getResponseKeyFromInfo(info);
1360}
1361function getReturnType$1(info) {
1362 if (info == null) {
1363 throw new Error(`Return type cannot be inferred without a source schema.`);
1364 }
1365 return info.returnType;
1366}
1367
1368class Transformer {
1369 constructor(context) {
1370 this.transformations = [];
1371 this.delegationContext = context;
1372 const transforms = context.transforms;
1373 const delegationTransforms = transforms.slice().reverse();
1374 for (const transform of delegationTransforms) {
1375 this.addTransform(transform, {});
1376 }
1377 }
1378 addTransform(transform, context = {}) {
1379 this.transformations.push({ transform, context });
1380 }
1381 transformRequest(originalRequest) {
1382 var _a;
1383 let request = {
1384 ...originalRequest,
1385 document: prepareGatewayDocument(originalRequest.document, this.delegationContext.transformedSchema, this.delegationContext.returnType, (_a = this.delegationContext.info) === null || _a === void 0 ? void 0 : _a.schema),
1386 };
1387 for (const transformation of this.transformations) {
1388 if (transformation.transform.transformRequest) {
1389 request = transformation.transform.transformRequest(request, this.delegationContext, transformation.context);
1390 }
1391 }
1392 return finalizeGatewayRequest(request, this.delegationContext);
1393 }
1394 transformResult(originalResult) {
1395 let result = originalResult;
1396 // from rigth to left
1397 for (let i = this.transformations.length - 1; i >= 0; i--) {
1398 const transformation = this.transformations[i];
1399 if (transformation.transform.transformResult) {
1400 result = transformation.transform.transformResult(result, this.delegationContext, transformation.context);
1401 }
1402 }
1403 return checkResultAndHandleErrors(result, this.delegationContext);
1404 }
1405}
1406
1407function getDelegatingOperation(parentType, schema) {
1408 if (parentType === schema.getMutationType()) {
1409 return 'mutation';
1410 }
1411 else if (parentType === schema.getSubscriptionType()) {
1412 return 'subscription';
1413 }
1414 return 'query';
1415}
1416function createRequestFromInfo({ info, rootValue, operationName, operation = getDelegatingOperation(info.parentType, info.schema), fieldName = info.fieldName, selectionSet, fieldNodes = info.fieldNodes, context, }) {
1417 return createRequest({
1418 sourceSchema: info.schema,
1419 sourceParentType: info.parentType,
1420 sourceFieldName: info.fieldName,
1421 fragments: info.fragments,
1422 variableDefinitions: info.operation.variableDefinitions,
1423 variableValues: info.variableValues,
1424 targetRootValue: rootValue,
1425 targetOperationName: operationName,
1426 targetOperation: operation,
1427 targetFieldName: fieldName,
1428 selectionSet,
1429 fieldNodes,
1430 context,
1431 info,
1432 });
1433}
1434function createRequest({ sourceSchema, sourceParentType, sourceFieldName, fragments, variableDefinitions, variableValues, targetRootValue, targetOperationName, targetOperation, targetFieldName, selectionSet, fieldNodes, context, info, }) {
1435 var _a, _b;
1436 let newSelectionSet;
1437 const argumentNodeMap = Object.create(null);
1438 if (selectionSet != null) {
1439 newSelectionSet = selectionSet;
1440 }
1441 else {
1442 const selections = [];
1443 for (const fieldNode of fieldNodes || []) {
1444 if (fieldNode.selectionSet) {
1445 for (const selection of fieldNode.selectionSet.selections) {
1446 selections.push(selection);
1447 }
1448 }
1449 }
1450 newSelectionSet = selections.length
1451 ? {
1452 kind: Kind.SELECTION_SET,
1453 selections,
1454 }
1455 : undefined;
1456 const args = (_a = fieldNodes === null || fieldNodes === void 0 ? void 0 : fieldNodes[0]) === null || _a === void 0 ? void 0 : _a.arguments;
1457 if (args) {
1458 for (const argNode of args) {
1459 argumentNodeMap[argNode.name.value] = argNode;
1460 }
1461 }
1462 }
1463 const newVariables = Object.create(null);
1464 const variableDefinitionMap = Object.create(null);
1465 if (sourceSchema != null && variableDefinitions != null) {
1466 for (const def of variableDefinitions) {
1467 const varName = def.variable.name.value;
1468 variableDefinitionMap[varName] = def;
1469 const varType = typeFromAST(sourceSchema, def.type);
1470 const serializedValue = serializeInputValue(varType, variableValues === null || variableValues === void 0 ? void 0 : variableValues[varName]);
1471 if (serializedValue !== undefined) {
1472 newVariables[varName] = serializedValue;
1473 }
1474 }
1475 }
1476 if (sourceParentType != null && sourceFieldName != null) {
1477 updateArgumentsWithDefaults(sourceParentType, sourceFieldName, argumentNodeMap, variableDefinitionMap, newVariables);
1478 }
1479 const rootFieldName = targetFieldName !== null && targetFieldName !== void 0 ? targetFieldName : (_b = fieldNodes === null || fieldNodes === void 0 ? void 0 : fieldNodes[0]) === null || _b === void 0 ? void 0 : _b.name.value;
1480 if (rootFieldName === undefined) {
1481 throw new Error(`Either "targetFieldName" or a non empty "fieldNodes" array must be provided.`);
1482 }
1483 const rootfieldNode = {
1484 kind: Kind.FIELD,
1485 arguments: Object.values(argumentNodeMap),
1486 name: {
1487 kind: Kind.NAME,
1488 value: rootFieldName,
1489 },
1490 selectionSet: newSelectionSet,
1491 };
1492 const operationName = targetOperationName
1493 ? {
1494 kind: Kind.NAME,
1495 value: targetOperationName,
1496 }
1497 : undefined;
1498 const operationDefinition = {
1499 kind: Kind.OPERATION_DEFINITION,
1500 name: operationName,
1501 operation: targetOperation,
1502 variableDefinitions: Object.values(variableDefinitionMap),
1503 selectionSet: {
1504 kind: Kind.SELECTION_SET,
1505 selections: [rootfieldNode],
1506 },
1507 };
1508 const definitions = [operationDefinition];
1509 if (fragments != null) {
1510 for (const fragmentName in fragments) {
1511 const fragment = fragments[fragmentName];
1512 definitions.push(fragment);
1513 }
1514 }
1515 const document = {
1516 kind: Kind.DOCUMENT,
1517 definitions,
1518 };
1519 return {
1520 document,
1521 variables: newVariables,
1522 rootValue: targetRootValue,
1523 operationName: targetOperationName,
1524 operationType: targetOperation,
1525 context,
1526 info,
1527 };
1528}
1529function updateArgumentsWithDefaults(sourceParentType, sourceFieldName, argumentNodeMap, variableDefinitionMap, variableValues) {
1530 const generateVariableName = createVariableNameGenerator(variableDefinitionMap);
1531 const sourceField = sourceParentType.getFields()[sourceFieldName];
1532 for (const argument of sourceField.args) {
1533 const argName = argument.name;
1534 const sourceArgType = argument.type;
1535 if (argumentNodeMap[argName] === undefined) {
1536 const defaultValue = argument.defaultValue;
1537 if (defaultValue !== undefined) {
1538 updateArgument(argumentNodeMap, variableDefinitionMap, variableValues, argName, generateVariableName(argName), sourceArgType, serializeInputValue(sourceArgType, defaultValue));
1539 }
1540 }
1541 }
1542}
1543
1544/**
1545 * Resolver that knows how to:
1546 * a) handle aliases for proxied schemas
1547 * b) handle errors from proxied schemas
1548 * c) handle external to internal enum conversion
1549 */
1550function defaultMergedResolver(parent, args, context, info) {
1551 if (!parent) {
1552 return null;
1553 }
1554 const responseKey = getResponseKeyFromInfo(info);
1555 // check to see if parent is not a proxied result, i.e. if parent resolver was manually overwritten
1556 // See https://github.com/apollographql/graphql-tools/issues/967
1557 if (!isExternalObject(parent)) {
1558 return defaultFieldResolver(parent, args, context, info);
1559 }
1560 const data = parent[responseKey];
1561 const unpathedErrors = getUnpathedErrors(parent);
1562 const subschema = getSubschema(parent, responseKey);
1563 return resolveExternalValue(data, unpathedErrors, subschema, context, info);
1564}
1565
1566function delegateToSchema(options) {
1567 const { info, schema, rootValue, operationName, operation = getDelegatingOperation(info.parentType, info.schema), fieldName = info.fieldName, selectionSet, fieldNodes, context, } = options;
1568 const request = createRequestFromInfo({
1569 info,
1570 operation,
1571 fieldName,
1572 selectionSet,
1573 fieldNodes,
1574 rootValue: rootValue !== null && rootValue !== void 0 ? rootValue : schema.rootValue,
1575 operationName,
1576 context,
1577 });
1578 return delegateRequest({
1579 ...options,
1580 request,
1581 });
1582}
1583function getDelegationReturnType(targetSchema, operation, fieldName) {
1584 const rootType = getDefinedRootType(targetSchema, operation);
1585 return rootType.getFields()[fieldName].type;
1586}
1587function delegateRequest(options) {
1588 const delegationContext = getDelegationContext(options);
1589 const transformer = new Transformer(delegationContext);
1590 const processedRequest = transformer.transformRequest(options.request);
1591 if (options.validateRequest) {
1592 validateRequest(delegationContext, processedRequest.document);
1593 }
1594 const executor = getExecutor(delegationContext);
1595 return new ValueOrPromise(() => executor(processedRequest))
1596 .then(originalResult => {
1597 if (isAsyncIterable(originalResult)) {
1598 // "subscribe" to the subscription result and map the result through the transforms
1599 return mapAsyncIterator(originalResult, result => transformer.transformResult(result));
1600 }
1601 return transformer.transformResult(originalResult);
1602 })
1603 .resolve();
1604}
1605function getDelegationContext({ request, schema, fieldName, returnType, args, info, transforms = [], transformedSchema, skipTypeMerging = false, }) {
1606 var _a, _b, _c, _d;
1607 const { operationType: operation, context, operationName, document } = request;
1608 let operationDefinition;
1609 let targetFieldName;
1610 if (fieldName == null) {
1611 operationDefinition = getOperationAST(document, operationName);
1612 if (operationDefinition == null) {
1613 throw new Error('Cannot infer main operation from the provided document.');
1614 }
1615 targetFieldName = (operationDefinition === null || operationDefinition === void 0 ? void 0 : operationDefinition.selectionSet.selections[0]).name.value;
1616 }
1617 else {
1618 targetFieldName = fieldName;
1619 }
1620 const stitchingInfo = (_a = info === null || info === void 0 ? void 0 : info.schema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
1621 const subschemaOrSubschemaConfig = (_b = stitchingInfo === null || stitchingInfo === void 0 ? void 0 : stitchingInfo.subschemaMap.get(schema)) !== null && _b !== void 0 ? _b : schema;
1622 if (isSubschemaConfig(subschemaOrSubschemaConfig)) {
1623 const targetSchema = subschemaOrSubschemaConfig.schema;
1624 return {
1625 subschema: schema,
1626 subschemaConfig: subschemaOrSubschemaConfig,
1627 targetSchema,
1628 operation,
1629 fieldName: targetFieldName,
1630 args,
1631 context,
1632 info,
1633 returnType: (_c = returnType !== null && returnType !== void 0 ? returnType : info === null || info === void 0 ? void 0 : info.returnType) !== null && _c !== void 0 ? _c : getDelegationReturnType(targetSchema, operation, targetFieldName),
1634 transforms: subschemaOrSubschemaConfig.transforms != null
1635 ? subschemaOrSubschemaConfig.transforms.concat(transforms)
1636 : transforms,
1637 transformedSchema: transformedSchema !== null && transformedSchema !== void 0 ? transformedSchema : (subschemaOrSubschemaConfig instanceof Subschema ? subschemaOrSubschemaConfig.transformedSchema : targetSchema),
1638 skipTypeMerging,
1639 };
1640 }
1641 return {
1642 subschema: schema,
1643 subschemaConfig: undefined,
1644 targetSchema: subschemaOrSubschemaConfig,
1645 operation,
1646 fieldName: targetFieldName,
1647 args,
1648 context,
1649 info,
1650 returnType: (_d = returnType !== null && returnType !== void 0 ? returnType : info === null || info === void 0 ? void 0 : info.returnType) !== null && _d !== void 0 ? _d : getDelegationReturnType(subschemaOrSubschemaConfig, operation, targetFieldName),
1651 transforms,
1652 transformedSchema: transformedSchema !== null && transformedSchema !== void 0 ? transformedSchema : subschemaOrSubschemaConfig,
1653 skipTypeMerging,
1654 };
1655}
1656function validateRequest(delegationContext, document) {
1657 const errors = validate(delegationContext.targetSchema, document);
1658 if (errors.length > 0) {
1659 if (errors.length > 1) {
1660 const combinedError = new AggregateError(errors);
1661 throw combinedError;
1662 }
1663 const error = errors[0];
1664 throw error.originalError || error;
1665 }
1666}
1667function getExecutor(delegationContext) {
1668 var _a, _b;
1669 const { subschemaConfig, targetSchema, context } = delegationContext;
1670 let executor = (subschemaConfig === null || subschemaConfig === void 0 ? void 0 : subschemaConfig.executor) || createDefaultExecutor(targetSchema);
1671 if (subschemaConfig === null || subschemaConfig === void 0 ? void 0 : subschemaConfig.batch) {
1672 const batchingOptions = subschemaConfig === null || subschemaConfig === void 0 ? void 0 : subschemaConfig.batchingOptions;
1673 executor = getBatchingExecutor((_b = (_a = context !== null && context !== void 0 ? context : globalThis) !== null && _a !== void 0 ? _a : window) !== null && _b !== void 0 ? _b : global, executor, batchingOptions === null || batchingOptions === void 0 ? void 0 : batchingOptions.dataLoaderOptions, batchingOptions === null || batchingOptions === void 0 ? void 0 : batchingOptions.extensionsReducer);
1674 }
1675 return executor;
1676}
1677const defaultExecutorCache = new WeakMap();
1678function createDefaultExecutor(schema) {
1679 let defaultExecutor = defaultExecutorCache.get(schema);
1680 if (!defaultExecutor) {
1681 defaultExecutor = function defaultExecutor({ document, context, variables, rootValue, operationName, operationType, }) {
1682 const executionArgs = {
1683 schema,
1684 document,
1685 contextValue: context,
1686 variableValues: variables,
1687 rootValue,
1688 operationName,
1689 };
1690 if (operationType === 'subscription') {
1691 return subscribe(executionArgs);
1692 }
1693 return execute(executionArgs);
1694 };
1695 defaultExecutorCache.set(schema, defaultExecutor);
1696 }
1697 return defaultExecutor;
1698}
1699
1700export { Subschema, Transformer, annotateExternalObject, applySchemaTransforms, cloneSubschemaConfig, createDefaultExecutor, createRequest, createRequestFromInfo, defaultMergedResolver, delegateRequest, delegateToSchema, getDelegatingOperation, getSubschema, getUnpathedErrors, isExternalObject, isSubschema, isSubschemaConfig, mergeFields, resolveExternalValue };