Skip to content

fix: replace eslint with oxlint#8677

Merged
sriramveeraghanta merged 3 commits intopreviewfrom
feat-oxlint-implementation
Mar 2, 2026
Merged

fix: replace eslint with oxlint#8677
sriramveeraghanta merged 3 commits intopreviewfrom
feat-oxlint-implementation

Conversation

@sriramveeraghanta
Copy link
Member

@sriramveeraghanta sriramveeraghanta commented Mar 2, 2026

Type of Change

  • Code refactoring

Summary by CodeRabbit

  • Chores

    • Migrated linting from ESLint to OxLint across the repo, added a shared OxLint config, updated package scripts and formatting tooling.
    • CI updated to run lint and type checks as separate jobs with adjusted caching and steps.
  • Documentation

    • Replaced ESLint docs with new OxLint-based linting guidance.
  • Bug Fixes

    • Fixed incorrect undefined checks in local-storage utilities.

Copilot AI review requested due to automatic review settings March 2, 2026 15:53
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 2, 2026

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

📥 Commits

Reviewing files that changed from the base of the PR and between d984aeb and 223741a.

📒 Files selected for processing (4)
  • .oxlintrc.json
  • packages/services/src/module/link.service.ts
  • packages/services/src/module/module.service.ts
  • packages/services/src/module/operations.service.ts
 ____________________________________________
< Forcing bugs to surrender unconditionally. >
 --------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ

✏️ Tip: You can disable in-progress messages and the fortune message in your review settings.

Tip

You can customize the high-level summary generated by CodeRabbit.

Configure the reviews.high_level_summary_instructions setting to provide custom instructions for generating the high-level summary.

📝 Walkthrough

Walkthrough

The PR migrates linting from ESLint to OxLint across the monorepo (configs, package scripts, CI, turbo), removes the old ESLint configuration and related devDependencies, adds a new .oxlintrc.json, adjusts CI lint/type jobs, updates documentation, and includes a small runtime bug fix and removal of explicit constructors in several service classes.

Changes

Cohort / File(s) Summary
CI workflow
.github/workflows/pull-request-build-lint-web-apps.yml
Split lint/types into separate jobs (check-lint, check-types); replaced matrix step with explicit per-job steps and scoped caching.
Lint config
.oxlintrc.json, eslint.config.mjs
Added OxLint config (.oxlintrc.json) and removed legacy eslint.config.mjs.
Package scripts (apps)
apps/admin/package.json, apps/live/package.json, apps/space/package.json, apps/web/package.json
Replaced ESLint-based check:lint/fix:lint scripts with oxlint equivalents.
Package scripts (packages)
packages/*/package.json (e.g., packages/editor, packages/hooks, packages/ui, packages/services, packages/types, packages/utils, packages/shared-state, packages/constants, packages/decorators, packages/i18n, packages/logger, packages/propel)
Replaced ESLint invocations with oxlint in check:lint and fix:lint across many packages; adjusted max-warnings values.
Repo root
package.json, turbo.json
Removed ESLint-related devDependencies, added oxlint & turbo; updated lint-staged to use oxlint; replaced eslint.config.mjs with .oxlintrc.json in turbo globalDependencies and removed lint task cache/dependsOn outputs.
Docs
AGENTS.md, CONTRIBUTING.md, docs/eslint.md (deleted), docs/linting.md (added)
Replaced ESLint/Prettier references with OxLint/oxfmt and added new linting documentation; deleted old ESLint doc.
Prettier ignore
packages/eslint-config/.prettierignore
Removed ignore patterns (file deleted/lines removed).
Code fixes / refactors
packages/hooks/src/use-local-storage.tsx, packages/services/src/module/*.service.ts
Fixed incorrect typeof window checks in use-local-storage; removed explicit constructors from ModuleService, ModuleLinkService, ModuleOperationService.
Linting tooling files
..
Various package-level script updates and minor manifest edits to reflect the tooling swap.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through configs, swift and spry,
ESLint waved a soft goodbye,
OxLint came with fresh new cheer,
Rules all tidy, warnings clear,
A carrot for the CI, and a happy ear!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is incomplete, containing only a checked change-type checkbox without any detailed description of the changes, rationale, test scenarios, or references required by the template. Add a detailed description explaining the ESLint-to-OxLint migration rationale, include test scenarios verifying linting behavior, and add relevant issue references per the template.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: replace eslint with oxlint' clearly and directly summarizes the main change across the entire changeset—migrating from ESLint to OxLint tooling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-oxlint-implementation

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.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates the monorepo’s linting setup from ESLint to OxLint, updating tooling config, package scripts, and CI/docs accordingly.

Changes:

  • Replace ESLint-based check:lint / fix:lint scripts across apps/packages with oxlint equivalents.
  • Introduce root .oxlintrc.json, remove eslint.config.mjs, and update Turbo global deps/caching for lint tasks.
  • Update linting documentation and CI workflow to run lint independently of build.

Reviewed changes

Copilot reviewed 30 out of 31 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
turbo.json Switch global dependency from eslint.config.mjs to .oxlintrc.json; adjust lint task outputs/deps for OxLint workflow.
pnpm-lock.yaml Remove ESLint dependency tree; add OxLint packages/bindings.
packages/utils/package.json Update lint scripts to oxlint.
packages/ui/package.json Update lint scripts to oxlint.
packages/types/package.json Update lint scripts to oxlint.
packages/shared-state/package.json Update lint scripts to oxlint.
packages/services/src/module/operations.service.ts Remove redundant constructor; leaves minor whitespace cleanup needed.
packages/services/src/module/module.service.ts Remove redundant constructor; leaves minor whitespace cleanup needed.
packages/services/src/module/link.service.ts Remove redundant constructor but leaves stale constructor JSDoc block that should be cleaned up.
packages/services/package.json Update lint scripts to oxlint.
packages/propel/package.json Update lint scripts to oxlint.
packages/logger/package.json Update lint scripts to oxlint.
packages/i18n/package.json Update lint scripts to oxlint.
packages/hooks/src/use-local-storage.tsx Replace incorrect typeof window === undefined check, but introduces duplicated condition that should be simplified.
packages/hooks/package.json Update lint scripts to oxlint.
packages/eslint-config/.prettierignore Remove Prettier ignore file from the eslint-config package.
packages/editor/package.json Update lint scripts to oxlint.
packages/decorators/package.json Update lint scripts to oxlint.
packages/constants/package.json Update lint scripts to oxlint.
package.json Drop ESLint devDependencies; add oxlint; update lint-staged to run oxlint.
eslint.config.mjs Remove ESLint flat config.
docs/linting.md Add OxLint-focused linting documentation.
docs/eslint.md Remove ESLint documentation.
apps/web/package.json Update lint scripts to oxlint.
apps/space/package.json Update lint scripts to oxlint.
apps/live/package.json Update lint scripts to oxlint.
apps/admin/package.json Update lint scripts to oxlint.
CONTRIBUTING.md Update contributor guidance to reference OxLint + oxfmt instead of ESLint + Prettier.
AGENTS.md Update agent/dev workflow notes to reference OxLint.
.oxlintrc.json Add root OxLint configuration.
.github/workflows/pull-request-build-lint-web-apps.yml Split out check:lint into its own job (no build dependency) and keep check:types gated on build.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/services/src/module/link.service.ts (1)

17-21: ⚠️ Potential issue | 🟡 Minor

Remove stale constructor JSDoc after constructor deletion.

Lines 17–20 still document a constructor (baseURL) that no longer exists, which is misleading.

✂️ Suggested cleanup
 export class ModuleLinkService extends APIService {
-  /**
-   * Creates an instance of ModuleLinkService.
-   * `@param` {string} baseURL - The base URL for the API endpoints
-   */
-  
-
   /**
    * Creates a new module link.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/services/src/module/link.service.ts` around lines 17 - 21, The JSDoc
block describing a constructor and a baseURL parameter is stale after removal of
the constructor in ModuleLinkService; remove the orphaned JSDoc (the /** ... */
block referencing the constructor/baseURL) from
packages/services/src/module/link.service.ts or replace it with an accurate
class-level comment for ModuleLinkService, ensuring there are no remaining
`@param` tags for baseURL and no misleading constructor documentation.
packages/hooks/src/use-local-storage.tsx (2)

42-46: ⚠️ Potential issue | 🟠 Major

Missing SSR guard in clearValue callback.

Same issue as setValue - direct window access without SSR guard.

🐛 Proposed fix
   const clearValue = useCallback(() => {
+    if (typeof window === "undefined") return;
     window.localStorage.removeItem(key);
     setStoredValue(null);
     window.dispatchEvent(new Event(`local-storage:${key}`));
   }, [key]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/hooks/src/use-local-storage.tsx` around lines 42 - 46, The
clearValue callback directly accesses window (window.localStorage.removeItem and
window.dispatchEvent) causing SSR failures; update the clearValue function (the
useCallback that references key and setStoredValue) to first check typeof window
!== "undefined" before calling window.localStorage.removeItem or
window.dispatchEvent, and still call setStoredValue(null) unconditionally so
state updates work on the server; mirror the same SSR guard pattern used in
setValue to keep behavior consistent.

33-38: ⚠️ Potential issue | 🟠 Major

Missing SSR guard in setValue callback.

The setValue function directly accesses window.localStorage without the same SSR guard used in getValueFromLocalStorage and setValueIntoLocalStorage. This will throw a ReferenceError during server-side rendering.

🐛 Proposed fix
   const setValue = useCallback(
     (value: T) => {
+      if (typeof window === "undefined") return;
       window.localStorage.setItem(key, JSON.stringify(value));
       setStoredValue(value);
       window.dispatchEvent(new Event(`local-storage:${key}`));
     },
     [key]
   );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/hooks/src/use-local-storage.tsx` around lines 33 - 38, The setValue
callback in use-local-storage.tsx directly accesses window.localStorage and will
throw during SSR; update the setValue function (the useCallback block) to guard
access with the same client-side check used in getValueFromLocalStorage and
setValueIntoLocalStorage (e.g., if (typeof window === "undefined") return or
only call window.localStorage when window exists), ensure setStoredValue(value)
still runs on server-safe paths as appropriate, and keep the
window.dispatchEvent call behind the same guard so no window access occurs
during SSR.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/hooks/src/use-local-storage.tsx`:
- Line 10: The guard in use-local-storage (inside the useLocalStorage hook)
repeats the same check; replace the second duplicate `typeof window ===
"undefined"` with a check for localStorage availability (e.g., `typeof
window.localStorage === "undefined"` or equivalent) so the condition correctly
returns defaultValue when running server-side or when localStorage is
unavailable.
- Line 21: The guard in use-local-storage.tsx currently repeats the same check
twice ("typeof window === 'undefined' || typeof window === 'undefined'"); update
that condition to verify localStorage exists instead (e.g., change the second
check to typeof window.localStorage === 'undefined') so the early return
correctly handles server environments and browsers without localStorage—apply
this change to the guard used in the useLocalStorage/getValueFromLocalStorage
logic.

In `@packages/services/src/module/module.service.ts`:
- Around line 12-14: ModuleService currently extends APIService but omitted a
constructor, causing a TypeScript error because APIService requires a baseURL;
add a constructor on ModuleService that either accepts a baseURL parameter and
calls super(baseURL) or calls super(DEFAULT_API_BASE_URL) (or another
env-derived default) so the base class is properly initialized; update the
ModuleService class declaration to include this constructor and ensure any
callers are adjusted if you choose the required-arg form.

---

Outside diff comments:
In `@packages/hooks/src/use-local-storage.tsx`:
- Around line 42-46: The clearValue callback directly accesses window
(window.localStorage.removeItem and window.dispatchEvent) causing SSR failures;
update the clearValue function (the useCallback that references key and
setStoredValue) to first check typeof window !== "undefined" before calling
window.localStorage.removeItem or window.dispatchEvent, and still call
setStoredValue(null) unconditionally so state updates work on the server; mirror
the same SSR guard pattern used in setValue to keep behavior consistent.
- Around line 33-38: The setValue callback in use-local-storage.tsx directly
accesses window.localStorage and will throw during SSR; update the setValue
function (the useCallback block) to guard access with the same client-side check
used in getValueFromLocalStorage and setValueIntoLocalStorage (e.g., if (typeof
window === "undefined") return or only call window.localStorage when window
exists), ensure setStoredValue(value) still runs on server-safe paths as
appropriate, and keep the window.dispatchEvent call behind the same guard so no
window access occurs during SSR.

In `@packages/services/src/module/link.service.ts`:
- Around line 17-21: The JSDoc block describing a constructor and a baseURL
parameter is stale after removal of the constructor in ModuleLinkService; remove
the orphaned JSDoc (the /** ... */ block referencing the constructor/baseURL)
from packages/services/src/module/link.service.ts or replace it with an accurate
class-level comment for ModuleLinkService, ensuring there are no remaining
`@param` tags for baseURL and no misleading constructor documentation.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 41abaff and 0bc2de9.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (30)
  • .github/workflows/pull-request-build-lint-web-apps.yml
  • .oxlintrc.json
  • AGENTS.md
  • CONTRIBUTING.md
  • apps/admin/package.json
  • apps/live/package.json
  • apps/space/package.json
  • apps/web/package.json
  • docs/eslint.md
  • docs/linting.md
  • eslint.config.mjs
  • package.json
  • packages/constants/package.json
  • packages/decorators/package.json
  • packages/editor/package.json
  • packages/eslint-config/.prettierignore
  • packages/hooks/package.json
  • packages/hooks/src/use-local-storage.tsx
  • packages/i18n/package.json
  • packages/logger/package.json
  • packages/propel/package.json
  • packages/services/package.json
  • packages/services/src/module/link.service.ts
  • packages/services/src/module/module.service.ts
  • packages/services/src/module/operations.service.ts
  • packages/shared-state/package.json
  • packages/types/package.json
  • packages/ui/package.json
  • packages/utils/package.json
  • turbo.json
💤 Files with no reviewable changes (3)
  • docs/eslint.md
  • packages/eslint-config/.prettierignore
  • eslint.config.mjs


export const getValueFromLocalStorage = (key: string, defaultValue: any) => {
if (typeof window === undefined || typeof window === "undefined") return defaultValue;
if (typeof window === "undefined" || typeof window === "undefined") return defaultValue;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Duplicate condition detected.

The guard typeof window === "undefined" || typeof window === "undefined" repeats the same check twice, which is redundant. This appears to be a copy-paste error.

🐛 Proposed fix
-  if (typeof window === "undefined" || typeof window === "undefined") return defaultValue;
+  if (typeof window === "undefined") return defaultValue;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (typeof window === "undefined" || typeof window === "undefined") return defaultValue;
if (typeof window === "undefined") return defaultValue;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/hooks/src/use-local-storage.tsx` at line 10, The guard in
use-local-storage (inside the useLocalStorage hook) repeats the same check;
replace the second duplicate `typeof window === "undefined"` with a check for
localStorage availability (e.g., `typeof window.localStorage === "undefined"` or
equivalent) so the condition correctly returns defaultValue when running
server-side or when localStorage is unavailable.


export const setValueIntoLocalStorage = (key: string, value: any) => {
if (typeof window === undefined || typeof window === "undefined") return false;
if (typeof window === "undefined" || typeof window === "undefined") return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Same duplicate condition issue.

Same redundant guard here as in getValueFromLocalStorage.

🐛 Proposed fix
-  if (typeof window === "undefined" || typeof window === "undefined") return false;
+  if (typeof window === "undefined") return false;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (typeof window === "undefined" || typeof window === "undefined") return false;
if (typeof window === "undefined") return false;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/hooks/src/use-local-storage.tsx` at line 21, The guard in
use-local-storage.tsx currently repeats the same check twice ("typeof window ===
'undefined' || typeof window === 'undefined'"); update that condition to verify
localStorage exists instead (e.g., change the second check to typeof
window.localStorage === 'undefined') so the early return correctly handles
server environments and browsers without localStorage—apply this change to the
guard used in the useLocalStorage/getValueFromLocalStorage logic.

@sriramveeraghanta sriramveeraghanta merged commit c554243 into preview Mar 2, 2026
9 of 10 checks passed
@sriramveeraghanta sriramveeraghanta deleted the feat-oxlint-implementation branch March 2, 2026 19:16
darkingtail added a commit to darkingtail/plane that referenced this pull request Mar 3, 2026
After makeplane#8677 replaced ESLint with OxLint, the react-in-jsx-scope rule
was not disabled. This causes all commits touching JSX files to fail
the pre-commit hook (oxlint --deny-warnings).

React 17+ uses automatic JSX runtime so explicit React imports are
not required.

Fixes makeplane#8681
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.

3 participants