Skip to content

Commit 60ab617

Browse files
committed
Merge branch 'rh389-feature/graphql-15-compat'
2 parents e35ccd3 + bffa43f commit 60ab617

File tree

20 files changed

+114
-1158
lines changed

20 files changed

+114
-1158
lines changed

.circleci/config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ workflows:
1212
# definitions for field extensions in older @types/graphql versions
1313
matrix:
1414
parameters:
15-
graphql-version: ["~0.13", "~14.0", "~14.5", "~14.6"]
15+
graphql-version: ["~0.13", "~14.0", "~14.5", "~14.6", "~15.0"]
1616
- test-and-build:
1717
# Leave graphql-version unspecified to respect the lockfile and also run tsc
1818
name: test-and-build-with-typecheck

README.md

-4
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,6 @@ or write your own:
8383
schema definition (for example via GraphQL SDL)
8484
* **[`fieldExtensionsEstimator`](src/estimators/fieldExtensions/README.md):** The field extensions estimator lets you set a numeric value or a custom estimator
8585
function in the field config extensions of your schema.
86-
* **[`fieldConfigEstimator`](src/estimators/fieldConfig/README.md):** (DEPRECATED) The field config estimator lets you set a numeric value or a custom estimator
87-
function in the field config of your schema.
88-
* **[`legacyEstimator`](src/estimators/legacy/README.md):** (DEPRECATED) The legacy estimator implements the logic of previous versions. Can be used
89-
to gradually migrate your codebase to new estimators.
9086
* PRs welcome...
9187

9288
Consult the documentation of each estimator for information about how to use them.

package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"lodash.get": "^4.4.2"
2121
},
2222
"peerDependencies": {
23-
"graphql": "^0.13.0 || ^14.0.0"
23+
"graphql": "^0.13.0 || ^14.0.0 || ^15.0.0"
2424
},
2525
"files": [
2626
"dist",
@@ -41,14 +41,13 @@
4141
"devDependencies": {
4242
"@types/assert": "^1.4.6",
4343
"@types/chai": "^4.2.11",
44-
"@types/graphql": "^0.13.0 || ^14.0.0",
4544
"@types/lodash.get": "^4.4.6",
4645
"@types/mocha": "^7.0.2",
4746
"@typescript-eslint/eslint-plugin": "^2.27.0",
4847
"@typescript-eslint/parser": "^2.27.0",
4948
"chai": "^4.2.0",
5049
"eslint": "^6.8.0",
51-
"graphql": "^0.13.0 || ^14.0.0",
50+
"graphql": "^14.5.0 || ^15.0.0",
5251
"mocha": "^7.1.1",
5352
"rimraf": "^3.0.2",
5453
"ts-node": "^8.8.2",

src/QueryComplexity.ts

+4-18
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ import {
2929
getNamedType,
3030
GraphQLError
3131
} from 'graphql';
32-
import {
33-
simpleEstimator,
34-
legacyEstimator
35-
} from './estimators';
3632

3733
declare module 'graphql/type/definition' {
3834
export interface GraphQLField<TSource, TContext, TArgs = { [argName: string]: any }> {
@@ -72,7 +68,7 @@ export interface QueryComplexityOptions {
7268
createError?: (max: number, actual: number) => GraphQLError,
7369

7470
// An array of complexity estimators to use for estimating the complexity
75-
estimators?: Array<ComplexityEstimator>;
71+
estimators: Array<ComplexityEstimator>;
7672
}
7773

7874
function queryComplexityMessage(max: number, actual: number): string {
@@ -91,7 +87,7 @@ export function getComplexity(options: {
9187
}): number {
9288
const typeInfo = new TypeInfo(options.schema);
9389

94-
const context = new ValidationContext(options.schema, options.query, typeInfo);
90+
const context = new ValidationContext(options.schema, options.query, typeInfo, () => null);
9591
const visitor = new QueryComplexity(context, {
9692
// Maximum complexity does not matter since we're only interested in the calculated complexity.
9793
maximumComplexity: Infinity,
@@ -127,17 +123,7 @@ export default class QueryComplexity {
127123

128124
this.includeDirectiveDef = this.context.getSchema().getDirective('include');
129125
this.skipDirectiveDef = this.context.getSchema().getDirective('skip');
130-
131-
if (!options.estimators) {
132-
console.warn(
133-
'DEPRECATION WARNING: Estimators should be configured in the queryComplexity options.'
134-
);
135-
}
136-
137-
this.estimators = options.estimators || [
138-
legacyEstimator(),
139-
simpleEstimator()
140-
];
126+
this.estimators = options.estimators
141127

142128
this.OperationDefinition = {
143129
enter: this.onOperationDefinitionEnter,
@@ -178,7 +164,7 @@ export default class QueryComplexity {
178164
if (typeof this.options.operationName === 'string' && this.options.operationName !== operation.name.value) {
179165
return;
180166
}
181-
167+
182168
if (this.options.onComplete) {
183169
this.options.onComplete(this.complexity);
184170
}

src/__tests__/QueryComplexity-test.ts

+25-25
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import {
66
parse,
77
TypeInfo,
8-
ValidationContext,
98
visit,
109
visitWithTypeInfo,
1110
} from 'graphql';
@@ -18,8 +17,9 @@ import ComplexityVisitor, {getComplexity} from '../QueryComplexity';
1817
import {
1918
simpleEstimator,
2019
directiveEstimator,
21-
fieldConfigEstimator,
20+
fieldExtensionsEstimator,
2221
} from '../index';
22+
import { CompatibleValidationContext } from './fixtures/CompatibleValidationContext';
2323

2424
describe('QueryComplexity analysis', () => {
2525
const typeInfo = new TypeInfo(schema);
@@ -135,7 +135,7 @@ describe('QueryComplexity analysis', () => {
135135

136136
const complexity = getComplexity({
137137
estimators: [
138-
fieldConfigEstimator(),
138+
fieldExtensionsEstimator(),
139139
simpleEstimator({defaultComplexity: 1})
140140
],
141141
schema,
@@ -154,7 +154,7 @@ describe('QueryComplexity analysis', () => {
154154
}
155155
`);
156156

157-
const context = new ValidationContext(schema, ast, typeInfo);
157+
const context = new CompatibleValidationContext(schema, ast, typeInfo);
158158
const visitor = new ComplexityVisitor(context, {
159159
maximumComplexity: 100,
160160
estimators: [
@@ -173,11 +173,11 @@ describe('QueryComplexity analysis', () => {
173173
}
174174
`);
175175

176-
const context = new ValidationContext(schema, ast, typeInfo);
176+
const context = new CompatibleValidationContext(schema, ast, typeInfo);
177177
const visitor = new ComplexityVisitor(context, {
178178
maximumComplexity: 100,
179179
estimators: [
180-
fieldConfigEstimator(),
180+
fieldExtensionsEstimator(),
181181
simpleEstimator({
182182
defaultComplexity: 1
183183
})
@@ -203,11 +203,11 @@ describe('QueryComplexity analysis', () => {
203203
}
204204
`);
205205

206-
const context = new ValidationContext(schema, ast, typeInfo);
206+
const context = new CompatibleValidationContext(schema, ast, typeInfo);
207207
const visitor = new ComplexityVisitor(context, {
208208
maximumComplexity: 100,
209209
estimators: [
210-
fieldConfigEstimator(),
210+
fieldExtensionsEstimator(),
211211
simpleEstimator({
212212
defaultComplexity: 1
213213
})
@@ -230,11 +230,11 @@ describe('QueryComplexity analysis', () => {
230230
}
231231
`);
232232

233-
const context = new ValidationContext(schema, ast, typeInfo);
233+
const context = new CompatibleValidationContext(schema, ast, typeInfo);
234234
const visitor = new ComplexityVisitor(context, {
235235
maximumComplexity: 100,
236236
estimators: [
237-
fieldConfigEstimator(),
237+
fieldExtensionsEstimator(),
238238
simpleEstimator({
239239
defaultComplexity: 1
240240
})
@@ -257,11 +257,11 @@ describe('QueryComplexity analysis', () => {
257257
}
258258
`);
259259

260-
const context = new ValidationContext(schema, ast, typeInfo);
260+
const context = new CompatibleValidationContext(schema, ast, typeInfo);
261261
const visitor = new ComplexityVisitor(context, {
262262
maximumComplexity: 100,
263263
estimators: [
264-
fieldConfigEstimator(),
264+
fieldExtensionsEstimator(),
265265
simpleEstimator({
266266
defaultComplexity: 1
267267
})
@@ -284,11 +284,11 @@ describe('QueryComplexity analysis', () => {
284284
}
285285
`);
286286

287-
const context = new ValidationContext(schema, ast, typeInfo);
287+
const context = new CompatibleValidationContext(schema, ast, typeInfo);
288288
const visitor = new ComplexityVisitor(context, {
289289
maximumComplexity: 100,
290290
estimators: [
291-
fieldConfigEstimator(),
291+
fieldExtensionsEstimator(),
292292
simpleEstimator({
293293
defaultComplexity: 1
294294
})
@@ -310,11 +310,11 @@ describe('QueryComplexity analysis', () => {
310310
}
311311
`);
312312

313-
const context = new ValidationContext(schema, ast, typeInfo);
313+
const context = new CompatibleValidationContext(schema, ast, typeInfo);
314314
const visitor = new ComplexityVisitor(context, {
315315
maximumComplexity: 100,
316316
estimators: [
317-
fieldConfigEstimator(),
317+
fieldExtensionsEstimator(),
318318
simpleEstimator({
319319
defaultComplexity: 1
320320
})
@@ -332,11 +332,11 @@ describe('QueryComplexity analysis', () => {
332332
}
333333
`);
334334

335-
const context = new ValidationContext(schema, ast, typeInfo);
335+
const context = new CompatibleValidationContext(schema, ast, typeInfo);
336336
const visitor = new ComplexityVisitor(context, {
337337
maximumComplexity: 100,
338338
estimators: [
339-
fieldConfigEstimator(),
339+
fieldExtensionsEstimator(),
340340
simpleEstimator({
341341
defaultComplexity: 1
342342
})
@@ -353,11 +353,11 @@ describe('QueryComplexity analysis', () => {
353353
requiredArgs
354354
}
355355
`);
356-
const context = new ValidationContext(schema, ast, typeInfo);
356+
const context = new CompatibleValidationContext(schema, ast, typeInfo);
357357
const visitor = new ComplexityVisitor(context, {
358358
maximumComplexity: 100,
359359
estimators: [
360-
fieldConfigEstimator(),
360+
fieldExtensionsEstimator(),
361361
simpleEstimator({
362362
defaultComplexity: 1
363363
})
@@ -374,7 +374,7 @@ describe('QueryComplexity analysis', () => {
374374
scalar
375375
}
376376
`);
377-
const context = new ValidationContext(schema, ast, typeInfo);
377+
const context = new CompatibleValidationContext(schema, ast, typeInfo);
378378
const visitor = new ComplexityVisitor(context, {
379379
maximumComplexity: 100,
380380
estimators: []
@@ -393,11 +393,11 @@ describe('QueryComplexity analysis', () => {
393393
scalar
394394
}
395395
`);
396-
const context = new ValidationContext(schema, ast, typeInfo);
396+
const context = new CompatibleValidationContext(schema, ast, typeInfo);
397397
const visitor = new ComplexityVisitor(context, {
398398
maximumComplexity: 100,
399399
estimators: [
400-
fieldConfigEstimator()
400+
fieldExtensionsEstimator()
401401
]
402402
});
403403
visit(ast, visitWithTypeInfo(typeInfo, visitor));
@@ -463,7 +463,7 @@ describe('QueryComplexity analysis', () => {
463463

464464
const complexity1 = getComplexity({
465465
estimators: [
466-
fieldConfigEstimator(),
466+
fieldExtensionsEstimator(),
467467
simpleEstimator({defaultComplexity: 1})
468468
],
469469
schema,
@@ -473,7 +473,7 @@ describe('QueryComplexity analysis', () => {
473473

474474
const complexity2 = getComplexity({
475475
estimators: [
476-
fieldConfigEstimator(),
476+
fieldExtensionsEstimator(),
477477
simpleEstimator({defaultComplexity: 1})
478478
],
479479
schema,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { GraphQLError, TypeInfo, ValidationContext } from "graphql";
2+
import { GraphQLSchema } from "graphql/type/schema";
3+
import { DocumentNode } from "graphql/language/ast";
4+
5+
/**
6+
* This class is used to test that validation errors are raised correctly
7+
*
8+
* A compatibility layer is necessary to support graphql versions since 15.0.0
9+
* *as well as* versions prior to 14.5.0 with the same test, because older
10+
* versions of `ValidationContext` only expose a `getErrors` API and newer
11+
* versions only expose the `onError` API via a fourth constructor argument.
12+
*
13+
* Once we drop support for versions older than 14.5.0 this layer will no
14+
* longer be necessary and tests may use `ValidationContext` directly using the
15+
* `onError` API.
16+
*/
17+
export class CompatibleValidationContext extends ValidationContext {
18+
private errors: GraphQLError[] = []
19+
20+
constructor(schema: GraphQLSchema, ast: DocumentNode, typeInfo: TypeInfo) {
21+
super(schema, ast, typeInfo, err => this.errors.push(err));
22+
}
23+
24+
getErrors(): ReadonlyArray<GraphQLError> {
25+
// @ts-ignore
26+
return super.getErrors ? super.getErrors() : this.errors
27+
}
28+
}

src/__tests__/fixtures/schema.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,22 @@ const Item: GraphQLObjectType = new GraphQLObjectType({
2121
fields: () => ({
2222
variableList: {
2323
type: Item,
24-
complexity: (args: ComplexityEstimatorArgs) => args.childComplexity * (args.args.count || 10),
24+
extensions: {
25+
complexity: (args: ComplexityEstimatorArgs) => args.childComplexity * (args.args.count || 10)
26+
},
2527
args: {
2628
count: {
2729
type: GraphQLInt
2830
}
2931
}
3032
},
3133
scalar: { type: GraphQLString },
32-
complexScalar: { type: GraphQLString, complexity: 20 },
34+
complexScalar: { type: GraphQLString, extensions: { complexity: 20 } },
3335
variableScalar: {
3436
type: Item,
35-
complexity: (args: ComplexityEstimatorArgs) => 10 * (args.args.count || 10),
37+
extensions: {
38+
complexity: (args: ComplexityEstimatorArgs) => 10 * (args.args.count || 10)
39+
},
3640
args: {
3741
count: {
3842
type: GraphQLInt
@@ -97,7 +101,9 @@ const Query = new GraphQLObjectType({
97101
name: { type: GraphQLString },
98102
variableList: {
99103
type: Item,
100-
complexity: (args: ComplexityEstimatorArgs) => args.childComplexity * (args.args.count || 10),
104+
extensions: {
105+
complexity: (args: ComplexityEstimatorArgs) => args.childComplexity * (args.args.count || 10)
106+
},
101107
args: {
102108
count: {
103109
type: GraphQLInt
@@ -107,11 +113,13 @@ const Query = new GraphQLObjectType({
107113
interface: {type: NameInterface},
108114
enum: {type: EnumType},
109115
scalar: { type: GraphQLString },
110-
complexScalar: { type: GraphQLString, complexity: 20 },
116+
complexScalar: { type: GraphQLString, extensions: { complexity: 20 } },
111117
union: { type: Union },
112118
variableScalar: {
113119
type: Item,
114-
complexity: (args: ComplexityEstimatorArgs) => 10 * (args.args.count || 10),
120+
extensions: {
121+
complexity: (args: ComplexityEstimatorArgs) => 10 * (args.args.count || 10)
122+
},
115123
args: {
116124
count: {
117125
type: GraphQLInt

0 commit comments

Comments
 (0)