66 Kind , 
77 DirectiveNode , 
88 SelectionNode , 
9-  getArgumentValues , 
109}  from  'graphql' ; 
1110import  {  FieldWeight ,  TypeWeightObject ,  Variables  }  from  '../@types/buildTypeWeights' ; 
1211/** 
@@ -19,26 +18,27 @@ import { FieldWeight, TypeWeightObject, Variables } from '../@types/buildTypeWei
1918 * | 
2019 * Definiton Node 
2120 * (operation and fragment definitons) 
22-  * / \  
23-  * |-----> Selection Set Node  not done  
21+  * / |  
22+  * |-----> Selection Set Node <-------|  
2423 * | / 
2524 * | Selection Node 
2625 * | (Field, Inline fragment and fragment spread) 
27-  * | | \ \ 
28-  * |--Field Node not done not done 
29-  * 
26+  * | | | \ 
27+  * |--Field Node | fragmentCache 
28+  * | | 
29+  * |-------------------| 
3030 */ 
3131
32- class  ASTParser  { 
33-  typeWeights : TypeWeightObject ; 
32+ class  ComplexityAnalysis  { 
33+  private typeWeights : TypeWeightObject ; 
3434
35-  depth : number ; 
35+  private depth : number ; 
3636
37-  maxDepth : number ; 
37+  public maxDepth : number ; 
3838
39-  variables : Variables ; 
39+  private variables : Variables ; 
4040
41-  fragmentCache : {  [ index : string ] : {  complexity : number ;  depth : number  }  } ; 
41+  private fragmentCache : {  [ index : string ] : {  complexity : number ;  depth : number  }  } ; 
4242
4343 constructor ( typeWeights : TypeWeightObject ,  variables : Variables )  { 
4444 this . typeWeights  =  typeWeights ; 
@@ -59,7 +59,6 @@ class ASTParser {
5959 let  selectionsCost  =  0 ; 
6060 let  calculatedWeight  =  0 ; 
6161
62-  // call the function to handle selection set node with selectionSet property if it is not undefined 
6362 if  ( node . selectionSet )  { 
6463 selectionsCost  +=  this . selectionSetNode ( node . selectionSet ,  typeName ) ; 
6564 } 
@@ -80,22 +79,26 @@ class ASTParser {
8079 private  fieldNode ( node : FieldNode ,  parentName : string ) : number  { 
8180 try  { 
8281 let  complexity  =  0 ; 
82+  // the node must have a parent in typeweights or the analysis will fail. this should never happen 
8383 const  parentType  =  this . typeWeights [ parentName ] ; 
8484 if  ( ! parentType )  { 
8585 throw  new  Error ( 
8686 `ERROR: ASTParser Failed to obtain parentType for parent: ${ parentName } ${ node . name . value }  
8787 ) ; 
8888 } 
89+ 8990 let  typeName : string  |  undefined ; 
9091 let  typeWeight : FieldWeight  |  undefined ; 
91-  if  ( node . name . value  ===  '__typename' )  return  complexity ; 
92+ 93+  if  ( node . name . value  ===  '__typename' )  return  complexity ;  // this will be zero, ie. this field has no complexity 
94+ 9295 if  ( node . name . value  in  this . typeWeights )  { 
93-  // node is an object type n  the typeWeight root 
96+  // node is an object type in  the typeWeight root 
9497 typeName  =  node . name . value ; 
9598 typeWeight  =  this . typeWeights [ typeName ] . weight ; 
9699 complexity  +=  this . calculateCost ( node ,  parentName ,  typeName ,  typeWeight ) ; 
97100 }  else  if  ( parentType . fields [ node . name . value ] . resolveTo )  { 
98-  // field resolves to another type in type weights or a list 
101+  // node is a field on a typeWeight root,  field resolves to another type in type weights or a list 
99102 typeName  =  parentType . fields [ node . name . value ] . resolveTo ; 
100103 typeWeight  =  parentType . fields [ node . name . value ] . weight ; 
101104 // if this is a list typeWeight is a weight function 
@@ -147,7 +150,8 @@ class ASTParser {
147150 * 2. there is a directive named inlcude and the value is true 
148151 * 3. there is a directive named skip and the value is false 
149152 */ 
150-  directiveCheck ( directive : DirectiveNode ) : boolean  { 
153+  // THIS IS NOT CALLED ANYWEHERE. IN PROGRESS 
154+  private  directiveCheck ( directive : DirectiveNode ) : boolean  { 
151155 if  ( directive ?. arguments )  { 
152156 // get the first argument 
153157 const  argument  =  directive . arguments [ 0 ] ; 
@@ -172,8 +176,9 @@ class ASTParser {
172176
173177 private  selectionNode ( node : SelectionNode ,  parentName : string ) : number  { 
174178 let  complexity  =  0 ; 
179+  // TODO: complete implementation of directives include and skip 
175180 /** 
176-  * process this node if: 
181+  * process this node only  if: 
177182 * 1. there is no directive 
178183 * 2. there is a directive named inlcude and the value is true 
179184 * 3. there is a directive named skip and the value is false 
@@ -182,9 +187,8 @@ class ASTParser {
182187 // if (directive && this.directiveCheck(directive[0])) { 
183188 this . depth  +=  1 ; 
184189 if  ( this . depth  >  this . maxDepth )  this . maxDepth  =  this . depth ; 
185-  // check  the kind property against the set of selection nodes that are possible  
190+  // the kind of a field node will either be field, fragment spread or inline fragment  
186191 if  ( node . kind  ===  Kind . FIELD )  { 
187-  // call the function that handle field nodes 
188192 complexity  +=  this . fieldNode ( node ,  parentName . toLowerCase ( ) ) ; 
189193 }  else  if  ( node . kind  ===  Kind . FRAGMENT_SPREAD )  { 
190194 // add complexity and depth from fragment cache 
@@ -214,25 +218,23 @@ class ASTParser {
214218 } 
215219
216220 this . depth  -=  1 ; 
217-  // } 
221+  //*   
218222 return  complexity ; 
219223 } 
220224
221225 private  selectionSetNode ( node : SelectionSetNode ,  parentName : string ) : number  { 
222226 let  complexity  =  0 ; 
223227 let  maxFragmentComplexity  =  0 ; 
224-  // iterate shrough the 'selections' array on the seletion set node 
225228 for  ( let  i  =  0 ;  i  <  node . selections . length ;  i  +=  1 )  { 
226-  // call the function to handle seletion nodes 
227229 // pass the current parent through because selection sets act only as intermediaries 
228230 const  selectionNode  =  node . selections [ i ] ; 
229-  const  selectionCost  =  this . selectionNode ( node . selections [ i ] ,  parentName ) ; 
231+  const  selectionCost  =  this . selectionNode ( selectionNode ,  parentName ) ; 
230232
231233 // we need to get the largest possible complexity so we save the largest inline fragment 
232-  // FIXME: Consider the case where 2 typed fragments are applicable 
233234 // e.g. ...UnionType and ...PartofTheUnion 
234235 // this case these complexities should be summed in order to be accurate 
235236 // However an estimation suffice 
237+  // FIXME: Consider the case where 2 typed fragments are applicable 
236238 if  ( selectionNode . kind  ===  Kind . INLINE_FRAGMENT )  { 
237239 if  ( ! selectionNode . typeCondition )  { 
238240 // complexity is always applicable 
@@ -248,22 +250,17 @@ class ASTParser {
248250
249251 private  definitionNode ( node : DefinitionNode ) : number  { 
250252 let  complexity  =  0 ; 
251-  // check the kind property against the set of definiton nodes that are possible  
253+  // Operation definition is either query, mutation or subscripiton  
252254 if  ( node . kind  ===  Kind . OPERATION_DEFINITION )  { 
253-  // check if the operation is in the type weights object. 
254255 if  ( node . operation . toLocaleLowerCase ( )  in  this . typeWeights )  { 
255-  // if it is, it is an object type, add it's type weight to the total 
256256 complexity  +=  this . typeWeights [ node . operation ] . weight ; 
257-  // console.log(`the weight of ${node.operation} is ${complexity}`); 
258-  // call the function to handle selection set node with selectionSet property if it is not undefined 
259257 if  ( node . selectionSet )  { 
260258 complexity  +=  this . selectionSetNode ( node . selectionSet ,  node . operation ) ; 
261259 } 
262260 } 
263261 }  else  if  ( node . kind  ===  Kind . FRAGMENT_DEFINITION )  { 
264262 // Fragments can only be defined on the root type. 
265-  // Parse the complexity of this fragment once and store it for use when analyzing other 
266-  // nodes. The complexity of a fragment can be added to the selection cost for the query. 
263+  // Parse the complexity of this fragment once and store it for use when analyzing other nodes 
267264 const  namedType  =  node . typeCondition . name . value ; 
268265 // Duplicate fragment names are not allowed by the GraphQL spec and an error is thrown if used. 
269266 const  fragmentName  =  node . name . value ; 
@@ -276,10 +273,12 @@ class ASTParser {
276273 // Don't count fragment complexity in the node's complexity. Only when fragment is used. 
277274 this . fragmentCache [ fragmentName ]  =  { 
278275 complexity : fragmentComplexity , 
279-  depth : this . maxDepth  -  1 ,  // subtract one from the calculated depth of the fragment to correct for the additional depth the fragment ads  to the query when used 
276+  depth : this . maxDepth  -  1 ,  // subtract one from the calculated depth of the fragment to correct for the additional depth the fragment adds  to the query when used 
280277 } ; 
281-  }  // else { 
282-  // // TODO: Verify that are no other type definition nodes that need to be handled (see ast.d.ts in 'graphql') 
278+  } 
279+  // TODO: Verify that there are no other type definition nodes that need to be handled (see ast.d.ts in 'graphql') 
280+  // else { 
281+  // 
283282 // // Other types include TypeSystemDefinitionNode (Schema, Type, Directvie) and 
284283 // // TypeSystemExtensionNode(Schema, Type); 
285284 // throw new Error(`ERROR: ASTParser.definitionNode: ${node.kind} type not supported`); 
@@ -289,21 +288,20 @@ class ASTParser {
289288
290289 private  documentNode ( node : DocumentNode ) : number  { 
291290 let  complexity  =  0 ; 
292-  // sort  the definitions array by kind so that fragments are always parsed first. 
291+  // Sort  the definitions array by kind so that fragments are always parsed first. 
293292 // Fragments must be parsed first so that their complexity is available to other nodes. 
294293 const  sortedDefinitions  =  [ ...node . definitions ] . sort ( ( a ,  b )  => 
295294 a . kind . localeCompare ( b . kind ) 
296295 ) ; 
297296 for  ( let  i  =  0 ;  i  <  sortedDefinitions . length ;  i  +=  1 )  { 
298-  // call the function to handle the various types of definition nodes 
299297 complexity  +=  this . definitionNode ( sortedDefinitions [ i ] ) ; 
300298 } 
301299 return  complexity ; 
302300 } 
303301
304-  processQuery ( queryAST : DocumentNode ) : number  { 
302+  public processQuery ( queryAST : DocumentNode ) : number  { 
305303 return  this . documentNode ( queryAST ) ; 
306304 } 
307305} 
308306
309- export  default  ASTParser ; 
307+ export  default  ComplexityAnalysis ; 
0 commit comments