vite-plus 0.2.9 → 0.3.0

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.
Files changed (58) hide show
  1. package/README.md +4 -3
  2. package/binding/index.cjs +57 -54
  3. package/binding/index.d.cts +93 -0
  4. package/dist/{agent-DQU8uS6P.js → agent-Wqx0MPk0.js} +1 -1
  5. package/dist/bin.js +16 -6
  6. package/dist/command-CLJK5jGW.js +2 -0
  7. package/dist/command-CguLh2KL.js +471 -0
  8. package/dist/config/bin.js +7 -5
  9. package/dist/{constants-CG513DRa.js → constants-Bn-U8o4v.js} +5 -3
  10. package/dist/create/bin.js +28 -52
  11. package/dist/{define-config-CV4bQG_8.js → define-config-GXUdVT-0.js} +2 -2
  12. package/dist/{define-config-DyNLA_f0.cjs → define-config-WiVlryJ2.cjs} +2 -2
  13. package/dist/define-config.cjs +1 -1
  14. package/dist/define-config.js +1 -1
  15. package/dist/{editor-g4PosU99.js → editor-CC4DqODz.js} +562 -59
  16. package/dist/{terminal-Bz-ps6rJ.js → help-BmKpeOP9.js} +1 -38
  17. package/dist/hooks/bin.js +3 -2
  18. package/dist/{hooks-pNCBWtFT.js → hooks-DFqViZqZ.js} +5 -2
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/migration/bin.js +60 -11
  22. package/dist/migration/compat/worker.js +1 -1
  23. package/dist/{oxlint-plugin-config-BEZ9IUf7.js → oxlint-plugin-config-DX5ezKbB.js} +1 -1
  24. package/dist/oxlint-plugin.js +1 -1
  25. package/dist/pack-bin.js +5 -4
  26. package/dist/{package-B4T8RGMG.js → package-CBe9EWPY.js} +2 -2
  27. package/dist/{prompts-CHz_98bJ.js → prompts-DF3yU-eU.js} +6 -474
  28. package/dist/{report-BS7ULx7A.js → report-ZNR1Mk6h.js} +1 -0
  29. package/dist/{resolve-vite-config-Dmeyeyj-.js → resolve-vite-config-ipGb39Jo.js} +2 -2
  30. package/dist/staged/bin.js +77 -47
  31. package/dist/terminal-MKGAuy-p.js +39 -0
  32. package/dist/toolchain.js +9 -9
  33. package/dist/toolchain.json +9 -9
  34. package/dist/tsconfig-BVHG3DpR.js +2 -0
  35. package/dist/{tsconfig-7v_BHagU.js → tsconfig-LD2QhQ0O.js} +5 -4
  36. package/dist/version.js +4 -3
  37. package/dist/versions.js +5 -5
  38. package/docs/guide/env.md +20 -6
  39. package/docs/guide/install.md +2 -1
  40. package/docs/guide/installer-env-vars.md +41 -5
  41. package/docs/guide/migrate-rules.md +9 -0
  42. package/docs/guide/migrate.md +5 -5
  43. package/docs/guide/test.md +8 -0
  44. package/docs/guide/upgrade.md +48 -1
  45. package/package.json +32 -33
  46. package/docs/_data/team.ts +0 -131
  47. package/docs/package.json +0 -30
  48. package/docs/pnpm-lock.yaml +0 -4003
  49. package/docs/pnpm-workspace.yaml +0 -13
  50. package/docs/public/checkmark.svg +0 -1
  51. package/docs/public/cta-background.jpg +0 -0
  52. package/docs/public/favicon.svg +0 -1
  53. package/docs/public/icon.svg +0 -1
  54. package/docs/public/logo.svg +0 -1
  55. package/docs/public/og.jpg +0 -0
  56. package/docs/vite.config.ts +0 -20
  57. package/dist/{json-qlK6UH0r.js → json-cULBl7Pi.js} +107 -107
  58. package/dist/{log-update-CoW8Z4Dl.js → log-update-DHZRyJ2m.js} +1 -1
@@ -1,23 +1,24 @@
1
1
  import { r as __toESM } from "./rolldown-runtime-CMFfr-1z.js";
2
- import { a as VITEST_AGE_GATE_EXEMPT_PACKAGES, c as VITE_PLUS_NAME, f as isForceOverrideMode, l as VITE_PLUS_OVERRIDE_PACKAGES, n as BASEURL_TSCONFIG_WARNING, o as VITEST_VERSION, s as VITE_CONFIG_FILES, u as VITE_PLUS_VERSION } from "./constants-CG513DRa.js";
3
- import { i as ensureVitePlusImportRuleDefaults, r as createDefaultVitePlusLintConfig } from "./oxlint-plugin-config-BEZ9IUf7.js";
4
- import { A as isCancel, C as log, E as select, M as runCommandSilently, N as require_cross_spawn, _ as getSpinner, b as require_semver, d as readYamlFile, f as scalarString, g as getSilentSpinner, t as cancelAndExit, u as editYamlFile, w as multiselect, x as confirm, y as PackageManager } from "./prompts-CHz_98bJ.js";
5
- import { a as writeJsonFile, c as parse, i as readJsonFile, n as editJsonFile, o as applyEdits, r as isJsonFile, s as modify, t as detectFormattingOptions } from "./json-qlK6UH0r.js";
2
+ import { a as TSDOWN_MIGRATE_VERSION, c as VITEST_VERSION, d as VITE_PLUS_OVERRIDE_PACKAGES, f as VITE_PLUS_VERSION, l as VITE_CONFIG_FILES, m as isForceOverrideMode, n as BASEURL_TSCONFIG_WARNING, o as TSDOWN_MIGRATION_SKILL_URL, s as VITEST_AGE_GATE_EXEMPT_PACKAGES, u as VITE_PLUS_NAME } from "./constants-Bn-U8o4v.js";
3
+ import { i as ensureVitePlusImportRuleDefaults, r as createDefaultVitePlusLintConfig } from "./oxlint-plugin-config-DX5ezKbB.js";
4
+ import { A as isCancel, C as log, E as select, _ as getSpinner, b as require_semver, d as readYamlFile, f as scalarString, g as getSilentSpinner, t as cancelAndExit, u as editYamlFile, w as multiselect, x as confirm, y as PackageManager } from "./prompts-DF3yU-eU.js";
5
+ import { a as writeJsonFile, c as parse, i as readJsonFile, n as editJsonFile, o as applyEdits, r as isJsonFile, s as modify, t as detectFormattingOptions } from "./json-cULBl7Pi.js";
6
+ import { n as detectPackageMetadata, r as getScopeFromPackageName } from "./package-CBe9EWPY.js";
7
+ import { l as displayRelative, u as rulesDir } from "./agent-Wqx0MPk0.js";
8
+ import { n as addMigrationWarning, t as addManualStep } from "./report-ZNR1Mk6h.js";
9
+ import { n as runCommandSilently, r as require_cross_spawn } from "./command-CguLh2KL.js";
6
10
  import { t as require_dist } from "./dist-BDYZP12R.js";
7
- import { a as hasTypesToRewriteInTsconfig, c as rewriteTypesInTsconfig, i as hasBaseUrlInTsconfig, n as findTsconfigFiles, o as hasVitestTypesInTsconfig, s as removeDeprecatedTsconfigFalseOption } from "./tsconfig-7v_BHagU.js";
8
- import { n as detectPackageMetadata, r as getScopeFromPackageName } from "./package-B4T8RGMG.js";
9
- import { l as displayRelative, u as rulesDir } from "./agent-DQU8uS6P.js";
10
- import { n as addMigrationWarning, t as addManualStep } from "./report-BS7ULx7A.js";
11
- import { a as findUnsafeHookInstallPath, n as SUPPORTED_GIT_HOOK_NAMES } from "./hooks-pNCBWtFT.js";
11
+ import { a as hasBaseUrlInTsconfig, c as hasVitestTypesInTsconfig, l as removeDeprecatedTsconfigFalseOption, n as findTsconfigFiles, s as hasTypesToRewriteInTsconfig, u as rewriteTypesInTsconfig } from "./tsconfig-LD2QhQ0O.js";
12
+ import { a as findUnsafeHookInstallPath, n as SUPPORTED_GIT_HOOK_NAMES } from "./hooks-DFqViZqZ.js";
12
13
  import path, { posix, win32 } from "node:path";
13
14
  import { fileURLToPath } from "node:url";
14
- import { detectWorkspace, hasConfigKey, mergeJsonConfig, mergeTsdownConfig, rewriteEslint, rewriteImportsInDirectory, rewritePrettier, rewriteScripts, wrapLazyPlugins } from "../binding/index.js";
15
+ import { detectWorkspace, getVpDirs, hasConfigKey, mergeJsonConfig, mergeTsdownConfig, rewriteEslint, rewriteImportsInDirectory, rewritePrettier, rewriteScripts, wrapLazyPlugins } from "../binding/index.js";
15
16
  import { styleText } from "node:util";
16
17
  import * as actualFS from "node:fs";
17
18
  import fs from "node:fs";
18
19
  import os from "node:os";
19
- import { lstatSync as lstatSync$1, readdir, readdirSync as readdirSync$1, readlinkSync, realpathSync as realpathSync$1 } from "fs";
20
20
  import "oxlint";
21
+ import { lstatSync as lstatSync$1, readdir, readdirSync as readdirSync$1, readlinkSync, realpathSync as realpathSync$1 } from "fs";
21
22
  import fsPromises, { lstat, readdir as readdir$1, readlink, realpath } from "node:fs/promises";
22
23
  import { EventEmitter } from "node:events";
23
24
  import Stream from "node:stream";
@@ -82,6 +83,48 @@ const VITEST_BROWSER_DEP_NAMES = [
82
83
  ];
83
84
  const VITEST_IS_MANAGED_OVERRIDE = "vitest" in VITE_PLUS_OVERRIDE_PACKAGES;
84
85
  const LEGACY_WRAPPER_FALLBACK_VERSIONS = { vitest: VITEST_VERSION };
86
+ /**
87
+ * Managed pnpm override keys use an explicit `@*` range, not a bare package
88
+ * name: `vite@*`, not `vite`.
89
+ *
90
+ * pnpm applies overrides through a read-package hook. The hook replaces the
91
+ * declared spec on every manifest, importer manifests included, before
92
+ * resolution runs. A bare override key has no range, and pnpm treats a key with
93
+ * no range as a match for every declared spec. That includes `catalog:`. An
94
+ * importer that declares `vite: "catalog:"` therefore loses its link to the
95
+ * catalog during resolution, and `pnpm update` then writes the resolved core
96
+ * alias into that importer's package.json (issue #2309).
97
+ *
98
+ * The `@*` range keeps the override on the declared semver ranges that
99
+ * transitive and peer `vite` declarations use. Those declarations are the
100
+ * reason this override exists. The range leaves `catalog:` specs alone, because
101
+ * `catalog:` is not a valid semver range, so pnpm's `isIntersectingRange`
102
+ * rejects it before it compares anything. The installed result does not change:
103
+ * an importer that references the catalog already resolves to the aliased core
104
+ * through its catalog entry.
105
+ *
106
+ * Known gap on pnpm 9 to 11: a declaration that pins an EXACT prerelease, such
107
+ * as `vite: "8.0.0-beta.18"`, escapes the override. pnpm compares with
108
+ * `semver.intersects(declaredSpec, keyRange)`. That call is asymmetric for
109
+ * prereleases: it returns false for an exact prerelease against a wildcard
110
+ * range. The reversed argument order returns true. No range string avoids
111
+ * this, because node-semver only admits a prerelease when a comparator carries
112
+ * the same version tuple. A prerelease RANGE such as `^8.0.0-beta.1` still
113
+ * matches. pnpm 12 matches the exact form too. A bare key would cover this
114
+ * case, but a bare key is what clobbers `catalog:` specs. Below pnpm 12,
115
+ * prerelease coverage and `catalog:` safety cannot both hold.
116
+ *
117
+ * This applies to pnpm only. npm and bun `overrides`, and yarn `resolutions`,
118
+ * keep bare keys. Those package managers have no `catalog:` importer specs to
119
+ * lose. Bun catalogs live in package.json, and bun resolves them before it
120
+ * applies overrides.
121
+ */
122
+ function pnpmOverrideKey(dependencyName) {
123
+ return `${dependencyName}@*`;
124
+ }
125
+ function managedOverrideKey(dependencyName, keyStyle) {
126
+ return keyStyle === "pnpm-ranged" ? pnpmOverrideKey(dependencyName) : dependencyName;
127
+ }
85
128
  function warnMigration(message, report) {
86
129
  addMigrationWarning(report, message);
87
130
  if (!report) log.warn(message);
@@ -132,6 +175,16 @@ function pnpmMajor(version) {
132
175
  //#endregion
133
176
  //#region src/migration/detector.ts
134
177
  const PRETTIER_PACKAGE_JSON_CONFIG = "package.json#prettier";
178
+ const TSUP_PACKAGE_JSON_CONFIG = "package.json#tsup";
179
+ const TSUP_CONFIG_FILES = [
180
+ "tsup.config.ts",
181
+ "tsup.config.mts",
182
+ "tsup.config.cts",
183
+ "tsup.config.js",
184
+ "tsup.config.mjs",
185
+ "tsup.config.cjs",
186
+ "tsup.config.json"
187
+ ];
135
188
  const PRETTIER_CONFIG_FILES = [
136
189
  ".prettierrc",
137
190
  ".prettierrc.json",
@@ -182,6 +235,10 @@ function detectConfigs(projectPath) {
182
235
  configs.tsdownConfig = config;
183
236
  break;
184
237
  }
238
+ for (const config of TSUP_CONFIG_FILES) if (fs.existsSync(path.join(projectPath, config))) {
239
+ configs.tsupConfig = config;
240
+ break;
241
+ }
185
242
  for (const config of [".oxlintrc.json", ".oxlintrc.jsonc"]) if (fs.existsSync(path.join(projectPath, config))) {
186
243
  configs.oxlintConfig = config;
187
244
  break;
@@ -223,6 +280,7 @@ function detectConfigs(projectPath) {
223
280
  const content = fs.readFileSync(packageJsonPath, "utf8");
224
281
  const pkg = JSON.parse(content);
225
282
  if (!configs.prettierConfig && pkg.prettier) configs.prettierConfig = PRETTIER_PACKAGE_JSON_CONFIG;
283
+ if (!configs.tsupConfig && pkg.tsup) configs.tsupConfig = TSUP_PACKAGE_JSON_CONFIG;
226
284
  const voltaNode = pkg.volta?.node;
227
285
  if (typeof voltaNode === "string") configs.voltaNode = voltaNode;
228
286
  } catch {}
@@ -881,6 +939,397 @@ async function promptPrettierMigration(projectPath, interactive, packages) {
881
939
  return true;
882
940
  }
883
941
  //#endregion
942
+ //#region src/migration/migrator/tsup.ts
943
+ function showTsdownMigrationOptions(targetLabel = "the project root", automaticMigrationFailed = false) {
944
+ const lines = [
945
+ "Choose one of these manual migration methods:",
946
+ ` 1. Run \`vp dlx tsdown-migrate\` in ${targetLabel}.`,
947
+ " 2. Use the tsdown migration skill:",
948
+ ` ${TSDOWN_MIGRATION_SKILL_URL}`
949
+ ];
950
+ if (automaticMigrationFailed) {
951
+ lines.unshift("Automatic tsup migration failed.", "");
952
+ lines.push("");
953
+ }
954
+ log.info(lines.join("\n"));
955
+ }
956
+ function showTsdownMigrationSkillGuidance(instructions) {
957
+ log.info([
958
+ ...instructions,
959
+ "",
960
+ "Use the tsdown migration skill for guidance:",
961
+ ` ${TSDOWN_MIGRATION_SKILL_URL}`
962
+ ].join("\n"));
963
+ }
964
+ function detectTsupProject(projectPath, packages) {
965
+ const packageJsonPath = path.join(projectPath, "package.json");
966
+ let hasDependency = false;
967
+ if (fs.existsSync(packageJsonPath)) {
968
+ const pkg = readJsonFile(packageJsonPath);
969
+ hasDependency = !!(pkg.devDependencies?.tsup || pkg.dependencies?.tsup);
970
+ }
971
+ const configFile = detectConfigs(projectPath).tsupConfig;
972
+ let hasConfig = !!configFile;
973
+ for (const wp of packages ?? []) {
974
+ const workspacePath = path.join(projectPath, wp.path);
975
+ hasConfig ||= !!detectConfigs(workspacePath).tsupConfig;
976
+ if (!hasDependency) {
977
+ const workspacePackageJsonPath = path.join(workspacePath, "package.json");
978
+ if (fs.existsSync(workspacePackageJsonPath)) {
979
+ const workspacePackageJson = readJsonFile(workspacePackageJsonPath);
980
+ hasDependency = !!(workspacePackageJson.devDependencies?.tsup || workspacePackageJson.dependencies?.tsup);
981
+ }
982
+ }
983
+ }
984
+ return {
985
+ hasDependency,
986
+ hasConfig,
987
+ configFile
988
+ };
989
+ }
990
+ const TSDOWN_MIGRATION_FILES = [
991
+ "package.json",
992
+ ...TSUP_CONFIG_FILES,
993
+ ...TSUP_CONFIG_FILES.map((file) => file.replace("tsup", "tsdown"))
994
+ ];
995
+ function escapeRegExp(value) {
996
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
997
+ }
998
+ const STANDARD_TSUP_CONFIG_FILE_PATTERN = TSUP_CONFIG_FILES.flatMap((file) => [file, file.replace("tsup", "tsdown")]).map(escapeRegExp).join("|");
999
+ const TSDOWN_STANDARD_CONFIG_OPTION_RE = new RegExp(String.raw`(\btsdown(?:-node)?\b(?:(?!&&|\|\||[;|]).)*?)\s+(?:--config(?:=|\s+)|-c\s+)["']?(?:\.[\\/])?(?:${STANDARD_TSUP_CONFIG_FILE_PATTERN})["']?(?=\s|$|[;&|])`, "g");
1000
+ const TSUP_CONFIG_OPTION_RE = /\btsup(?:-node)?\b(?:(?!&&|\|\||[;|]).)*?\s+(?:--config(?:=|\s+)|-c\s+)(?:"([^"]+)"|'([^']+)'|([^\s;&|]+))(?=\s|$|[;&|])/g;
1001
+ function removeStandardTsdownConfigOption(script) {
1002
+ return script.replace(TSDOWN_STANDARD_CONFIG_OPTION_RE, "$1");
1003
+ }
1004
+ function resolveScriptConfigPath(packagePath, configPath) {
1005
+ return path.resolve(packagePath, configPath.replace(/[\\/]/g, path.sep));
1006
+ }
1007
+ function collectSharedTsupConfigs(projectPath, packages, tsupTargets) {
1008
+ const migratedConfigPaths = new Set(tsupTargets.flatMap((target) => TSUP_CONFIG_FILES.map((file) => path.join(target, file)).filter((file) => fs.existsSync(file))));
1009
+ const sharedConfigs = /* @__PURE__ */ new Map();
1010
+ const consumers = [{
1011
+ label: "the project root",
1012
+ packagePath: path.resolve(projectPath)
1013
+ }, ...(packages ?? []).map((workspacePackage) => ({
1014
+ label: workspacePackage.path,
1015
+ packagePath: path.resolve(projectPath, workspacePackage.path)
1016
+ }))];
1017
+ for (const { label, packagePath } of consumers) {
1018
+ const packageJsonPath = path.join(packagePath, "package.json");
1019
+ if (!fs.existsSync(packageJsonPath)) continue;
1020
+ const packageJson = readJsonFile(packageJsonPath);
1021
+ for (const [scriptName, script] of Object.entries(packageJson.scripts ?? {})) for (const match of script.matchAll(TSUP_CONFIG_OPTION_RE)) {
1022
+ const configPath = resolveScriptConfigPath(packagePath, match[1] ?? match[2] ?? match[3]);
1023
+ if (!migratedConfigPaths.has(configPath) || path.dirname(configPath) === packagePath) continue;
1024
+ const sharedConfig = sharedConfigs.get(configPath) ?? { consumers: /* @__PURE__ */ new Map() };
1025
+ const consumer = sharedConfig.consumers.get(packagePath) ?? {
1026
+ label,
1027
+ packagePath,
1028
+ scriptNames: /* @__PURE__ */ new Set()
1029
+ };
1030
+ consumer.scriptNames.add(scriptName);
1031
+ sharedConfig.consumers.set(packagePath, consumer);
1032
+ sharedConfigs.set(configPath, sharedConfig);
1033
+ }
1034
+ }
1035
+ return sharedConfigs;
1036
+ }
1037
+ function collectTsupConfigCollisions(tsupTargets) {
1038
+ const collisions = [];
1039
+ for (const target of tsupTargets) {
1040
+ const tsdownConfig = detectConfigs(target).tsdownConfig;
1041
+ if (tsdownConfig) collisions.push({ configPath: path.join(target, tsdownConfig) });
1042
+ const packageJsonPath = path.join(target, "package.json");
1043
+ if (fs.existsSync(packageJsonPath)) {
1044
+ const packageJson = readJsonFile(packageJsonPath);
1045
+ if (Object.hasOwn(packageJson, "tsdown")) collisions.push({ configPath: `${packageJsonPath}#tsdown` });
1046
+ }
1047
+ }
1048
+ return collisions;
1049
+ }
1050
+ function collectInlineTsupConfigs(tsupTargets) {
1051
+ return tsupTargets.flatMap((target) => {
1052
+ const packageJsonPath = path.join(target, "package.json");
1053
+ if (!fs.existsSync(packageJsonPath) || !Object.hasOwn(readJsonFile(packageJsonPath), "tsup")) return [];
1054
+ return [{ configPath: `${packageJsonPath}#tsup` }];
1055
+ });
1056
+ }
1057
+ function isRemovableDefaultConfigArgument(configArgument, defaultConfig) {
1058
+ return !!defaultConfig && (configArgument === defaultConfig || configArgument === `./${defaultConfig}` || configArgument === `.\\${defaultConfig}`);
1059
+ }
1060
+ function collectUnsupportedTsupConfigConsumers(tsupTargets) {
1061
+ const migratedConfigPaths = new Set(tsupTargets.flatMap((target) => TSUP_CONFIG_FILES.map((file) => path.join(target, file)).filter((file) => fs.existsSync(file))));
1062
+ const unsupported = [];
1063
+ for (const target of tsupTargets) {
1064
+ const packageJsonPath = path.join(target, "package.json");
1065
+ if (!fs.existsSync(packageJsonPath)) continue;
1066
+ const detectedConfig = detectConfigs(target).tsupConfig;
1067
+ const defaultConfigPath = detectedConfig && detectedConfig !== "package.json#tsup" ? path.join(target, detectedConfig) : void 0;
1068
+ const packageJson = readJsonFile(packageJsonPath);
1069
+ for (const [scriptName, script] of Object.entries(packageJson.scripts ?? {})) for (const match of script.matchAll(TSUP_CONFIG_OPTION_RE)) {
1070
+ const configArgument = match[1] ?? match[2] ?? match[3];
1071
+ const configPath = resolveScriptConfigPath(target, configArgument);
1072
+ const isDefaultConfig = configPath === defaultConfigPath && isRemovableDefaultConfigArgument(configArgument, detectedConfig);
1073
+ const isSharedMigratedConfig = migratedConfigPaths.has(configPath) && path.dirname(configPath) !== target;
1074
+ if (!isDefaultConfig && !isSharedMigratedConfig) unsupported.push({
1075
+ configArgument,
1076
+ packagePath: target,
1077
+ scriptName
1078
+ });
1079
+ }
1080
+ }
1081
+ return unsupported;
1082
+ }
1083
+ function restoreSharedTsupUsage(sharedConfigs, snapshots) {
1084
+ const preservedDependencyTargets = /* @__PURE__ */ new Set();
1085
+ const restoredScripts = /* @__PURE__ */ new Map();
1086
+ for (const [configPath, sharedConfig] of sharedConfigs) {
1087
+ const contents = snapshots.get(configPath);
1088
+ if (contents !== void 0) fs.writeFileSync(configPath, contents);
1089
+ preservedDependencyTargets.add(path.dirname(configPath));
1090
+ for (const consumer of sharedConfig.consumers.values()) {
1091
+ preservedDependencyTargets.add(consumer.packagePath);
1092
+ const scriptNames = restoredScripts.get(consumer.packagePath) ?? /* @__PURE__ */ new Set();
1093
+ for (const scriptName of consumer.scriptNames) scriptNames.add(scriptName);
1094
+ restoredScripts.set(consumer.packagePath, scriptNames);
1095
+ }
1096
+ }
1097
+ for (const target of preservedDependencyTargets) {
1098
+ const packageJsonPath = path.join(target, "package.json");
1099
+ const originalPackageJson = snapshots.get(packageJsonPath);
1100
+ if (!originalPackageJson || !fs.existsSync(packageJsonPath)) continue;
1101
+ const original = JSON.parse(originalPackageJson.toString());
1102
+ editJsonFile(packageJsonPath, (pkg) => {
1103
+ let changed = false;
1104
+ for (const field of ["devDependencies", "dependencies"]) {
1105
+ const spec = original[field]?.tsup;
1106
+ if (spec && pkg[field]?.tsup !== spec) {
1107
+ pkg[field] ??= {};
1108
+ pkg[field].tsup = spec;
1109
+ changed = true;
1110
+ }
1111
+ }
1112
+ for (const scriptName of restoredScripts.get(target) ?? []) {
1113
+ const script = original.scripts?.[scriptName];
1114
+ if (script !== void 0 && pkg.scripts?.[scriptName] !== script) {
1115
+ pkg.scripts ??= {};
1116
+ pkg.scripts[scriptName] = script;
1117
+ changed = true;
1118
+ }
1119
+ }
1120
+ return changed ? pkg : void 0;
1121
+ });
1122
+ }
1123
+ return preservedDependencyTargets;
1124
+ }
1125
+ function snapshotTsupMigrationTargets(targets) {
1126
+ const snapshots = /* @__PURE__ */ new Map();
1127
+ for (const target of targets) for (const file of TSDOWN_MIGRATION_FILES) {
1128
+ const filePath = path.join(target, file);
1129
+ snapshots.set(filePath, fs.existsSync(filePath) ? fs.readFileSync(filePath) : void 0);
1130
+ }
1131
+ return snapshots;
1132
+ }
1133
+ function restoreTsupMigrationTargets(snapshots) {
1134
+ const failures = [];
1135
+ for (const [filePath, contents] of snapshots) try {
1136
+ if (contents === void 0) fs.rmSync(filePath, { force: true });
1137
+ else fs.writeFileSync(filePath, contents);
1138
+ } catch {
1139
+ failures.push(displayRelative(filePath));
1140
+ }
1141
+ return failures;
1142
+ }
1143
+ function extractTsdownMigrationWarnings(output) {
1144
+ return output.toString().replaceAll("\r\n", "\n").split(/\n\s*\n/).map((block) => block.trim().match(/^WARN\s+([\s\S]+)$/)?.[1]?.trim()).filter((warning) => !!warning);
1145
+ }
1146
+ /** Run `vp dlx tsdown-migrate` in `cwd` with graceful error handling. */
1147
+ async function runTsdownMigrateStep(vpBin, cwd, packageManager) {
1148
+ try {
1149
+ const result = await runCommandSilently({
1150
+ command: vpBin,
1151
+ args: [
1152
+ "dlx",
1153
+ `tsdown-migrate@${TSDOWN_MIGRATE_VERSION}`,
1154
+ "--yes",
1155
+ "--package-manager",
1156
+ packageManager,
1157
+ "--no-install"
1158
+ ],
1159
+ cwd,
1160
+ envs: process.env
1161
+ });
1162
+ if (result.exitCode !== 0) {
1163
+ const stderr = result.stderr.toString().trim();
1164
+ if (stderr) log.warn(`⚠ ${stderr}`);
1165
+ return {
1166
+ ok: false,
1167
+ warnings: []
1168
+ };
1169
+ }
1170
+ return {
1171
+ ok: true,
1172
+ warnings: [...extractTsdownMigrationWarnings(result.stdout), ...extractTsdownMigrationWarnings(result.stderr)]
1173
+ };
1174
+ } catch {
1175
+ return {
1176
+ ok: false,
1177
+ warnings: []
1178
+ };
1179
+ }
1180
+ }
1181
+ async function migrateTsupToTsdown(projectPath, interactive, packageManager, tsupConfigFile, packages, options) {
1182
+ const vpBin = process.env.VP_CLI_BIN ?? "vp";
1183
+ const spinner = options?.silent ? getSilentSpinner() : getSpinner(interactive);
1184
+ const rootPath = path.resolve(projectPath);
1185
+ const tsupTargets = [rootPath, ...(packages ?? []).map((p) => path.resolve(rootPath, p.path))].filter((target) => target === rootPath ? !!tsupConfigFile : !!detectConfigs(target).tsupConfig);
1186
+ const configCollisions = collectTsupConfigCollisions(tsupTargets);
1187
+ if (configCollisions.length > 0) {
1188
+ log.warn(`Automatic tsup migration was skipped because these tsdown configs already exist:\n${configCollisions.map(({ configPath }) => ` ${displayRelative(configPath, projectPath)}`).join("\n")}`);
1189
+ showTsdownMigrationSkillGuidance([
1190
+ "Resolve this configuration conflict manually:",
1191
+ " 1. Merge the tsup and tsdown configurations into `pack` in `vite.config.*`.",
1192
+ " 2. Do not run `tsdown-migrate`. It can overwrite the existing tsdown configuration."
1193
+ ]);
1194
+ return false;
1195
+ }
1196
+ const inlineTsupConfigs = collectInlineTsupConfigs(tsupTargets);
1197
+ if (inlineTsupConfigs.length > 0) {
1198
+ log.warn(`Automatic tsup migration was skipped because these inline tsup configs cannot be migrated automatically:\n${inlineTsupConfigs.map(({ configPath }) => ` ${displayRelative(configPath, projectPath)}`).join("\n")}`);
1199
+ showTsdownMigrationSkillGuidance([
1200
+ "Resolve this inline configuration manually:",
1201
+ " 1. Move each `package.json#tsup` configuration into `pack` in `vite.config.*`.",
1202
+ " 2. Do not run `tsdown-migrate`. Vite+ Pack does not read `package.json#tsdown`."
1203
+ ]);
1204
+ return false;
1205
+ }
1206
+ const unsupportedConfigConsumers = collectUnsupportedTsupConfigConsumers(tsupTargets);
1207
+ if (unsupportedConfigConsumers.length > 0) {
1208
+ log.warn(`Automatic tsup migration was skipped because these scripts use configs that cannot be migrated automatically:\n${unsupportedConfigConsumers.map(({ configArgument, packagePath, scriptName }) => ` ${displayRelative(path.join(packagePath, "package.json"), projectPath)}#${scriptName} -> ${configArgument}`).join("\n")}`);
1209
+ showTsdownMigrationSkillGuidance([
1210
+ "Resolve these config paths manually:",
1211
+ " 1. Migrate each listed config into `pack` in `vite.config.*`.",
1212
+ " 2. Update each listed script.",
1213
+ " 3. Do not run `tsdown-migrate`. It cannot safely resolve these config paths."
1214
+ ]);
1215
+ return false;
1216
+ }
1217
+ const sharedConfigs = collectSharedTsupConfigs(projectPath, packages, tsupTargets);
1218
+ let preservedDependencyTargets = /* @__PURE__ */ new Set();
1219
+ if (tsupTargets.length > 0) {
1220
+ const snapshots = snapshotTsupMigrationTargets(tsupTargets);
1221
+ const migrationWarnings = [];
1222
+ spinner.start("Migrating tsup config to tsdown...");
1223
+ for (const target of tsupTargets) {
1224
+ const targetLabel = target === rootPath ? "the project root" : displayRelative(target, projectPath);
1225
+ const migrateResult = await runTsdownMigrateStep(vpBin, target, packageManager);
1226
+ if (!migrateResult.ok) {
1227
+ spinner.stop();
1228
+ const restoreFailures = restoreTsupMigrationTargets(snapshots);
1229
+ if (restoreFailures.length > 0) log.warn(`Could not restore these files after the failed migration:\n${restoreFailures.map((file) => ` ${file}`).join("\n")}`);
1230
+ showTsdownMigrationOptions(targetLabel, true);
1231
+ return false;
1232
+ }
1233
+ for (const warning of migrateResult.warnings) migrationWarnings.push({
1234
+ targetLabel,
1235
+ warning
1236
+ });
1237
+ }
1238
+ spinner.stop("tsup config migrated to tsdown.config");
1239
+ preservedDependencyTargets = restoreSharedTsupUsage(sharedConfigs, snapshots);
1240
+ for (const { targetLabel, warning } of migrationWarnings) {
1241
+ const message = targetLabel === "the project root" ? `tsdown-migrate: ${warning}` : `tsdown-migrate (${targetLabel}): ${warning}`;
1242
+ if (options?.report) addMigrationWarning(options.report, message);
1243
+ else log.warn(message);
1244
+ }
1245
+ for (const [configPath, sharedConfig] of sharedConfigs) {
1246
+ const message = `${displayRelative(configPath, projectPath)} is shared by ${[...sharedConfig.consumers.values()].map((consumer) => consumer.label).toSorted().join(", ")}. It was preserved and must be migrated manually.`;
1247
+ if (options?.report) addMigrationWarning(options.report, message);
1248
+ else log.warn(message);
1249
+ }
1250
+ }
1251
+ if (options?.report) options.report.tsupMigrated = true;
1252
+ for (const target of tsupTargets) {
1253
+ if (!fs.existsSync(path.join(target, "package.json"))) continue;
1254
+ deleteTsupConfigFiles(target, new Set([...sharedConfigs.keys()].filter((configPath) => path.dirname(configPath) === path.resolve(target))), options?.report, options?.silent);
1255
+ rewriteTsupPackageJson(path.join(target, "package.json"), preservedDependencyTargets.has(path.resolve(target)));
1256
+ }
1257
+ return true;
1258
+ }
1259
+ function deleteTsupConfigFiles(basePath, preservedConfigs, report, silent = false) {
1260
+ const configs = detectConfigs(basePath);
1261
+ if (configs.tsupConfig && configs.tsupConfig !== "package.json#tsup") {
1262
+ const configPath = path.join(basePath, configs.tsupConfig);
1263
+ if (!preservedConfigs.has(configPath) && fs.existsSync(configPath)) {
1264
+ fs.unlinkSync(configPath);
1265
+ if (report) report.removedConfigCount++;
1266
+ if (!silent) log.success(`✔ Removed ${displayRelative(configPath)}`);
1267
+ }
1268
+ }
1269
+ for (const file of TSUP_CONFIG_FILES) {
1270
+ if (file === configs.tsupConfig) continue;
1271
+ const configPath = path.join(basePath, file);
1272
+ if (!preservedConfigs.has(configPath) && fs.existsSync(configPath)) {
1273
+ fs.unlinkSync(configPath);
1274
+ if (report) report.removedConfigCount++;
1275
+ if (!silent) log.success(`✔ Removed ${displayRelative(configPath)}`);
1276
+ }
1277
+ }
1278
+ editJsonFile(path.join(basePath, "package.json"), (pkg) => {
1279
+ if (pkg.tsup) {
1280
+ delete pkg.tsup;
1281
+ return pkg;
1282
+ }
1283
+ });
1284
+ }
1285
+ function rewriteTsupPackageJson(packageJsonPath, preserveTsupDependency = false) {
1286
+ if (!fs.existsSync(packageJsonPath)) return;
1287
+ editJsonFile(packageJsonPath, (pkg) => {
1288
+ let changed = false;
1289
+ for (const [name, script] of Object.entries(pkg.scripts ?? {})) {
1290
+ const rewritten = removeStandardTsdownConfigOption(script);
1291
+ if (rewritten !== script) {
1292
+ pkg.scripts[name] = rewritten;
1293
+ changed = true;
1294
+ }
1295
+ }
1296
+ if (!preserveTsupDependency) {
1297
+ for (const field of ["devDependencies", "dependencies"]) if (pkg[field]?.tsup) {
1298
+ delete pkg[field].tsup;
1299
+ changed = true;
1300
+ }
1301
+ }
1302
+ return changed ? pkg : void 0;
1303
+ });
1304
+ }
1305
+ function warnMissingTsupConfig() {
1306
+ log.warn("tsup detected, but no tsup config was found. The tsup setup must be migrated manually.");
1307
+ }
1308
+ async function confirmTsupMigration(interactive) {
1309
+ if (interactive) {
1310
+ const confirmed = await confirm({
1311
+ message: "Migrate tsup config to tsdown using tsdown-migrate?\n " + styleText("gray", "tsdown is Vite+'s built-in bundler (exposed via `vp pack`) — a mostly drop-in tsup replacement powered by Rolldown. tsdown-migrate converts your existing config automatically."),
1312
+ initialValue: true
1313
+ });
1314
+ if (isCancel(confirmed)) cancelAndExit();
1315
+ if (!confirmed) showTsdownMigrationOptions();
1316
+ return confirmed;
1317
+ }
1318
+ log.info("tsup configuration detected. Auto-migrating to tsdown...");
1319
+ return true;
1320
+ }
1321
+ async function promptTsupMigration(projectPath, interactive, packageManager, packages) {
1322
+ const tsupProject = detectTsupProject(projectPath, packages);
1323
+ if (!tsupProject.hasDependency) return false;
1324
+ if (!tsupProject.hasConfig) {
1325
+ warnMissingTsupConfig();
1326
+ return false;
1327
+ }
1328
+ if (!await confirmTsupMigration(interactive)) return false;
1329
+ if (!await migrateTsupToTsdown(projectPath, interactive, packageManager, tsupProject.configFile, packages)) cancelAndExit("Complete the tsup migration manually, then re-run `vp migrate`.", 1);
1330
+ return true;
1331
+ }
1332
+ //#endregion
884
1333
  //#region src/migration/migrator/tsconfig.ts
885
1334
  function cleanupDeprecatedTsconfigOptions(projectPath, silent = false, report) {
886
1335
  const deprecatedOptions = ["esModuleInterop", "allowSyntheticDefaultImports"];
@@ -1137,17 +1586,21 @@ function projectListsRequiredVitestPeer(projectPath, pkg) {
1137
1586
  function projectUsesVitestDirectly(projectPath, pkg, requiredVitestPeer, preserveNuxtVitestImports = true, precomputedScans) {
1138
1587
  return projectListsVitestEcosystemDep(pkg) || (requiredVitestPeer ?? projectListsRequiredVitestPeer(projectPath, pkg)) || VITEST_BROWSER_DEP_NAMES.some((name) => pkg.peerDependencies?.[name] !== void 0) || (precomputedScans?.retainedModule ?? sourceTreeReferencesRetainedVitestModule(projectPath)) || preserveNuxtVitestImports && hasNuxtTestUtilsDependency(pkg) || (precomputedScans?.browserMode ?? usesVitestBrowserMode(projectPath));
1139
1588
  }
1140
- function removeManagedVitestEntry(record) {
1141
- if (VITEST_IS_MANAGED_OVERRIDE && typeof record?.vitest === "string") {
1142
- delete record.vitest;
1143
- return true;
1589
+ function removeManagedVitestEntry(record, keyStyle = "bare") {
1590
+ if (!VITEST_IS_MANAGED_OVERRIDE || !record) return false;
1591
+ let removed = false;
1592
+ for (const key of managedVitestOverrideKeys(keyStyle)) if (typeof record[key] === "string") {
1593
+ delete record[key];
1594
+ removed = true;
1144
1595
  }
1145
- return false;
1596
+ return removed;
1146
1597
  }
1147
- function removeYamlMapVitestEntry(map) {
1598
+ function removeYamlMapVitestEntry(map, keyStyle = "bare") {
1148
1599
  if (!VITEST_IS_MANAGED_OVERRIDE || !(map instanceof import_dist.YAMLMap)) return;
1149
- const target = map.items.find((item) => item.key instanceof import_dist.Scalar && item.key.value === "vitest")?.key;
1150
- if (target) map.delete(target);
1600
+ for (const key of managedVitestOverrideKeys(keyStyle)) map.delete(key);
1601
+ }
1602
+ function managedVitestOverrideKeys(keyStyle) {
1603
+ return keyStyle === "pnpm-ranged" ? ["vitest", pnpmOverrideKey("vitest")] : ["vitest"];
1151
1604
  }
1152
1605
  function removeVitestPeerDependencyRule(peerDependencyRules) {
1153
1606
  if (!VITEST_IS_MANAGED_OVERRIDE) return;
@@ -1240,7 +1693,7 @@ function vitestEcosystemCatalogReferencesPending(pkg, catalogDependencyResolver)
1240
1693
  pkg.optionalDependencies
1241
1694
  ]) {
1242
1695
  if (!dependencies) continue;
1243
- for (const [name, spec] of Object.entries(dependencies)) if (isAlignableVitestEcosystemPackage(name) && spec.startsWith("catalog:") && catalogDependencyResolver(spec, name) !== "4.1.10") return true;
1696
+ for (const [name, spec] of Object.entries(dependencies)) if (isAlignableVitestEcosystemPackage(name) && spec.startsWith("catalog:") && catalogDependencyResolver(spec, name) !== "4.1.11") return true;
1244
1697
  }
1245
1698
  return false;
1246
1699
  }
@@ -6933,10 +7386,12 @@ function rewritePnpmWorkspaceYaml(projectPath, pnpmMajorVersion, shouldAllowBrow
6933
7386
  const keysSnapshot = overrides.items.map((item) => item.key);
6934
7387
  for (const keyNode of keysSnapshot) if (shouldDropProviderOverrideKey(keyNode instanceof import_dist.Scalar ? String(keyNode.value ?? "") : String(keyNode ?? ""))) overrides.delete(keyNode);
6935
7388
  }
6936
- if (!usesVitest) removeYamlMapVitestEntry(doc.getIn(["overrides"]));
7389
+ if (!usesVitest) removeYamlMapVitestEntry(doc.getIn(["overrides"]), "pnpm-ranged");
6937
7390
  for (const key of Object.keys(managed)) {
6938
- const version = getCatalogDependencySpec(getYamlMapScalarStringValue(overrides, key), managed[key], true, { preferredCatalogSpec });
6939
- doc.setIn(["overrides", scalarString(key)], scalarString(version));
7391
+ const overrideKey = pnpmOverrideKey(key);
7392
+ const version = getCatalogDependencySpec(getYamlMapScalarStringValue(overrides, overrideKey) ?? getYamlMapScalarStringValue(overrides, key), managed[key], true, { preferredCatalogSpec });
7393
+ if (overrides instanceof import_dist.YAMLMap) overrides.delete(key);
7394
+ doc.setIn(["overrides", scalarString(overrideKey)], scalarString(version));
6940
7395
  }
6941
7396
  const updatedOverrides = doc.getIn(["overrides"]);
6942
7397
  const updatedOverrideKeys = updatedOverrides.items.map((item) => item.key);
@@ -7035,14 +7490,17 @@ function getCatalogDependencySpec(currentValue, version, supportCatalog, options
7035
7490
  }
7036
7491
  /**
7037
7492
  * #1932: under pnpm, an importer that depends on `vite-plus` (which bundles
7038
- * `vitest`) needs a DIRECT `vite` devDep so the `vite` override binds vitest's
7039
- * required `vite` peer to @voidzero-dev/vite-plus-core. Without a direct edge,
7040
- * pnpm's `autoInstallPeers` fabricates a separate upstream `vite` to satisfy the
7493
+ * `vitest`) needs a DIRECT `vite` devDep pointing at @voidzero-dev/vite-plus-core
7494
+ * so vitest's required `vite` peer binds to it. Without a direct edge, pnpm's
7495
+ * `autoInstallPeers` fabricates a separate upstream `vite` to satisfy the
7041
7496
  * peer, splitting vite-plus / vite / vitest into duplicate instances (the extra
7042
7497
  * vite also lacks vite's `@voidzero-dev/vite-task-client` integration, breaking
7043
- * the `vp test` cache). npm/yarn/bun redirect transitive/peer vite via root
7044
- * overrides/resolutions (and drop the aliased vite), so this is pnpm-only,
7045
- * mirroring the bun root-package branch in `rewriteRootWorkspacePackageJson`.
7498
+ * the `vp test` cache). Under a catalog the edge is a `catalog:` reference and
7499
+ * the catalog entry carries the alias; the `vite@*` workspace override covers
7500
+ * transitive and peer declarations instead of this one (see `pnpmOverrideKey`).
7501
+ * npm/yarn/bun redirect transitive/peer vite via root overrides/resolutions (and
7502
+ * drop the aliased vite), so this is pnpm-only, mirroring the bun root-package
7503
+ * branch in `rewriteRootWorkspacePackageJson`.
7046
7504
  *
7047
7505
  * A package that already declares `vite` in ANY dependency field, including
7048
7506
  * `peerDependencies` (e.g. a vite plugin pinning `vite ^6`), is left untouched
@@ -7157,6 +7615,39 @@ function getYamlMapScalarStringValue(map, key) {
7157
7615
  if (!(map instanceof import_dist.YAMLMap)) return;
7158
7616
  for (const item of map.items) if (item.key instanceof import_dist.Scalar && item.key.value === key && item.value instanceof import_dist.Scalar && typeof item.value.value === "string") return item.value.value;
7159
7617
  }
7618
+ /**
7619
+ * Merge the managed override entries into a pnpm `overrides` record, under the
7620
+ * range-qualified keys (see `pnpmOverrideKey`).
7621
+ *
7622
+ * Both writers of the package.json `pnpm.overrides` sink go through this
7623
+ * helper: the standalone writer and the monorepo-root writer. That sink serves
7624
+ * pnpm 9.5 to 10.6.1. The helper deletes a bare managed key that a pre-#2309
7625
+ * migration left. Two keys for one package would restore the match that
7626
+ * clobbers `catalog:` importer specs.
7627
+ *
7628
+ * A bare key's `catalog:` value moves to the ranged key, so a user's own
7629
+ * `catalog:<name>` choice survives the re-keying. This mirrors
7630
+ * `getCatalogDependencySpec`, which keeps a `catalog:` reference in the
7631
+ * pnpm-workspace.yaml sink. A `file:` managed spec (force-override mode) always
7632
+ * wins, because there is no catalog to resolve against in that mode.
7633
+ *
7634
+ * Force-override mode also appends the `vite-plus` pin, under a BARE key. The
7635
+ * pin only exists in `file:` tgz mode, where migration writes the tgz spec
7636
+ * straight into every manifest instead of a `catalog:` reference. In that mode
7637
+ * there is no catalog provenance for a bare key to strip. This matches the
7638
+ * workspace-yaml force-override path in `rewriteStandaloneProject`.
7639
+ */
7640
+ function mergeManagedPnpmOverrides(overrides, managed) {
7641
+ const next = { ...overrides };
7642
+ for (const [dependencyName, managedSpec] of Object.entries(managed)) {
7643
+ const overrideKey = pnpmOverrideKey(dependencyName);
7644
+ const existing = next[overrideKey] ?? next[dependencyName];
7645
+ delete next[dependencyName];
7646
+ next[overrideKey] = existing?.startsWith("catalog:") && !managedSpec.startsWith("file:") ? existing : managedSpec;
7647
+ }
7648
+ if (isForceOverrideMode()) next[VITE_PLUS_NAME] = VITE_PLUS_VERSION;
7649
+ return next;
7650
+ }
7160
7651
  function pruneYamlMapLegacyWrapperAliases(map) {
7161
7652
  if (!(map instanceof import_dist.YAMLMap)) return;
7162
7653
  const stale = [];
@@ -7312,15 +7803,11 @@ function rewriteRootWorkspacePackageJson(projectPath, packageManager, skipStaged
7312
7803
  const overrideKeys = Object.keys(managed);
7313
7804
  if (!pnpmSupportsWorkspaceSettings(pnpmVersion ?? "")) {
7314
7805
  dropRemovePackageOverrideKeys(pkg.pnpm?.overrides);
7315
- if (!workspaceUsesVitest) removeManagedVitestEntry(pkg.pnpm?.overrides);
7806
+ if (!workspaceUsesVitest) removeManagedVitestEntry(pkg.pnpm?.overrides, "pnpm-ranged");
7316
7807
  if (!workspaceUsesVitest && pkg.pnpm?.peerDependencyRules) removeVitestPeerDependencyRule(pkg.pnpm.peerDependencyRules);
7317
7808
  pkg.pnpm = {
7318
7809
  ...pkg.pnpm,
7319
- overrides: {
7320
- ...pkg.pnpm?.overrides,
7321
- ...managed,
7322
- ...isForceOverrideMode() ? { [VITE_PLUS_NAME]: VITE_PLUS_VERSION } : {}
7323
- },
7810
+ overrides: mergeManagedPnpmOverrides(pkg.pnpm?.overrides, managed),
7324
7811
  peerDependencyRules: {
7325
7812
  ...pkg.pnpm?.peerDependencyRules,
7326
7813
  allowAny: [.../* @__PURE__ */ new Set([...pkg.pnpm?.peerDependencyRules?.allowAny ?? [], ...overrideKeys])],
@@ -7709,9 +8196,11 @@ function overrideSpecSatisfiesVitePlus(dependencyName, spec, catalogDependencyRe
7709
8196
  if (!spec.startsWith("catalog:")) return false;
7710
8197
  return isSemanticVitePlusOverrideSpec(dependencyName, catalogDependencyResolver?.(spec, dependencyName));
7711
8198
  }
7712
- function overridesSatisfyVitePlus(overrides, usesVitest, catalogDependencyResolver) {
7713
- if (!usesVitest && VITEST_IS_MANAGED_OVERRIDE && typeof overrides?.vitest === "string") return false;
7714
- return Object.keys(managedOverridePackages(usesVitest)).every((dependencyName) => overrideSpecSatisfiesVitePlus(dependencyName, overrides?.[dependencyName], catalogDependencyResolver));
8199
+ function overridesSatisfyVitePlus(overrides, usesVitest, catalogDependencyResolver, keyStyle = "bare") {
8200
+ const managed = managedOverridePackages(usesVitest);
8201
+ if (!usesVitest && VITEST_IS_MANAGED_OVERRIDE && (typeof overrides?.vitest === "string" || keyStyle === "pnpm-ranged" && typeof overrides?.[pnpmOverrideKey("vitest")] === "string")) return false;
8202
+ if (keyStyle === "pnpm-ranged" && Object.keys(managed).some((dependencyName) => typeof overrides?.[dependencyName] === "string")) return false;
8203
+ return Object.keys(managed).every((dependencyName) => overrideSpecSatisfiesVitePlus(dependencyName, overrides?.[managedOverrideKey(dependencyName, keyStyle)], catalogDependencyResolver));
7715
8204
  }
7716
8205
  function hasPackageManagerPin(pkg) {
7717
8206
  return Boolean(pkg.packageManager || pkg.devEngines?.packageManager);
@@ -7932,11 +8421,11 @@ function detectVitePlusBootstrapPending(projectPath, packageManager, packages, p
7932
8421
  if (packageManager === PackageManager.pnpm) {
7933
8422
  if (!pnpmWorkspaceExoticSubdepsSettingSatisfied(projectPath)) return true;
7934
8423
  if (!usePnpmWorkspaceYaml) {
7935
- if (supportCatalog) return catalogVitePlusDependencyPending(pkg, catalogDependencyResolver) || !overridesSatisfyVitePlus(pkg.pnpm?.overrides, usesVitest, catalogDependencyResolver) || !pnpmPeerDependencyRulesSatisfyVitePlus(pkg.pnpm?.peerDependencyRules, usesVitest);
7936
- return vitePlusDependencyNeedsConcreteVersion(pkg) || !overridesSatisfyVitePlus(pkg.pnpm?.overrides, usesVitest) || !pnpmPeerDependencyRulesSatisfyVitePlus(pkg.pnpm?.peerDependencyRules, usesVitest);
8424
+ if (supportCatalog) return catalogVitePlusDependencyPending(pkg, catalogDependencyResolver) || !overridesSatisfyVitePlus(pkg.pnpm?.overrides, usesVitest, catalogDependencyResolver, "pnpm-ranged") || !pnpmPeerDependencyRulesSatisfyVitePlus(pkg.pnpm?.peerDependencyRules, usesVitest);
8425
+ return vitePlusDependencyNeedsConcreteVersion(pkg) || !overridesSatisfyVitePlus(pkg.pnpm?.overrides, usesVitest, void 0, "pnpm-ranged") || !pnpmPeerDependencyRulesSatisfyVitePlus(pkg.pnpm?.peerDependencyRules, usesVitest);
7937
8426
  }
7938
8427
  const resolver = readPnpmWorkspaceCatalogDependencyResolver(projectPath);
7939
- return workspaceCatalogVitePlusDependencyPending(projectPath, packages, resolver) || !overridesSatisfyVitePlus(readPnpmWorkspaceOverrides(projectPath), usesVitest, resolver) || !pnpmPeerDependencyRulesSatisfyVitePlus(readPnpmWorkspacePeerDependencyRules(projectPath), usesVitest) || pnpmWorkspaceMinimumReleaseAgeExemptionsPending(projectPath);
8428
+ return workspaceCatalogVitePlusDependencyPending(projectPath, packages, resolver) || !overridesSatisfyVitePlus(readPnpmWorkspaceOverrides(projectPath), usesVitest, resolver, "pnpm-ranged") || !pnpmPeerDependencyRulesSatisfyVitePlus(readPnpmWorkspacePeerDependencyRules(projectPath), usesVitest) || pnpmWorkspaceMinimumReleaseAgeExemptionsPending(projectPath);
7940
8429
  }
7941
8430
  return false;
7942
8431
  }
@@ -7975,13 +8464,21 @@ function ensureVitePlusDependencySpecs(pkg, version, ensurePresent = true) {
7975
8464
  function readTextFileIfExists(filePath) {
7976
8465
  return fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf-8") : void 0;
7977
8466
  }
7978
- function ensureOverrideEntries(overrides, usesVitest, catalogDependencyResolver) {
8467
+ function ensureOverrideEntries(overrides, usesVitest, catalogDependencyResolver, keyStyle = "bare") {
7979
8468
  const next = { ...overrides };
7980
8469
  let changed = false;
7981
- if (!usesVitest && removeManagedVitestEntry(next)) changed = true;
7982
- for (const [dependencyName, overrideSpec] of Object.entries(managedOverridePackages(usesVitest))) if (!overrideSpecSatisfiesVitePlus(dependencyName, next[dependencyName], catalogDependencyResolver)) {
7983
- next[dependencyName] = overrideSpec;
7984
- changed = true;
8470
+ if (!usesVitest && removeManagedVitestEntry(next, keyStyle)) changed = true;
8471
+ for (const [dependencyName, overrideSpec] of Object.entries(managedOverridePackages(usesVitest))) {
8472
+ const overrideKey = managedOverrideKey(dependencyName, keyStyle);
8473
+ if (overrideKey !== dependencyName && next[dependencyName] !== void 0) {
8474
+ next[overrideKey] ??= next[dependencyName];
8475
+ delete next[dependencyName];
8476
+ changed = true;
8477
+ }
8478
+ if (!overrideSpecSatisfiesVitePlus(dependencyName, next[overrideKey], catalogDependencyResolver)) {
8479
+ next[overrideKey] = overrideSpec;
8480
+ changed = true;
8481
+ }
7985
8482
  }
7986
8483
  return {
7987
8484
  overrides: next,
@@ -8061,7 +8558,7 @@ function ensureVitePlusBootstrap(workspaceInfo, report) {
8061
8558
  }
8062
8559
  } else if (workspaceInfo.packageManager === PackageManager.pnpm && !usePnpmWorkspaceYaml) {
8063
8560
  pkg.pnpm ??= {};
8064
- const ensured = ensureOverrideEntries(pkg.pnpm.overrides, usesVitest, supportCatalog ? readPnpmWorkspaceCatalogDependencyResolver(projectPath) : void 0);
8561
+ const ensured = ensureOverrideEntries(pkg.pnpm.overrides, usesVitest, supportCatalog ? readPnpmWorkspaceCatalogDependencyResolver(projectPath) : void 0, "pnpm-ranged");
8065
8562
  if (ensured.changed) {
8066
8563
  pkg.pnpm.overrides = ensured.overrides;
8067
8564
  packageJsonChanged = true;
@@ -8100,7 +8597,7 @@ function ensureVitePlusBootstrap(workspaceInfo, report) {
8100
8597
  const before = readTextFileIfExists(pnpmWorkspaceYamlPath);
8101
8598
  migratePnpmSettingsToWorkspaceYaml(projectPath, movedPnpmSettings);
8102
8599
  const catalogDependencyResolver = readPnpmWorkspaceCatalogDependencyResolver(projectPath);
8103
- if (movedPnpmSettings !== void 0 || result.packageJson || ecosystemCatalogReferencesPending || !pnpmWorkspaceExoticSubdepsSettingSatisfied(projectPath) || pnpmWorkspaceMinimumReleaseAgeExemptionsPending(projectPath) || workspaceCatalogVitePlusDependencyPending(projectPath, workspaceInfo.packages, catalogDependencyResolver) || !overridesSatisfyVitePlus(readPnpmWorkspaceOverrides(projectPath), usesVitest, catalogDependencyResolver) || !pnpmPeerDependencyRulesSatisfyVitePlus(readPnpmWorkspacePeerDependencyRules(projectPath), usesVitest)) rewritePnpmWorkspaceYaml(projectPath, pnpmMajorVersion, shouldAllowBrowserBuilds, usesVitest, vitestEcosystemPackages, true, providerCatalogAdditions);
8600
+ if (movedPnpmSettings !== void 0 || result.packageJson || ecosystemCatalogReferencesPending || !pnpmWorkspaceExoticSubdepsSettingSatisfied(projectPath) || pnpmWorkspaceMinimumReleaseAgeExemptionsPending(projectPath) || workspaceCatalogVitePlusDependencyPending(projectPath, workspaceInfo.packages, catalogDependencyResolver) || !overridesSatisfyVitePlus(readPnpmWorkspaceOverrides(projectPath), usesVitest, catalogDependencyResolver, "pnpm-ranged") || !pnpmPeerDependencyRulesSatisfyVitePlus(readPnpmWorkspacePeerDependencyRules(projectPath), usesVitest)) rewritePnpmWorkspaceYaml(projectPath, pnpmMajorVersion, shouldAllowBrowserBuilds, usesVitest, vitestEcosystemPackages, true, providerCatalogAdditions);
8104
8601
  if (fs.existsSync(pnpmWorkspaceYamlPath)) ensurePnpmWorkspacePackages(projectPath, workspaceInfo.workspacePatterns);
8105
8602
  result.packageManagerConfig = before !== readTextFileIfExists(pnpmWorkspaceYamlPath);
8106
8603
  } else {
@@ -8629,12 +9126,19 @@ function findGitRoot(startPath) {
8629
9126
  }
8630
9127
  }
8631
9128
  async function initGitRepository(cwd) {
8632
- return (await runCommandSilently({
9129
+ const result = await runCommandSilently({
8633
9130
  command: "git",
8634
9131
  args: ["init"],
8635
9132
  cwd,
8636
9133
  envs: process.env
8637
- })).exitCode === 0;
9134
+ });
9135
+ if (result.exitCode !== 0) {
9136
+ log.warn("Failed to initialize git repository");
9137
+ const stderr = result.stderr.toString().trim();
9138
+ if (stderr) log.info(stderr);
9139
+ return false;
9140
+ }
9141
+ return true;
8638
9142
  }
8639
9143
  //#endregion
8640
9144
  //#region src/migration/migrator/git-hooks.ts
@@ -8902,7 +9406,7 @@ const NODE_VERSION_FILE_NVMRC_RE = /(node-version-file:[ \t]*)(['"]?)(\.\/)?\.nv
8902
9406
  * Collect GitHub Actions YAML files that may carry a `node-version-file:`
8903
9407
  * reference: top-level workflows (`.github/workflows/*.{yml,yaml}`, which GitHub
8904
9408
  * runs only when flat in that directory) and composite action definitions
8905
- * (`.github/actions/**​/action.{yml,yaml}`, which may nest at any depth). Returns
9409
+ * (`.github/actions/**\/action.{yml,yaml}`, which may nest at any depth). Returns
8906
9410
  * absolute paths; a missing `.github` tree just yields an empty list. `nocase`
8907
9411
  * keeps the match case-insensitive on case-sensitive filesystems.
8908
9412
  */
@@ -9104,16 +9608,12 @@ function rewriteStandaloneProject(projectPath, workspaceInfo, skipStagedMigratio
9104
9608
  if (!usePnpmWorkspaceYaml) {
9105
9609
  dropRemovePackageOverrideKeys(pkg.pnpm?.overrides);
9106
9610
  if (!usesVitest) {
9107
- removeManagedVitestEntry(pkg.pnpm?.overrides);
9611
+ removeManagedVitestEntry(pkg.pnpm?.overrides, "pnpm-ranged");
9108
9612
  if (pkg.pnpm?.peerDependencyRules) removeVitestPeerDependencyRule(pkg.pnpm.peerDependencyRules);
9109
9613
  }
9110
9614
  pkg.pnpm = {
9111
9615
  ...pkg.pnpm,
9112
- overrides: {
9113
- ...pkg.pnpm?.overrides,
9114
- ...managed,
9115
- ...isForceOverrideMode() ? { [VITE_PLUS_NAME]: VITE_PLUS_VERSION } : {}
9116
- },
9616
+ overrides: mergeManagedPnpmOverrides(pkg.pnpm?.overrides, managed),
9117
9617
  peerDependencyRules: {
9118
9618
  ...pkg.pnpm?.peerDependencyRules,
9119
9619
  allowAny: [.../* @__PURE__ */ new Set([...pkg.pnpm?.peerDependencyRules?.allowAny ?? [], ...overrideKeys])],
@@ -9294,13 +9794,16 @@ const JETBRAINS_EXTERNAL_DEPENDENCIES = `<?xml version="1.0" encoding="UTF-8"?>
9294
9794
  </component>
9295
9795
  </project>
9296
9796
  `;
9797
+ function jetbrainsNodeInterpreterPath() {
9798
+ return path.join(getVpDirs().bin, process.platform === "win32" ? "node.exe" : "node");
9799
+ }
9297
9800
  function jetbrainsWorkspaceConfig(packageManager) {
9298
9801
  return `<?xml version="1.0" encoding="UTF-8"?>
9299
9802
  <project version="4">
9300
9803
  <component name="PropertiesComponent">
9301
9804
  <![CDATA[${JSON.stringify({ keyToString: {
9302
9805
  "javascript.preferred.runtime.type.id": "node",
9303
- nodejs_interpreter_path: "$USER_HOME$/.vite-plus/bin/node.exe",
9806
+ nodejs_interpreter_path: jetbrainsNodeInterpreterPath(),
9304
9807
  nodejs_package_manager_path: packageManager
9305
9808
  } }, null, 2)}]]>
9306
9809
  </component>
@@ -9588,4 +10091,4 @@ function resolveEditorIds(editors) {
9588
10091
  return uniqueEditorIds.length === 0 ? void 0 : uniqueEditorIds;
9589
10092
  }
9590
10093
  //#endregion
9591
- export { isBingoTemplate as A, warnPackageLevelPrettier as B, mergeViteConfigFiles as C, configureYarnNodeModulesMode as D, ensureVitePlusBootstrap as E, hasFrameworkShim as F, promptEslintMigration as G, detectEslintProject as H, confirmPrettierMigration as I, warnPackageLevelEslint as J, warnIncompatibleEslintIntegration as K, detectPrettierProject as L, updateWorkspaceConfig as M, addFrameworkShim as N, detectYarnPnpMode as O, detectFramework as P, migratePrettierToOxfmt as R, injectLintTypeCheckDefaults as S, detectVitePlusBootstrapPending as T, detectIncompatibleEslintIntegration as U, confirmEslintMigration as V, migrateEslintToOxlint as W, checkVitestVersion as X, checkViteVersion as Y, preflightGitHooksSetup as _, selectEditors as a, initGitRepository as b, rewriteMonorepoProject as c, finalizeCoreMigrationForExistingVitePlus as d, detectNodeVersionManagerFile as f, installGitHooks as g, detectLegacyGitHooksMigrationCandidate as h, selectEditor as i, updatePackageJsonWithDeps as j, detectWorkspace$1 as k, rewriteStandaloneProject as l, setPackageManager as m, detectExistingEditors as n, writeEditorConfigs as o, migrateNodeVersionManagerFile as p, warnLegacyEslintConfig as q, isJsonLikeFile as r, rewriteMonorepo as s, detectEditorConflicts as t, detectPendingCoreMigration as u, shouldSkipStagedMigrationForHooks as v, collectToolchainVersionChanges as w, injectCreateDefaultTemplate as x, findGitRoot as y, promptPrettierMigration as z };
10094
+ export { warnLegacyEslintConfig as $, detectWorkspace$1 as A, promptTsupMigration as B, mergeTsdownConfigFile as C, ensureVitePlusBootstrap as D, detectVitePlusBootstrapPending as E, detectFramework as F, promptPrettierMigration as G, confirmPrettierMigration as H, hasFrameworkShim as I, detectEslintProject as J, warnPackageLevelPrettier as K, confirmTsupMigration as L, updatePackageJsonWithDeps as M, updateWorkspaceConfig as N, configureYarnNodeModulesMode as O, addFrameworkShim as P, warnIncompatibleEslintIntegration as Q, detectTsupProject as R, injectLintTypeCheckDefaults as S, collectToolchainVersionChanges as T, detectPrettierProject as U, warnMissingTsupConfig as V, migratePrettierToOxfmt as W, migrateEslintToOxlint as X, detectIncompatibleEslintIntegration as Y, promptEslintMigration as Z, preflightGitHooksSetup as _, selectEditors as a, initGitRepository as b, rewriteMonorepoProject as c, finalizeCoreMigrationForExistingVitePlus as d, warnPackageLevelEslint as et, detectNodeVersionManagerFile as f, installGitHooks as g, detectLegacyGitHooksMigrationCandidate as h, selectEditor as i, isBingoTemplate as j, detectYarnPnpMode as k, rewriteStandaloneProject as l, setPackageManager as m, detectExistingEditors as n, checkVitestVersion as nt, writeEditorConfigs as o, migrateNodeVersionManagerFile as p, confirmEslintMigration as q, isJsonLikeFile as r, rewriteMonorepo as s, detectEditorConflicts as t, checkViteVersion as tt, detectPendingCoreMigration as u, shouldSkipStagedMigrationForHooks as v, mergeViteConfigFiles as w, injectCreateDefaultTemplate as x, findGitRoot as y, migrateTsupToTsdown as z };