Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

59 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

ESLint Plugin Zero Tolerance

@coderrob/eslint-plugin-zero-tolerance

77 opinionated ESLint rules for TypeScript teams that refuse to compromise on code quality.

npm version License Coverage threshold: at least 95% ESLint TypeScript


Zero tolerance means every rule earns its place. No warnings you learn to ignore. No exceptions you forget about. Every violation is a conversation about quality โ€” and quality always wins.

Why Zero Tolerance?

Most linting setups start strict and erode over time. A scattered eslint-disable here, an any cast there, and before long the rules exist in name only.

This plugin takes the opposite approach:

  • No eslint-disable comments โ€” fix the root cause, don't silence the symptom.
  • No any smuggling โ€” type assertions and non-null assertions are flagged.
  • No magic values โ€” every number and string earns a name.
  • No leaky tests โ€” persistent mocks, imprecise matchers, and timer abuse are caught.
  • No complexity hiding โ€” functions stay short, parameters stay few, imports stay clean.

The result is a codebase where the rules are the culture and the culture is visible in every file.


Documentation

Hosted docs https://coderrob.github.io/eslint-config-zero-tolerance/
Rules reference docs/rules/index.md
Configuration guide docs/configuration.md

Packages

This monorepo publishes one package:

Package Description
@coderrob/eslint-plugin-zero-tolerance The ESLint plugin โ€” 77 custom rules

packages/config is retained as an internal workspace package for development and compatibility testing; it is not published to npm.

Requirements

  • ESLint 8.57.0+, 9.x, or 10.x
  • TypeScript-ESLint 8.x
  • TypeScript 5.x

Installation

npm install --save-dev @coderrob/eslint-plugin-zero-tolerance @typescript-eslint/parser

Usage

ESLint 9+ (Flat Config)

Using the recommended preset:

// eslint.config.js
import zeroTolerance from '@coderrob/eslint-plugin-zero-tolerance';

export default [
  zeroTolerance.configs.recommended,
  // your other configs...
];

Using the strict preset:

// eslint.config.js
import zeroTolerance from '@coderrob/eslint-plugin-zero-tolerance';

export default [
  zeroTolerance.configs.strict,
  // your other configs...
];

Custom configuration:

// eslint.config.js
import zeroTolerance from '@coderrob/eslint-plugin-zero-tolerance';

export default [
  {
    plugins: {
      'zero-tolerance': zeroTolerance,
    },
    rules: {
      'zero-tolerance/require-interface-prefix': 'error',
      'zero-tolerance/no-throw-literal': 'error',
      'zero-tolerance/max-function-lines': ['warn', { max: 40 }],
      // ... other rules
    },
  },
];

ESLint 8.x (Legacy Config)

Using .eslintrc.js:

module.exports = {
  plugins: ['@coderrob/zero-tolerance'],
  extends: ['plugin:@coderrob/zero-tolerance/legacy-recommended'],
  // or for strict mode:
  // extends: ['plugin:@coderrob/zero-tolerance/legacy-strict'],
};

Rules

The plugin ships 77 rules across 8 categories. The grouped catalog below is exhaustive and links every rule to its dedicated documentation page.

Preset columns report the configured severity: ๐Ÿ’ผ for error, โš ๏ธ for warn, and ๐Ÿšซ for off. A blank cell means the preset does not configure the rule.

Category Rules Focus
Naming Conventions 1 Interface naming standards
Documentation 5 JSDoc, BDD specs, optional chaining, readonly props
Testing 8 Test descriptions, mocks, timers, fetch, interfaces
Type Safety 12 Assertions, unions, imports, exported types
Code Quality 16 Function size, magic values, immutability, sorting
Error Handling 3 Throw safety, empty catches, Result patterns
Imports 12 Barrels, re-exports, dynamic imports, node protocol
Bug Prevention 20 Identical code, control flow, async safety

๐Ÿ—‚๏ธ The type of rule.
โ— Identifies problems that could cause errors or unexpected behavior.
๐Ÿ“– Identifies potential improvements.
๐Ÿ’ผ Configurations enabled in.
โš ๏ธ Configurations set to warn in.
๐Ÿšซ Configurations disabled in.
R Set in the recommended configuration.
S Set in the strict configuration.

Naming Conventions

Interface naming standards

Name ๐Ÿ—‚๏ธ ๐Ÿ’ผ โš ๏ธ ๐Ÿšซ Description
require-interface-prefix ๐Ÿ“– S R Enforce that interface names start with "I"

Documentation

JSDoc, BDD specs, optional chaining, readonly props

Nameย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  ๐Ÿ—‚๏ธ ๐Ÿ’ผ โš ๏ธ ๐Ÿšซ Description
require-bdd-spec ๐Ÿ“– R S Enforce sibling, source-reference, and export relationships for BDD specs
require-jsdoc-anonymous-functions ๐Ÿ“– R S Require JSDoc comments on anonymous function-like constructs except in test files and known test callbacks
require-jsdoc-functions ๐Ÿ“– S R Require JSDoc comments on all functions and require @param/@returns/@throws tags when applicable (except in test files)
require-optional-chaining ๐Ÿ“– S R Require optional chaining instead of repeated logical guard access
require-readonly-props ๐Ÿ“– S R Require readonly typing for JSX component props

Testing

Test descriptions, mocks, timers, fetch, interfaces

Nameย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  ๐Ÿ—‚๏ธ ๐Ÿ’ผ โš ๏ธ ๐Ÿšซ Description
no-fetch-in-tests ๐Ÿ“– R S Disallow fetch usage in test files
no-jest-have-been-called ๐Ÿ“– S R Prohibit toBeCalled, toHaveBeenCalled, toBeCalledWith, toHaveBeenCalledWith, toHaveBeenLastCalledWith, and toLastCalledWith; use toHaveBeenCalledTimes with an explicit call count and toHaveBeenNthCalledWith with an explicit nth-call index and arguments instead
no-mock-implementation ๐Ÿ“– S R Prohibit persistent mock implementations; use the Once variants to avoid test bleeds
no-restricted-imports-in-tests ๐Ÿ“– R S Disallow restricted dependency imports in test files
no-set-interval-in-tests ๐Ÿ“– S R Disallow setInterval usage in test files
no-set-timeout-in-tests ๐Ÿ“– S R Disallow setTimeout usage in test files
no-test-interface-declaration ๐Ÿ“– S R Disallow interface declarations in test files; import production types instead
require-test-description-style ๐Ÿ“– S R Enforce that test descriptions start with "should"

Type Safety

Assertions, unions, imports, exported types

Nameย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  ๐Ÿ—‚๏ธ ๐Ÿ’ผ โš ๏ธ ๐Ÿšซ Description
no-destructured-parameter-type-literal ๐Ÿ“– S R Disallow inline object type literals on destructured parameters; require a named type instead
no-explicit-any โ— S R Disallow explicit any; model unknown values precisely and narrow them explicitly
no-indexed-access-types โ— S R Disallow TypeScript indexed access types
no-inline-type-import โ— S R Disallow TypeScript inline type imports using import("...")
no-literal-property-unions ๐Ÿ“– S R Require property literal unions to use named domain types
no-literal-unions ๐Ÿ“– S R Ban literal unions in favor of enums
no-non-null-assertion โ— S R Disallow non-null assertions using the "!" postfix operator
no-return-type โ— S R Disallow TypeScript ReturnType utility usage
no-type-assertion ๐Ÿ“– S R Prevent use of TypeScript "as" type assertions
no-unsafe-json-parse โ— S R Disallow treating JSON.parse results as typed data without validation
require-exported-object-type ๐Ÿ“– S R Require exported object constants to declare an explicit type annotation
require-union-type-alias ๐Ÿ“– S R Require inline union types with three or more members and multiple type references to be extracted into named type aliases

Code Quality

Function size, magic values, immutability, sorting

Nameย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  ๐Ÿ—‚๏ธ ๐Ÿ’ผ โš ๏ธ ๐Ÿšซ Description
max-function-lines ๐Ÿ“– S R Enforce a maximum number of lines per function body
max-params ๐Ÿ“– S R Enforce a maximum number of function parameters
no-array-mutation ๐Ÿ“– S R Disallow mutating array methods; prefer immutable alternatives such as spread, slice, and toSorted
no-date-now ๐Ÿ“– S R Disallow Date.now() and new Date(); prefer injected clocks for deterministic behavior
no-magic-numbers ๐Ÿ“– S R Disallow magic numbers; use named constants instead of raw numeric literals
no-magic-strings ๐Ÿ“– S R Disallow magic strings in comparisons and switch cases; use named constants instead
no-map-set-mutation ๐Ÿ“– S R Disallow direct Map and Set mutation methods; rebuild collections instead of mutating them in place
no-object-mutation ๐Ÿ“– S R Disallow direct object-property mutation; prefer creating new objects with immutable update patterns
no-placeholder-implementation โ— S R Disallow placeholder, stub, TODO, and not implemented production code
prefer-nullish-coalescing ๐Ÿ“– S R Prefer nullish coalescing instead of a nullish guard ternary
prefer-object-spread ๐Ÿ“– S R Enforce object spread syntax instead of Object.assign with an empty object literal as the first argument
prefer-readonly-parameters ๐Ÿ“– S R Prefer readonly typing for object and array-like parameters to prevent accidental mutation of inputs
prefer-string-raw ๐Ÿ“– S R Prefer String.raw for string literals containing escaped backslashes (Sonar S7780)
prefer-structured-clone ๐Ÿ“– S R Prefer structuredClone(...) over JSON.parse(JSON.stringify(...)) when creating a deep clone
sort-functions ๐Ÿ“– S R Require top-level functions to be sorted alphabetically
sort-imports ๐Ÿ“– S R Require import declarations to be grouped (side-effect -> builtin -> external -> parent -> peer -> index) and sorted alphabetically within each group

Error Handling

Throw safety, empty catches, Result patterns

Nameย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  ๐Ÿ—‚๏ธ ๐Ÿ’ผ โš ๏ธ ๐Ÿšซ Description
no-empty-catch โ— S R Disallow empty catch blocks that silently swallow errors
no-throw-literal โ— S R Disallow throwing literals, objects, or templates; always throw a new Error instance
prefer-result-return ๐Ÿ“– S R Prefer Result-style return values instead of throw statements to make error flows explicit and composable

Imports

Barrels, re-exports, dynamic imports, node protocol

Nameย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  ๐Ÿ—‚๏ธ ๐Ÿ’ผ โš ๏ธ ๐Ÿšซ Description
no-barrel-parent-imports ๐Ÿ“– S R Disallow parent-directory imports (.. and ../*) inside barrel files (index.*) across import declarations, import expressions, require calls, and import-equals declarations
no-dynamic-import โ— S R Ban await import() and require() except in test files
no-export-alias ๐Ÿ“– S R Prevent use of alias in export statements
no-hardcoded-secrets โ— S R Disallow hardcoded secrets, credentials, tokens, and secret env defaults
no-parent-internal-access ๐Ÿ“– R S Disallow parent-relative access into protected internal directories such as src
no-raw-sql-interpolation โ— S R Disallow interpolated raw SQL and unsafe raw query helpers
no-re-export ๐Ÿ“– S R Disallow direct or indirect re-export statements from parent or ancestor modules; barrel files (index.*) are exempt from this restriction
no-shell-command-construction โ— S R Disallow shell command construction through subprocess APIs
no-unsafe-code-generation โ— S R Disallow eval, Function constructors, string timers, and vm code execution APIs
require-barrel-relative-exports ๐Ÿ“– S R Require barrel re-export declarations to use current-directory descendant paths that start with './'
require-clean-barrel ๐Ÿ“– S R Require barrel files (index.*) to contain only module re-export declarations
require-node-protocol ๐Ÿ“– S R Require Node.js built-in module imports to use the node: protocol prefix

Bug Prevention

Identical code, control flow, async safety

Nameย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  ๐Ÿ—‚๏ธ ๐Ÿ’ผ โš ๏ธ ๐Ÿšซ Description
no-await-in-loop โ— S R Disallow await expressions inside loops; use Promise.all() for parallel execution
no-boolean-return-trap ๐Ÿ“– S R Disallow ambiguous boolean-return APIs; prefer predicate naming or richer result types for clearer call sites
no-eslint-disable ๐Ÿ“– S R Prevent use of eslint-disable comments
no-flag-argument ๐Ÿ“– S R Disallow boolean flag arguments in function declarations; prefer explicit methods or command objects
no-floating-promises โ— S R Disallow floating promises; explicitly handle with await, void, or rejection handlers
no-for-in โ— S R Disallow for..in loops; use Object.keys/values/entries to avoid prototype-chain iteration
no-identical-branches ๐Ÿ“– S R Disallow identical if/else and conditional-expression branches; consolidate duplicate conditional fragments
no-identical-expressions โ— S R Disallow identical expressions on both sides of a binary or logical operator (Sonar S1764)
no-labels โ— S R Disallow labels because they make control flow harder to reason about
no-math-random โ— S R Disallow Math.random(); inject randomness explicitly or use a dedicated random source
no-parameter-reassign ๐Ÿ“– S R Disallow assignments and updates to function parameters; use a new local variable instead
no-process-env-outside-config โ— S R Disallow process.env reads outside configuration modules; import typed config instead
no-query-side-effects ๐Ÿ“– S R Disallow side effects in query-style functions (get*/is*/has*/can*/should*); separate query from modifier
no-redundant-boolean ๐Ÿ“– S R Disallow redundant comparisons to boolean literals (Sonar S1125)
no-ts-nocheck โ— S R Prevent use of @ts-nocheck comments
no-with โ— S R Disallow with statements because they make scope resolution unpredictable
prefer-guard-clauses ๐Ÿ“– S R Prefer guard clauses by disallowing else blocks when the if branch already terminates control flow
prefer-shortcut-return ๐Ÿ“– S R Prefer shortcut boolean returns by replacing if/return true-false patterns with direct return expressions
require-exhaustive-switch ๐Ÿ“– S R Require exhaustive switch statements over finite union, enum, and boolean discriminants
require-timeout-for-io โ— S R Require timeout or cancellation options for external IO calls

Development

This repository itself is a pnpm workspace and dogfoods its own rules through eslint.config.mjs. Every source file in the plugin must pass the same rules it enforces on consumers.

Setup

pnpm install

Building

pnpm build

Testing

pnpm test

Coverage gates are enforced per-file at 95% minimum across statements, branches, functions, and lines. The static badge reports this enforced contract rather than a generated point-in-time percentage.

README Sync

pnpm readme:sync
pnpm validate:readme

eslint-doc-generator builds the root rule catalog from the published plugin shape and deterministic category metadata in scripts/metadata/readme-rule-catalog.json. It verifies rule documentation links and derives error, warning, and off states from the exported presets.

Type Checking

pnpm --filter @coderrob/eslint-plugin-zero-tolerance exec tsc -p tsconfig.json --noEmit
pnpm --filter @coderrob/eslint-config-zero-tolerance exec tsc -p tsconfig.json --noEmit

Dependency Graph

pnpm deps:graph
pnpm deps:circular

Publishing

Only @coderrob/eslint-plugin-zero-tolerance is published. Update its version and the dated changelog entry in the release PR, then run the full validation suite. After that commit has passed CI, publish from a clean, authenticated checkout:

pnpm lint
pnpm test
pnpm release:publish:plugin

The publish command targets only packages/plugin; its prepack lifecycle rebuilds the package before pnpm publish --access public. The internal config workspace package is not published.

License

Apache 2.0 Copyright Robert Lindley

About

Zero-tolerance ESLint plugin and config for enforcing strict code quality standards.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages