Skip to content

Commit a822992

Browse files
authored
Add a context option for passing the request context to estimators (#77)
* Add a context option for passing the request context to estimators * Fix tests
1 parent d59c636 commit a822992

File tree

4 files changed

+49
-8
lines changed

4 files changed

+49
-8
lines changed

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ const rule = createComplexityRule({
3838
// in the visitor of the graphql-js library
3939
variables: {},
4040

41+
// The context object for the request (optional)
42+
context: {}
43+
4144
// specify operation name only when pass multi-operation documents
4245
operationName?: string,
4346

@@ -110,6 +113,9 @@ type ComplexityEstimatorArgs = {
110113

111114
// The complexity of all child selections for that field
112115
childComplexity: number;
116+
117+
// The context object for the request if it was provided
118+
context?: Record<string, any>;
113119
};
114120

115121
type ComplexityEstimator = (options: ComplexityEstimatorArgs) => number | void;

src/QueryComplexity.ts

+9
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export type ComplexityEstimatorArgs = {
4343
node: FieldNode;
4444
args: { [key: string]: any };
4545
childComplexity: number;
46+
context?: Record<string, any>;
4647
};
4748

4849
export type ComplexityEstimator = (
@@ -78,6 +79,9 @@ export interface QueryComplexityOptions {
7879

7980
// An array of complexity estimators to use for estimating the complexity
8081
estimators: Array<ComplexityEstimator>;
82+
83+
// Pass request context to the estimators via estimationContext
84+
context?: Record<string, any>;
8185
}
8286

8387
function queryComplexityMessage(max: number, actual: number): string {
@@ -93,6 +97,7 @@ export function getComplexity(options: {
9397
query: DocumentNode;
9498
variables?: Record<string, any>;
9599
operationName?: string;
100+
context?: Record<string, any>;
96101
}): number {
97102
const typeInfo = new TypeInfo(options.schema);
98103

@@ -109,6 +114,7 @@ export function getComplexity(options: {
109114
estimators: options.estimators,
110115
variables: options.variables,
111116
operationName: options.operationName,
117+
context: options.context,
112118
});
113119

114120
visit(options.query, visitWithTypeInfo(typeInfo, visitor));
@@ -130,6 +136,7 @@ export default class QueryComplexity {
130136
includeDirectiveDef: GraphQLDirective;
131137
skipDirectiveDef: GraphQLDirective;
132138
variableValues: Record<string, any>;
139+
requestContext?: Record<string, any>;
133140

134141
constructor(context: ValidationContext, options: QueryComplexityOptions) {
135142
if (
@@ -149,6 +156,7 @@ export default class QueryComplexity {
149156
this.skipDirectiveDef = this.context.getSchema().getDirective('skip');
150157
this.estimators = options.estimators;
151158
this.variableValues = {};
159+
this.requestContext = options.context;
152160

153161
this.OperationDefinition = {
154162
enter: this.onOperationDefinitionEnter,
@@ -327,6 +335,7 @@ export default class QueryComplexity {
327335
field,
328336
node: childNode,
329337
type: typeDef,
338+
context: this.requestContext,
330339
};
331340
const validScore = this.estimators.find((estimator) => {
332341
const tmpComplexity = estimator(estimatorArgs);

src/__tests__/QueryComplexity-test.ts

+31-3
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ describe('QueryComplexity analysis', () => {
639639
...on Union {
640640
...on Item {
641641
complexScalar1: complexScalar
642-
}
642+
}
643643
}
644644
...on SecondItem {
645645
scalar
@@ -678,7 +678,7 @@ describe('QueryComplexity analysis', () => {
678678
fragment F on Union {
679679
...on Item {
680680
complexScalar1: complexScalar
681-
}
681+
}
682682
}
683683
`);
684684

@@ -759,7 +759,7 @@ describe('QueryComplexity analysis', () => {
759759
}
760760
}
761761
}
762-
762+
763763
fragment F on Query {
764764
complexScalar
765765
...on Query {
@@ -832,4 +832,32 @@ describe('QueryComplexity analysis', () => {
832832
}),
833833
]);
834834
});
835+
836+
it('passed context to estimators', () => {
837+
const ast = parse(`
838+
query {
839+
scalar
840+
requiredArgs(count: 10) {
841+
scalar
842+
}
843+
}
844+
`);
845+
846+
const contextEstimator: ComplexityEstimator = ({
847+
context,
848+
childComplexity,
849+
}) => {
850+
return context['complexityMultiplier'] * (childComplexity || 1);
851+
};
852+
853+
const complexity = getComplexity({
854+
estimators: [contextEstimator],
855+
schema,
856+
query: ast,
857+
context: { complexityMultiplier: 5 },
858+
});
859+
860+
// query.scalar(5) + query.requiredArgs(5) * requiredArgs.scalar(5)
861+
expect(complexity).to.equal(30);
862+
});
835863
});

src/__tests__/utils/compatResolveType.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import { GraphQLType } from 'graphql';
2-
3-
import graphqlPackage from 'graphql/package.json';
1+
import * as graphql from 'graphql';
42
import semver from 'semver';
53

64
/**
@@ -10,8 +8,8 @@ import semver from 'semver';
108
* @param type
119
* @returns
1210
*/
13-
export function compatResolveType(type: GraphQLType): any {
14-
if (semver.gte(graphqlPackage.version, '16.0.0')) {
11+
export function compatResolveType(type: graphql.GraphQLType): any {
12+
if (graphql.version && semver.gte(graphql.version, '16.0.0')) {
1513
return () => type.toString();
1614
} else {
1715
return () => type;

0 commit comments

Comments
 (0)