VariablesInAllowedPosition.mjs 2.9 KB

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