vite-plus 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/oxfmt +6 -3
- package/bin/oxlint +6 -3
- package/bin/vpr +9 -0
- package/binding/index.cjs +53 -53
- package/binding/index.d.cts +86 -144
- package/dist/agent-D7O7mSeO.js +9456 -0
- package/dist/bin.js +10 -7
- package/dist/{cli-truncate-CWsmbK3p.js → cli-truncate-BVOlIIPy.js} +1 -1
- package/dist/config/bin.js +2 -2
- package/dist/{constants-CrfJQIUX.js → constants-NeTOxrzV.js} +7 -3
- package/dist/create/bin.js +22 -60
- package/dist/{define-config-2tfJoXr1.d.ts → define-config-BuMs_LKa.d.ts} +64 -9
- package/dist/{define-config-DJUehepE.js → define-config-CSgy0zML.js} +43 -18
- package/dist/{define-config-BGSjF6Xp.cjs → define-config-CrA3lZhQ.cjs} +61 -22
- package/dist/define-config.cjs +2 -1
- package/dist/define-config.d.ts +2 -2
- package/dist/define-config.js +2 -2
- package/dist/{dist-Oxo16Y0q.js → dist-CKz3vcoG.js} +4 -4
- package/dist/dist-CtM2JRbM.js +3 -0
- package/dist/editor-CPzssglc.js +584 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{json-Dn87fvjk.js → json-DiRs8ceZ.js} +13 -1
- package/dist/{log-update-lyIiuflf.js → log-update-DHZRyJ2m.js} +2 -2
- package/dist/migration/bin.d.ts +1 -10
- package/dist/migration/bin.js +531 -170
- package/dist/migration/compat/worker.d.ts +1 -0
- package/dist/migration/compat/worker.js +35 -0
- package/dist/{oxlint-plugin-config-q8a5PFch.js → oxlint-plugin-config-C2Rqc_WQ.js} +1 -1
- package/dist/oxlint-plugin.js +78 -9
- package/dist/pack-bin.js +1 -1
- package/dist/{package-BHirM1_v.js → package-CU2g7URl.js} +52 -3
- package/dist/protocol-D99W10Qi.js +4 -0
- package/dist/{report-BHSkWqRR.js → report-BS7ULx7A.js} +2 -0
- package/dist/{resolve-vite-config-CmdsfQzS.js → resolve-vite-config-r91rIaPs.js} +14 -10
- package/dist/{rolldown-runtime-DnnnRqeS.js → rolldown-runtime-C7HZzL1F.js} +1 -1
- package/dist/staged/bin.js +23 -19
- package/dist/{tsconfig-BWQPmGKz.js → tsconfig-fvpxgUq2.js} +395 -200
- package/dist/version.js +2 -5
- package/dist/versions.js +5 -5
- package/dist/{wrap-ansi-k7Dn4VtV.js → wrap-ansi-DNjkuBEp.js} +1 -1
- package/dist/wrap-ansi-DUi52C6W.js +2 -0
- package/docs/_data/team.ts +9 -0
- package/docs/config/check.md +35 -0
- package/docs/config/index.md +2 -0
- package/docs/config/run.md +61 -12
- package/docs/guide/automatic-data-tracking.md +145 -0
- package/docs/guide/cache.md +14 -35
- package/docs/guide/check.md +16 -0
- package/docs/guide/ci.md +4 -0
- package/docs/guide/docker.md +175 -0
- package/docs/guide/env.md +12 -0
- package/docs/guide/github-actions-cache.md +165 -0
- package/docs/guide/install.md +12 -2
- package/docs/guide/migrate-rules.md +347 -0
- package/docs/guide/migrate.md +14 -0
- package/docs/guide/pack.md +8 -0
- package/docs/guide/run.md +33 -3
- package/docs/guide/troubleshooting.md +1 -1
- package/docs/guide/upgrade.md +43 -21
- package/docs/package.json +1 -1
- package/package.json +20 -19
- package/dist/agent--cKmgD_n.js +0 -3341
- package/dist/compat-Cql3K40m.js +0 -14
- package/dist/dist-DRJUd9bL.js +0 -3
- package/dist/workspace-D0AVy4fu.js +0 -5830
- package/dist/wrap-ansi-CeQuiQ31.js +0 -2
package/dist/migration/bin.js
CHANGED
|
@@ -1,17 +1,400 @@
|
|
|
1
|
-
import { r as __toESM } from "../rolldown-runtime-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { r as __toESM } from "../rolldown-runtime-C7HZzL1F.js";
|
|
2
|
+
import { d as isForceOverrideMode, l as VITE_PLUS_VERSION } from "../constants-NeTOxrzV.js";
|
|
3
|
+
import { B as runCommandSilently, D as require_semver, E as PackageManager, F as spinner, N as outro, P as select, R as isCancel, _ as upgradeYarn, d as downloadPackageManager, f as promptGitHooks, g as selectPackageManager, h as runViteInstall, i as hasBaseUrlInTsconfig, j as log, k as confirm, l as cancelAndExit, m as runViteFmt, r as fixBaseUrlInTsconfig, t as confirmBaseUrlFix, u as defaultInteractive } from "../tsconfig-fvpxgUq2.js";
|
|
4
4
|
import { a as printHeader, i as muted, r as log$1, s as warnMsg, t as accent } from "../terminal-uTv0ZaMr.js";
|
|
5
|
+
import { a as writeJsonFile, i as readJsonFile } from "../json-DiRs8ceZ.js";
|
|
5
6
|
import { t as lib_default } from "../lib-L3DWSRQp.js";
|
|
6
|
-
import { a as readNearestPackageJson, i as hasVitePlusDependency } from "../package-
|
|
7
|
-
import { A as
|
|
8
|
-
import { n as addMigrationWarning, r as createMigrationReport } from "../report-
|
|
9
|
-
import { a as
|
|
7
|
+
import { a as readNearestPackageJson, i as hasVitePlusDependency } from "../package-CU2g7URl.js";
|
|
8
|
+
import { A as detectWorkspace, B as warnIncompatibleEslintIntegration, C as injectLintTypeCheckDefaults, D as ensureVitePlusBootstrap, E as detectVitePlusBootstrapPending, F as detectEslintProject, H as warnPackageLevelEslint, I as detectIncompatibleEslintIntegration, K as checkViteVersion, L as migrateEslintToOxlint, O as configureYarnNodeModulesMode, P as confirmEslintMigration, T as collectToolchainVersionChanges, V as warnLegacyEslintConfig, Y as displayRelative, _ as detectLegacyGitHooksMigrationCandidate, b as preflightGitHooksSetup, d as rewriteStandaloneProject, f as detectPendingCoreMigration, h as migrateNodeVersionManagerFile, i as selectAgentTargetPaths, k as detectYarnPnpMode, l as rewriteMonorepo, m as detectNodeVersionManagerFile, n as detectAgentConflicts, p as finalizeCoreMigrationForExistingVitePlus, q as checkVitestVersion, r as detectExistingAgentTargetPaths, s as writeAgentInstructions, w as mergeViteConfigFiles, y as installGitHooks } from "../agent-D7O7mSeO.js";
|
|
9
|
+
import { n as addMigrationWarning, r as createMigrationReport } from "../report-BS7ULx7A.js";
|
|
10
|
+
import { a as writeEditorConfigs, c as hasFrameworkShim, d as migratePrettierToOxfmt, l as confirmPrettierMigration, o as addFrameworkShim, p as warnPackageLevelPrettier, r as selectEditor, s as detectFramework, t as detectEditorConflicts, u as detectPrettierProject } from "../editor-CPzssglc.js";
|
|
10
11
|
import { t as renderCliDoc } from "../help-YP84FSEz.js";
|
|
12
|
+
import { t as ROLLDOWN_COMPAT_RESULT_PREFIX } from "../protocol-D99W10Qi.js";
|
|
11
13
|
import path from "node:path";
|
|
14
|
+
import fs, { existsSync } from "node:fs";
|
|
12
15
|
import { styleText } from "node:util";
|
|
13
|
-
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
//#region src/migration/compat/runner.ts
|
|
14
18
|
var import_semver = /* @__PURE__ */ __toESM(require_semver(), 1);
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the isolated compat worker emitted at `migration/compat/worker.js`.
|
|
21
|
+
*
|
|
22
|
+
* The worker is a sibling of this module in source (`src/migration/compat/`),
|
|
23
|
+
* so `./worker.js` is the correct relative path. The bundler, however, inlines
|
|
24
|
+
* this runner into the parent `migration/bin.js` entry, which sits one level up
|
|
25
|
+
* from the emitted `migration/compat/worker.js`; there the worker lives in the
|
|
26
|
+
* nested `./compat/` directory. A fixed literal can only satisfy one layout:
|
|
27
|
+
* `./compat/worker.js` doubles to `compat/compat/worker.js` in source, while
|
|
28
|
+
* `./worker.js` misses the bundled worker. Probe for the nested
|
|
29
|
+
* `./compat/worker.js` next to this module to pick the right prefix for
|
|
30
|
+
* whichever layout this code is running in.
|
|
31
|
+
*/
|
|
32
|
+
function resolveWorkerPath() {
|
|
33
|
+
const nestedWorker = new URL("./compat/worker.js", import.meta.url);
|
|
34
|
+
if (existsSync(nestedWorker)) return fileURLToPath(nestedWorker);
|
|
35
|
+
return fileURLToPath(new URL("./worker.js", import.meta.url));
|
|
36
|
+
}
|
|
37
|
+
const WORKER_TIMEOUT_MS = 3e4;
|
|
38
|
+
function parseRolldownCompatibilityResult(stdout) {
|
|
39
|
+
const output = stdout.toString();
|
|
40
|
+
const markerIndex = output.lastIndexOf(ROLLDOWN_COMPAT_RESULT_PREFIX);
|
|
41
|
+
if (markerIndex === -1) return;
|
|
42
|
+
const resultStart = markerIndex + ROLLDOWN_COMPAT_RESULT_PREFIX.length;
|
|
43
|
+
const resultEnd = output.indexOf("\n", resultStart);
|
|
44
|
+
const serialized = output.slice(resultStart, resultEnd === -1 ? void 0 : resultEnd).trim();
|
|
45
|
+
try {
|
|
46
|
+
const result = JSON.parse(serialized);
|
|
47
|
+
if (!Array.isArray(result.warnings) || !result.warnings.every((item) => typeof item === "string")) return;
|
|
48
|
+
return { warnings: result.warnings };
|
|
49
|
+
} catch {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Resolve a project's Vite config in a child process before checking it for
|
|
55
|
+
* Rolldown-incompatible options. Config files execute arbitrary project code;
|
|
56
|
+
* isolating them prevents process-level handlers, explicit exits, and
|
|
57
|
+
* asynchronous crashes from terminating the migration itself.
|
|
58
|
+
*/
|
|
59
|
+
async function checkRolldownCompatibility(rootDir, report) {
|
|
60
|
+
try {
|
|
61
|
+
const workerPath = resolveWorkerPath();
|
|
62
|
+
const result = await runCommandSilently({
|
|
63
|
+
command: process.execPath,
|
|
64
|
+
args: [workerPath, rootDir],
|
|
65
|
+
cwd: rootDir,
|
|
66
|
+
envs: process.env,
|
|
67
|
+
timeoutMs: WORKER_TIMEOUT_MS
|
|
68
|
+
});
|
|
69
|
+
if (result.exitCode !== 0) return;
|
|
70
|
+
const compatibilityResult = parseRolldownCompatibilityResult(result.stdout);
|
|
71
|
+
for (const warning of compatibilityResult?.warnings ?? []) addMigrationWarning(report, warning);
|
|
72
|
+
} catch {}
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/migration/format.ts
|
|
76
|
+
const FORMAT_FAILURE_MESSAGE = "Automatic formatting failed. Run `vp fmt` manually after migration.";
|
|
77
|
+
const MAX_FORMAT_ARG_BYTES = process.platform === "win32" ? 24e3 : 1e5;
|
|
78
|
+
function chunkPathsByArgLength(paths) {
|
|
79
|
+
const chunks = [];
|
|
80
|
+
let current = [];
|
|
81
|
+
let currentBytes = 0;
|
|
82
|
+
for (const filePath of paths) {
|
|
83
|
+
const bytes = Buffer.byteLength(filePath) + 1;
|
|
84
|
+
if (current.length > 0 && currentBytes + bytes > MAX_FORMAT_ARG_BYTES) {
|
|
85
|
+
chunks.push(current);
|
|
86
|
+
current = [];
|
|
87
|
+
currentBytes = 0;
|
|
88
|
+
}
|
|
89
|
+
current.push(filePath);
|
|
90
|
+
currentBytes += bytes;
|
|
91
|
+
}
|
|
92
|
+
if (current.length > 0) chunks.push(current);
|
|
93
|
+
return chunks;
|
|
94
|
+
}
|
|
95
|
+
function parseNullDelimitedPaths(output) {
|
|
96
|
+
return output.toString().split("\0").filter(Boolean);
|
|
97
|
+
}
|
|
98
|
+
function isExistingFile(projectRoot, relativePath) {
|
|
99
|
+
const absolutePath = path.join(projectRoot, relativePath);
|
|
100
|
+
try {
|
|
101
|
+
return fs.statSync(absolutePath).isFile();
|
|
102
|
+
} catch {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Limit automatic formatting to files changed in the current Git worktree.
|
|
108
|
+
* This prevents migration from reformatting unrelated source trees while still
|
|
109
|
+
* covering manifests, generated config, and rewritten imports.
|
|
110
|
+
*
|
|
111
|
+
* Return `undefined` outside a Git worktree so non-Git projects retain the
|
|
112
|
+
* existing full-project formatting behavior.
|
|
113
|
+
*/
|
|
114
|
+
async function collectChangedFormatPaths(projectRoot, excludedPaths) {
|
|
115
|
+
try {
|
|
116
|
+
const git = (args) => runCommandSilently({
|
|
117
|
+
command: "git",
|
|
118
|
+
args,
|
|
119
|
+
cwd: projectRoot,
|
|
120
|
+
envs: process.env
|
|
121
|
+
});
|
|
122
|
+
const worktree = await git(["rev-parse", "--is-inside-work-tree"]);
|
|
123
|
+
if (worktree.exitCode !== 0) return worktree.stderr.toString().includes("not a git repository") ? void 0 : [];
|
|
124
|
+
if (worktree.stdout.toString().trim() !== "true") return;
|
|
125
|
+
const [unstaged, staged, untracked] = await Promise.all([
|
|
126
|
+
git([
|
|
127
|
+
"diff",
|
|
128
|
+
"--name-only",
|
|
129
|
+
"--relative",
|
|
130
|
+
"-z",
|
|
131
|
+
"--diff-filter=ACMRTUXB",
|
|
132
|
+
"--",
|
|
133
|
+
"."
|
|
134
|
+
]),
|
|
135
|
+
git([
|
|
136
|
+
"diff",
|
|
137
|
+
"--cached",
|
|
138
|
+
"--name-only",
|
|
139
|
+
"--relative",
|
|
140
|
+
"-z",
|
|
141
|
+
"--diff-filter=ACMRTUXB",
|
|
142
|
+
"--",
|
|
143
|
+
"."
|
|
144
|
+
]),
|
|
145
|
+
git([
|
|
146
|
+
"ls-files",
|
|
147
|
+
"--others",
|
|
148
|
+
"--exclude-standard",
|
|
149
|
+
"-z",
|
|
150
|
+
"--",
|
|
151
|
+
"."
|
|
152
|
+
])
|
|
153
|
+
]);
|
|
154
|
+
if (unstaged.exitCode !== 0 || staged.exitCode !== 0 || untracked.exitCode !== 0) return [];
|
|
155
|
+
return [.../* @__PURE__ */ new Set([
|
|
156
|
+
...parseNullDelimitedPaths(unstaged.stdout),
|
|
157
|
+
...parseNullDelimitedPaths(staged.stdout),
|
|
158
|
+
...parseNullDelimitedPaths(untracked.stdout)
|
|
159
|
+
])].filter((file) => !excludedPaths?.has(file) && isExistingFile(projectRoot, file)).toSorted();
|
|
160
|
+
} catch {
|
|
161
|
+
return [];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Do not apply Oxfmt to a project that still uses Prettier. Their formatting
|
|
166
|
+
* rules can conflict, especially when Prettier is enforced through ESLint.
|
|
167
|
+
*/
|
|
168
|
+
function canFormatWithOxfmt(hasPrettierDependency, prettierMigrated) {
|
|
169
|
+
return !hasPrettierDependency || prettierMigrated;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Format a successfully migrated project without turning a formatter problem
|
|
173
|
+
* into an unhandled migration failure. The formatter already prints its
|
|
174
|
+
* stdout/stderr when it exits nonzero; the report keeps the manual follow-up
|
|
175
|
+
* visible in the final migration summary.
|
|
176
|
+
*/
|
|
177
|
+
async function formatMigratedProject(projectRoot, interactive, report, options = {}) {
|
|
178
|
+
const { format = runViteFmt, collectPaths = collectChangedFormatPaths, excludedPaths } = options;
|
|
179
|
+
try {
|
|
180
|
+
const paths = await collectPaths(projectRoot, excludedPaths);
|
|
181
|
+
if (paths?.length === 0) return true;
|
|
182
|
+
const cliEntry = process.argv[1] ? path.resolve(process.cwd(), process.argv[1]) : void 0;
|
|
183
|
+
const formatOptions = {
|
|
184
|
+
silent: false,
|
|
185
|
+
...cliEntry ? {
|
|
186
|
+
command: process.execPath,
|
|
187
|
+
commandArgs: [...process.execArgv, cliEntry]
|
|
188
|
+
} : {}
|
|
189
|
+
};
|
|
190
|
+
const batches = paths === void 0 ? [void 0] : chunkPathsByArgLength(paths);
|
|
191
|
+
let allFormatted = true;
|
|
192
|
+
for (const batch of batches) if ((await format(projectRoot, interactive, batch, formatOptions)).status !== "formatted") {
|
|
193
|
+
allFormatted = false;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
if (allFormatted) return true;
|
|
197
|
+
} catch {}
|
|
198
|
+
addMigrationWarning(report, FORMAT_FAILURE_MESSAGE);
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region src/migration/npm-reinstall.ts
|
|
203
|
+
const VITE_PLUS_CORE_PACKAGE = "@voidzero-dev/vite-plus-core";
|
|
204
|
+
function isViteInstallPath(packagePath) {
|
|
205
|
+
return packagePath === "node_modules/vite" || packagePath.endsWith("/node_modules/vite");
|
|
206
|
+
}
|
|
207
|
+
function isVitePlusCorePackage(pkg) {
|
|
208
|
+
return pkg?.name === VITE_PLUS_CORE_PACKAGE || pkg?.resolved?.includes("/@voidzero-dev/vite-plus-core/") === true;
|
|
209
|
+
}
|
|
210
|
+
const STALE_VITE_BACKUP_NAME = ".vite-plus-migrate-stale-vite";
|
|
211
|
+
function removeStaleInstalledVite(packagePath, moved) {
|
|
212
|
+
const packageJsonPath = path.join(packagePath, "package.json");
|
|
213
|
+
if (!fs.existsSync(packageJsonPath)) return false;
|
|
214
|
+
try {
|
|
215
|
+
if (readJsonFile(packageJsonPath).name === VITE_PLUS_CORE_PACKAGE) return false;
|
|
216
|
+
} catch {}
|
|
217
|
+
const backupPath = path.join(path.dirname(packagePath), STALE_VITE_BACKUP_NAME);
|
|
218
|
+
try {
|
|
219
|
+
fs.rmSync(backupPath, {
|
|
220
|
+
recursive: true,
|
|
221
|
+
force: true
|
|
222
|
+
});
|
|
223
|
+
fs.renameSync(packagePath, backupPath);
|
|
224
|
+
moved.push({
|
|
225
|
+
originalPath: packagePath,
|
|
226
|
+
backupPath
|
|
227
|
+
});
|
|
228
|
+
} catch {
|
|
229
|
+
fs.rmSync(packagePath, {
|
|
230
|
+
recursive: true,
|
|
231
|
+
force: true
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* npm does not replace an already-installed package when its dependency changes
|
|
238
|
+
* from `vite` to the `@voidzero-dev/vite-plus-core` npm alias. Even `npm
|
|
239
|
+
* install --force` can exit successfully while retaining the real Vite package
|
|
240
|
+
* and its stale package-lock entry. Move those stale Vite installs aside (and
|
|
241
|
+
* drop their lock entries) before the migration's final install so npm resolves
|
|
242
|
+
* the managed alias afresh; the caller commits or restores them depending on
|
|
243
|
+
* whether the install succeeded, so a failed install does not strand the
|
|
244
|
+
* project without any vite package.
|
|
245
|
+
*/
|
|
246
|
+
function prepareNpmViteAliasReinstall(rootDir, projectPaths = [rootDir]) {
|
|
247
|
+
const packageLockPath = path.join(rootDir, "package-lock.json");
|
|
248
|
+
const moved = [];
|
|
249
|
+
let changed = false;
|
|
250
|
+
if (fs.existsSync(packageLockPath)) try {
|
|
251
|
+
const packageLock = readJsonFile(packageLockPath);
|
|
252
|
+
let lockChanged = false;
|
|
253
|
+
for (const [packagePath, pkg] of Object.entries(packageLock.packages ?? {})) {
|
|
254
|
+
if (!isViteInstallPath(packagePath)) continue;
|
|
255
|
+
const installPath = path.resolve(rootDir, packagePath);
|
|
256
|
+
const relativeInstallPath = path.relative(rootDir, installPath);
|
|
257
|
+
if (relativeInstallPath.startsWith("..") || path.isAbsolute(relativeInstallPath)) continue;
|
|
258
|
+
if (!isVitePlusCorePackage(pkg)) {
|
|
259
|
+
delete packageLock.packages?.[packagePath];
|
|
260
|
+
lockChanged = true;
|
|
261
|
+
removeStaleInstalledVite(installPath, moved);
|
|
262
|
+
} else changed = removeStaleInstalledVite(installPath, moved) || changed;
|
|
263
|
+
}
|
|
264
|
+
if (lockChanged) {
|
|
265
|
+
writeJsonFile(packageLockPath, packageLock);
|
|
266
|
+
changed = true;
|
|
267
|
+
}
|
|
268
|
+
} catch {}
|
|
269
|
+
for (const projectPath of projectPaths) changed = removeStaleInstalledVite(path.join(projectPath, "node_modules", "vite"), moved) || changed;
|
|
270
|
+
return {
|
|
271
|
+
changed,
|
|
272
|
+
commit: () => {
|
|
273
|
+
for (const { backupPath } of moved) try {
|
|
274
|
+
fs.rmSync(backupPath, {
|
|
275
|
+
recursive: true,
|
|
276
|
+
force: true
|
|
277
|
+
});
|
|
278
|
+
} catch {}
|
|
279
|
+
},
|
|
280
|
+
restore: () => {
|
|
281
|
+
for (const { originalPath, backupPath } of moved) try {
|
|
282
|
+
fs.rmSync(originalPath, {
|
|
283
|
+
recursive: true,
|
|
284
|
+
force: true
|
|
285
|
+
});
|
|
286
|
+
fs.renameSync(backupPath, originalPath);
|
|
287
|
+
} catch {}
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
//#endregion
|
|
292
|
+
//#region src/migration/setup-plan.ts
|
|
293
|
+
async function collectGitHooksDecision(rootDir, packageManager, options) {
|
|
294
|
+
let shouldSetupHooks = await promptGitHooks(options);
|
|
295
|
+
if (shouldSetupHooks) {
|
|
296
|
+
const reason = preflightGitHooksSetup(rootDir, packageManager);
|
|
297
|
+
if (reason) {
|
|
298
|
+
log.warn(`⚠ ${reason}`);
|
|
299
|
+
shouldSetupHooks = false;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return shouldSetupHooks;
|
|
303
|
+
}
|
|
304
|
+
async function collectAgentInstructionPlan(rootDir, options) {
|
|
305
|
+
const existingAgentTargetPaths = options.agent !== void 0 || !options.interactive ? void 0 : detectExistingAgentTargetPaths(rootDir);
|
|
306
|
+
const selectedAgentTargetPaths = existingAgentTargetPaths !== void 0 ? existingAgentTargetPaths : await selectAgentTargetPaths({
|
|
307
|
+
interactive: options.interactive,
|
|
308
|
+
agent: options.agent,
|
|
309
|
+
onCancel: () => cancelAndExit()
|
|
310
|
+
});
|
|
311
|
+
const agentConflicts = await detectAgentConflicts({
|
|
312
|
+
projectRoot: rootDir,
|
|
313
|
+
targetPaths: selectedAgentTargetPaths
|
|
314
|
+
});
|
|
315
|
+
const agentConflictDecisions = /* @__PURE__ */ new Map();
|
|
316
|
+
for (const conflict of agentConflicts) if (options.interactive) {
|
|
317
|
+
const action = await select({
|
|
318
|
+
message: `Agent instructions already exist at ${conflict.targetPath}.\n ` + styleText("gray", "The Vite+ template includes guidance on `vp` commands, the build pipeline, and project conventions."),
|
|
319
|
+
options: [{
|
|
320
|
+
label: "Append",
|
|
321
|
+
value: "append",
|
|
322
|
+
hint: "Add template content to the end"
|
|
323
|
+
}, {
|
|
324
|
+
label: "Skip",
|
|
325
|
+
value: "skip",
|
|
326
|
+
hint: "Leave existing file unchanged"
|
|
327
|
+
}],
|
|
328
|
+
initialValue: "skip"
|
|
329
|
+
});
|
|
330
|
+
if (isCancel(action)) cancelAndExit();
|
|
331
|
+
agentConflictDecisions.set(conflict.targetPath, action);
|
|
332
|
+
} else agentConflictDecisions.set(conflict.targetPath, "skip");
|
|
333
|
+
return {
|
|
334
|
+
selectedAgentTargetPaths,
|
|
335
|
+
agentConflictDecisions
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
async function collectEditorConfigPlan(rootDir, options) {
|
|
339
|
+
const selectedEditor = await selectEditor({
|
|
340
|
+
interactive: options.interactive,
|
|
341
|
+
editor: options.editor,
|
|
342
|
+
onCancel: () => cancelAndExit()
|
|
343
|
+
});
|
|
344
|
+
const editorConflicts = detectEditorConflicts({
|
|
345
|
+
projectRoot: rootDir,
|
|
346
|
+
editorId: selectedEditor
|
|
347
|
+
});
|
|
348
|
+
const editorConflictDecisions = /* @__PURE__ */ new Map();
|
|
349
|
+
for (const conflict of editorConflicts) if (options.interactive) {
|
|
350
|
+
const action = await select({
|
|
351
|
+
message: `${conflict.displayPath} already exists.\n ` + styleText("gray", "Vite+ adds editor settings for the built-in linter and formatter. Merge adds new keys without overwriting existing ones."),
|
|
352
|
+
options: [{
|
|
353
|
+
label: "Merge",
|
|
354
|
+
value: "merge",
|
|
355
|
+
hint: "Merge new settings into existing file"
|
|
356
|
+
}, {
|
|
357
|
+
label: "Skip",
|
|
358
|
+
value: "skip",
|
|
359
|
+
hint: "Leave existing file unchanged"
|
|
360
|
+
}],
|
|
361
|
+
initialValue: "skip"
|
|
362
|
+
});
|
|
363
|
+
if (isCancel(action)) cancelAndExit();
|
|
364
|
+
editorConflictDecisions.set(conflict.fileName, action);
|
|
365
|
+
} else editorConflictDecisions.set(conflict.fileName, "merge");
|
|
366
|
+
return {
|
|
367
|
+
selectedEditor,
|
|
368
|
+
editorConflictDecisions
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
async function collectEslintMigrationDecision(rootDir, options, packages) {
|
|
372
|
+
const eslintProject = detectEslintProject(rootDir, packages);
|
|
373
|
+
const incompatibleEslintIntegration = detectIncompatibleEslintIntegration(rootDir, packages);
|
|
374
|
+
let migrateEslint = false;
|
|
375
|
+
if (incompatibleEslintIntegration) warnIncompatibleEslintIntegration(incompatibleEslintIntegration);
|
|
376
|
+
else if (eslintProject.hasDependency && !eslintProject.configFile && eslintProject.legacyConfigFile) warnLegacyEslintConfig(eslintProject.legacyConfigFile);
|
|
377
|
+
else if (eslintProject.hasDependency && eslintProject.configFile) migrateEslint = await confirmEslintMigration(options.interactive);
|
|
378
|
+
else if (eslintProject.hasDependency) warnPackageLevelEslint();
|
|
379
|
+
return {
|
|
380
|
+
migrateEslint,
|
|
381
|
+
eslintConfigFile: eslintProject.configFile
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
async function collectMigrationSetupPlan(rootDir, packageManager, options, packages, includeEslint = true) {
|
|
385
|
+
const shouldSetupHooks = await collectGitHooksDecision(rootDir, packageManager, options);
|
|
386
|
+
const agentPlan = await collectAgentInstructionPlan(rootDir, options);
|
|
387
|
+
const editorPlan = await collectEditorConfigPlan(rootDir, options);
|
|
388
|
+
const eslintPlan = includeEslint ? await collectEslintMigrationDecision(rootDir, options, packages) : { migrateEslint: false };
|
|
389
|
+
return {
|
|
390
|
+
shouldSetupHooks,
|
|
391
|
+
...agentPlan,
|
|
392
|
+
...editorPlan,
|
|
393
|
+
...eslintPlan
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
//#endregion
|
|
397
|
+
//#region src/migration/bin.ts
|
|
15
398
|
async function confirmNodeVersionFileMigration(interactive, detection) {
|
|
16
399
|
const message = {
|
|
17
400
|
"package.json": "Migrate Volta node version (package.json) to .node-version?",
|
|
@@ -22,7 +405,7 @@ async function confirmNodeVersionFileMigration(interactive, detection) {
|
|
|
22
405
|
message,
|
|
23
406
|
initialValue: true
|
|
24
407
|
});
|
|
25
|
-
if (
|
|
408
|
+
if (isCancel(confirmed)) cancelAndExit();
|
|
26
409
|
return confirmed;
|
|
27
410
|
}
|
|
28
411
|
return true;
|
|
@@ -37,11 +420,27 @@ async function confirmFrameworkShim(framework, interactive) {
|
|
|
37
420
|
message: `Add TypeScript shim for ${name} component files (*.${framework})?\n ` + styleText("gray", `Lets TypeScript recognize .${framework} files until vp check fully supports them.`),
|
|
38
421
|
initialValue: true
|
|
39
422
|
});
|
|
40
|
-
if (
|
|
423
|
+
if (isCancel(confirmed)) cancelAndExit();
|
|
41
424
|
return confirmed;
|
|
42
425
|
}
|
|
43
426
|
return true;
|
|
44
427
|
}
|
|
428
|
+
async function confirmYarnNodeModulesMode(rootDir, packageManager, packageManagerVersion, interactive) {
|
|
429
|
+
if (packageManager !== PackageManager.yarn) return false;
|
|
430
|
+
const pnp = detectYarnPnpMode(rootDir, packageManagerVersion);
|
|
431
|
+
if (!pnp) return false;
|
|
432
|
+
log.warn(`⚠ Vite+ does not currently support Yarn Plug'n'Play (PnP).`);
|
|
433
|
+
if (pnp.source === "environment") cancelAndExit("YARN_NODE_LINKER=pnp overrides project configuration. Set it to node-modules or unset it, then re-run `vp migrate`.", 1);
|
|
434
|
+
if (interactive) {
|
|
435
|
+
const confirmed = await confirm({
|
|
436
|
+
message: "Switch this project to Yarn node-modules mode and continue?",
|
|
437
|
+
initialValue: true
|
|
438
|
+
});
|
|
439
|
+
if (isCancel(confirmed)) cancelAndExit();
|
|
440
|
+
if (!confirmed) cancelAndExit("Migration cancelled. Vite+ requires Yarn node-modules mode.");
|
|
441
|
+
}
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
45
444
|
async function fixBaseUrlForWorkspace(workspaceInfo, fixBaseUrl, updateProgress, report) {
|
|
46
445
|
if (!fixBaseUrl) return [];
|
|
47
446
|
const fixedProjectPaths = [];
|
|
@@ -61,11 +460,16 @@ function getWorkspaceProjectPaths(workspaceInfo) {
|
|
|
61
460
|
return [workspaceInfo.rootDir, ...(workspaceInfo.packages ?? []).map((pkg) => path.join(workspaceInfo.rootDir, pkg.path))];
|
|
62
461
|
}
|
|
63
462
|
function hasBaseUrlInWorkspace(workspaceInfo) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
463
|
+
return getWorkspaceProjectPaths(workspaceInfo).some(hasBaseUrlInTsconfig);
|
|
464
|
+
}
|
|
465
|
+
async function checkWorkspaceRolldownCompatibility(workspaceInfo, report, updateProgress) {
|
|
466
|
+
const projectPaths = getWorkspaceProjectPaths(workspaceInfo);
|
|
467
|
+
for (const [index, projectPath] of projectPaths.entries()) {
|
|
468
|
+
const counter = projectPaths.length > 1 ? ` (${index + 1}/${projectPaths.length})` : "";
|
|
469
|
+
const label = displayRelative(projectPath, workspaceInfo.rootDir);
|
|
470
|
+
updateProgress?.(`Checking config compatibility${counter}${label ? `: ${label}` : ""}`);
|
|
471
|
+
await checkRolldownCompatibility(projectPath, report);
|
|
67
472
|
}
|
|
68
|
-
return false;
|
|
69
473
|
}
|
|
70
474
|
const helpMessage = renderCliDoc({
|
|
71
475
|
usage: "vp migrate [PATH] [OPTIONS]",
|
|
@@ -106,6 +510,10 @@ const helpMessage = renderCliDoc({
|
|
|
106
510
|
label: "--no-hooks",
|
|
107
511
|
description: "Skip pre-commit hooks setup"
|
|
108
512
|
},
|
|
513
|
+
{
|
|
514
|
+
label: "--full",
|
|
515
|
+
description: "Existing Vite+ projects: also run the full setup (hooks, editor, agent files, ESLint/Prettier migration, framework shims, tsconfig baseUrl, .node-version). Without it, `vp migrate` only upgrades the toolchain version."
|
|
516
|
+
},
|
|
109
517
|
{
|
|
110
518
|
label: "--no-interactive",
|
|
111
519
|
description: "Run in non-interactive mode (skip prompts and use defaults)"
|
|
@@ -178,7 +586,8 @@ function parseArgs() {
|
|
|
178
586
|
boolean: [
|
|
179
587
|
"help",
|
|
180
588
|
"interactive",
|
|
181
|
-
"hooks"
|
|
589
|
+
"hooks",
|
|
590
|
+
"full"
|
|
182
591
|
],
|
|
183
592
|
default: { interactive: defaultInteractive() }
|
|
184
593
|
});
|
|
@@ -193,7 +602,8 @@ function parseArgs() {
|
|
|
193
602
|
help: parsed.help,
|
|
194
603
|
agent: parsed.agent,
|
|
195
604
|
editor: parsed.editor,
|
|
196
|
-
hooks: parsed.hooks
|
|
605
|
+
hooks: parsed.hooks,
|
|
606
|
+
full: parsed.full
|
|
197
607
|
}
|
|
198
608
|
};
|
|
199
609
|
}
|
|
@@ -244,120 +654,18 @@ function hasExistingVitePlusMigrationCandidates(workspaceInfo, options) {
|
|
|
244
654
|
const prettierProject = detectPrettierProject(workspaceInfo.rootDir, workspaceInfo.packages);
|
|
245
655
|
return hasExplicitExistingVitePlusSetupRequest(options) || detectLegacyGitHooksMigrationCandidate(workspaceInfo.rootDir) || hasBaseUrlInWorkspace(workspaceInfo) || eslintProject.hasDependency || prettierProject.hasDependency || detectNodeVersionManagerFile(workspaceInfo.rootDir) !== void 0 || getFrameworkShimCandidates(workspaceInfo.rootDir, workspaceInfo.packages).length > 0;
|
|
246
656
|
}
|
|
247
|
-
|
|
248
|
-
let shouldSetupHooks = await promptGitHooks(options);
|
|
249
|
-
if (shouldSetupHooks) {
|
|
250
|
-
const reason = preflightGitHooksSetup(rootDir, packageManager);
|
|
251
|
-
if (reason) {
|
|
252
|
-
log.warn(`⚠ ${reason}`);
|
|
253
|
-
shouldSetupHooks = false;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
return shouldSetupHooks;
|
|
257
|
-
}
|
|
258
|
-
async function collectAgentInstructionPlan(rootDir, options) {
|
|
259
|
-
const existingAgentTargetPaths = options.agent !== void 0 || !options.interactive ? void 0 : detectExistingAgentTargetPaths(rootDir);
|
|
260
|
-
const selectedAgentTargetPaths = existingAgentTargetPaths !== void 0 ? existingAgentTargetPaths : await selectAgentTargetPaths({
|
|
261
|
-
interactive: options.interactive,
|
|
262
|
-
agent: options.agent,
|
|
263
|
-
onCancel: () => cancelAndExit()
|
|
264
|
-
});
|
|
265
|
-
const agentConflicts = await detectAgentConflicts({
|
|
266
|
-
projectRoot: rootDir,
|
|
267
|
-
targetPaths: selectedAgentTargetPaths
|
|
268
|
-
});
|
|
269
|
-
const agentConflictDecisions = /* @__PURE__ */ new Map();
|
|
270
|
-
for (const conflict of agentConflicts) if (options.interactive) {
|
|
271
|
-
const action = await select({
|
|
272
|
-
message: `Agent instructions already exist at ${conflict.targetPath}.\n ` + styleText("gray", "The Vite+ template includes guidance on `vp` commands, the build pipeline, and project conventions."),
|
|
273
|
-
options: [{
|
|
274
|
-
label: "Append",
|
|
275
|
-
value: "append",
|
|
276
|
-
hint: "Add template content to the end"
|
|
277
|
-
}, {
|
|
278
|
-
label: "Skip",
|
|
279
|
-
value: "skip",
|
|
280
|
-
hint: "Leave existing file unchanged"
|
|
281
|
-
}],
|
|
282
|
-
initialValue: "skip"
|
|
283
|
-
});
|
|
284
|
-
if (R(action)) cancelAndExit();
|
|
285
|
-
agentConflictDecisions.set(conflict.targetPath, action);
|
|
286
|
-
} else agentConflictDecisions.set(conflict.targetPath, "skip");
|
|
287
|
-
return {
|
|
288
|
-
selectedAgentTargetPaths,
|
|
289
|
-
agentConflictDecisions
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
async function collectEditorConfigPlan(rootDir, options) {
|
|
293
|
-
const selectedEditor = await selectEditor({
|
|
294
|
-
interactive: options.interactive,
|
|
295
|
-
editor: options.editor,
|
|
296
|
-
onCancel: () => cancelAndExit()
|
|
297
|
-
});
|
|
298
|
-
const editorConflicts = detectEditorConflicts({
|
|
299
|
-
projectRoot: rootDir,
|
|
300
|
-
editorId: selectedEditor
|
|
301
|
-
});
|
|
302
|
-
const editorConflictDecisions = /* @__PURE__ */ new Map();
|
|
303
|
-
for (const conflict of editorConflicts) if (options.interactive) {
|
|
304
|
-
const action = await select({
|
|
305
|
-
message: `${conflict.displayPath} already exists.\n ` + styleText("gray", "Vite+ adds editor settings for the built-in linter and formatter. Merge adds new keys without overwriting existing ones."),
|
|
306
|
-
options: [{
|
|
307
|
-
label: "Merge",
|
|
308
|
-
value: "merge",
|
|
309
|
-
hint: "Merge new settings into existing file"
|
|
310
|
-
}, {
|
|
311
|
-
label: "Skip",
|
|
312
|
-
value: "skip",
|
|
313
|
-
hint: "Leave existing file unchanged"
|
|
314
|
-
}],
|
|
315
|
-
initialValue: "skip"
|
|
316
|
-
});
|
|
317
|
-
if (R(action)) cancelAndExit();
|
|
318
|
-
editorConflictDecisions.set(conflict.fileName, action);
|
|
319
|
-
} else editorConflictDecisions.set(conflict.fileName, "merge");
|
|
320
|
-
return {
|
|
321
|
-
selectedEditor,
|
|
322
|
-
editorConflictDecisions
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
async function collectEslintMigrationDecision(rootDir, options, packages) {
|
|
326
|
-
const eslintProject = detectEslintProject(rootDir, packages);
|
|
327
|
-
const incompatibleEslintIntegration = detectIncompatibleEslintIntegration(rootDir, packages);
|
|
328
|
-
let migrateEslint = false;
|
|
329
|
-
if (incompatibleEslintIntegration) warnIncompatibleEslintIntegration(incompatibleEslintIntegration);
|
|
330
|
-
else if (eslintProject.hasDependency && !eslintProject.configFile && eslintProject.legacyConfigFile) warnLegacyEslintConfig(eslintProject.legacyConfigFile);
|
|
331
|
-
else if (eslintProject.hasDependency && eslintProject.configFile) migrateEslint = await confirmEslintMigration(options.interactive);
|
|
332
|
-
else if (eslintProject.hasDependency) warnPackageLevelEslint();
|
|
333
|
-
return {
|
|
334
|
-
migrateEslint,
|
|
335
|
-
eslintConfigFile: eslintProject.configFile
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
async function collectMigrationSetupPlan(rootDir, packageManager, options, packages, includeEslint = true) {
|
|
339
|
-
const shouldSetupHooks = await collectGitHooksDecision(rootDir, packageManager, options);
|
|
340
|
-
const agentPlan = await collectAgentInstructionPlan(rootDir, options);
|
|
341
|
-
const editorPlan = await collectEditorConfigPlan(rootDir, options);
|
|
342
|
-
const eslintPlan = includeEslint ? await collectEslintMigrationDecision(rootDir, options, packages) : { migrateEslint: false };
|
|
343
|
-
return {
|
|
344
|
-
shouldSetupHooks,
|
|
345
|
-
...agentPlan,
|
|
346
|
-
...editorPlan,
|
|
347
|
-
...eslintPlan
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
function getExistingVitePlusSetupOptions(options, legacyGitHooksMigrationCandidate, useFullMigrationDefaults = false) {
|
|
657
|
+
function getExistingVitePlusSetupOptions(options, useFullMigrationDefaults = false) {
|
|
351
658
|
if (useFullMigrationDefaults) return options;
|
|
352
659
|
return {
|
|
353
660
|
...options,
|
|
354
|
-
hooks: options.hooks ??
|
|
661
|
+
hooks: options.hooks ?? false,
|
|
355
662
|
agent: options.agent ?? false,
|
|
356
663
|
editor: options.editor ?? false
|
|
357
664
|
};
|
|
358
665
|
}
|
|
359
|
-
async function collectMigrationPlan(rootDir, detectedPackageManager, options, packages) {
|
|
666
|
+
async function collectMigrationPlan(rootDir, detectedPackageManager, detectedPackageManagerVersion, options, packages) {
|
|
360
667
|
const packageManager = detectedPackageManager ?? await selectPackageManager(options.interactive, true);
|
|
668
|
+
const convertYarnPnp = await confirmYarnNodeModulesMode(rootDir, packageManager, detectedPackageManager ? detectedPackageManagerVersion : "latest", options.interactive);
|
|
361
669
|
const setupPlan = await collectMigrationSetupPlan(rootDir, packageManager, options, packages);
|
|
362
670
|
const prettierProject = detectPrettierProject(rootDir, packages);
|
|
363
671
|
let migratePrettier = false;
|
|
@@ -373,8 +681,10 @@ async function collectMigrationPlan(rootDir, detectedPackageManager, options, pa
|
|
|
373
681
|
const frameworkShimFrameworks = await collectFrameworkShimFrameworks(rootDir, options, packages);
|
|
374
682
|
return {
|
|
375
683
|
packageManager,
|
|
684
|
+
convertYarnPnp,
|
|
376
685
|
...setupPlan,
|
|
377
686
|
migratePrettier,
|
|
687
|
+
hasPrettierDependency: prettierProject.hasDependency,
|
|
378
688
|
prettierConfigFile: prettierProject.configFile,
|
|
379
689
|
fixBaseUrl,
|
|
380
690
|
migrateNodeVersionFile,
|
|
@@ -409,12 +719,19 @@ function handleInstallResult(installSummary, rootDir, report, options) {
|
|
|
409
719
|
}
|
|
410
720
|
return 0;
|
|
411
721
|
}
|
|
722
|
+
const FULL_MIGRATION_HINT = `${styleText("gray", "•")} Skipped editor, hooks, and lint setup. Run \`vp migrate --full\` to apply them.`;
|
|
412
723
|
function showMigrationSummary(options) {
|
|
413
|
-
const { projectRoot, packageManager, packageManagerVersion, installDurationMs, finalInstallOk, report, updatedExistingVitePlus } = options;
|
|
724
|
+
const { projectRoot, packageManager, packageManagerVersion, installDurationMs, finalInstallOk, report, updatedExistingVitePlus, suggestFullMigration } = options;
|
|
414
725
|
const projectLabel = displayRelative(projectRoot) || ".";
|
|
415
726
|
const configUpdates = report.createdViteConfigCount + report.mergedConfigCount + report.mergedStagedConfigCount + report.inlinedLintStagedConfigCount + report.removedConfigCount + report.tsdownImportCount + report.wrappedPluginConfigCount;
|
|
416
|
-
log$1(`${styleText("magenta", "◇")} ${updatedExistingVitePlus ? "Updated" : "Migrated"} ${accent(projectLabel)}
|
|
727
|
+
log$1(`${styleText("magenta", "◇")} ${updatedExistingVitePlus ? "Updated" : "Migrated"} ${accent(projectLabel)} to Vite+ ${VITE_PLUS_VERSION}`);
|
|
417
728
|
log$1(`${styleText("gray", "•")} Node ${process.versions.node} ${packageManager} ${packageManagerVersion}`);
|
|
729
|
+
if (report.dependencyUpgrades.length > 0) {
|
|
730
|
+
const nameWidth = Math.max(...report.dependencyUpgrades.map((change) => change.name.length));
|
|
731
|
+
const fromWidth = Math.max(...report.dependencyUpgrades.map((change) => (change.from ?? "").length));
|
|
732
|
+
log$1(`${styleText("gray", "•")} Dependencies:`);
|
|
733
|
+
for (const change of report.dependencyUpgrades) log$1(` ${change.name.padEnd(nameWidth)} ${muted((change.from ?? "").padEnd(fromWidth))} → ${styleText("green", change.to)}`);
|
|
734
|
+
}
|
|
418
735
|
if (finalInstallOk && installDurationMs > 0) log$1(`${styleText("green", "✓")} Dependencies installed in ${formatDuration(installDurationMs)}`);
|
|
419
736
|
if (configUpdates > 0 || report.rewrittenImportFileCount > 0) {
|
|
420
737
|
const parts = [];
|
|
@@ -422,6 +739,7 @@ function showMigrationSummary(options) {
|
|
|
422
739
|
if (report.rewrittenImportFileCount > 0) parts.push(`${report.rewrittenImportFileCount} ${report.rewrittenImportFileCount === 1 ? "file had" : "files had"} imports rewritten`);
|
|
423
740
|
log$1(`${styleText("gray", "•")} ${parts.join(", ")}`);
|
|
424
741
|
}
|
|
742
|
+
if (report.preservedUpstreamVitestImportFileCount > 0) log$1(`${styleText("gray", "•")} Kept upstream \`vitest\` imports in ${report.preservedUpstreamVitestImportFileCount} ${report.preservedUpstreamVitestImportFileCount === 1 ? "file" : "files"} for @nuxt/test-utils compatibility`);
|
|
425
743
|
if (report.eslintMigrated) log$1(`${styleText("gray", "•")} ESLint rules migrated to Oxlint`);
|
|
426
744
|
if (report.prettierMigrated) log$1(`${styleText("gray", "•")} Prettier migrated to Oxfmt`);
|
|
427
745
|
if (report.nodeVersionFileMigrated) log$1(`${styleText("gray", "•")} Node version manager file migrated to .node-version`);
|
|
@@ -429,6 +747,7 @@ function showMigrationSummary(options) {
|
|
|
429
747
|
if (report.gitHooksConfigured) log$1(`${styleText("gray", "•")} Git hooks configured`);
|
|
430
748
|
if (report.frameworkShimAdded) log$1(`${styleText("gray", "•")} TypeScript shim added for framework component files`);
|
|
431
749
|
if (report.packageManagerBootstrapConfigured) log$1(`${styleText("gray", "•")} Package manager settings configured`);
|
|
750
|
+
if (suggestFullMigration) log$1(FULL_MIGRATION_HINT);
|
|
432
751
|
if (report.warnings.length > 0) {
|
|
433
752
|
log$1(`${styleText("yellow", "!")} Warnings:`);
|
|
434
753
|
for (const warning of report.warnings) log$1(` - ${warning}`);
|
|
@@ -438,17 +757,6 @@ function showMigrationSummary(options) {
|
|
|
438
757
|
for (const step of report.manualSteps) log$1(` - ${step}`);
|
|
439
758
|
}
|
|
440
759
|
}
|
|
441
|
-
async function checkRolldownCompatibility(rootDir, report) {
|
|
442
|
-
try {
|
|
443
|
-
const { resolveConfig } = await import("../index.js");
|
|
444
|
-
const { checkManualChunksCompat } = await import("../compat-Cql3K40m.js");
|
|
445
|
-
checkManualChunksCompat((await resolveConfig({
|
|
446
|
-
root: rootDir,
|
|
447
|
-
logLevel: "silent",
|
|
448
|
-
configLoader: "runner"
|
|
449
|
-
}, "build")).build?.rollupOptions?.output, report);
|
|
450
|
-
} catch {}
|
|
451
|
-
}
|
|
452
760
|
async function downloadSupportedPackageManager(options) {
|
|
453
761
|
const { rootDir, packageManager, packageManagerVersion, interactive, updateMigrationProgress, failMigrationProgress } = options;
|
|
454
762
|
updateMigrationProgress("Preparing migration");
|
|
@@ -467,7 +775,7 @@ async function downloadSupportedPackageManager(options) {
|
|
|
467
775
|
}
|
|
468
776
|
return downloadResult;
|
|
469
777
|
}
|
|
470
|
-
async function executeMigrationPlan(workspaceInfoOptional, plan, interactive) {
|
|
778
|
+
async function executeMigrationPlan(workspaceInfoOptional, plan, interactive, preExistingChangedPaths) {
|
|
471
779
|
const report = createMigrationReport();
|
|
472
780
|
const migrationProgress = interactive ? spinner({ indicator: "timer" }) : void 0;
|
|
473
781
|
let migrationProgressStarted = false;
|
|
@@ -505,6 +813,11 @@ async function executeMigrationPlan(workspaceInfoOptional, plan, interactive) {
|
|
|
505
813
|
packageManager: plan.packageManager,
|
|
506
814
|
downloadPackageManager: downloadResult
|
|
507
815
|
};
|
|
816
|
+
if (plan.convertYarnPnp) {
|
|
817
|
+
updateMigrationProgress("Configuring Yarn node-modules mode");
|
|
818
|
+
report.packageManagerBootstrapConfigured = configureYarnNodeModulesMode(workspaceInfo.rootDir);
|
|
819
|
+
if (report.packageManagerBootstrapConfigured) log.success("✔ Switched Yarn to node-modules mode");
|
|
820
|
+
}
|
|
508
821
|
if (plan.migrateNodeVersionFile && plan.nodeVersionDetection) {
|
|
509
822
|
updateMigrationProgress("Migrating node version file");
|
|
510
823
|
migrateNodeVersionManagerFile(workspaceInfo.rootDir, plan.nodeVersionDetection, report);
|
|
@@ -522,9 +835,7 @@ async function executeMigrationPlan(workspaceInfoOptional, plan, interactive) {
|
|
|
522
835
|
failMigrationProgress("Migration failed");
|
|
523
836
|
cancelAndExit("Vite+ cannot automatically migrate this project yet.", 1);
|
|
524
837
|
}
|
|
525
|
-
|
|
526
|
-
await checkRolldownCompatibility(workspaceInfo.rootDir, report);
|
|
527
|
-
if (workspaceInfo.packages) for (const pkg of workspaceInfo.packages) await checkRolldownCompatibility(path.join(workspaceInfo.rootDir, pkg.path), report);
|
|
838
|
+
await checkWorkspaceRolldownCompatibility(workspaceInfo, report, updateMigrationProgress);
|
|
528
839
|
await fixBaseUrlForWorkspace(workspaceInfo, plan.fixBaseUrl, updateMigrationProgress, report);
|
|
529
840
|
if (plan.migrateEslint) {
|
|
530
841
|
updateMigrationProgress("Migrating ESLint");
|
|
@@ -572,15 +883,21 @@ async function executeMigrationPlan(workspaceInfoOptional, plan, interactive) {
|
|
|
572
883
|
});
|
|
573
884
|
addFrameworkShimsForWorkspace(workspaceInfo.rootDir, plan.frameworkShimFrameworks, workspaceInfo.packages, report, updateMigrationProgress);
|
|
574
885
|
const installArgs = plan.packageManager === PackageManager.npm || plan.packageManager === PackageManager.bun ? ["--force"] : ["--no-frozen-lockfile"];
|
|
886
|
+
const npmReinstallPreparation = plan.packageManager === PackageManager.npm ? prepareNpmViteAliasReinstall(workspaceInfo.rootDir, getWorkspaceProjectPaths(workspaceInfo)) : void 0;
|
|
575
887
|
updateMigrationProgress("Installing dependencies");
|
|
576
888
|
const finalInstallSummary = await runViteInstall(workspaceInfo.rootDir, interactive, installArgs, {
|
|
577
889
|
silent: true,
|
|
578
890
|
packageManager: workspaceInfo.packageManager,
|
|
579
891
|
packageManagerVersion: workspaceInfo.downloadPackageManager.version
|
|
580
892
|
});
|
|
893
|
+
if (finalInstallSummary.status === "failed") npmReinstallPreparation?.restore();
|
|
894
|
+
else npmReinstallPreparation?.commit();
|
|
581
895
|
clearMigrationProgress();
|
|
896
|
+
const initialInstallDurationMs = handleInstallResult(initialInstallSummary, workspaceInfo.rootDir, report, { propagateExitCode: false });
|
|
897
|
+
const finalInstallDurationMs = handleInstallResult(finalInstallSummary, workspaceInfo.rootDir, report);
|
|
898
|
+
if (finalInstallSummary.status === "installed" && canFormatWithOxfmt(plan.hasPrettierDependency, plan.migratePrettier)) await formatMigratedProject(workspaceInfo.rootDir, interactive, report, { excludedPaths: preExistingChangedPaths });
|
|
582
899
|
return {
|
|
583
|
-
installDurationMs:
|
|
900
|
+
installDurationMs: initialInstallDurationMs + finalInstallDurationMs,
|
|
584
901
|
finalInstallOk: finalInstallSummary.status === "installed",
|
|
585
902
|
packageManagerVersion: downloadResult.version,
|
|
586
903
|
report
|
|
@@ -595,11 +912,15 @@ async function main() {
|
|
|
595
912
|
}
|
|
596
913
|
printHeader();
|
|
597
914
|
const workspaceInfoOptional = await detectWorkspace(projectPath);
|
|
915
|
+
const initialChangedPaths = await collectChangedFormatPaths(workspaceInfoOptional.rootDir);
|
|
916
|
+
const preExistingChangedPaths = initialChangedPaths ? new Set(initialChangedPaths) : void 0;
|
|
598
917
|
const resolvedPackageManager = workspaceInfoOptional.packageManager ?? "unknown";
|
|
599
918
|
if (hasVitePlusDependency(readNearestPackageJson(workspaceInfoOptional.rootDir)) && !isForceOverrideMode()) {
|
|
919
|
+
let convertYarnPnp = await confirmYarnNodeModulesMode(workspaceInfoOptional.rootDir, workspaceInfoOptional.packageManager, workspaceInfoOptional.packageManagerVersion, options.interactive);
|
|
600
920
|
let didMigrate = false;
|
|
601
921
|
let installDurationMs = 0;
|
|
602
922
|
let finalInstallOk = true;
|
|
923
|
+
let canFormatMigratedProject = !process.env.VP_SKIP_INSTALL;
|
|
603
924
|
const report = createMigrationReport();
|
|
604
925
|
const migrationProgress = options.interactive ? spinner({ indicator: "timer" }) : void 0;
|
|
605
926
|
let migrationProgressStarted = false;
|
|
@@ -625,8 +946,7 @@ async function main() {
|
|
|
625
946
|
}
|
|
626
947
|
};
|
|
627
948
|
const pendingCoreMigration = detectPendingCoreMigration(workspaceInfoOptional);
|
|
628
|
-
const
|
|
629
|
-
const vitePlusBootstrapPending = detectVitePlusBootstrapPending(workspaceInfoOptional.rootDir, workspaceInfoOptional.packageManager);
|
|
949
|
+
const vitePlusBootstrapPending = detectVitePlusBootstrapPending(workspaceInfoOptional.rootDir, workspaceInfoOptional.packageManager, workspaceInfoOptional.packages, workspaceInfoOptional.packageManagerVersion);
|
|
630
950
|
let packageManager = vitePlusBootstrapPending ? workspaceInfoOptional.packageManager ?? await selectPackageManager(options.interactive, true) : workspaceInfoOptional.packageManager;
|
|
631
951
|
let downloadedPackageManager;
|
|
632
952
|
let packageManagerVersion = workspaceInfoOptional.packageManagerVersion;
|
|
@@ -648,16 +968,23 @@ async function main() {
|
|
|
648
968
|
return downloadExistingPackageManager();
|
|
649
969
|
};
|
|
650
970
|
if (vitePlusBootstrapPending) await ensureExistingPackageManager();
|
|
971
|
+
clearMigrationProgress();
|
|
972
|
+
if (!convertYarnPnp && workspaceInfoOptional.packageManager === void 0 && packageManager === PackageManager.yarn) convertYarnPnp = await confirmYarnNodeModulesMode(workspaceInfoOptional.rootDir, packageManager, packageManagerVersion, options.interactive);
|
|
973
|
+
report.dependencyUpgrades = await collectToolchainVersionChanges(workspaceInfoOptional.rootDir);
|
|
974
|
+
updateMigrationProgress("Rewriting toolchain imports across the workspace");
|
|
651
975
|
const coreMigrationResult = finalizeCoreMigrationForExistingVitePlus(workspaceInfoOptional, true, report, pendingCoreMigration);
|
|
652
976
|
if (coreMigrationResult.scripts || coreMigrationResult.tsconfigTypes || coreMigrationResult.imports) didMigrate = true;
|
|
653
|
-
|
|
977
|
+
clearMigrationProgress();
|
|
978
|
+
const fullSetup = options.full === true;
|
|
979
|
+
const skippedSetupCandidates = !fullSetup && !hasExplicitExistingVitePlusSetupRequest(options) && hasExistingVitePlusMigrationCandidates(workspaceInfoOptional, options);
|
|
980
|
+
if (!didMigrate && !convertYarnPnp && report.warnings.length === 0 && !vitePlusBootstrapPending && !(fullSetup ? hasExistingVitePlusMigrationCandidates(workspaceInfoOptional, options) : hasExplicitExistingVitePlusSetupRequest(options))) {
|
|
981
|
+
if (skippedSetupCandidates) log$1(FULL_MIGRATION_HINT);
|
|
654
982
|
outro(`This project is already using Vite+! ${accent("Happy coding!")}`);
|
|
655
983
|
return;
|
|
656
984
|
}
|
|
657
|
-
const
|
|
658
|
-
const
|
|
659
|
-
const
|
|
660
|
-
const frameworkShimFrameworks = await collectFrameworkShimFrameworks(workspaceInfoOptional.rootDir, options, workspaceInfoOptional.packages);
|
|
985
|
+
const setupOptions = getExistingVitePlusSetupOptions(options, fullSetup);
|
|
986
|
+
const plan = await collectMigrationSetupPlan(workspaceInfoOptional.rootDir, packageManager, setupOptions, workspaceInfoOptional.packages, fullSetup);
|
|
987
|
+
const frameworkShimFrameworks = fullSetup ? await collectFrameworkShimFrameworks(workspaceInfoOptional.rootDir, options, workspaceInfoOptional.packages) : void 0;
|
|
661
988
|
let needsInstall = false;
|
|
662
989
|
if (vitePlusBootstrapPending) {
|
|
663
990
|
const downloadResult = await ensureExistingPackageManager();
|
|
@@ -672,7 +999,12 @@ async function main() {
|
|
|
672
999
|
needsInstall = bootstrapResult.changed || needsInstall;
|
|
673
1000
|
}
|
|
674
1001
|
}
|
|
675
|
-
|
|
1002
|
+
let fixBaseUrl = false;
|
|
1003
|
+
if (fullSetup && hasBaseUrlInWorkspace(workspaceInfoOptional)) {
|
|
1004
|
+
if (options.interactive) clearMigrationProgress();
|
|
1005
|
+
fixBaseUrl = await confirmBaseUrlFix(options.interactive);
|
|
1006
|
+
}
|
|
1007
|
+
const fixedBaseUrlProjectPaths = await fixBaseUrlForWorkspace(workspaceInfoOptional, fixBaseUrl, updateMigrationProgress, report);
|
|
676
1008
|
if (fixedBaseUrlProjectPaths.length > 0) {
|
|
677
1009
|
updateMigrationProgress("Updating lint defaults");
|
|
678
1010
|
for (const projectPath of fixedBaseUrlProjectPaths) injectLintTypeCheckDefaults(projectPath, true, report);
|
|
@@ -694,23 +1026,38 @@ async function main() {
|
|
|
694
1026
|
}
|
|
695
1027
|
const prettierProject = detectPrettierProject(workspaceInfoOptional.rootDir, workspaceInfoOptional.packages);
|
|
696
1028
|
let prettierMigrated = false;
|
|
697
|
-
if (
|
|
698
|
-
if (
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
1029
|
+
if (fullSetup) {
|
|
1030
|
+
if (prettierProject.hasDependency && prettierProject.configFile) {
|
|
1031
|
+
if (options.interactive) clearMigrationProgress();
|
|
1032
|
+
if (await confirmPrettierMigration(options.interactive)) {
|
|
1033
|
+
await ensureExistingPackageManager();
|
|
1034
|
+
updateMigrationProgress("Migrating Prettier");
|
|
1035
|
+
if (!await migratePrettierToOxfmt(workspaceInfoOptional.rootDir, options.interactive, prettierProject.configFile, workspaceInfoOptional.packages, {
|
|
1036
|
+
silent: true,
|
|
1037
|
+
report
|
|
1038
|
+
})) {
|
|
1039
|
+
clearMigrationProgress();
|
|
1040
|
+
cancelAndExit("Prettier migration failed. Fix the issue and re-run `vp migrate`.", 1);
|
|
1041
|
+
}
|
|
1042
|
+
prettierMigrated = true;
|
|
707
1043
|
}
|
|
708
|
-
|
|
1044
|
+
} else if (prettierProject.hasDependency) warnPackageLevelPrettier();
|
|
1045
|
+
}
|
|
1046
|
+
if (fullSetup) {
|
|
1047
|
+
const nodeVersionDetection = detectNodeVersionManagerFile(workspaceInfoOptional.rootDir);
|
|
1048
|
+
if (nodeVersionDetection) {
|
|
1049
|
+
if (options.interactive) clearMigrationProgress();
|
|
1050
|
+
if (await confirmNodeVersionFileMigration(options.interactive, nodeVersionDetection) && migrateNodeVersionManagerFile(workspaceInfoOptional.rootDir, nodeVersionDetection, report)) didMigrate = true;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
if (convertYarnPnp) {
|
|
1054
|
+
updateMigrationProgress("Configuring Yarn node-modules mode");
|
|
1055
|
+
if (configureYarnNodeModulesMode(workspaceInfoOptional.rootDir)) {
|
|
1056
|
+
log.success("✔ Switched Yarn to node-modules mode");
|
|
1057
|
+
report.packageManagerBootstrapConfigured = true;
|
|
1058
|
+
didMigrate = true;
|
|
1059
|
+
needsInstall = true;
|
|
709
1060
|
}
|
|
710
|
-
} else if (prettierProject.hasDependency) warnPackageLevelPrettier();
|
|
711
|
-
const nodeVersionDetection = detectNodeVersionManagerFile(workspaceInfoOptional.rootDir);
|
|
712
|
-
if (nodeVersionDetection) {
|
|
713
|
-
if (await confirmNodeVersionFileMigration(options.interactive, nodeVersionDetection) && migrateNodeVersionManagerFile(workspaceInfoOptional.rootDir, nodeVersionDetection, report)) didMigrate = true;
|
|
714
1061
|
}
|
|
715
1062
|
if (addFrameworkShimsForWorkspace(workspaceInfoOptional.rootDir, frameworkShimFrameworks, workspaceInfoOptional.packages, report, updateMigrationProgress)) didMigrate = true;
|
|
716
1063
|
if (eslintMigrated || prettierMigrated) {
|
|
@@ -733,12 +1080,18 @@ async function main() {
|
|
|
733
1080
|
const resolved = await ensureExistingPackageManager();
|
|
734
1081
|
updateMigrationProgress("Installing dependencies");
|
|
735
1082
|
const resolvedVersion = resolved?.version ?? packageManagerVersion;
|
|
1083
|
+
const npmReinstallPreparation = packageManager === PackageManager.npm ? prepareNpmViteAliasReinstall(workspaceInfoOptional.rootDir, getWorkspaceProjectPaths(workspaceInfoOptional)) : void 0;
|
|
736
1084
|
const installSummary = await runViteInstall(workspaceInfoOptional.rootDir, options.interactive, packageManager === PackageManager.npm || packageManager === PackageManager.bun ? ["--force"] : ["--no-frozen-lockfile"], {
|
|
737
1085
|
silent: true,
|
|
738
1086
|
packageManager,
|
|
739
1087
|
packageManagerVersion: resolvedVersion
|
|
740
1088
|
});
|
|
741
|
-
if (installSummary.status === "failed")
|
|
1089
|
+
if (installSummary.status === "failed") {
|
|
1090
|
+
clearMigrationProgress();
|
|
1091
|
+
npmReinstallPreparation?.restore();
|
|
1092
|
+
} else npmReinstallPreparation?.commit();
|
|
1093
|
+
finalInstallOk = installSummary.status !== "failed";
|
|
1094
|
+
canFormatMigratedProject = finalInstallOk && canFormatMigratedProject;
|
|
742
1095
|
installDurationMs += handleInstallResult(installSummary, workspaceInfoOptional.rootDir, report);
|
|
743
1096
|
}
|
|
744
1097
|
if (plan.selectedAgentTargetPaths && plan.selectedAgentTargetPaths.length > 0) {
|
|
@@ -763,8 +1116,11 @@ async function main() {
|
|
|
763
1116
|
});
|
|
764
1117
|
didMigrate = true;
|
|
765
1118
|
}
|
|
766
|
-
await
|
|
767
|
-
if (
|
|
1119
|
+
await checkWorkspaceRolldownCompatibility(workspaceInfoOptional, report, updateMigrationProgress);
|
|
1120
|
+
if (didMigrate && finalInstallOk && canFormatMigratedProject && canFormatWithOxfmt(prettierProject.hasDependency, prettierMigrated)) {
|
|
1121
|
+
clearMigrationProgress();
|
|
1122
|
+
await formatMigratedProject(workspaceInfoOptional.rootDir, options.interactive, report, { excludedPaths: preExistingChangedPaths });
|
|
1123
|
+
}
|
|
768
1124
|
if (didMigrate || report.warnings.length > 0) {
|
|
769
1125
|
clearMigrationProgress();
|
|
770
1126
|
showMigrationSummary({
|
|
@@ -774,13 +1130,18 @@ async function main() {
|
|
|
774
1130
|
installDurationMs,
|
|
775
1131
|
finalInstallOk,
|
|
776
1132
|
report,
|
|
777
|
-
updatedExistingVitePlus:
|
|
1133
|
+
updatedExistingVitePlus: true,
|
|
1134
|
+
suggestFullMigration: skippedSetupCandidates
|
|
778
1135
|
});
|
|
779
|
-
} else
|
|
1136
|
+
} else {
|
|
1137
|
+
clearMigrationProgress();
|
|
1138
|
+
if (skippedSetupCandidates) log$1(FULL_MIGRATION_HINT);
|
|
1139
|
+
outro(`This project is already using Vite+! ${accent("Happy coding!")}`);
|
|
1140
|
+
}
|
|
780
1141
|
return;
|
|
781
1142
|
}
|
|
782
|
-
const plan = await collectMigrationPlan(workspaceInfoOptional.rootDir, workspaceInfoOptional.packageManager, options, workspaceInfoOptional.packages);
|
|
783
|
-
const result = await executeMigrationPlan(workspaceInfoOptional, plan, options.interactive);
|
|
1143
|
+
const plan = await collectMigrationPlan(workspaceInfoOptional.rootDir, workspaceInfoOptional.packageManager, workspaceInfoOptional.packageManagerVersion, options, workspaceInfoOptional.packages);
|
|
1144
|
+
const result = await executeMigrationPlan(workspaceInfoOptional, plan, options.interactive, preExistingChangedPaths);
|
|
784
1145
|
showMigrationSummary({
|
|
785
1146
|
projectRoot: workspaceInfoOptional.rootDir,
|
|
786
1147
|
packageManager: plan.packageManager,
|