UNPKG

@graphql-eslint/eslint-plugin

Version:
86 lines (85 loc) 2.86 kB
import { ARRAY_DEFAULT_OPTIONS, pascalCase, getLocation } from '../utils.js'; const RULE_ID = 'lone-executable-definition'; const definitionTypes = ['fragment', 'query', 'mutation', 'subscription']; const schema = { type: 'array', maxItems: 1, items: { type: 'object', minProperties: 1, additionalProperties: false, properties: { ignore: { ...ARRAY_DEFAULT_OPTIONS, maxItems: 3, items: { enum: definitionTypes, }, description: 'Allow certain definitions to be placed alongside others.', }, }, }, }; export const rule = { meta: { type: 'suggestion', docs: { category: 'Operations', description: 'Require queries, mutations, subscriptions or fragments to be located in separate files.', url: `https://github.com/B2o5T/graphql-eslint/blob/master/docs/rules/${RULE_ID}.md`, examples: [ { title: 'Incorrect', code: /* GraphQL */ ` query Foo { id } fragment Bar on Baz { id } `, }, { title: 'Correct', code: /* GraphQL */ ` query Foo { id } `, }, ], }, messages: { [RULE_ID]: '{{name}} should be in a separate file.', }, schema, }, create(context) { var _a; const ignore = new Set(((_a = context.options[0]) === null || _a === void 0 ? void 0 : _a.ignore) || []); const definitions = []; return { ':matches(OperationDefinition, FragmentDefinition)'(node) { const type = 'operation' in node ? node.operation : 'fragment'; if (!ignore.has(type)) { definitions.push({ type, node }); } }, 'Program:exit'() { var _a, _b; for (const { node, type } of definitions.slice(1) /* ignore first definition */) { let name = pascalCase(type); const definitionName = (_a = node.name) === null || _a === void 0 ? void 0 : _a.value; if (definitionName) { name += ` "${definitionName}"`; } context.report({ loc: ((_b = node.name) === null || _b === void 0 ? void 0 : _b.loc) || getLocation(node.loc.start, type), messageId: RULE_ID, data: { name }, }); } }, }; }, };