Skip to content

build: migrate to the oxc toolchain (oxlint + oxfmt) - #143

Merged
andre-j3sus merged 3 commits into
mainfrom
ajesus/migrate-to-oxc-toolchain
Aug 24, 2026
Merged

build: migrate to the oxc toolchain (oxlint + oxfmt)#143
andre-j3sus merged 3 commits into
mainfrom
ajesus/migrate-to-oxc-toolchain

Conversation

@andre-j3sus

@andre-j3sus andre-j3sus commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Replaces ESLint 9 and Prettier 3 with oxlint and oxfmt.

Two defects fixed along the way. CI linted 25 of 49 files — the lint script
globbed src/**/*.ts and *.json only, so tests/ and the root configs went
unchecked. lint-staged did cover them, making the pre-commit hook stronger
than CI, which is how a no-explicit-any error survived in
tests/unit/Results/Results.test.ts. There was also no format gate in CI.

eslint-plugin-compat is dropped rather than replaced. AGENTS.md credited it
with enforcing the browser-only constraint, but it checks browser API
availability against browserslist targets and cannot detect Node.js APIs. That
constraint is really enforced by tsconfig.jsonlib is ["ES2022", "DOM", "DOM.Iterable"] with no @types/node — which is untouched here. It also
reported zero violations against a browserslist config that doesn't exist.
wrap-iife has no oxlint equivalent either, but both IIFEs already match the
style it required.

printWidth is pinned to 80 and sortPackageJson to false, since oxfmt
defaults to 100 and true. Markdown and YAML stay excluded; Prettier never
covered them and formatting them rewrites the README table and every workflow.

Removing the ESLint tree drops 247 packages, taking minimatch@3 and
brace-expansion@1.1.x out of the lockfile entirely.

Reformat and the any fix are separate commits. The published .d.ts is
unchanged.

Adopt the oxc toolchain. The previous setup had two problems beyond being
slow.

CI linted 25 of 49 files: the "lint" script globbed src/**/*.ts and *.json
only, leaving tests/ and the root config files unchecked. lint-staged did
cover them, so the pre-commit hook was strictly stronger than CI, which is
how an @typescript-eslint/no-explicit-any error survives in
tests/unit/Results/Results.test.ts today. The tests/**/*.ts override in
eslint.config.js was dead config for the same reason. oxlint now covers all
40 source files, and "format" no longer skips tests/ and the root configs.

eslint-plugin-compat is dropped rather than replaced. AGENTS.md credited it
with enforcing the browser-only constraint, but it checks browser API
availability against browserslist targets and cannot detect Node.js APIs.
That constraint is actually enforced by tsconfig's lib and the deliberate
absence of @types/node, which is untouched here. The plugin also reported
zero violations and had no browserslist config to target, so it was running
against browserslist's implicit defaults. wrap-iife has no oxlint
equivalent; both IIFEs in the codebase already match the "inside" style it
required and oxfmt preserves paren placement.

printWidth is pinned to 80 and sortPackageJson to false, since oxfmt
defaults to 100 and true respectively. Markdown and YAML stay excluded:
Prettier never covered them and enabling them would rewrite the README
config table and re-indent every workflow.

tsc joins the lint script, and the format check now gates CI, which it
previously did not. Removing the ESLint tree also drops eslint-plugin-import
(installed but never referenced) and brace-expansion (a direct devDep
shadowing the vulnerable 1.1.x reachable only via minimatch@3 in that tree)
-- 247 packages in total.
Pure formatting, no behaviour change. Mostly collapsing hand-wrapped lines
that fit in 80 columns, plus oxfmt's leading-pipe style for multi-line union
types in src/Results/index.ts.

Four of these test files had drifted because the old "format" script only
covered src/**/*.ts.
Surfaced by oxlint now covering tests/. The helper cast the merged config to
any, which disabled checking on every call site. Exporting ResultsConfig lets
the overrides be typed and narrows the remaining cast to the real reason it
exists: spreading a Partial makes every property optional again.

ResultsConfig was already inlined into the published .d.ts for the Results
constructor signature, and src/index.ts does not re-export it, so the
declaration output is unchanged.
@andre-j3sus andre-j3sus self-assigned this Aug 24, 2026
@ask-bonk

ask-bonk Bot commented Aug 24, 2026

Copy link
Copy Markdown
@ask-bonk

ask-bonk Bot commented Aug 24, 2026

Copy link
Copy Markdown

@andre-j3sus Bonk workflow failed. Check the logs for details.

View workflow run · To retry, trigger Bonk again.

@andre-j3sus
andre-j3sus marked this pull request as ready for review August 24, 2026 15:51
@andre-j3sus
andre-j3sus merged commit 69f8adb into main Aug 24, 2026
6 of 7 checks passed
@andre-j3sus
andre-j3sus deleted the ajesus/migrate-to-oxc-toolchain branch August 24, 2026 16:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants