Skip to content

Commit 7d045b1

Browse files
committed
Add handling for invalid argument values, error reporting in getComplexity function #61
1 parent a940f94 commit 7d045b1

File tree

4 files changed

+71
-21
lines changed

4 files changed

+71
-21
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
node_modules
33
.DS_Store
44
.idea
5+
.vscode

README.md

+15-10
Original file line numberDiff line numberDiff line change
@@ -171,16 +171,21 @@ const query = parse(`
171171
}
172172
`);
173173

174-
const complexity = getComplexity({
175-
estimators: [simpleEstimator({ defaultComplexity: 1 })],
176-
schema,
177-
query,
178-
variables: {
179-
count: 10,
180-
},
181-
});
182-
183-
console.log(complexity); // Output: 3
174+
try {
175+
const complexity = getComplexity({
176+
estimators: [simpleEstimator({ defaultComplexity: 1 })],
177+
schema,
178+
query,
179+
variables: {
180+
count: 10,
181+
},
182+
});
183+
184+
console.log(complexity); // Output: 3
185+
} catch (e) {
186+
// Log error in case complexity cannot be calculated (invalid query, misconfiguration, etc.)
187+
console.error('Could not calculate complexity', e.message);
188+
}
184189
```
185190

186191
## Prior Art

src/QueryComplexity.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,12 @@ export function getComplexity(options: {
9696
}): number {
9797
const typeInfo = new TypeInfo(options.schema);
9898

99+
const errors: GraphQLError[] = [];
99100
const context = new ValidationContext(
100101
options.schema,
101102
options.query,
102103
typeInfo,
103-
() => null
104+
(error) => errors.push(error)
104105
);
105106
const visitor = new QueryComplexity(context, {
106107
// Maximum complexity does not matter since we're only interested in the calculated complexity.
@@ -111,6 +112,12 @@ export function getComplexity(options: {
111112
});
112113

113114
visit(options.query, visitWithTypeInfo(typeInfo, visitor));
115+
116+
// Throw first error if any
117+
if (errors.length) {
118+
throw errors.pop();
119+
}
120+
114121
return visitor.complexity;
115122
}
116123

@@ -244,7 +251,7 @@ export default class QueryComplexity {
244251
(
245252
complexities: ComplexityMap,
246253
childNode: FieldNode | FragmentSpreadNode | InlineFragmentNode
247-
) => {
254+
): ComplexityMap => {
248255
// let nodeComplexity = 0;
249256
let innerComplexities = complexities;
250257

@@ -297,7 +304,8 @@ export default class QueryComplexity {
297304
this.variableValues || {}
298305
);
299306
} catch (e) {
300-
return this.context.reportError(e);
307+
this.context.reportError(e);
308+
return complexities;
301309
}
302310

303311
// Check if we have child complexity

src/__tests__/QueryComplexity-test.ts

+44-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22
* Created by Ivo Meißner on 28.07.17.
33
*/
44

5-
import { parse, TypeInfo, visit, visitWithTypeInfo } from 'graphql';
5+
import {
6+
parse,
7+
TypeInfo,
8+
visit,
9+
visitWithTypeInfo,
10+
validate,
11+
specifiedRules,
12+
} from 'graphql';
613

714
import { expect } from 'chai';
815

@@ -523,7 +530,7 @@ describe('QueryComplexity analysis', () => {
523530
);
524531
});
525532

526-
it('should return NaN when no astNode available on field when using directiveEstimator', () => {
533+
it('should throw error when no astNode available on field when using directiveEstimator', () => {
527534
const ast = parse(`
528535
query {
529536
_service {
@@ -532,12 +539,13 @@ describe('QueryComplexity analysis', () => {
532539
}
533540
`);
534541

535-
const complexity = getComplexity({
536-
estimators: [directiveEstimator()],
537-
schema,
538-
query: ast,
539-
});
540-
expect(Number.isNaN(complexity)).to.equal(true);
542+
expect(() => {
543+
getComplexity({
544+
estimators: [directiveEstimator()],
545+
schema,
546+
query: ast,
547+
});
548+
}).to.throw(/No complexity could be calculated for field Query._service/);
541549
});
542550

543551
it('should skip complexity calculation by directiveEstimator when no astNode available on field', () => {
@@ -796,4 +804,32 @@ describe('QueryComplexity analysis', () => {
796804
});
797805
expect(complexity).to.equal(30); // 3 fields on nonNullItem * 10
798806
});
807+
808+
it('should handle invalid argument values for multiple query fields', () => {
809+
const ast = parse(`
810+
query {
811+
requiredArgs(count: x) {
812+
scalar
813+
complexScalar
814+
}
815+
nonNullItem {
816+
scalar
817+
complexScalar
818+
variableScalar(count: 10)
819+
}
820+
}
821+
`);
822+
823+
validate(schema, ast, [
824+
...specifiedRules,
825+
createComplexityRule({
826+
maximumComplexity: 1000,
827+
estimators: [
828+
simpleEstimator({
829+
defaultComplexity: 1,
830+
}),
831+
],
832+
}),
833+
]);
834+
});
799835
});

0 commit comments

Comments
 (0)