@graphql-eslint/eslint-plugin
Version: 
GraphQL plugin for ESLint
95 lines (92 loc) • 3.17 kB
JavaScript
;Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _graphql = require('graphql');
var _utilsjs = require('../../utils.js');
const RULE_ID = "lone-executable-definition";
const definitionTypes = ["fragment", ...Object.values(_graphql.OperationTypeNode)];
const schema = {
  type: "array",
  maxItems: 1,
  items: {
    type: "object",
    minProperties: 1,
    additionalProperties: false,
    properties: {
      ignore: {
        ..._utilsjs.ARRAY_DEFAULT_OPTIONS,
        maxItems: 3,
        // ignore all 4 types is redundant
        items: {
          enum: definitionTypes
        },
        description: "Allow certain definitions to be placed alongside others."
      }
    }
  }
};
const rule = {
  meta: {
    type: "suggestion",
    docs: {
      category: "Operations",
      description: "Require queries, mutations, subscriptions or fragments to be located in separate files.",
      url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`,
      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) {
    const ignore = new Set(_optionalChain([context, 'access', _ => _.options, 'access', _2 => _2[0], 'optionalAccess', _3 => _3.ignore]) || []);
    const definitions = [];
    return {
      ":matches(OperationDefinition, FragmentDefinition)"(node) {
        const type = "operation" in node ? node.operation : "fragment";
        if (!ignore.has(type)) {
          definitions.push({ type, node });
        }
      },
      "Document:exit"() {
        for (const { node, type } of definitions.slice(1)) {
          let name = _utilsjs.pascalCase.call(void 0, type);
          const definitionName = _optionalChain([node, 'access', _4 => _4.name, 'optionalAccess', _5 => _5.value]);
          if (definitionName) {
            name += ` "${definitionName}"`;
          }
          context.report({
            loc: _optionalChain([node, 'access', _6 => _6.name, 'optionalAccess', _7 => _7.loc]) || _utilsjs.getLocation.call(void 0, node.loc.start, type),
            messageId: RULE_ID,
            data: { name }
          });
        }
      }
    };
  }
};
exports.rule = rule;