Query complexity validation for GraphQL.js
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
src add context parameter to onCost to allow better logging Oct 8, 2018
test fix test Oct 8, 2018
.babelrc Update dependencies Nov 6, 2017
.eslintrc Use Prettier Feb 25, 2018
.gitignore Initial implementation Jun 21, 2017
.travis.yml Switch to Yarn Sep 16, 2017
LICENSE Initial commit Jun 20, 2017
README.md Handle cost directives Feb 24, 2018
package.json v0.2.4 Oct 8, 2018
yarn.lock Use Prettier Feb 25, 2018

README.md

graphql-validation-complexity Travis npm

Query complexity validation for GraphQL.js.

Codecov

Usage

import { createComplexityLimitRule } from 'graphql-validation-complexity';

const ComplexityLimitRule = createComplexityLimitRule(1000);
// Then use this rule with validate() or other validation APIs.

For example, with express-graphql, pass the complexity limit rule to validationRules.

const graphqlMiddleware = graphqlHTTP({
  schema,
  validationRules: [
    createComplexityLimitRule(1000),
  ],
});

You can provide a configuration object with custom global costs for scalars and objects as scalarCost and objectCost respectively, and a custom cost factor for lists as listFactor.

const ComplexityLimitRule = createComplexityLimitRule(1000, {
  scalarCost: 1,
  objectCost: 10, // Default is 0.
  listFactor: 20, // Default is 10.
});

You can also set custom costs and cost factors on fields definitions with getCost and getCostFactor callbacks.

const expensiveField = {
  type: ExpensiveItem,
  getCost: () => 50,
};

const expensiveList = {
  type: new GraphQLList(MyItem),
  getCostFactor: () => 100,
};

You can also define these via field directives in the SDL.

type CustomCostItem {
  expensiveField: ExpensiveItem @cost(value: 50)
  expensiveList: [MyItem] @costFactor(value: 100)
}

The configuration object also supports an onCost callback for logging query costs and a formatErrorMessage callback for customizing error messages. onCost will be called for every query with its cost. formatErrorMessage will be called with the cost whenever a query exceeds the complexity limit, and should return a string containing the error message.

const ComplexityLimitRule = createComplexityLimitRule(1000, {
  onCost: (cost) => {
    console.log('query cost:', cost);
  },
  formatErrorMessage: cost => (
    `query with cost ${cost} exceeds complexity limit`
  ),
});

The configuration object also supports a createError callback for creating a custom GraphQLError. createError will be called with the cost and the document node whenever an error occurs. formatErrorMessage will be ignored when createError is specified.

const ComplexityLimitRule = createComplexityLimitRule(1000, {
  createError(cost, documentNode) {
    const error = new GraphQLError('custom error', [documentNode]);
    error.meta = { cost };
    return error;
  },
});

By default, the validation rule applies a custom, lower cost factor for lists of introspection types, to prevent introspection queries from having unreasonably high costs. You can adjust this by setting introspectionListFactor on the configuration object.

const ComplexityLimitRule = createComplexityLimitRule(1000, {
  introspectionListFactor: 10, // Default is 2.
});