Skip to content

ci: add oxlint as fast pre-lint pass before ESLint#10355

Open
benpsnyder wants to merge 2 commits intoTanStack:mainfrom
benpsnyder:feat/oxlint-eslint-bridge
Open

ci: add oxlint as fast pre-lint pass before ESLint#10355
benpsnyder wants to merge 2 commits intoTanStack:mainfrom
benpsnyder:feat/oxlint-eslint-bridge

Conversation

@benpsnyder
Copy link
Copy Markdown

@benpsnyder benpsnyder commented Mar 30, 2026

🎯 Changes

Add oxlint (Rust-based linter, ~50-100x faster than ESLint) as a first-pass linter that runs before ESLint in CI. Oxlint handles the bulk of correctness rules in ~250ms across 691 files, letting ESLint focus only on rules it exclusively covers (cspell, type-aware typescript-eslint rules, import ordering, react-hooks).

This pattern is already used by Preact, Sentry, Renovate, and Kibana. The implementation follows the same approach used in the AnalogJS repo (v3-alpha branch).

What changed:

  • New: oxlint.config.ts — typed config with defineConfig, plugins: typescript, vitest, import, react
  • Modified: eslint.config.js — imports oxlint config via jiti, appends buildFromOxlintConfig() as last entry to auto-disable overlapping rules, sets reportUnusedDisableDirectives: 'off'
  • Modified: package.json — adds test:oxlint script, adds it to test:pr/test:ci Nx targets and includedScripts
  • Modified: packages/vue-query/src/__tests__/useMutation.test.ts — fix pre-existing unsafe optional chaining with a defensive check
  • Modified: packages/react-query/src/__tests__/useQuery.promise.test.tsx — suppress false positive on vitest 3-arg describe() with options object
  • New devDependencies: oxlint, eslint-plugin-oxlint, jiti

Also incorporated from other open PRs:

Rules that stay ESLint-only (no oxlint equivalent)
  • @cspell/eslint-plugin (spell checking)
  • @typescript-eslint/consistent-type-imports, array-type, naming-convention, method-signature-style
  • @typescript-eslint/no-unnecessary-condition, no-unnecessary-type-assertion, no-for-in-array, require-await (type-aware)
  • import/* rules (ordering, no-commonjs, no-duplicates)
  • node/prefer-node-protocol
  • @stylistic/spaced-comment
  • sort-imports
  • eslint-plugin-react-hooks

Related issues & PRs

Superseded by this PR (can be closed):

Related but independent (not affected by this PR):

This is PR 1 of 6 in the Oxc/Rolldown/tsdown modernization series.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

…nfiguration

- Added `eslint-plugin-oxlint` and `jiti` as dependencies.
- Created `oxlint.config.ts` for custom linting rules and configurations.
- Updated `eslint.config.js` to include oxlint settings and disable overlapping ESLint rules.
- Modified package scripts to include a new `test:oxlint` command for running oxlint checks.
- Adjusted test files to comply with new linting rules.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

📝 Walkthrough

Walkthrough

Added oxlint integration: new oxlint.config.ts, dynamic loading in eslint.config.js via jiti to append oxlint-generated rules, updated scripts/devDependencies to run oxlint, and small test lint/assertion adjustments.

Changes

Cohort / File(s) Summary
Oxlint integration
eslint.config.js, oxlint.config.ts
Added oxlint.config.ts (plugins, envs, overrides) and refactored eslint.config.js to import('eslint').Linter.Config[] config, load oxlint.config.ts via jiti, append oxlint.buildFromOxlintConfig(...), add eslint-plugin-unused-imports and disable specific rules and unused-disable reporting.
Tooling / Scripts
package.json
Added test:oxlint script, included it in test:pr and test:ci, updated nx.includedScripts, bumped @tanstack/eslint-config, added devDeps: oxlint, eslint-plugin-oxlint, eslint-plugin-unused-imports, jiti.
Test edits
packages/react-query/src/__tests__/useQuery.promise.test.tsx, packages/vue-query/src/__tests__/useMutation.test.ts
Added ESLint disable for vitest/valid-describe-callback; refactored assertion to assert relevantMutation defined then check nested key.
ESLint export refactors (many examples/packages)
examples/react/.../eslint.config.js, packages/.../eslint.config.js (multiple files across examples and packages, see diff)
Replaced inline export default [...] array exports with a named config constant (typed via JSDoc or TS type) and export default config across many example and package ESLint flat config files; no semantic rule changes.

Sequence Diagram(s)

sequenceDiagram
  participant DevTool as "ESLint/Runner"
  participant RootConfig as "eslint.config.js"
  participant Jiti as "jiti loader"
  participant OxlintConfig as "oxlint.config.ts"
  participant Oxlint as "oxlint.buildFromOxlintConfig"
  participant ESLintEngine as "Final ESLint config"

  DevTool->>RootConfig: Load config (runtime)
  RootConfig->>Jiti: require('./oxlint.config.ts')\nvia jiti(import.meta.url)
  Jiti->>OxlintConfig: compile & return default export
  OxlintConfig->>Oxlint: pass config to buildFromOxlintConfig(...)
  Oxlint-->>RootConfig: return oxlint rule configs
  RootConfig->>ESLintEngine: append oxlint rules,\nmerge plugins & linterOptions
  ESLintEngine-->>DevTool: run lint with final config
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through configs, neat and bright,
Jiti fetched oxlint late at night,
Rules aligned in a tidy row,
Warnings whisper, errors glow,
A tiny rabbit's linting delight ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding oxlint as a pre-linting pass before ESLint in CI.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description is comprehensive and follows the template structure with clear sections on changes, checklist items, and release impact.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@benpsnyder benpsnyder changed the title feat: integrate oxlint for enhanced linting support and add oxlint configuration ci: add oxlint as fast pre-lint pass before ESLint Mar 30, 2026
- Added `eslint-plugin-unused-imports` to manage unused imports.
- Updated `@tanstack/eslint-config` to version 0.4.0 for improved linting rules.
- Modified ESLint configurations across multiple packages to include type annotations and ensure consistent exports.
- Adjusted rules in `oxlint.config.ts` to allow shadowing and refined other linting rules.
- Updated package dependencies in `pnpm-lock.yaml` to reflect the changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment