Skip to content

feat: migrate to pnpm from yarn v1.22.22#7593

Merged
sriramveeraghanta merged 9 commits intopreviewfrom
setup-pnpm-2
Aug 19, 2025
Merged

feat: migrate to pnpm from yarn v1.22.22#7593
sriramveeraghanta merged 9 commits intopreviewfrom
setup-pnpm-2

Conversation

@lifeiscontent
Copy link
Collaborator

@lifeiscontent lifeiscontent commented Aug 18, 2025

Description

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

Screenshots and Media (if applicable)

Test Scenarios

References

Summary by CodeRabbit

  • New Features

    • Added emoji picker support and related emoji/runtime deps.
  • Bug Fixes

    • Charts update more reliably when changing axes.
    • Improved pie-chart active-slice rendering.
    • More robust file ID parsing to avoid empty/undefined values.
    • Minor UI stability and type-safety improvements.
  • Documentation

    • CONTRIBUTING updated to use pnpm commands.
  • Chores

    • Migrated repo tooling and CI from Yarn to pnpm; added pnpm workspace config.
    • Reworked Docker builds and caching for faster reproducible images.
    • Expanded .dockerignore/.gitignore entries and updated setup script.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 18, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Repository-wide migration from Yarn to pnpm: CI, Dockerfiles, setup scripts, and root configs updated; pnpm workspace and overrides added. Many package.json files switch to workspace:*. TypeScript configs simplified. Numerous import reorderings and focused typing/API adjustments in propel, constants, and file helpers.

Changes

Cohort / File(s) Summary
Package manager & workspace
package.json, .npmrc, pnpm-workspace.yaml, .yarnrc.yml, setup.sh, turbo.json
Switch to pnpm (set packageManager, add .npmrc, add pnpm-workspace.yaml), remove Yarn nodeLinker, add pnpm overrides, enable corepack/pnpm in scripts, and add turbo globalDependencies/inputs.
CI workflow
.github/workflows/pull-request-build-lint-web-apps.yml
Replace Yarn steps with Corepack+pnpm steps (enable pnpm, pnpm install --frozen-lockfile, pnpm run ...).
Docker / build pipelines
apps/*/Dockerfile* (e.g., apps/live/Dockerfile.live, apps/web/Dockerfile.web, apps/space/Dockerfile.space, apps/admin/Dockerfile.*, dev Dockerfiles)
Migrate dev and multi-stage Dockerfiles from Yarn to pnpm: add # syntax, ARG TURBO_VERSION, PNPM_HOME/PATH, corepack enable pnpm, install turbo via pnpm, use pnpm fetch/store caching, copy pnpm-lock.yaml, run pnpm turbo run build / pnpm dev, restructure builder/installer/runner stages and non-root runner users.
Ignore & housekeeping
.dockerignore, .gitignore, CONTRIBUTING.md
Expand .dockerignore with logs, caches, editors, envs; adjust .gitignore (add tsbuildinfo, pnpm debug logs; stop ignoring pnpm lock/.npmrc); update CONTRIBUTING dev command to pnpm dev.
Workspace package manifests
apps/*/package.json, packages/*/package.json
Convert many internal deps/devDeps from "*" to "workspace:*", add/remove packages (sharp, mobx, lucide-react, emoji-regex, emoji-picker-react, etc.), and move some @types between deps/devDeps.
Root overrides & packageManager
package.json
Add pnpm overrides (pin transitive deps), bump devDeps (prettier-plugin-tailwindcss, turbo), and set packageManager to pnpm@10.12.1.
Turbo config
turbo.json
Add globalDependencies: ["pnpm-lock.yaml", "pnpm-workspace.yaml", ".npmrc"] and update check:lint inputs.
TypeScript configs
packages/typescript-config/*, packages/propel/tsconfig.json, packages/editor/tsconfig.json, apps/space/tsconfig.json
Simplify/restructure several tsconfig files, change JSX runtime to react-jsx, remove node ambient types from editor, and adjust compilerOptions across workspace configs.
Code: import ordering & minor cleanups
apps/web/**, packages/ui/** (many files)
Large-scale import reorderings and duplicate import removals across app/UI files; mostly stylistic, no behavioral changes.
Propel: typing & API changes
packages/propel/src/* (avatar, charts, menu, table, types)
Tighten typings (isAValidNumber type guard, Pie sector typing), include yAxis.key in memo deps, remove some Menu/SubMenu props, adjust menu callback types, and refactor table forwardRef generics to tag-based ComponentRef/ComponentPropsWithoutRef.
Helpers & constants
packages/constants/src/workspace.ts, apps/space/helpers/file.helper.ts, packages/services/src/file/helper.ts
Add non-null assertions in workspace navigation initializers; getAssetIdFromUrl now returns assetUrl ?? "" to ensure string return.
Prettier ignore
packages/decorators/.prettierignore
Add dist/ to Prettier ignore.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Dev as Dev (local)
  participant GH as GitHub Actions
  participant Registry as Package Registry (pnpm)
  participant BuildKit as Docker BuildKit

  Dev->>GH: push PR (pnpm migration)
  GH->>GH: checkout, setup Node
  GH->>GH: corepack enable pnpm
  GH->>Registry: pnpm install --frozen-lockfile
  GH->>GH: pnpm run check:lint / format / build
  GH->>BuildKit: docker build (multi-stage using pnpm)
  BuildKit->>Registry: pnpm fetch --store-dir (uses cache)
  BuildKit->>Registry: pnpm install --offline --frozen-lockfile --store-dir
  BuildKit->>BuildKit: pnpm turbo run build --filter=<app>
  BuildKit-->>GH: built image/artifacts
  GH-->>Dev: CI results (lint/build)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60–90 minutes

Possibly related PRs

Suggested labels

🧹chore, ready_to_merge

Suggested reviewers

  • Palanikannan1437
  • prateekshourya29

Poem

"I hopped through lockfiles, swapped yarn for pnpm with flair,
Pruned Docker stages, cached the store, and scurried everywhere.
Types tidied up, imports neat — a soft paw on each line,
Workspace stitched and builds aligned — the repository's fine.
A rabbit’s twitch: tests pass green, now ship it with a cheer!" 🐇🚀

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7a7b01d and a433573.

📒 Files selected for processing (4)
  • apps/admin/Dockerfile.admin (4 hunks)
  • apps/live/Dockerfile.live (4 hunks)
  • apps/space/Dockerfile.space (4 hunks)
  • apps/web/Dockerfile.web (5 hunks)
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch setup-pnpm-2

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 5

🔭 Outside diff range comments (1)
apps/space/Dockerfile.space (1)

11-16: Use pnpm dlx for turbo prune to avoid PATH issues from global installs

Global-installing turbo with pnpm doesn’t guarantee it’s on PATH in this Alpine base, and prune runs before node_modules exist. Prefer pnpm dlx to pin the version and avoid PATH pitfalls.

Apply this diff:

-ARG TURBO_VERSION=2.5.6
-RUN corepack enable pnpm && pnpm add -g turbo@${TURBO_VERSION}
+ARG TURBO_VERSION=2.5.6
+RUN corepack enable pnpm
@@
-RUN turbo prune --scope=space --docker
+RUN pnpm dlx turbo@${TURBO_VERSION} prune --scope=space --docker
🧹 Nitpick comments (42)
CONTRIBUTING.md (1)

75-77: Clarify pnpm dev usage in CONTRIBUTING.md
The pnpm dev snippet at lines 75–77 should explicitly call out that it’s a root-level script (powered by Turborepo) and mention Corepack and version pinning. Suggested updates:

• Update the code block to show it’s run from the repo root via Turbo:

@@ CONTRIBUTING.md:75-77
- ```bash
- pnpm dev
- ```
+ ```bash
+ # From repo root – runs all app & package dev scripts via Turborepo
+ pnpm dev
+ ```

• Add a note that Corepack must be enabled and that package.json pins pnpm@10.12.1 in the packageManager field.
• Show per-app and recursive alternatives:

# Single app
pnpm --filter @plane/web dev

# pnpm-native recursive run
pnpm -r dev
apps/space/tsconfig.json (1)

20-26: Types configuration verified: no missing ambient types
No test-specific tsconfigs or test-framework dev-dependencies (jest/vitest/cypress) were found in apps/space. The added

"types": ["node","react"]

therefore safely limits ambient types to Node and React. If you introduce tests later, include their types (e.g. jest, vitest) in a dedicated test tsconfig.

Optional: consolidate duplicated plugins entries to avoid confusion

  • In apps/space/tsconfig.json, remove the top-level plugins block (lines 3–7) and keep only the one under compilerOptions.plugins (lines 20–24):
 apps/space/tsconfig.json
- "plugins": [
-   { "name": "next" }
- ],
   "compilerOptions": {
     …
     "plugins": [
       { "name": "next" }
     ],
packages/constants/tsconfig.json (1)

8-10: Avoid coupling a constants package to React ambient types unless strictly required

Including "react" here pulls in React typings for this package’s compilation and can mask unintended React/DOM usage in a pure constants library. If this package doesn’t contain JSX/React types, prefer keeping only Node (or no types at all) to minimize ambient-type surface.

Consider:

-    "allowSyntheticDefaultImports": true,
-    "types": ["node", "react"]
+    "allowSyntheticDefaultImports": true
+    // Add types only if needed, e.g. "types": ["node"]

If React types are truly needed by this package, ignore this comment.

apps/web/tsconfig.json (1)

13-14: Narrowing ambient types via "types" can hide needed globals (tests, Storybook, Cypress).

Specifying "types" restricts auto-included @types packages to only Node and React. If this app relies on other globals (e.g., Jest, Cypress, Storybook, Google Maps), you’ll see missing-type errors until those are explicitly added here or in env-specific tsconfigs.

If the intent is not to restrict, consider removing the "types" override:

     "plugins": [{ "name": "next" }],
-    "strictNullChecks": true,
-    "types": ["node", "react"]
+    "strictNullChecks": true

Otherwise, ensure all required env types are listed (e.g., "jest", "cypress") or split into per-env tsconfig extends.

apps/space/Dockerfile.dev (1)

8-9: Global turbo install appears unused; simplify and pin installs.

The CMD runs pnpm scripts directly, not turbo. Installing turbo globally adds image weight without benefit. Also, consider lockfile enforcement for reproducibility.

Apply:

-RUN corepack enable pnpm && pnpm add -g turbo
-RUN pnpm install
+RUN corepack enable pnpm
+RUN pnpm install --frozen-lockfile
apps/admin/tsconfig.json (1)

17-19: Refine “types” in apps/admin/tsconfig.json to only include necessary entries

Next.js already wires types via next-env.d.ts, and restricting the "types" array to ["node","react"] can be both redundant and overly restrictive:

  • apps/admin/next-env.d.ts is present and provides Next.js/React typings
  • @types/node and @types/react are installed, and Node APIs (e.g., process.env…) are used
  • No in-package tests (Jest/Cypress/Playwright) were detected, so limiting ambient types isn’t blocking test types here

Recommended optional refactor (either pick one):

--- a/apps/admin/tsconfig.json
+++ b/apps/admin/tsconfig.json
@@ lines 17–19
-    "types": ["node", "react"]
+    "types": ["node"]

Or remove "types" entirely and rely on Next.js + automatic type inclusion (add separate test-specific tsconfigs if you introduce tests):

--- a/apps/admin/tsconfig.json
+++ b/apps/admin/tsconfig.json
@@ lines 17–19
-    "types": ["node", "react"]
+    // Rely on next-env.d.ts and automatic @types inclusion
packages/types/tsconfig.json (1)

7-8: Limit ambient types to React only

Node ambient types aren’t used in this package (no process or Buffer references), while React types are heavily referenced. Update your tsconfig to remove "node" and keep only React:

• File: packages/types/tsconfig.json
Lines 7–8

     "strictNullChecks": true,
-    "types": ["node", "react"]
+    "types": ["react"]
.gitignore (1)

32-33: Deduplicate pnpm debug log ignore patterns

You now have both a wildcard and a specific pnpm-debug.log entry. The wildcard already covers the specific filename; keep one for clarity.

Apply this diff to remove the redundant specific entry:

- pnpm-debug.log

Also applies to: 65-65

packages/ui/tsconfig.json (1)

5-7: Remove unnecessary Node types from UI tsconfig

A scan of all .ts/.tsx files in packages/ui/src found no imports of Node core modules or use of Node globals, so it’s safe to drop the "node" ambient types here.

Suggested change:

--- packages/ui/tsconfig.json
@@ lines 5-7
-    "types": ["node", "react"]
+    "types": ["react"]
packages/utils/tsconfig.json (1)

5-7: Limit ambient Node types in packages/utils

We ran a search across packages/utils/src for Node-specific APIs (fs, path, process, etc.) and found no usages. To prevent accidental Node globals from leaking into browser consumers, you can safely remove the "node" ambient types:

• packages/utils/tsconfig.json

-    "types": ["node", "react"]
+    "types": ["react"]

If this package is ever consumed by a Node environment, you can re-add "node" then.

packages/hooks/tsconfig.json (1)

5-7: Be cautious: adding "types" narrows ambient types; verify if additional globals are needed (e.g., vite/client, jest).

Setting "types" to ["node","react"] restricts ambient types to only these. If hooks import env globals (Vite, Next.js types) or rely on test types in the same config chain, they'll be missing unless explicitly listed. Since include targets only src, this might be fine. Still, please verify usage or drop "types" if not strictly required by this package.

Would you like me to scan for imports/usages that require additional ambient types and propose the exact additions?

apps/live/Dockerfile.dev (2)

7-9: Avoid global turbo install; pin pnpm via Corepack; enforce lockfile on install.

  • Global turbo is not required if dev scripts invoke the workspace-local turbo via pnpm. Removing it reduces image size and avoids version drift.
  • Consider pinning pnpm via Corepack (honor root packageManager) and use --frozen-lockfile for reproducible dev installs.

Suggested change:

-RUN corepack enable pnpm && pnpm add -g turbo
-RUN pnpm install
+RUN corepack enable pnpm
+RUN pnpm install --frozen-lockfile

If dev scripts rely on a global turbo, I can adjust to pnpm dlx turbo or ensure turbo is a root devDependency instead. Confirm preference.


15-15: CMD looks good; consider adding -w to ensure root workspace context.

If dev relies on workspace root scripts, using the workspace root explicitly can be safer:

-CMD ["pnpm","dev", "--filter=live"]
+CMD ["pnpm","-w","dev","--filter=live"]

Optional; keep as-is if the current command resolves correctly in your context.

apps/admin/Dockerfile.dev (2)

8-9: Same as live: remove global turbo, pin pnpm via Corepack, and use --frozen-lockfile.

Suggested change:

-RUN corepack enable pnpm && pnpm add -g turbo
-RUN pnpm install
+RUN corepack enable pnpm
+RUN pnpm install --frozen-lockfile

If admin's dev script depends on global turbo, I can switch it to use the workspace turbo or pnpm dlx turbo.


17-17: Nit: consider explicit workspace root for dev.

-CMD ["pnpm", "dev", "--filter=admin"]
+CMD ["pnpm", "-w", "dev", "--filter=admin"]
apps/web/Dockerfile.dev (2)

8-9: Repeat of the above: drop global turbo, pin pnpm, enforce lockfile.

Suggested change:

-RUN corepack enable pnpm && pnpm add -g turbo
-RUN pnpm install
+RUN corepack enable pnpm
+RUN pnpm install --frozen-lockfile

13-13: Optional: run dev from workspace root explicitly.

-CMD ["pnpm", "dev", "--filter=web"]
+CMD ["pnpm", "-w", "dev", "--filter=web"]
pnpm-workspace.yaml (1)

11-14: Catalog is good; recommend pinning turbo without a range to avoid surprise upgrades.

Catalog is typically used to standardize exact versions across the workspace. Using a caret on turbo weakens that guarantee.

Suggested change:

 catalog:
   sharp: "0.33.5"
-  turbo: "^2.5.6"
+  turbo: "2.5.6"
   typescript: "5.6.3"

Do you want me to scan package.json files to normalize turbo versions to the catalog across the workspace?

packages/types/package.json (1)

34-40: Align root TypeScript version with workspace packages

Root package.json declares "typescript": "5.6.3" in its devDependencies (line 38), while every workspace package pins "typescript": "5.8.3". This mismatch can lead to confusion when running TS commands from the monorepo root.

• package.json (root) @ line 38: "typescript": "5.6.3"
• All workspaces: "typescript": "5.8.3"

Consider bumping the root devDependency to match the workspaces:

--- package.json
+++ package.json
@@ devDependencies
-    "typescript": "5.6.3"
+    "typescript": "5.8.3"

Alternatively, if you prefer to standardize on 5.6.x, downgrade each workspace to "typescript": "5.6.3".

apps/live/src/core/helpers/logger.ts (1)

40-40: Avoid double-casting through unknown; prefer a single, explicit cast or inferred type

The unknown bridge hides real type incompatibilities. If the goal is to expose a pino Logger, a single cast is clearer. Alternatively, use typeof to preserve the exact type.

Apply one of the following:

  • Prefer a single cast:
-export const manualLogger: Logger = logger.logger as unknown as Logger;
+export const manualLogger: Logger = logger.logger as Logger;
  • Or keep the exact type without any casts:
-export const manualLogger: Logger = logger.logger as unknown as Logger;
+export const manualLogger = logger.logger;
+export type ManualLogger = typeof manualLogger;
turbo.json (2)

22-22: Consider adding package.json to globalDependencies for more reliable cache busting

You already track pnpm-lock.yaml, pnpm-workspace.yaml, and .npmrc. Changes to root pnpm.overrides in package.json can also affect installs/builds. Tracking package.json helps avoid stale caches across the monorepo.

-  "globalDependencies": ["pnpm-lock.yaml", "pnpm-workspace.yaml", ".npmrc"],
+  "globalDependencies": ["pnpm-lock.yaml", "pnpm-workspace.yaml", ".npmrc", "package.json"],

38-39: Be explicit about excluding node_modules and .turbo in lint inputs

Turbo typically ignores node_modules, but being explicit avoids accidental regressions and reduces watch/load. Also exclude .turbo.

-      "inputs": ["**/*", "!**/.next/**", "!**/dist/**"]
+      "inputs": ["**/*", "!**/.next/**", "!**/dist/**", "!**/node_modules/**", "!**/.turbo/**"]
package.json (1)

24-26: Avoid using "latest" for Prettier; pin to a stable major/minor for reproducibility

"latest" can suddenly change formatting and break CI. Prefer a pinned version (exact or at least a major range). Also consider aligning the devDependency version of turbo with the override to avoid mixed signals.

-    "prettier": "latest",
-    "prettier-plugin-tailwindcss": "^0.6.14",
-    "turbo": "^2.5.6"
+    "prettier": "^3.0.0",
+    "prettier-plugin-tailwindcss": "^0.6.14",
+    "turbo": "2.5.6"

If you want to keep Prettier strictly pinned, replace ^3.0.0 with the exact version resolved in your CI after the first pnpm install.

.dockerignore (1)

19-64: Nice expansion; consider ignoring PNPM store and lint caches too

Great coverage. To keep Docker build contexts even leaner, add PNPM local store (if ever configured inside the repo) and ESLint cache.

 # Misc
 *.pem
 *.key
+.eslintcache
+.pnpm-store/
+**/.pnpm-store/

If your .npmrc sets a custom local store-dir within the repo, the above will significantly reduce context size.

apps/admin/Dockerfile.admin (1)

11-16: Avoid global turbo install; use pnpm dlx and pin pnpm via Corepack

Global installs add state and can be flaky in CI. Use pnpm dlx for turbo (no global state) and let Corepack activate the repo’s declared pnpm version from package.json.

Apply this diff:

 ARG TURBO_VERSION=2.5.6
-RUN corepack enable pnpm && pnpm add -g turbo@${TURBO_VERSION}
+RUN corepack enable && pnpm dlx turbo@${TURBO_VERSION} --version
 COPY . .
 
-RUN turbo prune --scope=admin --docker
+RUN pnpm dlx turbo@${TURBO_VERSION} prune --scope=admin --docker
apps/web/Dockerfile.web (1)

12-16: Prefer pnpm dlx for turbo; avoid global install

Same rationale as admin: ephemeral, pinned execution without global state.

Apply this diff:

 ARG TURBO_VERSION=2.5.6
-RUN corepack enable pnpm && pnpm add -g turbo@${TURBO_VERSION}
+RUN corepack enable && pnpm dlx turbo@${TURBO_VERSION} --version
 COPY . .
 
-RUN turbo prune --scope=web --docker
+RUN pnpm dlx turbo@${TURBO_VERSION} prune --scope=web --docker
apps/live/Dockerfile.live (3)

9-11: Remove apk update; it’s unnecessary with --no-cache and adds extra layers

apk add --no-cache already fetches fresh indexes. Dropping apk update avoids extra layers and reduces image size.

Apply this diff:

-RUN apk update
-RUN apk add --no-cache libc6-compat
+RUN apk add --no-cache libc6-compat
...
-FROM base AS installer
-RUN apk update
-RUN apk add --no-cache libc6-compat
+FROM base AS installer
+RUN apk add --no-cache libc6-compat

Also applies to: 23-25


13-17: Use pnpm dlx for turbo instead of global install

Avoid global state and rely on a pinned version per build.

Apply this diff:

 ARG TURBO_VERSION=2.5.6
-RUN corepack enable pnpm && pnpm add -g turbo@${TURBO_VERSION}
+RUN corepack enable && pnpm dlx turbo@${TURBO_VERSION} --version
 COPY . .
-RUN turbo prune --scope=live --docker
+RUN pnpm dlx turbo@${TURBO_VERSION} prune --scope=live --docker

27-37: Build needs devDeps, but runtime doesn’t; prune devDeps after build to slim the image

Install all deps to build, then prune to production before copying node_modules into the runner. This reduces image size and attack surface without breaking the build.

Apply this diff:

 COPY turbo.json turbo.json
-RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm install --offline --frozen-lockfile --store-dir=/pnpm/store
+RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm install --offline --frozen-lockfile --store-dir=/pnpm/store

Then after the build step (below), add a prune:

-RUN pnpm turbo run build --filter=live
+RUN pnpm turbo run build --filter=live
+RUN pnpm prune --prod

Optional hardening: set NODE_ENV=production in runner.

 FROM base AS runner
 WORKDIR /app
+ENV NODE_ENV=production
.npmrc (2)

9-12: Peer dep settings may mask mismatches

auto-install-peers=true and strict-peer-dependencies=false can hide real peer issues across the monorepo. If you hit subtle runtime problems, consider reverting to defaults and fixing peer ranges explicitly.


29-31: Caution with resolution-mode=highest

This can increase churn and unexpected resolutions when adding packages. The lockfile mitigates it, but if you see frequent diffs or duplication elsewhere, consider the default resolution mode.

.github/workflows/pull-request-build-lint-web-apps.yml (2)

41-43: Pin pnpm version via Corepack to ensure consistency

Enable shims and activate the repo-declared pnpm version (package.json: packageManager). This avoids environment drift.

Apply this diff:

-      - name: Enable Corepack and pnpm
-        run: corepack enable pnpm
+      - name: Enable Corepack and use repo pnpm version
+        run: |
+          corepack enable
+          node -p "require('./package.json').packageManager" | xargs corepack use

44-55: Add PNPM cache and broaden path triggers for PNPM/Turbo config changes

  • Cache PNPM in setup-node to speed installs.
  • Include pnpm-lock.yaml, pnpm-workspace.yaml, .npmrc, and turbo.json in workflow paths so builds run when tooling/config changes.

Suggested YAML changes (non-diff):

  • In “Set up Node.js” step:
    with:
    node-version-file: ".nvmrc"
    cache: "pnpm"

  • In on.pull_request.paths:

    • "pnpm-lock.yaml"
    • "pnpm-workspace.yaml"
    • ".npmrc"
    • "turbo.json"
apps/space/Dockerfile.space (2)

56-56: Ensure turbo is available for build or use dlx consistently

This relies on turbo being present in the pruned workspace’s devDependencies. To avoid coupling to that, invoke via pnpm dlx with the pinned version, consistent with the prune step.

Optional change:

-RUN pnpm turbo run build --filter=space
+RUN pnpm dlx turbo@${TURBO_VERSION} run build --filter=space

If you prefer keeping pnpm turbo, please confirm turbo is included in the pruned root package.json produced by turbo prune.


35-52: Duplicate ARG/ENV in installer stage may be unnecessary

NEXT_PUBLIC_* vars are also set in the runner stage. Unless you need them at build time for Next’s compile-time replacement, consider removing from installer to reduce noise.

apps/web/package.json (1)

45-45: New dependency: assess bundle impact of emoji-picker-react.

emoji-picker-react can add noticeable client bundle weight. Consider lazy-loading it where used to minimize initial page load.

packages/propel/package.json (1)

35-37: Dev configs to workspace: — consistent change. Also consider peerDependencies for library React packages.*

Optional: as a UI library, declaring react and react-dom as peerDependencies (with matching devDependencies for local dev) can prevent duplicate Reacts in consumers. Not required for this PR; just a heads-up for packaging best practices.

apps/live/package.json (1)

27-28: Workspace: linking approved; Node ≥ 20 requirement verified*

  • Both apps/live/Dockerfile.dev and apps/live/Dockerfile.live use node:22-alpine.
  • The dev and start scripts in apps/live/package.json correctly include --env-file.

Optional: add

"engines": { "node": ">=20" }

to apps/live/package.json to enforce the minimum Node version in local setups.

packages/utils/package.json (2)

24-25: Good switch to pnpm workspace protocol; consider using workspace:^ for semver-aligned bumps

workspace:* is valid and will link local packages. If you want downstream bump automation to follow normal semver ranges (and to better reflect intended compatibility), prefer workspace:^. For private-only packages, workspace:* is fine; this is an optional consistency tweak.

Apply if desired:

-    "@plane/constants": "workspace:*",
-    "@plane/types": "workspace:*",
+    "@plane/constants": "workspace:^",
+    "@plane/types": "workspace:^",

35-36: Align devDependencies to workspace:^ for consistency

Same note as dependencies: using workspace:^ can make version intent clearer across the monorepo. Optional.

-    "@plane/eslint-config": "workspace:*",
-    "@plane/typescript-config": "workspace:*",
+    "@plane/eslint-config": "workspace:^",
+    "@plane/typescript-config": "workspace:^",
packages/ui/package.json (2)

37-40: Workspace migration looks correct; consider workspace:^ to encode compatibility intent

These internal deps will link properly under pnpm. If you prefer semver-aware intent and smoother publish workflows (for any future non-private packages), workspace:^ is a conventional choice. Optional.

-    "@plane/constants": "workspace:*",
-    "@plane/hooks": "workspace:*",
-    "@plane/utils": "workspace:*",
-    "@plane/types": "workspace:*",
+    "@plane/constants": "workspace:^",
+    "@plane/hooks": "workspace:^",
+    "@plane/utils": "workspace:^",
+    "@plane/types": "workspace:^",

56-58: Dev config packages: optional switch to workspace:^ for consistency with dependencies

Not required, but it keeps a uniform pattern across the repo.

-    "@plane/eslint-config": "workspace:*",
-    "@plane/tailwind-config": "workspace:*",
-    "@plane/typescript-config": "workspace:*",
+    "@plane/eslint-config": "workspace:^",
+    "@plane/tailwind-config": "workspace:^",
+    "@plane/typescript-config": "workspace:^",
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d8f58d2 and 901409f.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (49)
  • .dockerignore (1 hunks)
  • .github/workflows/pull-request-build-lint-web-apps.yml (1 hunks)
  • .gitignore (3 hunks)
  • .npmrc (1 hunks)
  • .yarnrc.yml (0 hunks)
  • CONTRIBUTING.md (1 hunks)
  • apps/admin/Dockerfile.admin (5 hunks)
  • apps/admin/Dockerfile.dev (1 hunks)
  • apps/admin/package.json (2 hunks)
  • apps/admin/tsconfig.json (1 hunks)
  • apps/live/Dockerfile.dev (1 hunks)
  • apps/live/Dockerfile.live (4 hunks)
  • apps/live/package.json (2 hunks)
  • apps/live/src/core/helpers/logger.ts (1 hunks)
  • apps/live/tsconfig.json (1 hunks)
  • apps/space/.gitignore (0 hunks)
  • apps/space/Dockerfile.dev (1 hunks)
  • apps/space/Dockerfile.space (5 hunks)
  • apps/space/package.json (2 hunks)
  • apps/space/tsconfig.json (1 hunks)
  • apps/web/Dockerfile.dev (1 hunks)
  • apps/web/Dockerfile.web (5 hunks)
  • apps/web/package.json (3 hunks)
  • apps/web/tsconfig.json (1 hunks)
  • package.json (1 hunks)
  • packages/constants/package.json (1 hunks)
  • packages/constants/tsconfig.json (1 hunks)
  • packages/decorators/package.json (1 hunks)
  • packages/decorators/tsconfig.json (1 hunks)
  • packages/editor/package.json (2 hunks)
  • packages/hooks/package.json (1 hunks)
  • packages/hooks/tsconfig.json (1 hunks)
  • packages/i18n/package.json (1 hunks)
  • packages/logger/package.json (1 hunks)
  • packages/logger/tsconfig.json (1 hunks)
  • packages/propel/package.json (2 hunks)
  • packages/services/package.json (1 hunks)
  • packages/services/tsconfig.json (1 hunks)
  • packages/shared-state/package.json (1 hunks)
  • packages/types/package.json (1 hunks)
  • packages/types/tsconfig.json (1 hunks)
  • packages/ui/.storybook/main.ts (1 hunks)
  • packages/ui/package.json (2 hunks)
  • packages/ui/tsconfig.json (1 hunks)
  • packages/utils/package.json (2 hunks)
  • packages/utils/tsconfig.json (1 hunks)
  • pnpm-workspace.yaml (1 hunks)
  • setup.sh (1 hunks)
  • turbo.json (2 hunks)
💤 Files with no reviewable changes (2)
  • apps/space/.gitignore
  • .yarnrc.yml
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-04T16:22:44.344Z
Learnt from: lifeiscontent
PR: makeplane/plane#7164
File: packages/ui/.storybook/main.ts:24-47
Timestamp: 2025-06-04T16:22:44.344Z
Learning: In packages/ui/.storybook/main.ts, the webpackFinal function intentionally overrides the CSS loader strategy by finding and replacing existing CSS rules. This is a temporary workaround for a known upstream issue in Storybook's CSS handling that has been communicated to the Storybook maintainers. The current implementation should not be changed until the upstream issue is resolved.

Applied to files:

  • packages/ui/.storybook/main.ts
🧬 Code Graph Analysis (1)
apps/live/src/core/helpers/logger.ts (1)
packages/logger/src/config.ts (1)
  • logger (61-66)
🔇 Additional comments (39)
packages/shared-state/package.json (1)

21-21: Good move switching to workspace:* for the internal eslint config

This aligns with pnpm workspaces and ensures local resolution without version skew. No issues from me.

packages/decorators/tsconfig.json (1)

9-9: Adding "types": ["node"] is appropriate for a Node-targeted library

This should stabilize ambient Node typings without pulling in browser/React types. Looks good.

packages/logger/package.json (1)

37-38: Switch to workspace: for internal devDeps looks good.*

Aligns with PNPM workspaces and will resolve locally without publishing. No issues spotted.

packages/ui/.storybook/main.ts (1)

7-7: Comment update to generic PnP is appropriate.

No functional changes. This keeps the helper aligned with monorepo/PnP setups. Also acknowledges prior decision to retain the CSS loader override in this file until the upstream Storybook issue is resolved.

packages/hooks/package.json (1)

27-27: workspace: for internal eslint config is consistent with the PNPM migration.*

Looks good; no runtime impact.

packages/logger/tsconfig.json (1)

15-16: Confirmed: @types/node is declared as a devDependency
The packages/logger/package.json already lists "@types/node": "^22.5.4" under devDependencies, so TypeScript will correctly resolve the ambient Node types with pnpm’s strict node_modules.

apps/live/tsconfig.json (1)

22-22: LGTM – Node types are correctly configured

Confirmed that @types/node@^20.14.9 is listed under apps/live/package.json devDependencies. Approving these changes.

setup.sh (1)

80-83: Version Pinning Verified

The root package.json has "packageManager": "pnpm@10.12.1", and running Corepack confirms pnpm 10.12.1 is used across environments—no updates needed.

.gitignore (1)

79-83: pnpm lockfile confirmed and tracked

pnpm-lock.yaml is present at the repository root and committed, ensuring reproducible installs.

packages/decorators/package.json (1)

28-29: LGTM: move internal devDependencies to workspace ranges

Switching to "workspace:*" is consistent with pnpm workspaces and keeps local packages aligned.

pnpm-workspace.yaml (2)

16-20: onlyBuiltDependencies is valid in pnpm-workspace.yaml

The onlyBuiltDependencies setting is officially supported in pnpm-workspace.yaml for workspace-wide control (pnpm v10+). There is no .npmrc key named only-built-dependencies—use:

onlyBuiltDependencies:
  - turbo
  - sharp

in pnpm-workspace.yaml, or for per-package control:

// package.json
{
  "pnpm": {
    "onlyBuiltDependencies": ["turbo", "sharp"]
  }
}

No changes are needed to move this to .npmrc.

Likely an incorrect or invalid review comment.


21-22: Retain useNodeVersion for pnpm-managed Node pinning
pnpm natively supports a useNodeVersion key in the root pnpm-workspace.yaml (or use-node-version in .npmrc) to auto-install and use the specified Node.js version for pnpm run and pnpm node. You do not need to remove it.

If you’d like broader enforcement across editors, shells, and CI, you can layer on one or more of the following:

  • Add in package.json
    "engines": { "node": "22.18.0" }
    and enable PNPM’s engine checks (nodeVersion + engineStrict) in your workspace config.
  • Commit a .nvmrc or .node-version file for local tooling.
  • Pin via Volta (or asdf/nvm) in package.json to ensure every environment—including CI—uses the same Node.

Likely an incorrect or invalid review comment.

packages/types/package.json (1)

34-35: Switching internal configs to workspace: looks good*

Using workspace:* for internal packages is appropriate for PNPM workspaces.

package.json (1)

27-41: esbuild override confirmed compatible with tsup 8.4.0

tsup 8.4.0 ships with (and depends on) esbuild ^0.25.0, so pinning esbuild to 0.25.0 in your pnpm.overrides aligns exactly and won’t introduce incompatibilities.

• File: package.json → pnpm.overrides → "esbuild": "0.25.0"
• (Optional) To double-check that only one copy is installed, run:

pnpm ls esbuild
apps/admin/Dockerfile.admin (3)

56-56: Build invocation looks good

pnpm turbo run build --filter=admin aligns with the workspace build pattern and the prune step.


98-98: Verify server entry path is correct at runtime

Depending on Next.js standalone output, the server entry can be at ./server.js or nested (e.g., apps/admin/server.js). Confirm this path matches what .next/standalone emits for admin.

If needed, prefer the standalone’s root entry:

  • CMD ["node", "server.js"]

27-34: LGTM: PNPM fetch/install pattern and version locking verified

  • Dockerfile.admin (apps/admin/Dockerfile.admin, lines 27–34): fetch + offline + cache pattern is correct.
  • Root package.json contains packageManager: "pnpm@10.12.1", ensuring Corepack uses a consistent pnpm version in Docker and CI.
apps/web/Dockerfile.web (3)

30-37: Solid PNPM offline install and caching

The fetch + offline install with a mounted store will keep layers stable and builds faster.


66-66: Build step LGTM

pnpm turbo run build --filter=web is consistent with prune scope.


115-115: Confirm server start path

As with admin, verify that the entry point exists as apps/web/server.js in the standalone output. If not, consider using node server.js.

apps/live/Dockerfile.live (2)

41-41: Build command aligns with prune scope

No issues spotted.


58-58: CMD looks correct for copied layout

You’re copying dist to /app/live and starting live/server.js. This matches the COPY paths.

.npmrc (1)

17-22: Workspace and public hoist settings look good

These should reduce duplication for common tooling and keep workspace links intact.

apps/space/Dockerfile.space (1)

98-98: Confirm server.js path for Next standalone output

CMD points to apps/space/server.js. With Next 14 standalone output, paths can differ based on config. Please confirm this file exists in the copied standalone root.

Run inside the built image: ls -l apps/space/server.js (or adjust CMD to the correct path).

apps/admin/package.json (2)

21-27: Switch to workspace: looks good*

Moving internal @plane deps to workspace:* aligns with PNPM workspaces and improves consistency.


42-42: Adding sharp: ensure Docker builds don’t use offline installs or provide libvips

sharp requires downloading prebuilt binaries/libvips at install. If your Dockerfiles use pnpm install --offline (as in apps/space), the install will likely fail. Either drop --offline for images building this app or install system libvips/toolchain.

Would you like me to propose Dockerfile adjustments for the admin app similar to space?

packages/i18n/package.json (1)

18-23: Workspace migration acknowledged

Switching to workspace:* for internal packages is correct and consistent with the PNPM migration.

apps/space/package.json (2)

24-31: Workspace: specifiers LGTM*

Internal dependencies moved to workspace:* are consistent and correct.


50-51: Adding sharp: align Docker install flags to avoid failures

As noted for admin, ensure your Docker build for space doesn’t use pnpm install --offline or, if you prefer offline installs, add system libvips and toolchain.

I can open a follow-up to make the Dockerfile.space change if you confirm the preferred approach (online install vs. system libvips).

packages/editor/package.json (1)

43-48: Workspace migration LGTM

Using workspace:* for internal @plane deps in both dependencies and devDependencies is correct. No further issues spotted.

packages/constants/package.json (1)

30-34: Workspace protocol switch looks good.

Using workspace:* for internal packages aligns with pnpm workspaces and prevents accidental external resolution. Given this package is private, this is safe.

apps/web/package.json (3)

24-32: Good move to workspace: for internal packages.*

This will ensure local linking and consistent versions across the monorepo with pnpm.


72-74: Dev config packages switched to workspace: — aligned with the migration.*


64-64: Environment support in place for sharp 0.33
All Node-based Dockerfiles already target node:22-alpine and install libc6-compat. Sharp 0.33+ ships prebuilt musl binaries, so no extra vips or glibc packages are required in Alpine containers. If you have any non-Docker runtimes, just verify they run Node ≥ 16 LTS and glibc ≥ 2.28.

packages/services/package.json (2)

18-18: Internal dependency moved to workspace: — good.*

Ensures local linking under pnpm.


22-23: Dev config packages switched to workspace: — consistent with the rest of the repo.*

packages/propel/package.json (1)

25-25: Switching @plane/utils to workspace: looks correct.*

Monorepo-local resolution will avoid version drift.

apps/live/package.json (1)

49-50: Dev config packages to workspace: — consistent with the pnpm migration.*

packages/utils/package.json (1)

24-36: ✅ All internal @plane/ dependencies use workspace: protocol*
Ran a repo-wide scan and confirmed:

  • No @plane/* entries remain on non-workspace: specifiers.
  • pnpm-workspace.yaml is present at the root and includes packages/*.

No further changes required.

Comment on lines +23 to +25
# Enforce Node version for consistent installs
use-node-version=22.18.0

Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Align Node version across .npmrc and .nvmrc to avoid install-time mismatches

use-node-version=22.18.0 is strict. If .nvmrc differs, pnpm installs can fail. Ensure both match and CI uses the same Node.

Run to compare:


🏁 Script executed:

#!/bin/bash
echo "nvmrc: $(cat .nvmrc 2>/dev/null || echo missing)"
echo "npmrc use-node-version: $(rg -n '^use-node-version=' .npmrc | sed 's/.*=//')"

Length of output: 179


Align Node versions across .nvmrc and .npmrc

Our verification shows:

  • .nvmrc: lts/jod
  • .npmrc (use-node-version): 22.18.0

Since pnpm’s use-node-version check is strict, mismatched values will cause install failures in CI or on developers’ machines. Please update one of the following so both files specify the same version:

• Change .nvmrc → 22.18.0
• Or set use-node-version=lts/jod in .npmrc (if you intend to rely on the LTS alias)

After updating, ensure your CI pipeline uses this same Node version.

🤖 Prompt for AI Agents
In .npmrc around lines 23 to 25, the Node version set (use-node-version=22.18.0)
conflicts with .nvmrc (lts/jod); update one of them so both match — either
change .nvmrc to "22.18.0" or change .npmrc to "use-node-version=lts/jod" — then
verify and align the CI/node runtime configuration to use the same version
string you choose.

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: 1

🔭 Outside diff range comments (6)
apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx (1)

66-74: Fix progress percentage logic (wrong variable check can cause divide-by-zero)

In the “issues” branch, the condition checks completedIssues twice and never validates totalIssues. This can compute Infinity/NaN if totalIssues is 0.

Apply this diff:

-      : completedIssues != 0 && completedIssues != 0
-        ? Math.round((completedIssues / totalIssues) * 100)
+      : completedIssues != 0 && totalIssues != 0
+        ? Math.round((completedIssues / totalIssues) * 100)
         : 0
apps/web/core/components/workspace-notifications/sidebar/notification-card/item.tsx (1)

39-41: Potential runtime crash: unsafe access to notification and missing optional chaining

Line 40 dereferences notification.triggered_by_details without null checks. If useNotification hasn’t loaded yet, render will throw before the early return guard. Also, Line 39 accesses issue_activity.field without optional chaining on issue_activity, which can break when issue_activity is absent.

Apply safer optional chaining:

-  const notificationField = notification?.data?.issue_activity.field || undefined;
-  const notificationTriggeredBy = notification.triggered_by_details || undefined;
+  const notificationField = notification?.data?.issue_activity?.field || undefined;
+  const notificationTriggeredBy = notification?.triggered_by_details || undefined;
packages/propel/src/charts/area-chart/root.tsx (1)

84-95: Avoid NaN from divide-by-zero when data has a single point

With a single datum, data.length - 1 is 0, making ratio NaN. Recharts may silently drop the series. Short-circuit for fewer than 2 points.

-    if (!data || data.length === 0) return [];
+    if (!data || data.length < 2) return [];
apps/web/core/components/dropdowns/estimate.tsx (1)

22-31: Align onChange/value/option types to include null

Options include a "no estimate" entry with value null, and Props.value allows null, but Props.onChange and dropdownOnChange exclude null. This can cause type unsoundness and consumer bugs when "no estimate" is selected.

Apply this diff to make types consistent:

 type Props = TDropdownProps & {
   button?: ReactNode;
   dropdownArrow?: boolean;
   dropdownArrowClassName?: string;
-  onChange: (val: string | undefined) => void;
+  onChange: (val: string | null | undefined) => void;
   onClose?: () => void;
   projectId: string | undefined;
   value: string | undefined | null;
   renderByDefault?: boolean;
 };
-  const dropdownOnChange = (val: string | undefined) => {
+  const dropdownOnChange = (val: string | null | undefined) => {
     onChange(val);
     handleClose();
   };

Also applies to: 150-153

packages/propel/src/menu/types.ts (1)

1-1: Import React types to avoid “Cannot find name 'React'” in type-only file

This file references React.ReactNode but doesn’t import React types. In TS projects using the automatic JSX runtime, the React namespace isn’t globally available in type space; this can break builds.

Add a type-only import at the top:

import type React from "react";
packages/propel/src/menu/menu.tsx (1)

53-57: Bug: close() here calls the global window.close(), not the menu API

close() is not defined in this scope, so this will call the browser’s window.close() (and often no-op due to browser restrictions). It won’t close the menu and may confuse behavior.

Remove it and rely on BaseMenu’s default item behavior (menus usually close on selection) or explicitly wire a proper close from context if needed.

-      onClick={(e) => {
-        close();
-        onClick?.(e);
-        submenuContext?.closeSubmenu();
-      }}
+      onClick={(e) => {
+        onClick?.(e);
+        submenuContext?.closeSubmenu();
+      }}
🧹 Nitpick comments (32)
packages/ui/src/button/button.tsx (1)

4-4: Nit: use type-only imports for TS types to improve clarity and bundling.

Separating value imports from type imports helps with TS 4.5+ verbatimModuleSyntax/isolatedDeclarations setups and avoids accidental runtime named import lookups.

-import { getIconStyling, getButtonStyling, TButtonVariant, TButtonSizes } from "./helper";
+import { getIconStyling, getButtonStyling } from "./helper";
+import type { TButtonVariant, TButtonSizes } from "./helper";
.gitignore (4)

27-27: Prefer wildcard ignore for TypeScript build info files

Covers all incremental build artifacts across packages, not just the default filename.

-tsconfig.tsbuildinfo
+*.tsbuildinfo

33-35: Deduplicate pnpm debug log ignore patterns

pnpm-debug.log* at Line 33 already covers pnpm-debug.log at Line 65. Keeping the glob once avoids drift and keeps the file lean.

- pnpm-debug.log

Also consider removing duplicate npm/yarn log patterns later in the file (e.g., npm-debug.log, yarn-error.log) since they’re already covered in the Debug section. I can propose a full dedupe pass if helpful.

Also applies to: 65-65


73-73: Consolidate lockfile ignores; consider ignoring yarn.lock during pnpm migration

  • package-lock.json appears twice (Lines 73 and 80). Keep a single entry under the "lock files" section.
  • If the repo is standardizing on pnpm, ignoring yarn.lock can prevent accidental reintroduction.
- package-lock.json
 # lock files
 package-lock.json
+yarn.lock

Please confirm that:

  • pnpm is the sole package manager (so ignoring yarn.lock is desired).
  • pnpm-lock.yaml is tracked at the repo root (expected per this migration).

Also applies to: 79-81


82-83: Remove stray blank lines (nit)

Not functional, just tidies the ignore list.

-
-
packages/propel/src/charts/pie-chart/active-shape.tsx (1)

3-3: Prefer a type-only import (and verify the import path’s stability).

Use import type to avoid emitting a runtime import for a type, which is especially important with TS configs using verbatimModuleSyntax/isolatedModules. Also, the recharts/types/... path is semi-internal; if PieSectorDataItem is re-exported from recharts, prefer that. If not, keep the current path but with a type-only import.

-import { PieSectorDataItem } from "recharts/types/polar/Pie";
+import type { PieSectorDataItem } from "recharts/types/polar/Pie";

If PieSectorDataItem is exported from the root package, even better:

import type { PieSectorDataItem } from "recharts";
apps/web/core/components/onboarding/invitations.tsx (1)

48-48: Clarify/simplify early-return guard

The current condition returns only when both no selection and missing role. If the intent is simply to prevent submission with no selection (button is already disabled for this), simplifying improves readability and avoids role-coupling.

Apply this minimal change:

-    if (invitationsRespond.length <= 0 && !invitation?.role) return;
+    if (invitationsRespond.length === 0) return;
apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx (1)

101-117: Ensure loader is reset reliably; use try/catch/finally

setLoader(false) is duplicated in both try and catch. Use finally to guarantee cleanup and reduce duplication.

   const onChange = async (value: TModulePlotType) => {
     setPlotType(moduleId, value);
     if (!workspaceSlug || !projectId || !moduleId) return;
-    try {
-      setLoader(true);
+    setLoader(true);
+    try {
       if (isArchived) {
         await fetchArchivedModuleDetails(workspaceSlug, projectId, moduleId);
       } else {
         await fetchModuleDetails(workspaceSlug, projectId, moduleId);
       }
-      setLoader(false);
     } catch (error) {
-      setLoader(false);
       setPlotType(moduleId, plotType);
+    } finally {
+      setLoader(false);
     }
   };
packages/ui/src/popovers/popover-menu.tsx (1)

3-3: Minor: keep cn import grouped under helpers/utils for consistency

cn is a utility helper, not a component. In this file it’s placed under the “components” section, while in modal-core it’s under “constants”. Consider standardizing its placement (e.g., a “helpers” or “utils” section) across the UI package to reduce churn and improve readability. Optional, non-blocking.

apps/web/core/components/dropdowns/member/member-options.tsx (3)

79-96: Skip undefined users and avoid “undefined” in search index

getUserDetails can return undefined; currently those entries still produce option objects and the query string can contain literal “undefined” fragments. Filter early and build the query from present fields. Also removes the now-redundant final filter.

Apply this diff:

-  const options = memberIds
-    ?.map((userId) => {
-      const userDetails = getUserDetails(userId);
-      return {
-        value: userId,
-        query: `${userDetails?.display_name} ${userDetails?.first_name} ${userDetails?.last_name}`,
-        content: (
-          <div className="flex items-center gap-2">
-            <Avatar name={userDetails?.display_name} src={getFileURL(userDetails?.avatar_url ?? "")} />
-            <span className="flex-grow truncate">
-              {currentUser?.id === userId ? t("you") : userDetails?.display_name}
-            </span>
-          </div>
-        ),
-      };
-    })
-    .filter((o) => !!o);
+  const options = memberIds
+    ?.map((userId) => {
+      const userDetails = getUserDetails(userId);
+      if (!userDetails) return null;
+      const { display_name = "", first_name = "", last_name = "", avatar_url } = userDetails;
+      return {
+        value: userId,
+        query: [display_name, first_name, last_name].filter(Boolean).join(" "),
+        content: (
+          <div className="flex items-center gap-2">
+            <Avatar name={display_name} src={getFileURL(avatar_url ?? "")} />
+            <span className="flex-grow truncate">
+              {currentUser?.id === userId ? t("you") : display_name}
+            </span>
+          </div>
+        ),
+      };
+    })
+    .filter(Boolean);

19-28: Prefer optional prop syntax over union with undefined

Idiomatic TS for optional props is placement?: Placement instead of Placement | undefined.

-  placement: Placement | undefined;
+  placement?: Placement;

63-71: Include onDropdownOpen in effect deps (or memoize it)

Prevents a stale reference and satisfies exhaustive-deps linting. If onDropdownOpen is stable (e.g., from store), this is a no-op.

-  }, [isOpen, isMobile]);
+  }, [isOpen, isMobile, onDropdownOpen]);
packages/editor/package.json (3)

43-47: Switch workspace ranges to workspace:^ for smoother semver alignment.

workspace:* works, but it publishes as an exact version pin, which makes dependents churn on every internal release. Using workspace:^ gives you the same local linking benefits while publishing as a caret range, easing coordinated bumps across the monorepo.

Apply this diff:

-    "@plane/constants": "workspace:*",
-    "@plane/hooks": "workspace:*",
-    "@plane/types": "workspace:*",
-    "@plane/ui": "workspace:*",
-    "@plane/utils": "workspace:*",
+    "@plane/constants": "workspace:^",
+    "@plane/hooks": "workspace:^",
+    "@plane/types": "workspace:^",
+    "@plane/ui": "workspace:^",
+    "@plane/utils": "workspace:^",

84-86: Use workspace:^ for devConfigs to reduce noisy cross-package pinning.

Same rationale as runtime deps: workspace:^ eases coordinated updates of shared configs without forcing exact-version churn.

-    "@plane/eslint-config": "workspace:*",
-    "@plane/tailwind-config": "workspace:*",
-    "@plane/typescript-config": "workspace:*",
+    "@plane/eslint-config": "workspace:^",
+    "@plane/tailwind-config": "workspace:^",
+    "@plane/typescript-config": "workspace:^",

70-71: SSR Safety Confirmed; Optional: Hoist Regex Instance for Performance

  • Verified that isEmojiSupported() is only invoked inside a function (packages/editor/src/core/extensions/emoji/emoji.ts – line 158), not at module load, so SSR/Node won’t break.
  • Verified that emojiRegex() is called within the text-matching function (…/emoji.ts – line 405), also inside runtime code, so no top-level execution during import.

Optional refactor to avoid reallocating the regex on every match:

// At top of emoji.ts
const emojiPattern = emojiRegex();

// Later inside your function:
const matches = [...node.text.matchAll(emojiPattern)];
packages/propel/src/charts/area-chart/root.tsx (2)

88-88: Coerce lastYValue to number to prevent accidental NaN

If the last point’s y value is a string (e.g., "10"), implicit coercion works, but any non-numeric string yields NaN. Be explicit.

-    const lastYValue = lastPoint[yAxis.key] ?? 0;
+    const lastYValue = Number(lastPoint[yAxis.key] ?? 0);

93-99: Optional: base interpolation on x-values (handles irregular x spacing)

Index-based ratios assume evenly spaced x values. If x is time or irregular, compute ratio by x distance for a true straight line from (x0, 0) to (xN, yN).

-      const ratio = index / (data.length - 1);
-      const interpolatedValue = ratio * lastYValue;
+      // compute ratio by x-distance; supports number or Date; falls back to index if conversion fails
+      const toNum = (v: unknown) =>
+        v instanceof Date ? v.getTime() : (typeof v === "number" ? v : Number(v));
+      const x0Raw = data[0]?.[xAxis.key];
+      const xNRaw = lastPoint[xAxis.key];
+      const xiRaw = item[xAxis.key];
+      const x0 = toNum(x0Raw);
+      const xN = toNum(xNRaw);
+      const xi = toNum(xiRaw);
+      const denom = Number.isFinite(xN - x0) && xN !== x0 ? xN - x0 : (data.length - 1);
+      const numer = Number.isFinite(xi - x0) ? xi - x0 : index;
+      const ratio = denom ? numer / denom : 0;
+      const interpolatedValue = ratio * lastYValue;
apps/web/core/components/issues/workspace-draft/draft-issue-properties.tsx (1)

256-268: Nit: Redundant project_id guard (already guaranteed by early return)

You return null at Line 119 if !issue.project_id, so the extra issue.project_id && check here is redundant. This also allows dropping optional chaining on toString().

-      {issue.project_id && areEstimateEnabledByProjectId(issue.project_id?.toString()) && (
+      {areEstimateEnabledByProjectId(issue.project_id.toString()) && (
apps/web/core/components/labels/delete-label-modal.tsx (1)

35-70: Avoid mixing await with .then/.catch; use try/catch for clarity

This reads cleaner and prevents double-promise handling. Behavior remains the same.

   const handleDeletion = async () => {
     if (!workspaceSlug || !projectId || !data) return;

     setIsDeleteLoading(true);

-    await deleteLabel(workspaceSlug.toString(), projectId.toString(), data.id)
-      .then(() => {
-        captureSuccess({
-          eventName: PROJECT_SETTINGS_TRACKER_EVENTS.label_deleted,
-          payload: {
-            name: data.name,
-            project_id: projectId,
-          },
-        });
-        handleClose();
-      })
-      .catch((err) => {
-        setIsDeleteLoading(false);
-
-        captureError({
-          eventName: PROJECT_SETTINGS_TRACKER_EVENTS.label_deleted,
-          payload: {
-            name: data.name,
-            project_id: projectId,
-          },
-          error: err,
-        });
-
-        const error = err?.error || "Label could not be deleted. Please try again.";
-        setToast({
-          type: TOAST_TYPE.ERROR,
-          title: "Error!",
-          message: error,
-        });
-      });
+    try {
+      await deleteLabel(workspaceSlug.toString(), projectId.toString(), data.id);
+      captureSuccess({
+        eventName: PROJECT_SETTINGS_TRACKER_EVENTS.label_deleted,
+        payload: {
+          name: data.name,
+          project_id: projectId,
+        },
+      });
+      handleClose();
+    } catch (err: any) {
+      setIsDeleteLoading(false);
+      captureError({
+        eventName: PROJECT_SETTINGS_TRACKER_EVENTS.label_deleted,
+        payload: {
+          name: data.name,
+          project_id: projectId,
+        },
+        error: err,
+      });
+      const error = err?.error || "Label could not be deleted. Please try again.";
+      setToast({
+        type: TOAST_TYPE.ERROR,
+        title: "Error!",
+        message: error,
+      });
+    }
   };
apps/web/core/components/dropdowns/estimate.tsx (4)

97-117: Remove dead branch and tighten the options build

The map callback has an else undefined; that does nothing; you’re also using optional chaining on an already defaulted array. This refactor improves readability and removes the need for a custom undefined filter.

-  const options: DropdownOptions = (estimatePointIds ?? [])
-    ?.map((estimatePoint) => {
-      const currentEstimatePoint = estimatePointById(estimatePoint);
-      if (currentEstimatePoint)
-        return {
-          value: currentEstimatePoint.id,
-          query: `${currentEstimatePoint?.value}`,
-          content: (
-            <div className="flex items-center gap-2">
-              <Triangle className="h-3 w-3 flex-shrink-0" />
-              <span className="flex-grow truncate">
-                {currentActiveEstimate?.type === EEstimateSystem.TIME
-                  ? convertMinutesToHoursMinutesString(Number(currentEstimatePoint.value))
-                  : currentEstimatePoint.value}
-              </span>
-            </div>
-          ),
-        };
-      else undefined;
-    })
-    .filter((estimatePointDropdownOption) => estimatePointDropdownOption != undefined) as DropdownOptions;
+  const options: DropdownOptions = (estimatePointIds ?? [])
+    .map((estimatePoint) => {
+      const currentEstimatePoint = estimatePointById(estimatePoint);
+      return (
+        currentEstimatePoint && {
+          value: currentEstimatePoint.id,
+          query: `${currentEstimatePoint.value}`,
+          content: (
+            <div className="flex items-center gap-2">
+              <Triangle className="h-3 w-3 flex-shrink-0" />
+              <span className="flex-grow truncate">
+                {currentActiveEstimate?.type === EEstimateSystem.TIME
+                  ? convertMinutesToHoursMinutesString(Number(currentEstimatePoint.value))
+                  : currentEstimatePoint.value}
+              </span>
+            </div>
+          ),
+        }
+      );
+    })
+    .filter(Boolean) as DropdownOptions;

260-260: Normalize React key to a string

Minor cleanup to avoid non-string keys and make uniqueness explicit.

-                        <Combobox.Option key={option.value} value={option.value}>
+                        <Combobox.Option key={String(option.value)} value={option.value}>

224-224: Drop “static” on Options (it’s already conditionally rendered)

You’re gating rendering with isOpen &&, so static is redundant.

-        <Combobox.Options className="fixed z-10" static>
+        <Combobox.Options className="fixed z-10">

97-131: Optional: memoize options/filtering to reduce re-renders

If this dropdown is used frequently, consider wrapping options and filteredOptions with useMemo keyed on [estimatePointIds, currentActiveEstimate?.type, query, t] to avoid recomputation.

packages/propel/tsconfig.json (1)

5-6: Ambient types confirmed—no extras needed.

Our scan of packages/propel found no usage of import.meta, process., Buffer, testing globals (test, vi., describe, it, jest.), or triple-slash references. That means no additional ambient type packages are required.

• You can safely keep the "types": ["node", "react"] filter as is.
• To fall back on the base config’s default ambient types, simply remove the entire "types" entry.
• If this library is truly browser-only, you may trim out Node types:

-    "types": ["node", "react"]
+    "types": ["react"]
packages/i18n/tsconfig.json (1)

6-8: Align i18n tsconfig.json with repo conventions

  • There are no TS/TSX files under packages/i18n/src, so the current "jsx" and "types" options have no effect today.
  • Optional JSX runtime update: if you plan to add React/TSX here, switch to the automatic runtime:
    -    "jsx": "react",
    +    "jsx": "react-jsx",
  • Ambient types: by specifying "types": ["node", "react"], you’re preventing other ambient types from the base config (e.g. vite/client, jest, vitest) from being included.
    • Remove the types field to inherit everything from @plane/typescript-config/react-library.json, or
    • Explicitly add any additional type packages you need.
packages/shared-state/tsconfig.json (1)

8-9: Remove unnecessary Node ambient types from shared-state tsconfig

No references to process, Buffer, __dirname, fs, path or other Node-only APIs were found under packages/shared-state/src. You can safely drop the explicit Node types to avoid pulling in Node globals that might mask browser-only issues.

  • packages/shared-state/tsconfig.json
     {
       …
    -  "types": ["node"]
     }
  • If in the future you introduce Node-bound scripts or tests, create a separate tsconfig.node.json (or extend the base config) that adds "types": ["node"] only where needed.
  • Optionally, once you adopt the automatic JSX runtime repo-wide, update "jsx" to "react-jsx" in your base tsconfig for consistency.
packages/propel/src/menu/types.ts (1)

24-24: Good: widen handler to variadic args for future-proofing

The change to menuButtonOnClick?: (..._args: unknown[]) => void; is a sensible loosening. Consider actually forwarding the event from the trigger so downstream consumers can use it:

In menu.tsx, pass the event:

-    if (menuButtonOnClick) menuButtonOnClick();
+    menuButtonOnClick?.(e);
packages/propel/src/avatar/avatar.tsx (1)

107-107: Add alt text to improve accessibility for the avatar image

The image lacks an alt attribute, which is important for screen readers.

-        <AvatarPrimitive.Image src={src} width="48" height="48" />
+        <AvatarPrimitive.Image src={src} width="48" height="48" alt={name ?? fallbackLetter} />
packages/propel/src/menu/menu.tsx (3)

114-123: Avoid preventDefault; forward the click event to menuButtonOnClick

Calling e.preventDefault() on the trigger can interfere with the headless menu’s internal open logic (many libs bail if default is prevented). Also, now that menuButtonOnClick accepts variadic args, forward the event.

-  const handleMenuButtonClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
-    e.stopPropagation();
-    e.preventDefault();
+  const handleMenuButtonClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
+    e.stopPropagation();
     if (isOpen) {
       closeDropdown();
     } else {
       openDropdown();
     }
-    if (menuButtonOnClick) menuButtonOnClick();
+    menuButtonOnClick?.(e);
   };

126-126: Sync visual “open” styling with actual menu open state

isOpen is only toggled via the button click handler, and not updated when the menu opens/closes via other interactions (e.g., hover or outside click). Wire onOpenChange to keep isOpen in sync and still call the external handleOpenChange.

-  return (
-    <BaseMenu.Root openOnHover={openOnHover} onOpenChange={handleOpenChange}>
+  const onBaseOpenChange = React.useCallback(
+    (open: boolean) => {
+      setIsOpen(open);
+      handleOpenChange?.(open);
+    },
+    [handleOpenChange]
+  );
+
+  return (
+    <BaseMenu.Root openOnHover={openOnHover} onOpenChange={onBaseOpenChange}>

22-33: Submenu content class name: confirm removal or support it

TSubMenuProps still includes contentClassName, but SubMenu no longer destructures or uses it. If the prop is intentionally removed from the API, drop it from the type. If it’s still desired, wire it into the Popup.

Example to keep support:

-  const { children, trigger, disabled = false, className = "" } = props;
+  const { children, trigger, disabled = false, className = "", contentClassName } = props;

 ...
-          <BaseMenu.Popup className={className}>{children} </BaseMenu.Popup>
+          <BaseMenu.Popup className={contentClassName ?? className}>{children}</BaseMenu.Popup>
packages/propel/src/table/core.tsx (1)

5-11: Solid forwardRef typing; consider ElementRef for intrinsic elements

The forwardRef conversions look good and remove unsafe casts. For intrinsic elements (e.g., "table", "thead"), idiomatic typing uses React.ElementRef instead of React.ComponentRef.

Minimal changes:

-const Table = React.forwardRef<React.ComponentRef<"table">, React.ComponentPropsWithoutRef<"table">>(
+const Table = React.forwardRef<React.ElementRef<"table">, React.ComponentPropsWithoutRef<"table">>(
...
-const TableHeader = React.forwardRef<React.ComponentRef<"thead">, React.ComponentPropsWithoutRef<"thead">>(
+const TableHeader = React.forwardRef<React.ElementRef<"thead">, React.ComponentPropsWithoutRef<"thead">>(
...
-const TableBody = React.forwardRef<React.ComponentRef<"tbody">, React.ComponentPropsWithoutRef<"tbody">>(
+const TableBody = React.forwardRef<React.ElementRef<"tbody">, React.ComponentPropsWithoutRef<"tbody">>(
...
-const TableFooter = React.forwardRef<React.ComponentRef<"tfoot">, React.ComponentPropsWithoutRef<"tfoot">>(
+const TableFooter = React.forwardRef<React.ElementRef<"tfoot">, React.ComponentPropsWithoutRef<"tfoot">>(
...
-const TableRow = React.forwardRef<React.ComponentRef<"tr">, React.ComponentPropsWithoutRef<"tr">>(
+const TableRow = React.forwardRef<React.ElementRef<"tr">, React.ComponentPropsWithoutRef<"tr">>(
...
-const TableHead = React.forwardRef<React.ComponentRef<"th">, React.ComponentPropsWithoutRef<"th">>(
+const TableHead = React.forwardRef<React.ElementRef<"th">, React.ComponentPropsWithoutRef<"th">>(
...
-const TableCell = React.forwardRef<React.ComponentRef<"td">, React.ComponentPropsWithoutRef<"td">>(
+const TableCell = React.forwardRef<React.ElementRef<"td">, React.ComponentPropsWithoutRef<"td">>(
...
-const TableCaption = React.forwardRef<React.ComponentRef<"caption">, React.ComponentPropsWithoutRef<"caption">>(
+const TableCaption = React.forwardRef<React.ElementRef<"caption">, React.ComponentPropsWithoutRef<"caption">>(

Also applies to: 14-23, 25-29, 30-36, 37-47, 48-60, 62-71, 73-77

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 901409f and 5f8e316.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (107)
  • .gitignore (3 hunks)
  • apps/space/core/components/editor/rich-text-editor.tsx (1 hunks)
  • apps/space/package.json (3 hunks)
  • apps/web/ce/components/workspace/edition-badge.tsx (1 hunks)
  • apps/web/ce/components/workspace/sidebar/extended-sidebar-item.tsx (1 hunks)
  • apps/web/core/components/analytics/analytics-filter-actions.tsx (1 hunks)
  • apps/web/core/components/analytics/work-items/priority-chart.tsx (1 hunks)
  • apps/web/core/components/command-palette/command-palette.tsx (1 hunks)
  • apps/web/core/components/cycles/analytics-sidebar/issue-progress.tsx (1 hunks)
  • apps/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx (1 hunks)
  • apps/web/core/components/cycles/dropdowns/estimate-type-dropdown.tsx (1 hunks)
  • apps/web/core/components/dropdowns/estimate.tsx (1 hunks)
  • apps/web/core/components/dropdowns/member/member-options.tsx (1 hunks)
  • apps/web/core/components/estimates/delete/modal.tsx (1 hunks)
  • apps/web/core/components/estimates/estimate-disable-switch.tsx (1 hunks)
  • apps/web/core/components/estimates/estimate-list-item.tsx (1 hunks)
  • apps/web/core/components/estimates/root.tsx (1 hunks)
  • apps/web/core/components/gantt-chart/chart/root.tsx (1 hunks)
  • apps/web/core/components/home/home-dashboard-widgets.tsx (1 hunks)
  • apps/web/core/components/home/root.tsx (1 hunks)
  • apps/web/core/components/home/widgets/empty-states/no-projects.tsx (1 hunks)
  • apps/web/core/components/inbox/content/inbox-issue-header.tsx (1 hunks)
  • apps/web/core/components/inbox/inbox-filter/filters/filter-selection.tsx (1 hunks)
  • apps/web/core/components/issues/archive-issue-modal.tsx (1 hunks)
  • apps/web/core/components/issues/filters.tsx (1 hunks)
  • apps/web/core/components/issues/issue-layouts/calendar/base-calendar-root.tsx (1 hunks)
  • apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx (1 hunks)
  • apps/web/core/components/issues/issue-layouts/gantt/base-gantt-root.tsx (1 hunks)
  • apps/web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx (1 hunks)
  • apps/web/core/components/issues/issue-layouts/list/blocks-list.tsx (1 hunks)
  • apps/web/core/components/issues/issue-modal/context/issue-modal-context.tsx (1 hunks)
  • apps/web/core/components/issues/workspace-draft/draft-issue-properties.tsx (1 hunks)
  • apps/web/core/components/labels/delete-label-modal.tsx (1 hunks)
  • apps/web/core/components/labels/project-setting-label-group.tsx (1 hunks)
  • apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx (1 hunks)
  • apps/web/core/components/modules/analytics-sidebar/root.tsx (1 hunks)
  • apps/web/core/components/onboarding/create-workspace.tsx (1 hunks)
  • apps/web/core/components/onboarding/invitations.tsx (1 hunks)
  • apps/web/core/components/onboarding/root.tsx (1 hunks)
  • apps/web/core/components/onboarding/steps/team/root.tsx (1 hunks)
  • apps/web/core/components/onboarding/steps/workspace/create.tsx (1 hunks)
  • apps/web/core/components/onboarding/steps/workspace/join-invites.tsx (1 hunks)
  • apps/web/core/components/project/filters.tsx (1 hunks)
  • apps/web/core/components/settings/header.tsx (1 hunks)
  • apps/web/core/components/workspace-notifications/root.tsx (1 hunks)
  • apps/web/core/components/workspace-notifications/sidebar/notification-card/item.tsx (1 hunks)
  • apps/web/core/components/workspace-notifications/sidebar/root.tsx (1 hunks)
  • apps/web/core/components/workspace/delete-workspace-form.tsx (1 hunks)
  • apps/web/core/components/workspace/settings/members-list-item.tsx (1 hunks)
  • apps/web/core/components/workspace/settings/workspace-details.tsx (1 hunks)
  • apps/web/core/components/workspace/sidebar/sidebar-item.tsx (1 hunks)
  • apps/web/core/components/workspace/sidebar/workspace-menu-root.tsx (1 hunks)
  • apps/web/core/hooks/use-favorite-item-details.tsx (1 hunks)
  • apps/web/core/hooks/use-project-issue-properties.ts (1 hunks)
  • apps/web/core/hooks/use-workspace-issue-properties.ts (1 hunks)
  • apps/web/core/layouts/auth-layout/project-wrapper.tsx (1 hunks)
  • apps/web/core/layouts/auth-layout/workspace-wrapper.tsx (1 hunks)
  • apps/web/core/lib/intercom-provider.tsx (1 hunks)
  • apps/web/core/lib/posthog-provider.tsx (1 hunks)
  • apps/web/core/lib/wrappers/authentication-wrapper.tsx (1 hunks)
  • apps/web/core/store/timeline/modules-timeline.store.ts (1 hunks)
  • packages/decorators/.prettierignore (1 hunks)
  • packages/editor/package.json (3 hunks)
  • packages/hooks/package.json (1 hunks)
  • packages/i18n/package.json (1 hunks)
  • packages/i18n/tsconfig.json (1 hunks)
  • packages/propel/package.json (2 hunks)
  • packages/propel/src/avatar/avatar.tsx (1 hunks)
  • packages/propel/src/charts/area-chart/root.tsx (1 hunks)
  • packages/propel/src/charts/pie-chart/active-shape.tsx (2 hunks)
  • packages/propel/src/menu/menu.tsx (1 hunks)
  • packages/propel/src/menu/types.ts (2 hunks)
  • packages/propel/src/table/core.tsx (4 hunks)
  • packages/propel/tsconfig.json (1 hunks)
  • packages/services/package.json (1 hunks)
  • packages/shared-state/package.json (1 hunks)
  • packages/shared-state/tsconfig.json (1 hunks)
  • packages/ui/src/auth-form/auth-form.tsx (1 hunks)
  • packages/ui/src/auth-form/auth-input.tsx (1 hunks)
  • packages/ui/src/badge/badge.tsx (1 hunks)
  • packages/ui/src/breadcrumbs/breadcrumbs.tsx (1 hunks)
  • packages/ui/src/breadcrumbs/navigation-dropdown.tsx (1 hunks)
  • packages/ui/src/breadcrumbs/navigation-search-dropdown.tsx (1 hunks)
  • packages/ui/src/button/button.tsx (1 hunks)
  • packages/ui/src/button/toggle-switch.tsx (1 hunks)
  • packages/ui/src/collapsible/collapsible-button.tsx (1 hunks)
  • packages/ui/src/collapsible/collapsible.tsx (1 hunks)
  • packages/ui/src/content-wrapper/content-wrapper.tsx (1 hunks)
  • packages/ui/src/dropdown/multi-select.tsx (1 hunks)
  • packages/ui/src/dropdown/single-select.tsx (1 hunks)
  • packages/ui/src/dropdowns/custom-menu.tsx (1 hunks)
  • packages/ui/src/dropdowns/custom-select.tsx (1 hunks)
  • packages/ui/src/emoji/emoji-icon-picker-new.tsx (1 hunks)
  • packages/ui/src/emoji/emoji-icon-picker.tsx (1 hunks)
  • packages/ui/src/emoji/icons-list.tsx (1 hunks)
  • packages/ui/src/emoji/lucide-icons-list.tsx (1 hunks)
  • packages/ui/src/form-fields/input-color-picker.tsx (1 hunks)
  • packages/ui/src/form-fields/textarea.tsx (1 hunks)
  • packages/ui/src/header/header.tsx (1 hunks)
  • packages/ui/src/icons/cycle/cycle-group-icon.tsx (1 hunks)
  • packages/ui/src/icons/priority-icon.tsx (1 hunks)
  • packages/ui/src/modals/alert-modal.tsx (1 hunks)
  • packages/ui/src/modals/modal-core.tsx (1 hunks)
  • packages/ui/src/popovers/popover-menu.stories.tsx (1 hunks)
  • packages/ui/src/popovers/popover-menu.tsx (1 hunks)
  • packages/ui/src/popovers/popover.tsx (1 hunks)
  • packages/ui/src/popovers/types.ts (1 hunks)
⛔ Files not processed due to max files limit (3)
  • packages/ui/src/sortable/draggable.tsx
  • packages/ui/src/toast/index.tsx
  • packages/utils/package.json
✅ Files skipped from review due to trivial changes (73)
  • packages/ui/src/auth-form/auth-input.tsx
  • packages/ui/src/emoji/icons-list.tsx
  • packages/ui/src/breadcrumbs/breadcrumbs.tsx
  • apps/web/core/components/analytics/work-items/priority-chart.tsx
  • packages/decorators/.prettierignore
  • apps/web/core/components/home/widgets/empty-states/no-projects.tsx
  • apps/web/core/lib/wrappers/authentication-wrapper.tsx
  • apps/web/core/components/workspace/sidebar/workspace-menu-root.tsx
  • apps/web/core/components/issues/issue-layouts/gantt/base-gantt-root.tsx
  • apps/web/core/components/home/home-dashboard-widgets.tsx
  • packages/ui/src/breadcrumbs/navigation-dropdown.tsx
  • apps/web/core/hooks/use-favorite-item-details.tsx
  • packages/ui/src/form-fields/input-color-picker.tsx
  • packages/ui/src/breadcrumbs/navigation-search-dropdown.tsx
  • apps/web/core/hooks/use-workspace-issue-properties.ts
  • packages/ui/src/header/header.tsx
  • apps/web/core/components/modules/analytics-sidebar/root.tsx
  • apps/web/core/components/gantt-chart/chart/root.tsx
  • apps/web/core/components/workspace-notifications/sidebar/root.tsx
  • packages/ui/src/form-fields/textarea.tsx
  • apps/web/core/components/settings/header.tsx
  • packages/ui/src/dropdown/multi-select.tsx
  • apps/web/core/components/workspace/delete-workspace-form.tsx
  • apps/web/core/store/timeline/modules-timeline.store.ts
  • packages/ui/src/collapsible/collapsible.tsx
  • packages/ui/src/content-wrapper/content-wrapper.tsx
  • apps/web/core/components/onboarding/root.tsx
  • apps/web/core/lib/intercom-provider.tsx
  • apps/web/core/components/cycles/analytics-sidebar/issue-progress.tsx
  • apps/web/core/components/onboarding/steps/workspace/create.tsx
  • packages/ui/src/dropdowns/custom-menu.tsx
  • apps/web/core/components/onboarding/steps/workspace/join-invites.tsx
  • packages/ui/src/popovers/popover-menu.stories.tsx
  • apps/web/core/components/cycles/dropdowns/estimate-type-dropdown.tsx
  • apps/space/core/components/editor/rich-text-editor.tsx
  • apps/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx
  • apps/web/core/components/workspace-notifications/root.tsx
  • apps/web/core/components/issues/issue-layouts/list/blocks-list.tsx
  • packages/ui/src/dropdowns/custom-select.tsx
  • apps/web/core/components/estimates/estimate-list-item.tsx
  • apps/web/core/layouts/auth-layout/project-wrapper.tsx
  • apps/web/core/components/issues/issue-layouts/kanban/base-kanban-root.tsx
  • packages/ui/src/collapsible/collapsible-button.tsx
  • apps/web/core/components/onboarding/steps/team/root.tsx
  • packages/ui/src/popovers/popover.tsx
  • apps/web/core/components/command-palette/command-palette.tsx
  • packages/ui/src/dropdown/single-select.tsx
  • apps/web/core/components/issues/issue-modal/context/issue-modal-context.tsx
  • apps/web/core/components/estimates/delete/modal.tsx
  • packages/ui/src/emoji/emoji-icon-picker-new.tsx
  • apps/web/core/components/project/filters.tsx
  • apps/web/core/components/workspace/settings/workspace-details.tsx
  • apps/web/core/components/issues/issue-layouts/calendar/base-calendar-root.tsx
  • apps/web/core/components/issues/issue-layouts/filters/applied-filters/roots/project-root.tsx
  • apps/web/ce/components/workspace/edition-badge.tsx
  • apps/web/core/lib/posthog-provider.tsx
  • apps/web/core/components/estimates/root.tsx
  • apps/web/core/components/onboarding/create-workspace.tsx
  • apps/web/core/components/issues/archive-issue-modal.tsx
  • apps/web/core/hooks/use-project-issue-properties.ts
  • packages/ui/src/button/toggle-switch.tsx
  • packages/ui/src/auth-form/auth-form.tsx
  • apps/web/core/components/workspace/sidebar/sidebar-item.tsx
  • apps/web/core/components/issues/filters.tsx
  • apps/web/core/components/workspace/settings/members-list-item.tsx
  • packages/ui/src/icons/priority-icon.tsx
  • packages/ui/src/badge/badge.tsx
  • packages/ui/src/emoji/emoji-icon-picker.tsx
  • packages/ui/src/popovers/types.ts
  • apps/web/core/components/home/root.tsx
  • packages/ui/src/modals/alert-modal.tsx
  • apps/web/core/components/estimates/estimate-disable-switch.tsx
  • packages/ui/src/icons/cycle/cycle-group-icon.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/hooks/package.json
  • packages/shared-state/package.json
  • packages/propel/package.json
  • packages/services/package.json
  • apps/space/package.json
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-14T13:16:23.323Z
Learnt from: vamsikrishnamathala
PR: makeplane/plane#7061
File: web/core/components/workspace-notifications/root.tsx:18-18
Timestamp: 2025-05-14T13:16:23.323Z
Learning: In the Plane project codebase, the path alias `@/plane-web` resolves to the `ce` directory, making imports like `@/plane-web/hooks/use-notification-preview` correctly resolve to files in `web/ce/hooks/`.

Applied to files:

  • apps/web/core/components/analytics/analytics-filter-actions.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build and lint web apps
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (28)
apps/web/core/components/inbox/content/inbox-issue-header.tsx (1)

29-30: LGTM: Import reordering only; no runtime impact

Reordering these hook imports is fine and keeps the hooks grouped logically. No changes to bindings or behavior.

packages/ui/src/button/button.tsx (1)

4-4: LGTM: import reordering is safe and non-functional.

This is a straightforward import-order tweak with no runtime impact. Good to keep imports organized consistently.

packages/propel/src/charts/pie-chart/active-shape.tsx (1)

5-5: Nice: explicit props typing improves safety and DX.

Typing the props as PieSectorDataItem removes any and aligns with Recharts’ expected shape.

apps/web/core/components/onboarding/invitations.tsx (1)

17-17: Import reordering LGTM

Reordering the hook imports keeps the hooks grouped and preserves behavior. No functional impact.

apps/web/core/components/analytics/analytics-filter-actions.tsx (1)

5-5: Import reordering only; no runtime impact — LGTM

Grouping hook imports is consistent and does not affect behavior. No further action needed.

apps/web/core/components/modules/analytics-sidebar/issue-progress.tsx (1)

20-20: Import reordering improves readability — LGTM

Moving useProjectEstimates into the hooks group keeps imports organized. No behavior change.

apps/web/core/components/inbox/inbox-filter/filters/filter-selection.tsx (1)

6-6: Import reordering aligns with hooks grouping — LGTM

No functional change; keeps store hooks together for readability.

packages/ui/src/modals/modal-core.tsx (1)

2-2: LGTM: import reorg only; no runtime or type changes

Reordering React and moving cn to the top block doesn’t affect behavior. The paths remain correct and ModalCore usage is unchanged.

Also applies to: 4-4

packages/i18n/package.json (3)

18-18: Switch to workspace: for internal utils looks good*

Using workspace:* ensures local resolution under pnpm and prevents accidental registry fetches. Good alignment with the monorepo migration.


24-25: Workspace-scoped tooling dependencies LGTM

Pointing @plane/eslint-config and @plane/typescript-config to workspace:* is correct for pnpm workspaces and keeps toolchain versions consistent.


18-21: MobX dependencies are actively used in i18n package

The verification confirms that both mobx and mobx-react are legitimately used in the i18n package:

packages/i18n/src/store/index.ts: Uses makeAutoObservable and runInAction from mobx
packages/i18n/src/context/index.tsx: Uses observer from mobx-react to wrap the TranslationProvider component

The i18n package implements a MobX-based translation store with reactive components, making these dependencies necessary for its functionality. The dependencies should remain as regular dependencies rather than being moved to peerDependencies, as this is a utility package that needs to manage its own state store.

apps/web/core/components/workspace-notifications/sidebar/notification-card/item.tsx (1)

10-13: Import re-order reads clean and preserves behavior

Hooks are grouped under the "hooks" section and there’s no duplicate import anymore. No runtime changes introduced.

apps/web/core/components/dropdowns/member/member-options.tsx (1)

12-12: Consolidated IUserLite import — LGTM

Importing IUserLite alongside other Plane workspace imports keeps things tidy and avoids duplicate imports. No runtime impact; types are correctly scoped.

packages/propel/src/charts/area-chart/root.tsx (1)

101-101: Good catch: add yAxis.key to useMemo deps

Including yAxis.key ensures recomputation when the metric changes. This prevents stale comparison lines when toggling Y metrics.

packages/ui/src/emoji/lucide-icons-list.tsx (2)

7-7: Import reorder looks good; no functional impact.

Moving the cn import has no runtime effect and aligns with the broader import tidy-up implied by the PR. Safe change.


90-93: No changes needed: cn supports object syntax
cn is defined in packages/ui/src/utils/classname.tsx as:

export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs));

Since clsx natively handles object maps for conditional classes and its output is passed to twMerge, the { "border-custom-border-400": !showHexInput } syntax is fully supported.

apps/web/core/components/issues/workspace-draft/draft-issue-properties.tsx (2)

24-24: Import reordering within the hooks block is fine

This keeps hooks grouped and has no runtime impact.


21-21: Import alias resolution validated: the useProjectEstimates hook is correctly exported and the @/* alias maps to core/* in apps/web/tsconfig.json. Consistent imports of @/hooks/store/estimates are already present across the codebase, so no further changes are needed.

apps/web/core/components/labels/delete-label-modal.tsx (2)

7-7: Consolidated constants import looks good

Bringing both PROJECT_SETTINGS_TRACKER_ELEMENTS and PROJECT_SETTINGS_TRACKER_EVENTS into a single top-level import cleans up duplication and keeps imports consistent.


13-13: Import organization LGTM

Keeping useLabel grouped with the other hooks imports improves readability.

apps/web/core/components/labels/project-setting-label-group.tsx (1)

8-12: Import path and ordering cleanup looks correct

Moving PROJECT_SETTINGS_TRACKER_ELEMENTS to import from @plane/constants and captureClick to the top import block keeps dependencies organized and removes bottom-file duplication.

apps/web/core/components/dropdowns/estimate.tsx (1)

13-15: Import re-order looks good

Pure import shuffle; no behavioral impact. Matches the broader stylistic cleanups in the PR.

packages/propel/tsconfig.json (1)

4-4: Verified React and TypeScript versions – safe to use react-jsx

All scanned package.json files show React ≥ 17 (v18.3.1) and TypeScript ≥ 4.1 (v5.8.3), so the "jsx": "react-jsx" setting is fully supported.

apps/web/ce/components/workspace/sidebar/extended-sidebar-item.tsx (1)

19-19: Import re-order is a safe no-op.

Moving the user hooks import below useWorkspace is stylistic and has no runtime side effects. Looks good.

apps/web/core/layouts/auth-layout/workspace-wrapper.tsx (2)

19-19: New useFavorite import aligns with existing usage.

This import matches the fetchFavorite usage below and the SWR gate by permissions. All good.


24-24: ✅ pnpm Migration Verified

Verified that the import reorder in apps/web/core/layouts/auth-layout/workspace-wrapper.tsx is a no-op and the pnpm migration is complete:

• pnpm-workspace.yaml present at repo root
• package.json’s packageManager set to “pnpm@10.12.1”
• No yarn or npm install/ci/run invocations outside pnpm context
• pnpm commands used consistently in workflows, Dockerfiles, and scripts

No further Yarn/NPM references detected—good to merge.

packages/propel/src/menu/types.ts (1)

46-46: Good: safer click signature for menu items

Using onClick?: (_args?: unknown) => void; avoids over-constraining consumer event payloads and aligns with the internal call sites that pass the native event.

packages/propel/src/avatar/avatar.tsx (1)

81-81: Robust number guard and correct NaN check

Type-narrowing with (value: unknown): value is number and Number.isNaN is the right approach here. Nice improvement over isNaN.

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: 5

🔭 Outside diff range comments (2)
packages/editor/tsconfig.json (2)

6-7: moduleResolution value casing likely invalid ("bundler" → "Bundler")

TypeScript expects the enum-cased value "Bundler". Using "bundler" can cause TS to error with an unknown moduleResolution.

Apply this diff to fix:

-    "moduleResolution": "bundler",
+    "moduleResolution": "Bundler",

3-11: Detected Node Buffer usage in browser‐only package – fix required

The editor package still references Buffer.from(…) in
packages/editor/src/core/helpers/yjs-utils.ts (lines 42 & 49). Without Node ambient types, TS will error here.

• File & lines to address
– packages/editor/src/core/helpers/yjs-utils.ts:42
– packages/editor/src/core/helpers/yjs-utils.ts:49

Recommended fixes

  1. Re-introduce Node types in your tsconfig:
// packages/editor/tsconfig.json
{
  "compilerOptions": {
+   "types": ["node", "vite/client"],
    …  
  }
}
  1. Or refactor these helpers to browser APIs (e.g. use atob()/btoa() on strings or TextEncoder/TextDecoder for ArrayBuffers) and remove Buffer.from.
  2. Alternatively, declare a local ambient for Buffer if you have a bundler polyfill:
// packages/editor/src/global.d.ts
declare const Buffer: {
  from(input: string | Uint8Array, encoding?: string): Uint8Array | string;
};
🧹 Nitpick comments (6)
apps/live/package.json (1)

49-50: Dotenv import detected—can’t remove until you migrate to --env-file

We found that apps/live is still importing and using dotenv, so you must keep it as a dependency unless you refactor startup to rely solely on Node’s --env-file flag. Also, there’s no @types/pino-http in this package, so nothing to remove there.

• apps/live/src/core/services/api.service.ts – import { config } from "dotenv";
• apps/live/src/core/helpers/logger.ts – import { pinoHttp } from "pino-http"; (no @types/pino-http entry in package.json)

If you do want to drop dotenv:

  1. Remove the config import and any calls to config() in your code.
  2. Update your start scripts (e.g. in package.json) to include node --env-file .env ….
  3. (Optional) Add an "engines": { "node": ">=20.6" } to apps/live/package.json to document the required Node version.
packages/utils/package.json (1)

30-30: Consider making UI libs peer deps or move icon helpers out of utils.

Adding lucide-react as a runtime dependency in a "utils" package couples it to React UI concerns and can cause duplicate installs in consumers. Options:

  • Prefer placing icon/React-specific helpers in @plane/ui.
  • Or declare react and lucide-react as peerDependencies here (and keep @types/react in devDependencies for typing).

Apply this minimal change to avoid bundling lucide-react from utils:

   "dependencies": {
     "@plane/constants": "workspace:*",
     "@plane/types": "workspace:*",
     "clsx": "^2.1.1",
     "date-fns": "^4.1.0",
     "isomorphic-dompurify": "^2.16.0",
     "lodash": "^4.17.21",
-    "lucide-react": "^0.469.0",
     "react": "^18.3.1",
     "tailwind-merge": "^2.5.5",
     "uuid": "^10.0.0"
   },
+  "peerDependencies": {
+    "react": "^18.0.0",
+    "lucide-react": "^0.469.0"
+  },
+  "peerDependenciesMeta": {
+    "lucide-react": {
+      "optional": true
+    }
+  },

If utils must export React/icon helpers, this approach prevents version conflicts and duplicate bundles in apps.

apps/space/package.json (1)

11-11: Raising max lint warnings masks issues.

Prefer fixing or disabling non-actionable rules rather than increasing the warning budget. If this is temporary to unblock the pnpm migration, add a TODO with a target to revert.

packages/editor/tsconfig.json (1)

2-20: Consider extending the shared tsconfig to reduce drift

This tsconfig doesn’t extend the monorepo’s shared configs. To stay aligned and reduce maintenance, consider:

+  "extends": "../typescript-config/react-library.json",
   "compilerOptions": {
-    "jsx": "react-jsx",
-    "lib": ["ES2022", "DOM"],
-    "module": "ESNext",
-    "moduleResolution": "Bundler",
-    "noEmit": true,
-    "skipLibCheck": true,
-    "sourceMap": true,
-    "target": "ESNext",
+    "jsx": "react-jsx",
+    "noEmit": true,
+    "sourceMap": true,
     "baseUrl": ".",
     "paths": {
       "@/*": ["./src/core/*"],
       "@/styles/*": ["./src/styles/*"],
       "@/plane-editor/*": ["./src/ce/*"]
     },
-    "strictNullChecks": true,
-    "allowSyntheticDefaultImports": true
+    "strictNullChecks": true
   },

Adjust as needed if you intentionally diverge (e.g., different target or libs).

packages/typescript-config/base.json (1)

7-8: Consider enabling incremental builds for faster TS rebuilds

"incremental": false disables TS’s build info caching. In a monorepo with Turbo/pnpm, incremental true often reduces CI and local re-check times significantly. If you don’t rely on tsc -b artifacts, feel free to skip.

-    "incremental": false,
+    "incremental": true,
packages/typescript-config/nextjs.json (1)

8-11: allowJs: true may widen the typecheck surface in Next apps

allowJs includes .js files in typechecking. If the app has many JS files, this can slow checks. Keep if intentional (mixed TS/JS), otherwise consider disabling or scoping via "include".

-    "allowJs": true,
+    // "allowJs": true,
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5f8e316 and e0aea3c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (19)
  • .npmrc (1 hunks)
  • apps/admin/package.json (2 hunks)
  • apps/live/package.json (2 hunks)
  • apps/live/tsconfig.json (1 hunks)
  • apps/space/package.json (3 hunks)
  • apps/space/tsconfig.json (1 hunks)
  • apps/web/package.json (3 hunks)
  • packages/constants/package.json (1 hunks)
  • packages/decorators/package.json (1 hunks)
  • packages/decorators/tsconfig.json (1 hunks)
  • packages/editor/tsconfig.json (1 hunks)
  • packages/logger/package.json (1 hunks)
  • packages/propel/src/charts/pie-chart/active-shape.tsx (2 hunks)
  • packages/propel/tsconfig.json (1 hunks)
  • packages/typescript-config/base.json (1 hunks)
  • packages/typescript-config/nextjs.json (1 hunks)
  • packages/typescript-config/node-library.json (1 hunks)
  • packages/typescript-config/react-library.json (1 hunks)
  • packages/utils/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (10)
  • packages/decorators/tsconfig.json
  • apps/web/package.json
  • apps/space/tsconfig.json
  • packages/decorators/package.json
  • packages/logger/package.json
  • packages/propel/src/charts/pie-chart/active-shape.tsx
  • apps/live/tsconfig.json
  • packages/constants/package.json
  • packages/propel/tsconfig.json
  • .npmrc
🔇 Additional comments (10)
apps/admin/package.json (2)

21-27: Workspace refs look good.

Switching internal @plane deps to "workspace:*" aligns with pnpm workspaces and will prevent accidental version drift. No concerns.


46-49: Dev deps migration to workspace: and moving @types/lodash to dev is correct.*

This cleans up install surfaces and keeps types out of runtime. Looks good.

apps/live/package.json (1)

27-29: Workspace refs migration is consistent.

@plane/editor and @plane/types to "workspace:*" is aligned with the pnpm move. No action needed.

packages/utils/package.json (2)

24-25: Workspace refs LGTM.

Using "workspace:*" for @plane/constants and @plane/types is correct for pnpm.


36-37: Dev tooling to workspace: and adding @types/lodash is fine.*

No issues here. If you adopt peerDependencies for React above, keeping @types/react here is still appropriate for local TS builds.

Also applies to: 41-41

apps/space/package.json (4)

24-31: Workspace refs migration is consistent and comprehensive.

All internal packages moved to "workspace:*" including the newly added @plane/utils. Looks good.


50-50: @popperjs/core version aligns with react-popper v2.

react-popper@^2 expects @popperjs/core@^2, so this addition is correct.


52-52: sharp requires native binaries—double-check build images for this app too.

Same caution as admin: ensure Docker/CI environments are compatible with sharp’s prebuilt binaries or install required libs (avoid Alpine or install libc-compat/libvips).

Run the same sharp/Docker verification script from the admin comment, replacing the path filter with apps/space if you maintain per-app Dockerfiles.


58-61: Dev deps to workspace: and updated @types/lodash are fine.*

No concerns.

packages/typescript-config/nextjs.json (1)

6-7: LGTM on ESNext/Bundler for Next.js

"module": "ESNext" and "moduleResolution": "Bundler" align with TS ≥ 5.3 and Next 14+ recommendations. Verified all workspace package.json files list TypeScript 5.6.3 or 5.8.3—no workspaces below 5.3, so no further action is needed.

…e and catalog; pnpm install to update lockfile
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: 1

♻️ Duplicate comments (1)
package.json (1)

27-41: TypeScript version alignment looks good now

The root pnpm override pins typescript to 5.8.3, which aligns with packages (e.g., packages/propel). This resolves the earlier mismatch noted in prior reviews.

🧹 Nitpick comments (3)
package.json (2)

43-43: Add engines to enforce Node/pnpm versions across contributors and CI

To avoid environment drift (especially with sharp/esbuild/turbo requirements), add an engines block. Also consider adding "engineStrict": true if you want installs to fail on mismatches.

Proposed addition near the top-level of package.json:

 {
   "name": "plane",
   "description": "Open-source project management that unlocks customer value",
   "repository": "https://github.com/makeplane/plane.git",
   "version": "0.28.0",
   "license": "AGPL-3.0",
   "private": true,
+  "engines": {
+    "node": ">=18.18.0",
+    "pnpm": ">=10.12.1"
+  },
   "workspaces": [
     "apps/*",
     "packages/*"
   ],

23-25: Pin Prettier to a fixed v3 version for deterministic installs

Pinning Prettier avoids non-reproducible CI/local installs. Align the root version with the one used in apps/web (v3.2.5) while preserving plugin compatibility:

• In package.json (root)

-    "prettier": "latest",
+    "prettier": "^3.2.5",
     "prettier-plugin-tailwindcss": "^0.6.14",
     "turbo": "^2.5.6"

• Compatibility verified:
– root prettier-plugin-tailwindcss ^0.6.14 → requires Prettier >=3 (✅)
– packages/tailwind-config prettier-plugin-tailwindcss ^0.3.0 → uses Prettier ^2.8.8 (unchanged)

packages/propel/package.json (1)

25-29: Good move to workspace protocol for internal deps

Switching to "workspace:*" ensures local linking and consistent versions across the monorepo.

If you want semver protection on intra-repo bumps, consider using "workspace:^" instead of "*" so consumers don’t inadvertently accept breaking changes before coordinated releases.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e0aea3c and 688a74f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • apps/space/package.json (3 hunks)
  • apps/web/package.json (3 hunks)
  • package.json (1 hunks)
  • packages/editor/package.json (3 hunks)
  • packages/propel/package.json (2 hunks)
  • packages/ui/package.json (2 hunks)
  • packages/utils/package.json (1 hunks)
  • pnpm-workspace.yaml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/utils/package.json
  • packages/editor/package.json
  • apps/web/package.json
  • packages/ui/package.json
  • pnpm-workspace.yaml
  • apps/space/package.json
🔇 Additional comments (2)
package.json (1)

27-41: esbuild 0.25.0 override is safe
Only tsup@8.4.0 (the sole esbuild consumer in this monorepo) declares "esbuild": "^0.25.0", so the override to 0.25.0 satisfies its dependency. No other build tools—Vite, Rollup, unplugin-*, next-transpile-modules, etc.—are present.

• Root package.json (lines 27–41): "esbuild": "0.25.0"
• All workspaces and apps use tsup@8.4.0, which depends on esbuild:^0.25.0

packages/propel/package.json (1)

39-41: Dev toolchains now aligned to workspace packages

All referenced @plane/* workspace dependencies have been verified and are resolvable. Using "workspace:*" for internal config packages (eslint, tailwind, tsconfig) keeps the toolchain consistent across packages. LGTM.

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: 0

♻️ Duplicate comments (1)
apps/space/Dockerfile.dev (1)

19-19: Fix pnpm filter flag position (likely running the wrong package).

--filter=space appears after the command, which pnpm treats as an argument to the script rather than a pnpm flag. This can execute the root script or the wrong package. Place the filter before the command or target the workspace directory with -C.

Apply one of these:

Option A (directory-scoped, most robust):

-CMD ["pnpm", "dev", "--filter=space"]
+CMD ["pnpm", "-C", "apps/space", "dev"]

Option B (keep filter, ensure correct flag position; adjust pattern to actual package if needed):

-CMD ["pnpm", "dev", "--filter=space"]
+CMD ["pnpm", "--filter=./apps/space", "dev"]
🧹 Nitpick comments (6)
packages/constants/src/workspace.ts (3)

276-281: Avoid non-null assertions on indexed access; tighten the map types instead

Using ! masks missing-key bugs at runtime. These keys exist, so prefer stronger typing over assertions.

Apply this diff to remove the non-null assertions:

 export const WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS_LINKS: IWorkspaceSidebarNavigationItem[] = [
-  WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS["views"]!,
-  WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS["analytics"]!,
-  WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS["drafts"]!,
-  WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS["archives"]!,
+  WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS["views"],
+  WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS["analytics"],
+  WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS["drafts"],
+  WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS["archives"],
 ];

If noUncheckedIndexedAccess is enabled, removing ! may surface type errors due to Record<string, ...>. In that case, also refine the record’s type to exact keys so the index is non-optional:

type DynamicNavKey = "views" | "analytics" | "drafts" | "archives";

// Option A (explicit Record)
export const WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS: Record<DynamicNavKey, IWorkspaceSidebarNavigationItem> = { /* existing object */ };

// Option B (preferred if TS >= 4.9)
export const WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS = {
  /* existing object */
} satisfies Record<DynamicNavKey, IWorkspaceSidebarNavigationItem>;

311-314: Same: drop non-null assertions and refine the static map type

Stay consistent and keep type-safety without !.

Apply this diff:

 export const WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS_LINKS: IWorkspaceSidebarNavigationItem[] = [
-  WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["home"]!,
-  WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["inbox"]!,
-  WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["your-work"]!,
+  WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["home"],
+  WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["inbox"],
+  WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["your-work"],
 ];

If needed for noUncheckedIndexedAccess, narrow the map keys:

type StaticNavKey = "home" | "inbox" | "your-work" | "projects";

export const WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS: Record<StaticNavKey, IWorkspaceSidebarNavigationItem> = { /* existing object */ };
// or with `satisfies` (TS >= 4.9)
export const WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS = { /* existing object */ } satisfies Record<StaticNavKey, IWorkspaceSidebarNavigationItem>;

316-318: Also remove the non-null assertion here

Consistent with the above, avoid ! for pinned items.

Apply this diff:

 export const WORKSPACE_SIDEBAR_STATIC_PINNED_NAVIGATION_ITEMS_LINKS: IWorkspaceSidebarNavigationItem[] = [
-  WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["projects"]!,
+  WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["projects"],
 ];
apps/space/Dockerfile.dev (1)

10-11: Pin installs and improve dev-layer caching (optional).

  • Use a locked install to avoid drift when the lockfile is present.
  • Consider cache-friendly layering to speed up rebuilds (copy only lockfiles and manifests before pnpm install). If you’ve added packageManager in package.json (pnpm@x), corepack enable will honor it.

Minimal hardening:

-RUN pnpm install
+RUN pnpm install --frozen-lockfile

Optional cache-friendly restructuring (illustrative; adjust paths as needed):

- COPY . .
- RUN corepack enable pnpm && pnpm add -g turbo
- RUN pnpm install
+ COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
+ COPY apps/space/package.json apps/space/
+ RUN corepack enable pnpm && pnpm install --frozen-lockfile
+ COPY . .

If you don’t actually need Turbo globally here, you can avoid the global install and use dlx:

-RUN corepack enable pnpm && pnpm add -g turbo
+RUN corepack enable pnpm
+# when needed: pnpm dlx turbo <cmd>
apps/space/helpers/file.helper.ts (1)

45-49: Current fallback is effectively a no-op; consider robust asset-id parsing (trim slash, strip query/hash, decode).

src.split("/") always yields at least one element, so assetUrl is never undefined—the ?? "" won’t trigger. For common cases like trailing slashes or signed URLs with query params, this can return an empty string or include the query string. Suggest normalizing: strip query/hash, trim trailing slashes, take the last path segment, and decode it.

Apply this focused refactor:

 export const getAssetIdFromUrl = (src: string): string => {
-  const sourcePaths = src.split("/");
-  const assetUrl = sourcePaths[sourcePaths.length - 1];
-  return assetUrl ?? "";
+  if (!src) return "";
+  // Strip query/hash and trailing slashes, then take last path segment
+  const [pathWithoutQuery] = src.split(/[?#]/);
+  const trimmed = pathWithoutQuery.replace(/\/+$/, "");
+  const lastSegment = trimmed.split("/").pop() ?? "";
+  try {
+    return decodeURIComponent(lastSegment);
+  } catch {
+    return lastSegment; // if not a valid URI component
+  }
 }

Verification suggestion:

  • Ensure all call sites treating a falsy id are resilient to empty-string returns (or consider returning undefined and updating types if that models “no id” better).

Optional follow-up:

  • This helper exists in multiple packages. Consider centralizing it in a shared util (e.g., a common package) to avoid drift. I can help consolidate if you want.
packages/services/src/file/helper.ts (1)

32-36: Consolidate and harden getAssetIdFromUrl across the repo

You’ve got three separate implementations of getAssetIdFromUrl (in packages/utils, packages/services, and apps/space), each with the same simplistic logic and a never-used ?? "" fallback. Let’s centralize to a single, robust helper and remove the duplicates.

Suggested steps:

  • Extract the improved version into packages/utils/src/file.ts (or a new shared module).
  • Update all imports in:
    packages/services/src/file/helper.ts
    apps/space/helpers/file.helper.ts
    • any other local copies
    to import from @plane/utils instead of redefining.
  • Enhance the implementation to:
    • guard against empty/invalid inputs
    • strip query (?) or hash (#) parts
    • trim trailing slashes
    • safely decode URI segments
    • fall back to "" if nothing’s left

Example shared helper in packages/utils/src/file.ts:

export function getAssetIdFromUrl(src: string): string {
  if (!src) return "";
  const [path] = src.split(/[?#]/);
  const trimmed = path.replace(/\/+$/, "");
  const segment = trimmed.split("/").pop() ?? "";
  try {
    return decodeURIComponent(segment);
  } catch {
    return segment;
  }
}

Then in your services and app code:

- import { getAssetIdFromUrl } from "./helper";
+ import { getAssetIdFromUrl } from "@plane/utils";

This DRYs up our code and ensures every consumer handles edge cases consistently.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 688a74f and e96fe46.

📒 Files selected for processing (5)
  • apps/space/Dockerfile.dev (1 hunks)
  • apps/space/core/components/editor/rich-text-editor.tsx (1 hunks)
  • apps/space/helpers/file.helper.ts (1 hunks)
  • packages/constants/src/workspace.ts (2 hunks)
  • packages/services/src/file/helper.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/space/core/components/editor/rich-text-editor.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Build and lint web apps
🔇 Additional comments (2)
apps/space/Dockerfile.dev (2)

17-17: Good catch on the node_modules volume path.

The workspace-specific node_modules path is now correct: /app/apps/space/node_modules.


13-13: Verify Docker Compose port mapping for space service

I’ve confirmed that:

  • apps/space/package.json dev script uses next dev -p 3002
  • apps/space/Dockerfile.dev exposes port 3002

However, neither of your docker-compose.yml files (in deployments/cli/community or the repo root) defines a ports: mapping for the space service. Please confirm one of the following:

  • If you need to publish the container port, add under space:
    services:
      space:
        ports:
          - "3002:3002"
  • If you rely on an external proxy or network routing, verify it’s configured to route traffic to container port 3002.

@sriramveeraghanta sriramveeraghanta changed the title Setup pnpm 2 migrate to pnpm from yarn v1.22.22 Aug 19, 2025
@sriramveeraghanta sriramveeraghanta changed the title migrate to pnpm from yarn v1.22.22 feat: migrate to pnpm from yarn v1.22.22 Aug 19, 2025
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: 1

♻️ Duplicate comments (2)
packages/typescript-config/base.json (2)

9-9: Do not leak DOM types from base config; keep base neutral

Including "DOM" and "DOM.Iterable" in base pollutes Node libraries with browser globals (e.g., window, fetch), causing type conflicts. Push DOM libs down into browser-facing presets (react/next) instead and keep base with just ES libs. Also align casing to "ES2022".

Apply this diff:

-    "lib": ["es2022", "DOM", "DOM.Iterable"],
+    "lib": ["ES2022"],

If not already, set these in packages/typescript-config/react-library.json and nextjs.json:

  • react-library.json: compilerOptions.lib ["ES2022", "DOM", "DOM.Iterable"]
  • nextjs.json: compilerOptions.lib ["ES2022", "DOM", "DOM.Iterable"]

10-12: Avoid Node-centric module defaults in base; move to per-preset configs

Setting "module": "NodeNext" and "moduleResolution": "NodeNext" (and forcing module detection) in base makes browser packages inherit Node behavior unless they override. Keep base minimal and move these to node-only presets; use ESNext/Bundler in browser presets.

Apply this diff to keep base neutral:

-    "module": "NodeNext",
-    "moduleDetection": "force",
-    "moduleResolution": "NodeNext",

Then ensure:

  • packages/typescript-config/node-library.json sets:
    "module": "NodeNext", "moduleResolution": "NodeNext", "moduleDetection": "force" (if you want strict ESM)
  • packages/typescript-config/react-library.json and nextjs.json set:
    "module": "ESNext", "moduleResolution": "Bundler"

To verify consumers are correctly configured, run:

#!/bin/bash
# List tsconfig.json files extending base and check for browser-safe overrides
echo "Scanning package tsconfig.json consumers..."
fd -a tsconfig.json packages | grep -v 'packages/typescript-config/' | while read -r f; do
  ext=$(jq -r '.extends // ""' "$f" 2>/dev/null)
  if [[ "$ext" == *"typescript-config/base.json"* ]]; then
    mod=$(jq -r '.compilerOptions.module // ""' "$f" 2>/dev/null)
    res=$(jq -r '.compilerOptions.moduleResolution // ""' "$f" 2>/dev/null)
    libs=$(jq -r '.compilerOptions.lib // [] | join(",")' "$f" 2>/dev/null)
    echo "$f extends base.json  | module=$mod | moduleResolution=$res | lib=[$libs]"
  fi
done
echo
echo "React/Next presets should show ESNext/Bundler and DOM libs; Node presets should show NodeNext/NodeNext and no DOM libs."
🧹 Nitpick comments (4)
apps/live/src/core/helpers/logger.ts (1)

39-39: LGTM for pnpm migration; optional: drop redundant type annotation

Using typeof logger.logger avoids importing the pino type directly, which is a good move under pnpm’s stricter transitive dependency rules. As a minor cleanup, you can rely on type inference and omit the explicit annotation.

Apply this diff if you prefer the leaner version:

-export const manualLogger: typeof logger.logger = logger.logger;
+export const manualLogger = logger.logger;
packages/typescript-config/base.json (1)

7-7: Don’t globally disable incremental builds in base

Setting "incremental": false at the base can slow down library rebuilds across the monorepo. Prefer leaving it unset here and enabling it in library-centric presets (with composite: true) to leverage TS build info caching.

Apply this diff:

-    "incremental": false,

And in packages/typescript-config/node-library.json (and similar for react-library.json if they build with tsc):

{
  "compilerOptions": {
    "composite": true,
    "incremental": true
  }
}
apps/live/package.json (2)

49-50: Optional: Align dev tooling to workspace:^ for consistency

Using workspace:* for internal configs is fine, but adopting workspace:^ here too keeps version compatibility checks consistent across the repo.

Possible diff:

-    "@plane/eslint-config": "workspace:*",
-    "@plane/typescript-config": "workspace:*",
+    "@plane/eslint-config": "workspace:^",
+    "@plane/typescript-config": "workspace:^",

27-28: Prefer workspace:^ over workspace:* for runtime dependencies

Using workspace:^ ensures that your runtime packages follow semver ranges and will break if incompatible versions are introduced, whereas workspace:* always links regardless of version mismatches.

File: apps/live/package.json
Lines: 27–28

-    "@plane/editor": "workspace:*",
-    "@plane/types": "workspace:*",
+    "@plane/editor": "workspace:^",
+    "@plane/types": "workspace:^",
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e96fe46 and 7a7b01d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • apps/live/package.json (2 hunks)
  • apps/live/src/core/helpers/logger.ts (1 hunks)
  • package.json (1 hunks)
  • packages/i18n/package.json (1 hunks)
  • packages/typescript-config/base.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/i18n/package.json
  • package.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build and lint web apps
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (1)
packages/typescript-config/base.json (1)

13-17: LGTM on strictness and common interop flags

resolveJsonModule, skipLibCheck, strict, and target look reasonable for a shared baseline. No changes requested here.

@sriramveeraghanta sriramveeraghanta merged commit 553f01f into preview Aug 19, 2025
4 of 6 checks passed
@sriramveeraghanta sriramveeraghanta deleted the setup-pnpm-2 branch August 19, 2025 14:36
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