vite-plus 0.1.24 → 0.2.1
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/LICENSE +30 -0
- package/README.md +8 -6
- package/bin/oxfmt +5 -2
- package/bin/oxlint +12 -2
- package/binding/index.cjs +84 -67
- package/binding/index.d.cts +155 -4
- package/dist/{agent-Nuk-9l77.js → agent--cKmgD_n.js} +941 -70
- package/dist/bin.js +22 -30
- package/dist/{compat-DXZgnEyq.js → compat-Cql3K40m.js} +1 -1
- package/dist/config/bin.js +30 -14
- package/dist/constants-CrfJQIUX.js +66 -0
- package/dist/create/bin.d.ts +6 -0
- package/dist/create/bin.js +508 -232
- package/dist/define-config-2tfJoXr1.d.ts +305 -0
- package/dist/define-config-BGSjF6Xp.cjs +488 -0
- package/dist/define-config-DJUehepE.js +445 -0
- package/dist/define-config.cjs +8 -1
- package/dist/define-config.d.ts +2 -2
- package/dist/define-config.js +2 -2
- package/dist/dist-DRJUd9bL.js +3 -0
- package/dist/{dist-BgQuvbtq.js → dist-Oxo16Y0q.js} +4 -4
- package/dist/index.cjs +9 -4
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/{main-DpJl3LoU.js → json-Dn87fvjk.js} +137 -1
- package/dist/migration/bin.js +292 -76
- package/dist/{oxlint-plugin-config-B89iKTKN.js → oxlint-plugin-config-q8a5PFch.js} +1 -1
- package/dist/oxlint-plugin.js +11 -3
- package/dist/pack-bin.js +44 -15
- package/dist/{package-PmBUZ-ve.js → package-BHirM1_v.js} +3 -138
- package/dist/{report-DgSBQUdz.js → report-BHSkWqRR.js} +2 -0
- package/dist/{resolve-vite-config-TTvhycU1.js → resolve-vite-config-CmdsfQzS.js} +13 -4
- package/dist/staged/bin.js +5 -5
- package/dist/test/_at-vitest-browser/context.d.ts +2 -0
- package/dist/test/_at-vitest-browser.d.ts +2 -0
- package/dist/test/browser/context.d.ts +2 -2
- package/dist/test/browser/context.js +1 -1
- package/dist/test/browser/providers/playwright/context.d.ts +1 -0
- package/dist/test/browser/providers/playwright/context.js +1 -0
- package/dist/test/browser/providers/playwright.d.ts +124 -2
- package/dist/test/browser/providers/playwright.js +1 -1
- package/dist/test/browser/providers/preview/context.d.ts +1 -0
- package/dist/test/browser/providers/preview/context.js +1 -0
- package/dist/test/browser/providers/preview.d.ts +32 -2
- package/dist/test/browser/providers/preview.js +1 -1
- package/dist/test/browser/providers/webdriverio/context.d.ts +1 -0
- package/dist/test/browser/providers/webdriverio/context.js +1 -0
- package/dist/test/browser/providers/webdriverio.d.ts +77 -2
- package/dist/test/browser/providers/webdriverio.js +1 -1
- package/dist/test/browser-compat.d.ts +2 -0
- package/dist/test/browser-compat.js +1 -1
- package/dist/test/browser-playwright/context.d.ts +1 -0
- package/dist/test/browser-playwright/context.js +1 -0
- package/dist/test/browser-playwright.d.ts +124 -2
- package/dist/test/browser-playwright.js +1 -1
- package/dist/test/browser-preview/context.d.ts +1 -0
- package/dist/test/browser-preview/context.js +1 -0
- package/dist/test/browser-preview.d.ts +32 -2
- package/dist/test/browser-preview.js +1 -1
- package/dist/test/browser-webdriverio/context.d.ts +1 -0
- package/dist/test/browser-webdriverio/context.js +1 -0
- package/dist/test/browser-webdriverio.d.ts +77 -2
- package/dist/test/browser-webdriverio.js +1 -1
- package/dist/test/browser.d.ts +2 -2
- package/dist/test/browser.js +1 -1
- package/dist/test/client.js +1 -1
- package/dist/test/config.cjs +1 -1
- package/dist/test/config.d.ts +2 -2
- package/dist/test/config.js +1 -1
- package/dist/test/context.d.ts +942 -2
- package/dist/test/context.js +1 -1
- package/dist/test/coverage.d.ts +2 -2
- package/dist/test/coverage.js +1 -1
- package/dist/test/environments.d.ts +2 -2
- package/dist/test/environments.js +1 -1
- package/dist/test/globals.d.ts +2 -2
- package/dist/test/import-meta.d.ts +2 -2
- package/dist/test/importMeta.d.ts +2 -2
- package/dist/test/index.cjs +1 -1
- package/dist/test/index.d.cts +2 -2
- package/dist/test/index.d.ts +2 -2
- package/dist/test/index.js +1 -1
- package/dist/test/internal/browser.d.ts +2 -2
- package/dist/test/internal/browser.js +1 -1
- package/dist/test/jsdom.d.ts +2 -2
- package/dist/test/locators.d.ts +294 -0
- package/dist/test/locators.js +1 -1
- package/dist/test/matchers.d.ts +29 -0
- package/dist/test/matchers.js +1 -1
- package/dist/test/node.d.ts +2 -2
- package/dist/test/node.js +1 -1
- package/dist/test/optional-runtime-types.js.d.ts +2 -2
- package/dist/test/optional-types.js.d.ts +2 -2
- package/dist/test/plugins/browser-client.js +1 -1
- package/dist/test/plugins/browser-context.js +1 -1
- package/dist/test/plugins/browser-locators.js +1 -1
- package/dist/test/plugins/browser-playwright.js +1 -1
- package/dist/test/plugins/browser-preview.js +1 -1
- package/dist/test/plugins/browser-webdriverio.js +1 -1
- package/dist/test/plugins/browser.js +1 -1
- package/dist/test/plugins/expect.js +1 -1
- package/dist/test/plugins/mocker-automock.js +1 -1
- package/dist/test/plugins/mocker-browser.js +1 -1
- package/dist/test/plugins/mocker-node.js +1 -1
- package/dist/test/plugins/mocker-redirect.js +1 -1
- package/dist/test/plugins/mocker-register.js +1 -1
- package/dist/test/plugins/mocker-transforms.js +1 -1
- package/dist/test/plugins/mocker.js +1 -1
- package/dist/test/plugins/pretty-format.js +1 -1
- package/dist/test/plugins/runner-types.js +1 -1
- package/dist/test/plugins/runner-utils.js +1 -1
- package/dist/test/plugins/runner.js +1 -1
- package/dist/test/plugins/snapshot-environment.js +1 -1
- package/dist/test/plugins/snapshot-manager.js +1 -1
- package/dist/test/plugins/snapshot.js +1 -1
- package/dist/test/plugins/spy.js +1 -1
- package/dist/test/plugins/utils-constants.js +1 -1
- package/dist/test/plugins/utils-diff.js +1 -1
- package/dist/test/plugins/utils-display.js +1 -1
- package/dist/test/plugins/utils-error.js +1 -1
- package/dist/test/plugins/utils-helpers.js +1 -1
- package/dist/test/plugins/utils-offset.js +1 -1
- package/dist/test/plugins/utils-resolver.js +1 -1
- package/dist/test/plugins/utils-serialize.js +1 -1
- package/dist/test/plugins/utils-source-map-node.js +1 -1
- package/dist/test/plugins/utils-source-map.js +1 -1
- package/dist/test/plugins/utils-timers.js +1 -1
- package/dist/test/plugins/utils.js +1 -1
- package/dist/test/reporters.d.ts +2 -2
- package/dist/test/reporters.js +1 -1
- package/dist/test/runners.d.ts +2 -2
- package/dist/test/runners.js +1 -1
- package/dist/test/runtime.d.ts +2 -2
- package/dist/test/runtime.js +1 -1
- package/dist/test/snapshot.d.ts +2 -2
- package/dist/test/snapshot.js +1 -1
- package/dist/test/suite.d.ts +2 -2
- package/dist/test/suite.js +1 -1
- package/dist/test/utils.js +1 -1
- package/dist/test/worker.d.ts +2 -2
- package/dist/test/worker.js +1 -1
- package/dist/{tsconfig-DFb5BKyT.js → tsconfig-BWQPmGKz.js} +565 -231
- package/dist/tsgolint-path-B-yOos8p.js +32 -0
- package/dist/tsgolint-path.d.ts +8 -0
- package/dist/tsgolint-path.js +2 -0
- package/dist/version.js +3 -3
- package/dist/versions.d.ts +1 -1
- package/dist/versions.js +6 -6
- package/dist/{workspace-NL-m9wgM.js → workspace-D0AVy4fu.js} +11 -9
- package/docs/_data/team.ts +2 -1
- package/docs/config/create.md +36 -1
- package/docs/config/index.md +7 -5
- package/docs/guide/commit-hooks.md +9 -0
- package/docs/guide/create.md +106 -2
- package/docs/guide/env.md +33 -5
- package/docs/guide/index.md +5 -3
- package/docs/guide/install.md +31 -12
- package/docs/guide/migrate.md +13 -3
- package/docs/guide/troubleshooting.md +2 -2
- package/docs/guide/upgrade.md +26 -7
- package/docs/package.json +3 -3
- package/docs/pnpm-lock.yaml +298 -395
- package/package.json +103 -55
- package/templates/generator/bin/index.ts +6 -3
- package/templates/generator/package.json +2 -3
- package/templates/generator/src/template.ts +0 -2
- package/templates/monorepo/package.json +1 -1
- package/dist/constants-DCBWlNrn.js +0 -33
- package/dist/define-config-BR1Y88zz.cjs +0 -84
- package/dist/define-config-BRC7qPNE.js +0 -21
- package/dist/define-config-COdn-tsn.d.ts +0 -177
- package/dist/dist-Bapm49IR.js +0 -3
- package/dist/test/plugins/utils-highlight.js +0 -1
- /package/dist/{chunk-DnnnRqeS.js → rolldown-runtime-DnnnRqeS.js} +0 -0
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { r as __toESM } from "./
|
|
2
|
-
import { a as
|
|
3
|
-
import { i as ensureVitePlusImportRuleDefaults, r as createDefaultVitePlusLintConfig } from "./oxlint-plugin-config-
|
|
4
|
-
import { A as
|
|
5
|
-
import { t as
|
|
6
|
-
import {
|
|
7
|
-
import { n as
|
|
1
|
+
import { r as __toESM } from "./rolldown-runtime-DnnnRqeS.js";
|
|
2
|
+
import { a as VITEST_VERSION, c as VITE_PLUS_VERSION, i as VITEST_AGE_GATE_EXEMPT_PACKAGES, n as BASEURL_TSCONFIG_WARNING, o as VITE_PLUS_NAME, s as VITE_PLUS_OVERRIDE_PACKAGES, u as isForceOverrideMode } from "./constants-CrfJQIUX.js";
|
|
3
|
+
import { i as ensureVitePlusImportRuleDefaults, r as createDefaultVitePlusLintConfig } from "./oxlint-plugin-config-q8a5PFch.js";
|
|
4
|
+
import { A as select, C as require_semver, D as log, I as runCommandSilently, L as require_cross_spawn, O as multiselect, P as R, S as PackageManager, T as confirm, a as hasTypesToRewriteInTsconfig, b as getSpinner, c as cancelAndExit, i as hasBaseUrlInTsconfig, n as findTsconfigFiles, o as removeDeprecatedTsconfigFalseOption, s as rewriteTypesInTsconfig } from "./tsconfig-BWQPmGKz.js";
|
|
5
|
+
import { n as isJsonFile, r as readJsonFile, t as editJsonFile } from "./json-Dn87fvjk.js";
|
|
6
|
+
import { t as require_dist } from "./dist-Oxo16Y0q.js";
|
|
7
|
+
import { n as detectPackageMetadata } from "./package-BHirM1_v.js";
|
|
8
|
+
import { n as addMigrationWarning, t as addManualStep } from "./report-BHSkWqRR.js";
|
|
8
9
|
import path from "node:path";
|
|
9
|
-
import { hasConfigKey, mergeJsonConfig, mergeTsdownConfig, rewriteEslint, rewriteImportsInDirectory, rewritePrettier, rewriteScripts } from "../binding/index.js";
|
|
10
|
+
import { hasConfigKey, mergeJsonConfig, mergeTsdownConfig, rewriteEslint, rewriteImportsInDirectory, rewritePrettier, rewriteScripts, wrapLazyPlugins } from "../binding/index.js";
|
|
10
11
|
import fs from "node:fs";
|
|
11
12
|
import { styleText } from "node:util";
|
|
13
|
+
import os from "node:os";
|
|
12
14
|
import fsPromises from "node:fs/promises";
|
|
13
15
|
//#region src/utils/path.ts
|
|
14
16
|
var import_cross_spawn = /* @__PURE__ */ __toESM(require_cross_spawn(), 1);
|
|
@@ -173,14 +175,134 @@ const REMOVE_PACKAGES = [
|
|
|
173
175
|
"oxfmt",
|
|
174
176
|
"tsdown",
|
|
175
177
|
"@vitest/browser",
|
|
176
|
-
"@vitest/browser-preview"
|
|
177
|
-
"@vitest/browser-playwright",
|
|
178
|
-
"@vitest/browser-webdriverio"
|
|
178
|
+
"@vitest/browser-preview"
|
|
179
179
|
];
|
|
180
|
+
const WEBDRIVERIO_PROVIDER = "@vitest/browser-webdriverio";
|
|
181
|
+
const PLAYWRIGHT_PROVIDER = "@vitest/browser-playwright";
|
|
182
|
+
const OPT_IN_BROWSER_PROVIDERS = [WEBDRIVERIO_PROVIDER, PLAYWRIGHT_PROVIDER];
|
|
183
|
+
const PROVIDER_OVERRIDE_DROP_NAMES = [...REMOVE_PACKAGES, ...OPT_IN_BROWSER_PROVIDERS];
|
|
184
|
+
function extractOverrideTargetName(key) {
|
|
185
|
+
let target = key.trim();
|
|
186
|
+
for (let delim = target.search(/[^ |@]>/); delim !== -1; delim = target.search(/[^ |@]>/)) target = target.slice(delim + 2).trim();
|
|
187
|
+
if (!target) return target;
|
|
188
|
+
if (target.includes("/")) {
|
|
189
|
+
const segments = target.split("/");
|
|
190
|
+
const last = segments[segments.length - 1];
|
|
191
|
+
const scope = segments[segments.length - 2];
|
|
192
|
+
target = scope?.startsWith("@") ? `${scope}/${last}` : last;
|
|
193
|
+
}
|
|
194
|
+
const nameStart = target.startsWith("@") ? target.indexOf("/") + 1 : 0;
|
|
195
|
+
const versionAt = target.indexOf("@", nameStart);
|
|
196
|
+
if (versionAt > 0) target = target.slice(0, versionAt);
|
|
197
|
+
return target;
|
|
198
|
+
}
|
|
199
|
+
function isRemovePackageOverrideKey(key) {
|
|
200
|
+
return PROVIDER_OVERRIDE_DROP_NAMES.includes(extractOverrideTargetName(key));
|
|
201
|
+
}
|
|
202
|
+
function stripSegmentVersion(segment) {
|
|
203
|
+
const nameStart = segment.startsWith("@") ? segment.indexOf("/") + 1 : 0;
|
|
204
|
+
const versionAt = segment.indexOf("@", nameStart);
|
|
205
|
+
return versionAt > 0 ? segment.slice(0, versionAt) : segment;
|
|
206
|
+
}
|
|
207
|
+
function parentGlobMatchesName(glob, name) {
|
|
208
|
+
const pattern = glob.split("*").map((part) => part.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join(".*");
|
|
209
|
+
return new RegExp(`^${pattern}$`).test(name);
|
|
210
|
+
}
|
|
211
|
+
function ancestorSegmentMatches(segment, name) {
|
|
212
|
+
return segment.includes("*") ? parentGlobMatchesName(segment, name) : segment === name;
|
|
213
|
+
}
|
|
214
|
+
const OWNED_PROVIDER_ANCESTOR_NAMES = REMOVE_PACKAGES.filter((name) => name.startsWith("@vitest/"));
|
|
215
|
+
function parentChainReachesVitePlus(segments) {
|
|
216
|
+
const concrete = segments.filter((segment) => segment !== "**");
|
|
217
|
+
let index = 0;
|
|
218
|
+
if (concrete.length > 0 && ancestorSegmentMatches(concrete[0], "vite-plus")) index = 1;
|
|
219
|
+
for (; index < concrete.length; index += 1) {
|
|
220
|
+
const segment = concrete[index];
|
|
221
|
+
if (!OWNED_PROVIDER_ANCESTOR_NAMES.some((name) => ancestorSegmentMatches(segment, name))) return false;
|
|
222
|
+
}
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
function extractOverrideParentSegments(key) {
|
|
226
|
+
let rest = key.trim();
|
|
227
|
+
const pnpmParents = [];
|
|
228
|
+
for (let delim = rest.search(/[^ |@]>/); delim !== -1; delim = rest.search(/[^ |@]>/)) {
|
|
229
|
+
pnpmParents.push(stripSegmentVersion(rest.slice(0, delim + 1).trim()));
|
|
230
|
+
rest = rest.slice(delim + 2).trim();
|
|
231
|
+
}
|
|
232
|
+
if (pnpmParents.length > 0) return pnpmParents;
|
|
233
|
+
if (!rest.includes("/")) return null;
|
|
234
|
+
const segments = rest.split("/");
|
|
235
|
+
const descriptorSegmentCount = segments[segments.length - 2]?.startsWith("@") ?? false ? 2 : 1;
|
|
236
|
+
const rawParents = segments.slice(0, segments.length - descriptorSegmentCount);
|
|
237
|
+
if (rawParents.length === 0) return null;
|
|
238
|
+
const parents = [];
|
|
239
|
+
for (let i = 0; i < rawParents.length; i += 1) {
|
|
240
|
+
const segment = rawParents[i];
|
|
241
|
+
if (segment.startsWith("@") && i + 1 < rawParents.length) {
|
|
242
|
+
parents.push(stripSegmentVersion(`${segment}/${rawParents[i + 1]}`));
|
|
243
|
+
i += 1;
|
|
244
|
+
} else parents.push(stripSegmentVersion(segment));
|
|
245
|
+
}
|
|
246
|
+
return parents;
|
|
247
|
+
}
|
|
248
|
+
function providerKeyReachesVitePlus(key, ancestorChain) {
|
|
249
|
+
if (!isRemovePackageOverrideKey(key)) return false;
|
|
250
|
+
const keyParents = extractOverrideParentSegments(key) ?? [];
|
|
251
|
+
return parentChainReachesVitePlus([...ancestorChain, ...keyParents]);
|
|
252
|
+
}
|
|
253
|
+
function shouldDropProviderOverrideKey(key) {
|
|
254
|
+
return providerKeyReachesVitePlus(key, []);
|
|
255
|
+
}
|
|
256
|
+
function childChainContribution(key) {
|
|
257
|
+
return [...extractOverrideParentSegments(key) ?? [], extractOverrideTargetName(key)];
|
|
258
|
+
}
|
|
259
|
+
// @vitest/provider`. Covers bare, versioned, global-glob and `vite-plus`-parent
|
|
260
|
+
function dropRemovePackageOverrideKeys(overrides, ancestorChain = []) {
|
|
261
|
+
if (!overrides) return false;
|
|
262
|
+
let removed = false;
|
|
263
|
+
for (const key of Object.keys(overrides)) {
|
|
264
|
+
const value = overrides[key];
|
|
265
|
+
const child = value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
266
|
+
if (providerKeyReachesVitePlus(key, ancestorChain)) {
|
|
267
|
+
if (child) {
|
|
268
|
+
let changed = false;
|
|
269
|
+
if ("." in child) {
|
|
270
|
+
delete child["."];
|
|
271
|
+
changed = true;
|
|
272
|
+
}
|
|
273
|
+
if (dropRemovePackageOverrideKeys(child, [...ancestorChain, ...childChainContribution(key)])) changed = true;
|
|
274
|
+
if (Object.keys(child).length === 0) {
|
|
275
|
+
delete overrides[key];
|
|
276
|
+
changed = true;
|
|
277
|
+
}
|
|
278
|
+
if (changed) removed = true;
|
|
279
|
+
} else {
|
|
280
|
+
delete overrides[key];
|
|
281
|
+
removed = true;
|
|
282
|
+
}
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (child) {
|
|
286
|
+
if (dropRemovePackageOverrideKeys(child, [...ancestorChain, ...childChainContribution(key)])) {
|
|
287
|
+
removed = true;
|
|
288
|
+
if (Object.keys(child).length === 0) delete overrides[key];
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return removed;
|
|
293
|
+
}
|
|
180
294
|
const BROWSER_PROVIDER_PEER_DEPS = {
|
|
181
295
|
"@vitest/browser-playwright": "playwright",
|
|
182
296
|
"@vitest/browser-webdriverio": "webdriverio"
|
|
183
297
|
};
|
|
298
|
+
const BROWSER_PROVIDER_POSTINSTALL_PACKAGES = ["edgedriver", "geckodriver"];
|
|
299
|
+
const WEBDRIVERIO_ALLOW_SIGNAL_DEPS = ["webdriverio", WEBDRIVERIO_PROVIDER];
|
|
300
|
+
const VITEST_BROWSER_DEP_NAMES = [
|
|
301
|
+
"@vitest/browser",
|
|
302
|
+
"@vitest/browser-preview",
|
|
303
|
+
"@vitest/browser-playwright",
|
|
304
|
+
"@vitest/browser-webdriverio"
|
|
305
|
+
];
|
|
184
306
|
const PUBLIC_PEER_DEPENDENCY_FALLBACKS = {
|
|
185
307
|
vite: "*",
|
|
186
308
|
vitest: "*"
|
|
@@ -202,6 +324,46 @@ const OXLINT_NATIVE_PLUGINS = new Set([
|
|
|
202
324
|
"node",
|
|
203
325
|
"vue"
|
|
204
326
|
]);
|
|
327
|
+
const LEGACY_WRAPPER_PACKAGE_NAMES = ["@voidzero-dev/vite-plus-test"];
|
|
328
|
+
const LEGACY_WRAPPER_FALLBACK_VERSIONS = { vitest: VITEST_VERSION };
|
|
329
|
+
function isLegacyWrapperSpec(value) {
|
|
330
|
+
if (typeof value !== "string" || !value) return false;
|
|
331
|
+
for (const name of LEGACY_WRAPPER_PACKAGE_NAMES) if (value === `npm:${name}` || value.startsWith(`npm:${name}@`)) return true;
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Rewrite or remove keys whose value points at a deleted vite-plus wrapper.
|
|
336
|
+
* When a fallback exists for the key (e.g. `vitest`), the value is replaced
|
|
337
|
+
* so existing `catalog:` references continue to resolve. Otherwise the key
|
|
338
|
+
* is dropped entirely. Returns true iff any entry was changed.
|
|
339
|
+
*
|
|
340
|
+
* npm/bun `overrides` may nest an object of scoped overrides under a parent
|
|
341
|
+
* key (e.g. `{ "some-parent": { "vitest": "npm:@voidzero-dev/vite-plus-test@latest" } }`),
|
|
342
|
+
* so object values are recursed into; a parent emptied by pruning is dropped so
|
|
343
|
+
* no `{}` is left behind. Flat maps (pnpm `overrides`, yarn `resolutions`,
|
|
344
|
+
* catalogs) hold only string values, where the recursion is inert.
|
|
345
|
+
*/
|
|
346
|
+
function pruneLegacyWrapperAliases(record) {
|
|
347
|
+
if (!record) return false;
|
|
348
|
+
let mutated = false;
|
|
349
|
+
for (const key of Object.keys(record)) {
|
|
350
|
+
const value = record[key];
|
|
351
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
352
|
+
if (pruneLegacyWrapperAliases(value)) {
|
|
353
|
+
mutated = true;
|
|
354
|
+
if (Object.keys(value).length === 0) delete record[key];
|
|
355
|
+
}
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
if (isLegacyWrapperSpec(value)) {
|
|
359
|
+
const fallback = LEGACY_WRAPPER_FALLBACK_VERSIONS[key];
|
|
360
|
+
if (fallback !== void 0) record[key] = fallback;
|
|
361
|
+
else delete record[key];
|
|
362
|
+
mutated = true;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return mutated;
|
|
366
|
+
}
|
|
205
367
|
function warnMigration(message, report) {
|
|
206
368
|
addMigrationWarning(report, message);
|
|
207
369
|
if (!report) log.warn(message);
|
|
@@ -643,11 +805,17 @@ function cleanupDeprecatedTsconfigOptions(projectPath, silent = false, report) {
|
|
|
643
805
|
}
|
|
644
806
|
}
|
|
645
807
|
function rewriteTsconfigTypes(projectPath, silent = false, report) {
|
|
808
|
+
let changed = false;
|
|
646
809
|
const files = findTsconfigFiles(projectPath);
|
|
647
810
|
for (const filePath of files) if (rewriteTypesInTsconfig(filePath)) {
|
|
811
|
+
changed = true;
|
|
648
812
|
if (report) report.removedConfigCount++;
|
|
649
813
|
if (!silent) log.success(`✔ Rewrote types in ${displayRelative(filePath)}`);
|
|
650
814
|
}
|
|
815
|
+
return changed;
|
|
816
|
+
}
|
|
817
|
+
function hasTsconfigTypesToRewrite(projectPath) {
|
|
818
|
+
return findTsconfigFiles(projectPath).some((filePath) => hasTypesToRewriteInTsconfig(filePath));
|
|
651
819
|
}
|
|
652
820
|
const FRAMEWORK_SHIMS = {
|
|
653
821
|
vue: [
|
|
@@ -716,51 +884,67 @@ function rewriteStandaloneProject(projectPath, workspaceInfo, skipStagedMigratio
|
|
|
716
884
|
if (!fs.existsSync(packageJsonPath)) return;
|
|
717
885
|
const packageManager = workspaceInfo.packageManager;
|
|
718
886
|
const catalogDependencyResolver = createCatalogDependencyResolver(projectPath, packageManager);
|
|
887
|
+
const pnpmMajorVersion = pnpmMajor(workspaceInfo.downloadPackageManager.version);
|
|
719
888
|
let extractedStagedConfig = null;
|
|
720
889
|
let remainingPnpmOverrides;
|
|
721
890
|
let shouldRewritePnpmWorkspaceYaml = false;
|
|
722
891
|
let shouldAddPnpmWorkspaceVitePlusOverride = false;
|
|
892
|
+
let shouldAllowBrowserProviderBuilds = false;
|
|
723
893
|
let usePnpmWorkspaceYaml = false;
|
|
724
894
|
editJsonFile(packageJsonPath, (pkg) => {
|
|
895
|
+
shouldAllowBrowserProviderBuilds = hasOwnWebdriverioDependency(pkg) || usesWebdriverioProvider(projectPath);
|
|
896
|
+
pruneLegacyWrapperAliases(pkg.resolutions);
|
|
897
|
+
pruneLegacyWrapperAliases(pkg.overrides);
|
|
898
|
+
pruneLegacyWrapperAliases(pkg.pnpm?.overrides);
|
|
899
|
+
dropRemovePackageOverrideKeys(pkg.resolutions);
|
|
900
|
+
dropRemovePackageOverrideKeys(pkg.overrides);
|
|
725
901
|
if (packageManager === PackageManager.yarn) pkg.resolutions = {
|
|
726
902
|
...pkg.resolutions,
|
|
727
903
|
...VITE_PLUS_OVERRIDE_PACKAGES
|
|
728
904
|
};
|
|
729
|
-
else if (packageManager === PackageManager.npm || packageManager === PackageManager.bun)
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
905
|
+
else if (packageManager === PackageManager.npm || packageManager === PackageManager.bun) {
|
|
906
|
+
pkg.overrides = {
|
|
907
|
+
...pkg.overrides,
|
|
908
|
+
...VITE_PLUS_OVERRIDE_PACKAGES
|
|
909
|
+
};
|
|
910
|
+
if (packageManager === PackageManager.bun) pkg.devDependencies = {
|
|
911
|
+
...pkg.devDependencies,
|
|
912
|
+
vite: VITE_PLUS_OVERRIDE_PACKAGES.vite
|
|
913
|
+
};
|
|
914
|
+
} else if (packageManager === PackageManager.pnpm) {
|
|
734
915
|
usePnpmWorkspaceYaml = !pkg.pnpm;
|
|
735
916
|
if (usePnpmWorkspaceYaml) {
|
|
736
917
|
shouldRewritePnpmWorkspaceYaml = true;
|
|
737
918
|
shouldAddPnpmWorkspaceVitePlusOverride = isForceOverrideMode();
|
|
738
919
|
}
|
|
739
920
|
const overrideKeys = Object.keys(VITE_PLUS_OVERRIDE_PACKAGES);
|
|
740
|
-
if (!usePnpmWorkspaceYaml)
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
...pkg.pnpm
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
...pkg.pnpm?.peerDependencyRules?.
|
|
752
|
-
|
|
921
|
+
if (!usePnpmWorkspaceYaml) {
|
|
922
|
+
dropRemovePackageOverrideKeys(pkg.pnpm?.overrides);
|
|
923
|
+
pkg.pnpm = {
|
|
924
|
+
...pkg.pnpm,
|
|
925
|
+
overrides: {
|
|
926
|
+
...pkg.pnpm?.overrides,
|
|
927
|
+
...VITE_PLUS_OVERRIDE_PACKAGES,
|
|
928
|
+
...isForceOverrideMode() ? { [VITE_PLUS_NAME]: VITE_PLUS_VERSION } : {}
|
|
929
|
+
},
|
|
930
|
+
peerDependencyRules: {
|
|
931
|
+
...pkg.pnpm?.peerDependencyRules,
|
|
932
|
+
allowAny: [...new Set([...pkg.pnpm?.peerDependencyRules?.allowAny ?? [], ...overrideKeys])],
|
|
933
|
+
allowedVersions: {
|
|
934
|
+
...pkg.pnpm?.peerDependencyRules?.allowedVersions,
|
|
935
|
+
...Object.fromEntries(overrideKeys.map((key) => [key, "*"]))
|
|
936
|
+
}
|
|
753
937
|
}
|
|
754
|
-
}
|
|
755
|
-
};
|
|
756
|
-
else remainingPnpmOverrides = cleanupPnpmOverridesForWorkspaceYaml(pkg, overrideKeys);
|
|
938
|
+
};
|
|
939
|
+
} else remainingPnpmOverrides = cleanupPnpmOverridesForWorkspaceYaml(pkg, overrideKeys);
|
|
757
940
|
for (const key in pkg.pnpm?.overrides) if (key.includes(">")) {
|
|
758
941
|
const splits = key.split(">");
|
|
759
942
|
if (splits[splits.length - 1].trim() === "vite") delete pkg.pnpm.overrides[key];
|
|
760
943
|
}
|
|
761
|
-
for (const key of [...overrideKeys, ...
|
|
944
|
+
for (const key of [...overrideKeys, ...PROVIDER_OVERRIDE_DROP_NAMES]) if (pkg.resolutions?.[key]) delete pkg.resolutions[key];
|
|
945
|
+
if (!usePnpmWorkspaceYaml && pnpmMajorVersion !== void 0 && pkg.pnpm) applyBuildAllowanceToPackageJsonPnpm(pkg.pnpm, pnpmMajorVersion, shouldAllowBrowserProviderBuilds);
|
|
762
946
|
}
|
|
763
|
-
extractedStagedConfig = rewritePackageJson(pkg, packageManager, usePnpmWorkspaceYaml, skipStagedMigration, catalogDependencyResolver);
|
|
947
|
+
extractedStagedConfig = rewritePackageJson(pkg, packageManager, usePnpmWorkspaceYaml, skipStagedMigration, catalogDependencyResolver, usesVitestBrowserMode(projectPath), collectProviderSourceModes(projectPath));
|
|
764
948
|
if (!pkg.devDependencies?.["vite-plus"] || isForceOverrideMode()) {
|
|
765
949
|
const version = usePnpmWorkspaceYaml && !VITE_PLUS_VERSION.startsWith("file:") ? "catalog:" : VITE_PLUS_VERSION;
|
|
766
950
|
pkg.devDependencies = {
|
|
@@ -770,10 +954,11 @@ function rewriteStandaloneProject(projectPath, workspaceInfo, skipStagedMigratio
|
|
|
770
954
|
}
|
|
771
955
|
return pkg;
|
|
772
956
|
});
|
|
773
|
-
if (shouldRewritePnpmWorkspaceYaml) rewritePnpmWorkspaceYaml(projectPath);
|
|
957
|
+
if (shouldRewritePnpmWorkspaceYaml) rewritePnpmWorkspaceYaml(projectPath, pnpmMajorVersion, shouldAllowBrowserProviderBuilds);
|
|
774
958
|
if (remainingPnpmOverrides) migratePnpmOverridesToWorkspaceYaml(projectPath, remainingPnpmOverrides);
|
|
775
959
|
if (shouldAddPnpmWorkspaceVitePlusOverride) migratePnpmOverridesToWorkspaceYaml(projectPath, { [VITE_PLUS_NAME]: VITE_PLUS_VERSION });
|
|
776
960
|
if (packageManager === PackageManager.yarn) rewriteYarnrcYml(projectPath);
|
|
961
|
+
else if (packageManager === PackageManager.bun) ensureBunfigPeerSuppression(projectPath);
|
|
777
962
|
if (extractedStagedConfig) {
|
|
778
963
|
if (mergeStagedConfigToViteConfig(projectPath, extractedStagedConfig, silent, report)) removeLintStagedFromPackageJson(packageJsonPath);
|
|
779
964
|
}
|
|
@@ -785,6 +970,7 @@ function rewriteStandaloneProject(projectPath, workspaceInfo, skipStagedMigratio
|
|
|
785
970
|
injectFmtDefaults(projectPath, silent, report);
|
|
786
971
|
mergeTsdownConfigFile(projectPath, silent, report);
|
|
787
972
|
rewriteAllImports(projectPath, silent, report);
|
|
973
|
+
wrapLazyPluginsInViteConfig(projectPath, silent, report);
|
|
788
974
|
setPackageManager(projectPath, workspaceInfo.downloadPackageManager);
|
|
789
975
|
}
|
|
790
976
|
/**
|
|
@@ -793,15 +979,17 @@ function rewriteStandaloneProject(projectPath, workspaceInfo, skipStagedMigratio
|
|
|
793
979
|
*/
|
|
794
980
|
function rewriteMonorepo(workspaceInfo, skipStagedMigration, silent = false, report) {
|
|
795
981
|
const catalogDependencyResolver = createCatalogDependencyResolver(workspaceInfo.rootDir, workspaceInfo.packageManager);
|
|
796
|
-
|
|
982
|
+
const pnpmMajorVersion = pnpmMajor(workspaceInfo.downloadPackageManager.version);
|
|
983
|
+
const workspaceShouldAllowBrowserBuilds = workspaceUsesWebdriverio(workspaceInfo.rootDir, workspaceInfo.packages);
|
|
984
|
+
if (workspaceInfo.packageManager === PackageManager.pnpm) rewritePnpmWorkspaceYaml(workspaceInfo.rootDir, pnpmMajorVersion, workspaceShouldAllowBrowserBuilds);
|
|
797
985
|
else if (workspaceInfo.packageManager === PackageManager.yarn) rewriteYarnrcYml(workspaceInfo.rootDir);
|
|
798
986
|
else if (workspaceInfo.packageManager === PackageManager.bun) rewriteBunCatalog(workspaceInfo.rootDir);
|
|
799
|
-
rewriteRootWorkspacePackageJson(workspaceInfo.rootDir, workspaceInfo.packageManager, skipStagedMigration, catalogDependencyResolver, workspaceInfo.packages);
|
|
987
|
+
rewriteRootWorkspacePackageJson(workspaceInfo.rootDir, workspaceInfo.packageManager, skipStagedMigration, catalogDependencyResolver, workspaceInfo.packages, pnpmMajorVersion, workspaceShouldAllowBrowserBuilds);
|
|
800
988
|
const workspaceContext = {
|
|
801
989
|
rootDir: workspaceInfo.rootDir,
|
|
802
990
|
packages: workspaceInfo.packages
|
|
803
991
|
};
|
|
804
|
-
for (const pkg of workspaceInfo.packages) rewriteMonorepoProject(path.join(workspaceInfo.rootDir, pkg.path), workspaceInfo.packageManager, skipStagedMigration, silent, report, catalogDependencyResolver, workspaceContext);
|
|
992
|
+
for (const pkg of workspaceInfo.packages) rewriteMonorepoProject(path.join(workspaceInfo.rootDir, pkg.path), workspaceInfo.packageManager, skipStagedMigration, silent, report, catalogDependencyResolver, workspaceContext, true);
|
|
805
993
|
if (!skipStagedMigration) rewriteLintStagedConfigFile(workspaceInfo.rootDir, report);
|
|
806
994
|
cleanupDeprecatedTsconfigOptions(workspaceInfo.rootDir, silent, report);
|
|
807
995
|
rewriteTsconfigTypes(workspaceInfo.rootDir, silent, report);
|
|
@@ -810,6 +998,8 @@ function rewriteMonorepo(workspaceInfo, skipStagedMigration, silent = false, rep
|
|
|
810
998
|
injectFmtDefaults(workspaceInfo.rootDir, silent, report);
|
|
811
999
|
mergeTsdownConfigFile(workspaceInfo.rootDir, silent, report);
|
|
812
1000
|
rewriteAllImports(workspaceInfo.rootDir, silent, report);
|
|
1001
|
+
wrapLazyPluginsInViteConfig(workspaceInfo.rootDir, silent, report);
|
|
1002
|
+
for (const pkg of workspaceInfo.packages) wrapLazyPluginsInViteConfig(path.join(workspaceInfo.rootDir, pkg.path), silent, report);
|
|
813
1003
|
setPackageManager(workspaceInfo.rootDir, workspaceInfo.downloadPackageManager);
|
|
814
1004
|
}
|
|
815
1005
|
/**
|
|
@@ -821,32 +1011,41 @@ function rewriteMonorepo(workspaceInfo, skipStagedMigration, silent = false, rep
|
|
|
821
1011
|
* workspace root (paths in `packages` are relative to it); `packages`
|
|
822
1012
|
* is the workspace package list.
|
|
823
1013
|
*/
|
|
824
|
-
function rewriteMonorepoProject(projectPath, packageManager, skipStagedMigration, silent = false, report, catalogDependencyResolver, workspaceContext) {
|
|
1014
|
+
function rewriteMonorepoProject(projectPath, packageManager, skipStagedMigration, silent = false, report, catalogDependencyResolver, workspaceContext, deferLazyPluginWrapping = false) {
|
|
825
1015
|
cleanupDeprecatedTsconfigOptions(projectPath, silent, report);
|
|
826
1016
|
rewriteTsconfigTypes(projectPath, silent, report);
|
|
827
1017
|
mergeViteConfigFiles(projectPath, silent, report, workspaceContext?.packages, workspaceContext?.rootDir);
|
|
828
1018
|
mergeTsdownConfigFile(projectPath, silent, report);
|
|
829
1019
|
const packageJsonPath = path.join(projectPath, "package.json");
|
|
830
1020
|
if (!fs.existsSync(packageJsonPath)) return;
|
|
1021
|
+
const yarnHoisting = packageManager === PackageManager.yarn ? findYarnWorkspaceHoisting(workspaceContext?.rootDir ?? projectPath) : void 0;
|
|
831
1022
|
let extractedStagedConfig = null;
|
|
832
1023
|
editJsonFile(packageJsonPath, (pkg) => {
|
|
833
|
-
extractedStagedConfig = rewritePackageJson(pkg, packageManager, true, skipStagedMigration, catalogDependencyResolver);
|
|
1024
|
+
extractedStagedConfig = rewritePackageJson(pkg, packageManager, true, skipStagedMigration, catalogDependencyResolver, usesVitestBrowserMode(projectPath), collectProviderSourceModes(projectPath));
|
|
1025
|
+
if (yarnHoisting && path.resolve(projectPath) !== yarnHoisting.rootDir && pkg.devDependencies?.["vite-plus"]) applyYarnWorkspaceHoistingFix(pkg, yarnHoisting.limit, yarnHoisting.nodeLinker, path.relative(yarnHoisting.rootDir, projectPath) || projectPath, report);
|
|
834
1026
|
return pkg;
|
|
835
1027
|
});
|
|
836
1028
|
if (extractedStagedConfig) {
|
|
837
1029
|
if (mergeStagedConfigToViteConfig(projectPath, extractedStagedConfig, silent, report)) removeLintStagedFromPackageJson(packageJsonPath);
|
|
838
1030
|
}
|
|
1031
|
+
if (!deferLazyPluginWrapping) wrapLazyPluginsInViteConfig(projectPath, silent, report);
|
|
839
1032
|
}
|
|
840
1033
|
/**
|
|
841
1034
|
* Rewrite pnpm-workspace.yaml to add vite-plus dependencies
|
|
842
1035
|
* @param projectPath - The path to the project
|
|
843
1036
|
*/
|
|
844
|
-
function rewritePnpmWorkspaceYaml(projectPath) {
|
|
1037
|
+
function rewritePnpmWorkspaceYaml(projectPath, pnpmMajorVersion, shouldAllowBrowserBuilds) {
|
|
845
1038
|
const pnpmWorkspaceYamlPath = path.join(projectPath, "pnpm-workspace.yaml");
|
|
846
1039
|
if (!fs.existsSync(pnpmWorkspaceYamlPath)) fs.writeFileSync(pnpmWorkspaceYamlPath, "");
|
|
847
1040
|
editYamlFile(pnpmWorkspaceYamlPath, (doc) => {
|
|
848
1041
|
rewriteCatalog(doc);
|
|
1042
|
+
if (pnpmMajorVersion !== void 0) applyBuildAllowanceToWorkspaceYaml(doc, pnpmMajorVersion, shouldAllowBrowserBuilds);
|
|
849
1043
|
const overrides = doc.getIn(["overrides"]);
|
|
1044
|
+
pruneYamlMapLegacyWrapperAliases(overrides);
|
|
1045
|
+
if (overrides instanceof import_dist.YAMLMap) {
|
|
1046
|
+
const keysSnapshot = overrides.items.map((item) => item.key);
|
|
1047
|
+
for (const keyNode of keysSnapshot) if (shouldDropProviderOverrideKey(keyNode instanceof import_dist.Scalar ? String(keyNode.value ?? "") : String(keyNode ?? ""))) overrides.delete(keyNode);
|
|
1048
|
+
}
|
|
850
1049
|
for (const key of Object.keys(VITE_PLUS_OVERRIDE_PACKAGES)) {
|
|
851
1050
|
const version = getCatalogDependencySpec(getYamlMapScalarStringValue(overrides, key), VITE_PLUS_OVERRIDE_PACKAGES[key], true);
|
|
852
1051
|
doc.setIn(["overrides", scalarString(key)], scalarString(version));
|
|
@@ -874,7 +1073,8 @@ function rewritePnpmWorkspaceYaml(projectPath) {
|
|
|
874
1073
|
"oxlint-tsgolint",
|
|
875
1074
|
"@oxlint-tsgolint/*",
|
|
876
1075
|
"oxfmt",
|
|
877
|
-
"@oxfmt/*"
|
|
1076
|
+
"@oxfmt/*",
|
|
1077
|
+
...VITEST_AGE_GATE_EXEMPT_PACKAGES
|
|
878
1078
|
];
|
|
879
1079
|
let minimumReleaseAgeExclude = doc.getIn(["minimumReleaseAgeExclude"]);
|
|
880
1080
|
if (!minimumReleaseAgeExclude) minimumReleaseAgeExclude = new import_dist.YAMLSeq();
|
|
@@ -890,9 +1090,10 @@ function rewritePnpmWorkspaceYaml(projectPath) {
|
|
|
890
1090
|
* moved to pnpm-workspace.yaml.
|
|
891
1091
|
*/
|
|
892
1092
|
function cleanupPnpmOverridesForWorkspaceYaml(pkg, overrideKeys) {
|
|
1093
|
+
dropRemovePackageOverrideKeys(pkg.pnpm?.overrides);
|
|
893
1094
|
const catalogOverrides = {};
|
|
894
1095
|
const overrides = pkg.pnpm?.overrides;
|
|
895
|
-
for (const key of [...overrideKeys, ...
|
|
1096
|
+
for (const key of [...overrideKeys, ...PROVIDER_OVERRIDE_DROP_NAMES]) {
|
|
896
1097
|
const value = overrides?.[key];
|
|
897
1098
|
if (value) {
|
|
898
1099
|
if (overrideKeys.includes(key) && value.startsWith("catalog:")) catalogOverrides[key] = value;
|
|
@@ -925,6 +1126,65 @@ function migratePnpmOverridesToWorkspaceYaml(projectPath, overrides) {
|
|
|
925
1126
|
for (const [key, value] of Object.entries(overrides)) doc.setIn(["overrides", scalarString(key)], scalarString(value));
|
|
926
1127
|
});
|
|
927
1128
|
}
|
|
1129
|
+
function hasOwnWebdriverioDependency(pkg) {
|
|
1130
|
+
for (const name of WEBDRIVERIO_ALLOW_SIGNAL_DEPS) if (pkg.dependencies?.[name] ?? pkg.devDependencies?.[name] ?? pkg.optionalDependencies?.[name] ?? pkg.peerDependencies?.[name]) return true;
|
|
1131
|
+
return false;
|
|
1132
|
+
}
|
|
1133
|
+
function workspaceUsesWebdriverio(rootDir, packages) {
|
|
1134
|
+
const rootPkg = readPackageJsonIfExists(path.join(rootDir, "package.json"));
|
|
1135
|
+
if (rootPkg && hasOwnWebdriverioDependency(rootPkg)) return true;
|
|
1136
|
+
if (usesWebdriverioProvider(rootDir)) return true;
|
|
1137
|
+
if (!packages) return false;
|
|
1138
|
+
for (const pkg of packages) {
|
|
1139
|
+
const packageDir = path.join(rootDir, pkg.path);
|
|
1140
|
+
const subPkg = readPackageJsonIfExists(path.join(packageDir, "package.json"));
|
|
1141
|
+
if (subPkg && hasOwnWebdriverioDependency(subPkg)) return true;
|
|
1142
|
+
if (usesWebdriverioProvider(packageDir)) return true;
|
|
1143
|
+
}
|
|
1144
|
+
return false;
|
|
1145
|
+
}
|
|
1146
|
+
function readPackageJsonIfExists(packageJsonPath) {
|
|
1147
|
+
if (!fs.existsSync(packageJsonPath)) return;
|
|
1148
|
+
try {
|
|
1149
|
+
return readJsonFile(packageJsonPath);
|
|
1150
|
+
} catch {
|
|
1151
|
+
return;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
function pnpmMajor(version) {
|
|
1155
|
+
const coerced = version ? import_semver.default.coerce(version)?.version : void 0;
|
|
1156
|
+
return coerced ? import_semver.default.major(coerced) : void 0;
|
|
1157
|
+
}
|
|
1158
|
+
function applyBuildAllowanceToPackageJsonPnpm(pnpm, major, shouldAllow) {
|
|
1159
|
+
if (major >= 10) {
|
|
1160
|
+
if (shouldAllow) for (const name of BROWSER_PROVIDER_POSTINSTALL_PACKAGES) (pnpm.allowBuilds ??= {})[name] = true;
|
|
1161
|
+
} else if (shouldAllow) {
|
|
1162
|
+
const list = pnpm.onlyBuiltDependencies ?? [];
|
|
1163
|
+
const existing = new Set(list);
|
|
1164
|
+
for (const name of BROWSER_PROVIDER_POSTINSTALL_PACKAGES) if (!existing.has(name)) {
|
|
1165
|
+
list.push(name);
|
|
1166
|
+
existing.add(name);
|
|
1167
|
+
}
|
|
1168
|
+
pnpm.onlyBuiltDependencies = list;
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
function applyBuildAllowanceToWorkspaceYaml(doc, major, shouldAllow) {
|
|
1172
|
+
if (major >= 10) {
|
|
1173
|
+
if (shouldAllow) {
|
|
1174
|
+
const existing = doc.getIn(["allowBuilds"]);
|
|
1175
|
+
const isNew = !(existing instanceof import_dist.YAMLMap);
|
|
1176
|
+
const allowBuilds = isNew ? new import_dist.YAMLMap() : existing;
|
|
1177
|
+
for (const name of BROWSER_PROVIDER_POSTINSTALL_PACKAGES) allowBuilds.set(scalarString(name), new import_dist.Scalar(true));
|
|
1178
|
+
if (isNew) doc.setIn(["allowBuilds"], allowBuilds);
|
|
1179
|
+
}
|
|
1180
|
+
} else if (shouldAllow) {
|
|
1181
|
+
let onlyBuiltDependencies = doc.getIn(["onlyBuiltDependencies"]);
|
|
1182
|
+
if (!(onlyBuiltDependencies instanceof import_dist.YAMLSeq)) onlyBuiltDependencies = new import_dist.YAMLSeq();
|
|
1183
|
+
const existing = new Set(onlyBuiltDependencies.items.map((n) => n.value));
|
|
1184
|
+
for (const name of BROWSER_PROVIDER_POSTINSTALL_PACKAGES) if (!existing.has(name)) onlyBuiltDependencies.add(scalarString(name));
|
|
1185
|
+
doc.setIn(["onlyBuiltDependencies"], onlyBuiltDependencies);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
928
1188
|
/**
|
|
929
1189
|
* Remove only Vite-managed entries from peerDependencyRules, preserving custom ones.
|
|
930
1190
|
*/
|
|
@@ -943,11 +1203,78 @@ function cleanupPeerDependencyRules(peerDependencyRules, overrideKeys) {
|
|
|
943
1203
|
* Rewrite .yarnrc.yml to add vite-plus dependencies
|
|
944
1204
|
* @param projectPath - The path to the project
|
|
945
1205
|
*/
|
|
1206
|
+
function readYarnrcValue(dir, key) {
|
|
1207
|
+
const yarnrcYmlPath = path.join(dir, ".yarnrc.yml");
|
|
1208
|
+
if (!fs.existsSync(yarnrcYmlPath)) return;
|
|
1209
|
+
try {
|
|
1210
|
+
const value = readYamlFile(yarnrcYmlPath)?.[key];
|
|
1211
|
+
return typeof value === "string" ? value : void 0;
|
|
1212
|
+
} catch {
|
|
1213
|
+
return;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
function resolveEffectiveYarnConfigValue(workspaceRootDir, key, envVar) {
|
|
1217
|
+
const fromEnv = process.env[envVar]?.trim();
|
|
1218
|
+
if (fromEnv) return fromEnv;
|
|
1219
|
+
let dir = path.resolve(workspaceRootDir);
|
|
1220
|
+
for (;;) {
|
|
1221
|
+
const value = readYarnrcValue(dir, key);
|
|
1222
|
+
if (value !== void 0) return value;
|
|
1223
|
+
const parent = path.dirname(dir);
|
|
1224
|
+
if (parent === dir) break;
|
|
1225
|
+
dir = parent;
|
|
1226
|
+
}
|
|
1227
|
+
const home = os.homedir();
|
|
1228
|
+
return home ? readYarnrcValue(home, key) : void 0;
|
|
1229
|
+
}
|
|
1230
|
+
function dirIsWorkspaceRoot(dir) {
|
|
1231
|
+
const pkgJsonPath = path.join(dir, "package.json");
|
|
1232
|
+
if (!fs.existsSync(pkgJsonPath)) return false;
|
|
1233
|
+
try {
|
|
1234
|
+
return readJsonFile(pkgJsonPath).workspaces != null;
|
|
1235
|
+
} catch {
|
|
1236
|
+
return false;
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
function findYarnWorkspaceHoisting(startDir) {
|
|
1240
|
+
let dir = path.resolve(startDir);
|
|
1241
|
+
for (;;) {
|
|
1242
|
+
if (dirIsWorkspaceRoot(dir)) return {
|
|
1243
|
+
rootDir: dir,
|
|
1244
|
+
limit: resolveEffectiveYarnConfigValue(dir, "nmHoistingLimits", "YARN_NM_HOISTING_LIMITS"),
|
|
1245
|
+
nodeLinker: resolveEffectiveYarnConfigValue(dir, "nodeLinker", "YARN_NODE_LINKER")
|
|
1246
|
+
};
|
|
1247
|
+
const parent = path.dirname(dir);
|
|
1248
|
+
if (parent === dir) return;
|
|
1249
|
+
dir = parent;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
function setYarnWorkspaceHoistingOptOut(pkg) {
|
|
1253
|
+
if (pkg.installConfig?.hoistingLimits !== void 0) return;
|
|
1254
|
+
pkg.installConfig = {
|
|
1255
|
+
...pkg.installConfig,
|
|
1256
|
+
hoistingLimits: "none"
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
function applyYarnWorkspaceHoistingFix(pkg, rootLimit, nodeLinker, workspaceLabel, report) {
|
|
1260
|
+
if (nodeLinker !== "node-modules") return;
|
|
1261
|
+
if (rootLimit === "workspaces" && pkg.installConfig?.hoistingLimits === void 0) {
|
|
1262
|
+
setYarnWorkspaceHoistingOptOut(pkg);
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1265
|
+
const explicit = pkg.installConfig?.hoistingLimits;
|
|
1266
|
+
if (rootLimit === "dependencies" || explicit === "workspaces" || explicit === "dependencies") warnMigration(`Yarn workspace "${workspaceLabel}" isolates dependency hoisting (hoistingLimits: ${explicit ?? rootLimit}), so it keeps its own \`vitest\`/\`vite-plus\` copy and \`vp test\` may crash with a split \`@vitest/runner\`. Dedupe them to a single copy — relax this workspace's hoisting isolation or pin one \`vitest\` for the workspace.`, report);
|
|
1267
|
+
}
|
|
946
1268
|
function rewriteYarnrcYml(projectPath) {
|
|
947
1269
|
const yarnrcYmlPath = path.join(projectPath, ".yarnrc.yml");
|
|
948
1270
|
if (!fs.existsSync(yarnrcYmlPath)) fs.writeFileSync(yarnrcYmlPath, "");
|
|
949
1271
|
editYamlFile(yarnrcYmlPath, (doc) => {
|
|
950
1272
|
if (!doc.has("nodeLinker")) doc.set("nodeLinker", "node-modules");
|
|
1273
|
+
let npmPreapprovedPackages = doc.getIn(["npmPreapprovedPackages"]);
|
|
1274
|
+
if (!npmPreapprovedPackages) npmPreapprovedPackages = new import_dist.YAMLSeq();
|
|
1275
|
+
const existingPreapproved = new Set(npmPreapprovedPackages.items.map((n) => n.value));
|
|
1276
|
+
for (const pkg of VITEST_AGE_GATE_EXEMPT_PACKAGES) if (!existingPreapproved.has(pkg)) npmPreapprovedPackages.add(scalarString(pkg));
|
|
1277
|
+
doc.setIn(["npmPreapprovedPackages"], npmPreapprovedPackages);
|
|
951
1278
|
rewriteCatalog(doc);
|
|
952
1279
|
});
|
|
953
1280
|
}
|
|
@@ -1005,6 +1332,19 @@ function getYamlMapScalarStringValue(map, key) {
|
|
|
1005
1332
|
if (!(map instanceof import_dist.YAMLMap)) return;
|
|
1006
1333
|
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;
|
|
1007
1334
|
}
|
|
1335
|
+
function pruneYamlMapLegacyWrapperAliases(map) {
|
|
1336
|
+
if (!(map instanceof import_dist.YAMLMap)) return;
|
|
1337
|
+
const stale = [];
|
|
1338
|
+
for (const item of map.items) {
|
|
1339
|
+
const value = item.value instanceof import_dist.Scalar ? item.value.value : void 0;
|
|
1340
|
+
if (typeof value === "string" && isLegacyWrapperSpec(value) && item.key instanceof import_dist.Scalar) stale.push({
|
|
1341
|
+
key: item.key,
|
|
1342
|
+
fallback: LEGACY_WRAPPER_FALLBACK_VERSIONS[item.key.value]
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
for (const { key, fallback } of stale) if (fallback !== void 0) map.set(key, scalarString(fallback));
|
|
1346
|
+
else map.delete(key);
|
|
1347
|
+
}
|
|
1008
1348
|
function rewriteCatalog(doc) {
|
|
1009
1349
|
for (const [key, value] of Object.entries(VITE_PLUS_OVERRIDE_PACKAGES)) {
|
|
1010
1350
|
if (value.startsWith("file:")) continue;
|
|
@@ -1015,6 +1355,7 @@ function rewriteCatalog(doc) {
|
|
|
1015
1355
|
const path = ["catalog", name];
|
|
1016
1356
|
if (doc.hasIn(path)) doc.deleteIn(path);
|
|
1017
1357
|
}
|
|
1358
|
+
pruneYamlMapLegacyWrapperAliases(doc.getIn(["catalog"]));
|
|
1018
1359
|
const catalogs = doc.getIn(["catalogs"]);
|
|
1019
1360
|
if (!(catalogs instanceof import_dist.YAMLMap)) return;
|
|
1020
1361
|
for (const item of catalogs.items) {
|
|
@@ -1042,6 +1383,7 @@ function rewriteCatalog(doc) {
|
|
|
1042
1383
|
];
|
|
1043
1384
|
if (doc.hasIn(catalogPath)) doc.deleteIn(catalogPath);
|
|
1044
1385
|
}
|
|
1386
|
+
pruneYamlMapLegacyWrapperAliases(item.value);
|
|
1045
1387
|
}
|
|
1046
1388
|
}
|
|
1047
1389
|
function rewriteCatalogObject(catalog, addMissing) {
|
|
@@ -1056,6 +1398,34 @@ function rewriteCatalogsObject(catalogs) {
|
|
|
1056
1398
|
for (const catalog of Object.values(catalogs)) rewriteCatalogObject(catalog, false);
|
|
1057
1399
|
}
|
|
1058
1400
|
/**
|
|
1401
|
+
* Bun rejects vitest@4.1.9's `vite^6/^7/^8` peer-dep when the user's project
|
|
1402
|
+
* overrides `vite` to `@voidzero-dev/vite-plus-core` (whose package.json version
|
|
1403
|
+
* does not match those ranges). pnpm/yarn/npm all tolerate this redirect; bun
|
|
1404
|
+
* does not, and there is no `peerDependencyRules`-style escape hatch — only the
|
|
1405
|
+
* `[install] peer = false` setting in `bunfig.toml`.
|
|
1406
|
+
*
|
|
1407
|
+
* `vite-plus`/`@voidzero-dev/vite-plus-core` already provide the vite surface
|
|
1408
|
+
* the user needs, so disabling bun's auto-install of *missing* peers is safe in
|
|
1409
|
+
* this configuration: any vitest peer that's not already pulled in transitively
|
|
1410
|
+
* (jsdom, happy-dom, etc.) is marked optional upstream anyway.
|
|
1411
|
+
*
|
|
1412
|
+
* Writes/merges `bunfig.toml` at `projectPath` so the suppression applies on
|
|
1413
|
+
* the migration's reinstall AND every subsequent `bun install` the user runs.
|
|
1414
|
+
*/
|
|
1415
|
+
function ensureBunfigPeerSuppression(projectPath) {
|
|
1416
|
+
const bunfigPath = path.join(projectPath, "bunfig.toml");
|
|
1417
|
+
const block = "[install]\npeer = false\n";
|
|
1418
|
+
if (!fs.existsSync(bunfigPath)) {
|
|
1419
|
+
fs.writeFileSync(bunfigPath, block);
|
|
1420
|
+
return;
|
|
1421
|
+
}
|
|
1422
|
+
const existing = fs.readFileSync(bunfigPath, "utf8");
|
|
1423
|
+
if (/^\s*peer\s*=\s*(true|false)\s*$/m.test(existing)) return;
|
|
1424
|
+
const installSectionRe = /^\[install\][^[]*/m;
|
|
1425
|
+
const next = installSectionRe.test(existing) ? existing.replace(installSectionRe, (section) => `${section.trimEnd()}\npeer = false\n`) : `${existing.trimEnd()}\n\n${block}`;
|
|
1426
|
+
fs.writeFileSync(bunfigPath, next);
|
|
1427
|
+
}
|
|
1428
|
+
/**
|
|
1059
1429
|
* Write catalog entries to root package.json for bun.
|
|
1060
1430
|
* Bun stores catalogs in package.json under the `catalog` key,
|
|
1061
1431
|
* unlike pnpm which uses pnpm-workspace.yaml.
|
|
@@ -1069,30 +1439,54 @@ function rewriteBunCatalog(projectPath) {
|
|
|
1069
1439
|
const useWorkspacesCatalog = workspacesObj?.catalog != null || pkg.catalog == null && workspacesObj?.catalogs != null;
|
|
1070
1440
|
const catalog = { ...useWorkspacesCatalog ? workspacesObj?.catalog : pkg.catalog };
|
|
1071
1441
|
rewriteCatalogObject(catalog, true);
|
|
1442
|
+
pruneLegacyWrapperAliases(catalog);
|
|
1072
1443
|
if (useWorkspacesCatalog) {
|
|
1073
1444
|
workspacesObj.catalog = catalog;
|
|
1074
|
-
if (pkg.catalog)
|
|
1445
|
+
if (pkg.catalog) {
|
|
1446
|
+
rewriteCatalogObject(pkg.catalog, false);
|
|
1447
|
+
pruneLegacyWrapperAliases(pkg.catalog);
|
|
1448
|
+
}
|
|
1075
1449
|
} else {
|
|
1076
1450
|
pkg.catalog = catalog;
|
|
1077
|
-
if (workspacesObj?.catalog)
|
|
1451
|
+
if (workspacesObj?.catalog) {
|
|
1452
|
+
rewriteCatalogObject(workspacesObj.catalog, false);
|
|
1453
|
+
pruneLegacyWrapperAliases(workspacesObj.catalog);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
if (workspacesObj?.catalogs) {
|
|
1457
|
+
rewriteCatalogsObject(workspacesObj.catalogs);
|
|
1458
|
+
for (const named of Object.values(workspacesObj.catalogs)) pruneLegacyWrapperAliases(named);
|
|
1459
|
+
}
|
|
1460
|
+
if (pkg.catalogs) {
|
|
1461
|
+
rewriteCatalogsObject(pkg.catalogs);
|
|
1462
|
+
for (const named of Object.values(pkg.catalogs)) pruneLegacyWrapperAliases(named);
|
|
1078
1463
|
}
|
|
1079
|
-
if (workspacesObj?.catalogs) rewriteCatalogsObject(workspacesObj.catalogs);
|
|
1080
|
-
if (pkg.catalogs) rewriteCatalogsObject(pkg.catalogs);
|
|
1081
1464
|
const overrides = { ...pkg.overrides };
|
|
1082
|
-
|
|
1465
|
+
pruneLegacyWrapperAliases(overrides);
|
|
1466
|
+
for (const [key, value] of Object.entries(VITE_PLUS_OVERRIDE_PACKAGES)) {
|
|
1467
|
+
const current = overrides[key];
|
|
1468
|
+
if (current !== void 0 && typeof current !== "string") continue;
|
|
1469
|
+
overrides[key] = getCatalogDependencySpec(current, value, true);
|
|
1470
|
+
}
|
|
1083
1471
|
pkg.overrides = overrides;
|
|
1084
1472
|
return pkg;
|
|
1085
1473
|
});
|
|
1474
|
+
ensureBunfigPeerSuppression(projectPath);
|
|
1086
1475
|
}
|
|
1087
1476
|
/**
|
|
1088
1477
|
* Rewrite root workspace package.json to add vite-plus dependencies
|
|
1089
1478
|
* @param projectPath - The path to the project
|
|
1090
1479
|
*/
|
|
1091
|
-
function rewriteRootWorkspacePackageJson(projectPath, packageManager, skipStagedMigration, catalogDependencyResolver, packages) {
|
|
1480
|
+
function rewriteRootWorkspacePackageJson(projectPath, packageManager, skipStagedMigration, catalogDependencyResolver, packages, pnpmMajorVersion, shouldAllowBrowserBuilds = false) {
|
|
1092
1481
|
const packageJsonPath = path.join(projectPath, "package.json");
|
|
1093
1482
|
if (!fs.existsSync(packageJsonPath)) return;
|
|
1094
1483
|
let remainingPnpmOverrides;
|
|
1095
1484
|
editJsonFile(packageJsonPath, (pkg) => {
|
|
1485
|
+
pruneLegacyWrapperAliases(pkg.resolutions);
|
|
1486
|
+
pruneLegacyWrapperAliases(pkg.overrides);
|
|
1487
|
+
pruneLegacyWrapperAliases(pkg.pnpm?.overrides);
|
|
1488
|
+
dropRemovePackageOverrideKeys(pkg.resolutions);
|
|
1489
|
+
dropRemovePackageOverrideKeys(pkg.overrides);
|
|
1096
1490
|
if (packageManager === PackageManager.yarn) pkg.resolutions = {
|
|
1097
1491
|
...pkg.resolutions,
|
|
1098
1492
|
...VITE_PLUS_OVERRIDE_PACKAGES
|
|
@@ -1101,24 +1495,31 @@ function rewriteRootWorkspacePackageJson(projectPath, packageManager, skipStaged
|
|
|
1101
1495
|
...pkg.overrides,
|
|
1102
1496
|
...VITE_PLUS_OVERRIDE_PACKAGES
|
|
1103
1497
|
};
|
|
1104
|
-
else if (packageManager === PackageManager.bun)
|
|
1498
|
+
else if (packageManager === PackageManager.bun) pkg.devDependencies = {
|
|
1499
|
+
...pkg.devDependencies,
|
|
1500
|
+
vite: getCatalogDependencySpec(pkg.devDependencies?.vite, VITE_PLUS_OVERRIDE_PACKAGES.vite, true)
|
|
1501
|
+
};
|
|
1502
|
+
else if (packageManager === PackageManager.pnpm) {
|
|
1105
1503
|
const overrideKeys = Object.keys(VITE_PLUS_OVERRIDE_PACKAGES);
|
|
1106
|
-
if (isForceOverrideMode())
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
...pkg.pnpm
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1504
|
+
if (isForceOverrideMode()) {
|
|
1505
|
+
dropRemovePackageOverrideKeys(pkg.pnpm?.overrides);
|
|
1506
|
+
pkg.pnpm = {
|
|
1507
|
+
...pkg.pnpm,
|
|
1508
|
+
overrides: {
|
|
1509
|
+
...pkg.pnpm?.overrides,
|
|
1510
|
+
...VITE_PLUS_OVERRIDE_PACKAGES,
|
|
1511
|
+
[VITE_PLUS_NAME]: VITE_PLUS_VERSION
|
|
1512
|
+
}
|
|
1513
|
+
};
|
|
1514
|
+
} else {
|
|
1515
|
+
for (const key of [...overrideKeys, ...PROVIDER_OVERRIDE_DROP_NAMES]) if (pkg.resolutions?.[key]) delete pkg.resolutions[key];
|
|
1116
1516
|
remainingPnpmOverrides = cleanupPnpmOverridesForWorkspaceYaml(pkg, overrideKeys);
|
|
1117
1517
|
}
|
|
1118
1518
|
for (const key in pkg.pnpm?.overrides) if (key.includes(">")) {
|
|
1119
1519
|
const splits = key.split(">");
|
|
1120
1520
|
if (splits[splits.length - 1].trim() === "vite") delete pkg.pnpm.overrides[key];
|
|
1121
1521
|
}
|
|
1522
|
+
if (pnpmMajorVersion !== void 0 && pkg.pnpm) applyBuildAllowanceToPackageJsonPnpm(pkg.pnpm, pnpmMajorVersion, shouldAllowBrowserBuilds);
|
|
1122
1523
|
}
|
|
1123
1524
|
if (!pkg.devDependencies?.["vite-plus"]) pkg.devDependencies = {
|
|
1124
1525
|
...pkg.devDependencies,
|
|
@@ -1130,7 +1531,7 @@ function rewriteRootWorkspacePackageJson(projectPath, packageManager, skipStaged
|
|
|
1130
1531
|
rewriteMonorepoProject(projectPath, packageManager, skipStagedMigration, void 0, void 0, catalogDependencyResolver, packages ? {
|
|
1131
1532
|
rootDir: projectPath,
|
|
1132
1533
|
packages
|
|
1133
|
-
} : void 0);
|
|
1534
|
+
} : void 0, true);
|
|
1134
1535
|
}
|
|
1135
1536
|
const RULES_YAML_PATH = path.join(rulesDir, "vite-tools.yml");
|
|
1136
1537
|
const PREPARE_RULES_YAML_PATH = path.join(rulesDir, "vite-prepare.yml");
|
|
@@ -1151,7 +1552,401 @@ function readPrepareRulesYaml() {
|
|
|
1151
1552
|
cachedPrepareRulesYaml ??= fs.readFileSync(PREPARE_RULES_YAML_PATH, "utf8");
|
|
1152
1553
|
return cachedPrepareRulesYaml;
|
|
1153
1554
|
}
|
|
1154
|
-
function
|
|
1555
|
+
function getCoreMigrationProjectPaths(workspaceInfo) {
|
|
1556
|
+
return [workspaceInfo.rootDir, ...(workspaceInfo.packages ?? []).map((pkg) => path.join(workspaceInfo.rootDir, pkg.path))];
|
|
1557
|
+
}
|
|
1558
|
+
function hasCorePackageScriptRewrites(projectPath) {
|
|
1559
|
+
const packageJsonPath = path.join(projectPath, "package.json");
|
|
1560
|
+
if (!fs.existsSync(packageJsonPath)) return false;
|
|
1561
|
+
const pkg = readJsonFile(packageJsonPath);
|
|
1562
|
+
if (!pkg.scripts) return false;
|
|
1563
|
+
return !!rewriteScripts(JSON.stringify(pkg.scripts), getScriptRulesYaml(true));
|
|
1564
|
+
}
|
|
1565
|
+
function rewriteCorePackageScripts(projectPath) {
|
|
1566
|
+
const packageJsonPath = path.join(projectPath, "package.json");
|
|
1567
|
+
if (!fs.existsSync(packageJsonPath)) return false;
|
|
1568
|
+
let changed = false;
|
|
1569
|
+
editJsonFile(packageJsonPath, (pkg) => {
|
|
1570
|
+
if (!pkg.scripts) return;
|
|
1571
|
+
const updated = rewriteScripts(JSON.stringify(pkg.scripts), getScriptRulesYaml(true));
|
|
1572
|
+
if (!updated) return;
|
|
1573
|
+
pkg.scripts = JSON.parse(updated);
|
|
1574
|
+
changed = true;
|
|
1575
|
+
return pkg;
|
|
1576
|
+
});
|
|
1577
|
+
return changed;
|
|
1578
|
+
}
|
|
1579
|
+
function detectPendingCoreMigration(workspaceInfo) {
|
|
1580
|
+
const projectPaths = getCoreMigrationProjectPaths(workspaceInfo);
|
|
1581
|
+
return {
|
|
1582
|
+
scripts: projectPaths.some((projectPath) => hasCorePackageScriptRewrites(projectPath)),
|
|
1583
|
+
tsconfigTypes: projectPaths.some((projectPath) => hasTsconfigTypesToRewrite(projectPath))
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
function finalizeCoreMigrationForExistingVitePlus(workspaceInfo, silent = false, report, pending = detectPendingCoreMigration(workspaceInfo)) {
|
|
1587
|
+
const projectPaths = getCoreMigrationProjectPaths(workspaceInfo);
|
|
1588
|
+
const result = {
|
|
1589
|
+
scripts: false,
|
|
1590
|
+
tsconfigTypes: false,
|
|
1591
|
+
imports: false
|
|
1592
|
+
};
|
|
1593
|
+
if (pending.scripts) for (const projectPath of projectPaths) result.scripts = rewriteCorePackageScripts(projectPath) || result.scripts;
|
|
1594
|
+
if (pending.tsconfigTypes) for (const projectPath of projectPaths) result.tsconfigTypes = rewriteTsconfigTypes(projectPath, silent, report) || result.tsconfigTypes;
|
|
1595
|
+
result.imports = rewriteAllImports(workspaceInfo.rootDir, silent, report);
|
|
1596
|
+
return result;
|
|
1597
|
+
}
|
|
1598
|
+
function getVitePlusOverridePackageName(dependencyName) {
|
|
1599
|
+
if (dependencyName === "vite") return "@voidzero-dev/vite-plus-core";
|
|
1600
|
+
if (dependencyName === "vitest") return "@voidzero-dev/vite-plus-test";
|
|
1601
|
+
}
|
|
1602
|
+
function isSemanticVitePlusOverrideSpec(dependencyName, spec) {
|
|
1603
|
+
if (!spec) return false;
|
|
1604
|
+
if (isLegacyWrapperSpec(spec)) return false;
|
|
1605
|
+
if (spec === VITE_PLUS_OVERRIDE_PACKAGES[dependencyName]) return true;
|
|
1606
|
+
const packageName = getVitePlusOverridePackageName(dependencyName);
|
|
1607
|
+
return packageName !== void 0 && spec.includes(packageName);
|
|
1608
|
+
}
|
|
1609
|
+
function overrideSpecSatisfiesVitePlus(dependencyName, spec, catalogDependencyResolver) {
|
|
1610
|
+
if (!spec) return false;
|
|
1611
|
+
if (isSemanticVitePlusOverrideSpec(dependencyName, spec)) return true;
|
|
1612
|
+
if (!spec.startsWith("catalog:")) return false;
|
|
1613
|
+
return isSemanticVitePlusOverrideSpec(dependencyName, catalogDependencyResolver?.(spec, dependencyName));
|
|
1614
|
+
}
|
|
1615
|
+
function overridesSatisfyVitePlus(overrides, catalogDependencyResolver) {
|
|
1616
|
+
return Object.keys(VITE_PLUS_OVERRIDE_PACKAGES).every((dependencyName) => overrideSpecSatisfiesVitePlus(dependencyName, overrides?.[dependencyName], catalogDependencyResolver));
|
|
1617
|
+
}
|
|
1618
|
+
function hasPackageManagerPin(pkg) {
|
|
1619
|
+
return Boolean(pkg.packageManager || pkg.devEngines?.packageManager);
|
|
1620
|
+
}
|
|
1621
|
+
function vitePlusDependencyNeedsConcreteVersion(pkg) {
|
|
1622
|
+
return [
|
|
1623
|
+
pkg.devDependencies,
|
|
1624
|
+
pkg.dependencies,
|
|
1625
|
+
pkg.optionalDependencies
|
|
1626
|
+
].some((dependencies) => dependencies?.["vite-plus"]?.startsWith("catalog:") ?? false);
|
|
1627
|
+
}
|
|
1628
|
+
function defaultCatalogVitePlusDependencyPending(pkg, catalogDependencyResolver) {
|
|
1629
|
+
return [
|
|
1630
|
+
pkg.devDependencies,
|
|
1631
|
+
pkg.dependencies,
|
|
1632
|
+
pkg.optionalDependencies
|
|
1633
|
+
].some((dependencies) => {
|
|
1634
|
+
const spec = dependencies?.[VITE_PLUS_NAME];
|
|
1635
|
+
if (spec !== "catalog:" && spec !== "catalog:default") return false;
|
|
1636
|
+
return catalogDependencyResolver?.(spec, VITE_PLUS_NAME) !== VITE_PLUS_VERSION;
|
|
1637
|
+
});
|
|
1638
|
+
}
|
|
1639
|
+
function pnpmPeerDependencyRulesSatisfyVitePlus(peerDependencyRules) {
|
|
1640
|
+
const overrideKeys = Object.keys(VITE_PLUS_OVERRIDE_PACKAGES);
|
|
1641
|
+
const allowAny = new Set(peerDependencyRules?.allowAny ?? []);
|
|
1642
|
+
const allowedVersions = peerDependencyRules?.allowedVersions ?? {};
|
|
1643
|
+
return overrideKeys.every((key) => allowAny.has(key) && allowedVersions[key] === "*");
|
|
1644
|
+
}
|
|
1645
|
+
function npmVitePlusManagedDependenciesPending(pkg) {
|
|
1646
|
+
const dependencyGroups = [
|
|
1647
|
+
pkg.devDependencies,
|
|
1648
|
+
pkg.dependencies,
|
|
1649
|
+
pkg.optionalDependencies
|
|
1650
|
+
];
|
|
1651
|
+
return Object.keys(VITE_PLUS_OVERRIDE_PACKAGES).some((dependencyName) => dependencyGroups.some((dependencies) => dependencies?.[dependencyName] !== void 0 && !overrideSpecSatisfiesVitePlus(dependencyName, dependencies[dependencyName])));
|
|
1652
|
+
}
|
|
1653
|
+
function readPnpmWorkspaceCatalogDependencyResolver(projectPath) {
|
|
1654
|
+
const pnpmWorkspaceYamlPath = path.join(projectPath, "pnpm-workspace.yaml");
|
|
1655
|
+
if (!fs.existsSync(pnpmWorkspaceYamlPath)) return;
|
|
1656
|
+
const doc = readYamlFile(pnpmWorkspaceYamlPath);
|
|
1657
|
+
return createCatalogDependencyResolverFromCatalogs(doc?.catalog, doc?.catalogs);
|
|
1658
|
+
}
|
|
1659
|
+
function readPnpmWorkspaceOverrides(projectPath) {
|
|
1660
|
+
const pnpmWorkspaceYamlPath = path.join(projectPath, "pnpm-workspace.yaml");
|
|
1661
|
+
if (!fs.existsSync(pnpmWorkspaceYamlPath)) return;
|
|
1662
|
+
return readYamlFile(pnpmWorkspaceYamlPath)?.overrides;
|
|
1663
|
+
}
|
|
1664
|
+
function readPnpmWorkspacePeerDependencyRules(projectPath) {
|
|
1665
|
+
const pnpmWorkspaceYamlPath = path.join(projectPath, "pnpm-workspace.yaml");
|
|
1666
|
+
if (!fs.existsSync(pnpmWorkspaceYamlPath)) return;
|
|
1667
|
+
return readYamlFile(pnpmWorkspaceYamlPath)?.peerDependencyRules;
|
|
1668
|
+
}
|
|
1669
|
+
function yarnrcSatisfiesVitePlus(projectPath) {
|
|
1670
|
+
const yarnrcYmlPath = path.join(projectPath, ".yarnrc.yml");
|
|
1671
|
+
if (!fs.existsSync(yarnrcYmlPath)) return false;
|
|
1672
|
+
const doc = readYamlFile(yarnrcYmlPath);
|
|
1673
|
+
return !!doc && Object.hasOwn(doc, "nodeLinker") && overridesSatisfyVitePlus(doc.catalog) && (VITE_PLUS_VERSION.startsWith("file:") || doc.catalog?.["vite-plus"] === VITE_PLUS_VERSION);
|
|
1674
|
+
}
|
|
1675
|
+
function ensurePnpmWorkspacePackages(projectPath, workspacePatterns) {
|
|
1676
|
+
if (workspacePatterns.length === 0) return false;
|
|
1677
|
+
const pnpmWorkspaceYamlPath = path.join(projectPath, "pnpm-workspace.yaml");
|
|
1678
|
+
let changed = false;
|
|
1679
|
+
editYamlFile(pnpmWorkspaceYamlPath, (doc) => {
|
|
1680
|
+
if (doc.has("packages")) return;
|
|
1681
|
+
const packages = new import_dist.YAMLSeq();
|
|
1682
|
+
for (const pattern of workspacePatterns) packages.add(scalarString(pattern));
|
|
1683
|
+
doc.set("packages", packages);
|
|
1684
|
+
changed = true;
|
|
1685
|
+
});
|
|
1686
|
+
return changed;
|
|
1687
|
+
}
|
|
1688
|
+
function readBunCatalogDependencyResolver(pkg) {
|
|
1689
|
+
const workspacesObj = pkg.workspaces && !Array.isArray(pkg.workspaces) ? pkg.workspaces : {};
|
|
1690
|
+
const fromWorkspaces = createCatalogDependencyResolverFromCatalogs(workspacesObj.catalog, workspacesObj.catalogs);
|
|
1691
|
+
const fromPkg = createCatalogDependencyResolverFromCatalogs(pkg.catalog, pkg.catalogs);
|
|
1692
|
+
return (catalogSpec, dependencyName) => fromWorkspaces(catalogSpec, dependencyName) ?? fromPkg(catalogSpec, dependencyName);
|
|
1693
|
+
}
|
|
1694
|
+
function detectVitePlusBootstrapPending(projectPath, packageManager) {
|
|
1695
|
+
const packageJsonPath = path.join(projectPath, "package.json");
|
|
1696
|
+
if (!fs.existsSync(packageJsonPath)) return false;
|
|
1697
|
+
const pkg = readJsonFile(packageJsonPath);
|
|
1698
|
+
if (!pkg.devDependencies?.["vite-plus"] || !hasPackageManagerPin(pkg)) return true;
|
|
1699
|
+
if (packageManager === void 0) return true;
|
|
1700
|
+
if (packageManager === PackageManager.yarn) return !overridesSatisfyVitePlus(pkg.resolutions) || !yarnrcSatisfiesVitePlus(projectPath);
|
|
1701
|
+
if (packageManager === PackageManager.npm) return vitePlusDependencyNeedsConcreteVersion(pkg) || !overridesSatisfyVitePlus(pkg.overrides) || npmVitePlusManagedDependenciesPending(pkg);
|
|
1702
|
+
if (packageManager === PackageManager.bun) return !overridesSatisfyVitePlus(pkg.overrides, readBunCatalogDependencyResolver(pkg));
|
|
1703
|
+
if (packageManager === PackageManager.pnpm) {
|
|
1704
|
+
if (pkg.pnpm) return vitePlusDependencyNeedsConcreteVersion(pkg) || !overridesSatisfyVitePlus(pkg.pnpm.overrides) || !pnpmPeerDependencyRulesSatisfyVitePlus(pkg.pnpm.peerDependencyRules);
|
|
1705
|
+
const resolver = readPnpmWorkspaceCatalogDependencyResolver(projectPath);
|
|
1706
|
+
return defaultCatalogVitePlusDependencyPending(pkg, resolver) || !overridesSatisfyVitePlus(readPnpmWorkspaceOverrides(projectPath), resolver) || !pnpmPeerDependencyRulesSatisfyVitePlus(readPnpmWorkspacePeerDependencyRules(projectPath));
|
|
1707
|
+
}
|
|
1708
|
+
return false;
|
|
1709
|
+
}
|
|
1710
|
+
function ensureVitePlusDependencySpecs(pkg, version) {
|
|
1711
|
+
let changed = false;
|
|
1712
|
+
if (version !== "catalog:") {
|
|
1713
|
+
const dependencyGroups = [
|
|
1714
|
+
pkg.devDependencies,
|
|
1715
|
+
pkg.dependencies,
|
|
1716
|
+
pkg.optionalDependencies
|
|
1717
|
+
];
|
|
1718
|
+
for (const dependencies of dependencyGroups) if (dependencies?.["vite-plus"]?.startsWith("catalog:")) {
|
|
1719
|
+
dependencies[VITE_PLUS_NAME] = version;
|
|
1720
|
+
changed = true;
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
if (pkg.devDependencies?.["vite-plus"]) return changed;
|
|
1724
|
+
pkg.devDependencies = {
|
|
1725
|
+
...pkg.devDependencies,
|
|
1726
|
+
[VITE_PLUS_NAME]: version
|
|
1727
|
+
};
|
|
1728
|
+
return true;
|
|
1729
|
+
}
|
|
1730
|
+
function ensureOverrideEntries(overrides, catalogDependencyResolver) {
|
|
1731
|
+
const next = { ...overrides };
|
|
1732
|
+
let changed = false;
|
|
1733
|
+
for (const [dependencyName, overrideSpec] of Object.entries(VITE_PLUS_OVERRIDE_PACKAGES)) if (!overrideSpecSatisfiesVitePlus(dependencyName, next[dependencyName], catalogDependencyResolver)) {
|
|
1734
|
+
next[dependencyName] = overrideSpec;
|
|
1735
|
+
changed = true;
|
|
1736
|
+
}
|
|
1737
|
+
return {
|
|
1738
|
+
overrides: next,
|
|
1739
|
+
changed
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
function ensureNpmVitePlusManagedDependencies(pkg) {
|
|
1743
|
+
let changed = false;
|
|
1744
|
+
const dependencyGroups = [
|
|
1745
|
+
pkg.devDependencies,
|
|
1746
|
+
pkg.dependencies,
|
|
1747
|
+
pkg.optionalDependencies
|
|
1748
|
+
];
|
|
1749
|
+
for (const [dependencyName, version] of Object.entries(VITE_PLUS_OVERRIDE_PACKAGES)) for (const dependencies of dependencyGroups) if (dependencies?.[dependencyName] !== void 0 && !overrideSpecSatisfiesVitePlus(dependencyName, dependencies[dependencyName])) {
|
|
1750
|
+
dependencies[dependencyName] = version;
|
|
1751
|
+
changed = true;
|
|
1752
|
+
}
|
|
1753
|
+
return changed;
|
|
1754
|
+
}
|
|
1755
|
+
function ensurePnpmPeerDependencyRules(pkg) {
|
|
1756
|
+
const overrideKeys = Object.keys(VITE_PLUS_OVERRIDE_PACKAGES);
|
|
1757
|
+
pkg.pnpm ??= {};
|
|
1758
|
+
const peerDependencyRules = {
|
|
1759
|
+
...pkg.pnpm.peerDependencyRules,
|
|
1760
|
+
allowAny: [...new Set([...pkg.pnpm.peerDependencyRules?.allowAny ?? [], ...overrideKeys])],
|
|
1761
|
+
allowedVersions: {
|
|
1762
|
+
...pkg.pnpm.peerDependencyRules?.allowedVersions,
|
|
1763
|
+
...Object.fromEntries(overrideKeys.map((key) => [key, "*"]))
|
|
1764
|
+
}
|
|
1765
|
+
};
|
|
1766
|
+
const changed = JSON.stringify(pkg.pnpm.peerDependencyRules ?? {}) !== JSON.stringify(peerDependencyRules);
|
|
1767
|
+
pkg.pnpm.peerDependencyRules = peerDependencyRules;
|
|
1768
|
+
return changed;
|
|
1769
|
+
}
|
|
1770
|
+
function ensureVitePlusBootstrap(workspaceInfo, report) {
|
|
1771
|
+
const projectPath = workspaceInfo.rootDir;
|
|
1772
|
+
const packageJsonPath = path.join(projectPath, "package.json");
|
|
1773
|
+
const result = {
|
|
1774
|
+
changed: false,
|
|
1775
|
+
packageJson: false,
|
|
1776
|
+
packageManagerConfig: false,
|
|
1777
|
+
packageManagerField: false
|
|
1778
|
+
};
|
|
1779
|
+
if (!fs.existsSync(packageJsonPath)) return result;
|
|
1780
|
+
editJsonFile(packageJsonPath, (pkg) => {
|
|
1781
|
+
const usePnpmWorkspaceYaml = workspaceInfo.packageManager === PackageManager.pnpm && !pkg.pnpm;
|
|
1782
|
+
let packageJsonChanged = ensureVitePlusDependencySpecs(pkg, !VITE_PLUS_VERSION.startsWith("file:") && (usePnpmWorkspaceYaml || workspaceInfo.packageManager === PackageManager.bun) ? "catalog:" : VITE_PLUS_VERSION);
|
|
1783
|
+
if (workspaceInfo.packageManager === PackageManager.npm) packageJsonChanged = ensureNpmVitePlusManagedDependencies(pkg) || packageJsonChanged;
|
|
1784
|
+
if (workspaceInfo.packageManager === PackageManager.yarn) {
|
|
1785
|
+
const ensured = ensureOverrideEntries(pkg.resolutions);
|
|
1786
|
+
if (ensured.changed) {
|
|
1787
|
+
pkg.resolutions = ensured.overrides;
|
|
1788
|
+
packageJsonChanged = true;
|
|
1789
|
+
}
|
|
1790
|
+
} else if (workspaceInfo.packageManager === PackageManager.npm) {
|
|
1791
|
+
const ensured = ensureOverrideEntries(pkg.overrides);
|
|
1792
|
+
if (ensured.changed) {
|
|
1793
|
+
pkg.overrides = ensured.overrides;
|
|
1794
|
+
packageJsonChanged = true;
|
|
1795
|
+
}
|
|
1796
|
+
} else if (workspaceInfo.packageManager === PackageManager.bun) {
|
|
1797
|
+
const ensured = ensureOverrideEntries(pkg.overrides, readBunCatalogDependencyResolver(pkg));
|
|
1798
|
+
if (ensured.changed) {
|
|
1799
|
+
pkg.overrides = ensured.overrides;
|
|
1800
|
+
packageJsonChanged = true;
|
|
1801
|
+
}
|
|
1802
|
+
} else if (workspaceInfo.packageManager === PackageManager.pnpm && pkg.pnpm) {
|
|
1803
|
+
const ensured = ensureOverrideEntries(pkg.pnpm.overrides);
|
|
1804
|
+
if (ensured.changed) {
|
|
1805
|
+
pkg.pnpm.overrides = ensured.overrides;
|
|
1806
|
+
packageJsonChanged = true;
|
|
1807
|
+
}
|
|
1808
|
+
packageJsonChanged = ensurePnpmPeerDependencyRules(pkg) || packageJsonChanged;
|
|
1809
|
+
}
|
|
1810
|
+
result.packageJson = packageJsonChanged;
|
|
1811
|
+
return pkg;
|
|
1812
|
+
});
|
|
1813
|
+
if (workspaceInfo.packageManager === PackageManager.pnpm) {
|
|
1814
|
+
const pkg = readJsonFile(packageJsonPath);
|
|
1815
|
+
if (!pkg.pnpm) {
|
|
1816
|
+
const pnpmWorkspaceYamlPath = path.join(projectPath, "pnpm-workspace.yaml");
|
|
1817
|
+
const before = fs.existsSync(pnpmWorkspaceYamlPath) ? fs.readFileSync(pnpmWorkspaceYamlPath, "utf-8") : void 0;
|
|
1818
|
+
const catalogDependencyResolver = readPnpmWorkspaceCatalogDependencyResolver(projectPath);
|
|
1819
|
+
if (defaultCatalogVitePlusDependencyPending(pkg, catalogDependencyResolver) || !overridesSatisfyVitePlus(readPnpmWorkspaceOverrides(projectPath), catalogDependencyResolver) || !pnpmPeerDependencyRulesSatisfyVitePlus(readPnpmWorkspacePeerDependencyRules(projectPath))) rewritePnpmWorkspaceYaml(projectPath, void 0, false);
|
|
1820
|
+
if (fs.existsSync(pnpmWorkspaceYamlPath)) ensurePnpmWorkspacePackages(projectPath, workspaceInfo.workspacePatterns);
|
|
1821
|
+
result.packageManagerConfig = before !== (fs.existsSync(pnpmWorkspaceYamlPath) ? fs.readFileSync(pnpmWorkspaceYamlPath, "utf-8") : void 0);
|
|
1822
|
+
}
|
|
1823
|
+
} else if (workspaceInfo.packageManager === PackageManager.yarn) {
|
|
1824
|
+
const yarnrcYmlPath = path.join(projectPath, ".yarnrc.yml");
|
|
1825
|
+
const before = fs.existsSync(yarnrcYmlPath) ? fs.readFileSync(yarnrcYmlPath, "utf-8") : void 0;
|
|
1826
|
+
rewriteYarnrcYml(projectPath);
|
|
1827
|
+
result.packageManagerConfig = before !== fs.readFileSync(yarnrcYmlPath, "utf-8");
|
|
1828
|
+
} else if (workspaceInfo.packageManager === PackageManager.bun) {
|
|
1829
|
+
const before = fs.readFileSync(packageJsonPath, "utf-8");
|
|
1830
|
+
rewriteBunCatalog(projectPath);
|
|
1831
|
+
const after = fs.readFileSync(packageJsonPath, "utf-8");
|
|
1832
|
+
result.packageJson = result.packageJson || before !== after;
|
|
1833
|
+
}
|
|
1834
|
+
const beforePackageManager = fs.readFileSync(packageJsonPath, "utf-8");
|
|
1835
|
+
setPackageManager(projectPath, workspaceInfo.downloadPackageManager);
|
|
1836
|
+
result.packageManagerField = beforePackageManager !== fs.readFileSync(packageJsonPath, "utf-8");
|
|
1837
|
+
result.changed = result.packageJson || result.packageManagerConfig || result.packageManagerField;
|
|
1838
|
+
if (result.changed && report) report.packageManagerBootstrapConfigured = true;
|
|
1839
|
+
return result;
|
|
1840
|
+
}
|
|
1841
|
+
const VITEST_BROWSER_SPECIFIER_HINTS = [
|
|
1842
|
+
"@vitest/browser",
|
|
1843
|
+
"vite-plus/test/browser",
|
|
1844
|
+
"vite-plus/test/plugins/browser",
|
|
1845
|
+
"vite-plus/test/internal/browser",
|
|
1846
|
+
"vite-plus/test/client",
|
|
1847
|
+
"vite-plus/test/context",
|
|
1848
|
+
"vite-plus/test/locators",
|
|
1849
|
+
"vite-plus/test/matchers",
|
|
1850
|
+
"vite-plus/test/utils"
|
|
1851
|
+
];
|
|
1852
|
+
const WEBDRIVERIO_PROVIDER_SPECIFIER_HINTS = [
|
|
1853
|
+
"@vitest/browser-webdriverio",
|
|
1854
|
+
"vite-plus/test/browser-webdriverio",
|
|
1855
|
+
"vite-plus/test/browser/providers/webdriverio",
|
|
1856
|
+
"vite-plus/test/plugins/browser-webdriverio"
|
|
1857
|
+
];
|
|
1858
|
+
const PLAYWRIGHT_PROVIDER_SPECIFIER_HINTS = [
|
|
1859
|
+
"@vitest/browser-playwright",
|
|
1860
|
+
"vite-plus/test/browser-playwright",
|
|
1861
|
+
"vite-plus/test/browser/providers/playwright",
|
|
1862
|
+
"vite-plus/test/plugins/browser-playwright"
|
|
1863
|
+
];
|
|
1864
|
+
const BROWSER_PROVIDER_SPECIFIER_HINTS = {
|
|
1865
|
+
[WEBDRIVERIO_PROVIDER]: WEBDRIVERIO_PROVIDER_SPECIFIER_HINTS,
|
|
1866
|
+
[PLAYWRIGHT_PROVIDER]: PLAYWRIGHT_PROVIDER_SPECIFIER_HINTS
|
|
1867
|
+
};
|
|
1868
|
+
const VITEST_SCAN_EXTENSIONS = new Set([
|
|
1869
|
+
".ts",
|
|
1870
|
+
".mts",
|
|
1871
|
+
".cts",
|
|
1872
|
+
".tsx",
|
|
1873
|
+
".js",
|
|
1874
|
+
".mjs",
|
|
1875
|
+
".cjs",
|
|
1876
|
+
".jsx"
|
|
1877
|
+
]);
|
|
1878
|
+
const VITEST_SCAN_SKIP_DIRS = new Set([
|
|
1879
|
+
"node_modules",
|
|
1880
|
+
"dist",
|
|
1881
|
+
"build",
|
|
1882
|
+
"out",
|
|
1883
|
+
"coverage",
|
|
1884
|
+
".git",
|
|
1885
|
+
".next",
|
|
1886
|
+
".nuxt",
|
|
1887
|
+
".svelte-kit",
|
|
1888
|
+
".vite",
|
|
1889
|
+
".cache"
|
|
1890
|
+
]);
|
|
1891
|
+
/**
|
|
1892
|
+
* Detect whether a package uses vitest's browser mode.
|
|
1893
|
+
*
|
|
1894
|
+
* Upstream `@vitest/browser` injects `optimizeDeps.include` entries of the form
|
|
1895
|
+
* `vitest > expect-type` (and `vitest > @vitest/snapshot > magic-string`,
|
|
1896
|
+
* `vitest > @vitest/expect > chai`). Vite resolves the leading `vitest` segment
|
|
1897
|
+
* from the Vite config root, so `vitest` MUST be resolvable as a package from
|
|
1898
|
+
* the consuming package's directory. In a pnpm strict (non-hoisted) layout,
|
|
1899
|
+
* `vitest` pulled in only transitively via `vite-plus` is NOT reachable from the
|
|
1900
|
+
* package root — the optimizer then fails with `Failed to resolve dependency`
|
|
1901
|
+
* and the browser test page hangs forever.
|
|
1902
|
+
*
|
|
1903
|
+
* When this returns true the migration adds `vitest` as a direct
|
|
1904
|
+
* devDependency so it is hoisted next to the package and the optimizer chain
|
|
1905
|
+
* resolves. The signal is any of the package's TS/JS files (config, workspace
|
|
1906
|
+
* config under any name, or test file) referencing `@vitest/browser*` or
|
|
1907
|
+
* `vite-plus/test/browser*`. The scan recurses through the package directory
|
|
1908
|
+
* (skipping `node_modules`, build output, VCS metadata) so browser config in a
|
|
1909
|
+
* non-standard filename or browser imports in test files are all caught.
|
|
1910
|
+
*
|
|
1911
|
+
* Recursion stops at nested `package.json` boundaries: a workspace sub-package
|
|
1912
|
+
* is a separate package that the migration scans on its own pass, so the root
|
|
1913
|
+
* package must not inherit a browser-mode signal from a sub-package.
|
|
1914
|
+
*/
|
|
1915
|
+
function sourceTreeReferencesAny(projectPath, hints) {
|
|
1916
|
+
const matchesHint = (content) => hints.some((hint) => content.includes(hint));
|
|
1917
|
+
const scanDir = (dir, isRoot) => {
|
|
1918
|
+
let entries;
|
|
1919
|
+
try {
|
|
1920
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
1921
|
+
} catch {
|
|
1922
|
+
return false;
|
|
1923
|
+
}
|
|
1924
|
+
if (!isRoot && entries.some((e) => e.isFile() && e.name === "package.json")) return false;
|
|
1925
|
+
for (const entry of entries) {
|
|
1926
|
+
const entryPath = path.join(dir, entry.name);
|
|
1927
|
+
if (entry.isDirectory()) {
|
|
1928
|
+
if (VITEST_SCAN_SKIP_DIRS.has(entry.name)) continue;
|
|
1929
|
+
if (scanDir(entryPath, false)) return true;
|
|
1930
|
+
} else if (entry.isFile() && VITEST_SCAN_EXTENSIONS.has(path.extname(entry.name))) try {
|
|
1931
|
+
if (matchesHint(fs.readFileSync(entryPath, "utf8"))) return true;
|
|
1932
|
+
} catch {}
|
|
1933
|
+
}
|
|
1934
|
+
return false;
|
|
1935
|
+
};
|
|
1936
|
+
return scanDir(projectPath, true);
|
|
1937
|
+
}
|
|
1938
|
+
function usesVitestBrowserMode(projectPath) {
|
|
1939
|
+
return sourceTreeReferencesAny(projectPath, VITEST_BROWSER_SPECIFIER_HINTS);
|
|
1940
|
+
}
|
|
1941
|
+
function usesWebdriverioProvider(projectPath) {
|
|
1942
|
+
return sourceTreeReferencesAny(projectPath, WEBDRIVERIO_PROVIDER_SPECIFIER_HINTS);
|
|
1943
|
+
}
|
|
1944
|
+
function collectProviderSourceModes(projectPath) {
|
|
1945
|
+
const modes = {};
|
|
1946
|
+
for (const provider of OPT_IN_BROWSER_PROVIDERS) modes[provider] = sourceTreeReferencesAny(projectPath, BROWSER_PROVIDER_SPECIFIER_HINTS[provider]);
|
|
1947
|
+
return modes;
|
|
1948
|
+
}
|
|
1949
|
+
function rewritePackageJson(pkg, packageManager, isMonorepo, skipStagedMigration, catalogDependencyResolver, vitestBrowserMode, providerSourceModes) {
|
|
1155
1950
|
if (pkg.scripts) {
|
|
1156
1951
|
const updated = rewriteScripts(JSON.stringify(pkg.scripts), getScriptRulesYaml(skipStagedMigration));
|
|
1157
1952
|
if (updated) pkg.scripts = JSON.parse(updated);
|
|
@@ -1182,6 +1977,7 @@ function rewritePackageJson(pkg, packageManager, isMonorepo, skipStagedMigration
|
|
|
1182
1977
|
dependencies: pkg.optionalDependencies
|
|
1183
1978
|
}
|
|
1184
1979
|
];
|
|
1980
|
+
for (const { dependencies } of dependencyGroups) if (pruneLegacyWrapperAliases(dependencies)) needVitePlus = true;
|
|
1185
1981
|
for (const [key, version] of Object.entries(VITE_PLUS_OVERRIDE_PACKAGES)) for (const { dependencyField, dependencies } of dependencyGroups) if (dependencies?.[key]) {
|
|
1186
1982
|
dependencies[key] = getCatalogDependencySpec(dependencies[key], version, supportCatalog, {
|
|
1187
1983
|
dependencyField,
|
|
@@ -1191,6 +1987,13 @@ function rewritePackageJson(pkg, packageManager, isMonorepo, skipStagedMigration
|
|
|
1191
1987
|
});
|
|
1192
1988
|
needVitePlus = true;
|
|
1193
1989
|
}
|
|
1990
|
+
if (isForceOverrideMode()) {
|
|
1991
|
+
for (const { dependencies } of dependencyGroups) if (dependencies?.["vite-plus"]) {
|
|
1992
|
+
dependencies[VITE_PLUS_NAME] = VITE_PLUS_VERSION;
|
|
1993
|
+
needVitePlus = true;
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
const hasBrowserDepSignal = VITEST_BROWSER_DEP_NAMES.some((name) => dependencyGroups.some(({ dependencies }) => dependencies?.[name] !== void 0));
|
|
1194
1997
|
for (const name of REMOVE_PACKAGES) {
|
|
1195
1998
|
let wasRemoved = false;
|
|
1196
1999
|
for (const { dependencies } of dependencyGroups) if (dependencies?.[name]) {
|
|
@@ -1204,23 +2007,63 @@ function rewritePackageJson(pkg, packageManager, isMonorepo, skipStagedMigration
|
|
|
1204
2007
|
pkg.devDependencies[peerDep] = "*";
|
|
1205
2008
|
}
|
|
1206
2009
|
}
|
|
2010
|
+
let usesAnyOptInProvider = false;
|
|
2011
|
+
for (const provider of OPT_IN_BROWSER_PROVIDERS) {
|
|
2012
|
+
if (!(providerSourceModes?.[provider] || dependencyGroups.some(({ dependencies }) => dependencies?.[provider] !== void 0))) continue;
|
|
2013
|
+
usesAnyOptInProvider = true;
|
|
2014
|
+
const installGroup = [
|
|
2015
|
+
pkg.dependencies,
|
|
2016
|
+
pkg.devDependencies,
|
|
2017
|
+
pkg.optionalDependencies
|
|
2018
|
+
].find((deps) => deps?.[provider] !== void 0);
|
|
2019
|
+
if (installGroup) installGroup[provider] = VITEST_VERSION;
|
|
2020
|
+
else {
|
|
2021
|
+
pkg.devDependencies ??= {};
|
|
2022
|
+
pkg.devDependencies[provider] = VITEST_VERSION;
|
|
2023
|
+
}
|
|
2024
|
+
const peer = BROWSER_PROVIDER_PEER_DEPS[provider];
|
|
2025
|
+
const peerPresent = pkg.dependencies?.[peer] ?? pkg.devDependencies?.[peer] ?? pkg.peerDependencies?.[peer] ?? pkg.optionalDependencies?.[peer];
|
|
2026
|
+
if (peer && !peerPresent) {
|
|
2027
|
+
pkg.devDependencies ??= {};
|
|
2028
|
+
pkg.devDependencies[peer] = "*";
|
|
2029
|
+
}
|
|
2030
|
+
needVitePlus = true;
|
|
2031
|
+
}
|
|
2032
|
+
if (usesAnyOptInProvider && packageManager === PackageManager.npm) {
|
|
2033
|
+
const viteOverride = VITE_PLUS_OVERRIDE_PACKAGES.vite;
|
|
2034
|
+
const viteAlreadyDirect = pkg.dependencies?.vite ?? pkg.devDependencies?.vite ?? pkg.optionalDependencies?.vite;
|
|
2035
|
+
if (viteOverride && !viteAlreadyDirect) {
|
|
2036
|
+
pkg.devDependencies ??= {};
|
|
2037
|
+
pkg.devDependencies.vite = viteOverride;
|
|
2038
|
+
needVitePlus = true;
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
const effectiveBrowserMode = vitestBrowserMode || hasBrowserDepSignal;
|
|
2042
|
+
const installableNames = [
|
|
2043
|
+
...Object.keys(pkg.dependencies ?? {}),
|
|
2044
|
+
...Object.keys(pkg.devDependencies ?? {}),
|
|
2045
|
+
...Object.keys(pkg.optionalDependencies ?? {})
|
|
2046
|
+
];
|
|
2047
|
+
const adjacentSignals = [...installableNames, ...Object.keys(pkg.peerDependencies ?? {})];
|
|
2048
|
+
const isVitestAdjacent = !installableNames.includes("vitest") && adjacentSignals.some((name) => name !== "vitest" && name.includes("vitest"));
|
|
1207
2049
|
const canonicalVitePlusSpec = supportCatalog && !VITE_PLUS_VERSION.startsWith("file:") ? "catalog:" : VITE_PLUS_VERSION;
|
|
1208
2050
|
const existingVitePlus = pkg.devDependencies?.[VITE_PLUS_NAME];
|
|
1209
2051
|
const shouldNormalizeExistingVitePlus = !!existingVitePlus && supportCatalog && existingVitePlus !== canonicalVitePlusSpec && !isProtocolPinnedSpec(existingVitePlus);
|
|
2052
|
+
if (!existingVitePlus && (isVitestAdjacent || effectiveBrowserMode)) needVitePlus = true;
|
|
2053
|
+
const needDirectVitest = needVitePlus || effectiveBrowserMode || isVitestAdjacent;
|
|
1210
2054
|
if (needVitePlus || shouldNormalizeExistingVitePlus) pkg.devDependencies = {
|
|
1211
2055
|
...pkg.devDependencies,
|
|
1212
2056
|
[VITE_PLUS_NAME]: canonicalVitePlusSpec
|
|
1213
2057
|
};
|
|
1214
|
-
if (
|
|
2058
|
+
if (needDirectVitest) {
|
|
1215
2059
|
const installableDeps = {
|
|
1216
2060
|
...pkg.dependencies,
|
|
1217
2061
|
...pkg.devDependencies,
|
|
1218
2062
|
...pkg.optionalDependencies
|
|
1219
2063
|
};
|
|
1220
|
-
if (!installableDeps.vitest && Object.keys(installableDeps).some((name) => name.includes("vitest"))) {
|
|
1221
|
-
const ver = VITE_PLUS_OVERRIDE_PACKAGES.vitest;
|
|
2064
|
+
if (!installableDeps.vitest && (effectiveBrowserMode || Object.keys(installableDeps).some((name) => name.includes("vitest")))) {
|
|
1222
2065
|
pkg.devDependencies ??= {};
|
|
1223
|
-
pkg.devDependencies.vitest = getCatalogDependencySpec(void 0,
|
|
2066
|
+
pkg.devDependencies.vitest = getCatalogDependencySpec(void 0, VITEST_VERSION, supportCatalog);
|
|
1224
2067
|
}
|
|
1225
2068
|
}
|
|
1226
2069
|
return extractedStagedConfig;
|
|
@@ -1588,6 +2431,20 @@ function hasStagedConfigInViteConfig(projectPath) {
|
|
|
1588
2431
|
return /\bstaged\s*:/.test(content);
|
|
1589
2432
|
}
|
|
1590
2433
|
/**
|
|
2434
|
+
* Wrap safe inline Vite plugin arrays with lazyPlugins so check/lint/fmt do not
|
|
2435
|
+
* eagerly execute plugin factories while loading vite.config.ts.
|
|
2436
|
+
*/
|
|
2437
|
+
function wrapLazyPluginsInViteConfig(projectPath, silent = false, report) {
|
|
2438
|
+
const configs = detectConfigs(projectPath);
|
|
2439
|
+
if (!configs.viteConfig) return;
|
|
2440
|
+
const viteConfigPath = path.join(projectPath, configs.viteConfig);
|
|
2441
|
+
const result = wrapLazyPlugins(viteConfigPath);
|
|
2442
|
+
if (!result.updated) return;
|
|
2443
|
+
fs.writeFileSync(viteConfigPath, result.content);
|
|
2444
|
+
if (report) report.wrappedPluginConfigCount++;
|
|
2445
|
+
if (!silent) log.success(`✔ Wrapped inline Vite plugins with lazyPlugins in ${displayRelative(viteConfigPath)}`);
|
|
2446
|
+
}
|
|
2447
|
+
/**
|
|
1591
2448
|
* Rewrite imports in all TypeScript/JavaScript files under a directory
|
|
1592
2449
|
* This rewrites vite/vitest imports to @voidzero-dev/vite-plus
|
|
1593
2450
|
* @param projectPath - The root directory to search for files
|
|
@@ -1612,6 +2469,7 @@ function rewriteAllImports(projectPath, silent = false, report) {
|
|
|
1612
2469
|
log.warn(`⚠ ${errors === 1 ? "one file had an error" : `${errors} files had errors`}:`);
|
|
1613
2470
|
for (const error of result.errors) log.error(` ${displayRelative(error.path)}: ${error.message}`);
|
|
1614
2471
|
}
|
|
2472
|
+
return modified > 0;
|
|
1615
2473
|
}
|
|
1616
2474
|
/**
|
|
1617
2475
|
* Check if the project has an unsupported husky version (<9.0.0).
|
|
@@ -1656,6 +2514,12 @@ function removeReplacedHookPackages(packageJsonPath) {
|
|
|
1656
2514
|
return pkg;
|
|
1657
2515
|
});
|
|
1658
2516
|
}
|
|
2517
|
+
function detectLegacyGitHooksMigrationCandidate(projectPath) {
|
|
2518
|
+
const packageJsonPath = path.join(projectPath, "package.json");
|
|
2519
|
+
if (!fs.existsSync(packageJsonPath)) return false;
|
|
2520
|
+
const pkg = readJsonFile(packageJsonPath);
|
|
2521
|
+
return getOldHooksDir(projectPath) !== void 0 || pkg["lint-staged"] !== void 0;
|
|
2522
|
+
}
|
|
1659
2523
|
/**
|
|
1660
2524
|
* Walk up from `startPath` looking for `.git` (directory or file — submodules
|
|
1661
2525
|
* use a `.git` file). Returns the directory that contains `.git`, or `null`.
|
|
@@ -1801,10 +2665,10 @@ function setupGitHooks(projectPath, oldHooksDir, silent = false, report, package
|
|
|
1801
2665
|
const vpBin = process.env.VP_CLI_BIN ?? "vp";
|
|
1802
2666
|
const configArgs = isCustomDir ? [
|
|
1803
2667
|
"config",
|
|
1804
|
-
"--
|
|
2668
|
+
"--no-agent",
|
|
1805
2669
|
"--hooks-dir",
|
|
1806
2670
|
hooksDir
|
|
1807
|
-
] : ["config", "--
|
|
2671
|
+
] : ["config", "--no-agent"];
|
|
1808
2672
|
const configResult = import_cross_spawn.default.sync(vpBin, configArgs, {
|
|
1809
2673
|
cwd: projectPath,
|
|
1810
2674
|
stdio: "pipe"
|
|
@@ -1922,7 +2786,14 @@ function rewritePrepareScript(rootDir) {
|
|
|
1922
2786
|
}
|
|
1923
2787
|
function setPackageManager(projectDir, downloadPackageManager) {
|
|
1924
2788
|
editJsonFile(path.join(projectDir, "package.json"), (pkg) => {
|
|
1925
|
-
if (!pkg.packageManager
|
|
2789
|
+
if (!pkg.packageManager && !pkg.devEngines?.packageManager) pkg.devEngines = {
|
|
2790
|
+
...typeof pkg.devEngines === "object" && pkg.devEngines !== null && !Array.isArray(pkg.devEngines) ? pkg.devEngines : void 0,
|
|
2791
|
+
packageManager: {
|
|
2792
|
+
name: downloadPackageManager.name,
|
|
2793
|
+
version: downloadPackageManager.version,
|
|
2794
|
+
onFail: "download"
|
|
2795
|
+
}
|
|
2796
|
+
};
|
|
1926
2797
|
return pkg;
|
|
1927
2798
|
});
|
|
1928
2799
|
}
|
|
@@ -2467,4 +3338,4 @@ function getMarkedRange(content, startMarker, endMarker) {
|
|
|
2467
3338
|
};
|
|
2468
3339
|
}
|
|
2469
3340
|
//#endregion
|
|
2470
|
-
export {
|
|
3341
|
+
export { mergeViteConfigFiles as A, setPackageManager as B, ensureVitePlusBootstrap as C, injectCreateDefaultTemplate as D, hasStagedConfigInViteConfig as E, promptEslintMigration as F, editYamlFile as G, warnLegacyEslintConfig as H, promptPrettierMigration as I, templatesDir as J, readYamlFile as K, rewriteMonorepo as L, migrateNodeVersionManagerFile as M, migratePrettierToOxfmt as N, injectLintTypeCheckDefaults as O, preflightGitHooksSetup as P, rewriteMonorepoProject as R, ensurePreCommitHook as S, hasFrameworkShim as T, warnPackageLevelEslint as U, warnIncompatibleEslintIntegration as V, warnPackageLevelPrettier as W, detectLegacyGitHooksMigrationCandidate as _, selectAgentTargets as a, detectPrettierProject as b, writeCopilotSetupWorkflow as c, checkVitestVersion as d, confirmEslintMigration as f, detectIncompatibleEslintIntegration as g, detectFramework as h, selectAgentTargetPaths as i, migrateEslintToOxlint as j, installGitHooks as k, addFrameworkShim as l, detectEslintProject as m, detectAgentConflicts as n, updateExistingAgentInstructions as o, confirmPrettierMigration as p, displayRelative as q, detectExistingAgentTargetPaths as r, writeAgentInstructions as s, COPILOT_AGENT_ID as t, checkViteVersion as u, detectNodeVersionManagerFile as v, finalizeCoreMigrationForExistingVitePlus as w, detectVitePlusBootstrapPending as x, detectPendingCoreMigration as y, rewriteStandaloneProject as z };
|