Skip to content

chore(lint): migrate to Biome (ultracite) + lefthook#65

Merged
AZagatti merged 2 commits into
mainfrom
chore/biome-lefthook
Jun 24, 2026
Merged

chore(lint): migrate to Biome (ultracite) + lefthook#65
AZagatti merged 2 commits into
mainfrom
chore/biome-lefthook

Conversation

@AZagatti

Copy link
Copy Markdown
Collaborator

Summary

Replaces the ESLint (airbnb) + Prettier + (dead) Husky stack with Biome via the Ultracite preset, and adds lefthook for git hooks. Not a 1:1 port — adopts Ultracite's stricter ruleset and applies its safe improvements.

Tooling

  • biome.jsonc extends ultracite/biome/core + ultracite/biome/vitest. Formatter is matched to the old Prettier config (single quotes, trailing-comma all, arrow parens as-needed) → no quote/spacing churn.
  • Scripts: lintbiome check ./src, new lint:fix, formatbiome format --write ./src, preparelefthook install.
  • lefthook.yml: pre-commit runs biome check --write on staged files with stage_fixed: true — verified it auto-formats and re-stages. Replaces the never-wired husky + lint-staged.
  • Removed: eslint, @eslint/*, @typescript-eslint/*, airbnb-base, eslint-config-prettier, eslint-plugin-import, eslint-import-resolver-typescript, eslint-plugin-prettier, prettier, husky, lint-staged, globals. Deleted eslint.config.js, .prettierrc, .prettierignore. Dropped the now-unused unrs-resolver from allowBuilds.

Code improvements (behavior-preserving — 110 tests green)

  • Number namespace (parseIntNumber.parseInt, identical fn), numeric separators, explicit block statements.
  • forEachfor...of in validators and tests.
  • Hoisted regex literals to module scope.
  • Explicit type on an evolving let.

Rules disabled (with inline justification in biome.jsonc)

Rule Why
noSubstr code uses String.substring (not deprecated substr); slice would change edge-case semantics in checksum logic
useFilenamingConvention file names (validateCPF.ts) are the public import API
noBarrelFile index.ts barrels are the package entry points
useAtIndex .at() is es2022; tsconfig targets es2016
noNamespaceImport / noDynamicNamespaceImportAccess (ie/index.ts only) intentional UF→validator registry

Verification (Node 22)

pnpm build · ✅ pnpm coverage (110 tests) · ✅ pnpm lint (Biome) · ✅ tsc --noEmit · ✅ pnpm test:e2e · ✅ lefthook pre-commit hook tested live

🤖 Generated with Claude Code

…thook

Replace the ESLint/airbnb + Prettier + (dead) Husky stack with Biome via
the Ultracite preset, and add lefthook for git hooks.

Tooling:
- biome.jsonc extends ultracite/biome/{core,vitest}; formatter matched to
  the old Prettier style (single quotes, trailing-comma all, arrow parens
  as-needed) so there is no quote/spacing churn.
- Scripts: `lint` -> `biome check ./src`, add `lint:fix`, `format` ->
  `biome format --write ./src`, `prepare` -> `lefthook install`.
- lefthook.yml: pre-commit runs `biome check --write` on staged files
  with stage_fixed. Replaces the never-wired husky + lint-staged setup.
- Removed: eslint, @eslint/*, @typescript-eslint/*, eslint-config-airbnb-base,
  eslint-config-prettier, eslint-plugin-import, eslint-import-resolver-typescript,
  eslint-plugin-prettier, prettier, husky, lint-staged, globals; deleted
  eslint.config.js, .prettierrc, .prettierignore. Dropped the now-unused
  unrs-resolver from allowBuilds.

Code improvements applied (all behavior-preserving, 110 tests still green):
- Number namespace (parseInt -> Number.parseInt, etc.), numeric separators,
  explicit block statements.
- forEach -> for...of in validators and tests.
- Hoisted regex literals to module scope (useTopLevelRegex).
- Explicit type on an evolving `let` (am.ts).

Rules turned off with justification (see biome.jsonc): noSubstr (substring
is intentional and not deprecated), useFilenamingConvention (file names are
the public API), noBarrelFile (index barrels are the entry points),
useAtIndex (.at() is es2022; tsconfig targets es2016), and namespace/dynamic
access for the ie/index.ts validator registry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coveralls

coveralls commented Jun 24, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 91.413% (+0.04%) from 91.377% — chore/biome-lefthook into main

Review follow-ups:
- Remove @types/jest: the suite uses Vitest with explicit imports
  (no jest globals/types referenced anywhere), so the stubs were dead.
- Make the lefthook pre-commit glob explicit (**/*) for readability;
  behaviour is unchanged (lefthook already matches at any depth).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@AZagatti AZagatti merged commit 66a3017 into main Jun 24, 2026
3 checks passed
@AZagatti AZagatti deleted the chore/biome-lefthook branch June 24, 2026 02:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants