New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

eslint-seatbelt

Package Overview
Dependencies
Maintainers
0
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-seatbelt - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

dist/chunk-AFWUC23D.js

12

dist/api.d.ts

@@ -62,3 +62,3 @@ /** Uses posix open(2) O_EXCL to implement a multi-process mutual exclusion lock. */

declare const SEATBELT_FILE_NAME = "eslint.seatbelt.tsv";
declare const SEATBELT_FILE_NAME = "eslint.eslint.seatbelt.tsv";
declare const SEATBELT_FROZEN = "SEATBELT_FROZEN";

@@ -111,3 +111,3 @@ declare const SEATBELT_INCREASE = "SEATBELT_INCREASE";

* rules: {
* "eslint-seatbelt/configure": ["error", { seatbeltFile: "some/path/seatbelt.tsv" }]
* "eslint-seatbelt/configure": ["error", { seatbeltFile: "some/path/eslint.seatbelt.tsv" }]
* },

@@ -121,3 +121,3 @@ * },

* ```bash
* SEATBELT_FILE=some/path/seatbelt.tsv SEATBELT_FROZEN=1 eslint
* SEATBELT_FILE=some/path/eslint.seatbelt.tsv SEATBELT_FROZEN=1 eslint
* ```

@@ -130,3 +130,3 @@ */

*
* If not provided, $SEATBELT_PWD/seatbelt.tsv or $PWD/seatbelt.tsv will be used.
* If not provided, $SEATBELT_PWD/eslint.seatbelt.tsv or $PWD/eslint.seatbelt.tsv will be used.
*

@@ -140,5 +140,5 @@ * ```js

* // commonjs
* seatbeltFile: `${__dirname}/seatbelt.tsv`
* seatbeltFile: `${__dirname}/eslint.seatbelt.tsv`
* // esm
* seatbeltFile: new URL('./seatbelt.tsv', import.meta.url).pathname
* seatbeltFile: new URL('./eslint.seatbelt.tsv', import.meta.url).pathname
* }

@@ -145,0 +145,0 @@ * }

@@ -5,3 +5,3 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true});

var _chunkAYRXDXKNjs = require('./chunk-AYRXDXKN.js');
var _chunkAFWUC23Djs = require('./chunk-AFWUC23D.js');

@@ -26,3 +26,3 @@

var _chunk2DG4G5KOjs = require('./chunk-2DG4G5KO.js');
var _chunkNKPPNIO7js = require('./chunk-NKPPNIO7.js');

@@ -44,3 +44,3 @@ // src/FileLock.ts

} catch (e) {
if (_chunkAYRXDXKNjs.isErrno.call(void 0, e, "EEXIST")) {
if (_chunkAFWUC23Djs.isErrno.call(void 0, e, "EEXIST")) {
return false;

@@ -80,3 +80,3 @@ }

// src/api.ts
_chunk2DG4G5KOjs.init_SeatbeltConfig.call(void 0, );
_chunkNKPPNIO7js.init_SeatbeltConfig.call(void 0, );

@@ -103,3 +103,3 @@

exports.FileLock = FileLock; exports.SEATBELT_DISABLE = _chunk2DG4G5KOjs.SEATBELT_DISABLE; exports.SEATBELT_FILE = _chunk2DG4G5KOjs.SEATBELT_FILE; exports.SEATBELT_FILE_NAME = _chunk2DG4G5KOjs.SEATBELT_FILE_NAME; exports.SEATBELT_FROZEN = _chunk2DG4G5KOjs.SEATBELT_FROZEN; exports.SEATBELT_INCREASE = _chunk2DG4G5KOjs.SEATBELT_INCREASE; exports.SEATBELT_KEEP = _chunk2DG4G5KOjs.SEATBELT_KEEP; exports.SEATBELT_PWD = _chunk2DG4G5KOjs.SEATBELT_PWD; exports.SEATBELT_THREADSAFE = _chunk2DG4G5KOjs.SEATBELT_THREADSAFE; exports.SEATBELT_VERBOSE = _chunk2DG4G5KOjs.SEATBELT_VERBOSE; exports.SeatbeltArgs = _chunk2DG4G5KOjs.SeatbeltArgs; exports.SeatbeltConfig = _chunk2DG4G5KOjs.SeatbeltConfig; exports.SeatbeltConfigSchema = _chunkAYRXDXKNjs.SeatbeltConfigSchema; exports.SeatbeltEnv = _chunk2DG4G5KOjs.SeatbeltEnv; exports.SeatbeltFile = _chunkAYRXDXKNjs.SeatbeltFile; exports.formatFilename = _chunk2DG4G5KOjs.formatFilename; exports.formatRuleId = _chunk2DG4G5KOjs.formatRuleId; exports.logStderr = _chunk2DG4G5KOjs.logStderr; exports.logStdout = _chunk2DG4G5KOjs.logStdout; exports.padVarName = _chunk2DG4G5KOjs.padVarName;
exports.FileLock = FileLock; exports.SEATBELT_DISABLE = _chunkNKPPNIO7js.SEATBELT_DISABLE; exports.SEATBELT_FILE = _chunkNKPPNIO7js.SEATBELT_FILE; exports.SEATBELT_FILE_NAME = _chunkNKPPNIO7js.SEATBELT_FILE_NAME; exports.SEATBELT_FROZEN = _chunkNKPPNIO7js.SEATBELT_FROZEN; exports.SEATBELT_INCREASE = _chunkNKPPNIO7js.SEATBELT_INCREASE; exports.SEATBELT_KEEP = _chunkNKPPNIO7js.SEATBELT_KEEP; exports.SEATBELT_PWD = _chunkNKPPNIO7js.SEATBELT_PWD; exports.SEATBELT_THREADSAFE = _chunkNKPPNIO7js.SEATBELT_THREADSAFE; exports.SEATBELT_VERBOSE = _chunkNKPPNIO7js.SEATBELT_VERBOSE; exports.SeatbeltArgs = _chunkNKPPNIO7js.SeatbeltArgs; exports.SeatbeltConfig = _chunkNKPPNIO7js.SeatbeltConfig; exports.SeatbeltConfigSchema = _chunkAFWUC23Djs.SeatbeltConfigSchema; exports.SeatbeltEnv = _chunkNKPPNIO7js.SeatbeltEnv; exports.SeatbeltFile = _chunkAFWUC23Djs.SeatbeltFile; exports.formatFilename = _chunkNKPPNIO7js.formatFilename; exports.formatRuleId = _chunkNKPPNIO7js.formatRuleId; exports.logStderr = _chunkNKPPNIO7js.logStderr; exports.logStdout = _chunkNKPPNIO7js.logStdout; exports.padVarName = _chunkNKPPNIO7js.padVarName;
//# sourceMappingURL=api.js.map

@@ -7,13 +7,13 @@ #!/usr/bin/env -S pnpm exec tsx

var _chunk2DG4G5KOjs = require('./chunk-2DG4G5KO.js');
var _chunkNKPPNIO7js = require('./chunk-NKPPNIO7.js');
// src/command.ts
var require_command = _chunk2DG4G5KOjs.__commonJS.call(void 0, {
var require_command = _chunkNKPPNIO7js.__commonJS.call(void 0, {
"src/command.ts"(exports, module) {
_chunk2DG4G5KOjs.init_SeatbeltConfig.call(void 0, );
_chunkNKPPNIO7js.init_SeatbeltConfig.call(void 0, );
function main() {
_chunk2DG4G5KOjs.logStderr.call(void 0, "command not implemented");
_chunkNKPPNIO7js.logStderr.call(void 0, "command not implemented");
process.exit(1);
}
if (_chunk2DG4G5KOjs.__require.main === module) {
if (_chunkNKPPNIO7js.__require.main === module) {
main();

@@ -20,0 +20,0 @@ }

@@ -5,3 +5,3 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } 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 _chunkAYRXDXKNjs = require('./chunk-AYRXDXKN.js');
var _chunkAFWUC23Djs = require('./chunk-AFWUC23D.js');

@@ -20,14 +20,14 @@

var _chunk2DG4G5KOjs = require('./chunk-2DG4G5KO.js');
var _chunkNKPPNIO7js = require('./chunk-NKPPNIO7.js');
// src/index.ts
_chunk2DG4G5KOjs.init_package.call(void 0, );
_chunkNKPPNIO7js.init_package.call(void 0, );
// src/SeatbeltProcessor.ts
_chunk2DG4G5KOjs.init_package.call(void 0, );
_chunk2DG4G5KOjs.init_SeatbeltConfig.call(void 0, );
_chunkNKPPNIO7js.init_package.call(void 0, );
_chunkNKPPNIO7js.init_SeatbeltConfig.call(void 0, );
// src/pluginGlobals.ts
_chunk2DG4G5KOjs.init_SeatbeltConfig.call(void 0, );
_chunk2DG4G5KOjs.init_package.call(void 0, );
_chunkNKPPNIO7js.init_SeatbeltConfig.call(void 0, );
_chunkNKPPNIO7js.init_package.call(void 0, );
var ANY_CONFIG_DISABLED = false;

@@ -47,3 +47,3 @@ var LAST_VERBOSE_ARGS;

if (!envFallbackConfig) {
envFallbackConfig = _chunk2DG4G5KOjs.SeatbeltConfig.fromFallbackEnv(
envFallbackConfig = _chunkNKPPNIO7js.SeatbeltConfig.fromFallbackEnv(
process.env

@@ -57,3 +57,3 @@ );

if (!envOverrideConfig) {
envOverrideConfig = _chunk2DG4G5KOjs.SeatbeltConfig.fromEnvOverrides(
envOverrideConfig = _chunkNKPPNIO7js.SeatbeltConfig.fromEnvOverrides(
process.env

@@ -90,3 +90,3 @@ );

};
args = _chunk2DG4G5KOjs.SeatbeltArgs.fromConfig(compiledConfig);
args = _chunkNKPPNIO7js.SeatbeltArgs.fromConfig(compiledConfig);
ANY_CONFIG_DISABLED ||= args.disable;

@@ -104,5 +104,5 @@ if (args.verbose) {

}
var configureRuleName = `${_chunk2DG4G5KOjs.name}/configure`;
var configureRuleName = `${_chunkNKPPNIO7js.name}/configure`;
function logRuleSetupHint() {
_chunk2DG4G5KOjs.logStderr.call(void 0,
_chunkNKPPNIO7js.logStderr.call(void 0,
`

@@ -116,12 +116,12 @@ Make sure you have rule ${configureRuleName} enabled in your ESLint config for all files:

Docs: https://github.com/justjake/${_chunk2DG4G5KOjs.name}#setup`
Docs: https://github.com/justjake/${_chunkNKPPNIO7js.name}#setup`
);
}
function logConfig(args, baseConfig) {
const log = _chunk2DG4G5KOjs.SeatbeltArgs.getLogger(args);
_chunk2DG4G5KOjs.SeatbeltConfig.fromFallbackEnv(process.env, log);
const log = _chunkNKPPNIO7js.SeatbeltArgs.getLogger(args);
_chunkNKPPNIO7js.SeatbeltConfig.fromFallbackEnv(process.env, log);
for (const [key, value] of Object.entries(baseConfig)) {
log(`${_chunk2DG4G5KOjs.padVarName.call(void 0, "ESLint settings")} config.${key} =`, value);
log(`${_chunkNKPPNIO7js.padVarName.call(void 0, "ESLint settings")} config.${key} =`, value);
}
_chunk2DG4G5KOjs.SeatbeltConfig.fromEnvOverrides(process.env, log);
_chunkNKPPNIO7js.SeatbeltConfig.fromEnvOverrides(process.env, log);
}

@@ -140,3 +140,3 @@ function pushFileArgs(filename, args) {

if (lastLintedFile) {
_chunk2DG4G5KOjs.logStderr.call(void 0,
_chunkNKPPNIO7js.logStderr.call(void 0,
`WARNING: last configured by file \`${lastLintedFile.filename}\` but linting file \`${filename}\`.

@@ -147,3 +147,3 @@ You may have rule ${configureRuleName} enabled for some files, but not this one.

} else {
_chunk2DG4G5KOjs.logStderr.call(void 0,
_chunkNKPPNIO7js.logStderr.call(void 0,
`WARNING: rule ${configureRuleName} not enabled in ESLint config and no SEATBELT environment variables set`

@@ -159,3 +159,3 @@ );

if (!seatbeltFile) {
seatbeltFile = _chunkAYRXDXKNjs.SeatbeltFile.openSync(filename);
seatbeltFile = _chunkAFWUC23Djs.SeatbeltFile.openSync(filename);
seatbeltFileCache.set(filename, seatbeltFile);

@@ -184,3 +184,3 @@ }

// src/SeatbeltProcessor.ts
var { name: name2, version: version2 } = _chunk2DG4G5KOjs.package_default;
var { name: name2, version: version2 } = _chunkNKPPNIO7js.package_default;
var SeatbeltProcessor = {

@@ -261,6 +261,6 @@ supportsAutofix: true,

}
const formatLoc = (message) => `${_chunk2DG4G5KOjs.formatFilename.call(void 0, filename)}:${message.line}:${message.column}`;
const formatLoc = (message) => `${_chunkNKPPNIO7js.formatFilename.call(void 0, filename)}:${message.line}:${message.column}`;
return messages.map((message) => {
if (message.ruleId === null) {
_chunk2DG4G5KOjs.SeatbeltArgs.verboseLog(
_chunkNKPPNIO7js.SeatbeltArgs.verboseLog(
args,

@@ -278,3 +278,3 @@ () => `${formatLoc(message)}: cannot transform message with null ruleId`

const maxErrorCount = _nullishCoalesce(_optionalChain([ruleToMaxErrorCount, 'optionalAccess', _ => _.get, 'call', _2 => _2(message.ruleId)]), () => ( 0));
const allowIncrease2 = _chunk2DG4G5KOjs.SeatbeltArgs.ruleSetHas(
const allowIncrease2 = _chunkNKPPNIO7js.SeatbeltArgs.ruleSetHas(
args.allowIncreaseRules,

@@ -294,5 +294,5 @@ message.ruleId

if (verboseOnce(message.ruleId)) {
_chunk2DG4G5KOjs.SeatbeltArgs.verboseLog(
_chunkNKPPNIO7js.SeatbeltArgs.verboseLog(
args,
() => `${_chunk2DG4G5KOjs.formatFilename.call(void 0, filename)}: ${_chunk2DG4G5KOjs.formatRuleId.call(void 0, message.ruleId)}: error: ${errorCount} ${pluralErrors(errorCount)} found > max ${maxErrorCount}`
() => `${_chunkNKPPNIO7js.formatFilename.call(void 0, filename)}: ${_chunkNKPPNIO7js.formatRuleId.call(void 0, message.ruleId)}: error: ${errorCount} ${pluralErrors(errorCount)} found > max ${maxErrorCount}`
);

@@ -303,5 +303,5 @@ }

if (verboseOnce(message.ruleId)) {
_chunk2DG4G5KOjs.SeatbeltArgs.verboseLog(
_chunkNKPPNIO7js.SeatbeltArgs.verboseLog(
args,
() => `${_chunk2DG4G5KOjs.formatFilename.call(void 0, filename)}: ${_chunk2DG4G5KOjs.formatRuleId.call(void 0, message.ruleId)}: ok: ${errorCount} ${pluralErrors(errorCount)} found == max ${maxErrorCount}`
() => `${_chunkNKPPNIO7js.formatFilename.call(void 0, filename)}: ${_chunkNKPPNIO7js.formatRuleId.call(void 0, message.ruleId)}: ok: ${errorCount} ${pluralErrors(errorCount)} found == max ${maxErrorCount}`
);

@@ -389,3 +389,3 @@ }

message: `${message.message}
[${name2}]: ${_chunk2DG4G5KOjs.SEATBELT_INCREASE}: Temporarily allowing ${increaseCount} new ${pluralErrors(increaseCount)} of this type.
[${name2}]: ${_chunkNKPPNIO7js.SEATBELT_INCREASE}: Temporarily allowing ${increaseCount} new ${pluralErrors(increaseCount)} of this type.
`.trim()

@@ -420,3 +420,3 @@ };

return `
[${name2}]: ${_chunk2DG4G5KOjs.SEATBELT_FROZEN}: Expected ${maxErrorCount} ${pluralErrors(maxErrorCount)}, found ${errorCount}.
[${name2}]: ${_chunkNKPPNIO7js.SEATBELT_FROZEN}: Expected ${maxErrorCount} ${pluralErrors(maxErrorCount)}, found ${errorCount}.
If you fixed ${fixed} ${fixedMessage}, thank you, but you'll need to update the seatbelt file to match.

@@ -438,4 +438,4 @@ Try running eslint, then committing ${seatbeltFilename}.

alreadyModifiedError.add(e);
_chunkAYRXDXKNjs.appendErrorContext.call(void 0, e, `while processing \`${filename}\``);
_chunkAYRXDXKNjs.appendErrorContext.call(void 0,
_chunkAFWUC23Djs.appendErrorContext.call(void 0, e, `while processing \`${filename}\``);
_chunkAFWUC23Djs.appendErrorContext.call(void 0,
e,

@@ -452,10 +452,10 @@ `this may be a bug in ${name2}@${version2} or a problem with your setup`

// src/rules/configure.ts
_chunk2DG4G5KOjs.init_package.call(void 0, );
_chunkNKPPNIO7js.init_package.call(void 0, );
var configure = {
meta: {
docs: {
description: `Applies ${_chunk2DG4G5KOjs.name} configuration from ESLint config`,
url: `https://github.com/justjake/${_chunk2DG4G5KOjs.name}`
description: `Applies ${_chunkNKPPNIO7js.name} configuration from ESLint config`,
url: `https://github.com/justjake/${_chunkNKPPNIO7js.name}`
},
schema: [_chunkAYRXDXKNjs.SeatbeltConfigSchema]
schema: [_chunkAFWUC23Djs.SeatbeltConfigSchema]
},

@@ -466,3 +466,3 @@ create(context) {

const eslintSharedConfigViaShortName = _optionalChain([context, 'access', _7 => _7.settings, 'optionalAccess', _8 => _8.seatbelt]);
const eslintSharedConfigViaPackageName = _optionalChain([context, 'access', _9 => _9.settings, 'optionalAccess', _10 => _10[_chunk2DG4G5KOjs.name]]);
const eslintSharedConfigViaPackageName = _optionalChain([context, 'access', _9 => _9.settings, 'optionalAccess', _10 => _10[_chunkNKPPNIO7js.name]]);
const eslintSharedConfig = _nullishCoalesce(eslintSharedConfigViaShortName, () => ( eslintSharedConfigViaPackageName));

@@ -480,3 +480,3 @@ const fileOverrideConfig = context.options[0];

// src/index.ts
var { name: name3, version: version3 } = _chunk2DG4G5KOjs.package_default;
var { name: name3, version: version3 } = _chunkNKPPNIO7js.package_default;
var plugin = {

@@ -483,0 +483,0 @@ meta: {

{
"name": "eslint-seatbelt",
"version": "0.0.1",
"version": "0.0.2",
"description": "Gradually tighten ESLint rules in your codebase",

@@ -5,0 +5,0 @@ "keywords": [

@@ -5,23 +5,15 @@ # eslint-seatbelt

## Why eslint-seatbelt?
There are a few existing bulk suppression tools for ESLint and other linters, but I found
eslint-seatbelt is an open-source re-implementation of a Notion internal tool written originally written by the same author in 2022. It was originally implemented to manage a multi-year migration to React function components, and has since proven invaluable in maintaining our large, fast-moving codebase with hundreds of active contributors.
- Most other tools store error information in hierarchical formats like JSON or YAML that make merge conflicts confusing and painful. eslint-seatbelt stores errors in TSV - tab-separated values - which minimizes (but doesn't totally eliminate) merge pain.
eslint-seatbelt improves on publicly available bulk suppression tools in a few ways:
Some tools require complicated workflows invasive wrapper scripts, some going so far as to [monkey-patching in a replacement linter implementation](https://developers.tiktok.com/blog/bulk-suppressions-a-new-eslint-feature-for-large-codebases). eslint-seatbelt is a regular ESLint plugin ([using the processor API](https://eslint.org/docs/latest/extend/custom-processors)) so it integrates effortlessly with your editor, pre-commit hooks, and CI. It "tightens the seatbelt" by automatically reducing the allowed errors per file whenever you run `eslint` during development. In CI, state is frozen and checked for consistency with the current file error counts, so no one can forget to tighten the seatbelt.
Most other tools store error information in hierarchical formats like JSON or YAML that make merge conflicts confusing and painful. eslint-seatbelt stores errors in a simple `.tsv` tab-separated values file which minimizes (but doesn't totally eliminate) merge pain.
- Many tools in this genre
Other tools require complicated workflows invasive wrapper scripts, some going so far as to [monkey-patching in a replacement linter implementation](https://developers.tiktok.com/blog/bulk-suppressions-a-new-eslint-feature-for-large-codebases). eslint-seatbelt is a regular ESLint plugin ([using the processor API](https://eslint.org/docs/latest/extend/custom-processors)) so it integrates effortlessly with your editor, pre-commit hooks, and CI. It "tightens the seatbelt" by automatically reducing the allowed errors per file whenever you run `eslint` during development. In CI, state is frozen and checked for consistency with the current file error counts, so no one can forget to tighten the seatbelt.
Error counts are stored in a single `eslint.seatbelt.tsv` file in a line-oriented format that minimizes (but doesn't totally eliminate) merge pain.
eslint-seatbelt tracks the allowed number of errors per file in the `eslint.seatbelt.tsv` file, and reduces the count whenever you run `eslint` after fixing an error. Pair with lint-on-save in your editor or with pre-commit hooks to fully automate the process, although its not required: in CI, `eslint` verifies the `eslint.seatbelt.tsv` file is up-to-date.
## Setup
First, install the plugin: `npm add --save-dev --save-exact eslint-seatbelt`.
First, install the plugin: `npm add --save-dev eslint-seatbelt`.

@@ -33,3 +25,3 @@ Then, add the plugin to your ESLint config:

```js
// eslint.config.js
// eslint.config.mjs
import seatbelt from 'eslint-seatbelt'

@@ -57,6 +49,6 @@

```js
// .eslintrc.js
// .eslintrc.cjs
module.exports = {
"plugins": ["eslint-seatbelt"],
"extends": ["plugin:eslint-seatbelt/enable-legacy"]
plugins: ["eslint-seatbelt"],
extends: ["plugin:eslint-seatbelt/enable-legacy"]
}

@@ -66,5 +58,5 @@

module.exports = {
"plugins": ["eslint-seatbelt"],
"rules": { "eslint-seatbelt/configure": "error" },
"processor": "eslint-seatbelt/seatbelt"
plugins: ["eslint-seatbelt"],
rules: { "eslint-seatbelt/configure": "error" },
processor: "eslint-seatbelt/seatbelt",
}

@@ -75,14 +67,357 @@ ```

### Introducing a new rule
1. Add the rule to your ESLint config in "error" mode. (with eslint-seatbelt, configuring rules in "warning" mode is pointless)
seatbelt views eslint rules configured entirely in "warning" mode pointless: they'll mostly be ignored and just add needless noise to everyone's editor.
```diff
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -18,6 +18,7 @@ export default tseslint.config(
seatbelt.configs.enable,
{
rules: {
+ "@typescript-eslint/ban-ts-comment": "error",
```
### Introducing a new rule
2. Run `SEATBELT_INCREASE=<rule> eslint` to increase allowed errors.
3. Commit the changes to your ESLint config (`eslint.config.mjs`) and seatbelt file (`eslint.seatbelt.tsv`)
### Configuration
### After fixing errors
No further configuration is required to get started. By default eslint-seatbelt will track errors in the `eslint.seatbelt.tsv` file in the current working directory.
1. `eslint`
### Verify seatbelt file is up-to-date
1. `SEATBELT_FROZEN=1 eslint` or `CI=1 eslint`
## Workflow
### Introduce ESLint to an existing codebase
eslint-seatbelt makes it easy to introduce ESLint to an existing unlinted codebase.
1. Install eslint, eslint-seatbelt, and your favorite ESLint plugins: `npm add --save-dev eslint eslint-seatbelt`.
1. Configure plugins, rules, and set up eslint-seatbelt [as described above](#setup).
1. Run `SEATBELT_INCREASE=ALL eslint --fix` to either fix or allow existing errors.
1. Commit changes.
## Configuration
By default eslint-seatbelt stores error counts in a file named `eslint.seatbelt.tsv` in the current working directory. No configuration is required beyond setting up the plugin as described above.
If you prefer to customize this location or other options, you can pass configuration to eslint-seatbelt by one of the following methods:
1. Defined in the shared `settings` object in your ESLint config. This
requires also configuring the `eslint-seatbelt/configure` rule.
```js
// in eslint.config.js
const config = [
{
settings: {
seatbelt: {
// ...
}
},
rules: {
"eslint-seatbelt/configure": "error",
}
}
]
```
2. Using the `eslint-seatbelt/configure` rule in your ESLint config.
This can be used to override settings for specific files in legacy ESLint configs.
Any configuration provided here will override the shared `settings` object.
```js
// in .eslintrc.js
module.exports = {
rules: {
"eslint-seatbelt/configure": "error",
},
overrides: [
{
files: ["some/path/*"],
rules: {
"eslint-seatbelt/configure": ["error", { seatbeltFile: "some/path/eslint.seatbelt.tsv" }]
},
},
],
}
```
3. The settings in config files can be overridden with environment variables when running `eslint` or other tools.
```bash
SEATBELT_FILE=some/path/eslint.seatbelt.tsv SEATBELT_FROZEN=1 eslint
```
### Config reference
Copied from [./src/SeatbeltConfig.ts](./src/SeatbeltConfig.ts)
```typescript
export interface SeatbeltConfig {
/**
* The seatbelt file stores the max error counts allowed for each file. Should
* be an absolute path.
*
* If not provided, $SEATBELT_PWD/eslint.seatbelt.tsv or $PWD/eslint.seatbelt.tsv will be used.
*
* ```js
* // in eslint.config.js
* const config = [
* {
* settings: {
* seatbelt: {
* // commonjs
* seatbeltFile: `${__dirname}/eslint.seatbelt.tsv`
* // esm
* seatbeltFile: new URL('./eslint.seatbelt.tsv', import.meta.url).pathname
* }
* }
* }
* ]
* ```
*
* You can also set this with environment variable `SEATBELT_FILE`:
*
* ```bash
* SEATBELT_FILE=.config/custom-seatbelt-file eslint
* ```
*/
seatbeltFile?: string
/**
* By default whenever a file is linted and a rule has no errors, that rule's
* max errors for the file is set to zero.
*
* However with typescript-eslint, it can be helpful to have two ESLint configs:
*
* - A default ESLint config with only syntactic rules enabled that don't
* require typechecking, that runs on developer machines and in their editor.
* - A CI-only ESLint config with only type-aware rules enabled that requires
* typechecking. Since these rules require typechecking, they can be too
* slow to run in interactive contexts.
*
* To avoid seatbelt from mistakenly removing
*
* To avoid this, set `keepRules` to the names of *disabled but known rules*
* while linting.
*
* Example:
*
* ```js
* // Default ESLint config
* module.exports = [
* {
* settings: {
* seatbelt: {
* keepRules: require('./eslint-typed.config.js').flatMap(config => Object.keys(config.rules ?? {})),
* }
* },
* rules: {
* "no-unused-vars": "error",
* },
* }
* ]
*
* // Typechecking-required ESLint config for CI
* module.exports = [
* {
* settings: {
* seatbelt: {
* keepRules: require('./eslint.config.js').flatMap(config => Object.keys(config.rules ?? {})),
* }
* },
* rules: {
* // Requires typechecking (slow)
* "@typescript-eslint/no-floating-promises": "error",
* },
* }
* ]
* ```
*
* You can also set this with environment variable `SEATBELT_KEEP`:
*
* ```bash
* SEATBELT_KEEP="@typescript-eslint/no-floating-promises @typescript-eslint/prefer-reduce-type-parameter" \
* eslint
* ```
*
* You can set this to `"ALL"` to enable this setting for ALL rules:
*
* ```bash
* SEATBELT_KEEP=ALL eslint
* ```
*/
keepRules?: RuleId[] | "all"
/**
* When you enable a rule for the first time, lint with it in this set to set
* the initial max error counts.
*
* Typically this should be enabled for one lint run only via an environment
* variable, but it can also be configured via ESLint settings.
*
* ```bash
* SEATBELT_INCREASE="@typescript-eslint/no-floating-promises" eslint
* ```
*
* You can set this to `"ALL"` to enable this setting for ALL rules:
*
* ```bash
* SEATBELT_INCREASE=ALL eslint
* ```
*
* ```js
* // in eslint.config.js
* // maybe you have a use-case for this
* const config = [
* {
* settings: {
* seatbelt: {
* allowIncreaseRules: ["@typescript-eslint/no-floating-promises"],
* }
* }
* }
* ]
* ```
*/
allowIncreaseRules?: RuleId[] | "all"
/**
* Error if there is any change in the number of errors in the seatbelt file.
* This is useful in CI to ensures that developers keep the seatbelt file up-to-date as they fix errors.
*
* It is enabled by default when environment variable `CI` is set.
*
* ```bash
* CI=1 eslint
* ```
*
* This can be set with the `SEATBELT_FROZEN` environment variable.
*
* ```bash
* SEATBELT_FROZEN=1 eslint
* ```
*
* Or in ESLint config:
*
* ```js
* // in eslint.config.js
* const config = [
* {
* settings: {
* seatbelt: {
* frozen: true,
* }
* }
* }
* ]
*/
frozen?: boolean
/**
* Completely disable seatbelt error processing for a lint run while leaving it otherwise configured.
*
* This can be set with the `SEATBELT_DISABLE` environment variable.
*
* ```bash
* SEATBELT_DISABLE=1 eslint
* ```
*
* Or in ESLint config:
*
* ```js
* // in eslint.config.js
* const config = [
* {
* settings: {
* seatbelt: {
* disable: true,
* }
* }
* }
* ]
*/
disable?: boolean
/**
* By default seatbelt assumes that only one ESLint process will read and
* write to the seatbelt file at a time.
*
* This should be set to `true` if you use a parallel ESLint runner similar to
* jest-runner-eslint to avoid losing updates during parallel writes to the
* seatbelt file.
*
* When enabled, seatbelt creates temporary lock files to serialize updates to
* the seatbelt file. This comes at a small performance cost.
*
* This is enabled by default when run with Jest (environment variable `JEST_WORKER_ID` is set).
*
* It can also be set with environment variable `SEATBELT_THREADSAFE`:
*
* ```bash
* SEATBELT_THREADSAFE=1 eslint-parallel
* ```
*
* Or in ESLint config:
*
* ```js
* // in eslint.config.js
* const config = [
* {
* settings: {
* seatbelt: {
* threadsafe: true,
* }
* }
* }
* ]
* ```
*/
threadsafe?: boolean
/**
* Enable verbose logging.
*
* This can be set with the `SEATBELT_VERBOSE` environment variable.
*
* ```bash
* SEATBELT_VERBOSE=1 eslint
* ```
*
* Or in ESLint config:
*
* ```js
* // in eslint.config.js
* const config = [
* {
* settings: {
* seatbelt: {
* verbose: true,
* }
* }
* }
* ]
* ```
*
* If set to a function (like `console.error`), that function will be called with the log messages.
* The default logger when set to `true` is `console.error`.
*/
verbose?: boolean | "stdout" | "stderr" | ((...message: unknown[]) => void)
}
```
## Contributing
This project uses `pnpm` for package management.
### Improvement ideas
- [ ] Finish SEATBELT_THREADSAFE implementation
- [ ] Set SEATBELT_DISABLE=1 during git merge/rebase events
- [ ] Add SEATBELT_DISABLE_IN_EDITOR config option
- [ ] Integration tests
- [ ] Git merge driver to automatically resolve eslint.seatbelt.tsv conflicts
## Thanks
- Dedicated to [Nora Tarano](https://github.com/noratarano), who inspired me to write the open-source version. I love you.
- Thank you to [Ben Kraft](https://github.com/benjaminjkraft) for improvements to the Notion internal version, and for discussing changes for the open-source version.
- Thank you to Notion Labs, Inc for supporting engineering excellence. If you like this sort of thing, consider [joining us](https://www.notion.com/careers)!

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc