VariablesInAllowedPositionRule.mjs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import inspect from "../../jsutils/inspect.mjs";
  2. import { GraphQLError } from "../../error/GraphQLError.mjs";
  3. import { Kind } from "../../language/kinds.mjs";
  4. import { isNonNullType } from "../../type/definition.mjs";
  5. import { typeFromAST } from "../../utilities/typeFromAST.mjs";
  6. import { isTypeSubTypeOf } from "../../utilities/typeComparators.mjs";
  7. /**
  8. * Variables passed to field arguments conform to type
  9. */
  10. export function VariablesInAllowedPositionRule(context) {
  11. var varDefMap = Object.create(null);
  12. return {
  13. OperationDefinition: {
  14. enter: function enter() {
  15. varDefMap = Object.create(null);
  16. },
  17. leave: function leave(operation) {
  18. var usages = context.getRecursiveVariableUsages(operation);
  19. for (var _i2 = 0; _i2 < usages.length; _i2++) {
  20. var _ref2 = usages[_i2];
  21. var node = _ref2.node;
  22. var type = _ref2.type;
  23. var defaultValue = _ref2.defaultValue;
  24. var varName = node.name.value;
  25. var varDef = varDefMap[varName];
  26. if (varDef && type) {
  27. // A var type is allowed if it is the same or more strict (e.g. is
  28. // a subtype of) than the expected type. It can be more strict if
  29. // the variable type is non-null when the expected type is nullable.
  30. // If both are list types, the variable item type can be more strict
  31. // than the expected item type (contravariant).
  32. var schema = context.getSchema();
  33. var varType = typeFromAST(schema, varDef.type);
  34. if (varType && !allowedVariableUsage(schema, varType, varDef.defaultValue, type, defaultValue)) {
  35. var varTypeStr = inspect(varType);
  36. var typeStr = inspect(type);
  37. context.reportError(new GraphQLError("Variable \"$".concat(varName, "\" of type \"").concat(varTypeStr, "\" used in position expecting type \"").concat(typeStr, "\"."), [varDef, node]));
  38. }
  39. }
  40. }
  41. }
  42. },
  43. VariableDefinition: function VariableDefinition(node) {
  44. varDefMap[node.variable.name.value] = node;
  45. }
  46. };
  47. }
  48. /**
  49. * Returns true if the variable is allowed in the location it was found,
  50. * which includes considering if default values exist for either the variable
  51. * or the location at which it is located.
  52. */
  53. function allowedVariableUsage(schema, varType, varDefaultValue, locationType, locationDefaultValue) {
  54. if (isNonNullType(locationType) && !isNonNullType(varType)) {
  55. var hasNonNullVariableDefaultValue = varDefaultValue != null && varDefaultValue.kind !== Kind.NULL;
  56. var hasLocationDefaultValue = locationDefaultValue !== undefined;
  57. if (!hasNonNullVariableDefaultValue && !hasLocationDefaultValue) {
  58. return false;
  59. }
  60. var nullableLocationType = locationType.ofType;
  61. return isTypeSubTypeOf(schema, varType, nullableLocationType);
  62. }
  63. return isTypeSubTypeOf(schema, varType, locationType);
  64. }