Skip to content

chore: migrate from eslint to oxlint#623

Merged
B4nan merged 2 commits intomasterfrom
chore/migrate-to-oxlint
Apr 29, 2026
Merged

chore: migrate from eslint to oxlint#623
B4nan merged 2 commits intomasterfrom
chore/migrate-to-oxlint

Conversation

@B4nan
Copy link
Copy Markdown
Member

@B4nan B4nan commented Apr 28, 2026

Summary

Replaces ESLint with oxlint, pulling in the shared @apify/oxlint-config preset and oxlint-tsgolint for type-aware rules. Mirrors the migration already shipped in apify-storage-local-js and apify-core.

Stacked on top of #616 (pnpm migration). Will be retargeted to master after #616 merges.

What changed

  • Drop eslint, typescript-eslint, globals, @apify/eslint-config
  • Add oxlint@1.62.0, oxlint-tsgolint@0.22.0, @apify/oxlint-config@^0.2.5
  • Replace eslint.config.mjs and test/.eslintrc with oxlint.config.ts
  • lint / lint:fix now run oxlint --type-aware
  • lint-staged now runs oxlint --fix
  • tsconfig.json overrides module / moduleResolution to Node16 so oxlint-tsgolint can parse it (build tsconfig stays on commonjs / node so tsup keeps building correctly)
  • Stale import-x/* disable comments rewritten to oxlint's import/* plugin or removed where the underlying rule has no oxlint counterpart
  • Auto-fix surfaced issues: switch builtin imports to node: protocol, drop dead Node 14 conditional in test/log.test.ts, fix duplicate prefix in it('it works')
  • Allow intentional \0 regex match in BSON key escaping (line-level disable)

Lint output

$ pnpm lint
Found 0 warnings and 0 errors.
Finished in 246ms on 125 files with 115 rules using 14 threads.

Test plan

  • pnpm lint — clean
  • pnpm lint:fix — clean
  • pnpm test — 459/459 passing
  • pnpm build — all 15 packages built

@B4nan B4nan mentioned this pull request Apr 28, 2026
4 tasks
@B4nan B4nan added the adhoc Ad-hoc unplanned task added during the sprint. label Apr 28, 2026
Base automatically changed from chore/migrate-to-pnpm to master April 29, 2026 08:45
@B4nan B4nan force-pushed the chore/migrate-to-oxlint branch from ffdc7aa to e672ad1 Compare April 29, 2026 08:47
@github-actions github-actions Bot added this to the 139th sprint - Tooling team milestone Apr 29, 2026
@github-actions github-actions Bot added t-tooling Issues with this label are in the ownership of the tooling team. tested Temporary label used only programatically for some analytics. labels Apr 29, 2026
@B4nan B4nan force-pushed the chore/migrate-to-oxlint branch 2 times, most recently from 033d72f to a60c280 Compare April 29, 2026 09:09
@B4nan B4nan enabled auto-merge (squash) April 29, 2026 09:48
@B4nan B4nan requested a review from barjin April 29, 2026 09:48
@B4nan B4nan force-pushed the chore/migrate-to-oxlint branch from a60c280 to bc21bd5 Compare April 29, 2026 09:55
Copy link
Copy Markdown
Member

@barjin barjin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @B4nan , I only have one small nit / question ⬇️

Comment thread oxlint.config.ts
Comment on lines +29 to +34
'jest/no-conditional-expect': 'off',
'vitest/no-conditional-expect': 'off',
'jest/expect-expect': 'off',
'vitest/expect-expect': 'off',
'jest/no-standalone-expect': 'off',
'vitest/no-standalone-expect': 'off',
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these rules seem reasonable - is there a reason why we are disabling these? I don't see their equivalents in the eslint setup.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be all right in here, this is mostly based on apify-core where those triggered a lot of warnings due to false positives. I'll see if I can enable them here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested each — turned them on one at a time and counted violations:

rule violations decision
typescript/no-explicit-any 148 keep off (opt-in case-by-case)
no-param-reassign 40 keep off
typescript/no-empty-object-type 4 enable + fix
typescript/no-unsafe-declaration-merging 1 enable + fix
import/extensions 0 enable (free)
no-empty-function n/a preset already has it 'off', drop redundant override
no-use-before-define 2 enable (preset config), fix
no-void 0 preset enables with allowAsStatement: true, drop our override

Pushed as a separate commit on top of this branch so you can see the diff. The fixes are mostly removing the empty-interface declaration-merging trick (no longer needed) and switching mutually-recursive listener arrows to function declarations.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant mostly the jest/* and vitest/* rules, but it's cool we managed to shrink the main ruleset as well 👍

@B4nan B4nan disabled auto-merge April 29, 2026 11:15
Replace @apify/eslint-config + ESLint with @apify/oxlint-config + oxlint
(plus oxlint-tsgolint for type-aware rules), mirroring the migration
already done in apify-storage-local-js and apify-core.

- Drop eslint, typescript-eslint, globals, @apify/eslint-config
- Add oxlint, oxlint-tsgolint, @apify/oxlint-config
- Replace eslint.config.mjs and test/.eslintrc with oxlint.config.ts
- Update lint / lint:fix scripts to use oxlint --type-aware
- Update lint-staged to call oxlint --fix
- Override module/moduleResolution to Node16 in tsconfig.json so
  oxlint-tsgolint can parse it (build tsconfig stays on commonjs/node
  for tsup compatibility)
- Replace stale `eslint-disable import-x/*` with the rules removed or
  rewritten to oxlint's `import/*` and `typescript/*` plugin names
- Auto-fix surfaced issues: switch built-in imports to `node:` protocol,
  drop dead Node 14 conditional in test/log.test.ts, fix `it('it works')`
  duplicate prefix
- Allow intentional `\0` regex matches in BSON key escaping
@B4nan B4nan force-pushed the chore/migrate-to-oxlint branch from bc21bd5 to 6898006 Compare April 29, 2026 12:00
Most of the locally disabled rules were carried over from the apify-core
config where they fire on a lot of pre-existing code. In this much
smaller repo they're tractable.

Enabled (preset/oxlint defaults take over):
- typescript/no-empty-object-type (4 violations, all empty-interface
  tricks for recursive types or class+interface declaration merging)
- typescript/no-unsafe-declaration-merging (1 violation, RetryableError
  class+interface merge — no longer needed)
- import/extensions (0 violations, free win)
- no-empty-function (preset already has it 'off' — drop redundant override)
- no-use-before-define (preset config with safe options applies; 2
  violations in promisifyServerListen fixed by switching the mutually
  recursive listeners to function declarations)
- no-void (preset enables with allowAsStatement: true; no violations)

Kept disabled:
- typescript/no-explicit-any (148 violations — opt-in case-by-case)
- no-param-reassign (40 violations — too many to clean up here)
@B4nan B4nan force-pushed the chore/migrate-to-oxlint branch from 6898006 to c8e3902 Compare April 29, 2026 12:11
@B4nan B4nan merged commit a0c03f9 into master Apr 29, 2026
8 checks passed
@B4nan B4nan deleted the chore/migrate-to-oxlint branch April 29, 2026 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

adhoc Ad-hoc unplanned task added during the sprint. t-tooling Issues with this label are in the ownership of the tooling team. tested Temporary label used only programatically for some analytics.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants