NoUnusedFragmentsRule.js.flow 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. // @flow strict
  2. import { GraphQLError } from '../../error/GraphQLError';
  3. import type { ASTVisitor } from '../../language/visitor';
  4. import type { ASTValidationContext } from '../ValidationContext';
  5. /**
  6. * No unused fragments
  7. *
  8. * A GraphQL document is only valid if all fragment definitions are spread
  9. * within operations, or spread within other fragments spread within operations.
  10. */
  11. export function NoUnusedFragmentsRule(
  12. context: ASTValidationContext,
  13. ): ASTVisitor {
  14. const operationDefs = [];
  15. const fragmentDefs = [];
  16. return {
  17. OperationDefinition(node) {
  18. operationDefs.push(node);
  19. return false;
  20. },
  21. FragmentDefinition(node) {
  22. fragmentDefs.push(node);
  23. return false;
  24. },
  25. Document: {
  26. leave() {
  27. const fragmentNameUsed = Object.create(null);
  28. for (const operation of operationDefs) {
  29. for (const fragment of context.getRecursivelyReferencedFragments(
  30. operation,
  31. )) {
  32. fragmentNameUsed[fragment.name.value] = true;
  33. }
  34. }
  35. for (const fragmentDef of fragmentDefs) {
  36. const fragName = fragmentDef.name.value;
  37. if (fragmentNameUsed[fragName] !== true) {
  38. context.reportError(
  39. new GraphQLError(
  40. `Fragment "${fragName}" is never used.`,
  41. fragmentDef,
  42. ),
  43. );
  44. }
  45. }
  46. },
  47. },
  48. };
  49. }