@@ -6,25 +6,9 @@ import {
66 DefinitionNode ,
77 Kind ,
88 SelectionNode ,
9- ArgumentNode ,
9+ isConstValueNode ,
1010} from 'graphql' ;
1111import { FieldWeight , TypeWeightObject , Variables } from '../@types/buildTypeWeights' ;
12-
13- // TODO: handle variables and arguments
14- // ! this is not functional
15- const getArgObj = ( args : ArgumentNode [ ] ) : { [ index : string ] : any } => {
16- const argObj : { [ index : string ] : any } = { } ;
17- for ( let i = 0 ; i < args . length ; i + 1 ) {
18- const node = args [ i ] ;
19- if ( args [ i ] . value . kind !== Kind . VARIABLE ) {
20- if ( args [ i ] . value . kind === Kind . INT ) {
21- // FIXME: this does not work
22- argObj [ args [ i ] . name . value ] = args [ i ] . value ;
23- }
24- }
25- }
26- return argObj ;
27- } ;
2812/**
2913 * The AST node functions call each other following the nested structure below
3014 * Each function handles a specific GraphQL AST node type
@@ -52,34 +36,39 @@ export function fieldNode(
5236 parentName : string
5337) : number {
5438 let complexity = 0 ;
55- // console.log('fieldNode', node, parentName);
56- // check if the field name is in the type weight object.
57- if ( node . name . value . toLocaleLowerCase ( ) in typeWeights ) {
58- // if it is, than the field is an object type, add itss type weight to the total
59- complexity += typeWeights [ node . name . value ] . weight ;
39+ // 'resolvedTypeName' is the name of the Schema Type that this field resolves to
40+ const resolvedTypeName =
41+ node . name . value in typeWeights
42+ ? node . name . value
43+ : typeWeights [ parentName ] . fields [ node . name . value ] ?. resolveTo || null ;
44+
45+ if ( resolvedTypeName ) {
46+ // field resolves to an object or a list with possible selections
47+ let selectionsCost = 0 ;
48+ let calculatedWeight = 0 ;
49+ const weightFunction = typeWeights [ parentName ] ?. fields [ node . name . value ] ?. weight ;
50+
6051 // call the function to handle selection set node with selectionSet property if it is not undefined
6152 if ( node . selectionSet ) {
62- complexity += selectionSetNode (
53+ selectionsCost += selectionSetNode (
6354 node . selectionSet ,
6455 typeWeights ,
6556 variables ,
66- node . name . value
57+ resolvedTypeName
6758 ) ;
6859 }
60+ // if there are arguments and this is a list, call the 'weightFunction' to get the weight of this field. otherwise the weight is static and can be accessed through the typeWeights object
61+ if ( node . arguments && typeof weightFunction === 'function' ) {
62+ calculatedWeight += weightFunction ( [ ...node . arguments ] , variables , selectionsCost ) ;
63+ } else {
64+ calculatedWeight += typeWeights [ resolvedTypeName ] . weight + selectionsCost ;
65+ }
66+ complexity += calculatedWeight ;
6967 } else {
70- // otherwise the field is a scalar or a list.
71- const fieldWeight : FieldWeight = typeWeights [ parentName ] . fields [ node . name . value ] ;
72- if ( typeof fieldWeight === 'number' ) {
73- // if the feild weight is a number, add the number to the total complexity
74- complexity += fieldWeight ;
75- } else if ( node . arguments ) {
76- // BUG: This code is reached when fieldWeight is undefined, which could result from an invalid query or this type
77- // missing from the typeWeight object. If left unhandled an error is thrown
78- // otherwise the the feild weight is a list, invoke the function with variables
79- // TODO: calculate the complexity for lists with arguments and varibales
80- // ! this is not functional
81- // iterate through the arguments to build the object to
82- complexity += fieldWeight ( [ ...node . arguments ] ) ;
68+ // field is a scalar and 'weight' is a number
69+ const { weight } = typeWeights [ parentName ] . fields [ node . name . value ] ;
70+ if ( typeof weight === 'number' ) {
71+ complexity += weight ;
8372 }
8473 }
8574 return complexity ;
@@ -92,7 +81,6 @@ export function selectionNode(
9281 parentName : string
9382) : number {
9483 let complexity = 0 ;
95- // console.log('selectionNode', node, parentName);
9684 // check the kind property against the set of selection nodes that are possible
9785 if ( node . kind === Kind . FIELD ) {
9886 // call the function that handle field nodes
@@ -101,7 +89,6 @@ export function selectionNode(
10189 // TODO: add checks for Kind.FRAGMENT_SPREAD and Kind.INLINE_FRAGMENT here
10290 return complexity ;
10391}
104-
10592export function selectionSetNode (
10693 node : SelectionSetNode ,
10794 typeWeights : TypeWeightObject ,
@@ -130,14 +117,16 @@ export function definitionNode(
130117 if ( node . operation . toLocaleLowerCase ( ) in typeWeights ) {
131118 // if it is, it is an object type, add it's type weight to the total
132119 complexity += typeWeights [ node . operation ] . weight ;
120+ // console.log(`the weight of ${node.operation} is ${complexity}`);
133121 // call the function to handle selection set node with selectionSet property if it is not undefined
134- if ( node . selectionSet )
122+ if ( node . selectionSet ) {
135123 complexity += selectionSetNode (
136124 node . selectionSet ,
137125 typeWeights ,
138126 variables ,
139127 node . operation
140128 ) ;
129+ }
141130 }
142131 }
143132 // TODO: add checks for Kind.FRAGMENT_DEFINITION here (there are other type definition nodes that i think we can ignore. see ast.d.ts in 'graphql')
0 commit comments