build: adopt oxlint and oxfmt#20
Merged
Merged
Conversation
Adopt oxlint as the linter (dev dependency). Enables the typescript, unicorn, oxc, react, and vitest plugins with the `correctness` category as errors, and ignores the generated route tree and build output. Adds a `lint` npm script. Existing violations are fixed in the following commit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014DWovxbG4A7Ebda7xhG9nA
- App.tsx: hoist the empty stop list to a stable module constant so the byNode/locationLabel memos don't recompute every render while the index is loading (react-hooks/exhaustive-deps). - contract tests: assert the specific Schema validation each decode fails on instead of a bare toThrow() (vitest/require-to-throw-message). - stack integration test: narrow the decoded message with a guard and assert the degraded-or-key invariant unconditionally (vitest/no-conditional-expect). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014DWovxbG4A7Ebda7xhG9nA
Adopt oxfmt as the formatter (dev dependency). Config matches the existing house style (no semicolons, double quotes) with printWidth 100, which is the width that reflows the current source the least. Scoped to TS/TSX via ignorePatterns so it leaves package.json (managed by bun), JSON/YAML config, and Markdown docs untouched. Adds `fmt` and `fmt:check` npm scripts. The codebase is reformatted in the following commit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014DWovxbG4A7Ebda7xhG9nA
Apply oxfmt across the TS/TSX sources. Pure whitespace/line-reflow to printWidth 100; no semicolons added and quote style is unchanged. Lint, typecheck, and the full test suite (79 tests) remain green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014DWovxbG4A7Ebda7xhG9nA
|
🚀 Preview deployed: https://preview-20.tablo.run |
i11v
added a commit
that referenced
this pull request
Jun 21, 2026
Follow-up to #20: actually *enforce* the linter and formatter, in CI and locally. ## What **1. CI gates** (`ci: enforce lint and formatting checks`) - Adds `bun run lint` (oxlint) and `bun run fmt:check` (oxfmt) right after `bun install` in **both** workflows — `deploy.yml` (production) and `pr-preview.yml` (PRs). - Placed before `typecheck`/`test`/`build` so the cheap static checks fail fast. **2. Pre-commit hook via Lefthook** (`build: add pre-commit hook via lefthook`) - Uses **[Lefthook](https://lefthook.dev)** (dev dependency) to manage git hooks — the modern, dependency-light husky alternative (single Go binary, declarative config, no Node at hook time). - `lefthook.yml` declares a `pre-commit` hook that runs `oxlint` and `oxfmt --check` **in parallel**, mirroring the CI static checks. Bypass a run with `git commit --no-verify`. - Hooks install automatically via `lefthook install`, run from the existing `prepare` script on `bun install` (guarded with `|| true` so a non-git install context can't break `prepare`). ## Verification - Lefthook hook verified end-to-end: runs lint+format in parallel, **passes** on a clean tree and **blocks** an unformatted commit (exit 1). It ran live on both commits in this PR. - `lint`, `fmt:check`, `typecheck`, `test` (79), `build:web`, `verify:pwa` all green; `bun install --frozen-lockfile` in sync. ## Note After pulling this, contributors get the hook automatically on their next `bun install` (via `prepare`) — no manual setup. To enable immediately without reinstalling: `bunx lefthook install`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_014DWovxbG4A7Ebda7xhG9nA --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Following the Vite+ assessment, we opted for the lighter, lower-risk path: adopt the two tools Vite+ would have wrapped — oxlint (linter) and oxfmt (formatter) — directly as dev dependencies, leaving the existing Vite 8 / Vitest 4 / Alchemy / Bun stack completely untouched. No
vite/vitestaliasing, no overrides.What
Staged so each tool lands as tooling first, then the resulting code change — four commits:
build(lint): add oxlint with baseline config—oxlintdev dep +.oxlintrc.json(typescript/unicorn/oxc/react/vitest plugins,correctnessas errors, generated route tree & build output ignored) +lintscript.fix: resolve oxlint correctness violations— fixes the 14 findings:App.tsx: hoist the empty stop list to a stable module constant so thebyNode/locationLabelmemos don't recompute every render while the index loads (react-hooks/exhaustive-deps).toThrow()(vitest/require-to-throw-message).vitest/no-conditional-expect).build(fmt): add oxfmt scoped to TS/TSX—oxfmtdev dep +.oxfmtrc.json(matches house style: no semicolons, double quotes,printWidth: 100— the width that reflows current source the least) +fmt/fmt:checkscripts. Scoped to TS/TSX viaignorePatternsso it leavespackage.json(managed by bun), JSON/YAML config, and Markdown docs alone.style: format TS/TSX with oxfmt— applies oxfmt. Pure reflow: no semicolons added, quote style unchanged (38 files, +393/−203).Verification
bun run lint,bun run typecheck, andbun run test(79 tests) all pass on the final tree.Not included (your call)
lintandfmt:checkare not wired intodeploy.yml/pr-preview.ymlyet, since that gates your pipeline. Happy to add it as a follow-up.🤖 Generated with Claude Code
https://claude.ai/code/session_014DWovxbG4A7Ebda7xhG9nA
Generated by Claude Code