UniqueDirectivesPerLocationRule.mjs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import { GraphQLError } from "../../error/GraphQLError.mjs";
  2. import { Kind } from "../../language/kinds.mjs";
  3. import { isTypeDefinitionNode, isTypeExtensionNode } from "../../language/predicates.mjs";
  4. import { specifiedDirectives } from "../../type/directives.mjs";
  5. /**
  6. * Unique directive names per location
  7. *
  8. * A GraphQL document is only valid if all non-repeatable directives at
  9. * a given location are uniquely named.
  10. */
  11. export function UniqueDirectivesPerLocationRule(context) {
  12. var uniqueDirectiveMap = Object.create(null);
  13. var schema = context.getSchema();
  14. var definedDirectives = schema ? schema.getDirectives() : specifiedDirectives;
  15. for (var _i2 = 0; _i2 < definedDirectives.length; _i2++) {
  16. var directive = definedDirectives[_i2];
  17. uniqueDirectiveMap[directive.name] = !directive.isRepeatable;
  18. }
  19. var astDefinitions = context.getDocument().definitions;
  20. for (var _i4 = 0; _i4 < astDefinitions.length; _i4++) {
  21. var def = astDefinitions[_i4];
  22. if (def.kind === Kind.DIRECTIVE_DEFINITION) {
  23. uniqueDirectiveMap[def.name.value] = !def.repeatable;
  24. }
  25. }
  26. var schemaDirectives = Object.create(null);
  27. var typeDirectivesMap = Object.create(null);
  28. return {
  29. // Many different AST nodes may contain directives. Rather than listing
  30. // them all, just listen for entering any node, and check to see if it
  31. // defines any directives.
  32. enter: function enter(node) {
  33. if (node.directives == null) {
  34. return;
  35. }
  36. var seenDirectives;
  37. if (node.kind === Kind.SCHEMA_DEFINITION || node.kind === Kind.SCHEMA_EXTENSION) {
  38. seenDirectives = schemaDirectives;
  39. } else if (isTypeDefinitionNode(node) || isTypeExtensionNode(node)) {
  40. var typeName = node.name.value;
  41. seenDirectives = typeDirectivesMap[typeName];
  42. if (seenDirectives === undefined) {
  43. typeDirectivesMap[typeName] = seenDirectives = Object.create(null);
  44. }
  45. } else {
  46. seenDirectives = Object.create(null);
  47. }
  48. for (var _i6 = 0, _node$directives2 = node.directives; _i6 < _node$directives2.length; _i6++) {
  49. var _directive = _node$directives2[_i6];
  50. var directiveName = _directive.name.value;
  51. if (uniqueDirectiveMap[directiveName]) {
  52. if (seenDirectives[directiveName]) {
  53. context.reportError(new GraphQLError("The directive \"@".concat(directiveName, "\" can only be used once at this location."), [seenDirectives[directiveName], _directive]));
  54. } else {
  55. seenDirectives[directiveName] = _directive;
  56. }
  57. }
  58. }
  59. }
  60. };
  61. }