vite-plus 0.3.2 → 1.0.0-rc.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 (149) hide show
  1. package/LICENSE +35 -146
  2. package/README.md +3 -3
  3. package/binding/index.cjs +140 -55
  4. package/binding/index.d.cts +49 -0
  5. package/dist/{agent-C59HKB4Y.js → agent-Dinpyd-k.js} +6 -5
  6. package/dist/bin.js +48 -18
  7. package/dist/config/bin.js +2 -2
  8. package/dist/constants-CiKwrA0v.js +356 -0
  9. package/dist/create/bin.js +96 -71
  10. package/dist/{define-config-DPNEJxPz.d.ts → define-config-B9usMnEa.d.ts} +51 -10
  11. package/dist/{define-config-DpAPETDf.cjs → define-config-CBccpane.cjs} +173 -44
  12. package/dist/{define-config-DAaCa0U_.js → define-config-jhuYJ7Tb.js} +158 -42
  13. package/dist/define-config.cjs +1 -1
  14. package/dist/define-config.d.ts +1 -1
  15. package/dist/define-config.js +1 -1
  16. package/dist/documentation-DqcZSthV.js +11 -0
  17. package/dist/{editor-QOIGtmH4.js → editor-DMBczTdj.js} +216 -152
  18. package/dist/index.cjs +1 -1
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/{json-cULBl7Pi.js → json-JP24qHUF.js} +14 -6
  22. package/dist/lint-plugins.cjs +1 -1
  23. package/dist/migration/bin.js +3122 -15
  24. package/dist/{oxlint-plugin-config-BU42tr8y.js → oxlint-plugin-config-BgsDA6ua.js} +1 -1
  25. package/dist/oxlint-plugin.js +9 -7
  26. package/dist/pack-bin.js +1 -1
  27. package/dist/{package-BB-Jh_z3.js → package-B85H2Nw0.js} +6 -2
  28. package/dist/{vitest-ecosystem-BiRqcaRI.js → package-overrides-Dpn4scvN.js} +1 -7
  29. package/dist/{prompts-CujFOJXu.js → prompts-CQobX7uP.js} +2 -2
  30. package/dist/{resolve-vite-config-CHHjsjKJ.js → resolve-vite-config-BUFUmi8h.js} +2 -2
  31. package/dist/{resolve-vite-config-6Nox70uP.js → resolve-vite-config-I8fmpR7I.js} +1 -1
  32. package/dist/staged/bin.js +1205 -3317
  33. package/dist/sync-versions/bin.js +3 -2
  34. package/dist/sync-versions/bin.mjs +17 -2
  35. package/dist/test/browser/context.js +1 -1
  36. package/dist/test/browser/providers/playwright/context.js +1 -1
  37. package/dist/test/browser/providers/preview/context.js +1 -1
  38. package/dist/test/browser-playwright/context.js +1 -1
  39. package/dist/test/browser-preview/context.js +1 -1
  40. package/dist/test/context.d.ts +2 -942
  41. package/dist/test/context.js +1 -1
  42. package/dist/test/internal/traces.js +1 -0
  43. package/dist/test/locators.d.ts +2 -294
  44. package/dist/test/matchers.d.ts +2 -29
  45. package/dist/test/mocker.d.ts +2 -0
  46. package/dist/test/mocker.js +1 -0
  47. package/dist/test/{browser-webdriverio/context.js → plugins/browser-context.d.ts} +1 -0
  48. package/dist/test/plugins/browser-context.js +1 -1
  49. package/dist/test/plugins/browser-locators.d.ts +2 -0
  50. package/dist/test/plugins/browser-playwright.d.ts +2 -0
  51. package/dist/test/plugins/browser-preview.d.ts +2 -0
  52. package/dist/test/plugins/browser.d.ts +2 -0
  53. package/dist/test/plugins/mocker-automock.d.ts +2 -0
  54. package/dist/test/plugins/mocker-browser.d.ts +2 -0
  55. package/dist/test/plugins/mocker-node.d.ts +2 -0
  56. package/dist/test/plugins/mocker-redirect.d.ts +2 -0
  57. package/dist/test/plugins/mocker-register.d.ts +2 -0
  58. package/dist/test/plugins/mocker-transforms.d.ts +2 -0
  59. package/dist/test/plugins/mocker.d.ts +2 -0
  60. package/dist/test/plugins/pretty-format.d.ts +2 -0
  61. package/dist/test/plugins/snapshot-environment.d.ts +2 -0
  62. package/dist/test/plugins/snapshot-manager.d.ts +2 -0
  63. package/dist/test/plugins/snapshot.d.ts +2 -0
  64. package/dist/test/plugins/spy.d.ts +2 -0
  65. package/dist/test/plugins/utils-constants.d.ts +2 -0
  66. package/dist/test/plugins/utils-diff.d.ts +2 -0
  67. package/dist/test/plugins/utils-display.d.ts +2 -0
  68. package/dist/test/plugins/utils-error.d.ts +2 -0
  69. package/dist/test/plugins/utils-helpers.d.ts +2 -0
  70. package/dist/test/plugins/utils-offset.d.ts +2 -0
  71. package/dist/test/plugins/utils-resolver.d.ts +2 -0
  72. package/dist/test/plugins/utils-serialize.d.ts +2 -0
  73. package/dist/test/plugins/utils-source-map-node.d.ts +2 -0
  74. package/dist/test/plugins/utils-source-map.d.ts +2 -0
  75. package/dist/test/plugins/utils-timers.d.ts +2 -0
  76. package/dist/test/plugins/utils.d.ts +2 -0
  77. package/dist/toolchain.js +10 -10
  78. package/dist/toolchain.json +10 -10
  79. package/dist/{tsconfig-DCtWfQPA.js → tsconfig-Buo0RSzz.js} +8 -4
  80. package/dist/{tsconfig-MXktI3SX.js → tsconfig-C1VeTG9k.js} +1 -1
  81. package/dist/version.js +5 -3
  82. package/dist/versions.js +5 -5
  83. package/dist/vitest-ecosystem-BU0AqZq-.js +23 -0
  84. package/dist/vitest-v5-entry-points-DthU1e_O.js +25 -0
  85. package/docs/config/fmt.md +2 -2
  86. package/docs/config/lint.md +2 -2
  87. package/docs/config/run.md +1 -1
  88. package/docs/config/staged.md +1 -2
  89. package/docs/guide/check.md +2 -0
  90. package/docs/guide/ci.md +28 -31
  91. package/docs/guide/commit-hooks.md +18 -34
  92. package/docs/guide/create.md +1 -2
  93. package/docs/guide/docker.md +20 -68
  94. package/docs/guide/env.md +47 -32
  95. package/docs/guide/fmt.md +4 -2
  96. package/docs/guide/global-cli.md +426 -0
  97. package/docs/guide/ide-integration.md +1 -2
  98. package/docs/guide/implode.md +14 -1
  99. package/docs/guide/index.md +38 -35
  100. package/docs/guide/install.md +18 -20
  101. package/docs/guide/lint.md +6 -10
  102. package/docs/guide/local-cli.md +123 -0
  103. package/docs/guide/migrate-rules.md +104 -297
  104. package/docs/guide/migrate.md +82 -59
  105. package/docs/guide/monorepo.md +5 -1
  106. package/docs/guide/run.md +1 -1
  107. package/docs/guide/test.md +2 -0
  108. package/docs/guide/troubleshooting.md +6 -11
  109. package/docs/guide/upgrade-project.md +61 -0
  110. package/docs/guide/upgrade.md +17 -62
  111. package/docs/guide/vitest-v5.md +221 -0
  112. package/package.json +67 -90
  113. package/bin/oxfmt +0 -33
  114. package/bin/oxlint +0 -38
  115. package/dist/cli-truncate-Bg3RDXpi.js +0 -865
  116. package/dist/constants-IhOditRA.js +0 -80
  117. package/dist/is-fullwidth-code-point-BUNlIICg.js +0 -8
  118. package/dist/log-update-CoW8Z4Dl.js +0 -491
  119. package/dist/strip-ansi-C3wrWz9t.js +0 -853
  120. package/dist/test/browser/providers/webdriverio/context.d.ts +0 -1
  121. package/dist/test/browser/providers/webdriverio/context.js +0 -1
  122. package/dist/test/browser/providers/webdriverio.d.ts +0 -77
  123. package/dist/test/browser/providers/webdriverio.js +0 -1
  124. package/dist/test/browser-webdriverio/context.d.ts +0 -1
  125. package/dist/test/browser-webdriverio.d.ts +0 -77
  126. package/dist/test/browser-webdriverio.js +0 -1
  127. package/dist/test/coverage.d.ts +0 -2
  128. package/dist/test/coverage.js +0 -1
  129. package/dist/test/environments.d.ts +0 -2
  130. package/dist/test/environments.js +0 -1
  131. package/dist/test/plugins/browser-webdriverio.js +0 -1
  132. package/dist/test/plugins/expect.js +0 -1
  133. package/dist/test/plugins/runner-types.js +0 -1
  134. package/dist/test/plugins/runner-utils.js +0 -1
  135. package/dist/test/plugins/runner.js +0 -1
  136. package/dist/test/reporters.d.ts +0 -2
  137. package/dist/test/reporters.js +0 -1
  138. package/dist/test/runners.d.ts +0 -2
  139. package/dist/test/runners.js +0 -1
  140. package/dist/test/snapshot.d.ts +0 -2
  141. package/dist/test/snapshot.js +0 -1
  142. package/dist/test/suite.d.ts +0 -2
  143. package/dist/test/suite.js +0 -1
  144. package/dist/tsgolint-path-CbDReEOx.js +0 -34
  145. package/dist/tsgolint-path.d.ts +0 -7
  146. package/dist/tsgolint-path.js +0 -2
  147. package/dist/wrap-ansi-DNjkuBEp.js +0 -157
  148. package/dist/wrap-ansi-DUi52C6W.js +0 -2
  149. package/docs/guide/installer-env-vars.md +0 -286
@@ -34,19 +34,40 @@ var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["modu
34
34
  //#endregion
35
35
  let node_fs = require("node:fs");
36
36
  let node_module = require("node:module");
37
+ let node_path = require("node:path");
37
38
  let node_url = require("node:url");
38
39
  let vitest_config = require("vitest/config");
39
40
  //#region package.json
40
- var version = "0.3.2", VITE_PLUS_VERSION, VITEST_VERSION, CONFIG_METADATA_ENV;
41
+ var version = "1.0.0-rc.0", VITE_PLUS_VERSION, VITEST_VERSION, CONFIG_METADATA_ENV;
41
42
  var init_constants = __esmMin((() => {
42
43
  VITE_PLUS_VERSION = process.env.VP_VERSION || version;
43
- VITEST_VERSION = "4.1.11";
44
+ VITEST_VERSION = "5.0.1";
44
45
  process.env.VP_OVERRIDE_PACKAGES ? JSON.parse(process.env.VP_OVERRIDE_PACKAGES) : `${VITE_PLUS_VERSION}`;
45
46
  (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
46
47
  process.versions.node, process.release.name;
47
48
  CONFIG_METADATA_ENV = "VP_RESOLVING_CONFIG_METADATA";
48
49
  }));
49
50
  //#endregion
51
+ //#region src/utils/vitest-ecosystem.ts
52
+ var VITEST_EXACT_VERSION_PACKAGES, VITEST_RESOLVER_PACKAGES;
53
+ var init_vitest_ecosystem = __esmMin((() => {
54
+ VITEST_EXACT_VERSION_PACKAGES = /* @__PURE__ */ new Set([
55
+ "@vitest/browser",
56
+ "@vitest/browser-playwright",
57
+ "@vitest/browser-preview",
58
+ "@vitest/coverage-v8",
59
+ "@vitest/coverage-istanbul",
60
+ "@vitest/mocker",
61
+ "@vitest/pretty-format",
62
+ "@vitest/snapshot",
63
+ "@vitest/spy",
64
+ "@vitest/ui",
65
+ "@vitest/utils",
66
+ "@vitest/web-worker"
67
+ ]);
68
+ VITEST_RESOLVER_PACKAGES = /* @__PURE__ */ new Set(["vitest", ...VITEST_EXACT_VERSION_PACKAGES]);
69
+ }));
70
+ //#endregion
50
71
  //#region src/define-config.ts
51
72
  var define_config_exports = /* @__PURE__ */ __exportAll({
52
73
  AUTO_INLINE_DEPS: () => AUTO_INLINE_DEPS,
@@ -69,6 +90,18 @@ function getVitestAnchor() {
69
90
  }
70
91
  return vitestAnchor;
71
92
  }
93
+ function getVitestImportTarget(id) {
94
+ const anchor = getVitestAnchor();
95
+ if (!anchor) throw new Error("Cannot resolve the bundled Vitest package. Reinstall vite-plus.");
96
+ vitestExports ??= JSON.parse((0, node_fs.readFileSync)(anchor, "utf8")).exports;
97
+ let target = vitestExports[id === "vitest" ? "." : `.${id.slice(6)}`];
98
+ while (target && typeof target === "object") {
99
+ const conditions = target;
100
+ target = conditions.import ?? conditions.default;
101
+ }
102
+ if (typeof target !== "string" || !target.startsWith("./")) throw new Error(`The bundled Vitest has no ESM export for ${id}.`);
103
+ return (0, node_path.resolve)(anchor, "..", target);
104
+ }
72
105
  /**
73
106
  * Match the `vitest` / `@vitest/*` family of bare specifiers — the imports a
74
107
  * browser-mode Vite dev server must resolve. Any query string is stripped
@@ -79,7 +112,9 @@ function getVitestAnchor() {
79
112
  function isVitestFamilySpecifier(id) {
80
113
  const bare = id.split("?")[0];
81
114
  if (bare.startsWith(".") || bare.startsWith("/") || bare.startsWith("\0")) return false;
82
- return bare === "vitest" || bare.startsWith("vitest/") || bare === "@vitest/browser" || bare.startsWith("@vitest/");
115
+ const segments = bare.split("/");
116
+ const packageName = bare.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
117
+ return VITEST_RESOLVER_PACKAGES.has(packageName);
83
118
  }
84
119
  /**
85
120
  * Rescue `vitest` / `@vitest/*` resolution for browser-mode tests.
@@ -88,10 +123,10 @@ function isVitestFamilySpecifier(id) {
88
123
  * and `@vitest/browser` are transitive deps. pnpm's isolated layout only
89
124
  * exposes a package's *direct* deps, so the browser-mode Vite dev server
90
125
  * (rooted at the consumer project) cannot resolve `vitest/internal/browser`,
91
- * `@vitest/expect`, etc. Non-browser tests are unaffected — vitest's own
126
+ * `@vitest/mocker`, etc. Non-browser tests are unaffected — vitest's own
92
127
  * module runner handles resolution there.
93
128
  *
94
- * This plugin re-resolves the `vitest` / `@vitest/*` family through Vite's OWN
129
+ * This plugin re-resolves the explicit Vitest runtime allowlist through Vite's OWN
95
130
  * resolver, but ROOTED at `vite-plus`'s location ([[vitePlusModuleFile]]) and
96
131
  * then the bundled `vitest`'s location ([[getVitestAnchor]]) BEFORE the
97
132
  * project. So every such import binds to the same physical (pinned) Vitest that
@@ -132,10 +167,61 @@ function isVitestFamilySpecifier(id) {
132
167
  * [[vitePlusCoverageVersionGuardPlugin]] fails fast on a mismatch instead.
133
168
  */
134
169
  function vitePlusVitestResolverPlugin() {
170
+ let isVitestServer = false;
135
171
  return {
136
172
  name: "vite-plus:vitest-resolver",
137
173
  enforce: "pre",
174
+ config: {
175
+ order: "post",
176
+ handler(config, { command }) {
177
+ isVitestServer = command === "serve" && !!config.environments?.["__vitest__"];
178
+ if (!isVitestServer || !config.test?.browser?.enabled) return;
179
+ const aliases = config.resolve?.alias;
180
+ const entries = Array.isArray(aliases) ? [...aliases] : Object.entries(aliases ?? {}).map(([find, replacement]) => ({
181
+ find,
182
+ replacement
183
+ }));
184
+ const runtimeRequire = (0, node_module.createRequire)(getVitestAnchor());
185
+ const targets = new Map([
186
+ "vitest",
187
+ "vitest/internal/browser",
188
+ "vitest/internal/traces",
189
+ "expect-type",
190
+ "magic-string",
191
+ "chai",
192
+ "vite/module-runner"
193
+ ].map((id) => [id, id.startsWith("vitest") ? getVitestImportTarget(id) : runtimeRequire.resolve(id)]));
194
+ if (config.test.browser.provider?.name === "preview") {
195
+ const previewRequire = (0, node_module.createRequire)(vitePlusRequire.resolve("@vitest/browser-preview"));
196
+ for (const id of ["@testing-library/user-event", "@testing-library/dom"]) targets.set(id, previewRequire.resolve(id));
197
+ }
198
+ for (const [id, replacement] of targets) {
199
+ if (entries.some(({ find }) => typeof find === "string" ? id === find || id.startsWith(`${find}/`) : new RegExp(find).test(id))) continue;
200
+ entries.push({
201
+ find: new RegExp(`^${id}$`),
202
+ replacement
203
+ });
204
+ }
205
+ config.resolve ??= {};
206
+ config.resolve.alias = entries;
207
+ }
208
+ },
209
+ configResolved(config) {
210
+ const seen = /* @__PURE__ */ new Set();
211
+ const plugins = config.plugins;
212
+ const unique = plugins.filter((plugin) => {
213
+ if (!VITE_PLUS_TEST_PLUGIN_NAMES.has(plugin.name)) return true;
214
+ if (seen.has(plugin.name)) return false;
215
+ seen.add(plugin.name);
216
+ return true;
217
+ });
218
+ plugins.splice(0, plugins.length, ...unique);
219
+ },
138
220
  async resolveId(id, importer, options) {
221
+ if (isVitestServer && id === "vite-plus/test") return this.resolve("vitest", importer, {
222
+ ...options,
223
+ skipSelf: true
224
+ });
139
225
  if (!isVitestFamilySpecifier(id)) return null;
140
226
  if (id.includes("?")) return null;
141
227
  const vitestAnchorPath = getVitestAnchor();
@@ -164,18 +250,26 @@ function vitePlusVitestResolverPlugin() {
164
250
  *
165
251
  * Exported for unit testing. The `_createRequire` parameter lets tests inject
166
252
  * a controlled resolver without needing to spy on Node's ESM module namespace.
253
+ * Callers may share installation results for the same root within one config load.
167
254
  */
168
- function computeAutoInlineList(existingInline, projectRoot, _createRequire = node_module.createRequire) {
255
+ function computeAutoInlineList(existingInline, projectRoot, _createRequire = node_module.createRequire, installedPackages = /* @__PURE__ */ new Map()) {
169
256
  if (existingInline === true) return null;
170
- const projectRequire = _createRequire(`${projectRoot}/package.json`);
257
+ let projectRequire;
171
258
  const merged = Array.isArray(existingInline) ? [...existingInline] : [];
172
259
  for (const pkg of AUTO_INLINE_DEPS) {
173
260
  if (merged.some((entry) => entry === pkg || entry instanceof RegExp && entry.test(pkg))) continue;
174
- try {
175
- projectRequire.resolve(pkg);
176
- } catch {
177
- continue;
261
+ let installed = installedPackages.get(pkg);
262
+ if (installed === void 0) {
263
+ projectRequire ??= _createRequire(`${projectRoot}/package.json`);
264
+ try {
265
+ projectRequire.resolve(pkg);
266
+ installed = true;
267
+ } catch {
268
+ installed = false;
269
+ }
270
+ installedPackages.set(pkg, installed);
178
271
  }
272
+ if (!installed) continue;
179
273
  merged.push(pkg);
180
274
  }
181
275
  const hadEntries = Array.isArray(existingInline) ? existingInline.length : 0;
@@ -183,18 +277,47 @@ function computeAutoInlineList(existingInline, projectRoot, _createRequire = nod
183
277
  return merged;
184
278
  }
185
279
  function vitePlusAutoInlineMatcherPlugin() {
280
+ let projectRoot = "";
281
+ let isVitestServer = false;
282
+ const installedByRoot = /* @__PURE__ */ new Map();
283
+ function inlineList(existing, root) {
284
+ root = (0, node_path.resolve)(root);
285
+ let installed = installedByRoot.get(root);
286
+ if (!installed) {
287
+ installed = /* @__PURE__ */ new Map();
288
+ installedByRoot.set(root, installed);
289
+ }
290
+ return computeAutoInlineList(existing, root, node_module.createRequire, installed);
291
+ }
186
292
  return {
187
293
  name: "vite-plus:auto-inline-matcher-deps",
188
294
  enforce: "pre",
295
+ config: {
296
+ order: "post",
297
+ handler(config, { command }) {
298
+ isVitestServer = command === "serve" && !!config.environments?.["__vitest__"];
299
+ projectRoot = (0, node_path.resolve)(config.root ?? ".");
300
+ installedByRoot.clear();
301
+ }
302
+ },
303
+ configEnvironment(_name, config) {
304
+ if (!isVitestServer) return;
305
+ const existing = config.resolve?.noExternal;
306
+ const merged = inlineList(typeof existing === "string" || existing instanceof RegExp ? [existing] : existing, projectRoot);
307
+ if (merged !== null) {
308
+ config.resolve ??= {};
309
+ config.resolve.noExternal = merged;
310
+ }
311
+ },
189
312
  configResolved(resolvedConfig) {
190
- const testConfig = resolvedConfig.test;
191
- const merged = computeAutoInlineList(testConfig?.server?.deps?.inline, resolvedConfig.root);
192
- if (merged === null) return;
193
- if (!testConfig) resolvedConfig.test = { server: { deps: { inline: merged } } };
194
- else {
195
- if (!testConfig.server) testConfig.server = {};
196
- if (!testConfig.server.deps) testConfig.server.deps = {};
197
- testConfig.server.deps.inline = merged;
313
+ if (!isVitestServer) return;
314
+ const config = resolvedConfig;
315
+ const merged = inlineList(config.test?.server?.deps?.inline, config.root);
316
+ if (merged !== null) {
317
+ config.test ??= {};
318
+ config.test.server ??= {};
319
+ config.test.server.deps ??= {};
320
+ config.test.server.deps.inline = merged;
198
321
  }
199
322
  }
200
323
  };
@@ -299,15 +422,14 @@ function vitePlusCoverageVersionGuardPlugin() {
299
422
  }
300
423
  };
301
424
  }
302
- /**
303
- * Inject the vitest resolver plugin, the auto-inline matcher plugin, and the
304
- * coverage version guard into a single inline project config. Used both for
305
- * root configs and for object-shaped entries inside `test.projects`.
306
- *
307
- * The shapes overlap (both have an optional top-level `plugins` array and
308
- * an optional `test.server.deps.inline`), so a shared helper keeps the
309
- * wiring consistent.
310
- */
425
+ function withoutVitePlusTestPlugins(plugin) {
426
+ if (Array.isArray(plugin)) return plugin.filter(keepUserPlugin).map(withoutVitePlusTestPlugins);
427
+ if (plugin instanceof Promise) return plugin.then(withoutVitePlusTestPlugins);
428
+ return plugin && VITE_PLUS_TEST_PLUGIN_NAMES.has(plugin.name) ? false : plugin;
429
+ }
430
+ function keepUserPlugin(plugin) {
431
+ return !plugin || !("name" in plugin) || !VITE_PLUS_TEST_PLUGIN_NAMES.has(plugin.name);
432
+ }
311
433
  function injectPluginIntoInlineConfig(config) {
312
434
  return {
313
435
  ...config,
@@ -315,15 +437,13 @@ function injectPluginIntoInlineConfig(config) {
315
437
  vitePlusVitestResolverPlugin(),
316
438
  vitePlusAutoInlineMatcherPlugin(),
317
439
  vitePlusCoverageVersionGuardPlugin(),
318
- ...config.plugins ?? []
440
+ ...(config.plugins ?? []).filter(keepUserPlugin).map(withoutVitePlusTestPlugins)
319
441
  ]
320
442
  };
321
443
  }
322
444
  /**
323
- * Walk `config.test?.projects` and inject the vite-plus plugins into each
324
- * project entry. Vitest spins up an independent Vite pipeline per project, so
325
- * root-level plugins do NOT propagate — without this, files matched by a
326
- * project's `include` glob never get the vitest resolver / auto-inline plugins.
445
+ * Inline projects inherit root plugins by default in Vitest v5. Only projects
446
+ * with inheritance disabled or an external base need their own injection.
327
447
  *
328
448
  * Entry shapes (from `TestProjectConfiguration`):
329
449
  * - string (glob path like `'./packages/*'`) → passed through unchanged.
@@ -345,15 +465,18 @@ function injectPluginIntoProject(project) {
345
465
  if (typeof project === "function") {
346
466
  const wrapped = (env) => {
347
467
  const result = project(env);
348
- if (result instanceof Promise) return result.then(injectPluginIntoInlineConfig);
349
- return injectPluginIntoInlineConfig(result);
468
+ if (result instanceof Promise) return result.then(injectIndependentProject);
469
+ return injectIndependentProject(result);
350
470
  };
351
471
  return wrapped;
352
472
  }
353
- if (project instanceof Promise) return project.then(injectPluginIntoInlineConfig);
354
- if (typeof project === "object" && project !== null) return injectPluginIntoInlineConfig(project);
473
+ if (project instanceof Promise) return project.then(injectIndependentProject);
474
+ if (typeof project === "object" && project !== null) return injectIndependentProject(project);
355
475
  return project;
356
476
  }
477
+ function injectIndependentProject(config) {
478
+ return config.extends === false || typeof config.extends === "string" ? injectPlugin(config) : config;
479
+ }
357
480
  function injectPlugin(config) {
358
481
  const injected = injectPluginIntoInlineConfig(config);
359
482
  const projects = injected.test?.projects;
@@ -380,17 +503,17 @@ function defineConfig(config) {
380
503
  }
381
504
  /**
382
505
  * Inject the vite-plus plugins into a `defineProject` export. A project config
383
- * (`UserWorkspaceConfig`) cannot itself nest `test.projects`, so this only
384
- * touches the top-level `plugins` array (no project recursion like
385
- * [[injectPluginIntoConfig]] does).
506
+ * (`UserWorkspaceConfig`) can itself declare nested projects in v5. Referenced
507
+ * configs own a Vite server, so inject at their root and apply inheritance rules
508
+ * to their inline children.
386
509
  */
387
510
  function injectPluginIntoProjectExport(config) {
388
511
  if (typeof config === "function") return (env) => {
389
512
  const result = config(env);
390
- return result instanceof Promise ? result.then(injectPluginIntoInlineConfig) : injectPluginIntoInlineConfig(result);
513
+ return result instanceof Promise ? result.then(injectPlugin) : injectPlugin(result);
391
514
  };
392
- if (config instanceof Promise) return config.then(injectPluginIntoInlineConfig);
393
- return injectPluginIntoInlineConfig(config);
515
+ if (config instanceof Promise) return config.then(injectPlugin);
516
+ return injectPlugin(config);
394
517
  }
395
518
  function defineProject(config) {
396
519
  return (0, vitest_config.defineProject)(injectPluginIntoProjectExport(config));
@@ -432,9 +555,10 @@ function lazyPlugins(cb) {
432
555
  if (result instanceof Promise) return [result];
433
556
  return result;
434
557
  }
435
- var vitePlusRequire, vitePlusModuleFile, vitestAnchor, AUTO_INLINE_DEPS, KNOWN_COVERAGE_PROVIDERS, bundledVitestAnchorCache, coverageGuardedVitestInstances, configMetadataDepth, configMetadataSavedValue;
558
+ var vitePlusRequire, vitePlusModuleFile, vitestAnchor, vitestExports, AUTO_INLINE_DEPS, KNOWN_COVERAGE_PROVIDERS, bundledVitestAnchorCache, coverageGuardedVitestInstances, VITE_PLUS_TEST_PLUGIN_NAMES, configMetadataDepth, configMetadataSavedValue;
436
559
  var init_define_config = __esmMin((() => {
437
560
  init_constants();
561
+ init_vitest_ecosystem();
438
562
  vitePlusRequire = (0, node_module.createRequire)(typeof __dirname !== "undefined" ? __dirname : require("url").pathToFileURL(__filename).href);
439
563
  vitePlusModuleFile = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
440
564
  AUTO_INLINE_DEPS = [
@@ -444,6 +568,11 @@ var init_define_config = __esmMin((() => {
444
568
  ];
445
569
  KNOWN_COVERAGE_PROVIDERS = /* @__PURE__ */ new Set(["v8", "istanbul"]);
446
570
  coverageGuardedVitestInstances = /* @__PURE__ */ new WeakSet();
571
+ VITE_PLUS_TEST_PLUGIN_NAMES = /* @__PURE__ */ new Set([
572
+ "vite-plus:vitest-resolver",
573
+ "vite-plus:auto-inline-matcher-deps",
574
+ "vite-plus:coverage-version-guard"
575
+ ]);
447
576
  configMetadataDepth = 0;
448
577
  }));
449
578
  //#endregion
@@ -1,6 +1,7 @@
1
- import { c as VITEST_VERSION, r as CONFIG_METADATA_ENV } from "./constants-IhOditRA.js";
1
+ import { c as VITEST_VERSION, r as CONFIG_METADATA_ENV } from "./constants-CiKwrA0v.js";
2
+ import { t as VITEST_RESOLVER_PACKAGES } from "./vitest-ecosystem-BU0AqZq-.js";
2
3
  import { createRequire } from "node:module";
3
- import path from "node:path";
4
+ import path, { resolve } from "node:path";
4
5
  import { fileURLToPath } from "node:url";
5
6
  import { readFileSync } from "node:fs";
6
7
  import { defineConfig, defineProject } from "vitest/config";
@@ -43,10 +44,9 @@ const vitePlusRequire = createRequire(typeof __dirname !== "undefined" ? __dirna
43
44
  const vitePlusModuleFile = fileURLToPath(import.meta.url);
44
45
  /**
45
46
  * Absolute path to the bundled `vitest` package's `package.json`, used as a
46
- * second `this.resolve` importer. The nested `@vitest/*` family (`@vitest/expect`,
47
- * `@vitest/runner`, `@vitest/snapshot`, …) are dependencies of `vitest` itself —
48
- * not direct deps of `vite-plus` — so under pnpm's isolated layout they are
49
- * reachable from `vitest`'s location but not from [[vitePlusModuleFile]].
47
+ * second `this.resolve` importer. Supported transitive packages can be
48
+ * reachable from `vitest`'s location but not from [[vitePlusModuleFile]]
49
+ * under pnpm's isolated layout.
50
50
  * Resolving `package.json` is condition-agnostic, so this is safe with
51
51
  * `require.resolve`. Cached; `null` once an attempt has failed so we never retry.
52
52
  */
@@ -60,6 +60,19 @@ function getVitestAnchor() {
60
60
  }
61
61
  return vitestAnchor;
62
62
  }
63
+ let vitestExports;
64
+ function getVitestImportTarget(id) {
65
+ const anchor = getVitestAnchor();
66
+ if (!anchor) throw new Error("Cannot resolve the bundled Vitest package. Reinstall vite-plus.");
67
+ vitestExports ??= JSON.parse(readFileSync(anchor, "utf8")).exports;
68
+ let target = vitestExports[id === "vitest" ? "." : `.${id.slice(6)}`];
69
+ while (target && typeof target === "object") {
70
+ const conditions = target;
71
+ target = conditions.import ?? conditions.default;
72
+ }
73
+ if (typeof target !== "string" || !target.startsWith("./")) throw new Error(`The bundled Vitest has no ESM export for ${id}.`);
74
+ return resolve(anchor, "..", target);
75
+ }
63
76
  /**
64
77
  * Match the `vitest` / `@vitest/*` family of bare specifiers — the imports a
65
78
  * browser-mode Vite dev server must resolve. Any query string is stripped
@@ -70,7 +83,9 @@ function getVitestAnchor() {
70
83
  function isVitestFamilySpecifier(id) {
71
84
  const bare = id.split("?")[0];
72
85
  if (bare.startsWith(".") || bare.startsWith("/") || bare.startsWith("\0")) return false;
73
- return bare === "vitest" || bare.startsWith("vitest/") || bare === "@vitest/browser" || bare.startsWith("@vitest/");
86
+ const segments = bare.split("/");
87
+ const packageName = bare.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
88
+ return VITEST_RESOLVER_PACKAGES.has(packageName);
74
89
  }
75
90
  /**
76
91
  * Rescue `vitest` / `@vitest/*` resolution for browser-mode tests.
@@ -79,10 +94,10 @@ function isVitestFamilySpecifier(id) {
79
94
  * and `@vitest/browser` are transitive deps. pnpm's isolated layout only
80
95
  * exposes a package's *direct* deps, so the browser-mode Vite dev server
81
96
  * (rooted at the consumer project) cannot resolve `vitest/internal/browser`,
82
- * `@vitest/expect`, etc. Non-browser tests are unaffected — vitest's own
97
+ * `@vitest/mocker`, etc. Non-browser tests are unaffected — vitest's own
83
98
  * module runner handles resolution there.
84
99
  *
85
- * This plugin re-resolves the `vitest` / `@vitest/*` family through Vite's OWN
100
+ * This plugin re-resolves the explicit Vitest runtime allowlist through Vite's OWN
86
101
  * resolver, but ROOTED at `vite-plus`'s location ([[vitePlusModuleFile]]) and
87
102
  * then the bundled `vitest`'s location ([[getVitestAnchor]]) BEFORE the
88
103
  * project. So every such import binds to the same physical (pinned) Vitest that
@@ -123,10 +138,61 @@ function isVitestFamilySpecifier(id) {
123
138
  * [[vitePlusCoverageVersionGuardPlugin]] fails fast on a mismatch instead.
124
139
  */
125
140
  function vitePlusVitestResolverPlugin() {
141
+ let isVitestServer = false;
126
142
  return {
127
143
  name: "vite-plus:vitest-resolver",
128
144
  enforce: "pre",
145
+ config: {
146
+ order: "post",
147
+ handler(config, { command }) {
148
+ isVitestServer = command === "serve" && !!config.environments?.["__vitest__"];
149
+ if (!isVitestServer || !config.test?.browser?.enabled) return;
150
+ const aliases = config.resolve?.alias;
151
+ const entries = Array.isArray(aliases) ? [...aliases] : Object.entries(aliases ?? {}).map(([find, replacement]) => ({
152
+ find,
153
+ replacement
154
+ }));
155
+ const runtimeRequire = createRequire(getVitestAnchor());
156
+ const targets = new Map([
157
+ "vitest",
158
+ "vitest/internal/browser",
159
+ "vitest/internal/traces",
160
+ "expect-type",
161
+ "magic-string",
162
+ "chai",
163
+ "vite/module-runner"
164
+ ].map((id) => [id, id.startsWith("vitest") ? getVitestImportTarget(id) : runtimeRequire.resolve(id)]));
165
+ if (config.test.browser.provider?.name === "preview") {
166
+ const previewRequire = createRequire(vitePlusRequire.resolve("@vitest/browser-preview"));
167
+ for (const id of ["@testing-library/user-event", "@testing-library/dom"]) targets.set(id, previewRequire.resolve(id));
168
+ }
169
+ for (const [id, replacement] of targets) {
170
+ if (entries.some(({ find }) => typeof find === "string" ? id === find || id.startsWith(`${find}/`) : new RegExp(find).test(id))) continue;
171
+ entries.push({
172
+ find: new RegExp(`^${id}$`),
173
+ replacement
174
+ });
175
+ }
176
+ config.resolve ??= {};
177
+ config.resolve.alias = entries;
178
+ }
179
+ },
180
+ configResolved(config) {
181
+ const seen = /* @__PURE__ */ new Set();
182
+ const plugins = config.plugins;
183
+ const unique = plugins.filter((plugin) => {
184
+ if (!VITE_PLUS_TEST_PLUGIN_NAMES.has(plugin.name)) return true;
185
+ if (seen.has(plugin.name)) return false;
186
+ seen.add(plugin.name);
187
+ return true;
188
+ });
189
+ plugins.splice(0, plugins.length, ...unique);
190
+ },
129
191
  async resolveId(id, importer, options) {
192
+ if (isVitestServer && id === "vite-plus/test") return this.resolve("vitest", importer, {
193
+ ...options,
194
+ skipSelf: true
195
+ });
130
196
  if (!isVitestFamilySpecifier(id)) return null;
131
197
  if (id.includes("?")) return null;
132
198
  const vitestAnchorPath = getVitestAnchor();
@@ -157,10 +223,9 @@ function vitePlusVitestResolverPlugin() {
157
223
  * Absent packages are silently skipped so the server-deps optimizer never
158
224
  * tries to resolve a name that does not exist in the project's node_modules.
159
225
  *
160
- * The check is deferred to a `configResolved` plugin hook so that
161
- * `resolvedConfig.root` points at the actual project root (the value vite has
162
- * already normalised), rather than relying on `process.cwd()` at config-load
163
- * time (which can differ in workspace / monorepo setups).
226
+ * The environment hook adds installed packages to the module-runner options
227
+ * inherited by shared-server projects. The resolved-config hook also handles
228
+ * independent project servers, using each project's resolved root.
164
229
  *
165
230
  * Exported for unit testing.
166
231
  */
@@ -179,18 +244,26 @@ const AUTO_INLINE_DEPS = [
179
244
  *
180
245
  * Exported for unit testing. The `_createRequire` parameter lets tests inject
181
246
  * a controlled resolver without needing to spy on Node's ESM module namespace.
247
+ * Callers may share installation results for the same root within one config load.
182
248
  */
183
- function computeAutoInlineList(existingInline, projectRoot, _createRequire = createRequire) {
249
+ function computeAutoInlineList(existingInline, projectRoot, _createRequire = createRequire, installedPackages = /* @__PURE__ */ new Map()) {
184
250
  if (existingInline === true) return null;
185
- const projectRequire = _createRequire(`${projectRoot}/package.json`);
251
+ let projectRequire;
186
252
  const merged = Array.isArray(existingInline) ? [...existingInline] : [];
187
253
  for (const pkg of AUTO_INLINE_DEPS) {
188
254
  if (merged.some((entry) => entry === pkg || entry instanceof RegExp && entry.test(pkg))) continue;
189
- try {
190
- projectRequire.resolve(pkg);
191
- } catch {
192
- continue;
255
+ let installed = installedPackages.get(pkg);
256
+ if (installed === void 0) {
257
+ projectRequire ??= _createRequire(`${projectRoot}/package.json`);
258
+ try {
259
+ projectRequire.resolve(pkg);
260
+ installed = true;
261
+ } catch {
262
+ installed = false;
263
+ }
264
+ installedPackages.set(pkg, installed);
193
265
  }
266
+ if (!installed) continue;
194
267
  merged.push(pkg);
195
268
  }
196
269
  const hadEntries = Array.isArray(existingInline) ? existingInline.length : 0;
@@ -198,18 +271,47 @@ function computeAutoInlineList(existingInline, projectRoot, _createRequire = cre
198
271
  return merged;
199
272
  }
200
273
  function vitePlusAutoInlineMatcherPlugin() {
274
+ let projectRoot = "";
275
+ let isVitestServer = false;
276
+ const installedByRoot = /* @__PURE__ */ new Map();
277
+ function inlineList(existing, root) {
278
+ root = resolve(root);
279
+ let installed = installedByRoot.get(root);
280
+ if (!installed) {
281
+ installed = /* @__PURE__ */ new Map();
282
+ installedByRoot.set(root, installed);
283
+ }
284
+ return computeAutoInlineList(existing, root, createRequire, installed);
285
+ }
201
286
  return {
202
287
  name: "vite-plus:auto-inline-matcher-deps",
203
288
  enforce: "pre",
289
+ config: {
290
+ order: "post",
291
+ handler(config, { command }) {
292
+ isVitestServer = command === "serve" && !!config.environments?.["__vitest__"];
293
+ projectRoot = resolve(config.root ?? ".");
294
+ installedByRoot.clear();
295
+ }
296
+ },
297
+ configEnvironment(_name, config) {
298
+ if (!isVitestServer) return;
299
+ const existing = config.resolve?.noExternal;
300
+ const merged = inlineList(typeof existing === "string" || existing instanceof RegExp ? [existing] : existing, projectRoot);
301
+ if (merged !== null) {
302
+ config.resolve ??= {};
303
+ config.resolve.noExternal = merged;
304
+ }
305
+ },
204
306
  configResolved(resolvedConfig) {
205
- const testConfig = resolvedConfig.test;
206
- const merged = computeAutoInlineList(testConfig?.server?.deps?.inline, resolvedConfig.root);
207
- if (merged === null) return;
208
- if (!testConfig) resolvedConfig.test = { server: { deps: { inline: merged } } };
209
- else {
210
- if (!testConfig.server) testConfig.server = {};
211
- if (!testConfig.server.deps) testConfig.server.deps = {};
212
- testConfig.server.deps.inline = merged;
307
+ if (!isVitestServer) return;
308
+ const config = resolvedConfig;
309
+ const merged = inlineList(config.test?.server?.deps?.inline, config.root);
310
+ if (merged !== null) {
311
+ config.test ??= {};
312
+ config.test.server ??= {};
313
+ config.test.server.deps ??= {};
314
+ config.test.server.deps.inline = merged;
213
315
  }
214
316
  }
215
317
  };
@@ -340,6 +442,19 @@ function vitePlusCoverageVersionGuardPlugin() {
340
442
  * an optional `test.server.deps.inline`), so a shared helper keeps the
341
443
  * wiring consistent.
342
444
  */
445
+ const VITE_PLUS_TEST_PLUGIN_NAMES = /* @__PURE__ */ new Set([
446
+ "vite-plus:vitest-resolver",
447
+ "vite-plus:auto-inline-matcher-deps",
448
+ "vite-plus:coverage-version-guard"
449
+ ]);
450
+ function withoutVitePlusTestPlugins(plugin) {
451
+ if (Array.isArray(plugin)) return plugin.filter(keepUserPlugin).map(withoutVitePlusTestPlugins);
452
+ if (plugin instanceof Promise) return plugin.then(withoutVitePlusTestPlugins);
453
+ return plugin && VITE_PLUS_TEST_PLUGIN_NAMES.has(plugin.name) ? false : plugin;
454
+ }
455
+ function keepUserPlugin(plugin) {
456
+ return !plugin || !("name" in plugin) || !VITE_PLUS_TEST_PLUGIN_NAMES.has(plugin.name);
457
+ }
343
458
  function injectPluginIntoInlineConfig(config) {
344
459
  return {
345
460
  ...config,
@@ -347,15 +462,13 @@ function injectPluginIntoInlineConfig(config) {
347
462
  vitePlusVitestResolverPlugin(),
348
463
  vitePlusAutoInlineMatcherPlugin(),
349
464
  vitePlusCoverageVersionGuardPlugin(),
350
- ...config.plugins ?? []
465
+ ...(config.plugins ?? []).filter(keepUserPlugin).map(withoutVitePlusTestPlugins)
351
466
  ]
352
467
  };
353
468
  }
354
469
  /**
355
- * Walk `config.test?.projects` and inject the vite-plus plugins into each
356
- * project entry. Vitest spins up an independent Vite pipeline per project, so
357
- * root-level plugins do NOT propagate — without this, files matched by a
358
- * project's `include` glob never get the vitest resolver / auto-inline plugins.
470
+ * Inline projects inherit root plugins by default in Vitest v5. Only projects
471
+ * with inheritance disabled or an external base need their own injection.
359
472
  *
360
473
  * Entry shapes (from `TestProjectConfiguration`):
361
474
  * - string (glob path like `'./packages/*'`) → passed through unchanged.
@@ -377,15 +490,18 @@ function injectPluginIntoProject(project) {
377
490
  if (typeof project === "function") {
378
491
  const wrapped = (env) => {
379
492
  const result = project(env);
380
- if (result instanceof Promise) return result.then(injectPluginIntoInlineConfig);
381
- return injectPluginIntoInlineConfig(result);
493
+ if (result instanceof Promise) return result.then(injectIndependentProject);
494
+ return injectIndependentProject(result);
382
495
  };
383
496
  return wrapped;
384
497
  }
385
- if (project instanceof Promise) return project.then(injectPluginIntoInlineConfig);
386
- if (typeof project === "object" && project !== null) return injectPluginIntoInlineConfig(project);
498
+ if (project instanceof Promise) return project.then(injectIndependentProject);
499
+ if (typeof project === "object" && project !== null) return injectIndependentProject(project);
387
500
  return project;
388
501
  }
502
+ function injectIndependentProject(config) {
503
+ return config.extends === false || typeof config.extends === "string" ? injectPlugin(config) : config;
504
+ }
389
505
  function injectPlugin(config) {
390
506
  const injected = injectPluginIntoInlineConfig(config);
391
507
  const projects = injected.test?.projects;
@@ -412,17 +528,17 @@ function defineConfig$1(config) {
412
528
  }
413
529
  /**
414
530
  * Inject the vite-plus plugins into a `defineProject` export. A project config
415
- * (`UserWorkspaceConfig`) cannot itself nest `test.projects`, so this only
416
- * touches the top-level `plugins` array (no project recursion like
417
- * [[injectPluginIntoConfig]] does).
531
+ * (`UserWorkspaceConfig`) can itself declare nested projects in v5. Referenced
532
+ * configs own a Vite server, so inject at their root and apply inheritance rules
533
+ * to their inline children.
418
534
  */
419
535
  function injectPluginIntoProjectExport(config) {
420
536
  if (typeof config === "function") return (env) => {
421
537
  const result = config(env);
422
- return result instanceof Promise ? result.then(injectPluginIntoInlineConfig) : injectPluginIntoInlineConfig(result);
538
+ return result instanceof Promise ? result.then(injectPlugin) : injectPlugin(result);
423
539
  };
424
- if (config instanceof Promise) return config.then(injectPluginIntoInlineConfig);
425
- return injectPluginIntoInlineConfig(config);
540
+ if (config instanceof Promise) return config.then(injectPlugin);
541
+ return injectPlugin(config);
426
542
  }
427
543
  function defineProject$1(config) {
428
544
  return defineProject(injectPluginIntoProjectExport(config));