@@ -85,6 +85,11 @@ export interface QueryComplexityOptions {
8585
8686 // Pass request context to the estimators via estimationContext
8787 context ?: Record < string , any > ;
88+
89+ // The maximum number of nodes to evaluate. If this is set, the query will be
90+ // rejected if it exceeds this number. (Includes fields, fragments, inline fragments, etc.)
91+ // Defaults to 10_000.
92+ maxQueryNodes ?: number ;
8893}
8994
9095function queryComplexityMessage ( max : number , actual : number ) : string {
@@ -101,6 +106,7 @@ export function getComplexity(options: {
101106 variables ?: Record < string , any > ;
102107 operationName ?: string ;
103108 context ?: Record < string , any > ;
109+ maxQueryNodes ?: number ;
104110} ) : number {
105111 const typeInfo = new TypeInfo ( options . schema ) ;
106112
@@ -118,6 +124,7 @@ export function getComplexity(options: {
118124 variables : options . variables ,
119125 operationName : options . operationName ,
120126 context : options . context ,
127+ maxQueryNodes : options . maxQueryNodes ,
121128 } ) ;
122129
123130 visit ( options . query , visitWithTypeInfo ( typeInfo , visitor ) ) ;
@@ -140,6 +147,8 @@ export default class QueryComplexity {
140147 skipDirectiveDef : GraphQLDirective ;
141148 variableValues : Record < string , any > ;
142149 requestContext ?: Record < string , any > ;
150+ evaluatedNodes : number ;
151+ maxQueryNodes : number ;
143152
144153 constructor ( context : ValidationContext , options : QueryComplexityOptions ) {
145154 if (
@@ -154,7 +163,8 @@ export default class QueryComplexity {
154163 this . context = context ;
155164 this . complexity = 0 ;
156165 this . options = options ;
157-
166+ this . evaluatedNodes = 0 ;
167+ this . maxQueryNodes = options . maxQueryNodes ?? 10_000 ;
158168 this . includeDirectiveDef = this . context . getSchema ( ) . getDirective ( 'include' ) ;
159169 this . skipDirectiveDef = this . context . getSchema ( ) . getDirective ( 'skip' ) ;
160170 this . estimators = options . estimators ;
@@ -274,7 +284,12 @@ export default class QueryComplexity {
274284 complexities : ComplexityMap ,
275285 childNode : FieldNode | FragmentSpreadNode | InlineFragmentNode
276286 ) : ComplexityMap => {
277- // let nodeComplexity = 0;
287+ this . evaluatedNodes ++ ;
288+ if ( this . evaluatedNodes >= this . maxQueryNodes ) {
289+ throw new GraphQLError (
290+ 'Query exceeds the maximum allowed number of nodes.'
291+ ) ;
292+ }
278293 let innerComplexities = complexities ;
279294
280295 let includeNode = true ;
0 commit comments