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 FragmentDefinition: ['directives', 'selectionSet'],
772 ObjectValue: ['fields'],
773 ObjectField: ['name', 'value'],
774 Directive: ['arguments'],
775};
776function finalizeSelectionSet(schema, type, validFragments, selectionSet) {
777 const usedFragments = [];
778 const usedVariables = [];
779 const typeInfo = new TypeInfo(schema, undefined, type);
780 const filteredSelectionSet = visit(selectionSet, visitWithTypeInfo(typeInfo, {
781 [Kind.FIELD]: {
782 enter: node => {
783 const parentType = typeInfo.getParentType();
784 if (isObjectType(parentType) || isInterfaceType(parentType)) {
785 const fields = parentType.getFields();
786 const field = node.name.value === '__typename' ? TypeNameMetaFieldDef : fields[node.name.value];
787 if (!field) {
788 return null;
789 }
790 const args = field.args != null ? field.args : [];
791 const argsMap = Object.create(null);
792 for (const arg of args) {
793 argsMap[arg.name] = arg;
794 }
795 if (node.arguments != null) {
796 const newArgs = [];
797 for (const arg of node.arguments) {
798 if (arg.name.value in argsMap) {
799 newArgs.push(arg);
800 }
801 }
802 if (newArgs.length !== node.arguments.length) {
803 return {
804 ...node,
805 arguments: newArgs,
806 };
807 }
808 }
809 }
810 },
811 leave: node => {
812 const type = typeInfo.getType();
813 if (type == null) {
814 throw new Error(`No type was found for field node ${node}.`);
815 }
816 const namedType = getNamedType(type);
817 if (!schema.getType(namedType.name) == null) {
818 return null;
819 }
820 if (isObjectType(namedType) || isInterfaceType(namedType)) {
821 const selections = node.selectionSet != null ? node.selectionSet.selections : null;
822 if (selections == null || selections.length === 0) {
823 return null;
824 }
825 }
826 },
827 },
828 [Kind.FRAGMENT_SPREAD]: {
829 enter: node => {
830 if (!(node.name.value in validFragments)) {
831 return null;
832 }
833 const parentType = typeInfo.getParentType();
834 const innerType = validFragments[node.name.value];
835 if (!implementsAbstractType(schema, parentType, innerType)) {
836 return null;
837 }
838 usedFragments.push(node.name.value);
839 },
840 },
841 [Kind.INLINE_FRAGMENT]: {
842 enter: node => {
843 if (node.typeCondition != null) {
844 const parentType = typeInfo.getParentType();
845 const innerType = schema.getType(node.typeCondition.name.value);
846 if (!implementsAbstractType(schema, parentType, innerType)) {
847 return null;
848 }
849 }
850 },
851 },
852 [Kind.SELECTION_SET]: {
853 leave: node => {
854 const parentType = typeInfo.getParentType();
855 if (parentType != null && isAbstractType(parentType)) {
856 const selections = node.selections.concat([
857 {
858 kind: Kind.FIELD,
859 name: {
860 kind: Kind.NAME,
861 value: '__typename',
862 },
863 },
864 ]);
865 return {
866 ...node,
867 selections,
868 };
869 }
870 },
871 },
872 }),
873 // visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
874 // empty keys cannot be removed only because of typescript errors
875 // will hopefully be fixed in future version of graphql-js to be optional
876 filteredSelectionSetVisitorKeys);
877 visit(filteredSelectionSet, {
878 [Kind.VARIABLE]: variableNode => {
879 usedVariables.push(variableNode.name.value);
880 },
881 },
882 // visitorKeys argument usage a la https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
883 // empty keys cannot be removed only because of typescript errors
884 // will hopefully be fixed in future version of graphql-js to be optional
885 variablesVisitorKeys);
886 return {
887 selectionSet: filteredSelectionSet,
888 usedFragments,
889 usedVariables,
890 };
891}
892function union(...arrays) {
893 const cache = Object.create(null);
894 const result = [];
895 for (const array of arrays) {
896 for (const item of array) {
897 if (!(item in cache)) {
898 cache[item] = true;
899 result.push(item);
900 }
901 }
902 }
903 return result;
904}
905
906const UNPATHED_ERRORS_SYMBOL = Symbol('subschemaErrors');
907const OBJECT_SUBSCHEMA_SYMBOL = Symbol('initialSubschema');
908const FIELD_SUBSCHEMA_MAP_SYMBOL = Symbol('subschemaMap');
909
910const sortSubschemasByProxiability = memoize4(function sortSubschemasByProxiability(mergedTypeInfo, sourceSubschemaOrSourceSubschemas, targetSubschemas, fieldNodes) {
911 // 1. calculate if possible to delegate to given subschema
912 const proxiableSubschemas = [];
913 const nonProxiableSubschemas = [];
914 for (const t of targetSubschemas) {
915 const selectionSet = mergedTypeInfo.selectionSets.get(t);
916 const fieldSelectionSets = mergedTypeInfo.fieldSelectionSets.get(t);
917 if (selectionSet != null &&
918 !subschemaTypesContainSelectionSet(mergedTypeInfo, sourceSubschemaOrSourceSubschemas, selectionSet)) {
919 nonProxiableSubschemas.push(t);
920 }
921 else {
922 if (fieldSelectionSets == null ||
923 fieldNodes.every(fieldNode => {
924 const fieldName = fieldNode.name.value;
925 const fieldSelectionSet = fieldSelectionSets[fieldName];
926 return (fieldSelectionSet == null ||
927 subschemaTypesContainSelectionSet(mergedTypeInfo, sourceSubschemaOrSourceSubschemas, fieldSelectionSet));
928 })) {
929 proxiableSubschemas.push(t);
930 }
931 else {
932 nonProxiableSubschemas.push(t);
933 }
934 }
935 }
936 return {
937 proxiableSubschemas,
938 nonProxiableSubschemas,
939 };
940});
941const buildDelegationPlan = memoize3(function buildDelegationPlan(mergedTypeInfo, fieldNodes, proxiableSubschemas) {
942 var _a;
943 const { uniqueFields, nonUniqueFields } = mergedTypeInfo;
944 const unproxiableFieldNodes = [];
945 // 2. for each selection:
946 const delegationMap = new Map();
947 for (const fieldNode of fieldNodes) {
948 if (fieldNode.name.value === '__typename') {
949 continue;
950 }
951 // 2a. use uniqueFields map to assign fields to subschema if one of possible subschemas
952 const uniqueSubschema = uniqueFields[fieldNode.name.value];
953 if (uniqueSubschema != null) {
954 if (!proxiableSubschemas.includes(uniqueSubschema)) {
955 unproxiableFieldNodes.push(fieldNode);
956 continue;
957 }
958 const existingSubschema = (_a = delegationMap.get(uniqueSubschema)) === null || _a === void 0 ? void 0 : _a.selections;
959 if (existingSubschema != null) {
960 existingSubschema.push(fieldNode);
961 }
962 else {
963 delegationMap.set(uniqueSubschema, {
964 kind: Kind.SELECTION_SET,
965 selections: [fieldNode],
966 });
967 }
968 continue;
969 }
970 // 2b. use nonUniqueFields to assign to a possible subschema,
971 // preferring one of the subschemas already targets of delegation
972 let nonUniqueSubschemas = nonUniqueFields[fieldNode.name.value];
973 if (nonUniqueSubschemas == null) {
974 unproxiableFieldNodes.push(fieldNode);
975 continue;
976 }
977 nonUniqueSubschemas = nonUniqueSubschemas.filter(s => proxiableSubschemas.includes(s));
978 if (!nonUniqueSubschemas.length) {
979 unproxiableFieldNodes.push(fieldNode);
980 continue;
981 }
982 const existingSubschema = nonUniqueSubschemas.find(s => delegationMap.has(s));
983 if (existingSubschema != null) {
984 // It is okay we previously explicitly check whether the map has the element.
985 delegationMap.get(existingSubschema).selections.push(fieldNode);
986 }
987 else {
988 delegationMap.set(nonUniqueSubschemas[0], {
989 kind: Kind.SELECTION_SET,
990 selections: [fieldNode],
991 });
992 }
993 }
994 return {
995 delegationMap,
996 unproxiableFieldNodes,
997 };
998});
999const combineSubschemas = memoize2(function combineSubschemas(subschemaOrSubschemas, additionalSubschemas) {
1000 return Array.isArray(subschemaOrSubschemas)
1001 ? subschemaOrSubschemas.concat(additionalSubschemas)
1002 : [subschemaOrSubschemas].concat(additionalSubschemas);
1003});
1004function isExternalObject(data) {
1005 return data[UNPATHED_ERRORS_SYMBOL] !== undefined;
1006}
1007function annotateExternalObject(object, errors, subschema) {
1008 Object.defineProperties(object, {
1009 [OBJECT_SUBSCHEMA_SYMBOL]: { value: subschema },
1010 [FIELD_SUBSCHEMA_MAP_SYMBOL]: { value: Object.create(null) },
1011 [UNPATHED_ERRORS_SYMBOL]: { value: errors },
1012 });
1013 return object;
1014}
1015function getSubschema(object, responseKey) {
1016 var _a;
1017 return (_a = object[FIELD_SUBSCHEMA_MAP_SYMBOL][responseKey]) !== null && _a !== void 0 ? _a : object[OBJECT_SUBSCHEMA_SYMBOL];
1018}
1019function getUnpathedErrors(object) {
1020 return object[UNPATHED_ERRORS_SYMBOL];
1021}
1022async function mergeFields(mergedTypeInfo, typeName, object, fieldNodes, sourceSubschemaOrSourceSubschemas, targetSubschemas, context, info) {
1023 var _a;
1024 if (!fieldNodes.length) {
1025 return object;
1026 }
1027 const { proxiableSubschemas, nonProxiableSubschemas } = sortSubschemasByProxiability(mergedTypeInfo, sourceSubschemaOrSourceSubschemas, targetSubschemas, fieldNodes);
1028 const { delegationMap, unproxiableFieldNodes } = buildDelegationPlan(mergedTypeInfo, fieldNodes, proxiableSubschemas);
1029 if (!delegationMap.size) {
1030 return object;
1031 }
1032 const combinedErrors = object[UNPATHED_ERRORS_SYMBOL] || [];
1033 const path = responsePathAsArray(info.path);
1034 const newFieldSubschemaMap = (_a = object[FIELD_SUBSCHEMA_MAP_SYMBOL]) !== null && _a !== void 0 ? _a : Object.create(null);
1035 const type = info.schema.getType(object.__typename);
1036 const results = await Promise.all([...delegationMap.entries()].map(async ([s, selectionSet]) => {
1037 var _a;
1038 const resolver = mergedTypeInfo.resolvers.get(s);
1039 if (resolver) {
1040 let source;
1041 try {
1042 source = await resolver(object, context, info, s, selectionSet);
1043 }
1044 catch (error) {
1045 source = error;
1046 }
1047 if (source instanceof Error || source === null) {
1048 const fieldNodes = collectFields({
1049 schema: info.schema,
1050 variableValues: {},
1051 fragments: {},
1052 }, type, selectionSet, Object.create(null), Object.create(null));
1053 const nullResult = {};
1054 for (const responseKey in fieldNodes) {
1055 const combinedPath = [...path, responseKey];
1056 if (source instanceof GraphQLError) {
1057 nullResult[responseKey] = relocatedError(source, combinedPath);
1058 }
1059 else if (source instanceof Error) {
1060 nullResult[responseKey] = locatedError(source, fieldNodes[responseKey], combinedPath);
1061 }
1062 else {
1063 nullResult[responseKey] = null;
1064 }
1065 }
1066 source = nullResult;
1067 }
1068 else {
1069 if (source[UNPATHED_ERRORS_SYMBOL]) {
1070 combinedErrors.push(...source[UNPATHED_ERRORS_SYMBOL]);
1071 }
1072 }
1073 const objectSubschema = source[OBJECT_SUBSCHEMA_SYMBOL];
1074 const fieldSubschemaMap = source[FIELD_SUBSCHEMA_MAP_SYMBOL];
1075 for (const responseKey in source) {
1076 newFieldSubschemaMap[responseKey] = (_a = fieldSubschemaMap === null || fieldSubschemaMap === void 0 ? void 0 : fieldSubschemaMap[responseKey]) !== null && _a !== void 0 ? _a : objectSubschema;
1077 }
1078 return source;
1079 }
1080 }));
1081 const combinedResult = Object.assign({}, object, ...results);
1082 combinedResult[FIELD_SUBSCHEMA_MAP_SYMBOL] = newFieldSubschemaMap;
1083 combinedResult[OBJECT_SUBSCHEMA_SYMBOL] = object[OBJECT_SUBSCHEMA_SYMBOL];
1084 combinedResult[UNPATHED_ERRORS_SYMBOL] = combinedErrors;
1085 return mergeFields(mergedTypeInfo, typeName, combinedResult, unproxiableFieldNodes, combineSubschemas(sourceSubschemaOrSourceSubschemas, proxiableSubschemas), nonProxiableSubschemas, context, info);
1086}
1087const subschemaTypesContainSelectionSet = memoize3(function subschemaTypesContainSelectionSetMemoized(mergedTypeInfo, sourceSubschemaOrSourceSubschemas, selectionSet) {
1088 if (Array.isArray(sourceSubschemaOrSourceSubschemas)) {
1089 return typesContainSelectionSet(sourceSubschemaOrSourceSubschemas.map(sourceSubschema => sourceSubschema.transformedSchema.getType(mergedTypeInfo.typeName)), selectionSet);
1090 }
1091 return typesContainSelectionSet([sourceSubschemaOrSourceSubschemas.transformedSchema.getType(mergedTypeInfo.typeName)], selectionSet);
1092});
1093function typesContainSelectionSet(types, selectionSet) {
1094 var _a;
1095 const fieldMaps = types.map(type => type.getFields());
1096 for (const selection of selectionSet.selections) {
1097 if (selection.kind === Kind.FIELD) {
1098 const fields = fieldMaps.map(fieldMap => fieldMap[selection.name.value]).filter(field => field != null);
1099 if (!fields.length) {
1100 return false;
1101 }
1102 if (selection.selectionSet != null) {
1103 return typesContainSelectionSet(fields.map(field => getNamedType(field.type)), selection.selectionSet);
1104 }
1105 }
1106 else if (selection.kind === Kind.INLINE_FRAGMENT && ((_a = selection.typeCondition) === null || _a === void 0 ? void 0 : _a.name.value) === types[0].name) {
1107 return typesContainSelectionSet(types, selection.selectionSet);
1108 }
1109 }
1110 return true;
1111}
1112
1113function isSubschemaConfig(value) {
1114 return Boolean(value === null || value === void 0 ? void 0 : value.schema);
1115}
1116function cloneSubschemaConfig(subschemaConfig) {
1117 var _a, _b;
1118 const newSubschemaConfig = {
1119 ...subschemaConfig,
1120 transforms: subschemaConfig.transforms != null ? [...subschemaConfig.transforms] : undefined,
1121 };
1122 if (newSubschemaConfig.merge != null) {
1123 newSubschemaConfig.merge = { ...subschemaConfig.merge };
1124 for (const typeName in newSubschemaConfig.merge) {
1125 const mergedTypeConfig = (newSubschemaConfig.merge[typeName] = { ...((_b = (_a = subschemaConfig.merge) === null || _a === void 0 ? void 0 : _a[typeName]) !== null && _b !== void 0 ? _b : {}) });
1126 if (mergedTypeConfig.entryPoints != null) {
1127 mergedTypeConfig.entryPoints = mergedTypeConfig.entryPoints.map(entryPoint => ({ ...entryPoint }));
1128 }
1129 if (mergedTypeConfig.fields != null) {
1130 const fields = (mergedTypeConfig.fields = { ...mergedTypeConfig.fields });
1131 for (const fieldName in fields) {
1132 fields[fieldName] = { ...fields[fieldName] };
1133 }
1134 }
1135 }
1136 }
1137 return newSubschemaConfig;
1138}
1139
1140function collectSubFields(info, typeName) {
1141 let subFieldNodes = Object.create(null);
1142 const visitedFragmentNames = Object.create(null);
1143 const type = info.schema.getType(typeName);
1144 const partialExecutionContext = {
1145 schema: info.schema,
1146 variableValues: info.variableValues,
1147 fragments: info.fragments,
1148 };
1149 for (const fieldNode of info.fieldNodes) {
1150 if (fieldNode.selectionSet) {
1151 subFieldNodes = collectFields(partialExecutionContext, type, fieldNode.selectionSet, subFieldNodes, visitedFragmentNames);
1152 }
1153 }
1154 return subFieldNodes;
1155}
1156const getFieldsNotInSubschema = memoizeInfoAnd2Objects(function getFieldsNotInSubschemaMemoized(info, subschema, mergedTypeInfo) {
1157 var _a, _b;
1158 const typeMap = isSubschemaConfig(subschema) ? mergedTypeInfo.typeMaps.get(subschema) : subschema.getTypeMap();
1159 if (!typeMap) {
1160 return [];
1161 }
1162 const typeName = mergedTypeInfo.typeName;
1163 const fields = typeMap[typeName].getFields();
1164 const subFieldNodes = collectSubFields(info, typeName);
1165 // TODO: Verify whether it is safe that extensions always exists.
1166 const stitchingInfo = (_a = info.schema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
1167 const fieldNodesByField = stitchingInfo === null || stitchingInfo === void 0 ? void 0 : stitchingInfo.fieldNodesByField;
1168 const fieldsNotInSchema = new Set();
1169 for (const responseKey in subFieldNodes) {
1170 const subFieldNodesForResponseKey = subFieldNodes[responseKey];
1171 const fieldName = subFieldNodesForResponseKey[0].name.value;
1172 if (!fields[fieldName]) {
1173 for (const subFieldNodeForResponseKey of subFieldNodesForResponseKey) {
1174 fieldsNotInSchema.add(subFieldNodeForResponseKey);
1175 }
1176 }
1177 const fieldNodesForField = (_b = fieldNodesByField === null || fieldNodesByField === void 0 ? void 0 : fieldNodesByField[typeName]) === null || _b === void 0 ? void 0 : _b[fieldName];
1178 if (fieldNodesForField) {
1179 for (const fieldNode of fieldNodesForField) {
1180 if (!fields[fieldNode.name.value]) {
1181 fieldsNotInSchema.add(fieldNode);
1182 }
1183 }
1184 }
1185 }
1186 return Array.from(fieldsNotInSchema);
1187});
1188
1189function resolveExternalValue(result, unpathedErrors, subschema, context, info, returnType = getReturnType(info), skipTypeMerging) {
1190 const type = getNullableType(returnType);
1191 if (result instanceof Error) {
1192 return result;
1193 }
1194 if (result == null) {
1195 return reportUnpathedErrorsViaNull(unpathedErrors);
1196 }
1197 if ('parseValue' in type) {
1198 return type.parseValue(result);
1199 }
1200 else if (isCompositeType(type)) {
1201 return resolveExternalObject(type, result, unpathedErrors, subschema, context, info, skipTypeMerging);
1202 }
1203 else if (isListType(type)) {
1204 return resolveExternalList(type, result, unpathedErrors, subschema, context, info, skipTypeMerging);
1205 }
1206}
1207function resolveExternalObject(type, object, unpathedErrors, subschema, context, info, skipTypeMerging) {
1208 var _a;
1209 // if we have already resolved this object, for example, when the identical object appears twice
1210 // in a list, see https://github.com/ardatan/graphql-tools/issues/2304
1211 if (isExternalObject(object)) {
1212 return object;
1213 }
1214 annotateExternalObject(object, unpathedErrors, subschema);
1215 if (skipTypeMerging || info == null) {
1216 return object;
1217 }
1218 const stitchingInfo = (_a = info.schema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
1219 if (stitchingInfo == null) {
1220 return object;
1221 }
1222 let typeName;
1223 if (isAbstractType(type)) {
1224 const resolvedType = info.schema.getType(object.__typename);
1225 if (resolvedType == null) {
1226 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?`);
1227 }
1228 typeName = resolvedType.name;
1229 }
1230 else {
1231 typeName = type.name;
1232 }
1233 const mergedTypeInfo = stitchingInfo.mergedTypes[typeName];
1234 let targetSubschemas;
1235 // Within the stitching context, delegation to a stitched GraphQLSchema or SubschemaConfig
1236 // will be redirected to the appropriate Subschema object, from which merge targets can be queried.
1237 if (mergedTypeInfo != null) {
1238 targetSubschemas = mergedTypeInfo.targetSubschemas.get(subschema);
1239 }
1240 // If there are no merge targets from the subschema, return.
1241 if (!targetSubschemas) {
1242 return object;
1243 }
1244 const fieldNodes = getFieldsNotInSubschema(info, subschema, mergedTypeInfo);
1245 return mergeFields(mergedTypeInfo, typeName, object, fieldNodes, subschema, targetSubschemas, context, info);
1246}
1247function resolveExternalList(type, list, unpathedErrors, subschema, context, info, skipTypeMerging) {
1248 return list.map(listMember => resolveExternalListMember(getNullableType(type.ofType), listMember, unpathedErrors, subschema, context, info, skipTypeMerging));
1249}
1250function resolveExternalListMember(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging) {
1251 if (listMember instanceof Error) {
1252 return listMember;
1253 }
1254 if (listMember == null) {
1255 return reportUnpathedErrorsViaNull(unpathedErrors);
1256 }
1257 if (isLeafType(type)) {
1258 return type.parseValue(listMember);
1259 }
1260 else if (isCompositeType(type)) {
1261 return resolveExternalObject(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging);
1262 }
1263 else if (isListType(type)) {
1264 return resolveExternalList(type, listMember, unpathedErrors, subschema, context, info, skipTypeMerging);
1265 }
1266}
1267const reportedErrors = new WeakMap();
1268function reportUnpathedErrorsViaNull(unpathedErrors) {
1269 if (unpathedErrors.length) {
1270 const unreportedErrors = [];
1271 for (const error of unpathedErrors) {
1272 if (!reportedErrors.has(error)) {
1273 unreportedErrors.push(error);
1274 reportedErrors.set(error, true);
1275 }
1276 }
1277 if (unreportedErrors.length) {
1278 if (unreportedErrors.length === 1) {
1279 return unreportedErrors[0];
1280 }
1281 const combinedError = new AggregateError(unreportedErrors);
1282 // We cast path as any for GraphQL.js 14 compat
1283 // locatedError path argument must be defined, but it is just forwarded to a constructor that allows a undefined value
1284 // https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/locatedError.js#L25
1285 // https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/GraphQLError.js#L19
1286 return locatedError(combinedError, undefined, unreportedErrors[0].path);
1287 }
1288 }
1289 return null;
1290}
1291function getReturnType(info) {
1292 if (info == null) {
1293 throw new Error(`Return type cannot be inferred without a source schema.`);
1294 }
1295 return info.returnType;
1296}
1297
1298function checkResultAndHandleErrors(result, delegationContext) {
1299 const { context, info, fieldName: responseKey = getResponseKey(info), subschema, returnType = getReturnType$1(info), skipTypeMerging, onLocatedError, } = delegationContext;
1300 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);
1301 return resolveExternalValue(data, unpathedErrors, subschema, context, info, returnType, skipTypeMerging);
1302}
1303function mergeDataAndErrors(data, errors, path, onLocatedError, index = 1) {
1304 var _a;
1305 if (data == null) {
1306 if (!errors.length) {
1307 return { data: null, unpathedErrors: [] };
1308 }
1309 if (errors.length === 1) {
1310 const error = onLocatedError ? onLocatedError(errors[0]) : errors[0];
1311 const newPath = path === undefined ? error.path : error.path === undefined ? path : path.concat(error.path.slice(1));
1312 return { data: relocatedError(errors[0], newPath), unpathedErrors: [] };
1313 }
1314 // We cast path as any for GraphQL.js 14 compat
1315 // locatedError path argument must be defined, but it is just forwarded to a constructor that allows a undefined value
1316 // https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/locatedError.js#L25
1317 // https://github.com/graphql/graphql-js/blob/b4bff0ba9c15c9d7245dd68556e754c41f263289/src/error/GraphQLError.js#L19
1318 const newError = locatedError(new AggregateError(errors), undefined, path);
1319 return { data: newError, unpathedErrors: [] };
1320 }
1321 if (!errors.length) {
1322 return { data, unpathedErrors: [] };
1323 }
1324 const unpathedErrors = [];
1325 const errorMap = new Map();
1326 for (const error of errors) {
1327 const pathSegment = (_a = error.path) === null || _a === void 0 ? void 0 : _a[index];
1328 if (pathSegment != null) {
1329 let pathSegmentErrors = errorMap.get(pathSegment);
1330 if (pathSegmentErrors === undefined) {
1331 pathSegmentErrors = [error];
1332 errorMap.set(pathSegment, pathSegmentErrors);
1333 }
1334 else {
1335 pathSegmentErrors.push(error);
1336 }
1337 }
1338 else {
1339 unpathedErrors.push(error);
1340 }
1341 }
1342 for (const [pathSegment, pathSegmentErrors] of errorMap) {
1343 if (data[pathSegment] !== undefined) {
1344 const { data: newData, unpathedErrors: newErrors } = mergeDataAndErrors(data[pathSegment], pathSegmentErrors, path, onLocatedError, index + 1);
1345 data[pathSegment] = newData;
1346 unpathedErrors.push(...newErrors);
1347 }
1348 else {
1349 unpathedErrors.push(...pathSegmentErrors);
1350 }
1351 }
1352 return { data, unpathedErrors };
1353}
1354function getResponseKey(info) {
1355 if (info == null) {
1356 throw new Error(`Data cannot be extracted from result without an explicit key or source schema.`);
1357 }
1358 return getResponseKeyFromInfo(info);
1359}
1360function getReturnType$1(info) {
1361 if (info == null) {
1362 throw new Error(`Return type cannot be inferred without a source schema.`);
1363 }
1364 return info.returnType;
1365}
1366
1367class Transformer {
1368 constructor(context) {
1369 this.transformations = [];
1370 this.delegationContext = context;
1371 const transforms = context.transforms;
1372 const delegationTransforms = transforms.slice().reverse();
1373 for (const transform of delegationTransforms) {
1374 this.addTransform(transform, {});
1375 }
1376 }
1377 addTransform(transform, context = {}) {
1378 this.transformations.push({ transform, context });
1379 }
1380 transformRequest(originalRequest) {
1381 var _a;
1382 let request = {
1383 ...originalRequest,
1384 document: prepareGatewayDocument(originalRequest.document, this.delegationContext.transformedSchema, this.delegationContext.returnType, (_a = this.delegationContext.info) === null || _a === void 0 ? void 0 : _a.schema),
1385 };
1386 for (const transformation of this.transformations) {
1387 if (transformation.transform.transformRequest) {
1388 request = transformation.transform.transformRequest(request, this.delegationContext, transformation.context);
1389 }
1390 }
1391 return finalizeGatewayRequest(request, this.delegationContext);
1392 }
1393 transformResult(originalResult) {
1394 let result = originalResult;
1395 // from rigth to left
1396 for (let i = this.transformations.length - 1; i >= 0; i--) {
1397 const transformation = this.transformations[i];
1398 if (transformation.transform.transformResult) {
1399 result = transformation.transform.transformResult(result, this.delegationContext, transformation.context);
1400 }
1401 }
1402 return checkResultAndHandleErrors(result, this.delegationContext);
1403 }
1404}
1405
1406function getDelegatingOperation(parentType, schema) {
1407 if (parentType === schema.getMutationType()) {
1408 return 'mutation';
1409 }
1410 else if (parentType === schema.getSubscriptionType()) {
1411 return 'subscription';
1412 }
1413 return 'query';
1414}
1415function createRequestFromInfo({ info, rootValue, operationName, operation = getDelegatingOperation(info.parentType, info.schema), fieldName = info.fieldName, selectionSet, fieldNodes = info.fieldNodes, context, }) {
1416 return createRequest({
1417 sourceSchema: info.schema,
1418 sourceParentType: info.parentType,
1419 sourceFieldName: info.fieldName,
1420 fragments: info.fragments,
1421 variableDefinitions: info.operation.variableDefinitions,
1422 variableValues: info.variableValues,
1423 targetRootValue: rootValue,
1424 targetOperationName: operationName,
1425 targetOperation: operation,
1426 targetFieldName: fieldName,
1427 selectionSet,
1428 fieldNodes,
1429 context,
1430 info,
1431 });
1432}
1433function createRequest({ sourceSchema, sourceParentType, sourceFieldName, fragments, variableDefinitions, variableValues, targetRootValue, targetOperationName, targetOperation, targetFieldName, selectionSet, fieldNodes, context, info, }) {
1434 var _a, _b;
1435 let newSelectionSet;
1436 const argumentNodeMap = Object.create(null);
1437 if (selectionSet != null) {
1438 newSelectionSet = selectionSet;
1439 }
1440 else {
1441 const selections = [];
1442 for (const fieldNode of fieldNodes || []) {
1443 if (fieldNode.selectionSet) {
1444 for (const selection of fieldNode.selectionSet.selections) {
1445 selections.push(selection);
1446 }
1447 }
1448 }
1449 newSelectionSet = selections.length
1450 ? {
1451 kind: Kind.SELECTION_SET,
1452 selections,
1453 }
1454 : undefined;
1455 const args = (_a = fieldNodes === null || fieldNodes === void 0 ? void 0 : fieldNodes[0]) === null || _a === void 0 ? void 0 : _a.arguments;
1456 if (args) {
1457 for (const argNode of args) {
1458 argumentNodeMap[argNode.name.value] = argNode;
1459 }
1460 }
1461 }
1462 const newVariables = Object.create(null);
1463 const variableDefinitionMap = Object.create(null);
1464 if (sourceSchema != null && variableDefinitions != null) {
1465 for (const def of variableDefinitions) {
1466 const varName = def.variable.name.value;
1467 variableDefinitionMap[varName] = def;
1468 const varType = typeFromAST(sourceSchema, def.type);
1469 const serializedValue = serializeInputValue(varType, variableValues === null || variableValues === void 0 ? void 0 : variableValues[varName]);
1470 if (serializedValue !== undefined) {
1471 newVariables[varName] = serializedValue;
1472 }
1473 }
1474 }
1475 if (sourceParentType != null && sourceFieldName != null) {
1476 updateArgumentsWithDefaults(sourceParentType, sourceFieldName, argumentNodeMap, variableDefinitionMap, newVariables);
1477 }
1478 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;
1479 if (rootFieldName === undefined) {
1480 throw new Error(`Either "targetFieldName" or a non empty "fieldNodes" array must be provided.`);
1481 }
1482 const rootfieldNode = {
1483 kind: Kind.FIELD,
1484 arguments: Object.values(argumentNodeMap),
1485 name: {
1486 kind: Kind.NAME,
1487 value: rootFieldName,
1488 },
1489 selectionSet: newSelectionSet,
1490 };
1491 const operationName = targetOperationName
1492 ? {
1493 kind: Kind.NAME,
1494 value: targetOperationName,
1495 }
1496 : undefined;
1497 const operationDefinition = {
1498 kind: Kind.OPERATION_DEFINITION,
1499 name: operationName,
1500 operation: targetOperation,
1501 variableDefinitions: Object.values(variableDefinitionMap),
1502 selectionSet: {
1503 kind: Kind.SELECTION_SET,
1504 selections: [rootfieldNode],
1505 },
1506 };
1507 const definitions = [operationDefinition];
1508 if (fragments != null) {
1509 for (const fragmentName in fragments) {
1510 const fragment = fragments[fragmentName];
1511 definitions.push(fragment);
1512 }
1513 }
1514 const document = {
1515 kind: Kind.DOCUMENT,
1516 definitions,
1517 };
1518 return {
1519 document,
1520 variables: newVariables,
1521 rootValue: targetRootValue,
1522 operationName: targetOperationName,
1523 operationType: targetOperation,
1524 context,
1525 info,
1526 };
1527}
1528function updateArgumentsWithDefaults(sourceParentType, sourceFieldName, argumentNodeMap, variableDefinitionMap, variableValues) {
1529 const generateVariableName = createVariableNameGenerator(variableDefinitionMap);
1530 const sourceField = sourceParentType.getFields()[sourceFieldName];
1531 for (const argument of sourceField.args) {
1532 const argName = argument.name;
1533 const sourceArgType = argument.type;
1534 if (argumentNodeMap[argName] === undefined) {
1535 const defaultValue = argument.defaultValue;
1536 if (defaultValue !== undefined) {
1537 updateArgument(argumentNodeMap, variableDefinitionMap, variableValues, argName, generateVariableName(argName), sourceArgType, serializeInputValue(sourceArgType, defaultValue));
1538 }
1539 }
1540 }
1541}
1542
1543/**
1544 * Resolver that knows how to:
1545 * a) handle aliases for proxied schemas
1546 * b) handle errors from proxied schemas
1547 * c) handle external to internal enum conversion
1548 */
1549function defaultMergedResolver(parent, args, context, info) {
1550 if (!parent) {
1551 return null;
1552 }
1553 const responseKey = getResponseKeyFromInfo(info);
1554 // check to see if parent is not a proxied result, i.e. if parent resolver was manually overwritten
1555 // See https://github.com/apollographql/graphql-tools/issues/967
1556 if (!isExternalObject(parent)) {
1557 return defaultFieldResolver(parent, args, context, info);
1558 }
1559 const data = parent[responseKey];
1560 const unpathedErrors = getUnpathedErrors(parent);
1561 const subschema = getSubschema(parent, responseKey);
1562 return resolveExternalValue(data, unpathedErrors, subschema, context, info);
1563}
1564
1565function delegateToSchema(options) {
1566 const { info, schema, rootValue, operationName, operation = getDelegatingOperation(info.parentType, info.schema), fieldName = info.fieldName, selectionSet, fieldNodes, context, } = options;
1567 const request = createRequestFromInfo({
1568 info,
1569 operation,
1570 fieldName,
1571 selectionSet,
1572 fieldNodes,
1573 rootValue: rootValue !== null && rootValue !== void 0 ? rootValue : schema.rootValue,
1574 operationName,
1575 context,
1576 });
1577 return delegateRequest({
1578 ...options,
1579 request,
1580 });
1581}
1582function getDelegationReturnType(targetSchema, operation, fieldName) {
1583 const rootType = getDefinedRootType(targetSchema, operation);
1584 return rootType.getFields()[fieldName].type;
1585}
1586function delegateRequest(options) {
1587 const delegationContext = getDelegationContext(options);
1588 const transformer = new Transformer(delegationContext);
1589 const processedRequest = transformer.transformRequest(options.request);
1590 if (options.validateRequest) {
1591 validateRequest(delegationContext, processedRequest.document);
1592 }
1593 const executor = getExecutor(delegationContext);
1594 return new ValueOrPromise(() => executor(processedRequest))
1595 .then(originalResult => {
1596 if (isAsyncIterable(originalResult)) {
1597 // "subscribe" to the subscription result and map the result through the transforms
1598 return mapAsyncIterator(originalResult, result => transformer.transformResult(result));
1599 }
1600 return transformer.transformResult(originalResult);
1601 })
1602 .resolve();
1603}
1604function getDelegationContext({ request, schema, fieldName, returnType, args, info, transforms = [], transformedSchema, skipTypeMerging = false, }) {
1605 var _a, _b, _c, _d;
1606 const { operationType: operation, context, operationName, document } = request;
1607 let operationDefinition;
1608 let targetFieldName;
1609 if (fieldName == null) {
1610 operationDefinition = getOperationAST(document, operationName);
1611 if (operationDefinition == null) {
1612 throw new Error('Cannot infer main operation from the provided document.');
1613 }
1614 targetFieldName = (operationDefinition === null || operationDefinition === void 0 ? void 0 : operationDefinition.selectionSet.selections[0]).name.value;
1615 }
1616 else {
1617 targetFieldName = fieldName;
1618 }
1619 const stitchingInfo = (_a = info === null || info === void 0 ? void 0 : info.schema.extensions) === null || _a === void 0 ? void 0 : _a['stitchingInfo'];
1620 const subschemaOrSubschemaConfig = (_b = stitchingInfo === null || stitchingInfo === void 0 ? void 0 : stitchingInfo.subschemaMap.get(schema)) !== null && _b !== void 0 ? _b : schema;
1621 if (isSubschemaConfig(subschemaOrSubschemaConfig)) {
1622 const targetSchema = subschemaOrSubschemaConfig.schema;
1623 return {
1624 subschema: schema,
1625 subschemaConfig: subschemaOrSubschemaConfig,
1626 targetSchema,
1627 operation,
1628 fieldName: targetFieldName,
1629 args,
1630 context,
1631 info,
1632 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),
1633 transforms: subschemaOrSubschemaConfig.transforms != null
1634 ? subschemaOrSubschemaConfig.transforms.concat(transforms)
1635 : transforms,
1636 transformedSchema: transformedSchema !== null && transformedSchema !== void 0 ? transformedSchema : (subschemaOrSubschemaConfig instanceof Subschema ? subschemaOrSubschemaConfig.transformedSchema : targetSchema),
1637 skipTypeMerging,
1638 };
1639 }
1640 return {
1641 subschema: schema,
1642 subschemaConfig: undefined,
1643 targetSchema: subschemaOrSubschemaConfig,
1644 operation,
1645 fieldName: targetFieldName,
1646 args,
1647 context,
1648 info,
1649 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),
1650 transforms,
1651 transformedSchema: transformedSchema !== null && transformedSchema !== void 0 ? transformedSchema : subschemaOrSubschemaConfig,
1652 skipTypeMerging,
1653 };
1654}
1655function validateRequest(delegationContext, document) {
1656 const errors = validate(delegationContext.targetSchema, document);
1657 if (errors.length > 0) {
1658 if (errors.length > 1) {
1659 const combinedError = new AggregateError(errors);
1660 throw combinedError;
1661 }
1662 const error = errors[0];
1663 throw error.originalError || error;
1664 }
1665}
1666function getExecutor(delegationContext) {
1667 var _a, _b;
1668 const { subschemaConfig, targetSchema, context } = delegationContext;
1669 let executor = (subschemaConfig === null || subschemaConfig === void 0 ? void 0 : subschemaConfig.executor) || createDefaultExecutor(targetSchema);
1670 if (subschemaConfig === null || subschemaConfig === void 0 ? void 0 : subschemaConfig.batch) {
1671 const batchingOptions = subschemaConfig === null || subschemaConfig === void 0 ? void 0 : subschemaConfig.batchingOptions;
1672 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);
1673 }
1674 return executor;
1675}
1676const defaultExecutorCache = new WeakMap();
1677function createDefaultExecutor(schema) {
1678 let defaultExecutor = defaultExecutorCache.get(schema);
1679 if (!defaultExecutor) {
1680 defaultExecutor = function defaultExecutor({ document, context, variables, rootValue, operationName, operationType, }) {
1681 const executionArgs = {
1682 schema,
1683 document,
1684 contextValue: context,
1685 variableValues: variables,
1686 rootValue,
1687 operationName,
1688 };
1689 if (operationType === 'subscription') {
1690 return subscribe(executionArgs);
1691 }
1692 return execute(executionArgs);
1693 };
1694 defaultExecutorCache.set(schema, defaultExecutor);
1695 }
1696 return defaultExecutor;
1697}
1698
1699export { Subschema, Transformer, annotateExternalObject, applySchemaTransforms, cloneSubschemaConfig, createDefaultExecutor, createRequest, createRequestFromInfo, defaultMergedResolver, delegateRequest, delegateToSchema, getDelegatingOperation, getSubschema, getUnpathedErrors, isExternalObject, isSubschema, isSubschemaConfig, mergeFields, resolveExternalValue };