| import inspect from "../../jsutils/inspect.mjs"; |
| import { GraphQLError } from "../../error/GraphQLError.mjs"; |
| import { Kind } from "../../language/kinds.mjs"; |
| import { isNonNullType } from "../../type/definition.mjs"; |
| import { typeFromAST } from "../../utilities/typeFromAST.mjs"; |
| import { isTypeSubTypeOf } from "../../utilities/typeComparators.mjs"; |
| |
| /** |
| * Variables passed to field arguments conform to type |
| */ |
| export function VariablesInAllowedPositionRule(context) { |
| var varDefMap = Object.create(null); |
| return { |
| OperationDefinition: { |
| enter: function enter() { |
| varDefMap = Object.create(null); |
| }, |
| leave: function leave(operation) { |
| var usages = context.getRecursiveVariableUsages(operation); |
| |
| for (var _i2 = 0; _i2 < usages.length; _i2++) { |
| var _ref2 = usages[_i2]; |
| var node = _ref2.node; |
| var type = _ref2.type; |
| var defaultValue = _ref2.defaultValue; |
| var varName = node.name.value; |
| var varDef = varDefMap[varName]; |
| |
| if (varDef && type) { |
| // A var type is allowed if it is the same or more strict (e.g. is |
| // a subtype of) than the expected type. It can be more strict if |
| // the variable type is non-null when the expected type is nullable. |
| // If both are list types, the variable item type can be more strict |
| // than the expected item type (contravariant). |
| var schema = context.getSchema(); |
| var varType = typeFromAST(schema, varDef.type); |
| |
| if (varType && !allowedVariableUsage(schema, varType, varDef.defaultValue, type, defaultValue)) { |
| var varTypeStr = inspect(varType); |
| var typeStr = inspect(type); |
| context.reportError(new GraphQLError("Variable \"$".concat(varName, "\" of type \"").concat(varTypeStr, "\" used in position expecting type \"").concat(typeStr, "\"."), [varDef, node])); |
| } |
| } |
| } |
| } |
| }, |
| VariableDefinition: function VariableDefinition(node) { |
| varDefMap[node.variable.name.value] = node; |
| } |
| }; |
| } |
| /** |
| * Returns true if the variable is allowed in the location it was found, |
| * which includes considering if default values exist for either the variable |
| * or the location at which it is located. |
| */ |
| |
| function allowedVariableUsage(schema, varType, varDefaultValue, locationType, locationDefaultValue) { |
| if (isNonNullType(locationType) && !isNonNullType(varType)) { |
| var hasNonNullVariableDefaultValue = varDefaultValue != null && varDefaultValue.kind !== Kind.NULL; |
| var hasLocationDefaultValue = locationDefaultValue !== undefined; |
| |
| if (!hasNonNullVariableDefaultValue && !hasLocationDefaultValue) { |
| return false; |
| } |
| |
| var nullableLocationType = locationType.ofType; |
| return isTypeSubTypeOf(schema, varType, nullableLocationType); |
| } |
| |
| return isTypeSubTypeOf(schema, varType, locationType); |
| } |