UNPKG

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