UNPKG

graphql

Version:

A Query Language and Runtime which can target any service.

270 lines 13.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateInputValue = validateInputValue; exports.validateInputLiteral = validateInputLiteral; const didYouMean_ts_1 = require("../jsutils/didYouMean.js"); const inspect_ts_1 = require("../jsutils/inspect.js"); const isIterableObject_ts_1 = require("../jsutils/isIterableObject.js"); const isObjectLike_ts_1 = require("../jsutils/isObjectLike.js"); const keyMap_ts_1 = require("../jsutils/keyMap.js"); const Path_ts_1 = require("../jsutils/Path.js"); const suggestionList_ts_1 = require("../jsutils/suggestionList.js"); const ensureGraphQLError_ts_1 = require("../error/ensureGraphQLError.js"); const GraphQLError_ts_1 = require("../error/GraphQLError.js"); const kinds_ts_1 = require("../language/kinds.js"); const printer_ts_1 = require("../language/printer.js"); const definition_ts_1 = require("../type/definition.js"); const replaceVariables_ts_1 = require("./replaceVariables.js"); function validateInputValue(inputValue, type, onError, hideSuggestions) { return validateInputValueImpl(inputValue, type, onError, hideSuggestions, undefined); } function validateInputValueImpl(inputValue, type, onError, hideSuggestions, path) { if ((0, definition_ts_1.isNonNullType)(type)) { if (inputValue === undefined) { reportInvalidValue(onError, `Expected a value of non-null type "${type}" to be provided.`, path); return; } if (inputValue === null) { reportInvalidValue(onError, `Expected value of non-null type "${type}" not to be null.`, path); return; } return validateInputValueImpl(inputValue, type.ofType, onError, hideSuggestions, path); } if (inputValue == null) { return; } if ((0, definition_ts_1.isListType)(type)) { if (!(0, isIterableObject_ts_1.isIterableObject)(inputValue)) { validateInputValueImpl(inputValue, type.ofType, onError, hideSuggestions, path); } else { let index = 0; for (const itemValue of inputValue) { validateInputValueImpl(itemValue, type.ofType, onError, hideSuggestions, (0, Path_ts_1.addPath)(path, index++, undefined)); } } } else if ((0, definition_ts_1.isInputObjectType)(type)) { if (!(0, isObjectLike_ts_1.isObjectLike)(inputValue) || Array.isArray(inputValue)) { reportInvalidValue(onError, `Expected value of type "${type}" to be an object, found: ${(0, inspect_ts_1.inspect)(inputValue)}.`, path); return; } const fieldDefs = type.getFields(); for (const field of Object.values(fieldDefs)) { const fieldValue = inputValue[field.name]; if (fieldValue === undefined) { if ((0, definition_ts_1.isRequiredInputField)(field)) { reportInvalidValue(onError, `Expected value of type "${type}" to include required field "${field.name}", found: ${(0, inspect_ts_1.inspect)(inputValue)}.`, path); } } else { validateInputValueImpl(fieldValue, field.type, onError, hideSuggestions, (0, Path_ts_1.addPath)(path, field.name, type.name)); } } const fields = []; for (const fieldName of Object.keys(inputValue)) { if (inputValue[fieldName] === undefined) { continue; } if (!Object.hasOwn(fieldDefs, fieldName)) { const suggestion = hideSuggestions ? '' : (0, didYouMean_ts_1.didYouMean)((0, suggestionList_ts_1.suggestionList)(fieldName, Object.keys(fieldDefs))); reportInvalidValue(onError, `Expected value of type "${type}" not to include unknown field "${fieldName}"${suggestion ? `.${suggestion} Found` : ', found'}: ${(0, inspect_ts_1.inspect)(inputValue)}.`, path); continue; } fields.push(fieldName); } if (type.isOneOf) { if (fields.length !== 1) { reportInvalidValue(onError, getOneOfInputObjectErrorMessage(type), path); } const field = fields[0]; const value = inputValue[field]; if (value === null) { reportInvalidValue(onError, getOneOfInputObjectErrorMessage(type), (0, Path_ts_1.addPath)(path, field, type.name)); } } } else { (0, definition_ts_1.assertLeafType)(type); let result; let caughtError; try { result = type.coerceInputValue(inputValue, hideSuggestions); } catch (error) { if (error instanceof GraphQLError_ts_1.GraphQLError) { onError(error, (0, Path_ts_1.pathToArray)(path)); return; } caughtError = error; } if (result === undefined) { reportInvalidValue(onError, `Expected value of type "${type}"${caughtError != null ? `, but encountered error "${getCaughtErrorMessage(caughtError)}"; found` : ', found'}: ${(0, inspect_ts_1.inspect)(inputValue)}.`, path, (0, ensureGraphQLError_ts_1.ensureGraphQLError)(caughtError)); } } } function reportInvalidValue(onError, message, path, originalError) { onError(new GraphQLError_ts_1.GraphQLError(message, { originalError }), (0, Path_ts_1.pathToArray)(path)); } function validateInputLiteral(valueNode, type, onError, variables, fragmentVariableValues, hideSuggestions) { const context = { static: !variables && !fragmentVariableValues, onError, variables, fragmentVariableValues, }; return validateInputLiteralImpl(context, valueNode, type, hideSuggestions, undefined); } function validateInputLiteralImpl(context, valueNode, type, hideSuggestions, path) { if (valueNode.kind === kinds_ts_1.Kind.VARIABLE) { if (context.static) { return; } const scopedVariableValues = getScopedVariableValues(context, valueNode); const value = scopedVariableValues?.coerced[valueNode.name.value]; if ((0, definition_ts_1.isNonNullType)(type)) { if (value === undefined) { reportInvalidLiteral(context.onError, `Expected variable "$${valueNode.name.value}" provided to type "${type}" to provide a runtime value.`, valueNode, path); } else if (value === null) { reportInvalidLiteral(context.onError, `Expected variable "$${valueNode.name.value}" provided to non-null type "${type}" not to be null.`, valueNode, path); } } return; } if ((0, definition_ts_1.isNonNullType)(type)) { if (valueNode.kind === kinds_ts_1.Kind.NULL) { reportInvalidLiteral(context.onError, `Expected value of non-null type "${type}" not to be null.`, valueNode, path); return; } return validateInputLiteralImpl(context, valueNode, type.ofType, hideSuggestions, path); } if (valueNode.kind === kinds_ts_1.Kind.NULL) { return; } if ((0, definition_ts_1.isListType)(type)) { if (valueNode.kind !== kinds_ts_1.Kind.LIST) { validateInputLiteralImpl(context, valueNode, type.ofType, hideSuggestions, path); } else { let index = 0; for (const itemNode of valueNode.values) { validateInputLiteralImpl(context, itemNode, type.ofType, hideSuggestions, (0, Path_ts_1.addPath)(path, index++, undefined)); } } } else if ((0, definition_ts_1.isInputObjectType)(type)) { if (valueNode.kind !== kinds_ts_1.Kind.OBJECT) { reportInvalidLiteral(context.onError, `Expected value of type "${type}" to be an object, found: ${(0, printer_ts_1.print)(valueNode)}.`, valueNode, path); return; } const fieldDefs = type.getFields(); const fieldNodes = (0, keyMap_ts_1.keyMap)(valueNode.fields, (field) => field.name.value); for (const field of Object.values(fieldDefs)) { const fieldNode = fieldNodes[field.name]; if (fieldNode === undefined) { if ((0, definition_ts_1.isRequiredInputField)(field)) { reportInvalidLiteral(context.onError, `Expected value of type "${type}" to include required field "${field.name}", found: ${(0, printer_ts_1.print)(valueNode)}.`, valueNode, path); } } else { const fieldValueNode = fieldNode.value; if (fieldValueNode.kind === kinds_ts_1.Kind.VARIABLE && !context.static) { const scopedVariableValues = getScopedVariableValues(context, fieldValueNode); const variableName = fieldValueNode.name.value; const value = scopedVariableValues?.coerced[variableName]; if (type.isOneOf) { if (value === undefined) { reportInvalidLiteral(context.onError, `Expected variable "$${variableName}" provided to field "${field.name}" for OneOf Input Object type "${type}" to provide a runtime value.`, valueNode, path); } else if (value === null) { reportInvalidLiteral(context.onError, `Expected variable "$${variableName}" provided to field "${field.name}" for OneOf Input Object type "${type}" not to be null.`, valueNode, path); } } else if (value === undefined && !(0, definition_ts_1.isRequiredInputField)(field)) { continue; } } validateInputLiteralImpl(context, fieldValueNode, field.type, hideSuggestions, (0, Path_ts_1.addPath)(path, field.name, type.name)); } } const fields = valueNode.fields; const knownFields = []; for (const fieldNode of fields) { const fieldName = fieldNode.name.value; if (!Object.hasOwn(fieldDefs, fieldName)) { const suggestion = hideSuggestions ? '' : (0, didYouMean_ts_1.didYouMean)((0, suggestionList_ts_1.suggestionList)(fieldName, Object.keys(fieldDefs))); reportInvalidLiteral(context.onError, `Expected value of type "${type}" not to include unknown field "${fieldName}"${suggestion ? `.${suggestion} Found` : ', found'}: ${(0, printer_ts_1.print)(valueNode)}.`, fieldNode, path); } else { knownFields.push(fieldNode); } } if (type.isOneOf) { const isNotExactlyOneField = knownFields.length !== 1; if (isNotExactlyOneField) { reportInvalidLiteral(context.onError, getOneOfInputObjectErrorMessage(type), valueNode, path); return; } const fieldValueNode = knownFields[0].value; if (fieldValueNode.kind === kinds_ts_1.Kind.NULL) { const fieldName = knownFields[0].name.value; reportInvalidLiteral(context.onError, getOneOfInputObjectErrorMessage(type), valueNode, (0, Path_ts_1.addPath)(path, fieldName, undefined)); } } } else { (0, definition_ts_1.assertLeafType)(type); let result; let caughtError; try { result = type.coerceInputLiteral ? type.coerceInputLiteral((0, replaceVariables_ts_1.replaceVariables)(valueNode, context.variables, context.fragmentVariableValues), hideSuggestions) : type.parseLiteral(valueNode, undefined, hideSuggestions); } catch (error) { if (error instanceof GraphQLError_ts_1.GraphQLError) { context.onError(error, (0, Path_ts_1.pathToArray)(path)); return; } caughtError = error; } if (result === undefined) { reportInvalidLiteral(context.onError, `Expected value of type "${type}"${caughtError != null ? `, but encountered error "${getCaughtErrorMessage(caughtError)}"; found` : ', found'}: ${(0, printer_ts_1.print)(valueNode)}.`, valueNode, path, (0, ensureGraphQLError_ts_1.ensureGraphQLError)(caughtError)); } } } function getScopedVariableValues(context, valueNode) { const variableName = valueNode.name.value; const { fragmentVariableValues, variables } = context; return fragmentVariableValues?.sources[variableName] ? fragmentVariableValues : variables; } function reportInvalidLiteral(onError, message, valueNode, path, originalError) { onError(new GraphQLError_ts_1.GraphQLError(message, { nodes: valueNode, originalError, }), (0, Path_ts_1.pathToArray)(path)); } function getCaughtErrorMessage(caughtError) { if ((0, isObjectLike_ts_1.isObjectLike)(caughtError)) { const message = caughtError.message; if (typeof message === 'string' && message !== '') { return message; } } return String(caughtError); } function getOneOfInputObjectErrorMessage(type) { return `Within OneOf Input Object type "${type}", exactly one field must be specified, and the value for that field must be non-null.`; } //# sourceMappingURL=validateInputValue.js.map