coerceInputValue.mjs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { forEach, isCollection } from 'iterall';
  2. import objectValues from '../polyfills/objectValues';
  3. import inspect from '../jsutils/inspect';
  4. import invariant from '../jsutils/invariant';
  5. import didYouMean from '../jsutils/didYouMean';
  6. import isObjectLike from '../jsutils/isObjectLike';
  7. import suggestionList from '../jsutils/suggestionList';
  8. import printPathArray from '../jsutils/printPathArray';
  9. import { addPath, pathToArray } from '../jsutils/Path';
  10. import { GraphQLError } from '../error/GraphQLError';
  11. import { isScalarType, isEnumType, isInputObjectType, isListType, isNonNullType } from '../type/definition';
  12. /**
  13. * Coerces a JavaScript value given a GraphQL Input Type.
  14. */
  15. export function coerceInputValue(inputValue, type) {
  16. var onError = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultOnError;
  17. return coerceInputValueImpl(inputValue, type, onError);
  18. }
  19. function defaultOnError(path, invalidValue, error) {
  20. var errorPrefix = 'Invalid value ' + inspect(invalidValue);
  21. if (path.length > 0) {
  22. errorPrefix += " at \"value".concat(printPathArray(path), "\": ");
  23. }
  24. error.message = errorPrefix + ': ' + error.message;
  25. throw error;
  26. }
  27. function coerceInputValueImpl(inputValue, type, onError, path) {
  28. if (isNonNullType(type)) {
  29. if (inputValue != null) {
  30. return coerceInputValueImpl(inputValue, type.ofType, onError, path);
  31. }
  32. onError(pathToArray(path), inputValue, new GraphQLError("Expected non-nullable type ".concat(inspect(type), " not to be null.")));
  33. return;
  34. }
  35. if (inputValue == null) {
  36. // Explicitly return the value null.
  37. return null;
  38. }
  39. if (isListType(type)) {
  40. var itemType = type.ofType;
  41. if (isCollection(inputValue)) {
  42. var coercedValue = [];
  43. forEach(inputValue, function (itemValue, index) {
  44. coercedValue.push(coerceInputValueImpl(itemValue, itemType, onError, addPath(path, index)));
  45. });
  46. return coercedValue;
  47. } // Lists accept a non-list value as a list of one.
  48. return [coerceInputValueImpl(inputValue, itemType, onError, path)];
  49. }
  50. if (isInputObjectType(type)) {
  51. if (!isObjectLike(inputValue)) {
  52. onError(pathToArray(path), inputValue, new GraphQLError("Expected type ".concat(type.name, " to be an object.")));
  53. return;
  54. }
  55. var _coercedValue = {};
  56. var fieldDefs = type.getFields();
  57. for (var _i2 = 0, _objectValues2 = objectValues(fieldDefs); _i2 < _objectValues2.length; _i2++) {
  58. var field = _objectValues2[_i2];
  59. var fieldValue = inputValue[field.name];
  60. if (fieldValue === undefined) {
  61. if (field.defaultValue !== undefined) {
  62. _coercedValue[field.name] = field.defaultValue;
  63. } else if (isNonNullType(field.type)) {
  64. var typeStr = inspect(field.type);
  65. onError(pathToArray(path), inputValue, new GraphQLError("Field ".concat(field.name, " of required type ").concat(typeStr, " was not provided.")));
  66. }
  67. continue;
  68. }
  69. _coercedValue[field.name] = coerceInputValueImpl(fieldValue, field.type, onError, addPath(path, field.name));
  70. } // Ensure every provided field is defined.
  71. for (var _i4 = 0, _Object$keys2 = Object.keys(inputValue); _i4 < _Object$keys2.length; _i4++) {
  72. var fieldName = _Object$keys2[_i4];
  73. if (!fieldDefs[fieldName]) {
  74. var suggestions = suggestionList(fieldName, Object.keys(type.getFields()));
  75. onError(pathToArray(path), inputValue, new GraphQLError("Field \"".concat(fieldName, "\" is not defined by type ").concat(type.name, ".") + didYouMean(suggestions)));
  76. }
  77. }
  78. return _coercedValue;
  79. }
  80. if (isScalarType(type)) {
  81. var parseResult; // Scalars determine if a input value is valid via parseValue(), which can
  82. // throw to indicate failure. If it throws, maintain a reference to
  83. // the original error.
  84. try {
  85. parseResult = type.parseValue(inputValue);
  86. } catch (error) {
  87. onError(pathToArray(path), inputValue, new GraphQLError("Expected type ".concat(type.name, ". ") + error.message, undefined, undefined, undefined, undefined, error));
  88. return;
  89. }
  90. if (parseResult === undefined) {
  91. onError(pathToArray(path), inputValue, new GraphQLError("Expected type ".concat(type.name, ".")));
  92. }
  93. return parseResult;
  94. }
  95. /* istanbul ignore else */
  96. if (isEnumType(type)) {
  97. if (typeof inputValue === 'string') {
  98. var enumValue = type.getValue(inputValue);
  99. if (enumValue) {
  100. return enumValue.value;
  101. }
  102. }
  103. var _suggestions = suggestionList(String(inputValue), type.getValues().map(function (enumValue) {
  104. return enumValue.name;
  105. }));
  106. onError(pathToArray(path), inputValue, new GraphQLError("Expected type ".concat(type.name, ".") + didYouMean(_suggestions)));
  107. return;
  108. } // Not reachable. All possible input types have been considered.
  109. /* istanbul ignore next */
  110. invariant(false, 'Unexpected input type: ' + inspect(type));
  111. }