UNPKG

5.38 kBJavaScriptView Raw
1import objectValues from "../polyfills/objectValues.mjs";
2import keyMap from "../jsutils/keyMap.mjs";
3import inspect from "../jsutils/inspect.mjs";
4import invariant from "../jsutils/invariant.mjs";
5import { Kind } from "../language/kinds.mjs";
6import { isLeafType, isInputObjectType, isListType, isNonNullType } from "../type/definition.mjs";
7/**
8 * Produces a JavaScript value given a GraphQL Value AST.
9 *
10 * A GraphQL type must be provided, which will be used to interpret different
11 * GraphQL Value literals.
12 *
13 * Returns `undefined` when the value could not be validly coerced according to
14 * the provided type.
15 *
16 * | GraphQL Value | JSON Value |
17 * | -------------------- | ------------- |
18 * | Input Object | Object |
19 * | List | Array |
20 * | Boolean | Boolean |
21 * | String | String |
22 * | Int / Float | Number |
23 * | Enum Value | Mixed |
24 * | NullValue | null |
25 *
26 */
27
28export function valueFromAST(valueNode, type, variables) {
29 if (!valueNode) {
30 // When there is no node, then there is also no value.
31 // Importantly, this is different from returning the value null.
32 return;
33 }
34
35 if (valueNode.kind === Kind.VARIABLE) {
36 var variableName = valueNode.name.value;
37
38 if (variables == null || variables[variableName] === undefined) {
39 // No valid return value.
40 return;
41 }
42
43 var variableValue = variables[variableName];
44
45 if (variableValue === null && isNonNullType(type)) {
46 return; // Invalid: intentionally return no value.
47 } // Note: This does no further checking that this variable is correct.
48 // This assumes that this query has been validated and the variable
49 // usage here is of the correct type.
50
51
52 return variableValue;
53 }
54
55 if (isNonNullType(type)) {
56 if (valueNode.kind === Kind.NULL) {
57 return; // Invalid: intentionally return no value.
58 }
59
60 return valueFromAST(valueNode, type.ofType, variables);
61 }
62
63 if (valueNode.kind === Kind.NULL) {
64 // This is explicitly returning the value null.
65 return null;
66 }
67
68 if (isListType(type)) {
69 var itemType = type.ofType;
70
71 if (valueNode.kind === Kind.LIST) {
72 var coercedValues = [];
73
74 for (var _i2 = 0, _valueNode$values2 = valueNode.values; _i2 < _valueNode$values2.length; _i2++) {
75 var itemNode = _valueNode$values2[_i2];
76
77 if (isMissingVariable(itemNode, variables)) {
78 // If an array contains a missing variable, it is either coerced to
79 // null or if the item type is non-null, it considered invalid.
80 if (isNonNullType(itemType)) {
81 return; // Invalid: intentionally return no value.
82 }
83
84 coercedValues.push(null);
85 } else {
86 var itemValue = valueFromAST(itemNode, itemType, variables);
87
88 if (itemValue === undefined) {
89 return; // Invalid: intentionally return no value.
90 }
91
92 coercedValues.push(itemValue);
93 }
94 }
95
96 return coercedValues;
97 }
98
99 var coercedValue = valueFromAST(valueNode, itemType, variables);
100
101 if (coercedValue === undefined) {
102 return; // Invalid: intentionally return no value.
103 }
104
105 return [coercedValue];
106 }
107
108 if (isInputObjectType(type)) {
109 if (valueNode.kind !== Kind.OBJECT) {
110 return; // Invalid: intentionally return no value.
111 }
112
113 var coercedObj = Object.create(null);
114 var fieldNodes = keyMap(valueNode.fields, function (field) {
115 return field.name.value;
116 });
117
118 for (var _i4 = 0, _objectValues2 = objectValues(type.getFields()); _i4 < _objectValues2.length; _i4++) {
119 var field = _objectValues2[_i4];
120 var fieldNode = fieldNodes[field.name];
121
122 if (!fieldNode || isMissingVariable(fieldNode.value, variables)) {
123 if (field.defaultValue !== undefined) {
124 coercedObj[field.name] = field.defaultValue;
125 } else if (isNonNullType(field.type)) {
126 return; // Invalid: intentionally return no value.
127 }
128
129 continue;
130 }
131
132 var fieldValue = valueFromAST(fieldNode.value, field.type, variables);
133
134 if (fieldValue === undefined) {
135 return; // Invalid: intentionally return no value.
136 }
137
138 coercedObj[field.name] = fieldValue;
139 }
140
141 return coercedObj;
142 } // istanbul ignore else (See: 'https://github.com/graphql/graphql-js/issues/2618')
143
144
145 if (isLeafType(type)) {
146 // Scalars and Enums fulfill parsing a literal value via parseLiteral().
147 // Invalid values represent a failure to parse correctly, in which case
148 // no value is returned.
149 var result;
150
151 try {
152 result = type.parseLiteral(valueNode, variables);
153 } catch (_error) {
154 return; // Invalid: intentionally return no value.
155 }
156
157 if (result === undefined) {
158 return; // Invalid: intentionally return no value.
159 }
160
161 return result;
162 } // istanbul ignore next (Not reachable. All possible input types have been considered)
163
164
165 false || invariant(0, 'Unexpected input type: ' + inspect(type));
166} // Returns true if the provided valueNode is a variable which is not defined
167// in the set of variables.
168
169function isMissingVariable(valueNode, variables) {
170 return valueNode.kind === Kind.VARIABLE && (variables == null || variables[valueNode.name.value] === undefined);
171}