Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/estimators/directive/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,19 @@ input Filter {
```

The multipliers can be combined. Configured multipliers that don't have a value or `NULL` are ignored.

Code first approach can use the `createComplexityDirective` function to generate directive definition:

```typescript
import {createComplexityDirective} from 'graphql-query-complexity';

const schema = new GraphQLSchema({
directives: [
createComplexityDirective({
// Optionally change the name of the directive here... Default value is `complexity`
name: 'complexity'
})
]
// ... other config
});
```
42 changes: 40 additions & 2 deletions src/estimators/directive/__tests__/directiveEstimator-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@
*/

import {
GraphQLSchema,
parse,
print,
printSchema,
TypeInfo,
visit,
visitWithTypeInfo,
buildSchema
} from 'graphql';

import {expect} from 'chai';

import schema from './fixtures/schema';

import ComplexityVisitor from '../../../QueryComplexity';
import directiveEstimator from '../index';
import directiveEstimator, {createComplexityDirective} from '../index';
import { CompatibleValidationContext } from '../../../__tests__/fixtures/CompatibleValidationContext';

describe('directiveEstimator analysis', () => {
Expand Down Expand Up @@ -224,7 +228,7 @@ describe('directiveEstimator analysis', () => {
expect(visitor.complexity).to.equal(10);
});

it('ignores fields without compexity directive', () => {
it('ignores fields without complexity directive', () => {
const ast = parse(`
query {
noDirective
Expand All @@ -245,4 +249,38 @@ describe('directiveEstimator analysis', () => {
'No complexity could be calculated for field Query.noDirective',
);
});

it('should create complexity directive that can be used to generate directive definition', () => {
const complexityDirective = createComplexityDirective();
const codeFirstSchema = new GraphQLSchema({
directives: [complexityDirective]
});

// rebuilding code first schema
// graphql-js <= 14 prints descriptions in different ways printSchema(schema) vs print(astNode)
// and directive from code first schema has no astNode
const builtCodeFirstSchema = buildSchema(printSchema(codeFirstSchema));

const printedSchemaFirstDirective = print(schema.getDirective('complexity').astNode);
const printedCodeFirstDirective = print(builtCodeFirstSchema.getDirective('complexity').astNode);

expect(printedSchemaFirstDirective).to.equal(printedCodeFirstDirective);
});

it('should create complexity directive with configured name', () => {
const complexityDirective = createComplexityDirective({name: 'cost'});
const codeFirstSchema = new GraphQLSchema({
directives: [complexityDirective]
});

// rebuilding code first schema
// graphql-js <= 14 prints descriptions in different ways printSchema(schema) vs print(astNode)
// and directive from code first schema has no astNode
const builtCodeFirstSchema = buildSchema(printSchema(codeFirstSchema));

const printedSchemaFirstDirective = print(schema.getDirective('cost').astNode);
const printedCodeFirstDirective = print(builtCodeFirstSchema.getDirective('cost').astNode);

expect(printedSchemaFirstDirective).to.equal(printedCodeFirstDirective);
});
});
4 changes: 4 additions & 0 deletions src/estimators/directive/__tests__/fixtures/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import {
} from 'graphql';

export default buildSchema(`
"""Define a relation between the field and other nodes"""
directive @cost(
"""The complexity value for the field"""
value: Int!,
multipliers: [String!]
) on FIELD_DEFINITION

"""Define a relation between the field and other nodes"""
directive @complexity(
"""The complexity value for the field"""
value: Int!,
multipliers: [String!]
) on FIELD_DEFINITION
Expand Down
14 changes: 11 additions & 3 deletions src/estimators/directive/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ import { GraphQLDirective } from 'graphql/type/directives';
import { DirectiveLocation } from 'graphql/language/directiveLocation';
import get from 'lodash.get';

export default function (options?: {}): ComplexityEstimator {
export type ComplexityDirectiveOptions = {
name?: string
}

export function createComplexityDirective(options?: ComplexityDirectiveOptions) {
const mergedOptions = {
name: 'complexity',
...(options || {})
};

const directive = new GraphQLDirective({
return new GraphQLDirective({
name: mergedOptions.name,
description: 'Define a relation between the field and other nodes',
locations: [
DirectiveLocation.FIELD,
DirectiveLocation.FIELD_DEFINITION,
],
args: {
value: {
Expand All @@ -26,6 +30,10 @@ export default function (options?: {}): ComplexityEstimator {
}
},
});
}

export default function (options: ComplexityDirectiveOptions = {}): ComplexityEstimator {
const directive = createComplexityDirective(options);

return (args: ComplexityEstimatorArgs) => {
// Ignore if astNode is undefined
Expand Down
2 changes: 1 addition & 1 deletion src/estimators/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export {default as simpleEstimator} from './simple';
export {default as directiveEstimator} from './directive';
export {default as directiveEstimator, ComplexityDirectiveOptions, createComplexityDirective} from './directive';
export {default as fieldExtensionsEstimator} from './fieldExtensions';