UniqueArgumentDefinitionNamesRule.mjs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import { groupBy } from '../../jsutils/groupBy.mjs';
  2. import { GraphQLError } from '../../error/GraphQLError.mjs';
  3. /**
  4. * Unique argument definition names
  5. *
  6. * A GraphQL Object or Interface type is only valid if all its fields have uniquely named arguments.
  7. * A GraphQL Directive is only valid if all its arguments are uniquely named.
  8. */
  9. export function UniqueArgumentDefinitionNamesRule(context) {
  10. return {
  11. DirectiveDefinition(directiveNode) {
  12. var _directiveNode$argume;
  13. // FIXME: https://github.com/graphql/graphql-js/issues/2203
  14. /* c8 ignore next */
  15. const argumentNodes =
  16. (_directiveNode$argume = directiveNode.arguments) !== null &&
  17. _directiveNode$argume !== void 0
  18. ? _directiveNode$argume
  19. : [];
  20. return checkArgUniqueness(`@${directiveNode.name.value}`, argumentNodes);
  21. },
  22. InterfaceTypeDefinition: checkArgUniquenessPerField,
  23. InterfaceTypeExtension: checkArgUniquenessPerField,
  24. ObjectTypeDefinition: checkArgUniquenessPerField,
  25. ObjectTypeExtension: checkArgUniquenessPerField,
  26. };
  27. function checkArgUniquenessPerField(typeNode) {
  28. var _typeNode$fields;
  29. const typeName = typeNode.name.value; // FIXME: https://github.com/graphql/graphql-js/issues/2203
  30. /* c8 ignore next */
  31. const fieldNodes =
  32. (_typeNode$fields = typeNode.fields) !== null &&
  33. _typeNode$fields !== void 0
  34. ? _typeNode$fields
  35. : [];
  36. for (const fieldDef of fieldNodes) {
  37. var _fieldDef$arguments;
  38. const fieldName = fieldDef.name.value; // FIXME: https://github.com/graphql/graphql-js/issues/2203
  39. /* c8 ignore next */
  40. const argumentNodes =
  41. (_fieldDef$arguments = fieldDef.arguments) !== null &&
  42. _fieldDef$arguments !== void 0
  43. ? _fieldDef$arguments
  44. : [];
  45. checkArgUniqueness(`${typeName}.${fieldName}`, argumentNodes);
  46. }
  47. return false;
  48. }
  49. function checkArgUniqueness(parentName, argumentNodes) {
  50. const seenArgs = groupBy(argumentNodes, (arg) => arg.name.value);
  51. for (const [argName, argNodes] of seenArgs) {
  52. if (argNodes.length > 1) {
  53. context.reportError(
  54. new GraphQLError(
  55. `Argument "${parentName}(${argName}:)" can only be defined once.`,
  56. {
  57. nodes: argNodes.map((node) => node.name),
  58. },
  59. ),
  60. );
  61. }
  62. }
  63. return false;
  64. }
  65. }