@@ -16,7 +16,11 @@ import {
1616 isListType ,
1717 isNonNullType ,
1818 GraphQLDirective ,
19+ TypeInfo ,
20+ visit ,
21+ visitWithTypeInfo ,
1922} from 'graphql' ;
23+ import { SiblingOperations } from './sibling-operations' ;
2024
2125export function createReachableTypesService ( schema : GraphQLSchema ) : ( ) => Set < string > ;
2226export function createReachableTypesService ( schema ?: GraphQLSchema ) : ( ) => Set < string > | null {
@@ -128,3 +132,62 @@ export function collectReachableTypes(schema: GraphQLSchema): Set<string> {
128132 return false ;
129133 }
130134}
135+
136+ export type FieldsCache = Record < string , Set < string > > ;
137+
138+ export function createUsedFieldsService ( schema : GraphQLSchema , operations : SiblingOperations ) : ( ) => FieldsCache | null {
139+ if ( ! schema || ! operations ) {
140+ return ( ) => null ;
141+ }
142+
143+ let cache : FieldsCache = null ;
144+
145+ return ( ) => {
146+ if ( ! cache ) {
147+ cache = collectUsedFields ( schema , operations ) ;
148+ }
149+
150+ return cache ;
151+ } ;
152+ }
153+
154+ export function collectUsedFields ( schema : GraphQLSchema , operations : SiblingOperations ) : FieldsCache {
155+ const cache : FieldsCache = { } ;
156+
157+ const addField = ( typeName , fieldName ) => {
158+ const fieldType = cache [ typeName ] ?? ( cache [ typeName ] = new Set ( ) ) ;
159+ fieldType . add ( fieldName ) ;
160+ } ;
161+
162+ const typeInfo = new TypeInfo ( schema ) ;
163+
164+ const visitor = visitWithTypeInfo ( typeInfo , {
165+ Field : {
166+ enter ( node ) {
167+ const fieldDef = typeInfo . getFieldDef ( ) ;
168+
169+ if ( ! fieldDef ) {
170+ // skip visiting this node if field is not defined in schema
171+ return false ;
172+ }
173+
174+ const parent = typeInfo . getParentType ( ) ;
175+ const fieldName = node . name . value ;
176+ addField ( parent . name , fieldName ) ;
177+
178+ return undefined ;
179+ } ,
180+ } ,
181+ } ) ;
182+
183+ const allDocuments = [
184+ ...operations . getOperations ( ) ,
185+ ...operations . getFragments ( ) ,
186+ ] ;
187+
188+ for ( const { document } of allDocuments ) {
189+ visit ( document , visitor ) ;
190+ }
191+
192+ return cache ;
193+ }
0 commit comments