ProvidedRequiredArgumentsRule.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true,
  4. });
  5. exports.ProvidedRequiredArgumentsOnDirectivesRule =
  6. ProvidedRequiredArgumentsOnDirectivesRule;
  7. exports.ProvidedRequiredArgumentsRule = ProvidedRequiredArgumentsRule;
  8. var _inspect = require('../../jsutils/inspect.js');
  9. var _keyMap = require('../../jsutils/keyMap.js');
  10. var _GraphQLError = require('../../error/GraphQLError.js');
  11. var _kinds = require('../../language/kinds.js');
  12. var _printer = require('../../language/printer.js');
  13. var _definition = require('../../type/definition.js');
  14. var _directives = require('../../type/directives.js');
  15. /**
  16. * Provided required arguments
  17. *
  18. * A field or directive is only valid if all required (non-null without a
  19. * default value) field arguments have been provided.
  20. */
  21. function ProvidedRequiredArgumentsRule(context) {
  22. return {
  23. // eslint-disable-next-line new-cap
  24. ...ProvidedRequiredArgumentsOnDirectivesRule(context),
  25. Field: {
  26. // Validate on leave to allow for deeper errors to appear first.
  27. leave(fieldNode) {
  28. var _fieldNode$arguments;
  29. const fieldDef = context.getFieldDef();
  30. if (!fieldDef) {
  31. return false;
  32. }
  33. const providedArgs = new Set( // FIXME: https://github.com/graphql/graphql-js/issues/2203
  34. /* c8 ignore next */
  35. (_fieldNode$arguments = fieldNode.arguments) === null ||
  36. _fieldNode$arguments === void 0
  37. ? void 0
  38. : _fieldNode$arguments.map((arg) => arg.name.value),
  39. );
  40. for (const argDef of fieldDef.args) {
  41. if (
  42. !providedArgs.has(argDef.name) &&
  43. (0, _definition.isRequiredArgument)(argDef)
  44. ) {
  45. const argTypeStr = (0, _inspect.inspect)(argDef.type);
  46. context.reportError(
  47. new _GraphQLError.GraphQLError(
  48. `Field "${fieldDef.name}" argument "${argDef.name}" of type "${argTypeStr}" is required, but it was not provided.`,
  49. {
  50. nodes: fieldNode,
  51. },
  52. ),
  53. );
  54. }
  55. }
  56. },
  57. },
  58. };
  59. }
  60. /**
  61. * @internal
  62. */
  63. function ProvidedRequiredArgumentsOnDirectivesRule(context) {
  64. var _schema$getDirectives;
  65. const requiredArgsMap = Object.create(null);
  66. const schema = context.getSchema();
  67. const definedDirectives =
  68. (_schema$getDirectives =
  69. schema === null || schema === void 0
  70. ? void 0
  71. : schema.getDirectives()) !== null && _schema$getDirectives !== void 0
  72. ? _schema$getDirectives
  73. : _directives.specifiedDirectives;
  74. for (const directive of definedDirectives) {
  75. requiredArgsMap[directive.name] = (0, _keyMap.keyMap)(
  76. directive.args.filter(_definition.isRequiredArgument),
  77. (arg) => arg.name,
  78. );
  79. }
  80. const astDefinitions = context.getDocument().definitions;
  81. for (const def of astDefinitions) {
  82. if (def.kind === _kinds.Kind.DIRECTIVE_DEFINITION) {
  83. var _def$arguments;
  84. // FIXME: https://github.com/graphql/graphql-js/issues/2203
  85. /* c8 ignore next */
  86. const argNodes =
  87. (_def$arguments = def.arguments) !== null && _def$arguments !== void 0
  88. ? _def$arguments
  89. : [];
  90. requiredArgsMap[def.name.value] = (0, _keyMap.keyMap)(
  91. argNodes.filter(isRequiredArgumentNode),
  92. (arg) => arg.name.value,
  93. );
  94. }
  95. }
  96. return {
  97. Directive: {
  98. // Validate on leave to allow for deeper errors to appear first.
  99. leave(directiveNode) {
  100. const directiveName = directiveNode.name.value;
  101. const requiredArgs = requiredArgsMap[directiveName];
  102. if (requiredArgs) {
  103. var _directiveNode$argume;
  104. // FIXME: https://github.com/graphql/graphql-js/issues/2203
  105. /* c8 ignore next */
  106. const argNodes =
  107. (_directiveNode$argume = directiveNode.arguments) !== null &&
  108. _directiveNode$argume !== void 0
  109. ? _directiveNode$argume
  110. : [];
  111. const argNodeMap = new Set(argNodes.map((arg) => arg.name.value));
  112. for (const [argName, argDef] of Object.entries(requiredArgs)) {
  113. if (!argNodeMap.has(argName)) {
  114. const argType = (0, _definition.isType)(argDef.type)
  115. ? (0, _inspect.inspect)(argDef.type)
  116. : (0, _printer.print)(argDef.type);
  117. context.reportError(
  118. new _GraphQLError.GraphQLError(
  119. `Directive "@${directiveName}" argument "${argName}" of type "${argType}" is required, but it was not provided.`,
  120. {
  121. nodes: directiveNode,
  122. },
  123. ),
  124. );
  125. }
  126. }
  127. }
  128. },
  129. },
  130. };
  131. }
  132. function isRequiredArgumentNode(arg) {
  133. return (
  134. arg.type.kind === _kinds.Kind.NON_NULL_TYPE && arg.defaultValue == null
  135. );
  136. }