UNPKG

graphql

Version:

A Query Language and Runtime which can target any service.

1 lines 7.53 kB
{"version":3,"file":"VariablesInAllowedPositionRule.js","sourceRoot":"","sources":["../../../src/validation/rules/VariablesInAllowedPositionRule.ts"],"names":[],"mappings":"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","sourcesContent":["/** @category Validation Rules */\n\nimport type { Maybe } from '../../jsutils/Maybe.ts';\n\nimport { GraphQLError } from '../../error/GraphQLError.ts';\n\nimport type { ValueNode, VariableDefinitionNode } from '../../language/ast.ts';\nimport { Kind } from '../../language/kinds.ts';\nimport type { ASTVisitor } from '../../language/visitor.ts';\n\nimport type { GraphQLType } from '../../type/definition.ts';\nimport {\n isInputObjectType,\n isNonNullType,\n isNullableType,\n} from '../../type/definition.ts';\nimport type { GraphQLSchema } from '../../type/schema.ts';\n\nimport { isTypeSubTypeOf } from '../../utilities/typeComparators.ts';\nimport { typeFromAST } from '../../utilities/typeFromAST.ts';\n\nimport type { ValidationContext } from '../ValidationContext.ts';\n\n/**\n * Variables in allowed position\n *\n * Variable usages must be compatible with the arguments they are passed to.\n *\n * See https://spec.graphql.org/draft/#sec-All-Variable-Usages-are-Allowed\n * @param context - The validation context used while checking the document.\n * @returns A visitor that reports validation errors for this rule.\n * @example\n * ```ts\n * import { buildSchema, parse, validate } from 'graphql';\n * import { VariablesInAllowedPositionRule } from 'graphql/validation';\n *\n * const schema = buildSchema(`\n * type Query {\n * field(arg: ID!): String\n * }\n * `);\n *\n * const invalidDocument = parse(`\n * query ($id: String) { field(arg: $id) }\n * `);\n * const invalidErrors = validate(schema, invalidDocument, [\n * VariablesInAllowedPositionRule,\n * ]);\n *\n * invalidErrors.length; // => 1\n *\n * const validDocument = parse(`\n * query ($id: ID!) { field(arg: $id) }\n * `);\n * const validErrors = validate(schema, validDocument, [\n * VariablesInAllowedPositionRule,\n * ]);\n *\n * validErrors; // => []\n * ```\n */\nexport function VariablesInAllowedPositionRule(\n context: ValidationContext,\n): ASTVisitor {\n let varDefMap: Map<string, VariableDefinitionNode>;\n\n return {\n OperationDefinition: {\n enter() {\n varDefMap = new Map();\n },\n leave(operation) {\n const usages = context.getRecursiveVariableUsages(operation);\n\n for (const {\n node,\n type,\n parentType,\n defaultValue,\n fragmentVariableDefinition,\n } of usages) {\n const varName = node.name.value;\n\n let varDef = fragmentVariableDefinition;\n varDef ??= varDefMap.get(varName);\n if (varDef && type) {\n // A var type is allowed if it is the same or more strict (e.g. is\n // a subtype of) than the expected type. It can be more strict if\n // the variable type is non-null when the expected type is nullable.\n // If both are list types, the variable item type can be more strict\n // than the expected item type (contravariant).\n const schema = context.getSchema();\n const varType = typeFromAST(schema, varDef.type);\n if (\n varType &&\n !allowedVariableUsage(\n schema,\n varType,\n varDef.defaultValue,\n type,\n defaultValue,\n )\n ) {\n context.reportError(\n new GraphQLError(\n `Variable \"$${varName}\" of type \"${varType}\" used in position expecting type \"${type}\".`,\n { nodes: [varDef, node] },\n ),\n );\n }\n\n if (\n isInputObjectType(parentType) &&\n parentType.isOneOf &&\n isNullableType(varType)\n ) {\n context.reportError(\n new GraphQLError(\n `Variable \"$${varName}\" is of type \"${varType}\" but must be non-nullable to be used for OneOf Input Object \"${parentType}\".`,\n { nodes: [varDef, node] },\n ),\n );\n }\n }\n }\n },\n },\n VariableDefinition(node) {\n varDefMap.set(node.variable.name.value, node);\n },\n };\n}\n\n/**\n * Returns true if the variable is allowed in the location it was found,\n * including considering if default values exist for either the variable\n * or the location at which it is located.\n *\n * OneOf Input Object Type fields are considered separately above to\n * provide a more descriptive error message.\n *\n * @internal\n */\nfunction allowedVariableUsage(\n schema: GraphQLSchema,\n varType: GraphQLType,\n varDefaultValue: Maybe<ValueNode>,\n locationType: GraphQLType,\n locationDefaultValue: unknown,\n): boolean {\n if (isNonNullType(locationType) && !isNonNullType(varType)) {\n const hasNonNullVariableDefaultValue =\n varDefaultValue != null && varDefaultValue.kind !== Kind.NULL;\n const hasLocationDefaultValue = locationDefaultValue !== undefined;\n if (!hasNonNullVariableDefaultValue && !hasLocationDefaultValue) {\n return false;\n }\n const nullableLocationType = locationType.ofType;\n return isTypeSubTypeOf(schema, varType, nullableLocationType);\n }\n return isTypeSubTypeOf(schema, varType, locationType);\n}\n"]}