Skip to content

Commit cb183c0

Browse files
committed
started to refactor the complexity analysis to use seperate functions for every type of node
1 parent 610d7b5 commit cb183c0

File tree

2 files changed

+95
-47
lines changed

2 files changed

+95
-47
lines changed

src/analysis/ASTnodefunctions.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import {
2+
DocumentNode,
3+
FieldNode,
4+
SelectionSetNode,
5+
DefinitionNode,
6+
Kind,
7+
SelectionNode,
8+
} from 'graphql';
9+
10+
export function fieldNode(
11+
node: FieldNode,
12+
typeWeights: TypeWeightObject,
13+
variables: any | undefined,
14+
parent: FieldNode | DefinitionNode
15+
): number {
16+
const complexity = 0;
17+
return complexity;
18+
}
19+
20+
export function selectionNode(
21+
node: SelectionNode,
22+
typeWeights: TypeWeightObject,
23+
variables: any | undefined,
24+
parent: DefinitionNode | FieldNode
25+
): number {
26+
let complexity = 0;
27+
// check the kind property against the set of selection nodes that are possible
28+
if (node.kind === Kind.FIELD) {
29+
// call the function that handle field nodes and multiply the result into complexity to accound for nested fields
30+
complexity *= fieldNode(node, typeWeights, variables, parent);
31+
}
32+
// TODO: add checks for Kind.FRAGMENT_SPREAD and Kind.INLINE_FRAGMENT here
33+
return complexity;
34+
}
35+
36+
export function selectionSetNode(
37+
node: SelectionSetNode,
38+
typeWeights: TypeWeightObject,
39+
variables: any | undefined,
40+
parent: DefinitionNode | FieldNode
41+
): number {
42+
let complexity = 0;
43+
// iterate shrough the 'selections' array on the seletion set node
44+
for (let i = 0; i < node.selections.length; i + 1) {
45+
// call the function to handle seletion nodes
46+
// pass the current parent through because selection sets act only as intermediaries
47+
complexity += selectionNode(node.selections[i], typeWeights, variables, parent);
48+
}
49+
return complexity;
50+
}
51+
52+
export function definitionNode(
53+
node: DefinitionNode,
54+
typeWeights: TypeWeightObject,
55+
variables: any | undefined
56+
): number {
57+
let complexity = 0;
58+
// check the kind property against the set of definiton nodes that are possible
59+
if (node.kind === Kind.OPERATION_DEFINITION) {
60+
// check if the operation is in the type weights object.
61+
if (node.operation.toLocaleLowerCase() in typeWeights) {
62+
// if it is, it is an object type, add it's type weight to the total
63+
complexity += typeWeights[node.operation].weight;
64+
// call the function to handle selection set node with selectionSet property if it is not undefined
65+
if (node.selectionSet)
66+
complexity += selectionSetNode(node.selectionSet, typeWeights, variables, node);
67+
}
68+
}
69+
// 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')
70+
return complexity;
71+
}
72+
73+
export function documentNode(
74+
node: DocumentNode,
75+
typeWeights: TypeWeightObject,
76+
variables: any | undefined
77+
): number {
78+
let complexity = 0;
79+
// iterate through 'definitions' array on the document node
80+
for (let i = 0; i < node.definitions.length; i + 1) {
81+
// call the function to handle the various types of definition nodes
82+
complexity += definitionNode(node.definitions[i], typeWeights, variables);
83+
}
84+
return complexity;
85+
}
Lines changed: 10 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
import { ASTNode, DocumentNode, Kind } from 'graphql';
2+
import {
3+
selectionSetNode,
4+
fieldNode,
5+
documentNode,
6+
operationDefinitionNode,
7+
} from './ASTnodefunctions';
28

39
/**
410
* Calculate the complexity for the query by recursivly traversing through the query AST,
@@ -13,55 +19,12 @@ import { ASTNode, DocumentNode, Kind } from 'graphql';
1319
// TODO add queryVaribables parameter
1420
function getQueryTypeComplexity(
1521
queryAST: DocumentNode,
16-
varibales: any | undefined,
22+
variables: any | undefined,
1723
typeWeights: TypeWeightObject
1824
): number {
19-
const getComplexityOfNode = (node: ASTNode, parent: ASTNode = node): number => {
20-
let complexity = 0;
21-
22-
if (node.kind === Kind.DOCUMENT) {
23-
// if 'kind' property is a 'Document'
24-
// iterate through queryAST.definitions array
25-
for (let i = 0; i < node.definitions.length; i + 1) {
26-
// call recursive with the definition node
27-
complexity += getComplexityOfNode(node.definitions[i], node);
28-
}
29-
} else if (node.kind === Kind.OPERATION_DEFINITION) {
30-
// if 'kind' property is 'operationDefinition'
31-
// TODO: case-sensitive
32-
if (node.operation.toLocaleLowerCase() in typeWeights) {
33-
// check 'operation' value against the type weights and add to total
34-
complexity += typeWeights[node.operation].weight;
35-
// call recursive with selectionSet property if it is not undefined
36-
if (node.selectionSet) complexity += getComplexityOfNode(node.selectionSet, node);
37-
}
38-
} else if (node.kind === Kind.SELECTION_SET) {
39-
// if 'kind' is 'selectionSet'
40-
// iterate shrough the 'selections' array of fields
41-
for (let i = 0; i < node.selections.length; i + 1) {
42-
// call recursive with the field
43-
complexity += getComplexityOfNode(node.selections[i], parent); // passing the current parent through because selection sets act only as intermediaries
44-
}
45-
} else if (node.kind === Kind.FIELD) {
46-
// if 'kind' property is 'field'
47-
// check the fields name.value against the type weights and total
48-
// TODO: case-sensitive
49-
if (node.name.value.toLocaleLowerCase() in typeWeights) {
50-
// if there is a match, it is an objcet type with feilds,
51-
complexity += typeWeights[node.name.value].weight;
52-
// call recursive with selectionSet property if it is not undefined
53-
if (node.selectionSet) complexity += getComplexityOfNode(node.selectionSet, node);
54-
// node.name.value in typeWeights[parent.operation || parent.name.value].fields
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];
60-
}
61-
}
62-
return complexity;
63-
};
64-
return getComplexityOfNode(queryAST);
25+
let complexity = 0;
26+
complexity += documentNode(queryAST, typeWeights, variables);
27+
return complexity;
6528
}
6629

6730
export default getQueryTypeComplexity;

0 commit comments

Comments
 (0)