UNPKG

160 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
7const graphql = require('graphql');
8const AggregateError = _interopDefault(require('@ardatan/aggregate-error'));
9const camelCase = require('camel-case');
10
11const asArray = (fns) => (Array.isArray(fns) ? fns : fns ? [fns] : []);
12function isEqual(a, b) {
13 if (Array.isArray(a) && Array.isArray(b)) {
14 if (a.length !== b.length) {
15 return false;
16 }
17 for (let index = 0; index < a.length; index++) {
18 if (a[index] !== b[index]) {
19 return false;
20 }
21 }
22 return true;
23 }
24 return a === b || (!a && !b);
25}
26function isNotEqual(a, b) {
27 return !isEqual(a, b);
28}
29function isDocumentString(str) {
30 // XXX: is-valid-path or is-glob treat SDL as a valid path
31 // (`scalar Date` for example)
32 // this why checking the extension is fast enough
33 // and prevent from parsing the string in order to find out
34 // if the string is a SDL
35 if (/\.[a-z0-9]+$/i.test(str)) {
36 return false;
37 }
38 try {
39 graphql.parse(str);
40 return true;
41 }
42 catch (e) { }
43 return false;
44}
45const invalidPathRegex = /[‘“!$%&^<=>`]/;
46function isValidPath(str) {
47 return typeof str === 'string' && !invalidPathRegex.test(str);
48}
49function compareStrings(a, b) {
50 if (a.toString() < b.toString()) {
51 return -1;
52 }
53 if (a.toString() > b.toString()) {
54 return 1;
55 }
56 return 0;
57}
58function nodeToString(a) {
59 if ('alias' in a) {
60 return a.alias.value;
61 }
62 if ('name' in a) {
63 return a.name.value;
64 }
65 return a.kind;
66}
67function compareNodes(a, b, customFn) {
68 const aStr = nodeToString(a);
69 const bStr = nodeToString(b);
70 if (typeof customFn === 'function') {
71 return customFn(aStr, bStr);
72 }
73 return compareStrings(aStr, bStr);
74}
75
76function debugLog(...args) {
77 if (process && process.env && process.env.DEBUG && !process.env.GQL_tools_NODEBUG) {
78 // tslint:disable-next-line: no-console
79 console.log(...args);
80 }
81}
82
83const fixWindowsPath = (path) => path.replace(/\\/g, '/');
84
85const flattenArray = (arr) => arr.reduce((acc, next) => acc.concat(Array.isArray(next) ? flattenArray(next) : next), []);
86
87const MAX_ARRAY_LENGTH = 10;
88const MAX_RECURSIVE_DEPTH = 2;
89/**
90 * Used to print values in error messages.
91 */
92function inspect(value) {
93 return formatValue(value, []);
94}
95function formatValue(value, seenValues) {
96 switch (typeof value) {
97 case 'string':
98 return JSON.stringify(value);
99 case 'function':
100 return value.name ? `[function ${value.name}]` : '[function]';
101 case 'object':
102 if (value === null) {
103 return 'null';
104 }
105 return formatObjectValue(value, seenValues);
106 default:
107 return String(value);
108 }
109}
110function formatObjectValue(value, previouslySeenValues) {
111 if (previouslySeenValues.indexOf(value) !== -1) {
112 return '[Circular]';
113 }
114 const seenValues = [...previouslySeenValues, value];
115 const customInspectFn = getCustomFn(value);
116 if (customInspectFn !== undefined) {
117 const customValue = customInspectFn.call(value);
118 // check for infinite recursion
119 if (customValue !== value) {
120 return typeof customValue === 'string' ? customValue : formatValue(customValue, seenValues);
121 }
122 }
123 else if (Array.isArray(value)) {
124 return formatArray(value, seenValues);
125 }
126 return formatObject(value, seenValues);
127}
128function formatObject(object, seenValues) {
129 const keys = Object.keys(object);
130 if (keys.length === 0) {
131 return '{}';
132 }
133 if (seenValues.length > MAX_RECURSIVE_DEPTH) {
134 return '[' + getObjectTag(object) + ']';
135 }
136 const properties = keys.map(key => {
137 const value = formatValue(object[key], seenValues);
138 return key + ': ' + value;
139 });
140 return '{ ' + properties.join(', ') + ' }';
141}
142function formatArray(array, seenValues) {
143 if (array.length === 0) {
144 return '[]';
145 }
146 if (seenValues.length > MAX_RECURSIVE_DEPTH) {
147 return '[Array]';
148 }
149 const len = Math.min(MAX_ARRAY_LENGTH, array.length);
150 const remaining = array.length - len;
151 const items = [];
152 for (let i = 0; i < len; ++i) {
153 items.push(formatValue(array[i], seenValues));
154 }
155 if (remaining === 1) {
156 items.push('... 1 more item');
157 }
158 else if (remaining > 1) {
159 items.push(`... ${remaining.toString(10)} more items`);
160 }
161 return '[' + items.join(', ') + ']';
162}
163function getCustomFn(obj) {
164 if (typeof obj.inspect === 'function') {
165 return obj.inspect;
166 }
167}
168function getObjectTag(obj) {
169 const tag = Object.prototype.toString
170 .call(obj)
171 .replace(/^\[object /, '')
172 .replace(/]$/, '');
173 if (tag === 'Object' && typeof obj.constructor === 'function') {
174 const name = obj.constructor.name;
175 if (typeof name === 'string' && name !== '') {
176 return name;
177 }
178 }
179 return tag;
180}
181
182/**
183 * Prepares an object map of argument values given a list of argument
184 * definitions and list of argument AST nodes.
185 *
186 * Note: The returned value is a plain Object with a prototype, since it is
187 * exposed to user code. Care should be taken to not pull values from the
188 * Object prototype.
189 */
190function getArgumentValues(def, node, variableValues = {}) {
191 var _a;
192 const variableMap = Object.entries(variableValues).reduce((prev, [key, value]) => ({
193 ...prev,
194 [key]: value,
195 }), {});
196 const coercedValues = {};
197 // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
198 const argumentNodes = (_a = node.arguments) !== null && _a !== void 0 ? _a : [];
199 const argNodeMap = argumentNodes.reduce((prev, arg) => ({
200 ...prev,
201 [arg.name.value]: arg,
202 }), {});
203 for (const argDef of def.args) {
204 const name = argDef.name;
205 const argType = argDef.type;
206 const argumentNode = argNodeMap[name];
207 if (!argumentNode) {
208 if (argDef.defaultValue !== undefined) {
209 coercedValues[name] = argDef.defaultValue;
210 }
211 else if (graphql.isNonNullType(argType)) {
212 throw new graphql.GraphQLError(`Argument "${name}" of required type "${inspect(argType)}" ` + 'was not provided.', node);
213 }
214 continue;
215 }
216 const valueNode = argumentNode.value;
217 let isNull = valueNode.kind === graphql.Kind.NULL;
218 if (valueNode.kind === graphql.Kind.VARIABLE) {
219 const variableName = valueNode.name.value;
220 if (variableValues == null || !(variableName in variableMap)) {
221 if (argDef.defaultValue !== undefined) {
222 coercedValues[name] = argDef.defaultValue;
223 }
224 else if (graphql.isNonNullType(argType)) {
225 throw new graphql.GraphQLError(`Argument "${name}" of required type "${inspect(argType)}" ` +
226 `was provided the variable "$${variableName}" which was not provided a runtime value.`, valueNode);
227 }
228 continue;
229 }
230 isNull = variableValues[variableName] == null;
231 }
232 if (isNull && graphql.isNonNullType(argType)) {
233 throw new graphql.GraphQLError(`Argument "${name}" of non-null type "${inspect(argType)}" ` + 'must not be null.', valueNode);
234 }
235 const coercedValue = graphql.valueFromAST(valueNode, argType, variableValues);
236 if (coercedValue === undefined) {
237 // Note: ValuesOfCorrectTypeRule validation should catch this before
238 // execution. This is a runtime check to ensure execution does not
239 // continue with an invalid argument value.
240 throw new graphql.GraphQLError(`Argument "${name}" has invalid value ${graphql.print(valueNode)}.`, valueNode);
241 }
242 coercedValues[name] = coercedValue;
243 }
244 return coercedValues;
245}
246
247function getDirectives(schema, node) {
248 const schemaDirectives = schema && schema.getDirectives ? schema.getDirectives() : [];
249 const schemaDirectiveMap = schemaDirectives.reduce((schemaDirectiveMap, schemaDirective) => {
250 schemaDirectiveMap[schemaDirective.name] = schemaDirective;
251 return schemaDirectiveMap;
252 }, {});
253 let astNodes = [];
254 if (node.astNode) {
255 astNodes.push(node.astNode);
256 }
257 if ('extensionASTNodes' in node && node.extensionASTNodes) {
258 astNodes = [...astNodes, ...node.extensionASTNodes];
259 }
260 const result = {};
261 astNodes.forEach(astNode => {
262 if (astNode.directives) {
263 astNode.directives.forEach(directive => {
264 const schemaDirective = schemaDirectiveMap[directive.name.value];
265 if (schemaDirective) {
266 const directiveValue = getDirectiveValues(schemaDirective, astNode);
267 if (schemaDirective.isRepeatable) {
268 if (result[schemaDirective.name]) {
269 result[schemaDirective.name] = result[schemaDirective.name].concat([directiveValue]);
270 }
271 else {
272 result[schemaDirective.name] = [directiveValue];
273 }
274 }
275 else {
276 result[schemaDirective.name] = directiveValue;
277 }
278 }
279 });
280 }
281 });
282 return result;
283}
284// graphql-js getDirectiveValues does not handle repeatable directives
285function getDirectiveValues(directiveDef, node) {
286 if (node.directives) {
287 if (directiveDef.isRepeatable) {
288 const directiveNodes = node.directives.filter(directive => directive.name.value === directiveDef.name);
289 return directiveNodes.map(directiveNode => getArgumentValues(directiveDef, directiveNode));
290 }
291 const directiveNode = node.directives.find(directive => directive.name.value === directiveDef.name);
292 return getArgumentValues(directiveDef, directiveNode);
293 }
294}
295
296function isObjectTypeDefinitionOrExtension(obj) {
297 return obj && (obj.kind === 'ObjectTypeDefinition' || obj.kind === 'ObjectTypeExtension');
298}
299function parseDirectiveValue(value) {
300 switch (value.kind) {
301 case graphql.Kind.INT:
302 return parseInt(value.value);
303 case graphql.Kind.FLOAT:
304 return parseFloat(value.value);
305 case graphql.Kind.BOOLEAN:
306 return Boolean(value.value);
307 case graphql.Kind.STRING:
308 case graphql.Kind.ENUM:
309 return value.value;
310 case graphql.Kind.LIST:
311 return value.values.map(v => parseDirectiveValue(v));
312 case graphql.Kind.OBJECT:
313 return value.fields.reduce((prev, v) => ({ ...prev, [v.name.value]: parseDirectiveValue(v.value) }), {});
314 case graphql.Kind.NULL:
315 return null;
316 default:
317 return null;
318 }
319}
320function getFieldsWithDirectives(documentNode) {
321 const result = {};
322 const allTypes = documentNode.definitions.filter(isObjectTypeDefinitionOrExtension);
323 for (const type of allTypes) {
324 const typeName = type.name.value;
325 for (const field of type.fields) {
326 if (field.directives && field.directives.length > 0) {
327 const fieldName = field.name.value;
328 const key = `${typeName}.${fieldName}`;
329 const directives = field.directives.map(d => ({
330 name: d.name.value,
331 args: (d.arguments || []).reduce((prev, arg) => ({ ...prev, [arg.name.value]: parseDirectiveValue(arg.value) }), {}),
332 }));
333 result[key] = directives;
334 }
335 }
336 }
337 return result;
338}
339
340function getImplementingTypes(interfaceName, schema) {
341 const allTypesMap = schema.getTypeMap();
342 const result = [];
343 for (const graphqlTypeName in allTypesMap) {
344 const graphqlType = allTypesMap[graphqlTypeName];
345 if (graphql.isObjectType(graphqlType)) {
346 const allInterfaces = graphqlType.getInterfaces();
347 if (allInterfaces.find(int => int.name === interfaceName)) {
348 result.push(graphqlType.name);
349 }
350 }
351 }
352 return result;
353}
354
355function createSchemaDefinition(def, config) {
356 const schemaRoot = {};
357 if (def.query) {
358 schemaRoot.query = def.query.toString();
359 }
360 if (def.mutation) {
361 schemaRoot.mutation = def.mutation.toString();
362 }
363 if (def.subscription) {
364 schemaRoot.subscription = def.subscription.toString();
365 }
366 const fields = Object.keys(schemaRoot)
367 .map(rootType => (schemaRoot[rootType] ? `${rootType}: ${schemaRoot[rootType]}` : null))
368 .filter(a => a);
369 if (fields.length) {
370 return `schema { ${fields.join('\n')} }`;
371 }
372 if (config && config.force) {
373 return ` schema { query: Query } `;
374 }
375 return undefined;
376}
377
378function printSchemaWithDirectives(schema, _options = {}) {
379 var _a;
380 const typesMap = schema.getTypeMap();
381 const result = [getSchemaDefinition(schema)];
382 for (const typeName in typesMap) {
383 const type = typesMap[typeName];
384 const isPredefinedScalar = graphql.isScalarType(type) && graphql.isSpecifiedScalarType(type);
385 const isIntrospection = graphql.isIntrospectionType(type);
386 if (isPredefinedScalar || isIntrospection) {
387 continue;
388 }
389 // KAMIL: we might want to turn on descriptions in future
390 result.push(graphql.print((_a = correctType(typeName, typesMap)) === null || _a === void 0 ? void 0 : _a.astNode));
391 }
392 const directives = schema.getDirectives();
393 for (const directive of directives) {
394 if (directive.astNode) {
395 result.push(graphql.print(directive.astNode));
396 }
397 }
398 return result.join('\n');
399}
400function extendDefinition(type) {
401 switch (type.astNode.kind) {
402 case graphql.Kind.OBJECT_TYPE_DEFINITION:
403 return {
404 ...type.astNode,
405 fields: type.astNode.fields.concat(type.extensionASTNodes.reduce((fields, node) => fields.concat(node.fields), [])),
406 };
407 case graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION:
408 return {
409 ...type.astNode,
410 fields: type.astNode.fields.concat(type.extensionASTNodes.reduce((fields, node) => fields.concat(node.fields), [])),
411 };
412 default:
413 return type.astNode;
414 }
415}
416function correctType(typeName, typesMap) {
417 var _a;
418 const type = typesMap[typeName];
419 type.name = typeName.toString();
420 if (type.astNode && type.extensionASTNodes) {
421 type.astNode = type.extensionASTNodes ? extendDefinition(type) : type.astNode;
422 }
423 const doc = graphql.parse(graphql.printType(type));
424 const fixedAstNode = doc.definitions[0];
425 const originalAstNode = type === null || type === void 0 ? void 0 : type.astNode;
426 if (originalAstNode) {
427 fixedAstNode.directives = originalAstNode === null || originalAstNode === void 0 ? void 0 : originalAstNode.directives;
428 if (fixedAstNode && 'fields' in fixedAstNode && originalAstNode && 'fields' in originalAstNode) {
429 for (const fieldDefinitionNode of fixedAstNode.fields) {
430 const originalFieldDefinitionNode = originalAstNode.fields.find(field => field.name.value === fieldDefinitionNode.name.value);
431 fieldDefinitionNode.directives = originalFieldDefinitionNode === null || originalFieldDefinitionNode === void 0 ? void 0 : originalFieldDefinitionNode.directives;
432 if (fieldDefinitionNode &&
433 'arguments' in fieldDefinitionNode &&
434 originalFieldDefinitionNode &&
435 'arguments' in originalFieldDefinitionNode) {
436 for (const argument of fieldDefinitionNode.arguments) {
437 const originalArgumentNode = (_a = originalFieldDefinitionNode.arguments) === null || _a === void 0 ? void 0 : _a.find(arg => arg.name.value === argument.name.value);
438 argument.directives = originalArgumentNode.directives;
439 }
440 }
441 }
442 }
443 else if (fixedAstNode && 'values' in fixedAstNode && originalAstNode && 'values' in originalAstNode) {
444 for (const valueDefinitionNode of fixedAstNode.values) {
445 const originalValueDefinitionNode = originalAstNode.values.find(valueNode => valueNode.name.value === valueDefinitionNode.name.value);
446 valueDefinitionNode.directives = originalValueDefinitionNode === null || originalValueDefinitionNode === void 0 ? void 0 : originalValueDefinitionNode.directives;
447 }
448 }
449 }
450 type.astNode = fixedAstNode;
451 return type;
452}
453function getSchemaDefinition(schema) {
454 if (!Object.getOwnPropertyDescriptor(schema, 'astNode').get && schema.astNode) {
455 return graphql.print(schema.astNode);
456 }
457 else {
458 return createSchemaDefinition({
459 query: schema.getQueryType(),
460 mutation: schema.getMutationType(),
461 subscription: schema.getSubscriptionType(),
462 });
463 }
464}
465
466async function validateGraphQlDocuments(schema, documentFiles, effectiveRules) {
467 effectiveRules = effectiveRules || createDefaultRules();
468 const allFragments = [];
469 documentFiles.forEach(documentFile => {
470 if (documentFile.document) {
471 for (const definitionNode of documentFile.document.definitions) {
472 if (definitionNode.kind === graphql.Kind.FRAGMENT_DEFINITION) {
473 allFragments.push(definitionNode);
474 }
475 }
476 }
477 });
478 const allErrors = [];
479 await Promise.all(documentFiles.map(async (documentFile) => {
480 const documentToValidate = {
481 kind: graphql.Kind.DOCUMENT,
482 definitions: [...allFragments, ...documentFile.document.definitions].filter((definition, index, list) => {
483 if (definition.kind === graphql.Kind.FRAGMENT_DEFINITION) {
484 const firstIndex = list.findIndex(def => def.kind === graphql.Kind.FRAGMENT_DEFINITION && def.name.value === definition.name.value);
485 const isDuplicated = firstIndex !== index;
486 if (isDuplicated) {
487 return false;
488 }
489 }
490 return true;
491 }),
492 };
493 const errors = graphql.validate(schema, documentToValidate, effectiveRules);
494 if (errors.length > 0) {
495 allErrors.push({
496 filePath: documentFile.location,
497 errors,
498 });
499 }
500 }));
501 return allErrors;
502}
503function checkValidationErrors(loadDocumentErrors) {
504 if (loadDocumentErrors.length > 0) {
505 const errors = [];
506 for (const loadDocumentError of loadDocumentErrors) {
507 for (const graphQLError of loadDocumentError.errors) {
508 const error = new Error();
509 error.name = 'GraphQLDocumentError';
510 error.message = `${error.name}: ${graphQLError.message}`;
511 error.stack = error.message;
512 graphQLError.locations.forEach(location => (error.stack += `\n at ${loadDocumentError.filePath}:${location.line}:${location.column}`));
513 errors.push(error);
514 }
515 }
516 throw new AggregateError(errors);
517 }
518}
519function createDefaultRules() {
520 const ignored = ['NoUnusedFragmentsRule', 'NoUnusedVariablesRule', 'KnownDirectivesRule'];
521 // GraphQL v14 has no Rule suffix in function names
522 // Adding `*Rule` makes validation backwards compatible
523 ignored.forEach(rule => {
524 ignored.push(rule.replace(/Rule$/, ''));
525 });
526 return graphql.specifiedRules.filter((f) => !ignored.includes(f.name));
527}
528
529function buildFixedSchema(schema, options) {
530 return graphql.buildSchema(printSchemaWithDirectives(schema, options), {
531 noLocation: true,
532 ...(options || {}),
533 });
534}
535function fixSchemaAst(schema, options) {
536 let schemaWithValidAst;
537 if (!schema.astNode) {
538 Object.defineProperty(schema, 'astNode', {
539 get() {
540 if (!schemaWithValidAst) {
541 schemaWithValidAst = buildFixedSchema(schema, options);
542 }
543 return schemaWithValidAst.astNode;
544 },
545 });
546 }
547 if (!schema.extensionASTNodes) {
548 Object.defineProperty(schema, 'extensionASTNodes', {
549 get() {
550 if (!schemaWithValidAst) {
551 schemaWithValidAst = buildFixedSchema(schema, options);
552 }
553 return schemaWithValidAst.extensionASTNodes;
554 },
555 });
556 }
557 return schema;
558}
559
560function stripBOM(content) {
561 content = content.toString();
562 // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
563 // because the buffer-to-string conversion in `fs.readFileSync()`
564 // translates it to FEFF, the UTF-16 BOM.
565 if (content.charCodeAt(0) === 0xfeff) {
566 content = content.slice(1);
567 }
568 return content;
569}
570function parseBOM(content) {
571 return JSON.parse(stripBOM(content));
572}
573function parseGraphQLJSON(location, jsonContent, options) {
574 let parsedJson = parseBOM(jsonContent);
575 if (parsedJson.data) {
576 parsedJson = parsedJson.data;
577 }
578 if (parsedJson.kind === 'Document') {
579 const document = parsedJson;
580 return {
581 location,
582 document,
583 };
584 }
585 else if (parsedJson.__schema) {
586 const schema = graphql.buildClientSchema(parsedJson, options);
587 const rawSDL = printSchemaWithDirectives(schema, options);
588 return {
589 location,
590 document: graphql.parse(rawSDL, options),
591 rawSDL,
592 schema,
593 };
594 }
595 throw new Error(`Not valid JSON content`);
596}
597
598function parseGraphQLSDL(location, rawSDL, options) {
599 let document;
600 try {
601 document = graphql.parse(new graphql.Source(rawSDL, location), options);
602 }
603 catch (e) {
604 if (e.message.includes('EOF')) {
605 document = {
606 kind: graphql.Kind.DOCUMENT,
607 definitions: [],
608 };
609 }
610 else {
611 throw e;
612 }
613 }
614 return {
615 location,
616 document,
617 rawSDL,
618 };
619}
620
621/**
622 * Get all GraphQL types from schema without:
623 *
624 * - Query, Mutation, Subscription objects
625 * - Internal scalars added by parser
626 *
627 * @param schema
628 */
629function getUserTypesFromSchema(schema) {
630 const allTypesMap = schema.getTypeMap();
631 // tslint:disable-next-line: no-unnecessary-local-variable
632 const modelTypes = Object.values(allTypesMap).filter((graphqlType) => {
633 if (graphql.isObjectType(graphqlType)) {
634 // Filter out private types
635 if (graphqlType.name.startsWith('__')) {
636 return false;
637 }
638 if (schema.getMutationType() && graphqlType.name === schema.getMutationType().name) {
639 return false;
640 }
641 if (schema.getQueryType() && graphqlType.name === schema.getQueryType().name) {
642 return false;
643 }
644 if (schema.getSubscriptionType() && graphqlType.name === schema.getSubscriptionType().name) {
645 return false;
646 }
647 return true;
648 }
649 return false;
650 });
651 return modelTypes;
652}
653
654let operationVariables = [];
655let fieldTypeMap = new Map();
656function addOperationVariable(variable) {
657 operationVariables.push(variable);
658}
659function resetOperationVariables() {
660 operationVariables = [];
661}
662function resetFieldMap() {
663 fieldTypeMap = new Map();
664}
665function buildOperationName(name) {
666 return camelCase.camelCase(name);
667}
668function buildOperationNodeForField({ schema, kind, field, models, ignore, depthLimit, circularReferenceDepth, argNames, selectedFields = true, }) {
669 resetOperationVariables();
670 resetFieldMap();
671 const operationNode = buildOperationAndCollectVariables({
672 schema,
673 fieldName: field,
674 kind,
675 models: models || [],
676 ignore: ignore || [],
677 depthLimit: depthLimit || Infinity,
678 circularReferenceDepth: circularReferenceDepth || 1,
679 argNames,
680 selectedFields,
681 });
682 // attach variables
683 operationNode.variableDefinitions = [...operationVariables];
684 resetOperationVariables();
685 resetFieldMap();
686 return operationNode;
687}
688function buildOperationAndCollectVariables({ schema, fieldName, kind, models, ignore, depthLimit, circularReferenceDepth, argNames, selectedFields, }) {
689 const typeMap = {
690 query: schema.getQueryType(),
691 mutation: schema.getMutationType(),
692 subscription: schema.getSubscriptionType(),
693 };
694 const type = typeMap[kind];
695 const field = type.getFields()[fieldName];
696 const operationName = buildOperationName(`${fieldName}_${kind}`);
697 if (field.args) {
698 field.args.forEach(arg => {
699 const argName = arg.name;
700 if (!argNames || argNames.includes(argName)) {
701 addOperationVariable(resolveVariable(arg, argName));
702 }
703 });
704 }
705 return {
706 kind: graphql.Kind.OPERATION_DEFINITION,
707 operation: kind,
708 name: {
709 kind: 'Name',
710 value: operationName,
711 },
712 variableDefinitions: [],
713 selectionSet: {
714 kind: graphql.Kind.SELECTION_SET,
715 selections: [
716 resolveField({
717 type,
718 field,
719 models,
720 firstCall: true,
721 path: [],
722 ancestors: [],
723 ignore,
724 depthLimit,
725 circularReferenceDepth,
726 schema,
727 depth: 0,
728 argNames,
729 selectedFields,
730 }),
731 ],
732 },
733 };
734}
735function resolveSelectionSet({ parent, type, models, firstCall, path, ancestors, ignore, depthLimit, circularReferenceDepth, schema, depth, argNames, selectedFields, }) {
736 if (typeof selectedFields === 'boolean' && depth > depthLimit) {
737 return;
738 }
739 if (graphql.isUnionType(type)) {
740 const types = type.getTypes();
741 return {
742 kind: graphql.Kind.SELECTION_SET,
743 selections: types
744 .filter(t => !hasCircularRef([...ancestors, t], {
745 depth: circularReferenceDepth,
746 }))
747 .map(t => {
748 return {
749 kind: graphql.Kind.INLINE_FRAGMENT,
750 typeCondition: {
751 kind: graphql.Kind.NAMED_TYPE,
752 name: {
753 kind: graphql.Kind.NAME,
754 value: t.name,
755 },
756 },
757 selectionSet: resolveSelectionSet({
758 parent: type,
759 type: t,
760 models,
761 path,
762 ancestors,
763 ignore,
764 depthLimit,
765 circularReferenceDepth,
766 schema,
767 depth,
768 argNames,
769 selectedFields,
770 }),
771 };
772 })
773 .filter(fragmentNode => { var _a, _b; return ((_b = (_a = fragmentNode === null || fragmentNode === void 0 ? void 0 : fragmentNode.selectionSet) === null || _a === void 0 ? void 0 : _a.selections) === null || _b === void 0 ? void 0 : _b.length) > 0; }),
774 };
775 }
776 if (graphql.isInterfaceType(type)) {
777 const types = Object.values(schema.getTypeMap()).filter((t) => graphql.isObjectType(t) && t.getInterfaces().includes(type));
778 return {
779 kind: graphql.Kind.SELECTION_SET,
780 selections: types
781 .filter(t => !hasCircularRef([...ancestors, t], {
782 depth: circularReferenceDepth,
783 }))
784 .map(t => {
785 return {
786 kind: graphql.Kind.INLINE_FRAGMENT,
787 typeCondition: {
788 kind: graphql.Kind.NAMED_TYPE,
789 name: {
790 kind: graphql.Kind.NAME,
791 value: t.name,
792 },
793 },
794 selectionSet: resolveSelectionSet({
795 parent: type,
796 type: t,
797 models,
798 path,
799 ancestors,
800 ignore,
801 depthLimit,
802 circularReferenceDepth,
803 schema,
804 depth,
805 argNames,
806 selectedFields,
807 }),
808 };
809 })
810 .filter(fragmentNode => { var _a, _b; return ((_b = (_a = fragmentNode === null || fragmentNode === void 0 ? void 0 : fragmentNode.selectionSet) === null || _a === void 0 ? void 0 : _a.selections) === null || _b === void 0 ? void 0 : _b.length) > 0; }),
811 };
812 }
813 if (graphql.isObjectType(type)) {
814 const isIgnored = ignore.includes(type.name) || ignore.includes(`${parent.name}.${path[path.length - 1]}`);
815 const isModel = models.includes(type.name);
816 if (!firstCall && isModel && !isIgnored) {
817 return {
818 kind: graphql.Kind.SELECTION_SET,
819 selections: [
820 {
821 kind: graphql.Kind.FIELD,
822 name: {
823 kind: graphql.Kind.NAME,
824 value: 'id',
825 },
826 },
827 ],
828 };
829 }
830 const fields = type.getFields();
831 return {
832 kind: graphql.Kind.SELECTION_SET,
833 selections: Object.keys(fields)
834 .filter(fieldName => {
835 return !hasCircularRef([...ancestors, graphql.getNamedType(fields[fieldName].type)], {
836 depth: circularReferenceDepth,
837 });
838 })
839 .map(fieldName => {
840 const selectedSubFields = typeof selectedFields === 'object' ? selectedFields[fieldName] : true;
841 if (selectedSubFields) {
842 return resolveField({
843 type: type,
844 field: fields[fieldName],
845 models,
846 path: [...path, fieldName],
847 ancestors,
848 ignore,
849 depthLimit,
850 circularReferenceDepth,
851 schema,
852 depth,
853 argNames,
854 selectedFields: selectedSubFields,
855 });
856 }
857 })
858 .filter(f => {
859 var _a, _b;
860 if (f) {
861 if ('selectionSet' in f) {
862 return (_b = (_a = f.selectionSet) === null || _a === void 0 ? void 0 : _a.selections) === null || _b === void 0 ? void 0 : _b.length;
863 }
864 else {
865 return true;
866 }
867 }
868 return false;
869 }),
870 };
871 }
872}
873function resolveVariable(arg, name) {
874 function resolveVariableType(type) {
875 if (graphql.isListType(type)) {
876 return {
877 kind: graphql.Kind.LIST_TYPE,
878 type: resolveVariableType(type.ofType),
879 };
880 }
881 if (graphql.isNonNullType(type)) {
882 return {
883 kind: graphql.Kind.NON_NULL_TYPE,
884 type: resolveVariableType(type.ofType),
885 };
886 }
887 return {
888 kind: graphql.Kind.NAMED_TYPE,
889 name: {
890 kind: graphql.Kind.NAME,
891 value: type.name,
892 },
893 };
894 }
895 return {
896 kind: graphql.Kind.VARIABLE_DEFINITION,
897 variable: {
898 kind: graphql.Kind.VARIABLE,
899 name: {
900 kind: graphql.Kind.NAME,
901 value: name || arg.name,
902 },
903 },
904 type: resolveVariableType(arg.type),
905 };
906}
907function getArgumentName(name, path) {
908 return camelCase.camelCase([...path, name].join('_'));
909}
910function resolveField({ type, field, models, firstCall, path, ancestors, ignore, depthLimit, circularReferenceDepth, schema, depth, argNames, selectedFields, }) {
911 const namedType = graphql.getNamedType(field.type);
912 let args = [];
913 let removeField = false;
914 if (field.args && field.args.length) {
915 args = field.args
916 .map(arg => {
917 const argumentName = getArgumentName(arg.name, path);
918 if (argNames && !argNames.includes(argumentName)) {
919 if (graphql.isNonNullType(arg.type)) {
920 removeField = true;
921 }
922 return null;
923 }
924 if (!firstCall) {
925 addOperationVariable(resolveVariable(arg, argumentName));
926 }
927 return {
928 kind: graphql.Kind.ARGUMENT,
929 name: {
930 kind: graphql.Kind.NAME,
931 value: arg.name,
932 },
933 value: {
934 kind: graphql.Kind.VARIABLE,
935 name: {
936 kind: graphql.Kind.NAME,
937 value: getArgumentName(arg.name, path),
938 },
939 },
940 };
941 })
942 .filter(Boolean);
943 }
944 if (removeField) {
945 return null;
946 }
947 let fieldName = field.name;
948 if (fieldTypeMap.has(fieldName) && fieldTypeMap.get(fieldName) !== field.type.toString()) {
949 fieldName += field.type.toString().replace('!', 'NonNull');
950 }
951 fieldTypeMap.set(fieldName, field.type.toString());
952 if (!graphql.isScalarType(namedType) && !graphql.isEnumType(namedType)) {
953 return {
954 kind: graphql.Kind.FIELD,
955 name: {
956 kind: graphql.Kind.NAME,
957 value: field.name,
958 },
959 ...(fieldName !== field.name && { alias: { kind: graphql.Kind.NAME, value: fieldName } }),
960 selectionSet: resolveSelectionSet({
961 parent: type,
962 type: namedType,
963 models,
964 firstCall,
965 path: [...path, field.name],
966 ancestors: [...ancestors, type],
967 ignore,
968 depthLimit,
969 circularReferenceDepth,
970 schema,
971 depth: depth + 1,
972 argNames,
973 selectedFields,
974 }) || undefined,
975 arguments: args,
976 };
977 }
978 return {
979 kind: graphql.Kind.FIELD,
980 name: {
981 kind: graphql.Kind.NAME,
982 value: field.name,
983 },
984 ...(fieldName !== field.name && { alias: { kind: graphql.Kind.NAME, value: fieldName } }),
985 arguments: args,
986 };
987}
988function hasCircularRef(types, config = {
989 depth: 1,
990}) {
991 const type = types[types.length - 1];
992 if (graphql.isScalarType(type)) {
993 return false;
994 }
995 const size = types.filter(t => t.name === type.name).length;
996 return size > config.depth;
997}
998
999(function (VisitSchemaKind) {
1000 VisitSchemaKind["TYPE"] = "VisitSchemaKind.TYPE";
1001 VisitSchemaKind["SCALAR_TYPE"] = "VisitSchemaKind.SCALAR_TYPE";
1002 VisitSchemaKind["ENUM_TYPE"] = "VisitSchemaKind.ENUM_TYPE";
1003 VisitSchemaKind["COMPOSITE_TYPE"] = "VisitSchemaKind.COMPOSITE_TYPE";
1004 VisitSchemaKind["OBJECT_TYPE"] = "VisitSchemaKind.OBJECT_TYPE";
1005 VisitSchemaKind["INPUT_OBJECT_TYPE"] = "VisitSchemaKind.INPUT_OBJECT_TYPE";
1006 VisitSchemaKind["ABSTRACT_TYPE"] = "VisitSchemaKind.ABSTRACT_TYPE";
1007 VisitSchemaKind["UNION_TYPE"] = "VisitSchemaKind.UNION_TYPE";
1008 VisitSchemaKind["INTERFACE_TYPE"] = "VisitSchemaKind.INTERFACE_TYPE";
1009 VisitSchemaKind["ROOT_OBJECT"] = "VisitSchemaKind.ROOT_OBJECT";
1010 VisitSchemaKind["QUERY"] = "VisitSchemaKind.QUERY";
1011 VisitSchemaKind["MUTATION"] = "VisitSchemaKind.MUTATION";
1012 VisitSchemaKind["SUBSCRIPTION"] = "VisitSchemaKind.SUBSCRIPTION";
1013})(exports.VisitSchemaKind || (exports.VisitSchemaKind = {}));
1014(function (MapperKind) {
1015 MapperKind["TYPE"] = "MapperKind.TYPE";
1016 MapperKind["SCALAR_TYPE"] = "MapperKind.SCALAR_TYPE";
1017 MapperKind["ENUM_TYPE"] = "MapperKind.ENUM_TYPE";
1018 MapperKind["COMPOSITE_TYPE"] = "MapperKind.COMPOSITE_TYPE";
1019 MapperKind["OBJECT_TYPE"] = "MapperKind.OBJECT_TYPE";
1020 MapperKind["INPUT_OBJECT_TYPE"] = "MapperKind.INPUT_OBJECT_TYPE";
1021 MapperKind["ABSTRACT_TYPE"] = "MapperKind.ABSTRACT_TYPE";
1022 MapperKind["UNION_TYPE"] = "MapperKind.UNION_TYPE";
1023 MapperKind["INTERFACE_TYPE"] = "MapperKind.INTERFACE_TYPE";
1024 MapperKind["ROOT_OBJECT"] = "MapperKind.ROOT_OBJECT";
1025 MapperKind["QUERY"] = "MapperKind.QUERY";
1026 MapperKind["MUTATION"] = "MapperKind.MUTATION";
1027 MapperKind["SUBSCRIPTION"] = "MapperKind.SUBSCRIPTION";
1028 MapperKind["DIRECTIVE"] = "MapperKind.DIRECTIVE";
1029 MapperKind["FIELD"] = "MapperKind.FIELD";
1030 MapperKind["COMPOSITE_FIELD"] = "MapperKind.COMPOSITE_FIELD";
1031 MapperKind["OBJECT_FIELD"] = "MapperKind.OBJECT_FIELD";
1032 MapperKind["ROOT_FIELD"] = "MapperKind.ROOT_FIELD";
1033 MapperKind["QUERY_ROOT_FIELD"] = "MapperKind.QUERY_ROOT_FIELD";
1034 MapperKind["MUTATION_ROOT_FIELD"] = "MapperKind.MUTATION_ROOT_FIELD";
1035 MapperKind["SUBSCRIPTION_ROOT_FIELD"] = "MapperKind.SUBSCRIPTION_ROOT_FIELD";
1036 MapperKind["INTERFACE_FIELD"] = "MapperKind.INTERFACE_FIELD";
1037 MapperKind["INPUT_OBJECT_FIELD"] = "MapperKind.INPUT_OBJECT_FIELD";
1038 MapperKind["ARGUMENT"] = "MapperKind.ARGUMENT";
1039 MapperKind["ENUM_VALUE"] = "MapperKind.ENUM_VALUE";
1040})(exports.MapperKind || (exports.MapperKind = {}));
1041
1042function createNamedStub(name, type) {
1043 let constructor;
1044 if (type === 'object') {
1045 constructor = graphql.GraphQLObjectType;
1046 }
1047 else if (type === 'interface') {
1048 constructor = graphql.GraphQLInterfaceType;
1049 }
1050 else {
1051 constructor = graphql.GraphQLInputObjectType;
1052 }
1053 return new constructor({
1054 name,
1055 fields: {
1056 __fake: {
1057 type: graphql.GraphQLString,
1058 },
1059 },
1060 });
1061}
1062function createStub(node, type) {
1063 switch (node.kind) {
1064 case graphql.Kind.LIST_TYPE:
1065 return new graphql.GraphQLList(createStub(node.type, type));
1066 case graphql.Kind.NON_NULL_TYPE:
1067 return new graphql.GraphQLNonNull(createStub(node.type, type));
1068 default:
1069 if (type === 'output') {
1070 return createNamedStub(node.name.value, 'object');
1071 }
1072 return createNamedStub(node.name.value, 'input');
1073 }
1074}
1075function isNamedStub(type) {
1076 if (graphql.isObjectType(type) || graphql.isInterfaceType(type) || graphql.isInputObjectType(type)) {
1077 const fields = type.getFields();
1078 const fieldNames = Object.keys(fields);
1079 return fieldNames.length === 1 && fields[fieldNames[0]].name === '__fake';
1080 }
1081 return false;
1082}
1083function getBuiltInForStub(type) {
1084 switch (type.name) {
1085 case graphql.GraphQLInt.name:
1086 return graphql.GraphQLInt;
1087 case graphql.GraphQLFloat.name:
1088 return graphql.GraphQLFloat;
1089 case graphql.GraphQLString.name:
1090 return graphql.GraphQLString;
1091 case graphql.GraphQLBoolean.name:
1092 return graphql.GraphQLBoolean;
1093 case graphql.GraphQLID.name:
1094 return graphql.GraphQLID;
1095 default:
1096 return type;
1097 }
1098}
1099
1100function rewireTypes(originalTypeMap, directives, options = {
1101 skipPruning: false,
1102}) {
1103 const newTypeMap = Object.create(null);
1104 Object.keys(originalTypeMap).forEach(typeName => {
1105 const namedType = originalTypeMap[typeName];
1106 if (namedType == null || typeName.startsWith('__')) {
1107 return;
1108 }
1109 const newName = namedType.name;
1110 if (newName.startsWith('__')) {
1111 return;
1112 }
1113 if (newTypeMap[newName] != null) {
1114 throw new Error(`Duplicate schema type name ${newName}`);
1115 }
1116 newTypeMap[newName] = namedType;
1117 });
1118 Object.keys(newTypeMap).forEach(typeName => {
1119 newTypeMap[typeName] = rewireNamedType(newTypeMap[typeName]);
1120 });
1121 const newDirectives = directives.map(directive => rewireDirective(directive));
1122 // TODO:
1123 // consider removing the default level of pruning in v7,
1124 // see comments below on the pruneTypes function.
1125 return options.skipPruning
1126 ? {
1127 typeMap: newTypeMap,
1128 directives: newDirectives,
1129 }
1130 : pruneTypes(newTypeMap, newDirectives);
1131 function rewireDirective(directive) {
1132 if (graphql.isSpecifiedDirective(directive)) {
1133 return directive;
1134 }
1135 const directiveConfig = directive.toConfig();
1136 directiveConfig.args = rewireArgs(directiveConfig.args);
1137 return new graphql.GraphQLDirective(directiveConfig);
1138 }
1139 function rewireArgs(args) {
1140 const rewiredArgs = {};
1141 Object.keys(args).forEach(argName => {
1142 const arg = args[argName];
1143 const rewiredArgType = rewireType(arg.type);
1144 if (rewiredArgType != null) {
1145 arg.type = rewiredArgType;
1146 rewiredArgs[argName] = arg;
1147 }
1148 });
1149 return rewiredArgs;
1150 }
1151 function rewireNamedType(type) {
1152 if (graphql.isObjectType(type)) {
1153 const config = type.toConfig();
1154 const newConfig = {
1155 ...config,
1156 fields: () => rewireFields(config.fields),
1157 interfaces: () => rewireNamedTypes(config.interfaces),
1158 };
1159 return new graphql.GraphQLObjectType(newConfig);
1160 }
1161 else if (graphql.isInterfaceType(type)) {
1162 const config = type.toConfig();
1163 const newConfig = {
1164 ...config,
1165 fields: () => rewireFields(config.fields),
1166 };
1167 if ('interfaces' in newConfig) {
1168 newConfig.interfaces = () => rewireNamedTypes(config.interfaces);
1169 }
1170 return new graphql.GraphQLInterfaceType(newConfig);
1171 }
1172 else if (graphql.isUnionType(type)) {
1173 const config = type.toConfig();
1174 const newConfig = {
1175 ...config,
1176 types: () => rewireNamedTypes(config.types),
1177 };
1178 return new graphql.GraphQLUnionType(newConfig);
1179 }
1180 else if (graphql.isInputObjectType(type)) {
1181 const config = type.toConfig();
1182 const newConfig = {
1183 ...config,
1184 fields: () => rewireInputFields(config.fields),
1185 };
1186 return new graphql.GraphQLInputObjectType(newConfig);
1187 }
1188 else if (graphql.isEnumType(type)) {
1189 const enumConfig = type.toConfig();
1190 return new graphql.GraphQLEnumType(enumConfig);
1191 }
1192 else if (graphql.isScalarType(type)) {
1193 if (graphql.isSpecifiedScalarType(type)) {
1194 return type;
1195 }
1196 const scalarConfig = type.toConfig();
1197 return new graphql.GraphQLScalarType(scalarConfig);
1198 }
1199 throw new Error(`Unexpected schema type: ${type}`);
1200 }
1201 function rewireFields(fields) {
1202 const rewiredFields = {};
1203 Object.keys(fields).forEach(fieldName => {
1204 const field = fields[fieldName];
1205 const rewiredFieldType = rewireType(field.type);
1206 if (rewiredFieldType != null) {
1207 field.type = rewiredFieldType;
1208 field.args = rewireArgs(field.args);
1209 rewiredFields[fieldName] = field;
1210 }
1211 });
1212 return rewiredFields;
1213 }
1214 function rewireInputFields(fields) {
1215 const rewiredFields = {};
1216 Object.keys(fields).forEach(fieldName => {
1217 const field = fields[fieldName];
1218 const rewiredFieldType = rewireType(field.type);
1219 if (rewiredFieldType != null) {
1220 field.type = rewiredFieldType;
1221 rewiredFields[fieldName] = field;
1222 }
1223 });
1224 return rewiredFields;
1225 }
1226 function rewireNamedTypes(namedTypes) {
1227 const rewiredTypes = [];
1228 namedTypes.forEach(namedType => {
1229 const rewiredType = rewireType(namedType);
1230 if (rewiredType != null) {
1231 rewiredTypes.push(rewiredType);
1232 }
1233 });
1234 return rewiredTypes;
1235 }
1236 function rewireType(type) {
1237 if (graphql.isListType(type)) {
1238 const rewiredType = rewireType(type.ofType);
1239 return rewiredType != null ? new graphql.GraphQLList(rewiredType) : null;
1240 }
1241 else if (graphql.isNonNullType(type)) {
1242 const rewiredType = rewireType(type.ofType);
1243 return rewiredType != null ? new graphql.GraphQLNonNull(rewiredType) : null;
1244 }
1245 else if (graphql.isNamedType(type)) {
1246 let rewiredType = originalTypeMap[type.name];
1247 if (rewiredType === undefined) {
1248 rewiredType = isNamedStub(type) ? getBuiltInForStub(type) : type;
1249 newTypeMap[rewiredType.name] = rewiredType;
1250 }
1251 return rewiredType != null ? newTypeMap[rewiredType.name] : null;
1252 }
1253 return null;
1254 }
1255}
1256// TODO:
1257// consider removing the default level of pruning in v7
1258//
1259// Pruning during mapSchema limits the ability to create an unpruned schema, which may be of use
1260// to some library users. pruning is now recommended via the dedicated pruneSchema function
1261// which does not force pruning on library users and gives granular control in terms of pruning
1262// types.
1263function pruneTypes(typeMap, directives) {
1264 const newTypeMap = {};
1265 const implementedInterfaces = {};
1266 Object.keys(typeMap).forEach(typeName => {
1267 const namedType = typeMap[typeName];
1268 if ('getInterfaces' in namedType) {
1269 namedType.getInterfaces().forEach(iface => {
1270 implementedInterfaces[iface.name] = true;
1271 });
1272 }
1273 });
1274 let prunedTypeMap = false;
1275 const typeNames = Object.keys(typeMap);
1276 for (let i = 0; i < typeNames.length; i++) {
1277 const typeName = typeNames[i];
1278 const type = typeMap[typeName];
1279 if (graphql.isObjectType(type) || graphql.isInputObjectType(type)) {
1280 // prune types with no fields
1281 if (Object.keys(type.getFields()).length) {
1282 newTypeMap[typeName] = type;
1283 }
1284 else {
1285 prunedTypeMap = true;
1286 }
1287 }
1288 else if (graphql.isUnionType(type)) {
1289 // prune unions without underlying types
1290 if (type.getTypes().length) {
1291 newTypeMap[typeName] = type;
1292 }
1293 else {
1294 prunedTypeMap = true;
1295 }
1296 }
1297 else if (graphql.isInterfaceType(type)) {
1298 // prune interfaces without fields or without implementations
1299 if (Object.keys(type.getFields()).length && implementedInterfaces[type.name]) {
1300 newTypeMap[typeName] = type;
1301 }
1302 else {
1303 prunedTypeMap = true;
1304 }
1305 }
1306 else {
1307 newTypeMap[typeName] = type;
1308 }
1309 }
1310 // every prune requires another round of healing
1311 return prunedTypeMap ? rewireTypes(newTypeMap, directives) : { typeMap, directives };
1312}
1313
1314function transformInputValue(type, value, transformer) {
1315 if (value == null) {
1316 return value;
1317 }
1318 const nullableType = graphql.getNullableType(type);
1319 if (graphql.isLeafType(nullableType)) {
1320 return transformer(nullableType, value);
1321 }
1322 else if (graphql.isListType(nullableType)) {
1323 return value.map((listMember) => transformInputValue(nullableType.ofType, listMember, transformer));
1324 }
1325 else if (graphql.isInputObjectType(nullableType)) {
1326 const fields = nullableType.getFields();
1327 const newValue = {};
1328 Object.keys(value).forEach(key => {
1329 newValue[key] = transformInputValue(fields[key].type, value[key], transformer);
1330 });
1331 return newValue;
1332 }
1333 // unreachable, no other possible return value
1334}
1335function serializeInputValue(type, value) {
1336 return transformInputValue(type, value, (t, v) => t.serialize(v));
1337}
1338function parseInputValue(type, value) {
1339 return transformInputValue(type, value, (t, v) => t.parseValue(v));
1340}
1341function parseInputValueLiteral(type, value) {
1342 return transformInputValue(type, value, (t, v) => t.parseLiteral(v, {}));
1343}
1344
1345function mapSchema(schema, schemaMapper = {}) {
1346 const originalTypeMap = schema.getTypeMap();
1347 let newTypeMap = mapDefaultValues(originalTypeMap, schema, serializeInputValue);
1348 newTypeMap = mapTypes(newTypeMap, schema, schemaMapper, type => graphql.isLeafType(type));
1349 newTypeMap = mapEnumValues(newTypeMap, schema, schemaMapper);
1350 newTypeMap = mapDefaultValues(newTypeMap, schema, parseInputValue);
1351 newTypeMap = mapTypes(newTypeMap, schema, schemaMapper, type => !graphql.isLeafType(type));
1352 newTypeMap = mapFields(newTypeMap, schema, schemaMapper);
1353 newTypeMap = mapArguments(newTypeMap, schema, schemaMapper);
1354 const originalDirectives = schema.getDirectives();
1355 const newDirectives = mapDirectives(originalDirectives, schema, schemaMapper);
1356 const queryType = schema.getQueryType();
1357 const mutationType = schema.getMutationType();
1358 const subscriptionType = schema.getSubscriptionType();
1359 const newQueryTypeName = queryType != null ? (newTypeMap[queryType.name] != null ? newTypeMap[queryType.name].name : undefined) : undefined;
1360 const newMutationTypeName = mutationType != null
1361 ? newTypeMap[mutationType.name] != null
1362 ? newTypeMap[mutationType.name].name
1363 : undefined
1364 : undefined;
1365 const newSubscriptionTypeName = subscriptionType != null
1366 ? newTypeMap[subscriptionType.name] != null
1367 ? newTypeMap[subscriptionType.name].name
1368 : undefined
1369 : undefined;
1370 const { typeMap, directives } = rewireTypes(newTypeMap, newDirectives);
1371 return new graphql.GraphQLSchema({
1372 ...schema.toConfig(),
1373 query: newQueryTypeName ? typeMap[newQueryTypeName] : undefined,
1374 mutation: newMutationTypeName ? typeMap[newMutationTypeName] : undefined,
1375 subscription: newSubscriptionTypeName != null ? typeMap[newSubscriptionTypeName] : undefined,
1376 types: Object.keys(typeMap).map(typeName => typeMap[typeName]),
1377 directives,
1378 });
1379}
1380function mapTypes(originalTypeMap, schema, schemaMapper, testFn = () => true) {
1381 const newTypeMap = {};
1382 Object.keys(originalTypeMap).forEach(typeName => {
1383 if (!typeName.startsWith('__')) {
1384 const originalType = originalTypeMap[typeName];
1385 if (originalType == null || !testFn(originalType)) {
1386 newTypeMap[typeName] = originalType;
1387 return;
1388 }
1389 const typeMapper = getTypeMapper(schema, schemaMapper, typeName);
1390 if (typeMapper == null) {
1391 newTypeMap[typeName] = originalType;
1392 return;
1393 }
1394 const maybeNewType = typeMapper(originalType, schema);
1395 if (maybeNewType === undefined) {
1396 newTypeMap[typeName] = originalType;
1397 return;
1398 }
1399 newTypeMap[typeName] = maybeNewType;
1400 }
1401 });
1402 return newTypeMap;
1403}
1404function mapEnumValues(originalTypeMap, schema, schemaMapper) {
1405 const enumValueMapper = getEnumValueMapper(schemaMapper);
1406 if (!enumValueMapper) {
1407 return originalTypeMap;
1408 }
1409 return mapTypes(originalTypeMap, schema, {
1410 [exports.MapperKind.ENUM_TYPE]: type => {
1411 const config = type.toConfig();
1412 const originalEnumValueConfigMap = config.values;
1413 const newEnumValueConfigMap = {};
1414 Object.keys(originalEnumValueConfigMap).forEach(externalValue => {
1415 const originalEnumValueConfig = originalEnumValueConfigMap[externalValue];
1416 const mappedEnumValue = enumValueMapper(originalEnumValueConfig, type.name, schema, externalValue);
1417 if (mappedEnumValue === undefined) {
1418 newEnumValueConfigMap[externalValue] = originalEnumValueConfig;
1419 }
1420 else if (Array.isArray(mappedEnumValue)) {
1421 const [newExternalValue, newEnumValueConfig] = mappedEnumValue;
1422 newEnumValueConfigMap[newExternalValue] =
1423 newEnumValueConfig === undefined ? originalEnumValueConfig : newEnumValueConfig;
1424 }
1425 else if (mappedEnumValue !== null) {
1426 newEnumValueConfigMap[externalValue] = mappedEnumValue;
1427 }
1428 });
1429 return correctASTNodes(new graphql.GraphQLEnumType({
1430 ...config,
1431 values: newEnumValueConfigMap,
1432 }));
1433 },
1434 }, type => graphql.isEnumType(type));
1435}
1436function mapDefaultValues(originalTypeMap, schema, fn) {
1437 const newTypeMap = mapArguments(originalTypeMap, schema, {
1438 [exports.MapperKind.ARGUMENT]: argumentConfig => {
1439 if (argumentConfig.defaultValue === undefined) {
1440 return argumentConfig;
1441 }
1442 const maybeNewType = getNewType(originalTypeMap, argumentConfig.type);
1443 if (maybeNewType != null) {
1444 return {
1445 ...argumentConfig,
1446 defaultValue: fn(maybeNewType, argumentConfig.defaultValue),
1447 };
1448 }
1449 },
1450 });
1451 return mapFields(newTypeMap, schema, {
1452 [exports.MapperKind.INPUT_OBJECT_FIELD]: inputFieldConfig => {
1453 if (inputFieldConfig.defaultValue === undefined) {
1454 return inputFieldConfig;
1455 }
1456 const maybeNewType = getNewType(newTypeMap, inputFieldConfig.type);
1457 if (maybeNewType != null) {
1458 return {
1459 ...inputFieldConfig,
1460 defaultValue: fn(maybeNewType, inputFieldConfig.defaultValue),
1461 };
1462 }
1463 },
1464 });
1465}
1466function getNewType(newTypeMap, type) {
1467 if (graphql.isListType(type)) {
1468 const newType = getNewType(newTypeMap, type.ofType);
1469 return newType != null ? new graphql.GraphQLList(newType) : null;
1470 }
1471 else if (graphql.isNonNullType(type)) {
1472 const newType = getNewType(newTypeMap, type.ofType);
1473 return newType != null ? new graphql.GraphQLNonNull(newType) : null;
1474 }
1475 else if (graphql.isNamedType(type)) {
1476 const newType = newTypeMap[type.name];
1477 return newType != null ? newType : null;
1478 }
1479 return null;
1480}
1481function mapFields(originalTypeMap, schema, schemaMapper) {
1482 const newTypeMap = {};
1483 Object.keys(originalTypeMap).forEach(typeName => {
1484 if (!typeName.startsWith('__')) {
1485 const originalType = originalTypeMap[typeName];
1486 if (!graphql.isObjectType(originalType) && !graphql.isInterfaceType(originalType) && !graphql.isInputObjectType(originalType)) {
1487 newTypeMap[typeName] = originalType;
1488 return;
1489 }
1490 const fieldMapper = getFieldMapper(schema, schemaMapper, typeName);
1491 if (fieldMapper == null) {
1492 newTypeMap[typeName] = originalType;
1493 return;
1494 }
1495 const config = originalType.toConfig();
1496 const originalFieldConfigMap = config.fields;
1497 const newFieldConfigMap = {};
1498 Object.keys(originalFieldConfigMap).forEach(fieldName => {
1499 const originalFieldConfig = originalFieldConfigMap[fieldName];
1500 const mappedField = fieldMapper(originalFieldConfig, fieldName, typeName, schema);
1501 if (mappedField === undefined) {
1502 newFieldConfigMap[fieldName] = originalFieldConfig;
1503 }
1504 else if (Array.isArray(mappedField)) {
1505 const [newFieldName, newFieldConfig] = mappedField;
1506 if (newFieldConfig.astNode != null) {
1507 newFieldConfig.astNode = {
1508 ...newFieldConfig.astNode,
1509 name: {
1510 ...newFieldConfig.astNode.name,
1511 value: newFieldName,
1512 },
1513 };
1514 }
1515 newFieldConfigMap[newFieldName] = newFieldConfig === undefined ? originalFieldConfig : newFieldConfig;
1516 }
1517 else if (mappedField !== null) {
1518 newFieldConfigMap[fieldName] = mappedField;
1519 }
1520 });
1521 if (graphql.isObjectType(originalType)) {
1522 newTypeMap[typeName] = correctASTNodes(new graphql.GraphQLObjectType({
1523 ...config,
1524 fields: newFieldConfigMap,
1525 }));
1526 }
1527 else if (graphql.isInterfaceType(originalType)) {
1528 newTypeMap[typeName] = correctASTNodes(new graphql.GraphQLInterfaceType({
1529 ...config,
1530 fields: newFieldConfigMap,
1531 }));
1532 }
1533 else {
1534 newTypeMap[typeName] = correctASTNodes(new graphql.GraphQLInputObjectType({
1535 ...config,
1536 fields: newFieldConfigMap,
1537 }));
1538 }
1539 }
1540 });
1541 return newTypeMap;
1542}
1543function mapArguments(originalTypeMap, schema, schemaMapper) {
1544 const newTypeMap = {};
1545 Object.keys(originalTypeMap).forEach(typeName => {
1546 if (!typeName.startsWith('__')) {
1547 const originalType = originalTypeMap[typeName];
1548 if (!graphql.isObjectType(originalType) && !graphql.isInterfaceType(originalType)) {
1549 newTypeMap[typeName] = originalType;
1550 return;
1551 }
1552 const argumentMapper = getArgumentMapper(schemaMapper);
1553 if (argumentMapper == null) {
1554 newTypeMap[typeName] = originalType;
1555 return;
1556 }
1557 const config = originalType.toConfig();
1558 const originalFieldConfigMap = config.fields;
1559 const newFieldConfigMap = {};
1560 Object.keys(originalFieldConfigMap).forEach(fieldName => {
1561 const originalFieldConfig = originalFieldConfigMap[fieldName];
1562 const originalArgumentConfigMap = originalFieldConfig.args;
1563 if (originalArgumentConfigMap == null) {
1564 newFieldConfigMap[fieldName] = originalFieldConfig;
1565 return;
1566 }
1567 const argumentNames = Object.keys(originalArgumentConfigMap);
1568 if (!argumentNames.length) {
1569 newFieldConfigMap[fieldName] = originalFieldConfig;
1570 return;
1571 }
1572 const newArgumentConfigMap = {};
1573 argumentNames.forEach(argumentName => {
1574 const originalArgumentConfig = originalArgumentConfigMap[argumentName];
1575 const mappedArgument = argumentMapper(originalArgumentConfig, fieldName, typeName, schema);
1576 if (mappedArgument === undefined) {
1577 newArgumentConfigMap[argumentName] = originalArgumentConfig;
1578 }
1579 else if (Array.isArray(mappedArgument)) {
1580 const [newArgumentName, newArgumentConfig] = mappedArgument;
1581 newArgumentConfigMap[newArgumentName] = newArgumentConfig;
1582 }
1583 else if (mappedArgument !== null) {
1584 newArgumentConfigMap[argumentName] = mappedArgument;
1585 }
1586 });
1587 newFieldConfigMap[fieldName] = {
1588 ...originalFieldConfig,
1589 args: newArgumentConfigMap,
1590 };
1591 });
1592 if (graphql.isObjectType(originalType)) {
1593 newTypeMap[typeName] = new graphql.GraphQLObjectType({
1594 ...config,
1595 fields: newFieldConfigMap,
1596 });
1597 }
1598 else if (graphql.isInterfaceType(originalType)) {
1599 newTypeMap[typeName] = new graphql.GraphQLInterfaceType({
1600 ...config,
1601 fields: newFieldConfigMap,
1602 });
1603 }
1604 else {
1605 newTypeMap[typeName] = new graphql.GraphQLInputObjectType({
1606 ...config,
1607 fields: newFieldConfigMap,
1608 });
1609 }
1610 }
1611 });
1612 return newTypeMap;
1613}
1614function mapDirectives(originalDirectives, schema, schemaMapper) {
1615 const directiveMapper = getDirectiveMapper(schemaMapper);
1616 if (directiveMapper == null) {
1617 return originalDirectives.slice();
1618 }
1619 const newDirectives = [];
1620 originalDirectives.forEach(directive => {
1621 const mappedDirective = directiveMapper(directive, schema);
1622 if (mappedDirective === undefined) {
1623 newDirectives.push(directive);
1624 }
1625 else if (mappedDirective !== null) {
1626 newDirectives.push(mappedDirective);
1627 }
1628 });
1629 return newDirectives;
1630}
1631function getTypeSpecifiers(schema, typeName) {
1632 const type = schema.getType(typeName);
1633 const specifiers = [exports.MapperKind.TYPE];
1634 if (graphql.isObjectType(type)) {
1635 specifiers.push(exports.MapperKind.COMPOSITE_TYPE, exports.MapperKind.OBJECT_TYPE);
1636 const query = schema.getQueryType();
1637 const mutation = schema.getMutationType();
1638 const subscription = schema.getSubscriptionType();
1639 if (query != null && typeName === query.name) {
1640 specifiers.push(exports.MapperKind.ROOT_OBJECT, exports.MapperKind.QUERY);
1641 }
1642 else if (mutation != null && typeName === mutation.name) {
1643 specifiers.push(exports.MapperKind.ROOT_OBJECT, exports.MapperKind.MUTATION);
1644 }
1645 else if (subscription != null && typeName === subscription.name) {
1646 specifiers.push(exports.MapperKind.ROOT_OBJECT, exports.MapperKind.SUBSCRIPTION);
1647 }
1648 }
1649 else if (graphql.isInputObjectType(type)) {
1650 specifiers.push(exports.MapperKind.INPUT_OBJECT_TYPE);
1651 }
1652 else if (graphql.isInterfaceType(type)) {
1653 specifiers.push(exports.MapperKind.COMPOSITE_TYPE, exports.MapperKind.ABSTRACT_TYPE, exports.MapperKind.INTERFACE_TYPE);
1654 }
1655 else if (graphql.isUnionType(type)) {
1656 specifiers.push(exports.MapperKind.COMPOSITE_TYPE, exports.MapperKind.ABSTRACT_TYPE, exports.MapperKind.UNION_TYPE);
1657 }
1658 else if (graphql.isEnumType(type)) {
1659 specifiers.push(exports.MapperKind.ENUM_TYPE);
1660 }
1661 else if (graphql.isScalarType(type)) {
1662 specifiers.push(exports.MapperKind.SCALAR_TYPE);
1663 }
1664 return specifiers;
1665}
1666function getTypeMapper(schema, schemaMapper, typeName) {
1667 const specifiers = getTypeSpecifiers(schema, typeName);
1668 let typeMapper;
1669 const stack = [...specifiers];
1670 while (!typeMapper && stack.length > 0) {
1671 const next = stack.pop();
1672 typeMapper = schemaMapper[next];
1673 }
1674 return typeMapper != null ? typeMapper : null;
1675}
1676function getFieldSpecifiers(schema, typeName) {
1677 const type = schema.getType(typeName);
1678 const specifiers = [exports.MapperKind.FIELD];
1679 if (graphql.isObjectType(type)) {
1680 specifiers.push(exports.MapperKind.COMPOSITE_FIELD, exports.MapperKind.OBJECT_FIELD);
1681 const query = schema.getQueryType();
1682 const mutation = schema.getMutationType();
1683 const subscription = schema.getSubscriptionType();
1684 if (query != null && typeName === query.name) {
1685 specifiers.push(exports.MapperKind.ROOT_FIELD, exports.MapperKind.QUERY_ROOT_FIELD);
1686 }
1687 else if (mutation != null && typeName === mutation.name) {
1688 specifiers.push(exports.MapperKind.ROOT_FIELD, exports.MapperKind.MUTATION_ROOT_FIELD);
1689 }
1690 else if (subscription != null && typeName === subscription.name) {
1691 specifiers.push(exports.MapperKind.ROOT_FIELD, exports.MapperKind.SUBSCRIPTION_ROOT_FIELD);
1692 }
1693 }
1694 else if (graphql.isInterfaceType(type)) {
1695 specifiers.push(exports.MapperKind.COMPOSITE_FIELD, exports.MapperKind.INTERFACE_FIELD);
1696 }
1697 else if (graphql.isInputObjectType(type)) {
1698 specifiers.push(exports.MapperKind.INPUT_OBJECT_FIELD);
1699 }
1700 return specifiers;
1701}
1702function getFieldMapper(schema, schemaMapper, typeName) {
1703 const specifiers = getFieldSpecifiers(schema, typeName);
1704 let fieldMapper;
1705 const stack = [...specifiers];
1706 while (!fieldMapper && stack.length > 0) {
1707 const next = stack.pop();
1708 fieldMapper = schemaMapper[next];
1709 }
1710 return fieldMapper != null ? fieldMapper : null;
1711}
1712function getArgumentMapper(schemaMapper) {
1713 const argumentMapper = schemaMapper[exports.MapperKind.ARGUMENT];
1714 return argumentMapper != null ? argumentMapper : null;
1715}
1716function getDirectiveMapper(schemaMapper) {
1717 const directiveMapper = schemaMapper[exports.MapperKind.DIRECTIVE];
1718 return directiveMapper != null ? directiveMapper : null;
1719}
1720function getEnumValueMapper(schemaMapper) {
1721 const enumValueMapper = schemaMapper[exports.MapperKind.ENUM_VALUE];
1722 return enumValueMapper != null ? enumValueMapper : null;
1723}
1724function correctASTNodes(type) {
1725 if (graphql.isObjectType(type)) {
1726 const config = type.toConfig();
1727 if (config.astNode != null) {
1728 const fields = [];
1729 Object.values(config.fields).forEach(fieldConfig => {
1730 if (fieldConfig.astNode != null) {
1731 fields.push(fieldConfig.astNode);
1732 }
1733 });
1734 config.astNode = {
1735 ...config.astNode,
1736 kind: graphql.Kind.OBJECT_TYPE_DEFINITION,
1737 fields,
1738 };
1739 }
1740 if (config.extensionASTNodes != null) {
1741 config.extensionASTNodes = config.extensionASTNodes.map(node => ({
1742 ...node,
1743 kind: graphql.Kind.OBJECT_TYPE_EXTENSION,
1744 fields: undefined,
1745 }));
1746 }
1747 return new graphql.GraphQLObjectType(config);
1748 }
1749 else if (graphql.isInterfaceType(type)) {
1750 const config = type.toConfig();
1751 if (config.astNode != null) {
1752 const fields = [];
1753 Object.values(config.fields).forEach(fieldConfig => {
1754 if (fieldConfig.astNode != null) {
1755 fields.push(fieldConfig.astNode);
1756 }
1757 });
1758 config.astNode = {
1759 ...config.astNode,
1760 kind: graphql.Kind.INTERFACE_TYPE_DEFINITION,
1761 fields,
1762 };
1763 }
1764 if (config.extensionASTNodes != null) {
1765 config.extensionASTNodes = config.extensionASTNodes.map(node => ({
1766 ...node,
1767 kind: graphql.Kind.INTERFACE_TYPE_EXTENSION,
1768 fields: undefined,
1769 }));
1770 }
1771 return new graphql.GraphQLInterfaceType(config);
1772 }
1773 else if (graphql.isInputObjectType(type)) {
1774 const config = type.toConfig();
1775 if (config.astNode != null) {
1776 const fields = [];
1777 Object.values(config.fields).forEach(fieldConfig => {
1778 if (fieldConfig.astNode != null) {
1779 fields.push(fieldConfig.astNode);
1780 }
1781 });
1782 config.astNode = {
1783 ...config.astNode,
1784 kind: graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION,
1785 fields,
1786 };
1787 }
1788 if (config.extensionASTNodes != null) {
1789 config.extensionASTNodes = config.extensionASTNodes.map(node => ({
1790 ...node,
1791 kind: graphql.Kind.INPUT_OBJECT_TYPE_EXTENSION,
1792 fields: undefined,
1793 }));
1794 }
1795 return new graphql.GraphQLInputObjectType(config);
1796 }
1797 else if (graphql.isEnumType(type)) {
1798 const config = type.toConfig();
1799 if (config.astNode != null) {
1800 const values = [];
1801 Object.values(config.values).forEach(enumValueConfig => {
1802 if (enumValueConfig.astNode != null) {
1803 values.push(enumValueConfig.astNode);
1804 }
1805 });
1806 config.astNode = {
1807 ...config.astNode,
1808 values,
1809 };
1810 }
1811 if (config.extensionASTNodes != null) {
1812 config.extensionASTNodes = config.extensionASTNodes.map(node => ({
1813 ...node,
1814 values: undefined,
1815 }));
1816 }
1817 return new graphql.GraphQLEnumType(config);
1818 }
1819 else {
1820 return type;
1821 }
1822}
1823
1824function filterSchema({ schema, rootFieldFilter = () => true, typeFilter = () => true, fieldFilter = () => true, }) {
1825 const filteredSchema = mapSchema(schema, {
1826 [exports.MapperKind.QUERY]: (type) => filterRootFields(type, 'Query', rootFieldFilter),
1827 [exports.MapperKind.MUTATION]: (type) => filterRootFields(type, 'Mutation', rootFieldFilter),
1828 [exports.MapperKind.SUBSCRIPTION]: (type) => filterRootFields(type, 'Subscription', rootFieldFilter),
1829 [exports.MapperKind.OBJECT_TYPE]: (type) => typeFilter(type.name, type) ? filterObjectFields(type, fieldFilter) : null,
1830 [exports.MapperKind.INTERFACE_TYPE]: (type) => (typeFilter(type.name, type) ? undefined : null),
1831 [exports.MapperKind.UNION_TYPE]: (type) => (typeFilter(type.name, type) ? undefined : null),
1832 [exports.MapperKind.INPUT_OBJECT_TYPE]: (type) => (typeFilter(type.name, type) ? undefined : null),
1833 [exports.MapperKind.ENUM_TYPE]: (type) => (typeFilter(type.name, type) ? undefined : null),
1834 [exports.MapperKind.SCALAR_TYPE]: (type) => (typeFilter(type.name, type) ? undefined : null),
1835 });
1836 return filteredSchema;
1837}
1838function filterRootFields(type, operation, rootFieldFilter) {
1839 const config = type.toConfig();
1840 Object.keys(config.fields).forEach(fieldName => {
1841 if (!rootFieldFilter(operation, fieldName, config.fields[fieldName])) {
1842 delete config.fields[fieldName];
1843 }
1844 });
1845 return new graphql.GraphQLObjectType(config);
1846}
1847function filterObjectFields(type, fieldFilter) {
1848 const config = type.toConfig();
1849 Object.keys(config.fields).forEach(fieldName => {
1850 if (!fieldFilter(type.name, fieldName, config.fields[fieldName])) {
1851 delete config.fields[fieldName];
1852 }
1853 });
1854 return new graphql.GraphQLObjectType(config);
1855}
1856
1857function cloneDirective(directive) {
1858 return graphql.isSpecifiedDirective(directive) ? directive : new graphql.GraphQLDirective(directive.toConfig());
1859}
1860function cloneType(type) {
1861 if (graphql.isObjectType(type)) {
1862 const config = type.toConfig();
1863 return new graphql.GraphQLObjectType({
1864 ...config,
1865 interfaces: typeof config.interfaces === 'function' ? config.interfaces : config.interfaces.slice(),
1866 });
1867 }
1868 else if (graphql.isInterfaceType(type)) {
1869 const config = type.toConfig();
1870 const newConfig = {
1871 ...config,
1872 interfaces: [...((typeof config.interfaces === 'function' ? config.interfaces() : config.interfaces) || [])],
1873 };
1874 return new graphql.GraphQLInterfaceType(newConfig);
1875 }
1876 else if (graphql.isUnionType(type)) {
1877 const config = type.toConfig();
1878 return new graphql.GraphQLUnionType({
1879 ...config,
1880 types: config.types.slice(),
1881 });
1882 }
1883 else if (graphql.isInputObjectType(type)) {
1884 return new graphql.GraphQLInputObjectType(type.toConfig());
1885 }
1886 else if (graphql.isEnumType(type)) {
1887 return new graphql.GraphQLEnumType(type.toConfig());
1888 }
1889 else if (graphql.isScalarType(type)) {
1890 return graphql.isSpecifiedScalarType(type) ? type : new graphql.GraphQLScalarType(type.toConfig());
1891 }
1892 throw new Error(`Invalid type ${type}`);
1893}
1894function cloneSchema(schema) {
1895 return mapSchema(schema);
1896}
1897
1898// Update any references to named schema types that disagree with the named
1899// types found in schema.getTypeMap().
1900//
1901// healSchema and its callers (visitSchema/visitSchemaDirectives) all modify the schema in place.
1902// Therefore, private variables (such as the stored implementation map and the proper root types)
1903// are not updated.
1904//
1905// If this causes issues, the schema could be more aggressively healed as follows:
1906//
1907// healSchema(schema);
1908// const config = schema.toConfig()
1909// const healedSchema = new GraphQLSchema({
1910// ...config,
1911// query: schema.getType('<desired new root query type name>'),
1912// mutation: schema.getType('<desired new root mutation type name>'),
1913// subscription: schema.getType('<desired new root subscription type name>'),
1914// });
1915//
1916// One can then also -- if necessary -- assign the correct private variables to the initial schema
1917// as follows:
1918// Object.assign(schema, healedSchema);
1919//
1920// These steps are not taken automatically to preserve backwards compatibility with graphql-tools v4.
1921// See https://github.com/ardatan/graphql-tools/issues/1462
1922//
1923// They were briefly taken in v5, but can now be phased out as they were only required when other
1924// areas of the codebase were using healSchema and visitSchema more extensively.
1925//
1926function healSchema(schema) {
1927 healTypes(schema.getTypeMap(), schema.getDirectives());
1928 return schema;
1929}
1930function healTypes(originalTypeMap, directives, config = {
1931 skipPruning: false,
1932}) {
1933 const actualNamedTypeMap = Object.create(null);
1934 // If any of the .name properties of the GraphQLNamedType objects in
1935 // schema.getTypeMap() have changed, the keys of the type map need to
1936 // be updated accordingly.
1937 Object.entries(originalTypeMap).forEach(([typeName, namedType]) => {
1938 if (namedType == null || typeName.startsWith('__')) {
1939 return;
1940 }
1941 const actualName = namedType.name;
1942 if (actualName.startsWith('__')) {
1943 return;
1944 }
1945 if (actualName in actualNamedTypeMap) {
1946 throw new Error(`Duplicate schema type name ${actualName}`);
1947 }
1948 actualNamedTypeMap[actualName] = namedType;
1949 // Note: we are deliberately leaving namedType in the schema by its
1950 // original name (which might be different from actualName), so that
1951 // references by that name can be healed.
1952 });
1953 // Now add back every named type by its actual name.
1954 Object.entries(actualNamedTypeMap).forEach(([typeName, namedType]) => {
1955 originalTypeMap[typeName] = namedType;
1956 });
1957 // Directive declaration argument types can refer to named types.
1958 directives.forEach((decl) => {
1959 decl.args = decl.args.filter(arg => {
1960 arg.type = healType(arg.type);
1961 return arg.type !== null;
1962 });
1963 });
1964 Object.entries(originalTypeMap).forEach(([typeName, namedType]) => {
1965 // Heal all named types, except for dangling references, kept only to redirect.
1966 if (!typeName.startsWith('__') && typeName in actualNamedTypeMap) {
1967 if (namedType != null) {
1968 healNamedType(namedType);
1969 }
1970 }
1971 });
1972 for (const typeName of Object.keys(originalTypeMap)) {
1973 if (!typeName.startsWith('__') && !(typeName in actualNamedTypeMap)) {
1974 delete originalTypeMap[typeName];
1975 }
1976 }
1977 if (!config.skipPruning) {
1978 // TODO:
1979 // consider removing the default level of pruning in v7,
1980 // see comments below on the pruneTypes function.
1981 pruneTypes$1(originalTypeMap, directives);
1982 }
1983 function healNamedType(type) {
1984 if (graphql.isObjectType(type)) {
1985 healFields(type);
1986 healInterfaces(type);
1987 return;
1988 }
1989 else if (graphql.isInterfaceType(type)) {
1990 healFields(type);
1991 if ('getInterfaces' in type) {
1992 healInterfaces(type);
1993 }
1994 return;
1995 }
1996 else if (graphql.isUnionType(type)) {
1997 healUnderlyingTypes(type);
1998 return;
1999 }
2000 else if (graphql.isInputObjectType(type)) {
2001 healInputFields(type);
2002 return;
2003 }
2004 else if (graphql.isLeafType(type)) {
2005 return;
2006 }
2007 throw new Error(`Unexpected schema type: ${type}`);
2008 }
2009 function healFields(type) {
2010 const fieldMap = type.getFields();
2011 for (const [key, field] of Object.entries(fieldMap)) {
2012 field.args
2013 .map(arg => {
2014 arg.type = healType(arg.type);
2015 return arg.type === null ? null : arg;
2016 })
2017 .filter(Boolean);
2018 field.type = healType(field.type);
2019 if (field.type === null) {
2020 delete fieldMap[key];
2021 }
2022 }
2023 }
2024 function healInterfaces(type) {
2025 if ('getInterfaces' in type) {
2026 const interfaces = type.getInterfaces();
2027 interfaces.push(...interfaces
2028 .splice(0)
2029 .map(iface => healType(iface))
2030 .filter(Boolean));
2031 }
2032 }
2033 function healInputFields(type) {
2034 const fieldMap = type.getFields();
2035 for (const [key, field] of Object.entries(fieldMap)) {
2036 field.type = healType(field.type);
2037 if (field.type === null) {
2038 delete fieldMap[key];
2039 }
2040 }
2041 }
2042 function healUnderlyingTypes(type) {
2043 const types = type.getTypes();
2044 types.push(...types
2045 .splice(0)
2046 .map(t => healType(t))
2047 .filter(Boolean));
2048 }
2049 function healType(type) {
2050 // Unwrap the two known wrapper types
2051 if (graphql.isListType(type)) {
2052 const healedType = healType(type.ofType);
2053 return healedType != null ? new graphql.GraphQLList(healedType) : null;
2054 }
2055 else if (graphql.isNonNullType(type)) {
2056 const healedType = healType(type.ofType);
2057 return healedType != null ? new graphql.GraphQLNonNull(healedType) : null;
2058 }
2059 else if (graphql.isNamedType(type)) {
2060 // If a type annotation on a field or an argument or a union member is
2061 // any `GraphQLNamedType` with a `name`, then it must end up identical
2062 // to `schema.getType(name)`, since `schema.getTypeMap()` is the source
2063 // of truth for all named schema types.
2064 // Note that new types can still be simply added by adding a field, as
2065 // the official type will be undefined, not null.
2066 const officialType = originalTypeMap[type.name];
2067 if (officialType && type !== officialType) {
2068 return officialType;
2069 }
2070 }
2071 return type;
2072 }
2073}
2074// TODO:
2075// consider removing the default level of pruning in v7
2076//
2077// Pruning was introduced into healSchema in v5, so legacy schema directives relying on pruning
2078// during healing are likely to be rare. pruning is now recommended via the dedicated pruneSchema
2079// function which does not force pruning on library users and gives granular control in terms of
2080// pruning types. pruneSchema does recreate the schema -- a parallel version that prunes in place
2081// could be considered.
2082function pruneTypes$1(typeMap, directives) {
2083 const implementedInterfaces = {};
2084 Object.values(typeMap).forEach(namedType => {
2085 if ('getInterfaces' in namedType) {
2086 namedType.getInterfaces().forEach(iface => {
2087 implementedInterfaces[iface.name] = true;
2088 });
2089 }
2090 });
2091 let prunedTypeMap = false;
2092 const typeNames = Object.keys(typeMap);
2093 for (let i = 0; i < typeNames.length; i++) {
2094 const typeName = typeNames[i];
2095 const type = typeMap[typeName];
2096 if (graphql.isObjectType(type) || graphql.isInputObjectType(type)) {
2097 // prune types with no fields
2098 if (!Object.keys(type.getFields()).length) {
2099 typeMap[typeName] = null;
2100 prunedTypeMap = true;
2101 }
2102 }
2103 else if (graphql.isUnionType(type)) {
2104 // prune unions without underlying types
2105 if (!type.getTypes().length) {
2106 typeMap[typeName] = null;
2107 prunedTypeMap = true;
2108 }
2109 }
2110 else if (graphql.isInterfaceType(type)) {
2111 // prune interfaces without fields or without implementations
2112 if (!Object.keys(type.getFields()).length || !(type.name in implementedInterfaces)) {
2113 typeMap[typeName] = null;
2114 prunedTypeMap = true;
2115 }
2116 }
2117 }
2118 // every prune requires another round of healing
2119 if (prunedTypeMap) {
2120 healTypes(typeMap, directives);
2121 }
2122}
2123
2124// Abstract base class of any visitor implementation, defining the available
2125// visitor methods along with their parameter types, and providing a static
2126// helper function for determining whether a subclass implements a given
2127// visitor method, as opposed to inheriting one of the stubs defined here.
2128class SchemaVisitor {
2129 // Determine if this SchemaVisitor (sub)class implements a particular
2130 // visitor method.
2131 static implementsVisitorMethod(methodName) {
2132 if (!methodName.startsWith('visit')) {
2133 return false;
2134 }
2135 const method = this.prototype[methodName];
2136 if (typeof method !== 'function') {
2137 return false;
2138 }
2139 if (this.name === 'SchemaVisitor') {
2140 // The SchemaVisitor class implements every visitor method.
2141 return true;
2142 }
2143 const stub = SchemaVisitor.prototype[methodName];
2144 if (method === stub) {
2145 // If this.prototype[methodName] was just inherited from SchemaVisitor,
2146 // then this class does not really implement the method.
2147 return false;
2148 }
2149 return true;
2150 }
2151 // Concrete subclasses of SchemaVisitor should override one or more of these
2152 // visitor methods, in order to express their interest in handling certain
2153 // schema types/locations. Each method may return null to remove the given
2154 // type from the schema, a non-null value of the same type to update the
2155 // type in the schema, or nothing to leave the type as it was.
2156 // eslint-disable-next-line @typescript-eslint/no-empty-function
2157 visitSchema(_schema) { }
2158 visitScalar(_scalar
2159 // eslint-disable-next-line @typescript-eslint/no-empty-function
2160 ) { }
2161 visitObject(_object
2162 // eslint-disable-next-line @typescript-eslint/no-empty-function
2163 ) { }
2164 visitFieldDefinition(_field, _details
2165 // eslint-disable-next-line @typescript-eslint/no-empty-function
2166 ) { }
2167 visitArgumentDefinition(_argument, _details
2168 // eslint-disable-next-line @typescript-eslint/no-empty-function
2169 ) { }
2170 visitInterface(_iface
2171 // eslint-disable-next-line @typescript-eslint/no-empty-function
2172 ) { }
2173 // eslint-disable-next-line @typescript-eslint/no-empty-function
2174 visitUnion(_union) { }
2175 // eslint-disable-next-line @typescript-eslint/no-empty-function
2176 visitEnum(_type) { }
2177 visitEnumValue(_value, _details
2178 // eslint-disable-next-line @typescript-eslint/no-empty-function
2179 ) { }
2180 visitInputObject(_object
2181 // eslint-disable-next-line @typescript-eslint/no-empty-function
2182 ) { }
2183 visitInputFieldDefinition(_field, _details
2184 // eslint-disable-next-line @typescript-eslint/no-empty-function
2185 ) { }
2186}
2187
2188function isSchemaVisitor(obj) {
2189 if ('schema' in obj && graphql.isSchema(obj.schema)) {
2190 if ('visitSchema' in obj && typeof obj.visitSchema === 'function') {
2191 return true;
2192 }
2193 }
2194 return false;
2195}
2196// Generic function for visiting GraphQLSchema objects.
2197function visitSchema(schema,
2198// To accommodate as many different visitor patterns as possible, the
2199// visitSchema function does not simply accept a single instance of the
2200// SchemaVisitor class, but instead accepts a function that takes the
2201// current VisitableSchemaType object and the name of a visitor method and
2202// returns an array of SchemaVisitor instances that implement the visitor
2203// method and have an interest in handling the given VisitableSchemaType
2204// object. In the simplest case, this function can always return an array
2205// containing a single visitor object, without even looking at the type or
2206// methodName parameters. In other cases, this function might sometimes
2207// return an empty array to indicate there are no visitors that should be
2208// applied to the given VisitableSchemaType object. For an example of a
2209// visitor pattern that benefits from this abstraction, see the
2210// SchemaDirectiveVisitor class below.
2211visitorOrVisitorSelector) {
2212 const visitorSelector = typeof visitorOrVisitorSelector === 'function' ? visitorOrVisitorSelector : () => visitorOrVisitorSelector;
2213 // Helper function that calls visitorSelector and applies the resulting
2214 // visitors to the given type, with arguments [type, ...args].
2215 function callMethod(methodName, type, ...args) {
2216 let visitors = visitorSelector(type, methodName);
2217 visitors = Array.isArray(visitors) ? visitors : [visitors];
2218 let finalType = type;
2219 visitors.every(visitorOrVisitorDef => {
2220 let newType;
2221 if (isSchemaVisitor(visitorOrVisitorDef)) {
2222 newType = visitorOrVisitorDef[methodName](finalType, ...args);
2223 }
2224 else if (graphql.isNamedType(finalType) &&
2225 (methodName === 'visitScalar' ||
2226 methodName === 'visitEnum' ||
2227 methodName === 'visitObject' ||
2228 methodName === 'visitInputObject' ||
2229 methodName === 'visitUnion' ||
2230 methodName === 'visitInterface')) {
2231 const specifiers = getTypeSpecifiers$1(finalType, schema);
2232 const typeVisitor = getVisitor(visitorOrVisitorDef, specifiers);
2233 newType = typeVisitor != null ? typeVisitor(finalType, schema) : undefined;
2234 }
2235 if (typeof newType === 'undefined') {
2236 // Keep going without modifying type.
2237 return true;
2238 }
2239 if (methodName === 'visitSchema' || graphql.isSchema(finalType)) {
2240 throw new Error(`Method ${methodName} cannot replace schema with ${newType}`);
2241 }
2242 if (newType === null) {
2243 // Stop the loop and return null form callMethod, which will cause
2244 // the type to be removed from the schema.
2245 finalType = null;
2246 return false;
2247 }
2248 // Update type to the new type returned by the visitor method, so that
2249 // later directives will see the new type, and callMethod will return
2250 // the final type.
2251 finalType = newType;
2252 return true;
2253 });
2254 // If there were no directives for this type object, or if all visitor
2255 // methods returned nothing, type will be returned unmodified.
2256 return finalType;
2257 }
2258 // Recursive helper function that calls any appropriate visitor methods for
2259 // each object in the schema, then traverses the object's children (if any).
2260 function visit(type) {
2261 if (graphql.isSchema(type)) {
2262 // Unlike the other types, the root GraphQLSchema object cannot be
2263 // replaced by visitor methods, because that would make life very hard
2264 // for SchemaVisitor subclasses that rely on the original schema object.
2265 callMethod('visitSchema', type);
2266 const typeMap = type.getTypeMap();
2267 Object.entries(typeMap).forEach(([typeName, namedType]) => {
2268 if (!typeName.startsWith('__') && namedType != null) {
2269 // Call visit recursively to let it determine which concrete
2270 // subclass of GraphQLNamedType we found in the type map.
2271 // We do not use updateEachKey because we want to preserve
2272 // deleted types in the typeMap so that other types that reference
2273 // the deleted types can be healed.
2274 typeMap[typeName] = visit(namedType);
2275 }
2276 });
2277 return type;
2278 }
2279 if (graphql.isObjectType(type)) {
2280 // Note that callMethod('visitObject', type) may not actually call any
2281 // methods, if there are no @directive annotations associated with this
2282 // type, or if this SchemaDirectiveVisitor subclass does not override
2283 // the visitObject method.
2284 const newObject = callMethod('visitObject', type);
2285 if (newObject != null) {
2286 visitFields(newObject);
2287 }
2288 return newObject;
2289 }
2290 if (graphql.isInterfaceType(type)) {
2291 const newInterface = callMethod('visitInterface', type);
2292 if (newInterface != null) {
2293 visitFields(newInterface);
2294 }
2295 return newInterface;
2296 }
2297 if (graphql.isInputObjectType(type)) {
2298 const newInputObject = callMethod('visitInputObject', type);
2299 if (newInputObject != null) {
2300 const fieldMap = newInputObject.getFields();
2301 for (const key of Object.keys(fieldMap)) {
2302 fieldMap[key] = callMethod('visitInputFieldDefinition', fieldMap[key], {
2303 // Since we call a different method for input object fields, we
2304 // can't reuse the visitFields function here.
2305 objectType: newInputObject,
2306 });
2307 if (!fieldMap[key]) {
2308 delete fieldMap[key];
2309 }
2310 }
2311 }
2312 return newInputObject;
2313 }
2314 if (graphql.isScalarType(type)) {
2315 return callMethod('visitScalar', type);
2316 }
2317 if (graphql.isUnionType(type)) {
2318 return callMethod('visitUnion', type);
2319 }
2320 if (graphql.isEnumType(type)) {
2321 let newEnum = callMethod('visitEnum', type);
2322 if (newEnum != null) {
2323 const newValues = newEnum
2324 .getValues()
2325 .map(value => callMethod('visitEnumValue', value, {
2326 enumType: newEnum,
2327 }))
2328 .filter(Boolean);
2329 // Recreate the enum type if any of the values changed
2330 const valuesUpdated = newValues.some((value, index) => value !== newEnum.getValues()[index]);
2331 if (valuesUpdated) {
2332 newEnum = new graphql.GraphQLEnumType({
2333 ...newEnum.toConfig(),
2334 values: newValues.reduce((prev, value) => ({
2335 ...prev,
2336 [value.name]: {
2337 value: value.value,
2338 deprecationReason: value.deprecationReason,
2339 description: value.description,
2340 astNode: value.astNode,
2341 },
2342 }), {}),
2343 });
2344 }
2345 }
2346 return newEnum;
2347 }
2348 throw new Error(`Unexpected schema type: ${type}`);
2349 }
2350 function visitFields(type) {
2351 const fieldMap = type.getFields();
2352 for (const [key, field] of Object.entries(fieldMap)) {
2353 // It would be nice if we could call visit(field) recursively here, but
2354 // GraphQLField is merely a type, not a value that can be detected using
2355 // an instanceof check, so we have to visit the fields in this lexical
2356 // context, so that TypeScript can validate the call to
2357 // visitFieldDefinition.
2358 const newField = callMethod('visitFieldDefinition', field, {
2359 // While any field visitor needs a reference to the field object, some
2360 // field visitors may also need to know the enclosing (parent) type,
2361 // perhaps to determine if the parent is a GraphQLObjectType or a
2362 // GraphQLInterfaceType. To obtain a reference to the parent, a
2363 // visitor method can have a second parameter, which will be an object
2364 // with an .objectType property referring to the parent.
2365 objectType: type,
2366 });
2367 if (newField.args != null) {
2368 newField.args = newField.args
2369 .map(arg => callMethod('visitArgumentDefinition', arg, {
2370 // Like visitFieldDefinition, visitArgumentDefinition takes a
2371 // second parameter that provides additional context, namely the
2372 // parent .field and grandparent .objectType. Remember that the
2373 // current GraphQLSchema is always available via this.schema.
2374 field: newField,
2375 objectType: type,
2376 }))
2377 .filter(Boolean);
2378 }
2379 // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2380 if (newField) {
2381 fieldMap[key] = newField;
2382 }
2383 else {
2384 delete fieldMap[key];
2385 }
2386 }
2387 }
2388 visit(schema);
2389 // Automatically update any references to named schema types replaced
2390 // during the traversal, so implementors don't have to worry about that.
2391 healSchema(schema);
2392 // Return schema for convenience, even though schema parameter has all updated types.
2393 return schema;
2394}
2395function getTypeSpecifiers$1(type, schema) {
2396 const specifiers = [exports.VisitSchemaKind.TYPE];
2397 if (graphql.isObjectType(type)) {
2398 specifiers.push(exports.VisitSchemaKind.COMPOSITE_TYPE, exports.VisitSchemaKind.OBJECT_TYPE);
2399 const query = schema.getQueryType();
2400 const mutation = schema.getMutationType();
2401 const subscription = schema.getSubscriptionType();
2402 if (type === query) {
2403 specifiers.push(exports.VisitSchemaKind.ROOT_OBJECT, exports.VisitSchemaKind.QUERY);
2404 }
2405 else if (type === mutation) {
2406 specifiers.push(exports.VisitSchemaKind.ROOT_OBJECT, exports.VisitSchemaKind.MUTATION);
2407 }
2408 else if (type === subscription) {
2409 specifiers.push(exports.VisitSchemaKind.ROOT_OBJECT, exports.VisitSchemaKind.SUBSCRIPTION);
2410 }
2411 }
2412 else if (graphql.isInputType(type)) {
2413 specifiers.push(exports.VisitSchemaKind.INPUT_OBJECT_TYPE);
2414 }
2415 else if (graphql.isInterfaceType(type)) {
2416 specifiers.push(exports.VisitSchemaKind.COMPOSITE_TYPE, exports.VisitSchemaKind.ABSTRACT_TYPE, exports.VisitSchemaKind.INTERFACE_TYPE);
2417 }
2418 else if (graphql.isUnionType(type)) {
2419 specifiers.push(exports.VisitSchemaKind.COMPOSITE_TYPE, exports.VisitSchemaKind.ABSTRACT_TYPE, exports.VisitSchemaKind.UNION_TYPE);
2420 }
2421 else if (graphql.isEnumType(type)) {
2422 specifiers.push(exports.VisitSchemaKind.ENUM_TYPE);
2423 }
2424 else if (graphql.isScalarType(type)) {
2425 specifiers.push(exports.VisitSchemaKind.SCALAR_TYPE);
2426 }
2427 return specifiers;
2428}
2429function getVisitor(visitorDef, specifiers) {
2430 let typeVisitor;
2431 const stack = [...specifiers];
2432 while (!typeVisitor && stack.length > 0) {
2433 const next = stack.pop();
2434 typeVisitor = visitorDef[next];
2435 }
2436 return typeVisitor != null ? typeVisitor : null;
2437}
2438
2439// This class represents a reusable implementation of a @directive that may
2440// appear in a GraphQL schema written in Schema Definition Language.
2441//
2442// By overriding one or more visit{Object,Union,...} methods, a subclass
2443// registers interest in certain schema types, such as GraphQLObjectType,
2444// GraphQLUnionType, etc. When SchemaDirectiveVisitor.visitSchemaDirectives is
2445// called with a GraphQLSchema object and a map of visitor subclasses, the
2446// overidden methods of those subclasses allow the visitors to obtain
2447// references to any type objects that have @directives attached to them,
2448// enabling visitors to inspect or modify the schema as appropriate.
2449//
2450// For example, if a directive called @rest(url: "...") appears after a field
2451// definition, a SchemaDirectiveVisitor subclass could provide meaning to that
2452// directive by overriding the visitFieldDefinition method (which receives a
2453// GraphQLField parameter), and then the body of that visitor method could
2454// manipulate the field's resolver function to fetch data from a REST endpoint
2455// described by the url argument passed to the @rest directive:
2456//
2457// const typeDefs = `
2458// type Query {
2459// people: [Person] @rest(url: "/api/v1/people")
2460// }`;
2461//
2462// const schema = makeExecutableSchema({ typeDefs });
2463//
2464// SchemaDirectiveVisitor.visitSchemaDirectives(schema, {
2465// rest: class extends SchemaDirectiveVisitor {
2466// public visitFieldDefinition(field: GraphQLField<any, any>) {
2467// const { url } = this.args;
2468// field.resolve = () => fetch(url);
2469// }
2470// }
2471// });
2472//
2473// The subclass in this example is defined as an anonymous class expression,
2474// for brevity. A truly reusable SchemaDirectiveVisitor would most likely be
2475// defined in a library using a named class declaration, and then exported for
2476// consumption by other modules and packages.
2477//
2478// See below for a complete list of overridable visitor methods, their
2479// parameter types, and more details about the properties exposed by instances
2480// of the SchemaDirectiveVisitor class.
2481class SchemaDirectiveVisitor extends SchemaVisitor {
2482 // Mark the constructor protected to enforce passing SchemaDirectiveVisitor
2483 // subclasses (not instances) to visitSchemaDirectives.
2484 constructor(config) {
2485 super();
2486 this.name = config.name;
2487 this.args = config.args;
2488 this.visitedType = config.visitedType;
2489 this.schema = config.schema;
2490 this.context = config.context;
2491 }
2492 // Override this method to return a custom GraphQLDirective (or modify one
2493 // already present in the schema) to enforce argument types, provide default
2494 // argument values, or specify schema locations where this @directive may
2495 // appear. By default, any declaration found in the schema will be returned.
2496 static getDirectiveDeclaration(directiveName, schema) {
2497 return schema.getDirective(directiveName);
2498 }
2499 // Call SchemaDirectiveVisitor.visitSchemaDirectives to visit every
2500 // @directive in the schema and create an appropriate SchemaDirectiveVisitor
2501 // instance to visit the object decorated by the @directive.
2502 static visitSchemaDirectives(schema,
2503 // The keys of this object correspond to directive names as they appear
2504 // in the schema, and the values should be subclasses (not instances!)
2505 // of the SchemaDirectiveVisitor class. This distinction is important
2506 // because a new SchemaDirectiveVisitor instance will be created each
2507 // time a matching directive is found in the schema AST, with arguments
2508 // and other metadata specific to that occurrence. To help prevent the
2509 // mistake of passing instances, the SchemaDirectiveVisitor constructor
2510 // method is marked as protected.
2511 directiveVisitors,
2512 // Optional context object that will be available to all visitor instances
2513 // via this.context. Defaults to an empty null-prototype object.
2514 context = Object.create(null)
2515 // The visitSchemaDirectives method returns a map from directive names to
2516 // lists of SchemaDirectiveVisitors created while visiting the schema.
2517 ) {
2518 // If the schema declares any directives for public consumption, record
2519 // them here so that we can properly coerce arguments when/if we encounter
2520 // an occurrence of the directive while walking the schema below.
2521 const declaredDirectives = this.getDeclaredDirectives(schema, directiveVisitors);
2522 // Map from directive names to lists of SchemaDirectiveVisitor instances
2523 // created while visiting the schema.
2524 const createdVisitors = Object.keys(directiveVisitors).reduce((prev, item) => ({
2525 ...prev,
2526 [item]: [],
2527 }), {});
2528 const directiveVisitorMap = Object.entries(directiveVisitors).reduce((prev, [key, value]) => ({
2529 ...prev,
2530 [key]: value,
2531 }), {});
2532 function visitorSelector(type, methodName) {
2533 var _a, _b;
2534 let directiveNodes = (_b = (_a = type === null || type === void 0 ? void 0 : type.astNode) === null || _a === void 0 ? void 0 : _a.directives) !== null && _b !== void 0 ? _b : [];
2535 const extensionASTNodes = type.extensionASTNodes;
2536 if (extensionASTNodes != null) {
2537 extensionASTNodes.forEach(extensionASTNode => {
2538 if (extensionASTNode.directives != null) {
2539 directiveNodes = directiveNodes.concat(extensionASTNode.directives);
2540 }
2541 });
2542 }
2543 const visitors = [];
2544 directiveNodes.forEach(directiveNode => {
2545 const directiveName = directiveNode.name.value;
2546 if (!(directiveName in directiveVisitorMap)) {
2547 return;
2548 }
2549 const VisitorClass = directiveVisitorMap[directiveName];
2550 // Avoid creating visitor objects if visitorClass does not override
2551 // the visitor method named by methodName.
2552 if (!VisitorClass.implementsVisitorMethod(methodName)) {
2553 return;
2554 }
2555 const decl = declaredDirectives[directiveName];
2556 let args;
2557 if (decl != null) {
2558 // If this directive was explicitly declared, use the declared
2559 // argument types (and any default values) to check, coerce, and/or
2560 // supply default values for the given arguments.
2561 args = getArgumentValues(decl, directiveNode);
2562 }
2563 else {
2564 // If this directive was not explicitly declared, just convert the
2565 // argument nodes to their corresponding JavaScript values.
2566 args = Object.create(null);
2567 if (directiveNode.arguments != null) {
2568 directiveNode.arguments.forEach(arg => {
2569 args[arg.name.value] = graphql.valueFromASTUntyped(arg.value);
2570 });
2571 }
2572 }
2573 // As foretold in comments near the top of the visitSchemaDirectives
2574 // method, this is where instances of the SchemaDirectiveVisitor class
2575 // get created and assigned names. While subclasses could override the
2576 // constructor method, the constructor is marked as protected, so
2577 // these are the only arguments that will ever be passed.
2578 visitors.push(new VisitorClass({
2579 name: directiveName,
2580 args,
2581 visitedType: type,
2582 schema,
2583 context,
2584 }));
2585 });
2586 if (visitors.length > 0) {
2587 visitors.forEach(visitor => {
2588 createdVisitors[visitor.name].push(visitor);
2589 });
2590 }
2591 return visitors;
2592 }
2593 visitSchema(schema, visitorSelector);
2594 return createdVisitors;
2595 }
2596 static getDeclaredDirectives(schema, directiveVisitors) {
2597 const declaredDirectives = schema.getDirectives().reduce((prev, curr) => ({
2598 ...prev,
2599 [curr.name]: curr,
2600 }), {});
2601 // If the visitor subclass overrides getDirectiveDeclaration, and it
2602 // returns a non-null GraphQLDirective, use that instead of any directive
2603 // declared in the schema itself. Reasoning: if a SchemaDirectiveVisitor
2604 // goes to the trouble of implementing getDirectiveDeclaration, it should
2605 // be able to rely on that implementation.
2606 Object.entries(directiveVisitors).forEach(([directiveName, visitorClass]) => {
2607 const decl = visitorClass.getDirectiveDeclaration(directiveName, schema);
2608 if (decl != null) {
2609 declaredDirectives[directiveName] = decl;
2610 }
2611 });
2612 Object.entries(declaredDirectives).forEach(([name, decl]) => {
2613 if (!(name in directiveVisitors)) {
2614 // SchemaDirectiveVisitors.visitSchemaDirectives might be called
2615 // multiple times with partial directiveVisitors maps, so it's not
2616 // necessarily an error for directiveVisitors to be missing an
2617 // implementation of a directive that was declared in the schema.
2618 return;
2619 }
2620 const visitorClass = directiveVisitors[name];
2621 decl.locations.forEach(loc => {
2622 const visitorMethodName = directiveLocationToVisitorMethodName(loc);
2623 if (SchemaVisitor.implementsVisitorMethod(visitorMethodName) &&
2624 !visitorClass.implementsVisitorMethod(visitorMethodName)) {
2625 // While visitor subclasses may implement extra visitor methods,
2626 // it's definitely a mistake if the GraphQLDirective declares itself
2627 // applicable to certain schema locations, and the visitor subclass
2628 // does not implement all the corresponding methods.
2629 throw new Error(`SchemaDirectiveVisitor for @${name} must implement ${visitorMethodName} method`);
2630 }
2631 });
2632 });
2633 return declaredDirectives;
2634 }
2635}
2636// Convert a string like "FIELD_DEFINITION" to "visitFieldDefinition".
2637function directiveLocationToVisitorMethodName(loc) {
2638 return ('visit' +
2639 loc.replace(/([^_]*)_?/g, (_wholeMatch, part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()));
2640}
2641
2642function getResolversFromSchema(schema) {
2643 const resolvers = Object.create({});
2644 const typeMap = schema.getTypeMap();
2645 Object.keys(typeMap).forEach(typeName => {
2646 const type = typeMap[typeName];
2647 if (graphql.isScalarType(type)) {
2648 if (!graphql.isSpecifiedScalarType(type)) {
2649 resolvers[typeName] = cloneType(type);
2650 }
2651 }
2652 else if (graphql.isEnumType(type)) {
2653 resolvers[typeName] = {};
2654 const values = type.getValues();
2655 values.forEach(value => {
2656 resolvers[typeName][value.name] = value.value;
2657 });
2658 }
2659 else if (graphql.isInterfaceType(type)) {
2660 if (type.resolveType != null) {
2661 resolvers[typeName] = {
2662 __resolveType: type.resolveType,
2663 };
2664 }
2665 }
2666 else if (graphql.isUnionType(type)) {
2667 if (type.resolveType != null) {
2668 resolvers[typeName] = {
2669 __resolveType: type.resolveType,
2670 };
2671 }
2672 }
2673 else if (graphql.isObjectType(type)) {
2674 resolvers[typeName] = {};
2675 if (type.isTypeOf != null) {
2676 resolvers[typeName].__isTypeOf = type.isTypeOf;
2677 }
2678 const fields = type.getFields();
2679 Object.keys(fields).forEach(fieldName => {
2680 const field = fields[fieldName];
2681 resolvers[typeName][fieldName] = {
2682 resolve: field.resolve,
2683 subscribe: field.subscribe,
2684 };
2685 });
2686 }
2687 });
2688 return resolvers;
2689}
2690
2691function forEachField(schema, fn) {
2692 const typeMap = schema.getTypeMap();
2693 Object.keys(typeMap).forEach(typeName => {
2694 const type = typeMap[typeName];
2695 // TODO: maybe have an option to include these?
2696 if (!graphql.getNamedType(type).name.startsWith('__') && graphql.isObjectType(type)) {
2697 const fields = type.getFields();
2698 Object.keys(fields).forEach(fieldName => {
2699 const field = fields[fieldName];
2700 fn(field, typeName, fieldName);
2701 });
2702 }
2703 });
2704}
2705
2706function forEachDefaultValue(schema, fn) {
2707 const typeMap = schema.getTypeMap();
2708 Object.keys(typeMap).forEach(typeName => {
2709 const type = typeMap[typeName];
2710 if (!graphql.getNamedType(type).name.startsWith('__')) {
2711 if (graphql.isObjectType(type)) {
2712 const fields = type.getFields();
2713 Object.keys(fields).forEach(fieldName => {
2714 const field = fields[fieldName];
2715 field.args.forEach(arg => {
2716 arg.defaultValue = fn(arg.type, arg.defaultValue);
2717 });
2718 });
2719 }
2720 else if (graphql.isInputObjectType(type)) {
2721 const fields = type.getFields();
2722 Object.keys(fields).forEach(fieldName => {
2723 const field = fields[fieldName];
2724 field.defaultValue = fn(field.type, field.defaultValue);
2725 });
2726 }
2727 }
2728 });
2729}
2730
2731// addTypes uses toConfig to create a new schema with a new or replaced
2732function addTypes(schema, newTypesOrDirectives) {
2733 const queryType = schema.getQueryType();
2734 const mutationType = schema.getMutationType();
2735 const subscriptionType = schema.getSubscriptionType();
2736 const queryTypeName = queryType != null ? queryType.name : undefined;
2737 const mutationTypeName = mutationType != null ? mutationType.name : undefined;
2738 const subscriptionTypeName = subscriptionType != null ? subscriptionType.name : undefined;
2739 const config = schema.toConfig();
2740 const originalTypeMap = {};
2741 config.types.forEach(type => {
2742 originalTypeMap[type.name] = type;
2743 });
2744 const originalDirectiveMap = {};
2745 config.directives.forEach(directive => {
2746 originalDirectiveMap[directive.name] = directive;
2747 });
2748 newTypesOrDirectives.forEach(newTypeOrDirective => {
2749 if (graphql.isNamedType(newTypeOrDirective)) {
2750 originalTypeMap[newTypeOrDirective.name] = newTypeOrDirective;
2751 }
2752 else if (graphql.isDirective(newTypeOrDirective)) {
2753 originalDirectiveMap[newTypeOrDirective.name] = newTypeOrDirective;
2754 }
2755 });
2756 const { typeMap, directives } = rewireTypes(originalTypeMap, Object.keys(originalDirectiveMap).map(directiveName => originalDirectiveMap[directiveName]));
2757 return new graphql.GraphQLSchema({
2758 ...config,
2759 query: queryTypeName ? typeMap[queryTypeName] : undefined,
2760 mutation: mutationTypeName ? typeMap[mutationTypeName] : undefined,
2761 subscription: subscriptionTypeName != null ? typeMap[subscriptionTypeName] : undefined,
2762 types: Object.keys(typeMap).map(typeName => typeMap[typeName]),
2763 directives,
2764 });
2765}
2766
2767/**
2768 * Prunes the provided schema, removing unused and empty types
2769 * @param schema The schema to prune
2770 * @param options Additional options for removing unused types from the schema
2771 */
2772function pruneSchema(schema, options = {}) {
2773 const pruningContext = {
2774 schema,
2775 unusedTypes: Object.create(null),
2776 implementations: Object.create(null),
2777 };
2778 Object.keys(schema.getTypeMap()).forEach(typeName => {
2779 const type = schema.getType(typeName);
2780 if ('getInterfaces' in type) {
2781 type.getInterfaces().forEach(iface => {
2782 if (pruningContext.implementations[iface.name] == null) {
2783 pruningContext.implementations[iface.name] = Object.create(null);
2784 }
2785 pruningContext.implementations[iface.name][type.name] = true;
2786 });
2787 }
2788 });
2789 visitTypes(pruningContext, schema);
2790 return mapSchema(schema, {
2791 [exports.MapperKind.TYPE]: (type) => {
2792 if (graphql.isObjectType(type) || graphql.isInputObjectType(type)) {
2793 if ((!Object.keys(type.getFields()).length && !options.skipEmptyCompositeTypePruning) ||
2794 (pruningContext.unusedTypes[type.name] && !options.skipUnusedTypesPruning)) {
2795 return null;
2796 }
2797 }
2798 else if (graphql.isUnionType(type)) {
2799 if ((!type.getTypes().length && !options.skipEmptyUnionPruning) ||
2800 (pruningContext.unusedTypes[type.name] && !options.skipUnusedTypesPruning)) {
2801 return null;
2802 }
2803 }
2804 else if (graphql.isInterfaceType(type)) {
2805 if ((!Object.keys(type.getFields()).length && !options.skipEmptyCompositeTypePruning) ||
2806 (!Object.keys(pruningContext.implementations[type.name]).length &&
2807 !options.skipUnimplementedInterfacesPruning) ||
2808 (pruningContext.unusedTypes[type.name] && !options.skipUnusedTypesPruning)) {
2809 return null;
2810 }
2811 }
2812 else {
2813 if (pruningContext.unusedTypes[type.name] && !options.skipUnusedTypesPruning) {
2814 return null;
2815 }
2816 }
2817 },
2818 });
2819}
2820function visitOutputType(visitedTypes, pruningContext, type) {
2821 if (visitedTypes[type.name]) {
2822 return;
2823 }
2824 visitedTypes[type.name] = true;
2825 pruningContext.unusedTypes[type.name] = false;
2826 if (graphql.isObjectType(type) || graphql.isInterfaceType(type)) {
2827 const fields = type.getFields();
2828 Object.keys(fields).forEach(fieldName => {
2829 const field = fields[fieldName];
2830 const namedType = graphql.getNamedType(field.type);
2831 visitOutputType(visitedTypes, pruningContext, namedType);
2832 const args = field.args;
2833 args.forEach(arg => {
2834 const type = graphql.getNamedType(arg.type);
2835 visitInputType(visitedTypes, pruningContext, type);
2836 });
2837 });
2838 if (graphql.isInterfaceType(type)) {
2839 Object.keys(pruningContext.implementations[type.name]).forEach(typeName => {
2840 visitOutputType(visitedTypes, pruningContext, pruningContext.schema.getType(typeName));
2841 });
2842 }
2843 if ('getInterfaces' in type) {
2844 type.getInterfaces().forEach(type => {
2845 visitOutputType(visitedTypes, pruningContext, type);
2846 });
2847 }
2848 }
2849 else if (graphql.isUnionType(type)) {
2850 const types = type.getTypes();
2851 types.forEach(type => visitOutputType(visitedTypes, pruningContext, type));
2852 }
2853}
2854function visitInputType(visitedTypes, pruningContext, type) {
2855 if (visitedTypes[type.name]) {
2856 return;
2857 }
2858 pruningContext.unusedTypes[type.name] = false;
2859 if (graphql.isInputObjectType(type)) {
2860 const fields = type.getFields();
2861 Object.keys(fields).forEach(fieldName => {
2862 const field = fields[fieldName];
2863 const namedType = graphql.getNamedType(field.type);
2864 visitInputType(visitedTypes, pruningContext, namedType);
2865 });
2866 }
2867 visitedTypes[type.name] = true;
2868}
2869function visitTypes(pruningContext, schema) {
2870 Object.keys(schema.getTypeMap()).forEach(typeName => {
2871 if (!typeName.startsWith('__')) {
2872 pruningContext.unusedTypes[typeName] = true;
2873 }
2874 });
2875 const visitedTypes = Object.create(null);
2876 const rootTypes = [schema.getQueryType(), schema.getMutationType(), schema.getSubscriptionType()].filter(type => type != null);
2877 rootTypes.forEach(rootType => visitOutputType(visitedTypes, pruningContext, rootType));
2878 schema.getDirectives().forEach(directive => {
2879 directive.args.forEach(arg => {
2880 const type = graphql.getNamedType(arg.type);
2881 visitInputType(visitedTypes, pruningContext, type);
2882 });
2883 });
2884}
2885
2886/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
2887function mergeDeep(target, ...sources) {
2888 if (graphql.isScalarType(target)) {
2889 return target;
2890 }
2891 const output = {
2892 ...target,
2893 };
2894 for (const source of sources) {
2895 if (isObject(target) && isObject(source)) {
2896 for (const key in source) {
2897 if (isObject(source[key])) {
2898 if (!(key in target)) {
2899 Object.assign(output, { [key]: source[key] });
2900 }
2901 else {
2902 output[key] = mergeDeep(target[key], source[key]);
2903 }
2904 }
2905 else {
2906 Object.assign(output, { [key]: source[key] });
2907 }
2908 }
2909 }
2910 }
2911 return output;
2912}
2913function isObject(item) {
2914 return item && typeof item === 'object' && !Array.isArray(item);
2915}
2916
2917function renameFieldNode(fieldNode, name) {
2918 return {
2919 ...fieldNode,
2920 alias: {
2921 kind: graphql.Kind.NAME,
2922 value: fieldNode.alias != null ? fieldNode.alias.value : fieldNode.name.value,
2923 },
2924 name: {
2925 kind: graphql.Kind.NAME,
2926 value: name,
2927 },
2928 };
2929}
2930function preAliasFieldNode(fieldNode, str) {
2931 return {
2932 ...fieldNode,
2933 alias: {
2934 kind: graphql.Kind.NAME,
2935 value: `${str}${fieldNode.alias != null ? fieldNode.alias.value : fieldNode.name.value}`,
2936 },
2937 };
2938}
2939function wrapFieldNode(fieldNode, path) {
2940 let newFieldNode = fieldNode;
2941 path.forEach(fieldName => {
2942 newFieldNode = {
2943 kind: graphql.Kind.FIELD,
2944 name: {
2945 kind: graphql.Kind.NAME,
2946 value: fieldName,
2947 },
2948 selectionSet: {
2949 kind: graphql.Kind.SELECTION_SET,
2950 selections: [fieldNode],
2951 },
2952 };
2953 });
2954 return newFieldNode;
2955}
2956function collectFields(selectionSet, fragments, fields = [], visitedFragmentNames = {}) {
2957 if (selectionSet != null) {
2958 selectionSet.selections.forEach(selection => {
2959 switch (selection.kind) {
2960 case graphql.Kind.FIELD:
2961 fields.push(selection);
2962 break;
2963 case graphql.Kind.INLINE_FRAGMENT:
2964 collectFields(selection.selectionSet, fragments, fields, visitedFragmentNames);
2965 break;
2966 case graphql.Kind.FRAGMENT_SPREAD: {
2967 const fragmentName = selection.name.value;
2968 if (!visitedFragmentNames[fragmentName]) {
2969 visitedFragmentNames[fragmentName] = true;
2970 collectFields(fragments[fragmentName].selectionSet, fragments, fields, visitedFragmentNames);
2971 }
2972 break;
2973 }
2974 }
2975 });
2976 }
2977 return fields;
2978}
2979function hoistFieldNodes({ fieldNode, fieldNames, path = [], delimeter = '__gqltf__', fragments, }) {
2980 const alias = fieldNode.alias != null ? fieldNode.alias.value : fieldNode.name.value;
2981 let newFieldNodes = [];
2982 if (path.length) {
2983 const remainingPathSegments = path.slice();
2984 const initialPathSegment = remainingPathSegments.shift();
2985 collectFields(fieldNode.selectionSet, fragments).forEach((possibleFieldNode) => {
2986 if (possibleFieldNode.name.value === initialPathSegment) {
2987 newFieldNodes = newFieldNodes.concat(hoistFieldNodes({
2988 fieldNode: preAliasFieldNode(possibleFieldNode, `${alias}${delimeter}`),
2989 fieldNames,
2990 path: remainingPathSegments,
2991 delimeter,
2992 fragments,
2993 }));
2994 }
2995 });
2996 }
2997 else {
2998 collectFields(fieldNode.selectionSet, fragments).forEach((possibleFieldNode) => {
2999 if (!fieldNames || fieldNames.includes(possibleFieldNode.name.value)) {
3000 newFieldNodes.push(preAliasFieldNode(possibleFieldNode, `${alias}${delimeter}`));
3001 }
3002 });
3003 }
3004 return newFieldNodes;
3005}
3006
3007function concatInlineFragments(type, fragments) {
3008 const fragmentSelections = fragments.reduce((selections, fragment) => selections.concat(fragment.selectionSet.selections), []);
3009 const deduplicatedFragmentSelection = deduplicateSelection(fragmentSelections);
3010 return {
3011 kind: graphql.Kind.INLINE_FRAGMENT,
3012 typeCondition: {
3013 kind: graphql.Kind.NAMED_TYPE,
3014 name: {
3015 kind: graphql.Kind.NAME,
3016 value: type,
3017 },
3018 },
3019 selectionSet: {
3020 kind: graphql.Kind.SELECTION_SET,
3021 selections: deduplicatedFragmentSelection,
3022 },
3023 };
3024}
3025function deduplicateSelection(nodes) {
3026 const selectionMap = nodes.reduce((map, node) => {
3027 switch (node.kind) {
3028 case 'Field': {
3029 if (node.alias != null) {
3030 if (node.alias.value in map) {
3031 return map;
3032 }
3033 return {
3034 ...map,
3035 [node.alias.value]: node,
3036 };
3037 }
3038 if (node.name.value in map) {
3039 return map;
3040 }
3041 return {
3042 ...map,
3043 [node.name.value]: node,
3044 };
3045 }
3046 case 'FragmentSpread': {
3047 if (node.name.value in map) {
3048 return map;
3049 }
3050 return {
3051 ...map,
3052 [node.name.value]: node,
3053 };
3054 }
3055 case 'InlineFragment': {
3056 if (map.__fragment != null) {
3057 const fragment = map.__fragment;
3058 return {
3059 ...map,
3060 __fragment: concatInlineFragments(fragment.typeCondition.name.value, [fragment, node]),
3061 };
3062 }
3063 return {
3064 ...map,
3065 __fragment: node,
3066 };
3067 }
3068 default: {
3069 return map;
3070 }
3071 }
3072 }, Object.create(null));
3073 const selection = Object.keys(selectionMap).reduce((selectionList, node) => selectionList.concat(selectionMap[node]), []);
3074 return selection;
3075}
3076function parseFragmentToInlineFragment(definitions) {
3077 if (definitions.trim().startsWith('fragment')) {
3078 const document = graphql.parse(definitions);
3079 for (const definition of document.definitions) {
3080 if (definition.kind === graphql.Kind.FRAGMENT_DEFINITION) {
3081 return {
3082 kind: graphql.Kind.INLINE_FRAGMENT,
3083 typeCondition: definition.typeCondition,
3084 selectionSet: definition.selectionSet,
3085 };
3086 }
3087 }
3088 }
3089 const query = graphql.parse(`{${definitions}}`).definitions[0];
3090 for (const selection of query.selectionSet.selections) {
3091 if (selection.kind === graphql.Kind.INLINE_FRAGMENT) {
3092 return selection;
3093 }
3094 }
3095 throw new Error('Could not parse fragment');
3096}
3097
3098function parseSelectionSet(selectionSet) {
3099 const query = graphql.parse(selectionSet).definitions[0];
3100 return query.selectionSet;
3101}
3102function typeContainsSelectionSet(type, selectionSet) {
3103 const fields = type.getFields();
3104 for (const selection of selectionSet.selections) {
3105 if (selection.kind === graphql.Kind.FIELD) {
3106 const field = fields[selection.name.value];
3107 if (field == null) {
3108 return false;
3109 }
3110 if (selection.selectionSet != null) {
3111 return typeContainsSelectionSet(graphql.getNamedType(field.type), selection.selectionSet);
3112 }
3113 }
3114 else if (selection.kind === graphql.Kind.INLINE_FRAGMENT) {
3115 const containsSelectionSet = typeContainsSelectionSet(type, selection.selectionSet);
3116 if (!containsSelectionSet) {
3117 return false;
3118 }
3119 }
3120 }
3121 return true;
3122}
3123
3124/**
3125 * Get the key under which the result of this resolver will be placed in the response JSON. Basically, just
3126 * resolves aliases.
3127 * @param info The info argument to the resolver.
3128 */
3129function getResponseKeyFromInfo(info) {
3130 return info.fieldNodes[0].alias != null ? info.fieldNodes[0].alias.value : info.fieldName;
3131}
3132
3133function applySchemaTransforms(originalSchema, transforms) {
3134 return transforms.reduce((schema, transform) => transform.transformSchema != null ? transform.transformSchema(cloneSchema(schema)) : schema, originalSchema);
3135}
3136function applyRequestTransforms(originalRequest, transforms) {
3137 return transforms.reduce((request, transform) => transform.transformRequest != null ? transform.transformRequest(request) : request, originalRequest);
3138}
3139function applyResultTransforms(originalResult, transforms) {
3140 return transforms.reduceRight((result, transform) => transform.transformResult != null ? transform.transformResult(result) : result, originalResult);
3141}
3142
3143function appendObjectFields(schema, typeName, additionalFields) {
3144 if (schema.getType(typeName) == null) {
3145 return addTypes(schema, [
3146 new graphql.GraphQLObjectType({
3147 name: typeName,
3148 fields: additionalFields,
3149 }),
3150 ]);
3151 }
3152 return mapSchema(schema, {
3153 [exports.MapperKind.OBJECT_TYPE]: type => {
3154 if (type.name === typeName) {
3155 const config = type.toConfig();
3156 const originalFieldConfigMap = config.fields;
3157 const newFieldConfigMap = {};
3158 Object.keys(originalFieldConfigMap).forEach(fieldName => {
3159 newFieldConfigMap[fieldName] = originalFieldConfigMap[fieldName];
3160 });
3161 Object.keys(additionalFields).forEach(fieldName => {
3162 newFieldConfigMap[fieldName] = additionalFields[fieldName];
3163 });
3164 return correctASTNodes(new graphql.GraphQLObjectType({
3165 ...config,
3166 fields: newFieldConfigMap,
3167 }));
3168 }
3169 },
3170 });
3171}
3172function removeObjectFields(schema, typeName, testFn) {
3173 const removedFields = {};
3174 const newSchema = mapSchema(schema, {
3175 [exports.MapperKind.OBJECT_TYPE]: type => {
3176 if (type.name === typeName) {
3177 const config = type.toConfig();
3178 const originalFieldConfigMap = config.fields;
3179 const newFieldConfigMap = {};
3180 Object.keys(originalFieldConfigMap).forEach(fieldName => {
3181 const originalFieldConfig = originalFieldConfigMap[fieldName];
3182 if (testFn(fieldName, originalFieldConfig)) {
3183 removedFields[fieldName] = originalFieldConfig;
3184 }
3185 else {
3186 newFieldConfigMap[fieldName] = originalFieldConfig;
3187 }
3188 });
3189 return correctASTNodes(new graphql.GraphQLObjectType({
3190 ...config,
3191 fields: newFieldConfigMap,
3192 }));
3193 }
3194 },
3195 });
3196 return [newSchema, removedFields];
3197}
3198function selectObjectFields(schema, typeName, testFn) {
3199 const selectedFields = {};
3200 mapSchema(schema, {
3201 [exports.MapperKind.OBJECT_TYPE]: type => {
3202 if (type.name === typeName) {
3203 const config = type.toConfig();
3204 const originalFieldConfigMap = config.fields;
3205 Object.keys(originalFieldConfigMap).forEach(fieldName => {
3206 const originalFieldConfig = originalFieldConfigMap[fieldName];
3207 if (testFn(fieldName, originalFieldConfig)) {
3208 selectedFields[fieldName] = originalFieldConfig;
3209 }
3210 });
3211 }
3212 return undefined;
3213 },
3214 });
3215 return selectedFields;
3216}
3217function modifyObjectFields(schema, typeName, testFn, newFields) {
3218 const removedFields = {};
3219 const newSchema = mapSchema(schema, {
3220 [exports.MapperKind.OBJECT_TYPE]: type => {
3221 if (type.name === typeName) {
3222 const config = type.toConfig();
3223 const originalFieldConfigMap = config.fields;
3224 const newFieldConfigMap = {};
3225 Object.keys(originalFieldConfigMap).forEach(fieldName => {
3226 const originalFieldConfig = originalFieldConfigMap[fieldName];
3227 if (testFn(fieldName, originalFieldConfig)) {
3228 removedFields[fieldName] = originalFieldConfig;
3229 }
3230 else {
3231 newFieldConfigMap[fieldName] = originalFieldConfig;
3232 }
3233 });
3234 Object.keys(newFields).forEach(fieldName => {
3235 const fieldConfig = newFields[fieldName];
3236 newFieldConfigMap[fieldName] = fieldConfig;
3237 });
3238 return correctASTNodes(new graphql.GraphQLObjectType({
3239 ...config,
3240 fields: newFieldConfigMap,
3241 }));
3242 }
3243 },
3244 });
3245 return [newSchema, removedFields];
3246}
3247
3248function renameType(type, newTypeName) {
3249 if (graphql.isObjectType(type)) {
3250 return new graphql.GraphQLObjectType({
3251 ...type.toConfig(),
3252 name: newTypeName,
3253 astNode: type.astNode == null
3254 ? type.astNode
3255 : {
3256 ...type.astNode,
3257 name: {
3258 ...type.astNode.name,
3259 value: newTypeName,
3260 },
3261 },
3262 extensionASTNodes: type.extensionASTNodes == null
3263 ? type.extensionASTNodes
3264 : type.extensionASTNodes.map(node => ({
3265 ...node,
3266 name: {
3267 ...node.name,
3268 value: newTypeName,
3269 },
3270 })),
3271 });
3272 }
3273 else if (graphql.isInterfaceType(type)) {
3274 return new graphql.GraphQLInterfaceType({
3275 ...type.toConfig(),
3276 name: newTypeName,
3277 astNode: type.astNode == null
3278 ? type.astNode
3279 : {
3280 ...type.astNode,
3281 name: {
3282 ...type.astNode.name,
3283 value: newTypeName,
3284 },
3285 },
3286 extensionASTNodes: type.extensionASTNodes == null
3287 ? type.extensionASTNodes
3288 : type.extensionASTNodes.map(node => ({
3289 ...node,
3290 name: {
3291 ...node.name,
3292 value: newTypeName,
3293 },
3294 })),
3295 });
3296 }
3297 else if (graphql.isUnionType(type)) {
3298 return new graphql.GraphQLUnionType({
3299 ...type.toConfig(),
3300 name: newTypeName,
3301 astNode: type.astNode == null
3302 ? type.astNode
3303 : {
3304 ...type.astNode,
3305 name: {
3306 ...type.astNode.name,
3307 value: newTypeName,
3308 },
3309 },
3310 extensionASTNodes: type.extensionASTNodes == null
3311 ? type.extensionASTNodes
3312 : type.extensionASTNodes.map(node => ({
3313 ...node,
3314 name: {
3315 ...node.name,
3316 value: newTypeName,
3317 },
3318 })),
3319 });
3320 }
3321 else if (graphql.isInputObjectType(type)) {
3322 return new graphql.GraphQLInputObjectType({
3323 ...type.toConfig(),
3324 name: newTypeName,
3325 astNode: type.astNode == null
3326 ? type.astNode
3327 : {
3328 ...type.astNode,
3329 name: {
3330 ...type.astNode.name,
3331 value: newTypeName,
3332 },
3333 },
3334 extensionASTNodes: type.extensionASTNodes == null
3335 ? type.extensionASTNodes
3336 : type.extensionASTNodes.map(node => ({
3337 ...node,
3338 name: {
3339 ...node.name,
3340 value: newTypeName,
3341 },
3342 })),
3343 });
3344 }
3345 else if (graphql.isEnumType(type)) {
3346 return new graphql.GraphQLEnumType({
3347 ...type.toConfig(),
3348 name: newTypeName,
3349 astNode: type.astNode == null
3350 ? type.astNode
3351 : {
3352 ...type.astNode,
3353 name: {
3354 ...type.astNode.name,
3355 value: newTypeName,
3356 },
3357 },
3358 extensionASTNodes: type.extensionASTNodes == null
3359 ? type.extensionASTNodes
3360 : type.extensionASTNodes.map(node => ({
3361 ...node,
3362 name: {
3363 ...node.name,
3364 value: newTypeName,
3365 },
3366 })),
3367 });
3368 }
3369 else if (graphql.isScalarType(type)) {
3370 return new graphql.GraphQLScalarType({
3371 ...type.toConfig(),
3372 name: newTypeName,
3373 astNode: type.astNode == null
3374 ? type.astNode
3375 : {
3376 ...type.astNode,
3377 name: {
3378 ...type.astNode.name,
3379 value: newTypeName,
3380 },
3381 },
3382 extensionASTNodes: type.extensionASTNodes == null
3383 ? type.extensionASTNodes
3384 : type.extensionASTNodes.map(node => ({
3385 ...node,
3386 name: {
3387 ...node.name,
3388 value: newTypeName,
3389 },
3390 })),
3391 });
3392 }
3393 throw new Error(`Unknown type ${type}.`);
3394}
3395
3396/**
3397 * Given a selectionSet, adds all of the fields in that selection to
3398 * the passed in map of fields, and returns it at the end.
3399 *
3400 * CollectFields requires the "runtime type" of an object. For a field which
3401 * returns an Interface or Union type, the "runtime type" will be the actual
3402 * Object type returned by that field.
3403 *
3404 * @internal
3405 */
3406function collectFields$1(exeContext, runtimeType, selectionSet, fields, visitedFragmentNames) {
3407 for (const selection of selectionSet.selections) {
3408 switch (selection.kind) {
3409 case graphql.Kind.FIELD: {
3410 if (!shouldIncludeNode(exeContext, selection)) {
3411 continue;
3412 }
3413 const name = getFieldEntryKey(selection);
3414 if (!(name in fields)) {
3415 fields[name] = [];
3416 }
3417 fields[name].push(selection);
3418 break;
3419 }
3420 case graphql.Kind.INLINE_FRAGMENT: {
3421 if (!shouldIncludeNode(exeContext, selection) ||
3422 !doesFragmentConditionMatch(exeContext, selection, runtimeType)) {
3423 continue;
3424 }
3425 collectFields$1(exeContext, runtimeType, selection.selectionSet, fields, visitedFragmentNames);
3426 break;
3427 }
3428 case graphql.Kind.FRAGMENT_SPREAD: {
3429 const fragName = selection.name.value;
3430 if (visitedFragmentNames[fragName] || !shouldIncludeNode(exeContext, selection)) {
3431 continue;
3432 }
3433 visitedFragmentNames[fragName] = true;
3434 const fragment = exeContext.fragments[fragName];
3435 if (!fragment || !doesFragmentConditionMatch(exeContext, fragment, runtimeType)) {
3436 continue;
3437 }
3438 collectFields$1(exeContext, runtimeType, fragment.selectionSet, fields, visitedFragmentNames);
3439 break;
3440 }
3441 }
3442 }
3443 return fields;
3444}
3445/**
3446 * Determines if a field should be included based on the @include and @skip
3447 * directives, where @skip has higher precedence than @include.
3448 */
3449function shouldIncludeNode(exeContext, node) {
3450 const skip = graphql.getDirectiveValues(graphql.GraphQLSkipDirective, node, exeContext.variableValues);
3451 if ((skip === null || skip === void 0 ? void 0 : skip.if) === true) {
3452 return false;
3453 }
3454 const include = graphql.getDirectiveValues(graphql.GraphQLIncludeDirective, node, exeContext.variableValues);
3455 if ((include === null || include === void 0 ? void 0 : include.if) === false) {
3456 return false;
3457 }
3458 return true;
3459}
3460/**
3461 * Determines if a fragment is applicable to the given type.
3462 */
3463function doesFragmentConditionMatch(exeContext, fragment, type) {
3464 const typeConditionNode = fragment.typeCondition;
3465 if (!typeConditionNode) {
3466 return true;
3467 }
3468 const conditionalType = graphql.typeFromAST(exeContext.schema, typeConditionNode);
3469 if (conditionalType === type) {
3470 return true;
3471 }
3472 if (graphql.isAbstractType(conditionalType)) {
3473 return exeContext.schema.isPossibleType(conditionalType, type);
3474 }
3475 return false;
3476}
3477/**
3478 * Implements the logic to compute the key of a given field's entry
3479 */
3480function getFieldEntryKey(node) {
3481 // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
3482 return node.alias ? node.alias.value : node.name.value;
3483}
3484
3485/**
3486 * Given an AsyncIterable and a callback function, return an AsyncIterator
3487 * which produces values mapped via calling the callback function.
3488 */
3489function mapAsyncIterator(iterator, callback, rejectCallback) {
3490 let $return;
3491 let abruptClose;
3492 if (typeof iterator.return === 'function') {
3493 $return = iterator.return;
3494 abruptClose = (error) => {
3495 const rethrow = () => Promise.reject(error);
3496 return $return.call(iterator).then(rethrow, rethrow);
3497 };
3498 }
3499 function mapResult(result) {
3500 return result.done ? result : asyncMapValue(result.value, callback).then(iteratorResult, abruptClose);
3501 }
3502 let mapReject;
3503 if (rejectCallback) {
3504 // Capture rejectCallback to ensure it cannot be null.
3505 const reject = rejectCallback;
3506 mapReject = (error) => asyncMapValue(error, reject).then(iteratorResult, abruptClose);
3507 }
3508 return {
3509 next() {
3510 return iterator.next().then(mapResult, mapReject);
3511 },
3512 return() {
3513 return $return
3514 ? $return.call(iterator).then(mapResult, mapReject)
3515 : Promise.resolve({ value: undefined, done: true });
3516 },
3517 throw(error) {
3518 if (typeof iterator.throw === 'function') {
3519 return iterator.throw(error).then(mapResult, mapReject);
3520 }
3521 return Promise.reject(error).catch(abruptClose);
3522 },
3523 [Symbol.asyncIterator]() {
3524 return this;
3525 },
3526 };
3527}
3528function asyncMapValue(value, callback) {
3529 return new Promise(resolve => resolve(callback(value)));
3530}
3531function iteratorResult(value) {
3532 return { value, done: false };
3533}
3534
3535function astFromType(type) {
3536 if (graphql.isNonNullType(type)) {
3537 const innerType = astFromType(type.ofType);
3538 if (innerType.kind === graphql.Kind.NON_NULL_TYPE) {
3539 throw new Error(`Invalid type node ${JSON.stringify(type)}. Inner type of non-null type cannot be a non-null type.`);
3540 }
3541 return {
3542 kind: graphql.Kind.NON_NULL_TYPE,
3543 type: innerType,
3544 };
3545 }
3546 else if (graphql.isListType(type)) {
3547 return {
3548 kind: graphql.Kind.LIST_TYPE,
3549 type: astFromType(type.ofType),
3550 };
3551 }
3552 return {
3553 kind: graphql.Kind.NAMED_TYPE,
3554 name: {
3555 kind: graphql.Kind.NAME,
3556 value: type.name,
3557 },
3558 };
3559}
3560
3561function updateArgument(argName, argType, argumentNodes, variableDefinitionsMap, variableValues, newArg) {
3562 let varName;
3563 let numGeneratedVariables = 0;
3564 do {
3565 varName = `_v${(numGeneratedVariables++).toString()}_${argName}`;
3566 } while (varName in variableDefinitionsMap);
3567 argumentNodes[argName] = {
3568 kind: graphql.Kind.ARGUMENT,
3569 name: {
3570 kind: graphql.Kind.NAME,
3571 value: argName,
3572 },
3573 value: {
3574 kind: graphql.Kind.VARIABLE,
3575 name: {
3576 kind: graphql.Kind.NAME,
3577 value: varName,
3578 },
3579 },
3580 };
3581 variableDefinitionsMap[varName] = {
3582 kind: graphql.Kind.VARIABLE_DEFINITION,
3583 variable: {
3584 kind: graphql.Kind.VARIABLE,
3585 name: {
3586 kind: graphql.Kind.NAME,
3587 value: varName,
3588 },
3589 },
3590 type: astFromType(argType),
3591 };
3592 if (newArg === undefined) {
3593 delete variableValues[varName];
3594 }
3595 else {
3596 variableValues[varName] = newArg;
3597 }
3598}
3599
3600function implementsAbstractType(schema, typeA, typeB) {
3601 if (typeA === typeB) {
3602 return true;
3603 }
3604 else if (graphql.isCompositeType(typeA) && graphql.isCompositeType(typeB)) {
3605 return graphql.doTypesOverlap(schema, typeA, typeB);
3606 }
3607 return false;
3608}
3609
3610const ERROR_SYMBOL = Symbol('subschemaErrors');
3611function relocatedError(originalError, path) {
3612 return new graphql.GraphQLError(originalError.message, originalError.nodes, originalError.source, originalError.positions, path === null ? undefined : path === undefined ? originalError.path : path, originalError.originalError, originalError.extensions);
3613}
3614function slicedError(originalError) {
3615 return relocatedError(originalError, originalError.path != null ? originalError.path.slice(1) : undefined);
3616}
3617function getErrorsByPathSegment(errors) {
3618 const record = Object.create(null);
3619 errors.forEach(error => {
3620 if (!error.path || error.path.length < 2) {
3621 return;
3622 }
3623 const pathSegment = error.path[1];
3624 const current = pathSegment in record ? record[pathSegment] : [];
3625 current.push(slicedError(error));
3626 record[pathSegment] = current;
3627 });
3628 return record;
3629}
3630function setErrors(result, errors) {
3631 result[ERROR_SYMBOL] = errors;
3632}
3633function getErrors(result, pathSegment) {
3634 const errors = result != null ? result[ERROR_SYMBOL] : result;
3635 if (!Array.isArray(errors)) {
3636 return null;
3637 }
3638 const fieldErrors = [];
3639 for (const error of errors) {
3640 if (!error.path || error.path[0] === pathSegment) {
3641 fieldErrors.push(error);
3642 }
3643 }
3644 return fieldErrors;
3645}
3646
3647function inputFieldToFieldConfig(field) {
3648 return {
3649 description: field.description,
3650 type: field.type,
3651 defaultValue: field.defaultValue,
3652 extensions: field.extensions,
3653 astNode: field.astNode,
3654 };
3655}
3656function fieldToFieldConfig(field) {
3657 return {
3658 description: field.description,
3659 type: field.type,
3660 args: argsToFieldConfigArgumentMap(field.args),
3661 resolve: field.resolve,
3662 subscribe: field.subscribe,
3663 deprecationReason: field.deprecationReason,
3664 extensions: field.extensions,
3665 astNode: field.astNode,
3666 };
3667}
3668function argsToFieldConfigArgumentMap(args) {
3669 const newArguments = {};
3670 args.forEach(arg => {
3671 newArguments[arg.name] = argumentToArgumentConfig(arg);
3672 });
3673 return newArguments;
3674}
3675function argumentToArgumentConfig(arg) {
3676 return {
3677 description: arg.description,
3678 type: arg.type,
3679 defaultValue: arg.defaultValue,
3680 extensions: arg.extensions,
3681 astNode: arg.astNode,
3682 };
3683}
3684
3685function observableToAsyncIterable(observable) {
3686 const pullQueue = [];
3687 const pushQueue = [];
3688 let listening = true;
3689 const pushValue = (value) => {
3690 if (pullQueue.length !== 0) {
3691 pullQueue.shift()({ value, done: false });
3692 }
3693 else {
3694 pushQueue.push({ value });
3695 }
3696 };
3697 const pushError = (error) => {
3698 if (pullQueue.length !== 0) {
3699 pullQueue.shift()({ value: { errors: [error] }, done: false });
3700 }
3701 else {
3702 pushQueue.push({ value: { errors: [error] } });
3703 }
3704 };
3705 const pullValue = () => new Promise(resolve => {
3706 if (pushQueue.length !== 0) {
3707 const element = pushQueue.shift();
3708 // either {value: {errors: [...]}} or {value: ...}
3709 resolve({
3710 ...element,
3711 done: false,
3712 });
3713 }
3714 else {
3715 pullQueue.push(resolve);
3716 }
3717 });
3718 const subscription = observable.subscribe({
3719 next(value) {
3720 pushValue(value);
3721 },
3722 error(err) {
3723 pushError(err);
3724 },
3725 });
3726 const emptyQueue = () => {
3727 if (listening) {
3728 listening = false;
3729 subscription.unsubscribe();
3730 pullQueue.forEach(resolve => resolve({ value: undefined, done: true }));
3731 pullQueue.length = 0;
3732 pushQueue.length = 0;
3733 }
3734 };
3735 return {
3736 next() {
3737 return listening ? pullValue() : this.return();
3738 },
3739 return() {
3740 emptyQueue();
3741 return Promise.resolve({ value: undefined, done: true });
3742 },
3743 throw(error) {
3744 emptyQueue();
3745 return Promise.reject(error);
3746 },
3747 [Symbol.asyncIterator]() {
3748 return this;
3749 },
3750 };
3751}
3752
3753function visitData(data, enter, leave) {
3754 if (Array.isArray(data)) {
3755 return data.map(value => visitData(value, enter, leave));
3756 }
3757 else if (typeof data === 'object') {
3758 const newData = enter != null ? enter(data) : data;
3759 if (newData != null) {
3760 Object.keys(newData).forEach(key => {
3761 const value = newData[key];
3762 newData[key] = visitData(value, enter, leave);
3763 });
3764 }
3765 return leave != null ? leave(newData) : newData;
3766 }
3767 return data;
3768}
3769function visitErrors(errors, visitor) {
3770 return errors.map(error => visitor(error));
3771}
3772function visitResult(result, request, schema, resultVisitorMap, errorVisitorMap) {
3773 const partialExecutionContext = {
3774 schema,
3775 fragments: request.document.definitions.reduce((acc, def) => {
3776 if (def.kind === graphql.Kind.FRAGMENT_DEFINITION) {
3777 acc[def.name.value] = def;
3778 }
3779 return acc;
3780 }, {}),
3781 variableValues: request.variables,
3782 };
3783 const errorInfo = {
3784 segmentInfoMap: new Map(),
3785 unpathedErrors: [],
3786 };
3787 const data = result.data;
3788 const errors = result.errors;
3789 const visitingErrors = errors != null && errorVisitorMap != null;
3790 if (data != null) {
3791 result.data = visitRoot(data, graphql.getOperationAST(request.document, undefined), partialExecutionContext, resultVisitorMap, visitingErrors ? errors : undefined, errorInfo);
3792 }
3793 if (visitingErrors) {
3794 result.errors = visitErrorsByType(errors, errorVisitorMap, errorInfo);
3795 }
3796 return result;
3797}
3798function visitErrorsByType(errors, errorVisitorMap, errorInfo) {
3799 return errors.map(error => {
3800 const pathSegmentsInfo = errorInfo.segmentInfoMap.get(error);
3801 if (pathSegmentsInfo == null) {
3802 return error;
3803 }
3804 return pathSegmentsInfo.reduceRight((acc, segmentInfo) => {
3805 const typeName = segmentInfo.type.name;
3806 const typeVisitorMap = errorVisitorMap[typeName];
3807 if (typeVisitorMap == null) {
3808 return acc;
3809 }
3810 const errorVisitor = typeVisitorMap[segmentInfo.fieldName];
3811 return errorVisitor == null ? acc : errorVisitor(acc, segmentInfo.pathIndex);
3812 }, error);
3813 });
3814}
3815function visitRoot(root, operation, exeContext, resultVisitorMap, errors, errorInfo) {
3816 const operationRootType = graphql.getOperationRootType(exeContext.schema, operation);
3817 const collectedFields = collectFields$1(exeContext, operationRootType, operation.selectionSet, Object.create(null), Object.create(null));
3818 return visitObjectValue(root, operationRootType, collectedFields, exeContext, resultVisitorMap, 0, errors, errorInfo);
3819}
3820function visitObjectValue(object, type, fieldNodeMap, exeContext, resultVisitorMap, pathIndex, errors, errorInfo) {
3821 const fieldMap = type.getFields();
3822 const typeVisitorMap = resultVisitorMap === null || resultVisitorMap === void 0 ? void 0 : resultVisitorMap[type.name];
3823 const enterObject = typeVisitorMap === null || typeVisitorMap === void 0 ? void 0 : typeVisitorMap.__enter;
3824 const newObject = enterObject != null ? enterObject(object) : object;
3825 let sortedErrors;
3826 let errorMap;
3827 if (errors != null) {
3828 sortedErrors = sortErrorsByPathSegment(errors, pathIndex);
3829 errorMap = sortedErrors.errorMap;
3830 errorInfo.unpathedErrors = errorInfo.unpathedErrors.concat(sortedErrors.unpathedErrors);
3831 }
3832 Object.keys(fieldNodeMap).forEach(responseKey => {
3833 const subFieldNodes = fieldNodeMap[responseKey];
3834 const fieldName = subFieldNodes[0].name.value;
3835 const fieldType = fieldMap[fieldName].type;
3836 const newPathIndex = pathIndex + 1;
3837 let fieldErrors;
3838 if (errors != null) {
3839 fieldErrors = errorMap[responseKey];
3840 if (fieldErrors != null) {
3841 delete errorMap[responseKey];
3842 }
3843 addPathSegmentInfo(type, fieldName, newPathIndex, fieldErrors, errorInfo);
3844 }
3845 const newValue = visitFieldValue(object[responseKey], fieldType, subFieldNodes, exeContext, resultVisitorMap, newPathIndex, fieldErrors, errorInfo);
3846 updateObject(newObject, responseKey, newValue, typeVisitorMap, fieldName);
3847 });
3848 const oldTypename = newObject.__typename;
3849 if (oldTypename != null) {
3850 updateObject(newObject, '__typename', oldTypename, typeVisitorMap, '__typename');
3851 }
3852 if (errors != null) {
3853 Object.keys(errorMap).forEach(unknownResponseKey => {
3854 errorInfo.unpathedErrors = errorInfo.unpathedErrors.concat(errorMap[unknownResponseKey]);
3855 });
3856 }
3857 const leaveObject = typeVisitorMap === null || typeVisitorMap === void 0 ? void 0 : typeVisitorMap.__leave;
3858 return leaveObject != null ? leaveObject(newObject) : newObject;
3859}
3860function updateObject(object, responseKey, newValue, typeVisitorMap, fieldName) {
3861 if (typeVisitorMap == null) {
3862 object[responseKey] = newValue;
3863 return;
3864 }
3865 const fieldVisitor = typeVisitorMap[fieldName];
3866 if (fieldVisitor == null) {
3867 object[responseKey] = newValue;
3868 return;
3869 }
3870 const visitedValue = fieldVisitor(newValue);
3871 if (visitedValue === undefined) {
3872 delete object[responseKey];
3873 return;
3874 }
3875 object[responseKey] = visitedValue;
3876}
3877function visitListValue(list, returnType, fieldNodes, exeContext, resultVisitorMap, pathIndex, errors, errorInfo) {
3878 return list.map(listMember => visitFieldValue(listMember, returnType, fieldNodes, exeContext, resultVisitorMap, pathIndex + 1, errors, errorInfo));
3879}
3880function visitFieldValue(value, returnType, fieldNodes, exeContext, resultVisitorMap, pathIndex, errors = [], errorInfo) {
3881 if (value == null) {
3882 return value;
3883 }
3884 const nullableType = graphql.getNullableType(returnType);
3885 if (graphql.isListType(nullableType)) {
3886 return visitListValue(value, nullableType.ofType, fieldNodes, exeContext, resultVisitorMap, pathIndex, errors, errorInfo);
3887 }
3888 else if (graphql.isAbstractType(nullableType)) {
3889 const finalType = exeContext.schema.getType(value.__typename);
3890 const collectedFields = collectSubFields(exeContext, finalType, fieldNodes);
3891 return visitObjectValue(value, finalType, collectedFields, exeContext, resultVisitorMap, pathIndex, errors, errorInfo);
3892 }
3893 else if (graphql.isObjectType(nullableType)) {
3894 const collectedFields = collectSubFields(exeContext, nullableType, fieldNodes);
3895 return visitObjectValue(value, nullableType, collectedFields, exeContext, resultVisitorMap, pathIndex, errors, errorInfo);
3896 }
3897 const typeVisitorMap = resultVisitorMap === null || resultVisitorMap === void 0 ? void 0 : resultVisitorMap[nullableType.name];
3898 if (typeVisitorMap == null) {
3899 return value;
3900 }
3901 const visitedValue = typeVisitorMap(value);
3902 return visitedValue === undefined ? value : visitedValue;
3903}
3904function sortErrorsByPathSegment(errors, pathIndex) {
3905 const errorMap = Object.create(null);
3906 const unpathedErrors = [];
3907 errors.forEach(error => {
3908 var _a;
3909 const pathSegment = (_a = error.path) === null || _a === void 0 ? void 0 : _a[pathIndex];
3910 if (pathSegment == null) {
3911 unpathedErrors.push(error);
3912 return;
3913 }
3914 if (pathSegment in errorMap) {
3915 errorMap[pathSegment].push(error);
3916 }
3917 else {
3918 errorMap[pathSegment] = [error];
3919 }
3920 });
3921 return {
3922 errorMap,
3923 unpathedErrors,
3924 };
3925}
3926function addPathSegmentInfo(type, fieldName, pathIndex, errors = [], errorInfo) {
3927 errors.forEach(error => {
3928 const segmentInfo = {
3929 type,
3930 fieldName,
3931 pathIndex,
3932 };
3933 const pathSegmentsInfo = errorInfo.segmentInfoMap.get(error);
3934 if (pathSegmentsInfo == null) {
3935 errorInfo.segmentInfoMap.set(error, [segmentInfo]);
3936 }
3937 else {
3938 pathSegmentsInfo.push(segmentInfo);
3939 }
3940 });
3941}
3942function collectSubFields(exeContext, type, fieldNodes) {
3943 let subFieldNodes = Object.create(null);
3944 const visitedFragmentNames = Object.create(null);
3945 fieldNodes.forEach(fieldNode => {
3946 subFieldNodes = collectFields$1(exeContext, type, fieldNode.selectionSet, subFieldNodes, visitedFragmentNames);
3947 });
3948 return subFieldNodes;
3949}
3950
3951exports.ERROR_SYMBOL = ERROR_SYMBOL;
3952exports.SchemaDirectiveVisitor = SchemaDirectiveVisitor;
3953exports.SchemaVisitor = SchemaVisitor;
3954exports.addTypes = addTypes;
3955exports.appendObjectFields = appendObjectFields;
3956exports.applyRequestTransforms = applyRequestTransforms;
3957exports.applyResultTransforms = applyResultTransforms;
3958exports.applySchemaTransforms = applySchemaTransforms;
3959exports.argsToFieldConfigArgumentMap = argsToFieldConfigArgumentMap;
3960exports.argumentToArgumentConfig = argumentToArgumentConfig;
3961exports.asArray = asArray;
3962exports.buildOperationNodeForField = buildOperationNodeForField;
3963exports.checkValidationErrors = checkValidationErrors;
3964exports.cloneDirective = cloneDirective;
3965exports.cloneSchema = cloneSchema;
3966exports.cloneType = cloneType;
3967exports.collectFields = collectFields$1;
3968exports.compareNodes = compareNodes;
3969exports.compareStrings = compareStrings;
3970exports.concatInlineFragments = concatInlineFragments;
3971exports.correctASTNodes = correctASTNodes;
3972exports.createNamedStub = createNamedStub;
3973exports.createSchemaDefinition = createSchemaDefinition;
3974exports.createStub = createStub;
3975exports.debugLog = debugLog;
3976exports.fieldToFieldConfig = fieldToFieldConfig;
3977exports.filterSchema = filterSchema;
3978exports.fixSchemaAst = fixSchemaAst;
3979exports.fixWindowsPath = fixWindowsPath;
3980exports.flattenArray = flattenArray;
3981exports.forEachDefaultValue = forEachDefaultValue;
3982exports.forEachField = forEachField;
3983exports.getBuiltInForStub = getBuiltInForStub;
3984exports.getDirectives = getDirectives;
3985exports.getErrors = getErrors;
3986exports.getErrorsByPathSegment = getErrorsByPathSegment;
3987exports.getFieldsWithDirectives = getFieldsWithDirectives;
3988exports.getImplementingTypes = getImplementingTypes;
3989exports.getResolversFromSchema = getResolversFromSchema;
3990exports.getResponseKeyFromInfo = getResponseKeyFromInfo;
3991exports.getUserTypesFromSchema = getUserTypesFromSchema;
3992exports.healSchema = healSchema;
3993exports.healTypes = healTypes;
3994exports.hoistFieldNodes = hoistFieldNodes;
3995exports.implementsAbstractType = implementsAbstractType;
3996exports.inputFieldToFieldConfig = inputFieldToFieldConfig;
3997exports.isDocumentString = isDocumentString;
3998exports.isEqual = isEqual;
3999exports.isNamedStub = isNamedStub;
4000exports.isNotEqual = isNotEqual;
4001exports.isValidPath = isValidPath;
4002exports.mapAsyncIterator = mapAsyncIterator;
4003exports.mapSchema = mapSchema;
4004exports.mergeDeep = mergeDeep;
4005exports.modifyObjectFields = modifyObjectFields;
4006exports.nodeToString = nodeToString;
4007exports.observableToAsyncIterable = observableToAsyncIterable;
4008exports.parseFragmentToInlineFragment = parseFragmentToInlineFragment;
4009exports.parseGraphQLJSON = parseGraphQLJSON;
4010exports.parseGraphQLSDL = parseGraphQLSDL;
4011exports.parseInputValue = parseInputValue;
4012exports.parseInputValueLiteral = parseInputValueLiteral;
4013exports.parseSelectionSet = parseSelectionSet;
4014exports.preAliasFieldNode = preAliasFieldNode;
4015exports.printSchemaWithDirectives = printSchemaWithDirectives;
4016exports.pruneSchema = pruneSchema;
4017exports.relocatedError = relocatedError;
4018exports.removeObjectFields = removeObjectFields;
4019exports.renameFieldNode = renameFieldNode;
4020exports.renameType = renameType;
4021exports.rewireTypes = rewireTypes;
4022exports.selectObjectFields = selectObjectFields;
4023exports.serializeInputValue = serializeInputValue;
4024exports.setErrors = setErrors;
4025exports.slicedError = slicedError;
4026exports.transformInputValue = transformInputValue;
4027exports.typeContainsSelectionSet = typeContainsSelectionSet;
4028exports.updateArgument = updateArgument;
4029exports.validateGraphQlDocuments = validateGraphQlDocuments;
4030exports.visitData = visitData;
4031exports.visitErrors = visitErrors;
4032exports.visitResult = visitResult;
4033exports.visitSchema = visitSchema;
4034exports.wrapFieldNode = wrapFieldNode;
4035//# sourceMappingURL=index.cjs.js.map