@graphql-eslint/eslint-plugin
Version:
GraphQL plugin for ESLint
142 lines (139 loc) • 4.6 kB
JavaScript
Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _graphql = require('graphql');
var _graphqldepthlimit = require('graphql-depth-limit'); var _graphqldepthlimit2 = _interopRequireDefault(_graphqldepthlimit);
var _utilsjs = require('../../utils.js');
const RULE_ID = "selection-set-depth";
const schema = {
type: "array",
minItems: 1,
maxItems: 1,
items: {
type: "object",
additionalProperties: false,
required: ["maxDepth"],
properties: {
maxDepth: {
type: "number"
},
ignore: _utilsjs.ARRAY_DEFAULT_OPTIONS
}
}
};
const rule = {
meta: {
type: "suggestion",
hasSuggestions: true,
docs: {
category: "Operations",
description: "Limit the complexity of the GraphQL operations solely by their depth. Based on [graphql-depth-limit](https://npmjs.com/package/graphql-depth-limit).",
url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
requiresSiblings: true,
examples: [
{
title: "Incorrect",
usage: [{ maxDepth: 1 }],
code: `
query deep2 {
viewer { # Level 0
albums { # Level 1
title # Level 2
}
}
}
`
},
{
title: "Correct",
usage: [{ maxDepth: 4 }],
code: `
query deep2 {
viewer { # Level 0
albums { # Level 1
title # Level 2
}
}
}
`
},
{
title: "Correct (ignored field)",
usage: [{ maxDepth: 1, ignore: ["albums"] }],
code: `
query deep2 {
viewer { # Level 0
albums { # Level 1
title # Level 2
}
}
}
`
}
],
recommended: true,
configOptions: [{ maxDepth: 7 }]
},
schema
},
create(context) {
let siblings = null;
try {
siblings = _utilsjs.requireGraphQLOperations.call(void 0, RULE_ID, context);
} catch (e2) {
_utilsjs.logger.warn(
`Rule "${RULE_ID}" works best with siblings operations loaded. See https://the-guild.dev/graphql/eslint/docs/usage#providing-operations for more info`
);
}
const { maxDepth, ignore = [] } = context.options[0];
const checkFn = _graphqldepthlimit2.default.call(void 0, maxDepth, { ignore });
return {
"OperationDefinition, FragmentDefinition"(node) {
try {
const rawNode = node.rawNode();
const fragmentsInUse = siblings ? siblings.getFragmentsInUse(rawNode) : [];
const document = {
kind: _graphql.Kind.DOCUMENT,
definitions: [rawNode, ...fragmentsInUse]
};
checkFn({
getDocument: () => document,
reportError(error) {
const { line, column } = error.locations[0];
const ancestors = context.sourceCode.getAncestors(node);
const token = ancestors[0].tokens.find(
(token2) => token2.loc.start.line === line && token2.loc.start.column === column - 1
);
context.report({
loc: {
line,
column: column - 1
},
message: error.message,
// Don't provide suggestions for fragment that can be in a separate file
...token && {
suggest: [
{
desc: "Remove selections",
fix(fixer) {
const sourceCode = context.getSourceCode();
const foundNode = sourceCode.getNodeByRangeIndex(token.range[0]);
const parentNode = foundNode.parent.parent;
return fixer.remove(
foundNode.kind === "Name" ? parentNode.parent : parentNode
);
}
}
]
}
});
}
});
} catch (e) {
_utilsjs.logger.warn(
`Rule "${RULE_ID}" check failed due to a missing siblings operations. See https://the-guild.dev/graphql/eslint/docs/usage#providing-operations for more info`,
e
);
}
}
};
}
};
exports.rule = rule;
;