Skip to content

feat: support bun package manager and bun workspaces#106

Merged
9romise merged 15 commits intonpmx-dev:mainfrom
RYGRIT:feat/bun
Apr 23, 2026
Merged

feat: support bun package manager and bun workspaces#106
9romise merged 15 commits intonpmx-dev:mainfrom
RYGRIT:feat/bun

Conversation

@RYGRIT
Copy link
Copy Markdown
Collaborator

@RYGRIT RYGRIT commented Apr 14, 2026

related #102

Changes:

  • add Bun support to workspace context and dependency resolution
  • support catalog, catalogs, workspaces.catalog, etc in Bun workspaces
  • merge Bun root package.json manifest and catalog entries for hover/diagnostics
  • add tests covering Bun package manager, workspace catalogs, and Windows path behavior
  • update playground/bun to a real Bun workspace example

@RYGRIT RYGRIT marked this pull request as ready for review April 15, 2026 02:39
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 15, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

This pull request adds support for Bun as a package manager alongside npm, pnpm, and yarn. It introduces workspace catalog extraction functionality through the extended JsonExtractor class implementing WorkspaceCatalogExtractor, enabling dependency resolution via catalog entries. The WorkspaceContext gains context-specific workspace file detection and Bun-aware catalog loading. New test suites validate catalog parsing and workspace context behaviour. A Bun playground workspace is introduced to demonstrate the feature. The codebase transitions from the pathe dependency to path-browserify for path utilities. Documentation is updated to reflect support for multiple package managers in workspace-aware resolution.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description is directly related to the changeset, detailing Bun support additions, catalog handling, and workspace context updates that align with the file changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

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

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

❤️ Share

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

Copy link
Copy Markdown
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

🧹 Nitpick comments (2)
packages/language-server/src/merge-resolved-dependencies.ts (1)

7-10: Return a fresh array in every non-undefined path for consistent immutability.

Current behaviour returns a copy when both inputs exist, but returns the original reference when only one exists. A consistent copy-on-return pattern is safer.

Proposed refactor
 export function mergeResolvedDependencies(
   manifestDependencies?: DependencyInfo[],
   workspaceDependencies?: DependencyInfo[],
 ): DependencyInfo[] | undefined {
-  if (manifestDependencies && workspaceDependencies)
-    return [...manifestDependencies, ...workspaceDependencies]
-
-  return manifestDependencies ?? workspaceDependencies
+  if (!manifestDependencies && !workspaceDependencies)
+    return undefined
+
+  return [
+    ...(manifestDependencies ?? []),
+    ...(workspaceDependencies ?? []),
+  ]
 }
packages/language-core/src/extractors/json.test.ts (1)

46-69: Add dependency assertions for the nested workspaces catalog case.

This test currently validates only catalogs. Asserting dependencies too would better guard against regressions in flattening logic.

Proposed test extension
   it('extracts catalogs nested inside the workspaces object', () => {
     const info = extractor.getWorkspaceCatalogInfo(`{
       "workspaces": {
         "packages": ["packages/*"],
         "catalog": {
           "react": "^19.0.0"
         },
         "catalogs": {
           "test": {
             "vitest": "^4.0.0"
           }
         }
       }
     }`)
 
     expect(info?.catalogs).toEqual({
       default: {
         react: '^19.0.0',
       },
       test: {
         vitest: '^4.0.0',
       },
     })
+    expect(info?.dependencies.map(({ rawName, rawSpec, categoryName }) => ({
+      rawName,
+      rawSpec,
+      categoryName,
+    }))).toEqual([
+      {
+        rawName: 'react',
+        rawSpec: '^19.0.0',
+        categoryName: '',
+      },
+      {
+        rawName: 'vitest',
+        rawSpec: '^4.0.0',
+        categoryName: 'test',
+      },
+    ])
   })

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ccbfa554-719f-48be-b1b2-85707c3dfbaf

📥 Commits

Reviewing files that changed from the base of the PR and between 3fe3c57 and cf58e9e.

📒 Files selected for processing (14)
  • README.md
  • extensions/vscode/README.md
  • packages/language-core/src/extractors/json.test.ts
  • packages/language-core/src/extractors/json.ts
  • packages/language-core/src/workspace.test.ts
  • packages/language-core/src/workspace.ts
  • packages/language-server/src/merge-resolved-dependencies.ts
  • packages/language-server/src/workspace.test.ts
  • packages/language-server/src/workspace.ts
  • playground/bun/.vscode/settings.json
  • playground/bun/package.json
  • playground/bun/packages/app/package.json
  • playground/bun/packages/utils/package.json
  • playground/playground.code-workspace

Comment thread packages/language-core/src/workspace.ts Outdated
Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
packages/language-core/src/workspace.test.ts (1)

39-39: Consider renaming this test for accuracy.

The current title says “loads”, but the assertions verify the missing-file path returning undefined. A tighter name will reduce ambiguity when failures are scanned.

✏️ Suggested rename
-  it('still loads workspace catalogs for pnpm workspaces', async () => {
+  it('returns undefined when the pnpm workspace file is missing', async () => {

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 640385d0-80de-4858-b674-28c5899ef6a9

📥 Commits

Reviewing files that changed from the base of the PR and between cf58e9e and 18703ae.

📒 Files selected for processing (3)
  • packages/language-core/src/workspace.test.ts
  • packages/language-core/src/workspace.ts
  • packages/language-server/src/workspace.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/language-server/src/workspace.ts
  • packages/language-core/src/workspace.ts

Copy link
Copy Markdown
Member

@9romise 9romise left a comment

Choose a reason for hiding this comment

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

Thank you for your awesome work!

Comment thread packages/language-core/src/workspace.ts Outdated
Comment thread packages/language-server/src/merge-resolved-dependencies.ts Outdated
Copy link
Copy Markdown
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.

🧹 Nitpick comments (3)
packages/language-server/src/workspace.ts (2)

163-178: Optional: parallelise the two loads for the Bun root manifest.

For the Bun case where uri.path === ctx.workspaceFilePath, loadPackageManifestInfo and loadWorkspaceFileInfo are independent and could run concurrently on the initial (un-cached) call:

♻️ Proposed change
-    const manifestDependencies = (await ctx.loadPackageManifestInfo(uri.path))?.dependencies
-    if (ctx.packageManager !== 'bun' || ctx.workspaceFilePath !== uri.path)
-      return manifestDependencies
-
-    const workspaceDependencies = (await ctx.loadWorkspaceFileInfo(uri.path))?.dependencies
-    return mergeResolvedDependencies(manifestDependencies, workspaceDependencies)
+    if (ctx.packageManager !== 'bun' || ctx.workspaceFilePath !== uri.path)
+      return (await ctx.loadPackageManifestInfo(uri.path))?.dependencies
+
+    const [manifestInfo, workspaceInfo] = await Promise.all([
+      ctx.loadPackageManifestInfo(uri.path),
+      ctx.loadWorkspaceFileInfo(uri.path),
+    ])
+    return mergeResolvedDependencies(manifestInfo?.dependencies, workspaceInfo?.dependencies)

40-49: The client-side handler already correctly supports the new URI format; consider removing the unused rootPath parameter from the WorkspaceAdapter interface.

The payload change from rootPath to folderUri.toString() is already handled correctly on the client side. The handler in extensions/vscode/src/request.ts (Line 18) calls Uri.parse(params.uri), which correctly expects and processes a full URI string rather than a bare path. No client-side changes are needed.

However, the WorkspaceAdapter interface in packages/language-core/src/workspace.ts (Line 32) still declares detectPackageManager: (rootPath: string) => Promise<PackageManager>, and the call site at Line 105 passes this.rootPath as an argument. The language-server implementation (Line 40 of packages/language-server/src/workspace.ts) omits this parameter entirely and never uses it. Remove the unused parameter from both the interface signature and the call site to clarify the actual contract.

packages/language-core/src/workspace.ts (1)

11-12: Finish the migration from pathe to path-browserify.

The previous review established that pathe.join normalises away the leading / of Windows URI paths (/D:/repo/...D:/repo/...), breaking equality with URI.path. Although join has been migrated, dirname on line 12 is still imported from pathe. It is used twice in findNearestPackageManifestPath (lines 178 and 189) where results are compared against this.rootPath via dir.startsWith(\${this.rootPath}/`). If pathe.dirname` applies the same normalisation, the walk will silently never match on Windows.

Consolidate both onto path-browserify to maintain consistent path semantics with URI.path throughout the file.

♻️ Proposed changes
-import path from 'path-browserify'
-import { dirname } from 'pathe'
+import path from 'path-browserify'
-    let dir = dirname(packageManifestPath)
+    let dir = path.posix.dirname(packageManifestPath)
-      const parent = dirname(dir)
+      const parent = path.posix.dirname(dir)

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6ed8f9b8-f770-4cc9-93e6-342f695427ba

📥 Commits

Reviewing files that changed from the base of the PR and between aa69f3c and a60abde.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • packages/language-core/package.json
  • packages/language-core/src/workspace.ts
  • packages/language-core/tsdown.config.ts
  • packages/language-server/src/workspace.test.ts
  • packages/language-server/src/workspace.ts
  • pnpm-workspace.yaml
✅ Files skipped from review due to trivial changes (3)
  • packages/language-core/tsdown.config.ts
  • pnpm-workspace.yaml
  • packages/language-server/src/workspace.test.ts

Copy link
Copy Markdown
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


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 38edb352-b734-449e-96e4-10104ac89e78

📥 Commits

Reviewing files that changed from the base of the PR and between a60abde and 7aaca15.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • package.json
  • packages/language-core/package.json
  • packages/language-core/src/extractors/index.ts
  • packages/language-core/src/utils/file.ts
  • packages/language-core/src/workspace.ts
  • packages/language-core/tsdown.config.ts
  • packages/language-server/src/workspace.ts
  • pnpm-workspace.yaml
✅ Files skipped from review due to trivial changes (3)
  • packages/language-core/src/extractors/index.ts
  • package.json
  • packages/language-core/tsdown.config.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • pnpm-workspace.yaml
  • packages/language-core/package.json

Comment thread packages/language-server/src/workspace.ts Outdated
Copy link
Copy Markdown
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


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 83d6ac82-ab77-4d1c-a140-32e6b1d23dde

📥 Commits

Reviewing files that changed from the base of the PR and between a60abde and ac8553d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • package.json
  • packages/language-core/package.json
  • packages/language-core/src/extractors/index.ts
  • packages/language-core/src/utils/file.ts
  • packages/language-core/src/workspace.ts
  • packages/language-core/tsdown.config.ts
  • packages/language-server/src/workspace.ts
  • pnpm-workspace.yaml
✅ Files skipped from review due to trivial changes (6)
  • package.json
  • packages/language-core/tsdown.config.ts
  • packages/language-core/src/extractors/index.ts
  • pnpm-workspace.yaml
  • packages/language-core/package.json
  • packages/language-core/src/workspace.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/language-core/src/utils/file.ts

Comment thread packages/language-server/src/workspace.ts
@9romise 9romise added this pull request to the merge queue Apr 23, 2026
Merged via the queue into npmx-dev:main with commit 8cce1e8 Apr 23, 2026
8 checks passed
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