diff --git a/src/execution/values.ts b/src/execution/values.ts index 5511911c78..12bab5cb6b 100644 --- a/src/execution/values.ts +++ b/src/execution/values.ts @@ -14,12 +14,12 @@ import { Kind } from '../language/kinds.js'; import { print } from '../language/printer.js'; import type { GraphQLField } from '../type/definition.js'; -import { isInputType, isNonNullType } from '../type/definition.js'; +import { isNonNullType } from '../type/definition.js'; import type { GraphQLDirective } from '../type/directives.js'; import type { GraphQLSchema } from '../type/schema.js'; import { coerceInputValue } from '../utilities/coerceInputValue.js'; -import { typeFromAST } from '../utilities/typeFromAST.js'; +import { getVariableSignature } from '../utilities/getVariableSignature.js'; import { valueFromAST } from '../utilities/valueFromAST.js'; type CoercedVariableValues = @@ -76,24 +76,16 @@ function coerceVariableValues( ): { [variable: string]: unknown } { const coercedValues: { [variable: string]: unknown } = {}; for (const varDefNode of varDefNodes) { - const varName = varDefNode.variable.name.value; - const varType = typeFromAST(schema, varDefNode.type); - if (!isInputType(varType)) { - // Must use input types for variables. This should be caught during - // validation, however is checked again here for safety. - const varTypeStr = print(varDefNode.type); - onError( - new GraphQLError( - `Variable "$${varName}" expected value of type "${varTypeStr}" which cannot be used as an input type.`, - { nodes: varDefNode.type }, - ), - ); + const varSignature = getVariableSignature(schema, varDefNode); + if (varSignature instanceof GraphQLError) { + onError(varSignature); continue; } + const { name: varName, type: varType } = varSignature; if (!Object.hasOwn(inputs, varName)) { if (varDefNode.defaultValue) { - coercedValues[varName] = valueFromAST(varDefNode.defaultValue, varType); + coercedValues[varName] = varSignature.defaultValue; } else if (isNonNullType(varType)) { const varTypeStr = inspect(varType); onError( diff --git a/src/utilities/getVariableSignature.ts b/src/utilities/getVariableSignature.ts new file mode 100644 index 0000000000..4ff7e977e4 --- /dev/null +++ b/src/utilities/getVariableSignature.ts @@ -0,0 +1,44 @@ +import { GraphQLError } from '../error/GraphQLError.js'; + +import { print } from '../language/printer.js'; + +import type { GraphQLInputType, GraphQLSchema } from '../type/index.js'; +import { isInputType } from '../type/index.js'; + +import type { VariableDefinitionNode } from '../index.js'; + +import { typeFromAST } from './typeFromAST.js'; +import { valueFromAST } from './valueFromAST.js'; + +/** + * A GraphQLVariableSignature is required to coerce a variable value. + * */ +export interface GraphQLVariableSignature { + name: string; + type: GraphQLInputType; + defaultValue: unknown; +} + +export function getVariableSignature( + schema: GraphQLSchema, + varDefNode: VariableDefinitionNode, +): GraphQLVariableSignature | GraphQLError { + const varName = varDefNode.variable.name.value; + const varType = typeFromAST(schema, varDefNode.type); + + if (!isInputType(varType)) { + // Must use input types for variables. This should be caught during + // validation, however is checked again here for safety. + const varTypeStr = print(varDefNode.type); + return new GraphQLError( + `Variable "$${varName}" expected value of type "${varTypeStr}" which cannot be used as an input type.`, + { nodes: varDefNode.type }, + ); + } + + return { + name: varName, + type: varType, + defaultValue: valueFromAST(varDefNode.defaultValue, varType), + }; +}