1 | import { didYouMean } from '../jsutils/didYouMean.mjs';
|
2 | import { inspect } from '../jsutils/inspect.mjs';
|
3 | import { invariant } from '../jsutils/invariant.mjs';
|
4 | import { isIterableObject } from '../jsutils/isIterableObject.mjs';
|
5 | import { isObjectLike } from '../jsutils/isObjectLike.mjs';
|
6 | import { addPath, pathToArray } from '../jsutils/Path.mjs';
|
7 | import { printPathArray } from '../jsutils/printPathArray.mjs';
|
8 | import { suggestionList } from '../jsutils/suggestionList.mjs';
|
9 | import { GraphQLError } from '../error/GraphQLError.mjs';
|
10 | import {
|
11 | isInputObjectType,
|
12 | isLeafType,
|
13 | isListType,
|
14 | isNonNullType,
|
15 | } from '../type/definition.mjs';
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | export function coerceInputValue(inputValue, type, onError = defaultOnError) {
|
21 | return coerceInputValueImpl(inputValue, type, onError, undefined);
|
22 | }
|
23 |
|
24 | function defaultOnError(path, invalidValue, error) {
|
25 | let errorPrefix = 'Invalid value ' + inspect(invalidValue);
|
26 |
|
27 | if (path.length > 0) {
|
28 | errorPrefix += ` at "value${printPathArray(path)}"`;
|
29 | }
|
30 |
|
31 | error.message = errorPrefix + ': ' + error.message;
|
32 | throw error;
|
33 | }
|
34 |
|
35 | function coerceInputValueImpl(inputValue, type, onError, path) {
|
36 | if (isNonNullType(type)) {
|
37 | if (inputValue != null) {
|
38 | return coerceInputValueImpl(inputValue, type.ofType, onError, path);
|
39 | }
|
40 |
|
41 | onError(
|
42 | pathToArray(path),
|
43 | inputValue,
|
44 | new GraphQLError(
|
45 | `Expected non-nullable type "${inspect(type)}" not to be null.`,
|
46 | ),
|
47 | );
|
48 | return;
|
49 | }
|
50 |
|
51 | if (inputValue == null) {
|
52 |
|
53 | return null;
|
54 | }
|
55 |
|
56 | if (isListType(type)) {
|
57 | const itemType = type.ofType;
|
58 |
|
59 | if (isIterableObject(inputValue)) {
|
60 | return Array.from(inputValue, (itemValue, index) => {
|
61 | const itemPath = addPath(path, index, undefined);
|
62 | return coerceInputValueImpl(itemValue, itemType, onError, itemPath);
|
63 | });
|
64 | }
|
65 |
|
66 | return [coerceInputValueImpl(inputValue, itemType, onError, path)];
|
67 | }
|
68 |
|
69 | if (isInputObjectType(type)) {
|
70 | if (!isObjectLike(inputValue)) {
|
71 | onError(
|
72 | pathToArray(path),
|
73 | inputValue,
|
74 | new GraphQLError(`Expected type "${type.name}" to be an object.`),
|
75 | );
|
76 | return;
|
77 | }
|
78 |
|
79 | const coercedValue = {};
|
80 | const fieldDefs = type.getFields();
|
81 |
|
82 | for (const field of Object.values(fieldDefs)) {
|
83 | const fieldValue = inputValue[field.name];
|
84 |
|
85 | if (fieldValue === undefined) {
|
86 | if (field.defaultValue !== undefined) {
|
87 | coercedValue[field.name] = field.defaultValue;
|
88 | } else if (isNonNullType(field.type)) {
|
89 | const typeStr = inspect(field.type);
|
90 | onError(
|
91 | pathToArray(path),
|
92 | inputValue,
|
93 | new GraphQLError(
|
94 | `Field "${field.name}" of required type "${typeStr}" was not provided.`,
|
95 | ),
|
96 | );
|
97 | }
|
98 |
|
99 | continue;
|
100 | }
|
101 |
|
102 | coercedValue[field.name] = coerceInputValueImpl(
|
103 | fieldValue,
|
104 | field.type,
|
105 | onError,
|
106 | addPath(path, field.name, type.name),
|
107 | );
|
108 | }
|
109 |
|
110 | for (const fieldName of Object.keys(inputValue)) {
|
111 | if (!fieldDefs[fieldName]) {
|
112 | const suggestions = suggestionList(
|
113 | fieldName,
|
114 | Object.keys(type.getFields()),
|
115 | );
|
116 | onError(
|
117 | pathToArray(path),
|
118 | inputValue,
|
119 | new GraphQLError(
|
120 | `Field "${fieldName}" is not defined by type "${type.name}".` +
|
121 | didYouMean(suggestions),
|
122 | ),
|
123 | );
|
124 | }
|
125 | }
|
126 |
|
127 | return coercedValue;
|
128 | }
|
129 |
|
130 | if (isLeafType(type)) {
|
131 | let parseResult;
|
132 |
|
133 |
|
134 |
|
135 | try {
|
136 | parseResult = type.parseValue(inputValue);
|
137 | } catch (error) {
|
138 | if (error instanceof GraphQLError) {
|
139 | onError(pathToArray(path), inputValue, error);
|
140 | } else {
|
141 | onError(
|
142 | pathToArray(path),
|
143 | inputValue,
|
144 | new GraphQLError(`Expected type "${type.name}". ` + error.message, {
|
145 | originalError: error,
|
146 | }),
|
147 | );
|
148 | }
|
149 |
|
150 | return;
|
151 | }
|
152 |
|
153 | if (parseResult === undefined) {
|
154 | onError(
|
155 | pathToArray(path),
|
156 | inputValue,
|
157 | new GraphQLError(`Expected type "${type.name}".`),
|
158 | );
|
159 | }
|
160 |
|
161 | return parseResult;
|
162 | }
|
163 |
|
164 |
|
165 |
|
166 | false || invariant(false, 'Unexpected input type: ' + inspect(type));
|
167 | }
|