4
4
5
5
import {
6
6
getArgumentValues ,
7
+ getDirectiveValues ,
7
8
} from 'graphql/execution/values' ;
8
9
9
10
import {
10
11
ValidationContext ,
11
12
FragmentDefinitionNode ,
12
13
OperationDefinitionNode ,
14
+ DirectiveNode ,
13
15
FieldNode ,
14
16
FragmentSpreadNode ,
15
17
InlineFragmentNode ,
16
18
assertCompositeType ,
17
19
GraphQLField , isCompositeType , GraphQLCompositeType , GraphQLFieldMap ,
18
20
GraphQLSchema , DocumentNode , TypeInfo ,
19
- visit , visitWithTypeInfo
21
+ visit , visitWithTypeInfo ,
22
+ GraphQLDirective ,
20
23
} from 'graphql' ;
21
24
import {
22
25
GraphQLUnionType ,
@@ -102,6 +105,8 @@ export default class QueryComplexity {
102
105
options : QueryComplexityOptions ;
103
106
OperationDefinition : Object ;
104
107
estimators : Array < ComplexityEstimator > ;
108
+ includeDirectiveDef : GraphQLDirective ;
109
+ skipDirectiveDef : GraphQLDirective ;
105
110
106
111
constructor (
107
112
context : ValidationContext ,
@@ -115,6 +120,9 @@ export default class QueryComplexity {
115
120
this . complexity = 0 ;
116
121
this . options = options ;
117
122
123
+ this . includeDirectiveDef = this . context . getSchema ( ) . getDirective ( 'include' ) ;
124
+ this . skipDirectiveDef = this . context . getSchema ( ) . getDirective ( 'skip' ) ;
125
+
118
126
if ( ! options . estimators ) {
119
127
console . warn (
120
128
'DEPRECATION WARNING: Estimators should be configured in the queryComplexity options.'
@@ -183,6 +191,29 @@ export default class QueryComplexity {
183
191
( total : number , childNode : FieldNode | FragmentSpreadNode | InlineFragmentNode ) => {
184
192
let nodeComplexity = 0 ;
185
193
194
+ let includeNode = true ;
195
+ let skipNode = false ;
196
+
197
+ childNode . directives . forEach ( ( directive : DirectiveNode ) => {
198
+ const directiveName = directive . name . value ;
199
+ switch ( directiveName ) {
200
+ case 'include' : {
201
+ const values = getDirectiveValues ( this . includeDirectiveDef , childNode , this . options . variables || { } ) ;
202
+ includeNode = values . if ;
203
+ break ;
204
+ }
205
+ case 'skip' : {
206
+ const values = getDirectiveValues ( this . skipDirectiveDef , childNode , this . options . variables || { } ) ;
207
+ skipNode = values . if ;
208
+ break ;
209
+ }
210
+ }
211
+ } ) ;
212
+
213
+ if ( ! includeNode || skipNode ) {
214
+ return total ;
215
+ }
216
+
186
217
switch ( childNode . kind ) {
187
218
case Kind . FIELD : {
188
219
const field = fields [ childNode . name . value ] ;
0 commit comments