Mirror: The spec-compliant minimum of client-side GraphQL.
1import type { TypeNode, ValueNode } from './ast';
2import type { Maybe } from './types';
3
4export function valueFromASTUntyped(
5 node: ValueNode,
6 variables?: Maybe<Record<string, any>>
7): unknown {
8 switch (node.kind) {
9 case 'NullValue':
10 return null;
11 case 'IntValue':
12 return parseInt(node.value, 10);
13 case 'FloatValue':
14 return parseFloat(node.value);
15 case 'StringValue':
16 case 'EnumValue':
17 case 'BooleanValue':
18 return node.value;
19 case 'ListValue': {
20 const values: unknown[] = [];
21 for (let i = 0, l = node.values.length; i < l; i++)
22 values.push(valueFromASTUntyped(node.values[i], variables));
23 return values;
24 }
25 case 'ObjectValue': {
26 const obj = Object.create(null);
27 for (let i = 0, l = node.fields.length; i < l; i++) {
28 const field = node.fields[i];
29 obj[field.name.value] = valueFromASTUntyped(field.value, variables);
30 }
31 return obj;
32 }
33 case 'Variable':
34 return variables && variables[node.name.value];
35 }
36}
37
38export function valueFromTypeNode(
39 node: ValueNode,
40 type: TypeNode,
41 variables?: Maybe<Record<string, any>>
42): unknown {
43 if (node.kind === 'Variable') {
44 const variableName = node.name.value;
45 return variables ? valueFromTypeNode(variables[variableName], type, variables) : undefined;
46 } else if (type.kind === 'NonNullType') {
47 return node.kind !== 'NullValue' ? valueFromTypeNode(node, type, variables) : undefined;
48 } else if (node.kind === 'NullValue') {
49 return null;
50 } else if (type.kind === 'ListType') {
51 if (node.kind === 'ListValue') {
52 const values: unknown[] = [];
53 for (let i = 0, l = node.values.length; i < l; i++) {
54 const value = node.values[i];
55 const coerced = valueFromTypeNode(value, type.type, variables);
56 if (coerced === undefined) {
57 return undefined;
58 } else {
59 values.push(coerced);
60 }
61 }
62 return values;
63 }
64 } else if (type.kind === 'NamedType') {
65 switch (type.name.value) {
66 case 'Int':
67 case 'Float':
68 case 'String':
69 case 'Bool':
70 return type.name.value + 'Value' === node.kind
71 ? valueFromASTUntyped(node, variables)
72 : undefined;
73 default:
74 return valueFromASTUntyped(node, variables);
75 }
76 }
77}