UNPKG

eslint-seatbelt

Version:

Gradually tighten ESLint rules in your codebase

1 lines 35 kB
{"version":3,"sources":["../package.json","../src/SeatbeltConfig.ts","../src/repoIntegration.ts","../src/jsonSchema/SeatbeltConfigSchema.ts"],"sourcesContent":["{\n \"name\": \"eslint-seatbelt\",\n \"version\": \"0.1.1\",\n \"description\": \"Gradually tighten ESLint rules in your codebase\",\n \"keywords\": [\n \"eslint\",\n \"incremental\",\n \"gradual\",\n \"workflow\",\n \"processor\",\n \"linting\"\n ],\n \"author\": {\n \"name\": \"Jake Teton-Landis\",\n \"url\": \"https://jake.tl\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/justjake/eslint-seatbelt.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/justjake/eslint-seatbelt/issues\"\n },\n \"scripts\": {\n \"build\": \"./scripts/make-json-schemas.ts && tsc && tsup\",\n \"test\": \"node --test --require tsx/cjs $(find src -name '*.test.ts')\",\n \"lint\": \"pnpm build && NODE_OPTIONS='--enable-source-maps' eslint .\"\n },\n \"types\": \"dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"main\": \"dist/index.js\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"default\": \"./dist/index.js\"\n },\n \"./api\": {\n \"types\": \"./dist/api.d.ts\",\n \"import\": \"./dist/api.mjs\",\n \"default\": \"./dist/api.js\"\n }\n },\n \"bin\": {\n \"eslint-seatbelt\": \"./dist/command.js\"\n },\n \"files\": [\n \"!*.tsbuildinfo\",\n \"!src/**/*.test.ts\",\n \"src\",\n \"dist\"\n ],\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"@types/eslint\": \"*\",\n \"eslint\": \"*\"\n },\n \"peerDependenciesMeta\": {\n \"eslint\": {\n \"optional\": true\n },\n \"@types/eslint\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@eslint/compat\": \"1.2.3\",\n \"@eslint/js\": \"9.15.0\",\n \"@types/eslint__js\": \"8.42.3\",\n \"@types/node\": \"22.9.0\",\n \"@typescript-eslint/rule-tester\": \"8.14.0\",\n \"@typescript-eslint/utils\": \"8.14.0\",\n \"eslint\": \"9.14.0\",\n \"prettier\": \"3.3.3\",\n \"tsup\": \"8.3.5\",\n \"tsx\": \"4.19.2\",\n \"typescript\": \"5.6.3\",\n \"typescript-eslint\": \"8.14.0\",\n \"typescript-json-schema\": \"0.65.1\"\n },\n \"dependencies\": {\n \"ts-command-line-args\": \"^2.5.1\"\n },\n \"packageManager\": \"pnpm@10.2.1+sha1.48adf39a4ab751eda7b73b99447d1f0b6d227e02\"\n}\n","import type { RuleId } from \"./SeatbeltFile\"\nimport { name } from \"../package.json\"\nimport path from \"node:path\"\nimport { findRepoRoot } from \"./repoIntegration\"\n\nexport const SEATBELT_FILE_NAME = \"eslint.seatbelt.tsv\"\n\nexport const SEATBELT_FROZEN = \"SEATBELT_FROZEN\"\nexport const SEATBELT_INCREASE = \"SEATBELT_INCREASE\"\nexport const SEATBELT_KEEP = \"SEATBELT_KEEP\"\nexport const SEATBELT_FILE = \"SEATBELT_FILE\"\nexport const SEATBELT_PWD = \"SEATBELT_PWD\"\nexport const SEATBELT_DISABLE = \"SEATBELT_DISABLE\"\nexport const SEATBELT_THREADSAFE = \"SEATBELT_THREADSAFE\"\nexport const SEATBELT_VERBOSE = \"SEATBELT_VERBOSE\"\nexport const SEATBELT_ROOT = \"SEATBELT_ROOT\"\n\nconst ENV_VARS = {\n SEATBELT_FROZEN,\n SEATBELT_INCREASE,\n SEATBELT_KEEP,\n SEATBELT_FILE,\n SEATBELT_PWD,\n SEATBELT_DISABLE,\n SEATBELT_THREADSAFE,\n SEATBELT_VERBOSE,\n SEATBELT_ROOT,\n CI: \"CI\",\n JEST_WORKER_ID: \"JEST_WORKER_ID\",\n}\n\n/**\n * Configuration for seatbelt can be provided in a few ways:\n *\n * 1. Defined in the shared `settings` object in your ESLint config. This\n * requires also configuring the `eslint-seatbelt/configure` rule.\n *\n * ```js\n * // in eslint.config.js\n * const config = [\n * {\n * settings: {\n * seatbelt: {\n * // ...\n * }\n * },\n * rules: {\n * \"eslint-seatbelt/configure\": \"error\",\n * }\n * }\n * ]\n * ```\n *\n * 2. Using the `eslint-seatbelt/configure` rule in your ESLint config.\n * This can be used to override settings for specific files in legacy ESLint configs.\n * Any configuration provided here will override the shared `settings` object.\n *\n * ```js\n * // in .eslintrc.js\n * module.exports = {\n * rules: {\n * \"eslint-seatbelt/configure\": \"error\",\n * },\n * overrides: [\n * {\n * files: [\"some/path/*\"],\n * rules: {\n * \"eslint-seatbelt/configure\": [\"error\", { seatbeltFile: \"some/path/eslint.seatbelt.tsv\" }]\n * },\n * },\n * ],\n * }\n * ```\n * 3. The settings in config files can be overridden with environment variables when running `eslint` or other tools.\n *\n * ```bash\n * SEATBELT_FILE=some/path/eslint.seatbelt.tsv SEATBELT_FROZEN=1 eslint\n * ```\n */\nexport interface SeatbeltConfig {\n /**\n * The seatbelt file stores the max error counts allowed for each file. Should\n * be an absolute path.\n *\n * If not provided, $SEATBELT_PWD/eslint.seatbelt.tsv or $PWD/eslint.seatbelt.tsv will be used.\n *\n * ```js\n * // in eslint.config.js\n * const config = [\n * {\n * settings: {\n * seatbelt: {\n * // commonjs\n * seatbeltFile: `${__dirname}/eslint.seatbelt.tsv`\n * // esm\n * seatbeltFile: new URL('./eslint.seatbelt.tsv', import.meta.url).pathname\n * }\n * }\n * }\n * ]\n * ```\n *\n * You can also set this with environment variable `SEATBELT_FILE`:\n *\n * ```bash\n * SEATBELT_FILE=.config/custom-seatbelt-file eslint\n * ```\n */\n seatbeltFile?: string\n /**\n * By default whenever a file is linted and a rule has no errors, that rule's\n * max errors for the file is set to zero.\n *\n * However with typescript-eslint, it can be helpful to have two ESLint configs:\n *\n * - A default ESLint config with only syntactic rules enabled that don't\n * require typechecking, that runs on developer machines and in their editor.\n * - A CI-only ESLint config with only type-aware rules enabled that requires\n * typechecking. Since these rules require typechecking, they can be too\n * slow to run in interactive contexts.\n *\n * To avoid this, set `keepRules` to the names of *disabled but known rules*\n * while linting.\n *\n * Example:\n *\n * ```js\n * // Default ESLint config\n * module.exports = [\n * {\n * settings: {\n * seatbelt: {\n * keepRules: require('./eslint-typed.config.js').flatMap(config => Object.keys(config.rules ?? {})),\n * }\n * },\n * rules: {\n * \"no-unused-vars\": \"error\",\n * },\n * }\n * ]\n *\n * // Typechecking-required ESLint config for CI\n * module.exports = [\n * {\n * settings: {\n * seatbelt: {\n * keepRules: require('./eslint.config.js').flatMap(config => Object.keys(config.rules ?? {})),\n * }\n * },\n * rules: {\n * // Requires typechecking (slow)\n * \"@typescript-eslint/no-floating-promises\": \"error\",\n * },\n * }\n * ]\n * ```\n *\n * You can also set this with environment variable `SEATBELT_KEEP`:\n *\n * ```bash\n * SEATBELT_KEEP=\"@typescript-eslint/no-floating-promises @typescript-eslint/prefer-reduce-type-parameter\" \\\n * eslint\n * ```\n *\n * You can set this to `\"ALL\"` to enable this setting for ALL rules:\n *\n * ```bash\n * SEATBELT_KEEP=ALL eslint\n * ```\n */\n keepRules?: RuleId[] | \"all\"\n /**\n * When you enable a rule for the first time, lint with it in this set to set\n * the initial max error counts.\n *\n * Typically this should be enabled for one lint run only via an environment\n * variable, but it can also be configured via ESLint settings.\n *\n * ```bash\n * SEATBELT_INCREASE=\"@typescript-eslint/no-floating-promises\" eslint\n * ```\n *\n * You can set this to `\"ALL\"` to enable this setting for ALL rules:\n *\n * ```bash\n * SEATBELT_INCREASE=ALL eslint\n * ```\n *\n * ```js\n * // in eslint.config.js\n * // maybe you have a use-case for this\n * const config = [\n * {\n * settings: {\n * seatbelt: {\n * allowIncreaseRules: [\"@typescript-eslint/no-floating-promises\"],\n * }\n * }\n * }\n * ]\n * ```\n */\n allowIncreaseRules?: RuleId[] | \"all\"\n /**\n * Error if there is any change in the number of errors in the seatbelt file.\n * This is useful in CI to ensures that developers keep the seatbelt file up-to-date as they fix errors.\n *\n * It is enabled by default when environment variable `CI` is set.\n *\n * ```bash\n * CI=1 eslint\n * ```\n *\n * This can be set with the `SEATBELT_FROZEN` environment variable.\n *\n * ```bash\n * SEATBELT_FROZEN=1 eslint\n * ```\n *\n * Or in ESLint config:\n *\n * ```js\n * // in eslint.config.js\n * const config = [\n * {\n * settings: {\n * seatbelt: {\n * frozen: true,\n * }\n * }\n * }\n * ]\n * ```\n */\n frozen?: boolean\n /**\n * Completely disable seatbelt error processing for a lint run while leaving it otherwise configured.\n *\n * This can be set with the `SEATBELT_DISABLE` environment variable.\n *\n * ```bash\n * SEATBELT_DISABLE=1 eslint\n * ```\n *\n * Or in ESLint config:\n *\n * ```js\n * // in eslint.config.js\n * const config = [\n * {\n * settings: {\n * seatbelt: {\n * disable: true,\n * }\n * }\n * }\n * ]\n * ```\n */\n disable?: boolean\n /**\n * By default seatbelt assumes that only one ESLint process will read and\n * write to the seatbelt file at a time.\n *\n * This should be set to `true` if you use a parallel ESLint runner similar to\n * jest-runner-eslint to avoid losing updates during parallel writes to the\n * seatbelt file.\n *\n * When enabled, seatbelt creates temporary lock files to serialize updates to\n * the seatbelt file. This comes at a small performance cost.\n *\n * This is enabled by default when run with Jest (environment variable `JEST_WORKER_ID` is set).\n *\n * It can also be set with environment variable `SEATBELT_THREADSAFE`:\n *\n * ```bash\n * SEATBELT_THREADSAFE=1 eslint-parallel\n * ```\n *\n * Or in ESLint config:\n *\n * ```js\n * // in eslint.config.js\n * const config = [\n * {\n * settings: {\n * seatbelt: {\n * threadsafe: true,\n * }\n * }\n * }\n * ]\n * ```\n */\n threadsafe?: boolean\n\n /**\n * Enable verbose logging.\n *\n * This can be set with the `SEATBELT_VERBOSE` environment variable.\n *\n * ```bash\n * SEATBELT_VERBOSE=1 eslint\n * ```\n *\n * Or in ESLint config:\n *\n * ```js\n * // in eslint.config.js\n * const config = [\n * {\n * settings: {\n * seatbelt: {\n * verbose: true,\n * }\n * }\n * }\n * ]\n * ```\n *\n * If set to a function (like `console.error`), that function will be called with the log messages.\n * The default logger when set to `true` is `console.error`.\n */\n verbose?: boolean | \"stdout\" | \"stderr\" | ((...message: unknown[]) => void)\n\n /**\n * Repository or project root.\n * By default this is inferred from `seatbeltFile` by checking ancestor directories for `.git`.\n * Used for editor integration to disable seatbelt during git actions like rebase or merge.\n *\n * This can be set with the `SEATBELT_ROOT` environment variable.\n */\n root?: string\n}\n\nexport interface SeatbeltConfigWithPwd extends SeatbeltConfig {\n pwd: string\n}\n\nexport const SeatbeltConfig = {\n withEnvOverrides(\n config: SeatbeltConfig,\n env: SeatbeltEnv & FallbackEnv,\n ): SeatbeltConfig {\n return {\n ...SeatbeltConfig.fromFallbackEnv(env),\n ...config,\n ...SeatbeltConfig.fromEnvOverrides(env),\n }\n },\n\n fromFallbackEnv(\n env: FallbackEnv,\n log?: (...message: unknown[]) => void,\n ): SeatbeltConfig {\n const config: SeatbeltConfig = {}\n const isCI = SeatbeltEnv.readBooleanEnvVar(env.CI)\n if (isCI) {\n config.frozen = true\n log?.(`${padVarName(\"CI\")} config.frozen defaults to`, true)\n }\n if (env.JEST_WORKER_ID) {\n config.threadsafe = true\n log?.(\n `${padVarName(\"JEST_WORKER_ID\")} config.threadsafe defaults to`,\n true,\n )\n }\n return config\n },\n\n fromEnvOverrides(\n env: SeatbeltEnv,\n log?: (...message: unknown[]) => void,\n ): SeatbeltConfigWithPwd {\n const config: SeatbeltConfigWithPwd = {\n pwd: env[SEATBELT_PWD] || process.cwd(),\n }\n\n const verbose = SeatbeltEnv.readBooleanEnvVar(env[SEATBELT_VERBOSE])\n if (verbose !== undefined) {\n config.verbose = verbose\n log?.(`${padVarName(SEATBELT_VERBOSE)} config.verbose =`, verbose)\n }\n const seatbeltFile = env[SEATBELT_FILE]\n if (seatbeltFile) {\n const rootRelative = path.isAbsolute(seatbeltFile) ? seatbeltFile : path.join(config.pwd, seatbeltFile)\n config.seatbeltFile = rootRelative\n log?.(`${padVarName(SEATBELT_FILE)} config.seatbeltFile =`, rootRelative)\n }\n const disable = SeatbeltEnv.readBooleanEnvVar(env[SEATBELT_DISABLE])\n if (disable !== undefined) {\n config.disable = disable\n log?.(`${padVarName(SEATBELT_DISABLE)} config.disable =`, disable)\n }\n const frozen = SeatbeltEnv.readBooleanEnvVar(env[SEATBELT_FROZEN])\n if (frozen !== undefined) {\n config.frozen = frozen\n log?.(`${padVarName(SEATBELT_FROZEN)} config.frozen =`, frozen)\n }\n const increase = SeatbeltEnv.parseRuleSetEnvVar(env[SEATBELT_INCREASE])\n if (increase !== undefined) {\n config.allowIncreaseRules = increase\n log?.(\n `${padVarName(SEATBELT_INCREASE)} config.allowIncreaseRules =`,\n increase,\n )\n }\n const keep = SeatbeltEnv.parseRuleSetEnvVar(env[SEATBELT_KEEP])\n if (keep !== undefined) {\n config.keepRules = keep\n log?.(`${padVarName(SEATBELT_KEEP)} config.keepRules =`, keep)\n }\n const threadsafe = SeatbeltEnv.readBooleanEnvVar(env[SEATBELT_THREADSAFE])\n if (threadsafe !== undefined) {\n config.threadsafe = threadsafe\n log?.(\n `${padVarName(SEATBELT_THREADSAFE)} config.threadsafe =`,\n threadsafe,\n )\n }\n const root = env[SEATBELT_ROOT]\n if (root) {\n config.root = root\n log?.(`${padVarName(SEATBELT_ROOT)} config.root =`, root)\n }\n\n return config\n },\n} as const\n\n/** A parsed {@link SeatbeltConfig} with all properties converted to runtime types. */\nexport type SeatbeltArgs = {\n [K in keyof SeatbeltConfig]-?: \"all\" | RuleId[] extends SeatbeltConfig[K]\n ? \"all\" | Set<RuleId>\n : SeatbeltConfig[K]\n}\n\n/** Catalogues the names of environment variables */\nexport interface SeatbeltEnv {\n [SEATBELT_INCREASE]?: string\n [SEATBELT_KEEP]?: string\n [SEATBELT_FILE]?: string\n [SEATBELT_PWD]?: string\n [SEATBELT_THREADSAFE]?: string\n [SEATBELT_DISABLE]?: string\n [SEATBELT_FROZEN]?: string\n [SEATBELT_VERBOSE]?: string\n [SEATBELT_ROOT]?: string\n}\n\nexport const SeatbeltEnv = {\n parseRuleSetEnvVar(value: string | undefined): RuleId[] | \"all\" | undefined {\n if (value === undefined) {\n return undefined\n }\n\n if (!value) {\n return []\n }\n\n const lower = value.toLowerCase()\n if (lower === \"all\" || lower === \"1\" || lower === \"true\") {\n return \"all\"\n }\n\n return value.split(/[\\s,]+/g).filter(Boolean)\n },\n\n readBooleanEnvVar(value: string | undefined): boolean | undefined {\n if (value === undefined || value === \"\") {\n return undefined\n }\n\n const lower = value.toLowerCase()\n if (lower === \"false\" || lower === \"0\" || lower === \"no\") {\n return false\n }\n return Boolean(value)\n },\n} as const\n\n/** Environment variables we may consider that don't override explicitly set config values. */\nexport interface FallbackEnv {\n CI?: string\n JEST_WORKER_ID?: string\n}\n\nexport const logStdout = (...message: unknown[]) =>\n // eslint-disable-next-line no-console\n console.log(`[${name}]:`, ...message)\nexport const logStderr = (...message: unknown[]) =>\n // eslint-disable-next-line no-console\n console.error(`[${name}]:`, ...message)\n\nexport const SeatbeltArgs = {\n fromConfig(config: SeatbeltConfig & { pwd?: string }): SeatbeltArgs {\n const cwd = config.pwd ?? process.cwd()\n const seatbeltFile =\n config.seatbeltFile ?? SeatbeltArgs.findSeatbeltFile(cwd)\n const root =\n config.root ?? findRepoRoot(seatbeltFile) ?? path.dirname(seatbeltFile)\n return {\n seatbeltFile,\n root,\n keepRules:\n typeof config.keepRules === \"string\"\n ? config.keepRules\n : new Set(config.keepRules ?? []),\n allowIncreaseRules:\n typeof config.allowIncreaseRules === \"string\"\n ? config.allowIncreaseRules\n : new Set(config.allowIncreaseRules ?? []),\n frozen: config.frozen ?? false,\n disable: config.disable ?? false,\n threadsafe: config.threadsafe ?? false,\n verbose: config.verbose ?? false,\n }\n },\n getLogger(args: SeatbeltArgs): (...message: unknown[]) => void {\n if (typeof args.verbose === \"function\") {\n return args.verbose\n }\n if (args.verbose === \"stdout\") {\n return logStdout\n }\n return logStderr\n },\n ruleSetHas(ruleSet: \"all\" | Set<RuleId>, ruleId: RuleId): boolean {\n return ruleSet === \"all\" || ruleSet.has(ruleId)\n },\n verboseLog(args: SeatbeltArgs, makeMessage: () => string | unknown[]) {\n if (args.verbose) {\n const message = makeMessage()\n const log = SeatbeltArgs.getLogger(args)\n if (typeof message === \"string\") {\n log(message)\n } else {\n log(...message)\n }\n }\n },\n findSeatbeltFile(cwd: string): string {\n // TODO: go up to parent dir w/ .git?\n return `${cwd}/${SEATBELT_FILE_NAME}`\n },\n}\n\nlet envVarMaxLength = 0\n\nexport function padVarName(name: string) {\n envVarMaxLength ||= Math.max(\n ...Object.values(ENV_VARS).map((name) => name.length),\n )\n return `${name}:`.padEnd(envVarMaxLength + 1)\n}\n\nexport function formatFilename(filename: string) {\n const relative = path.relative(\n process.env[SEATBELT_PWD] ?? process.cwd(),\n filename,\n )\n return relative ? relative : filename\n}\n\nexport function formatRuleId(ruleId: RuleId | null) {\n if (ruleId === null) {\n return `unknown rule`\n }\n return `rule ${ruleId}`\n}\n","import fs from \"node:fs\"\nimport nodePath from \"node:path\"\n\nfunction findAncestorDirectory(\n path: string,\n predicate: (dir: string) => boolean,\n) {\n let lastPath = undefined\n while (path !== lastPath) {\n if (predicate(path)) {\n return path\n }\n lastPath = path\n path = nodePath.dirname(path)\n }\n}\n\nfunction isGitRoot(dir: string) {\n return fs.existsSync(nodePath.join(dir, \".git\"))\n}\n\nexport function findRepoRoot(path: string) {\n return findAncestorDirectory(path, isGitRoot)\n}\n\nconst GIT_ACTION_FILES = [\n // git add, etc\n \"index.lock\",\n \"index.temp\",\n // git rebase\n // https://stackoverflow.com/questions/3921409/how-to-know-if-there-is-a-git-rebase-in-progress/67245016#67245016\n \"rebase-apply\",\n \"rebase-merge\",\n // git merge\n // https://stackoverflow.com/questions/30733415/how-to-determine-if-git-merge-is-in-process\n \"MERGE_HEAD\",\n]\n\nexport function isGitActionInProgress(dir: string) {\n if (!isGitRoot(dir)) {\n return false\n }\n return GIT_ACTION_FILES.some((file) =>\n fs.existsSync(nodePath.join(dir, \".git\", file)),\n )\n}\n","// This file is generated by running ./scripts/make-json-schemas.ts\n\nimport type { Rule } from \"eslint\"\ntype Schema = Rule.RuleMetaData[\"schema\"]\n\nexport const SeatbeltConfigSchema = {\n description:\n 'Configuration for seatbelt can be provided in a few ways:\\n\\n1. Defined in the shared `settings` object in your ESLint config. This\\n requires also configuring the `eslint-seatbelt/configure` rule.\\n\\n ```js\\n // in eslint.config.js\\n const config = [\\n {\\n settings: {\\n seatbelt: {\\n // ...\\n }\\n },\\n rules: {\\n \"eslint-seatbelt/configure\": \"error\",\\n }\\n }\\n ]\\n ```\\n\\n2. Using the `eslint-seatbelt/configure` rule in your ESLint config.\\n This can be used to override settings for specific files in legacy ESLint configs.\\n Any configuration provided here will override the shared `settings` object.\\n\\n ```js\\n // in .eslintrc.js\\n module.exports = {\\n rules: {\\n \"eslint-seatbelt/configure\": \"error\",\\n },\\n overrides: [\\n {\\n files: [\"some/path/*\"],\\n rules: {\\n \"eslint-seatbelt/configure\": [\"error\", { seatbeltFile: \"some/path/eslint.seatbelt.tsv\" }]\\n },\\n },\\n ],\\n }\\n ```\\n3. The settings in config files can be overridden with environment variables when running `eslint` or other tools.\\n\\n ```bash\\n SEATBELT_FILE=some/path/eslint.seatbelt.tsv SEATBELT_FROZEN=1 eslint\\n ```',\n type: \"object\",\n properties: {\n seatbeltFile: {\n description:\n \"The seatbelt file stores the max error counts allowed for each file. Should\\nbe an absolute path.\\n\\nIf not provided, $SEATBELT_PWD/eslint.seatbelt.tsv or $PWD/eslint.seatbelt.tsv will be used.\\n\\n```js\\n// in eslint.config.js\\nconst config = [\\n {\\n settings: {\\n seatbelt: {\\n // commonjs\\n seatbeltFile: `${__dirname}/eslint.seatbelt.tsv`\\n // esm\\n seatbeltFile: new URL('./eslint.seatbelt.tsv', import.meta.url).pathname\\n }\\n }\\n }\\n]\\n```\\n\\nYou can also set this with environment variable `SEATBELT_FILE`:\\n\\n```bash\\nSEATBELT_FILE=.config/custom-seatbelt-file eslint\\n```\",\n type: \"string\",\n },\n keepRules: {\n description:\n 'By default whenever a file is linted and a rule has no errors, that rule\\'s\\nmax errors for the file is set to zero.\\n\\nHowever with typescript-eslint, it can be helpful to have two ESLint configs:\\n\\n- A default ESLint config with only syntactic rules enabled that don\\'t\\n require typechecking, that runs on developer machines and in their editor.\\n- A CI-only ESLint config with only type-aware rules enabled that requires\\n typechecking. Since these rules require typechecking, they can be too\\n slow to run in interactive contexts.\\n\\nTo avoid this, set `keepRules` to the names of *disabled but known rules*\\nwhile linting.\\n\\nExample:\\n\\n```js\\n// Default ESLint config\\nmodule.exports = [\\n {\\n settings: {\\n seatbelt: {\\n keepRules: require(\\'./eslint-typed.config.js\\').flatMap(config => Object.keys(config.rules ?? {})),\\n }\\n },\\n rules: {\\n \"no-unused-vars\": \"error\",\\n },\\n }\\n]\\n\\n// Typechecking-required ESLint config for CI\\nmodule.exports = [\\n {\\n settings: {\\n seatbelt: {\\n keepRules: require(\\'./eslint.config.js\\').flatMap(config => Object.keys(config.rules ?? {})),\\n }\\n },\\n rules: {\\n // Requires typechecking (slow)\\n \"@typescript-eslint/no-floating-promises\": \"error\",\\n },\\n }\\n]\\n```\\n\\nYou can also set this with environment variable `SEATBELT_KEEP`:\\n\\n```bash\\nSEATBELT_KEEP=\"@typescript-eslint/no-floating-promises',\n anyOf: [\n {\n type: \"array\",\n items: {\n type: \"string\",\n },\n },\n {\n const: \"all\",\n type: \"string\",\n },\n ],\n },\n allowIncreaseRules: {\n description:\n 'When you enable a rule for the first time, lint with it in this set to set\\nthe initial max error counts.\\n\\nTypically this should be enabled for one lint run only via an environment\\nvariable, but it can also be configured via ESLint settings.\\n\\n```bash\\nSEATBELT_INCREASE=\"@typescript-eslint/no-floating-promises\" eslint\\n```\\n\\nYou can set this to `\"ALL\"` to enable this setting for ALL rules:\\n\\n```bash\\nSEATBELT_INCREASE=ALL eslint\\n```\\n\\n```js\\n// in eslint.config.js\\n// maybe you have a use-case for this\\nconst config = [\\n {\\n settings: {\\n seatbelt: {\\n allowIncreaseRules: [\"@typescript-eslint/no-floating-promises\"],\\n }\\n }\\n }\\n]\\n```',\n anyOf: [\n {\n type: \"array\",\n items: {\n type: \"string\",\n },\n },\n {\n const: \"all\",\n type: \"string\",\n },\n ],\n },\n frozen: {\n description:\n \"Error if there is any change in the number of errors in the seatbelt file.\\nThis is useful in CI to ensures that developers keep the seatbelt file up-to-date as they fix errors.\\n\\nIt is enabled by default when environment variable `CI` is set.\\n\\n```bash\\nCI=1 eslint\\n```\\n\\nThis can be set with the `SEATBELT_FROZEN` environment variable.\\n\\n```bash\\nSEATBELT_FROZEN=1 eslint\\n```\\n\\nOr in ESLint config:\\n\\n```js\\n// in eslint.config.js\\nconst config = [\\n {\\n settings: {\\n seatbelt: {\\n frozen: true,\\n }\\n }\\n }\\n]\\n```\",\n type: \"boolean\",\n },\n disable: {\n description:\n \"Completely disable seatbelt error processing for a lint run while leaving it otherwise configured.\\n\\nThis can be set with the `SEATBELT_DISABLE` environment variable.\\n\\n```bash\\nSEATBELT_DISABLE=1 eslint\\n```\\n\\nOr in ESLint config:\\n\\n```js\\n// in eslint.config.js\\nconst config = [\\n {\\n settings: {\\n seatbelt: {\\n disable: true,\\n }\\n }\\n }\\n]\\n```\",\n type: \"boolean\",\n },\n threadsafe: {\n description:\n \"By default seatbelt assumes that only one ESLint process will read and\\nwrite to the seatbelt file at a time.\\n\\nThis should be set to `true` if you use a parallel ESLint runner similar to\\njest-runner-eslint to avoid losing updates during parallel writes to the\\nseatbelt file.\\n\\nWhen enabled, seatbelt creates temporary lock files to serialize updates to\\nthe seatbelt file. This comes at a small performance cost.\\n\\nThis is enabled by default when run with Jest (environment variable `JEST_WORKER_ID` is set).\\n\\nIt can also be set with environment variable `SEATBELT_THREADSAFE`:\\n\\n```bash\\nSEATBELT_THREADSAFE=1 eslint-parallel\\n```\\n\\nOr in ESLint config:\\n\\n```js\\n// in eslint.config.js\\nconst config = [\\n {\\n settings: {\\n seatbelt: {\\n threadsafe: true,\\n }\\n }\\n }\\n]\\n```\",\n type: \"boolean\",\n },\n verbose: {\n description:\n \"Enable verbose logging.\\n\\nThis can be set with the `SEATBELT_VERBOSE` environment variable.\\n\\n```bash\\nSEATBELT_VERBOSE=1 eslint\\n```\\n\\nOr in ESLint config:\\n\\n```js\\n// in eslint.config.js\\nconst config = [\\n {\\n settings: {\\n seatbelt: {\\n verbose: true,\\n }\\n }\\n }\\n]\\n```\\n\\nIf set to a function (like `console.error`), that function will be called with the log messages.\\nThe default logger when set to `true` is `console.error`.\",\n anyOf: [\n {\n enum: [false, \"stderr\", \"stdout\", true],\n },\n {\n type: \"object\",\n },\n ],\n },\n root: {\n description:\n \"Repository or project root.\\nBy default this is inferred from `seatbeltFile` by checking ancestor directories for `.git`.\\nUsed for editor integration to disable seatbelt during git actions like rebase or merge.\\n\\nThis can be set with the `SEATBELT_ROOT` environment variable.\",\n type: \"string\",\n },\n },\n $schema: \"http://json-schema.org/draft-07/schema#\",\n} satisfies Schema\n"],"mappings":";;;;;;;;AACE,WAAQ;AACR,cAAW;AAFb;AAAA,EACE;AAAA,EACA;AAAA,EACA,aAAe;AAAA,EACf,UAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAU;AAAA,IACR,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,MAAQ;AAAA,IACN,KAAO;AAAA,EACT;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,MAAQ;AAAA,EACV;AAAA,EACA,OAAS;AAAA,EACT,QAAU;AAAA,EACV,MAAQ;AAAA,EACR,SAAW;AAAA,IACT,KAAK;AAAA,MACH,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,SAAS;AAAA,MACP,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,KAAO;AAAA,IACL,mBAAmB;AAAA,EACrB;AAAA,EACA,OAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,SAAW;AAAA,EACX,kBAAoB;AAAA,IAClB,iBAAiB;AAAA,IACjB,QAAU;AAAA,EACZ;AAAA,EACA,sBAAwB;AAAA,IACtB,QAAU;AAAA,MACR,UAAY;AAAA,IACd;AAAA,IACA,iBAAiB;AAAA,MACf,UAAY;AAAA,IACd;AAAA,EACF;AAAA,EACA,iBAAmB;AAAA,IACjB,kBAAkB;AAAA,IAClB,cAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,eAAe;AAAA,IACf,kCAAkC;AAAA,IAClC,4BAA4B;AAAA,IAC5B,QAAU;AAAA,IACV,UAAY;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,YAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,0BAA0B;AAAA,EAC5B;AAAA,EACA,cAAgB;AAAA,IACd,wBAAwB;AAAA,EAC1B;AAAA,EACA,gBAAkB;AACpB;;;AClFA,OAAO,UAAU;;;ACFjB,OAAO,QAAQ;AACf,OAAO,cAAc;AAErB,SAAS,sBACPA,OACA,WACA;AACA,MAAI,WAAW;AACf,SAAOA,UAAS,UAAU;AACxB,QAAI,UAAUA,KAAI,GAAG;AACnB,aAAOA;AAAA,IACT;AACA,eAAWA;AACX,IAAAA,QAAO,SAAS,QAAQA,KAAI;AAAA,EAC9B;AACF;AAEA,SAAS,UAAU,KAAa;AAC9B,SAAO,GAAG,WAAW,SAAS,KAAK,KAAK,MAAM,CAAC;AACjD;AAEO,SAAS,aAAaA,OAAc;AACzC,SAAO,sBAAsBA,OAAM,SAAS;AAC9C;;;ADlBO,IAAM,qBAAqB;AAE3B,IAAM,kBAAkB;AACxB,IAAM,oBAAoB;AAC1B,IAAM,gBAAgB;AACtB,IAAM,gBAAgB;AACtB,IAAM,eAAe;AACrB,IAAM,mBAAmB;AACzB,IAAM,sBAAsB;AAC5B,IAAM,mBAAmB;AACzB,IAAM,gBAAgB;AAE7B,IAAM,WAAW;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,IAAI;AAAA,EACJ,gBAAgB;AAClB;AAsTO,IAAM,iBAAiB;AAAA,EAC5B,iBACE,QACA,KACgB;AAChB,WAAO;AAAA,MACL,GAAG,eAAe,gBAAgB,GAAG;AAAA,MACrC,GAAG;AAAA,MACH,GAAG,eAAe,iBAAiB,GAAG;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,gBACE,KACA,KACgB;AAChB,UAAM,SAAyB,CAAC;AAChC,UAAM,OAAO,YAAY,kBAAkB,IAAI,EAAE;AACjD,QAAI,MAAM;AACR,aAAO,SAAS;AAChB,YAAM,GAAG,WAAW,IAAI,CAAC,8BAA8B,IAAI;AAAA,IAC7D;AACA,QAAI,IAAI,gBAAgB;AACtB,aAAO,aAAa;AACpB;AAAA,QACE,GAAG,WAAW,gBAAgB,CAAC;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,iBACE,KACA,KACuB;AACvB,UAAM,SAAgC;AAAA,MACpC,KAAK,IAAI,YAAY,KAAK,QAAQ,IAAI;AAAA,IACxC;AAEA,UAAM,UAAU,YAAY,kBAAkB,IAAI,gBAAgB,CAAC;AACnE,QAAI,YAAY,QAAW;AACzB,aAAO,UAAU;AACjB,YAAM,GAAG,WAAW,gBAAgB,CAAC,qBAAqB,OAAO;AAAA,IACnE;AACA,UAAM,eAAe,IAAI,aAAa;AACtC,QAAI,cAAc;AAChB,YAAM,eAAe,KAAK,WAAW,YAAY,IAAI,eAAe,KAAK,KAAK,OAAO,KAAK,YAAY;AACtG,aAAO,eAAe;AACtB,YAAM,GAAG,WAAW,aAAa,CAAC,0BAA0B,YAAY;AAAA,IAC1E;AACA,UAAM,UAAU,YAAY,kBAAkB,IAAI,gBAAgB,CAAC;AACnE,QAAI,YAAY,QAAW;AACzB,aAAO,UAAU;AACjB,YAAM,GAAG,WAAW,gBAAgB,CAAC,qBAAqB,OAAO;AAAA,IACnE;AACA,UAAM,SAAS,YAAY,kBAAkB,IAAI,eAAe,CAAC;AACjE,QAAI,WAAW,QAAW;AACxB,aAAO,SAAS;AAChB,YAAM,GAAG,WAAW,eAAe,CAAC,oBAAoB,MAAM;AAAA,IAChE;AACA,UAAM,WAAW,YAAY,mBAAmB,IAAI,iBAAiB,CAAC;AACtE,QAAI,aAAa,QAAW;AAC1B,aAAO,qBAAqB;AAC5B;AAAA,QACE,GAAG,WAAW,iBAAiB,CAAC;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AACA,UAAM,OAAO,YAAY,mBAAmB,IAAI,aAAa,CAAC;AAC9D,QAAI,SAAS,QAAW;AACtB,aAAO,YAAY;AACnB,YAAM,GAAG,WAAW,aAAa,CAAC,uBAAuB,IAAI;AAAA,IAC/D;AACA,UAAM,aAAa,YAAY,kBAAkB,IAAI,mBAAmB,CAAC;AACzE,QAAI,eAAe,QAAW;AAC5B,aAAO,aAAa;AACpB;AAAA,QACE,GAAG,WAAW,mBAAmB,CAAC;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AACA,UAAM,OAAO,IAAI,aAAa;AAC9B,QAAI,MAAM;AACR,aAAO,OAAO;AACd,YAAM,GAAG,WAAW,aAAa,CAAC,kBAAkB,IAAI;AAAA,IAC1D;AAEA,WAAO;AAAA,EACT;AACF;AAsBO,IAAM,cAAc;AAAA,EACzB,mBAAmB,OAAyD;AAC1E,QAAI,UAAU,QAAW;AACvB,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,OAAO;AACV,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,QAAQ,MAAM,YAAY;AAChC,QAAI,UAAU,SAAS,UAAU,OAAO,UAAU,QAAQ;AACxD,aAAO;AAAA,IACT;AAEA,WAAO,MAAM,MAAM,SAAS,EAAE,OAAO,OAAO;AAAA,EAC9C;AAAA,EAEA,kBAAkB,OAAgD;AAChE,QAAI,UAAU,UAAa,UAAU,IAAI;AACvC,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,MAAM,YAAY;AAChC,QAAI,UAAU,WAAW,UAAU,OAAO,UAAU,MAAM;AACxD,aAAO;AAAA,IACT;AACA,WAAO,QAAQ,KAAK;AAAA,EACtB;AACF;AAQO,IAAM,YAAY,IAAI;AAAA;AAAA,EAE3B,QAAQ,IAAI,IAAI,IAAI,MAAM,GAAG,OAAO;AAAA;AAC/B,IAAM,YAAY,IAAI;AAAA;AAAA,EAE3B,QAAQ,MAAM,IAAI,IAAI,MAAM,GAAG,OAAO;AAAA;AAEjC,IAAM,eAAe;AAAA,EAC1B,WAAW,QAAyD;AAClE,UAAM,MAAM,OAAO,OAAO,QAAQ,IAAI;AACtC,UAAM,eACJ,OAAO,gBAAgB,aAAa,iBAAiB,GAAG;AAC1D,UAAM,OACJ,OAAO,QAAQ,aAAa,YAAY,KAAK,KAAK,QAAQ,YAAY;AACxE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,WACE,OAAO,OAAO,cAAc,WACxB,OAAO,YACP,IAAI,IAAI,OAAO,aAAa,CAAC,CAAC;AAAA,MACpC,oBACE,OAAO,OAAO,uBAAuB,WACjC,OAAO,qBACP,IAAI,IAAI,OAAO,sBAAsB,CAAC,CAAC;AAAA,MAC7C,QAAQ,OAAO,UAAU;AAAA,MACzB,SAAS,OAAO,WAAW;AAAA,MAC3B,YAAY,OAAO,cAAc;AAAA,MACjC,SAAS,OAAO,WAAW;AAAA,IAC7B;AAAA,EACF;AAAA,EACA,UAAU,MAAqD;AAC7D,QAAI,OAAO,KAAK,YAAY,YAAY;AACtC,aAAO,KAAK;AAAA,IACd;AACA,QAAI,KAAK,YAAY,UAAU;AAC7B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EACA,WAAW,SAA8B,QAAyB;AAChE,WAAO,YAAY,SAAS,QAAQ,IAAI,MAAM;AAAA,EAChD;AAAA,EACA,WAAW,MAAoB,aAAuC;AACpE,QAAI,KAAK,SAAS;AAChB,YAAM,UAAU,YAAY;AAC5B,YAAM,MAAM,aAAa,UAAU,IAAI;AACvC,UAAI,OAAO,YAAY,UAAU;AAC/B,YAAI,OAAO;AAAA,MACb,OAAO;AACL,YAAI,GAAG,OAAO;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAAA,EACA,iBAAiB,KAAqB;AAEpC,WAAO,GAAG,GAAG,IAAI,kBAAkB;AAAA,EACrC;AACF;AAEA,IAAI,kBAAkB;AAEf,SAAS,WAAWC,OAAc;AACvC,sBAAoB,KAAK;AAAA,IACvB,GAAG,OAAO,OAAO,QAAQ,EAAE,IAAI,CAACA,UAASA,MAAK,MAAM;AAAA,EACtD;AACA,SAAO,GAAGA,KAAI,IAAI,OAAO,kBAAkB,CAAC;AAC9C;AAEO,SAAS,eAAe,UAAkB;AAC/C,QAAM,WAAW,KAAK;AAAA,IACpB,QAAQ,IAAI,YAAY,KAAK,QAAQ,IAAI;AAAA,IACzC;AAAA,EACF;AACA,SAAO,WAAW,WAAW;AAC/B;AAEO,SAAS,aAAa,QAAuB;AAClD,MAAI,WAAW,MAAM;AACnB,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,MAAM;AACvB;;;AErjBO,IAAM,uBAAuB;AAAA,EAClC,aACE;AAAA,EACF,MAAM;AAAA,EACN,YAAY;AAAA,IACV,cAAc;AAAA,MACZ,aACE;AAAA,MACF,MAAM;AAAA,IACR;AAAA,IACA,WAAW;AAAA,MACT,aACE;AAAA,MACF,OAAO;AAAA,QACL;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,YACL,MAAM;AAAA,UACR;AAAA,QACF;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,IACA,oBAAoB;AAAA,MAClB,aACE;AAAA,MACF,OAAO;AAAA,QACL;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,YACL,MAAM;AAAA,UACR;AAAA,QACF;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,aACE;AAAA,MACF,MAAM;AAAA,IACR;AAAA,IACA,SAAS;AAAA,MACP,aACE;AAAA,MACF,MAAM;AAAA,IACR;AAAA,IACA,YAAY;AAAA,MACV,aACE;AAAA,MACF,MAAM;AAAA,IACR;AAAA,IACA,SAAS;AAAA,MACP,aACE;AAAA,MACF,OAAO;AAAA,QACL;AAAA,UACE,MAAM,CAAC,OAAO,UAAU,UAAU,IAAI;AAAA,QACxC;AAAA,QACA;AAAA,UACE,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ,aACE;AAAA,MACF,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EACA,SAAS;AACX;","names":["path","name"]}