Skip to content

Fix linter setup #49

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 4, 2021
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
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules
/dist
13 changes: 3 additions & 10 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,8 @@
"env": {
"browser": true,
"es6": true,
"node": true
},

"globals": {
"describe": true,
"expect": true,
"it": true,
"before": true,
"after": true
"node": true,
"mocha": true
},

"parserOptions": {
Expand Down Expand Up @@ -226,4 +219,4 @@
"wrap-regex": 0,
"yoda": [2, "never", {"exceptRange": true}]
}
}
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"lint": "eslint src/**/*.ts",
"lint:fix": "eslint --fix src/**/*.ts",
"lint": "eslint --ext .ts .",
"lint:fix": "npm run lint -- --fix",
"clean": "rimraf dist/*",
"build": "tsc",
"test": "npm run lint && npm run testonly",
Expand Down
73 changes: 37 additions & 36 deletions src/QueryComplexity.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-use-before-define */
/**
* Created by Ivo Meißner on 28.07.17.
*/
Expand All @@ -11,11 +13,9 @@ import {
ValidationContext,
FragmentDefinitionNode,
OperationDefinitionNode,
DirectiveNode,
FieldNode,
FragmentSpreadNode,
InlineFragmentNode,
assertCompositeType,
GraphQLField, isCompositeType, GraphQLCompositeType, GraphQLFieldMap,
GraphQLSchema, DocumentNode, TypeInfo,
visit, visitWithTypeInfo,
Expand All @@ -31,11 +31,11 @@ import {
} from 'graphql';

export type ComplexityEstimatorArgs = {
type: GraphQLCompositeType,
field: GraphQLField<any, any>,
node: FieldNode,
args: {[key: string]: any},
childComplexity: number
type: GraphQLCompositeType;
field: GraphQLField<any, any>;
node: FieldNode;
args: {[key: string]: any};
childComplexity: number;
}

export type ComplexityEstimator = (options: ComplexityEstimatorArgs) => number | void;
Expand All @@ -45,27 +45,27 @@ export type Complexity = any;

// Map of complexities for possible types (of Union, Interface types)
type ComplexityMap = {
[typeName: string]: number,
[typeName: string]: number;
}

export interface QueryComplexityOptions {
// The maximum allowed query complexity, queries above this threshold will be rejected
maximumComplexity: number,
maximumComplexity: number;

// The query variables. This is needed because the variables are not available
// in the visitor of the graphql-js library
variables?: Object,
variables?: Record<string, any>;

// specify operation name only when pass multi-operation documents
operationName?: string,
operationName?: string;

// Optional callback function to retrieve the determined query complexity
// Will be invoked whether the query is rejected or not
// This can be used for logging or to implement rate limiting
onComplete?: (complexity: number) => void,
onComplete?: (complexity: number) => void;

// Optional function to create a custom error
createError?: (max: number, actual: number) => GraphQLError,
createError?: (max: number, actual: number) => GraphQLError;

// An array of complexity estimators to use for estimating the complexity
estimators: Array<ComplexityEstimator>;
Expand All @@ -79,11 +79,11 @@ function queryComplexityMessage(max: number, actual: number): string {
}

export function getComplexity(options: {
estimators: ComplexityEstimator[],
schema: GraphQLSchema,
query: DocumentNode,
variables?: Object,
operationName?: string
estimators: ComplexityEstimator[];
schema: GraphQLSchema;
query: DocumentNode;
variables?: Record<string, any>;
operationName?: string;
}): number {
const typeInfo = new TypeInfo(options.schema);

Expand All @@ -104,7 +104,7 @@ export default class QueryComplexity {
context: ValidationContext;
complexity: number;
options: QueryComplexityOptions;
OperationDefinition: Object;
OperationDefinition: Record<string, any>;
estimators: Array<ComplexityEstimator>;
includeDirectiveDef: GraphQLDirective;
skipDirectiveDef: GraphQLDirective;
Expand All @@ -123,15 +123,15 @@ export default class QueryComplexity {

this.includeDirectiveDef = this.context.getSchema().getDirective('include');
this.skipDirectiveDef = this.context.getSchema().getDirective('skip');
this.estimators = options.estimators
this.estimators = options.estimators;

this.OperationDefinition = {
enter: this.onOperationDefinitionEnter,
leave: this.onOperationDefinitionLeave
};
}

onOperationDefinitionEnter(operation: OperationDefinitionNode) {
onOperationDefinitionEnter(operation: OperationDefinitionNode): void {
if (typeof this.options.operationName === 'string' && this.options.operationName !== operation.name.value) {
return;
}
Expand Down Expand Up @@ -181,7 +181,7 @@ export default class QueryComplexity {
typeDef: GraphQLObjectType | GraphQLInterfaceType | GraphQLUnionType,
): number {
if (node.selectionSet) {
let fields:GraphQLFieldMap<any, any> = {};
let fields: GraphQLFieldMap<any, any> = {};
if (typeDef instanceof GraphQLObjectType || typeDef instanceof GraphQLInterfaceType) {
fields = typeDef.getFields();
}
Expand All @@ -191,18 +191,19 @@ export default class QueryComplexity {
if (isAbstractType(typeDef)) {
possibleTypeNames = this.context.getSchema().getPossibleTypes(typeDef).map(t => t.name);
} else {
possibleTypeNames = [typeDef.name];
possibleTypeNames = [ typeDef.name ];
}

// Collect complexities for all possible types individually
const selectionSetComplexities: ComplexityMap = node.selectionSet.selections.reduce(
(complexities: ComplexityMap, childNode: FieldNode | FragmentSpreadNode | InlineFragmentNode) => {
// let nodeComplexity = 0;
let innerComplexities = complexities;

let includeNode = true;
let skipNode = false;

childNode.directives?.forEach((directive: DirectiveNode) => {
for (const directive of childNode.directives ?? []) {
const directiveName = directive.name.value;
switch (directiveName) {
case 'include': {
Expand All @@ -216,7 +217,7 @@ export default class QueryComplexity {
break;
}
}
});
}

if (!includeNode || skipNode) {
return complexities;
Expand Down Expand Up @@ -258,7 +259,7 @@ export default class QueryComplexity {
const tmpComplexity = estimator(estimatorArgs);

if (typeof tmpComplexity === 'number' && !isNaN(tmpComplexity)) {
complexities = addComplexities(
innerComplexities = addComplexities(
tmpComplexity,
complexities,
possibleTypeNames,
Expand Down Expand Up @@ -292,17 +293,17 @@ export default class QueryComplexity {
const nodeComplexity = this.nodeComplexity(fragment, fragmentType);
if (isAbstractType(fragmentType)) {
// Add fragment complexity for all possible types
complexities = addComplexities(
innerComplexities = addComplexities(
nodeComplexity,
complexities,
this.context.getSchema().getPossibleTypes(fragmentType).map(t => t.name),
);
} else {
// Add complexity for object type
complexities = addComplexities(
innerComplexities = addComplexities(
nodeComplexity,
complexities,
[fragmentType.name],
[ fragmentType.name ],
);
}
break;
Expand All @@ -319,23 +320,23 @@ export default class QueryComplexity {
const nodeComplexity = this.nodeComplexity(childNode, inlineFragmentType);
if (isAbstractType(inlineFragmentType)) {
// Add fragment complexity for all possible types
complexities = addComplexities(
innerComplexities = addComplexities(
nodeComplexity,
complexities,
this.context.getSchema().getPossibleTypes(inlineFragmentType).map(t => t.name),
);
} else {
// Add complexity for object type
complexities = addComplexities(
innerComplexities = addComplexities(
nodeComplexity,
complexities,
[inlineFragmentType.name],
[ inlineFragmentType.name ],
);
}
break;
}
default: {
complexities = addComplexities(
innerComplexities = addComplexities(
this.nodeComplexity(childNode, typeDef),
complexities,
possibleTypeNames,
Expand All @@ -344,7 +345,7 @@ export default class QueryComplexity {
}
}

return complexities;
return innerComplexities;
}, {});
// Only return max complexity of all possible types
if (!selectionSetComplexities) {
Expand Down Expand Up @@ -381,8 +382,8 @@ function addComplexities(
possibleTypes: string[],
): ComplexityMap {
for (const type of possibleTypes) {
if (complexityMap.hasOwnProperty(type)) {
complexityMap[type] = complexityMap[type] + complexity;
if (Object.prototype.hasOwnProperty.call(complexityMap, type)) {
complexityMap[type] += complexity;
} else {
complexityMap[type] = complexity;
}
Expand Down
5 changes: 5 additions & 0 deletions src/__tests__/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
rules: {
'@typescript-eslint/explicit-function-return-type': "off"
}
}
13 changes: 7 additions & 6 deletions src/__tests__/fixtures/CompatibleValidationContext.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GraphQLError, TypeInfo, ValidationContext } from "graphql";
import { GraphQLSchema } from "graphql/type/schema";
import { DocumentNode } from "graphql/language/ast";
import { GraphQLError, TypeInfo, ValidationContext } from 'graphql';
import { GraphQLSchema } from 'graphql/type/schema';
import { DocumentNode } from 'graphql/language/ast';

/**
* This class is used to test that validation errors are raised correctly
Expand All @@ -18,11 +18,12 @@ export class CompatibleValidationContext extends ValidationContext {
private errors: GraphQLError[] = []

constructor(schema: GraphQLSchema, ast: DocumentNode, typeInfo: TypeInfo) {
super(schema, ast, typeInfo, err => this.errors.push(err));
super(schema, ast, typeInfo, err => this.errors.push(err));
}

getErrors(): ReadonlyArray<GraphQLError> {
// @ts-ignore
return super.getErrors ? super.getErrors() : this.errors
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
return super.getErrors ? super.getErrors() : this.errors;
}
}
20 changes: 10 additions & 10 deletions src/__tests__/fixtures/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,6 @@ const NameInterface = new GraphQLInterfaceType({
resolveType: () => Item
});

const UnionInterface = new GraphQLInterfaceType({
name: 'UnionInterface',
fields: () => ({
union: { type: Union }
}),
resolveType: () => Item
});

const SecondItem = new GraphQLObjectType({
name: 'SecondItem',
fields: () => ({
Expand All @@ -95,6 +87,14 @@ const Union = new GraphQLUnionType({
resolveType: () => Item
});

const UnionInterface = new GraphQLInterfaceType({
name: 'UnionInterface',
fields: () => ({
union: { type: Union }
}),
resolveType: () => Item
});

const SDLInterface = new GraphQLInterfaceType({
name: 'SDLInterface',
fields: {
Expand All @@ -108,7 +108,7 @@ const SDL = new GraphQLObjectType({
fields: {
sdl: { type: GraphQLString }
},
interfaces: () => [SDLInterface],
interfaces: () => [ SDLInterface ],
});

const Query = new GraphQLObjectType({
Expand Down Expand Up @@ -161,7 +161,7 @@ const Query = new GraphQLObjectType({
},
_service: {type: SDLInterface},
}),
interfaces: () => [NameInterface, UnionInterface,]
interfaces: () => [ NameInterface, UnionInterface, ]
});

export default new GraphQLSchema({
Expand Down
4 changes: 2 additions & 2 deletions src/estimators/directive/__tests__/directiveEstimator-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ describe('directiveEstimator analysis', () => {
it('should create complexity directive that can be used to generate directive definition', () => {
const complexityDirective = createComplexityDirective();
const codeFirstSchema = new GraphQLSchema({
directives: [complexityDirective]
directives: [ complexityDirective ]
});

// rebuilding code first schema
Expand All @@ -270,7 +270,7 @@ describe('directiveEstimator analysis', () => {
it('should create complexity directive with configured name', () => {
const complexityDirective = createComplexityDirective({name: 'cost'});
const codeFirstSchema = new GraphQLSchema({
directives: [complexityDirective]
directives: [ complexityDirective ]
});

// rebuilding code first schema
Expand Down
6 changes: 3 additions & 3 deletions src/estimators/directive/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { DirectiveLocation } from 'graphql/language/directiveLocation';
import get from 'lodash.get';

export type ComplexityDirectiveOptions = {
name?: string
name?: string;
}

export function createComplexityDirective(options?: ComplexityDirectiveOptions) {
export function createComplexityDirective(options?: ComplexityDirectiveOptions): GraphQLDirective {
const mergedOptions = {
name: 'complexity',
...(options || {})
Expand All @@ -35,7 +35,7 @@ export function createComplexityDirective(options?: ComplexityDirectiveOptions)
export default function (options: ComplexityDirectiveOptions = {}): ComplexityEstimator {
const directive = createComplexityDirective(options);

return (args: ComplexityEstimatorArgs) => {
return (args: ComplexityEstimatorArgs): number | void => {
// Ignore if astNode is undefined
if (!args.field.astNode) {
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/**
* Created by Ivo Meißner on 28.07.17.
*/
Expand Down
Loading