UNPKG

7.02 kBJavaScriptView Raw
1import find from '../polyfills/find';
2import keyMap from '../jsutils/keyMap';
3import inspect from '../jsutils/inspect';
4import printPathArray from '../jsutils/printPathArray';
5import { GraphQLError } from '../error/GraphQLError';
6import { Kind } from '../language/kinds';
7import { print } from '../language/printer';
8import { isInputType, isNonNullType } from '../type/definition';
9import { typeFromAST } from '../utilities/typeFromAST';
10import { valueFromAST } from '../utilities/valueFromAST';
11import { coerceInputValue } from '../utilities/coerceInputValue';
12
13/**
14 * Prepares an object map of variableValues of the correct type based on the
15 * provided variable definitions and arbitrary input. If the input cannot be
16 * parsed to match the variable definitions, a GraphQLError will be thrown.
17 *
18 * Note: The returned value is a plain Object with a prototype, since it is
19 * exposed to user code. Care should be taken to not pull values from the
20 * Object prototype.
21 */
22export function getVariableValues(schema, varDefNodes, inputs, options) {
23 var maxErrors = options && options.maxErrors;
24 var errors = [];
25
26 try {
27 var coerced = coerceVariableValues(schema, varDefNodes, inputs, function (error) {
28 if (maxErrors != null && errors.length >= maxErrors) {
29 throw new GraphQLError('Too many errors processing variables, error limit reached. Execution aborted.');
30 }
31
32 errors.push(error);
33 });
34
35 if (errors.length === 0) {
36 return {
37 coerced: coerced
38 };
39 }
40 } catch (error) {
41 errors.push(error);
42 }
43
44 return {
45 errors: errors
46 };
47}
48
49function coerceVariableValues(schema, varDefNodes, inputs, onError) {
50 var coercedValues = {};
51
52 var _loop = function _loop(_i2) {
53 var varDefNode = varDefNodes[_i2];
54 var varName = varDefNode.variable.name.value;
55 var varType = typeFromAST(schema, varDefNode.type);
56
57 if (!isInputType(varType)) {
58 // Must use input types for variables. This should be caught during
59 // validation, however is checked again here for safety.
60 var varTypeStr = print(varDefNode.type);
61 onError(new GraphQLError("Variable \"$".concat(varName, "\" expected value of type \"").concat(varTypeStr, "\" which cannot be used as an input type."), varDefNode.type));
62 return "continue";
63 }
64
65 if (!hasOwnProperty(inputs, varName)) {
66 if (varDefNode.defaultValue) {
67 coercedValues[varName] = valueFromAST(varDefNode.defaultValue, varType);
68 }
69
70 if (isNonNullType(varType)) {
71 var _varTypeStr = inspect(varType);
72
73 onError(new GraphQLError("Variable \"$".concat(varName, "\" of required type \"").concat(_varTypeStr, "\" was not provided."), varDefNode));
74 }
75
76 return "continue";
77 }
78
79 var value = inputs[varName];
80
81 if (value === null && isNonNullType(varType)) {
82 var _varTypeStr2 = inspect(varType);
83
84 onError(new GraphQLError("Variable \"$".concat(varName, "\" of non-null type \"").concat(_varTypeStr2, "\" must not be null."), varDefNode));
85 return "continue";
86 }
87
88 coercedValues[varName] = coerceInputValue(value, varType, function (path, invalidValue, error) {
89 var prefix = "Variable \"$".concat(varName, "\" got invalid value ") + inspect(invalidValue);
90
91 if (path.length > 0) {
92 prefix += " at \"".concat(varName).concat(printPathArray(path), "\"");
93 }
94
95 onError(new GraphQLError(prefix + '; ' + error.message, varDefNode, undefined, undefined, undefined, error.originalError));
96 });
97 };
98
99 for (var _i2 = 0; _i2 < varDefNodes.length; _i2++) {
100 var _ret = _loop(_i2);
101
102 if (_ret === "continue") continue;
103 }
104
105 return coercedValues;
106}
107/**
108 * Prepares an object map of argument values given a list of argument
109 * definitions and list of argument AST nodes.
110 *
111 * Note: The returned value is a plain Object with a prototype, since it is
112 * exposed to user code. Care should be taken to not pull values from the
113 * Object prototype.
114 */
115
116
117export function getArgumentValues(def, node, variableValues) {
118 var coercedValues = {};
119 var argNodeMap = keyMap(node.arguments || [], function (arg) {
120 return arg.name.value;
121 });
122
123 for (var _i4 = 0, _def$args2 = def.args; _i4 < _def$args2.length; _i4++) {
124 var argDef = _def$args2[_i4];
125 var name = argDef.name;
126 var argType = argDef.type;
127 var argumentNode = argNodeMap[name];
128
129 if (!argumentNode) {
130 if (argDef.defaultValue !== undefined) {
131 coercedValues[name] = argDef.defaultValue;
132 } else if (isNonNullType(argType)) {
133 throw new GraphQLError("Argument \"".concat(name, "\" of required type \"").concat(inspect(argType), "\" ") + 'was not provided.', node);
134 }
135
136 continue;
137 }
138
139 var valueNode = argumentNode.value;
140 var isNull = valueNode.kind === Kind.NULL;
141
142 if (valueNode.kind === Kind.VARIABLE) {
143 var variableName = valueNode.name.value;
144
145 if (variableValues == null || !hasOwnProperty(variableValues, variableName)) {
146 if (argDef.defaultValue !== undefined) {
147 coercedValues[name] = argDef.defaultValue;
148 } else if (isNonNullType(argType)) {
149 throw new GraphQLError("Argument \"".concat(name, "\" of required type \"").concat(inspect(argType), "\" ") + "was provided the variable \"$".concat(variableName, "\" which was not provided a runtime value."), valueNode);
150 }
151
152 continue;
153 }
154
155 isNull = variableValues[variableName] == null;
156 }
157
158 if (isNull && isNonNullType(argType)) {
159 throw new GraphQLError("Argument \"".concat(name, "\" of non-null type \"").concat(inspect(argType), "\" ") + 'must not be null.', valueNode);
160 }
161
162 var coercedValue = valueFromAST(valueNode, argType, variableValues);
163
164 if (coercedValue === undefined) {
165 // Note: ValuesOfCorrectType validation should catch this before
166 // execution. This is a runtime check to ensure execution does not
167 // continue with an invalid argument value.
168 throw new GraphQLError("Argument \"".concat(name, "\" has invalid value ").concat(print(valueNode), "."), valueNode);
169 }
170
171 coercedValues[name] = coercedValue;
172 }
173
174 return coercedValues;
175}
176/**
177 * Prepares an object map of argument values given a directive definition
178 * and a AST node which may contain directives. Optionally also accepts a map
179 * of variable values.
180 *
181 * If the directive does not exist on the node, returns undefined.
182 *
183 * Note: The returned value is a plain Object with a prototype, since it is
184 * exposed to user code. Care should be taken to not pull values from the
185 * Object prototype.
186 */
187
188export function getDirectiveValues(directiveDef, node, variableValues) {
189 var directiveNode = node.directives && find(node.directives, function (directive) {
190 return directive.name.value === directiveDef.name;
191 });
192
193 if (directiveNode) {
194 return getArgumentValues(directiveDef, directiveNode, variableValues);
195 }
196}
197
198function hasOwnProperty(obj, prop) {
199 return Object.prototype.hasOwnProperty.call(obj, prop);
200}