import { GraphQLError } from '../../error/GraphQLError' ; import type { FragmentDefinitionNode , OperationDefinitionNode , } from '../../language/ast' ; import type { ASTVisitor } from '../../language/visitor' ; import type { ASTValidationContext } from '../ValidationContext' ; /**
 * No unused fragments
 *
 * A GraphQL document is only valid if all fragment definitions are spread
 * within operations, or spread within other fragments spread within operations.
 *
 * See https://spec.graphql.org/draft/#sec-Fragments-Must-Be-Used
 */ export function NoUnusedFragmentsRule ( context ) { const operationDefs = [ ] ; const fragmentDefs = [ ] ; return { OperationDefinition ( node ) { operationDefs . push ( node ) ; return false ; } , FragmentDefinition ( node ) { fragmentDefs . push ( node ) ; return false ; } , Document : { leave ( ) { const fragmentNameUsed = Object . create ( null ) ; for ( const operation of operationDefs ) { for ( const fragment of context . getRecursivelyReferencedFragments ( operation ) ) { fragmentNameUsed [ fragment . name . value ] = true ; } } for ( const fragmentDef of fragmentDefs ) { const fragName = fragmentDef . name . value ; if ( fragmentNameUsed [ fragName ] !== true ) { context . reportError ( new GraphQLError ( `Fragment "${ fragName }" is never used.` , fragmentDef ) ) ; } } } , } , } ; }