Skip to content
Draft
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "migration-bun-old-no-top-level-catalog",
"workspaces": [],
"devDependencies": {
"vite": "^7.0.0"
},
"devEngines": {
"packageManager": {
"name": "bun",
"version": "1.2.20",
"onFail": "download"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[[case]]
name = "migration_bun_old_no_top_level_catalog"
vp = "global"
comment = "Bun before 1.2.21 reads only `workspaces.catalog`, so a top-level `catalog` would fail to resolve."
steps = [
{ argv = ["vp", "migrate", "--no-interactive"], comment = "an empty-workspaces bun 1.2.20 project without Vite+ migrates", continue-on-failure = true },
{ argv = ["vpt", "print-file", "package.json"], comment = "toolchain specs stay concrete and no top-level catalog is written", continue-on-failure = true },
{ argv = ["vp", "migrate", "--no-interactive"], comment = "a second run converges to the already-migrated fast exit", continue-on-failure = true },
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# migration_bun_old_no_top_level_catalog

Bun before 1.2.21 reads only `workspaces.catalog`, so a top-level `catalog` would fail to resolve.

## `vp migrate --no-interactive`

an empty-workspaces bun 1.2.20 project without Vite+ migrates

```
VITE+ - The Unified Toolchain for the Web

◇ Migrated . to Vite+ <version>
• Node <version> bun <version>
• 2 config updates applied
```

## `vpt print-file package.json`

toolchain specs stay concrete and no top-level catalog is written

```
{
"name": "migration-bun-old-no-top-level-catalog",
"workspaces": [],
"devDependencies": {
"vite": "npm:@voidzero-dev/vite-plus-core@<version>",
"vite-plus": "<version>"
},
"devEngines": {
"packageManager": {
"name": "bun",
"version": "<version>",
"onFail": "download"
}
},
"overrides": {
"vite": "npm:@voidzero-dev/vite-plus-core@<version>"
},
"scripts": {
"prepare": "vp config"
}
}
```

## `vp migrate --no-interactive`

a second run converges to the already-migrated fast exit

```
VITE+ - The Unified Toolchain for the Web

This project is already using Vite+! Happy coding!
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "migration-upgrade-bun-empty-workspaces-catalog",
"devDependencies": {
"vite-plus": "catalog:",
"vitest": "catalog:"
},
"overrides": {
"vite": "catalog:",
"vitest": "catalog:"
},
"devEngines": {
"packageManager": {
"name": "bun",
"version": "1.4.0",
"onFail": "download"
}
},
"workspaces": {
"packages": [],
"catalog": {
"vite-plus": "^0.1.20",
"vitest": "4.1.9"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[[case]]
name = "migration_upgrade_bun_empty_workspaces_catalog"
vp = "global"
comment = "Bun resolves catalogs whenever the root package.json has a `workspaces` field, even with an empty package list (#3375)."
steps = [
{ argv = ["vp", "migrate", "--no-interactive"], comment = "a single-package bun project with an empty workspaces.packages keeps its catalog", continue-on-failure = true },
{ argv = ["vpt", "print-file", "package.json"], comment = "toolchain specs stay catalog: and the workspaces.catalog is rewritten in place", continue-on-failure = true },
{ argv = ["vp", "migrate", "--no-interactive"], comment = "a second run converges to the already-migrated fast exit", continue-on-failure = true },
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# migration_upgrade_bun_empty_workspaces_catalog

Bun resolves catalogs whenever the root package.json has a `workspaces` field, even with an empty package list (#3375).

## `vp migrate --no-interactive`

a single-package bun project with an empty workspaces.packages keeps its catalog

```
VITE+ - The Unified Toolchain for the Web

◇ Updated . to Vite+ <version>
• Node <version> bun <version>
• Dependencies:
vite-plus 0.1.20 → <version>
vite → <version>
• Package manager settings configured
```

## `vpt print-file package.json`

toolchain specs stay catalog: and the workspaces.catalog is rewritten in place

```
{
"name": "migration-upgrade-bun-empty-workspaces-catalog",
"devDependencies": {
"vite": "catalog:",
"vite-plus": "catalog:"
},
"overrides": {
"vite": "catalog:"
},
"devEngines": {
"packageManager": {
"name": "bun",
"version": "<version>",
"onFail": "download"
}
},
"workspaces": {
"packages": [],
"catalog": {
"vite-plus": "<version>",
"vite": "npm:@voidzero-dev/vite-plus-core@<version>"
}
}
}
```

## `vp migrate --no-interactive`

a second run converges to the already-migrated fast exit

```
VITE+ - The Unified Toolchain for the Web

This project is already using Vite+! Happy coding!
```
4 changes: 3 additions & 1 deletion docs/guide/migrate-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,9 @@ Migration converts the Volta `volta.node` pin to `.node-version`, because Vite+

### Bun

- Bun catalogs only resolve inside a workspace (a root `package.json` with a non-empty `workspaces`). In a bun workspace, existing top-level or workspace catalog locations and named catalog references are preserved. A standalone (single-package) bun project keeps concrete specs and gets no catalog field, because `bun install` cannot resolve `catalog:` outside a workspace.
- Bun catalogs only resolve inside a workspace, which is a root `package.json` with a `workspaces` field. An empty `workspaces` field also counts. In a bun workspace, existing top-level or workspace catalog locations and named catalog references are preserved. A standalone bun project without `workspaces` keeps concrete specs and gets no catalog field, because `bun install` cannot resolve `catalog:` outside a workspace.
- Bun before 1.2.21 reads only catalogs under `workspaces`. On those versions, migration uses catalogs only when the project already has one under `workspaces`, and keeps concrete specs otherwise.
- When an existing named catalog already owns `vite-plus`, `vite`, or `vitest`, migration adds missing toolchain entries to that catalog instead of creating a default catalog beside it.
- The core alias is mirrored as a direct `vite` dependency so Bun sees the peer provider before applying overrides.

## After the Migration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ describe('rewriteMonorepo bun catalog with file: protocol', () => {
overrides: Record<string, string>;
devDependencies: Record<string, string>;
};
expect(pkg.workspaces.catalog.vite).toBeUndefined();
expect(pkg.workspaces.catalog.vitest).toBeUndefined();
expect(pkg.workspaces.catalog?.vite).toBeUndefined();
expect(pkg.workspaces.catalog?.vitest).toBeUndefined();
expect(pkg.workspaces.catalogs.build.vite).toBe('^7.0.0');
expect(pkg.workspaces.catalogs.build.vitest).toBe('^4.0.0');
expect(pkg.workspaces.catalogs.build.tsdown).toBeUndefined();
Expand Down
Loading
Loading