UNPKG

7.37 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.coerceValue = coerceValue;
7
8var _iterall = require("iterall");
9
10var _objectValues = _interopRequireDefault(require("../polyfills/objectValues"));
11
12var _inspect = _interopRequireDefault(require("../jsutils/inspect"));
13
14var _isInvalid = _interopRequireDefault(require("../jsutils/isInvalid"));
15
16var _orList = _interopRequireDefault(require("../jsutils/orList"));
17
18var _suggestionList = _interopRequireDefault(require("../jsutils/suggestionList"));
19
20var _GraphQLError = require("../error/GraphQLError");
21
22var _definition = require("../type/definition");
23
24function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
26function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
27
28/**
29 * Coerces a JavaScript value given a GraphQL Type.
30 *
31 * Returns either a value which is valid for the provided type or a list of
32 * encountered coercion errors.
33 *
34 */
35function coerceValue(value, type, blameNode, path) {
36 // A value must be provided if the type is non-null.
37 if ((0, _definition.isNonNullType)(type)) {
38 if (value == null) {
39 return ofErrors([coercionError("Expected non-nullable type ".concat((0, _inspect.default)(type), " not to be null"), blameNode, path)]);
40 }
41
42 return coerceValue(value, type.ofType, blameNode, path);
43 }
44
45 if (value == null) {
46 // Explicitly return the value null.
47 return ofValue(null);
48 }
49
50 if ((0, _definition.isScalarType)(type)) {
51 // Scalars determine if a value is valid via parseValue(), which can
52 // throw to indicate failure. If it throws, maintain a reference to
53 // the original error.
54 try {
55 var parseResult = type.parseValue(value);
56
57 if ((0, _isInvalid.default)(parseResult)) {
58 return ofErrors([coercionError("Expected type ".concat(type.name), blameNode, path)]);
59 }
60
61 return ofValue(parseResult);
62 } catch (error) {
63 return ofErrors([coercionError("Expected type ".concat(type.name), blameNode, path, error.message, error)]);
64 }
65 }
66
67 if ((0, _definition.isEnumType)(type)) {
68 if (typeof value === 'string') {
69 var enumValue = type.getValue(value);
70
71 if (enumValue) {
72 return ofValue(enumValue.value);
73 }
74 }
75
76 var suggestions = (0, _suggestionList.default)(String(value), type.getValues().map(function (enumValue) {
77 return enumValue.name;
78 }));
79 var didYouMean = suggestions.length !== 0 ? "did you mean ".concat((0, _orList.default)(suggestions), "?") : undefined;
80 return ofErrors([coercionError("Expected type ".concat(type.name), blameNode, path, didYouMean)]);
81 }
82
83 if ((0, _definition.isListType)(type)) {
84 var itemType = type.ofType;
85
86 if ((0, _iterall.isCollection)(value)) {
87 var errors;
88 var coercedValue = [];
89 (0, _iterall.forEach)(value, function (itemValue, index) {
90 var coercedItem = coerceValue(itemValue, itemType, blameNode, atPath(path, index));
91
92 if (coercedItem.errors) {
93 errors = add(errors, coercedItem.errors);
94 } else if (!errors) {
95 coercedValue.push(coercedItem.value);
96 }
97 });
98 return errors ? ofErrors(errors) : ofValue(coercedValue);
99 } // Lists accept a non-list value as a list of one.
100
101
102 var coercedItem = coerceValue(value, itemType, blameNode);
103 return coercedItem.errors ? coercedItem : ofValue([coercedItem.value]);
104 }
105
106 if ((0, _definition.isInputObjectType)(type)) {
107 if (_typeof(value) !== 'object') {
108 return ofErrors([coercionError("Expected type ".concat(type.name, " to be an object"), blameNode, path)]);
109 }
110
111 var _errors;
112
113 var _coercedValue = {};
114 var fields = type.getFields(); // Ensure every defined field is valid.
115
116 var _iteratorNormalCompletion = true;
117 var _didIteratorError = false;
118 var _iteratorError = undefined;
119
120 try {
121 for (var _iterator = (0, _objectValues.default)(fields)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
122 var field = _step.value;
123 var fieldValue = value[field.name];
124
125 if ((0, _isInvalid.default)(fieldValue)) {
126 if (!(0, _isInvalid.default)(field.defaultValue)) {
127 _coercedValue[field.name] = field.defaultValue;
128 } else if ((0, _definition.isNonNullType)(field.type)) {
129 _errors = add(_errors, coercionError("Field ".concat(printPath(atPath(path, field.name)), " of required ") + "type ".concat((0, _inspect.default)(field.type), " was not provided"), blameNode));
130 }
131 } else {
132 var coercedField = coerceValue(fieldValue, field.type, blameNode, atPath(path, field.name));
133
134 if (coercedField.errors) {
135 _errors = add(_errors, coercedField.errors);
136 } else if (!_errors) {
137 _coercedValue[field.name] = coercedField.value;
138 }
139 }
140 } // Ensure every provided field is defined.
141
142 } catch (err) {
143 _didIteratorError = true;
144 _iteratorError = err;
145 } finally {
146 try {
147 if (!_iteratorNormalCompletion && _iterator.return != null) {
148 _iterator.return();
149 }
150 } finally {
151 if (_didIteratorError) {
152 throw _iteratorError;
153 }
154 }
155 }
156
157 var _arr = Object.keys(value);
158
159 for (var _i = 0; _i < _arr.length; _i++) {
160 var fieldName = _arr[_i];
161
162 if (!fields[fieldName]) {
163 var _suggestions = (0, _suggestionList.default)(fieldName, Object.keys(fields));
164
165 var _didYouMean = _suggestions.length !== 0 ? "did you mean ".concat((0, _orList.default)(_suggestions), "?") : undefined;
166
167 _errors = add(_errors, coercionError("Field \"".concat(fieldName, "\" is not defined by type ").concat(type.name), blameNode, path, _didYouMean));
168 }
169 }
170
171 return _errors ? ofErrors(_errors) : ofValue(_coercedValue);
172 }
173 /* istanbul ignore next */
174
175
176 throw new Error("Unexpected type: ".concat(type, "."));
177}
178
179function ofValue(value) {
180 return {
181 errors: undefined,
182 value: value
183 };
184}
185
186function ofErrors(errors) {
187 return {
188 errors: errors,
189 value: undefined
190 };
191}
192
193function add(errors, moreErrors) {
194 return (errors || []).concat(moreErrors);
195}
196
197function atPath(prev, key) {
198 return {
199 prev: prev,
200 key: key
201 };
202}
203
204function coercionError(message, blameNode, path, subMessage, originalError) {
205 var pathStr = printPath(path); // Return a GraphQLError instance
206
207 return new _GraphQLError.GraphQLError(message + (pathStr ? ' at ' + pathStr : '') + (subMessage ? '; ' + subMessage : '.'), blameNode, undefined, undefined, undefined, originalError);
208} // Build a string describing the path into the value where the error was found
209
210
211function printPath(path) {
212 var pathStr = '';
213 var currentPath = path;
214
215 while (currentPath) {
216 pathStr = (typeof currentPath.key === 'string' ? '.' + currentPath.key : '[' + String(currentPath.key) + ']') + pathStr;
217 currentPath = currentPath.prev;
218 }
219
220 return pathStr ? 'value' + pathStr : '';
221}
\No newline at end of file