Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "migration-workspace-members",
"private": true,
"workspaces": [
"packages/*"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<!doctype html>
<title>Workspace member a</title>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "a",
"private": true,
"type": "module",
"scripts": {
"build": "vite build"
},
"devDependencies": {
"vite": "^7.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<!doctype html>
<title>Workspace member b</title>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "b",
"private": true,
"type": "module",
"scripts": {
"build": "vite build"
},
"devDependencies": {
"vite": "^7.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[[case]]
name = "migration_workspace_members"
vp = "local"
local-registry = true
unset-env = ["VP_SKIP_INSTALL"]
steps = [
{ argv = ["vp", "migrate", "--no-interactive", "--no-hooks", "--no-agent", "--no-editor"], comment = "migrate a workspace without a lockfile or package-manager declaration", timeout = 120000 },
{ argv = ["vpt", "print-file", "pnpm-workspace.yaml"], comment = "the selected pnpm manager retains the workspace members" },
{ argv = ["vp", "run", "-r", "build"], comment = "both migrated workspace members remain runnable", snapshot = false },
{ argv = ["vpt", "stat-file", "packages/a/dist/index.html", "--assert", "file"] },
{ argv = ["vpt", "stat-file", "packages/b/dist/index.html", "--assert", "file"] },
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# migration_workspace_members

## `vp migrate --no-interactive --no-hooks --no-agent --no-editor`

migrate a workspace without a lockfile or package-manager declaration

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

● Formatting code...
● Code formatted
◇ Migrated . to Vite+ <version>
• Node <version> pnpm <version>
✓ Dependencies installed in <duration>
• 1 config update applied
```

## `vpt print-file pnpm-workspace.yaml`

the selected pnpm manager retains the workspace members

```
packages:
- packages/*
catalog:
vite: npm:@voidzero-dev/vite-plus-core@<version>
vite-plus: <version>
overrides:
vite@*: "catalog:"
peerDependencyRules:
allowAny:
- vite
allowedVersions:
vite: "*"
```

## `vp run -r build`

both migrated workspace members remain runnable


## `vpt stat-file packages/a/dist/index.html --assert file`

```
packages/a/dist/index.html: file
```

## `vpt stat-file packages/b/dist/index.html --assert file`

```
packages/b/dist/index.html: file
```
55 changes: 55 additions & 0 deletions packages/cli/src/migration/__tests__/migrator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1866,6 +1866,61 @@ function readJson(filePath: string): Record<string, unknown> {
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
}

describe('first migration preserves pnpm workspace membership', () => {
let project: string;

beforeEach(() => {
project = fs.mkdtempSync(path.join(os.tmpdir(), 'vp-workspace-members-'));
fs.writeFileSync(
path.join(project, 'package.json'),
JSON.stringify({
name: 'root',
private: true,
workspaces: ['packages/*', '!packages/fixtures'],
}),
);
});

afterEach(() => {
fs.rmSync(project, { recursive: true, force: true });
});

it.each([undefined, 'catalog:\n example: ^1.0.0\n'])(
'writes detected globs when the workspace file has no packages: %s',
(existing) => {
const workspaceFile = path.join(project, 'pnpm-workspace.yaml');
if (existing !== undefined) {
fs.writeFileSync(workspaceFile, existing);
}
const workspace = makeWorkspaceInfo(project, PackageManager.pnpm, '11.24.0');
workspace.isMonorepo = true;
workspace.workspacePatterns = ['packages/*', '!packages/fixtures'];

rewriteMonorepo(workspace, true, true);

expect(readYamlObject(workspaceFile).packages).toEqual(workspace.workspacePatterns);
if (existing !== undefined) {
expect(readYamlObject(workspaceFile).catalog).toMatchObject({ example: '^1.0.0' });
}
const migrated = fs.readFileSync(workspaceFile, 'utf8');
rewriteMonorepo(workspace, true, true);
expect(fs.readFileSync(workspaceFile, 'utf8')).toBe(migrated);
},
);

it('preserves an existing packages field', () => {
const workspaceFile = path.join(project, 'pnpm-workspace.yaml');
fs.writeFileSync(workspaceFile, 'packages:\n - apps/*\n');
const workspace = makeWorkspaceInfo(project, PackageManager.pnpm);
workspace.isMonorepo = true;
workspace.workspacePatterns = ['packages/*'];

rewriteMonorepo(workspace, true, true);

expect(readYamlObject(workspaceFile).packages).toEqual(['apps/*']);
});
});

function readYaml(filePath: string): string {
return fs.readFileSync(filePath, 'utf8');
}
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/src/migration/migrator/orchestrators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
dropDeadOxlintPluginsDependency,
dropRemovePackageOverrideKeys,
ensurePnpmWorkspaceExoticSubdepsSetting,
ensurePnpmWorkspacePackages,
findYarnWorkspaceHoisting,
hasDirectVitePlusInstallEntry,
hasOwnWebdriverioDependency,
Expand Down Expand Up @@ -438,6 +439,7 @@ export function rewriteMonorepo(
providerCatalogAdditions,
usesWebdriverio,
);
ensurePnpmWorkspacePackages(workspaceInfo.rootDir, workspaceInfo.workspacePatterns);
if (usePnpmWorkspaceSettings && isForceOverrideMode()) {
migratePnpmOverridesToWorkspaceYaml(workspaceInfo.rootDir, {
[VITE_PLUS_NAME]: VITE_PLUS_VERSION,
Expand Down
Loading