Skip to content
This repository was archived by the owner on Dec 1, 2022. It is now read-only.

Commit 6ab0151

Browse files
committed
feat: the graphql-query-complexity Apollo Plugin
1 parent 44edddd commit 6ab0151

File tree

8 files changed

+508
-94
lines changed

8 files changed

+508
-94
lines changed

README.md

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,48 @@
1-
# Typescript Library Template
1+
# Graphql Query Complexity Apollo Plugin
22

3-
[![Release](https://github.com/reconbot/typescript-library-template/actions/workflows/test.yml/badge.svg)](https://github.com/reconbot/typescript-library-template/actions/workflows/test.yml)
3+
[![Release](https://github.com/reconbot/graphql-query-complexity-apollo-plugin/actions/workflows/test.yml/badge.svg)](https://github.com/reconbot/graphql-query-complexity-apollo-plugin/actions/workflows/test.yml)
44

5-
This is an example project for shipping typescript using the rules layed out by [@southpolesteve](https://twitter.com/southpolesteve) in his ["Shipping Typescript to NPM"](https://speakerdeck.com/southpolesteve/shipping-typescript-to-npm?slide=10) talk that he gave at NYC typescript.
5+
This is a plugin for Apollo Server 3 that throws if a query is too complex.
66

7-
It gives you a library in UMD and ESM that's rolled up with rollup and includes rolled up types. It makes browser users, node users and me very happy.
7+
## Example
88

9-
Also includes eslint, mocha, semantic-release and github actions. Now updated to include the exports directive in the package.json.
9+
```ts
10+
import { ApolloServer } from 'apollo-server-lambda'
11+
import { schema } from './schema'
12+
import { context } from './context'
13+
import { SystemConfigOptions } from '../lib/SystemConfig'
14+
import { fieldExtensionsEstimator, simpleEstimator } from 'graphql-query-complexity'
15+
import { createComplexityPlugin } from './createComplexityPlugin'
1016

11-
## Guide
17+
return new ApolloServer({
18+
schema,
19+
context,
20+
plugins: [
21+
createComplexityPlugin({
22+
schema,
23+
estimators: [
24+
fieldExtensionsEstimator(),
25+
simpleEstimator({ defaultComplexity: 1 }),
26+
],
27+
maximumComplexity: 1000,
28+
onComplete: (complexity) => {
29+
console.log('Query Complexity:', complexity)
30+
},
31+
}),
32+
],
33+
})
34+
```
1235

13-
- Set the repo secret `NPM_TOKEN` before your first push so that you can publish to npm.
14-
- Change all references in package.json to your own project name
15-
- If you want external dependencies, add them to the `external` section in the `rollup.config.js` otherwise they will be bundled in the library.
36+
## API
37+
38+
```ts
39+
export const createComplexityPlugin: ({ schema, maximumComplexity, estimators, onComplete, createError }: {
40+
schema: GraphQLSchema
41+
maximumComplexity: number
42+
estimators: Array<ComplexityEstimator>
43+
onComplete?: ((complexity: number) => Promise<void> | void)
44+
createError?: ((max: number, actual: number) => Promise<GraphQLError> | GraphQLError)
45+
}) => PluginDefinition
46+
```
47+
48+
- `createError` should return an error to be thrown if the actual complexity is more than the maximum complexity.

lib/index-test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { assert } from 'chai'
2+
import { createComplexityPlugin } from './'
3+
4+
describe('createComplexityPlugin', () => {
5+
it('requires', () => {
6+
assert.equal(typeof createComplexityPlugin, 'function')
7+
})
8+
})

lib/index.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,44 @@
1-
export { serial } from './serial'
1+
import { ComplexityEstimator, getComplexity } from 'graphql-query-complexity'
2+
import { GraphQLError, GraphQLSchema, separateOperations } from 'graphql'
3+
import { PluginDefinition } from 'apollo-server-core'
4+
5+
export const createComplexityPlugin = ({
6+
schema,
7+
maximumComplexity,
8+
estimators,
9+
onComplete,
10+
createError = (max, actual) => new GraphQLError(`Query too complex. Value of ${actual} is over the maximum ${max}.`),
11+
}: {
12+
schema: GraphQLSchema;
13+
maximumComplexity: number;
14+
estimators: Array<ComplexityEstimator>;
15+
onComplete?: (complexity: number) => Promise<void> | void;
16+
createError?: (max: number, actual: number) => Promise<GraphQLError> | GraphQLError;
17+
}): PluginDefinition => {
18+
return {
19+
async requestDidStart() {
20+
return ({
21+
async didResolveOperation({ request, document }) {
22+
const query = request.operationName
23+
? separateOperations(document)[request.operationName]
24+
: document
25+
26+
const complexity = getComplexity({
27+
schema,
28+
query,
29+
variables: request.variables,
30+
estimators,
31+
})
32+
33+
if (complexity >= maximumComplexity) {
34+
throw await createError(maximumComplexity, complexity)
35+
}
36+
37+
if (onComplete) {
38+
await onComplete(complexity)
39+
}
40+
},
41+
})
42+
},
43+
}
44+
}

lib/serial-test.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

lib/serial.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)