Skip to content

Commit

Permalink
introduce internal getVariableSignature utility
Browse files Browse the repository at this point in the history
extracted from my fragment arguments scratch branch
  • Loading branch information
yaacovCR committed Aug 22, 2024
1 parent 5c7d4d1 commit 480613c
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 16 deletions.
24 changes: 8 additions & 16 deletions src/execution/values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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);
if (varSignature.hasDefaultValue) {
coercedValues[varName] = varSignature.getDefaultValue();
} else if (isNonNullType(varType)) {
const varTypeStr = inspect(varType);
onError(
Expand Down
69 changes: 69 additions & 0 deletions src/utilities/getVariableSignature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
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 { ConstValueNode, VariableDefinitionNode } from '../index.js';

import { typeFromAST } from './typeFromAST.js';
import { valueFromAST } from './valueFromAST.js';

/**
* A GraphQLVariableSignature is required to coerce a variable value.
*
* @internal
* */
export class GraphQLVariableSignature {
name: string;
type: GraphQLInputType;
hasDefaultValue: boolean;
_defaultValue: unknown;

constructor(
name: string,
type: GraphQLInputType,
defaultValueNode: ConstValueNode | undefined,
) {
this.name = name;
this.type = type;
if (defaultValueNode) {
this.hasDefaultValue = true;
this._defaultValue = () => valueFromAST(defaultValueNode, type);
} else {
this.hasDefaultValue = false;
}
}

getDefaultValue(): unknown {
if (typeof this._defaultValue === 'function') {
this._defaultValue = this._defaultValue();
}
return this._defaultValue;
}
}

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 new GraphQLVariableSignature(
varName,
varType,
varDefNode.defaultValue,
);
}

0 comments on commit 480613c

Please sign in to comment.