UNPKG

@graphql-tools/graphql

Version:
175 lines (174 loc) 8.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getDirectiveValues = exports.getArgumentValues = exports.getVariableValues = void 0; const inspect_js_1 = require("../jsutils/inspect.js"); const keyMap_js_1 = require("../jsutils/keyMap.js"); const printPathArray_js_1 = require("../jsutils/printPathArray.js"); const GraphQLError_js_1 = require("../error/GraphQLError.js"); const kinds_js_1 = require("../language/kinds.js"); const printer_js_1 = require("../language/printer.js"); const definition_js_1 = require("../type/definition.js"); const coerceInputValue_js_1 = require("../utilities/coerceInputValue.js"); const typeFromAST_js_1 = require("../utilities/typeFromAST.js"); const valueFromAST_js_1 = require("../utilities/valueFromAST.js"); /** * Prepares an object map of variableValues of the correct type based on the * provided variable definitions and arbitrary input. If the input cannot be * parsed to match the variable definitions, a GraphQLError will be thrown. * * Note: The returned value is a plain Object with a prototype, since it is * exposed to user code. Care should be taken to not pull values from the * Object prototype. */ function getVariableValues(schema, varDefNodes, inputs, options) { const errors = []; const maxErrors = options === null || options === void 0 ? void 0 : options.maxErrors; try { const coerced = coerceVariableValues(schema, varDefNodes, inputs, error => { if (maxErrors != null && errors.length >= maxErrors) { throw new GraphQLError_js_1.GraphQLError('Too many errors processing variables, error limit reached. Execution aborted.'); } errors.push(error); }); if (errors.length === 0) { return { coerced }; } } catch (error) { errors.push(error); } // @ts-expect-error return { errors }; } exports.getVariableValues = getVariableValues; function coerceVariableValues(schema, varDefNodes, inputs, onError) { const coercedValues = {}; for (const varDefNode of varDefNodes) { const varName = varDefNode.variable.name.value; const varType = (0, typeFromAST_js_1.typeFromAST)(schema, varDefNode.type); if (!(0, definition_js_1.isInputType)(varType)) { // Must use input types for variables. This should be caught during // validation, however is checked again here for safety. const varTypeStr = (0, printer_js_1.print)(varDefNode.type); onError(new GraphQLError_js_1.GraphQLError(`Variable "$${varName}" expected value of type "${varTypeStr}" which cannot be used as an input type.`, { nodes: varDefNode.type })); continue; } if (!hasOwnProperty(inputs, varName)) { if (varDefNode.defaultValue) { coercedValues[varName] = (0, valueFromAST_js_1.valueFromAST)(varDefNode.defaultValue, varType); } else if ((0, definition_js_1.isNonNullType)(varType)) { const varTypeStr = (0, inspect_js_1.inspect)(varType); onError(new GraphQLError_js_1.GraphQLError(`Variable "$${varName}" of required type "${varTypeStr}" was not provided.`, { nodes: varDefNode, })); } continue; } const value = inputs[varName]; if (value === null && (0, definition_js_1.isNonNullType)(varType)) { const varTypeStr = (0, inspect_js_1.inspect)(varType); onError(new GraphQLError_js_1.GraphQLError(`Variable "$${varName}" of non-null type "${varTypeStr}" must not be null.`, { nodes: varDefNode, })); continue; } coercedValues[varName] = (0, coerceInputValue_js_1.coerceInputValue)(value, varType, (path, invalidValue, error) => { let prefix = `Variable "$${varName}" got invalid value ` + (0, inspect_js_1.inspect)(invalidValue); if (path.length > 0) { prefix += ` at "${varName}${(0, printPathArray_js_1.printPathArray)(path)}"`; } onError(new GraphQLError_js_1.GraphQLError(prefix + '; ' + error.message, { nodes: varDefNode, originalError: error.originalError, })); }); } return coercedValues; } /** * Prepares an object map of argument values given a list of argument * definitions and list of argument AST nodes. * * Note: The returned value is a plain Object with a prototype, since it is * exposed to user code. Care should be taken to not pull values from the * Object prototype. */ function getArgumentValues(def, node, variableValues) { var _a; const coercedValues = {}; // FIXME: https://github.com/graphql/graphql-js/issues/2203 /* c8 ignore next */ const argumentNodes = (_a = node.arguments) !== null && _a !== void 0 ? _a : []; const argNodeMap = (0, keyMap_js_1.keyMap)(argumentNodes, arg => arg.name.value); for (const argDef of def.args) { const name = argDef.name; const argType = argDef.type; const argumentNode = argNodeMap[name]; if (!argumentNode) { if (argDef.defaultValue !== undefined) { coercedValues[name] = argDef.defaultValue; } else if ((0, definition_js_1.isNonNullType)(argType)) { throw new GraphQLError_js_1.GraphQLError(`Argument "${name}" of required type "${(0, inspect_js_1.inspect)(argType)}" ` + 'was not provided.', { nodes: node, }); } continue; } const valueNode = argumentNode.value; let isNull = valueNode.kind === kinds_js_1.Kind.NULL; if (valueNode.kind === kinds_js_1.Kind.VARIABLE) { const variableName = valueNode.name.value; if (variableValues == null || !hasOwnProperty(variableValues, variableName)) { if (argDef.defaultValue !== undefined) { coercedValues[name] = argDef.defaultValue; } else if ((0, definition_js_1.isNonNullType)(argType)) { throw new GraphQLError_js_1.GraphQLError(`Argument "${name}" of required type "${(0, inspect_js_1.inspect)(argType)}" ` + `was provided the variable "$${variableName}" which was not provided a runtime value.`, { nodes: valueNode }); } continue; } isNull = variableValues[variableName] == null; } if (isNull && (0, definition_js_1.isNonNullType)(argType)) { throw new GraphQLError_js_1.GraphQLError(`Argument "${name}" of non-null type "${(0, inspect_js_1.inspect)(argType)}" ` + 'must not be null.', { nodes: valueNode, }); } const coercedValue = (0, valueFromAST_js_1.valueFromAST)(valueNode, argType, variableValues); if (coercedValue === undefined) { // Note: ValuesOfCorrectTypeRule validation should catch this before // execution. This is a runtime check to ensure execution does not // continue with an invalid argument value. throw new GraphQLError_js_1.GraphQLError(`Argument "${name}" has invalid value ${(0, printer_js_1.print)(valueNode)}.`, { nodes: valueNode }); } coercedValues[name] = coercedValue; } return coercedValues; } exports.getArgumentValues = getArgumentValues; /** * Prepares an object map of argument values given a directive definition * and a AST node which may contain directives. Optionally also accepts a map * of variable values. * * If the directive does not exist on the node, returns undefined. * * Note: The returned value is a plain Object with a prototype, since it is * exposed to user code. Care should be taken to not pull values from the * Object prototype. */ function getDirectiveValues(directiveDef, node, variableValues) { var _a; const directiveNode = (_a = node.directives) === null || _a === void 0 ? void 0 : _a.find(directive => directive.name.value === directiveDef.name); if (directiveNode) { return getArgumentValues(directiveDef, directiveNode, variableValues); } return undefined; } exports.getDirectiveValues = getDirectiveValues; function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }