1- import { query } from 'express' ;
21import { ASTNode , DocumentNode , Kind } from 'graphql' ;
32
43/**
5- * This function should
6- * 1. validate the query using graphql methods
7- * 2. parse the query string using the graphql parse method
8- * 3. itreate through the query AST and
9- * - cross reference the type weight object to check type weight
10- * - total all the eweights of all types in the query
11- * 4. return the total as the query complexity
4+ * Calculate the complexity for the query by recursivly traversing through the query AST,
5+ * checking the query fields against the type weight object and totaling the weights of every field.
126 *
13- * TO DO: extend the functionality to work for mutations and subscriptions
7+ * TO DO: extend the functionality to work for mutations and subscriptions and directives
148 *
159 * @param {string } queryAST
1610 * @param {any | undefined } varibales
@@ -22,75 +16,52 @@ function getQueryTypeComplexity(
2216 varibales : any | undefined ,
2317 typeWeights : TypeWeightObject
2418) : number {
25- const recursive = ( node : ASTNode , parent : ASTNode | null = null ) : number => {
26- /**
27- * pseudo code of the process
28- *
29- // if 'kind' property is 'Document'
30- // iterate through queryAST.definitions array
31- // call recursive with object
32-
33- // if 'kind' property is 'operationDefinition'
34- // check 'operation' value against the type weights and add to total
35- // call recursive with selectionSet property if it is not undefined
36-
37- // if 'kind' is 'selectionSet'
38- // iterate shrough the 'selections' array of fields
39- // if 'selectinSet' is not undefined, call recursive with the field
40-
41- // if 'kind' property is 'feild'
42- // check the fields name.value against the type weights and total
43- // if there is a match, it is an objcet type with feilds,
44- // call recursive with selectionSet property if it is not undefined
45- // if it is not a match, it is a scalar field, look in the parent.name.value to check type weights feilds
46- */
47-
19+ const getComplexityOfNode = ( node : ASTNode , parent : ASTNode = node ) : number => {
4820 let complexity = 0 ;
49- const parentName : string = parent ?. operation || parent ?. name . value || null ;
5021
5122 if ( node . kind === Kind . DOCUMENT ) {
5223 // if 'kind' property is a 'Document'
5324 // iterate through queryAST.definitions array
5425 for ( let i = 0 ; i < node . definitions . length ; i + 1 ) {
5526 // call recursive with the definition node
56- complexity += recursive ( node . definitions [ i ] , node ) ;
27+ complexity += getComplexityOfNode ( node . definitions [ i ] , node ) ;
5728 }
5829 } else if ( node . kind === Kind . OPERATION_DEFINITION ) {
5930 // if 'kind' property is 'operationDefinition'
6031 // TODO: case-sensitive
61- if ( node . operation in typeWeights ) {
32+ if ( node . operation . toLocaleLowerCase ( ) in typeWeights ) {
6233 // check 'operation' value against the type weights and add to total
6334 complexity += typeWeights [ node . operation ] . weight ;
6435 // call recursive with selectionSet property if it is not undefined
65- if ( node . selectionSet ) complexity += recursive ( node . selectionSet , node ) ;
36+ if ( node . selectionSet ) complexity += getComplexityOfNode ( node . selectionSet , node ) ;
6637 }
6738 } else if ( node . kind === Kind . SELECTION_SET ) {
6839 // if 'kind' is 'selectionSet'
6940 // iterate shrough the 'selections' array of fields
7041 for ( let i = 0 ; i < node . selections . length ; i + 1 ) {
7142 // call recursive with the field
72- complexity += recursive ( node . selections [ i ] , parent ) ; // passing the current parent through because selection sets act only as intermediaries
43+ complexity += getComplexityOfNode ( node . selections [ i ] , parent ) ; // passing the current parent through because selection sets act only as intermediaries
7344 }
7445 } else if ( node . kind === Kind . FIELD ) {
7546 // if 'kind' property is 'field'
7647 // check the fields name.value against the type weights and total
7748 // TODO: case-sensitive
78- if ( node . name . value in typeWeights ) {
49+ if ( node . name . value . toLocaleLowerCase ( ) in typeWeights ) {
7950 // if there is a match, it is an objcet type with feilds,
8051 complexity += typeWeights [ node . name . value ] . weight ;
8152 // call recursive with selectionSet property if it is not undefined
82- if ( node . selectionSet ) complexity += recursive ( node . selectionSet , node ) ;
53+ if ( node . selectionSet ) complexity += getComplexityOfNode ( node . selectionSet , node ) ;
8354 // node.name.value in typeWeights[parent.operation || parent.name.value].fields
84- } else if ( parent ?. opeartion ) {
85- // if it is not a match, it is a scalar field, look in the parent.name.value to check type weights feilds
86- // TODO: if it is a list, need to look at the parent
87- complexity += typeWeights [ parent . name . value ] . fields [ node . name . value ] ;
55+ } else {
56+ // TODO: if it is not a match, it is a scalar field or list,
57+ // if (parent?.objective !== null) {
58+ // }
59+ // const weight = typeWeights[parent.name.value].fields[node.name.value];
8860 }
8961 }
90-
9162 return complexity ;
9263 } ;
93- return recursive ( queryAST ) ;
64+ return getComplexityOfNode ( queryAST ) ;
9465}
9566
9667export default getQueryTypeComplexity ;
0 commit comments