NoDeprecatedCustomRule.js.flow 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // @flow strict
  2. import invariant from '../../../jsutils/invariant';
  3. import { GraphQLError } from '../../../error/GraphQLError';
  4. import type { ASTVisitor } from '../../../language/visitor';
  5. import { getNamedType, isInputObjectType } from '../../../type/definition';
  6. import type { ValidationContext } from '../../ValidationContext';
  7. /**
  8. * No deprecated
  9. *
  10. * A GraphQL document is only valid if all selected fields and all used enum values have not been
  11. * deprecated.
  12. *
  13. * Note: This rule is optional and is not part of the Validation section of the GraphQL
  14. * Specification. The main purpose of this rule is detection of deprecated usages and not
  15. * necessarily to forbid their use when querying a service.
  16. */
  17. export function NoDeprecatedCustomRule(context: ValidationContext): ASTVisitor {
  18. return {
  19. Field(node) {
  20. const fieldDef = context.getFieldDef();
  21. const deprecationReason = fieldDef?.deprecationReason;
  22. if (fieldDef && deprecationReason != null) {
  23. const parentType = context.getParentType();
  24. invariant(parentType != null);
  25. context.reportError(
  26. new GraphQLError(
  27. `The field ${parentType.name}.${fieldDef.name} is deprecated. ${deprecationReason}`,
  28. node,
  29. ),
  30. );
  31. }
  32. },
  33. Argument(node) {
  34. const argDef = context.getArgument();
  35. const deprecationReason = argDef?.deprecationReason;
  36. if (argDef && deprecationReason != null) {
  37. const directiveDef = context.getDirective();
  38. if (directiveDef != null) {
  39. context.reportError(
  40. new GraphQLError(
  41. `Directive "@${directiveDef.name}" argument "${argDef.name}" is deprecated. ${deprecationReason}`,
  42. node,
  43. ),
  44. );
  45. } else {
  46. const parentType = context.getParentType();
  47. const fieldDef = context.getFieldDef();
  48. invariant(parentType != null && fieldDef != null);
  49. context.reportError(
  50. new GraphQLError(
  51. `Field "${parentType.name}.${fieldDef.name}" argument "${argDef.name}" is deprecated. ${deprecationReason}`,
  52. node,
  53. ),
  54. );
  55. }
  56. }
  57. },
  58. ObjectField(node) {
  59. const inputObjectDef = getNamedType(context.getParentInputType());
  60. if (isInputObjectType(inputObjectDef)) {
  61. const inputFieldDef = inputObjectDef.getFields()[node.name.value];
  62. // flowlint-next-line unnecessary-optional-chain:off
  63. const deprecationReason = inputFieldDef?.deprecationReason;
  64. if (deprecationReason != null) {
  65. context.reportError(
  66. new GraphQLError(
  67. `The input field ${inputObjectDef.name}.${inputFieldDef.name} is deprecated. ${deprecationReason}`,
  68. node,
  69. ),
  70. );
  71. }
  72. }
  73. },
  74. EnumValue(node) {
  75. const enumValueDef = context.getEnumValue();
  76. const deprecationReason = enumValueDef?.deprecationReason;
  77. if (enumValueDef && deprecationReason != null) {
  78. const enumTypeDef = getNamedType(context.getInputType());
  79. invariant(enumTypeDef != null);
  80. context.reportError(
  81. new GraphQLError(
  82. `The enum value "${enumTypeDef.name}.${enumValueDef.name}" is deprecated. ${deprecationReason}`,
  83. node,
  84. ),
  85. );
  86. }
  87. },
  88. };
  89. }