@@ -16,7 +16,11 @@ import {
16
16
isListType ,
17
17
isNonNullType ,
18
18
GraphQLDirective ,
19
+ TypeInfo ,
20
+ visit ,
21
+ visitWithTypeInfo ,
19
22
} from 'graphql' ;
23
+ import { SiblingOperations } from './sibling-operations' ;
20
24
21
25
export function createReachableTypesService ( schema : GraphQLSchema ) : ( ) => Set < string > ;
22
26
export function createReachableTypesService ( schema ?: GraphQLSchema ) : ( ) => Set < string > | null {
@@ -128,3 +132,62 @@ export function collectReachableTypes(schema: GraphQLSchema): Set<string> {
128
132
return false ;
129
133
}
130
134
}
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