vite-plus 1.4.0 → 1.5.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 (68) hide show
  1. package/binding/index.cjs +54 -54
  2. package/binding/index.d.cts +31 -0
  3. package/dist/{agent-D8oxxhVR.js → agent-DkQD3xqe.js} +2 -2
  4. package/dist/bin.js +15 -7
  5. package/dist/config/bin.js +5 -5
  6. package/dist/{constants-DRUnJ_Dz.js → constants-D2P2aVKb.js} +6 -2
  7. package/dist/create/bin.js +114 -64
  8. package/dist/{define-config-rPhYIFSn.d.ts → define-config-BrvHRi-G.d.ts} +30 -2
  9. package/dist/{define-config-Cv2P6NT2.cjs → define-config-CwtQqYC1.cjs} +35 -3
  10. package/dist/{define-config-ChwJcu5e.js → define-config-wR57OZG_.js} +30 -5
  11. package/dist/define-config.cjs +2 -1
  12. package/dist/define-config.d.ts +2 -2
  13. package/dist/define-config.js +1 -1
  14. package/dist/{editor-ClL78D8u.js → editor-aOy1T15H.js} +1266 -884
  15. package/dist/hooks/bin.js +2 -2
  16. package/dist/{hooks-xRcJPc-O.js → hooks-w_e2whkQ.js} +40 -21
  17. package/dist/index.cjs +4 -3
  18. package/dist/index.d.ts +2 -2
  19. package/dist/index.js +2 -2
  20. package/dist/lint-plugins.cjs +1 -1
  21. package/dist/migration/bin.js +1302 -311
  22. package/dist/migration/compat/worker.js +1 -1
  23. package/dist/{oxlint-plugin-config-BVpqYdcC.js → oxlint-plugin-config-CHsI_zKo.js} +1 -1
  24. package/dist/oxlint-plugin.js +29 -4
  25. package/dist/pack-bin.js +2 -2
  26. package/dist/{package-DzsomcUD.js → package-DfFo6-E-.js} +1 -1
  27. package/dist/{prompts-GL1vj0wk.js → prompts-C7DI63WP.js} +3 -3
  28. package/dist/register.d.ts +1 -0
  29. package/dist/register.js +12 -0
  30. package/dist/{report-DLHO30yZ.js → report-BEdpIQvC.js} +2 -0
  31. package/dist/{resolve-vite-config-QO6cC0SP.js → resolve-vite-config-33bzSaeT.js} +1 -1
  32. package/dist/{resolve-vite-config-Dn5896A4.js → resolve-vite-config-Cx3cnVVI.js} +2 -2
  33. package/dist/script-esm-hooks.d.ts +5 -2
  34. package/dist/script-esm-hooks.js +5 -2
  35. package/dist/script-preload.cjs +24 -1
  36. package/dist/script-register.js +7 -2
  37. package/dist/script-watch.js +135 -41
  38. package/dist/staged/bin.js +2 -2
  39. package/dist/sync-versions/bin.js +1 -1
  40. package/dist/toolchain.js +13 -13
  41. package/dist/toolchain.json +13 -13
  42. package/dist/{tsconfig-Do6MAG_f.js → tsconfig-BE3Wj9OX.js} +1 -1
  43. package/dist/{tsconfig-LE_mAwe_.js → tsconfig-shNmmCE_.js} +2 -2
  44. package/dist/version.js +2 -2
  45. package/dist/versions.js +6 -6
  46. package/docs/config/check.md +2 -0
  47. package/docs/config/fmt.md +1 -1
  48. package/docs/config/lint.md +1 -1
  49. package/docs/config/run.md +6 -2
  50. package/docs/config/staged.md +1 -1
  51. package/docs/guide/check.md +5 -1
  52. package/docs/guide/ci.md +2 -2
  53. package/docs/guide/create.md +1 -1
  54. package/docs/guide/env.md +1 -1
  55. package/docs/guide/global-cli.md +12 -8
  56. package/docs/guide/homebrew.md +127 -0
  57. package/docs/guide/ide-integration.md +1 -3
  58. package/docs/guide/implode.md +5 -3
  59. package/docs/guide/local-cli.md +21 -0
  60. package/docs/guide/migrate-rules.md +81 -22
  61. package/docs/guide/migrate.md +9 -9
  62. package/docs/guide/run.md +23 -1
  63. package/docs/guide/test.md +1 -1
  64. package/docs/guide/troubleshooting.md +1 -1
  65. package/docs/guide/upgrade.md +12 -6
  66. package/docs/guide/vitest-v5.md +2 -2
  67. package/docs/guide/vpx.md +44 -4
  68. package/package.json +39 -33
@@ -1,4 +1,4 @@
1
- import { n as addMigrationWarning, r as createMigrationReport } from "../../report-DLHO30yZ.js";
1
+ import { n as addMigrationWarning, r as createMigrationReport } from "../../report-BEdpIQvC.js";
2
2
  import { t as ROLLDOWN_COMPAT_RESULT_PREFIX } from "../../protocol-CkNmY-Mr.js";
3
3
  import { writeSync } from "node:fs";
4
4
  // src/migration/compat/manual-chunks.ts
@@ -1,4 +1,4 @@
1
- import { u as VITE_PLUS_NAME } from "./constants-DRUnJ_Dz.js";
1
+ import { u as VITE_PLUS_NAME } from "./constants-D2P2aVKb.js";
2
2
  // src/oxlint-plugin-config.ts
3
3
  const VITE_PLUS_OXLINT_PLUGIN_NAME = VITE_PLUS_NAME;
4
4
  const VITE_PLUS_OXLINT_PLUGIN_SPECIFIER = `${VITE_PLUS_NAME}/oxlint-plugin`;
@@ -1,5 +1,5 @@
1
- import { v as exports } from "./constants-DRUnJ_Dz.js";
2
- import { n as PREFER_VITE_PLUS_IMPORTS_RULE_NAME, r as VITE_PLUS_OXLINT_PLUGIN_NAME } from "./oxlint-plugin-config-BVpqYdcC.js";
1
+ import { v as exports } from "./constants-D2P2aVKb.js";
2
+ import { n as PREFER_VITE_PLUS_IMPORTS_RULE_NAME, r as VITE_PLUS_OXLINT_PLUGIN_NAME } from "./oxlint-plugin-config-CHsI_zKo.js";
3
3
  import { t as vitest_v5_entry_points_default } from "./vitest-v5-entry-points-NyJsFeux.js";
4
4
  import path from "node:path";
5
5
  import fs from "node:fs";
@@ -93,9 +93,14 @@ function quoteSpecifier(literal, replacement) {
93
93
  }
94
94
  const nuxtTestUtilsPackageCache = /* @__PURE__ */ new Map();
95
95
  const oxlintOwnerPackageCache = /* @__PURE__ */ new Map();
96
+ const viteKeeperPackageCache = /* @__PURE__ */ new Map();
97
+ const vitestKeeperPackageCache = /* @__PURE__ */ new Map();
96
98
  function isUpstreamVitestSpecifier(specifier) {
97
99
  return specifier === "vitest" || specifier.startsWith("vitest/");
98
100
  }
101
+ function isVitestFamilySpecifier(specifier) {
102
+ return isUpstreamVitestSpecifier(specifier) || specifier.startsWith("@vitest/") || specifier in vitest_v5_entry_points_default;
103
+ }
99
104
  function nearestPackageMatches(filename, cache, matchesPackage) {
100
105
  if (!path.isAbsolute(filename)) return false;
101
106
  let directory = path.dirname(filename);
@@ -130,6 +135,20 @@ function nearestPackageUsesNuxtTestUtils(filename) {
130
135
  pkg.optionalDependencies
131
136
  ].some((dependencies) => dependencies?.["@nuxt/test-utils"] !== void 0));
132
137
  }
138
+ function dependsOnAtRuntime(pkg, name) {
139
+ return [pkg.dependencies, pkg.peerDependencies].some((dependencies) => dependencies?.[name] !== void 0);
140
+ }
141
+ function isPublishedVitePluginName(name) {
142
+ if (name === void 0) return false;
143
+ const unscoped = name.startsWith("@") ? name.split("/")[1] : name;
144
+ return unscoped !== void 0 && /^(vite-plugin|unplugin)-/.test(unscoped);
145
+ }
146
+ function nearestPackageKeepsVite(filename) {
147
+ return nearestPackageMatches(filename, viteKeeperPackageCache, (pkg) => dependsOnAtRuntime(pkg, "vite") || isPublishedVitePluginName(pkg.name));
148
+ }
149
+ function nearestPackageKeepsVitest(filename) {
150
+ return nearestPackageMatches(filename, vitestKeeperPackageCache, (pkg) => dependsOnAtRuntime(pkg, "vitest"));
151
+ }
133
152
  function nearestPackageOwnsOxlintApi(filename) {
134
153
  return nearestPackageMatches(filename, oxlintOwnerPackageCache, (pkg) => pkg.optionalDependencies?.[OXLINT_PLUGINS_PACKAGE] !== void 0 || [pkg.dependencies, pkg.peerDependencies].some((dependencies) => dependencies?.[OXLINT_PACKAGE] !== void 0 || dependencies?.[OXLINT_PLUGINS_PACKAGE] !== void 0));
135
154
  }
@@ -149,9 +168,11 @@ function reportSpecifier(context, literal, replacement) {
149
168
  function isOxlintApiSpecifier(specifier) {
150
169
  return specifier === OXLINT_PLUGINS_PACKAGE || specifier === OXLINT_PLUGINS_DEV_SUBPATH;
151
170
  }
152
- function maybeReportLiteral(context, literal, { preserveUpstreamVitest, fileIsViteConfig, ownsOxlintApi }) {
171
+ function maybeReportLiteral(context, literal, { preserveUpstreamVitest, fileIsViteConfig, ownsOxlintApi, keepsVite, keepsVitest }) {
153
172
  if (!literal || literal.type !== "Literal" || typeof literal.value !== "string") return;
154
173
  if (preserveUpstreamVitest && isUpstreamVitestSpecifier(literal.value)) return;
174
+ if (keepsVite && isViteSpecifier(literal.value)) return;
175
+ if (keepsVitest && isVitestFamilySpecifier(literal.value)) return;
155
176
  if (!fileIsViteConfig && isViteSpecifier(literal.value)) return;
156
177
  const replacement = rewriteVitePlusImportSpecifier(literal.value);
157
178
  if (!replacement) return;
@@ -185,13 +206,17 @@ const preferVitePlusImportsRule = defineRule({
185
206
  const options = {
186
207
  preserveUpstreamVitest: false,
187
208
  fileIsViteConfig: false,
188
- ownsOxlintApi: false
209
+ ownsOxlintApi: false,
210
+ keepsVite: false,
211
+ keepsVitest: false
189
212
  };
190
213
  return {
191
214
  Program() {
192
215
  options.preserveUpstreamVitest = nearestPackageUsesNuxtTestUtils(context.filename);
193
216
  options.fileIsViteConfig = isViteConfigFile(context.filename);
194
217
  options.ownsOxlintApi = nearestPackageOwnsOxlintApi(context.filename);
218
+ options.keepsVite = nearestPackageKeepsVite(context.filename);
219
+ options.keepsVitest = nearestPackageKeepsVitest(context.filename);
195
220
  },
196
221
  ImportDeclaration(node) {
197
222
  maybeReportLiteral(context, node.source, options);
package/dist/pack-bin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as cac } from "./dist-CdkMvIiQ.js";
3
- import { a as resolveViteConfig } from "./resolve-vite-config-Dn5896A4.js";
3
+ import { a as resolveViteConfig } from "./resolve-vite-config-Cx3cnVVI.js";
4
4
  import module from "node:module";
5
5
  import path from "node:path";
6
6
  import { buildWithConfigs, enableDebug, globalLogger, resolveUserConfig } from "vite/pack";
@@ -64,7 +64,7 @@ const DEFAULT_ENV_PREFIXES = ["VITE_PACK_", "TSDOWN_"];
64
64
  cli.command("[...files]", "Bundle files", {
65
65
  ignoreOptionDefaultValue: true,
66
66
  allowUnknownOptions: true
67
- }).option("--config-loader <loader>", "Config loader to use: auto, native, tsx, unrun", { default: "auto" }).option("--no-config", "Disable config file").option("-f, --format <format>", "Bundle format: esm, cjs, iife, umd", { default: "esm" }).option("--clean", "Clean output directory, --no-clean to disable").option("--deps.never-bundle <module>", "Mark dependencies as external").option("--minify", "Minify output").option("--devtools", "Enable devtools integration").option("--debug [feat]", "Show debug logs").option("--target <target>", "Bundle target, e.g \"es2015\", \"esnext\"").option("-l, --logLevel <level>", "Set log level: info, warn, error, silent").option("--fail-on-warn", "Fail on warnings", { default: true }).option("--no-write", "Disable writing files to disk, incompatible with watch mode").option("-d, --out-dir <dir>", "Output directory", { default: "dist" }).option("--treeshake", "Tree-shake bundle", { default: true }).option("--sourcemap", "Generate source map", { default: false }).option("--shims", "Enable cjs and esm shims", { default: false }).option("--platform <platform>", "Target platform", { default: "node" }).option("--dts", "Generate dts files").option("--publint", "Enable publint", { default: false }).option("--attw", "Enable Are the types wrong integration", { default: false }).option("--unused", "Enable unused dependencies check", { default: false }).option("-w, --watch [path]", "Watch mode").option("--ignore-watch <path>", "Ignore custom paths in watch mode").option("--from-vite [vitest]", "Reuse config from Vite or Vitest").option("--report", "Size report", { default: true }).option("--env.* <value>", "Define compile-time env variables").option("--env-file <file>", "Load environment variables from a file, when used together with --env, variables in --env take precedence").option("--env-prefix <prefix>", "Prefix for env variables to inject into the bundle", { default: DEFAULT_ENV_PREFIXES }).option("--on-success <command>", "Command to run on success").option("--copy <dir>", "Copy files to output dir").option("--tsconfig <tsconfig>", "Set tsconfig path").option("--unbundle", "Unbundle mode").option("--root <dir>", "Root directory of input files").option("--exe", "Bundle as executable").option("-W, --workspace [dir]", "Enable workspace mode").option("--concurrency <count>", "Maximum number of Rolldown builds to run in parallel").option("-F, --filter <pattern>", "Filter configs (cwd or name), e.g. /pkg-name$/ or pkg-name").option("--exports", "Generate export-related metadata for package.json (experimental)").action(async (input, flags) => {
67
+ }).option("--config-loader <loader>", "Config loader to use: auto, native, tsx, unrun", { default: "auto" }).option("--no-config", "Disable config file").option("-f, --format <format>", "Bundle format: esm, cjs, iife, umd", { default: "esm" }).option("--clean", "Clean output directory, --no-clean to disable").option("--deps.never-bundle <module>", "Mark dependencies as external").option("--minify", "Minify output").option("--devtools", "Enable devtools integration").option("--debug [feat]", "Show debug logs").option("--target <target>", "Bundle target, e.g \"es2015\", \"esnext\"").option("-l, --logLevel <level>", "Set log level: info, warn, error, silent").option("--fail-on-warn", "Fail on warnings", { default: true }).option("--no-write", "Disable writing files to disk, incompatible with watch mode").option("-d, --out-dir <dir>", "Output directory", { default: "dist" }).option("--treeshake", "Tree-shake bundle", { default: true }).option("--sourcemap", "Generate source map", { default: false }).option("--shims", "Enable cjs and esm shims", { default: false }).option("--platform <platform>", "Target platform", { default: "node" }).option("--dts", "Generate dts files").option("--publint", "Enable publint", { default: false }).option("--attw", "Enable Are the types wrong integration", { default: false }).option("--unused", "Enable unused dependencies check", { default: false }).option("-w, --watch [path]", "Watch mode").option("--ignore-watch <path>", "Ignore custom paths in watch mode").option("--from-vite [vitest]", "Reuse config from Vite or Vitest").option("--report", "Size report", { default: true }).option("--env.* <value>", "Define compile-time env variables").option("--env-file <file>", "Load environment variables from a file, can be repeated").option("--env-prefix <prefix>", "Prefix for env variables to inject into the bundle", { default: DEFAULT_ENV_PREFIXES }).option("--on-success <command>", "Command to run on success").option("--copy <dir>", "Copy files to output dir").option("--tsconfig <tsconfig>", "Set tsconfig path").option("--unbundle", "Unbundle mode").option("--root <dir>", "Root directory of input files").option("--exe", "Bundle as executable").option("-W, --workspace [dir]", "Enable workspace mode").option("--concurrency <count>", "Maximum number of Rolldown builds to run in parallel").option("-F, --filter <pattern>", "Filter configs (cwd or name), e.g. /pkg-name$/ or pkg-name").option("--exports", "Generate export-related metadata for package.json (experimental)").action(async (input, flags) => {
68
68
  if (input.length > 0) flags.entry = input;
69
69
  if (flags.envPrefix === void 0) flags.envPrefix = DEFAULT_ENV_PREFIXES;
70
70
  async function runBuild() {
@@ -1,4 +1,4 @@
1
- import "./constants-DRUnJ_Dz.js";
1
+ import "./constants-D2P2aVKb.js";
2
2
  import { i as readJsonFile } from "./json-kl84kDyH.js";
3
3
  import { createRequire } from "node:module";
4
4
  import path from "node:path";
@@ -1,10 +1,10 @@
1
1
  import { r as __toESM, t as __commonJSMin } from "./rolldown-runtime-DegdyBIC.js";
2
- import { t as accent } from "./terminal-BcuPUy-j.js";
3
- import { f as VITE_PLUS_VERSION } from "./constants-DRUnJ_Dz.js";
4
- import { a as writeJsonFile, i as readJsonFile } from "./json-kl84kDyH.js";
5
2
  import { _ as isGreaterThanOrEqual, b as safeRegex, g as formatComparableVersion, l as PRERELEASE, n as COERCE, r as COERCE_FULL, u as PRERELEASE_LOOSE, x as tryParse, y as parse } from "./comparison-CmVirWIW-UlEf2maz.js";
6
3
  import { i as runCommandSilently, n as getVpCommand } from "./command-rY79K5NI.js";
4
+ import { a as writeJsonFile, i as readJsonFile } from "./json-kl84kDyH.js";
5
+ import { t as accent } from "./terminal-BcuPUy-j.js";
7
6
  import { t as require_dist } from "./dist-Bs0SObNC.js";
7
+ import { f as VITE_PLUS_VERSION } from "./constants-D2P2aVKb.js";
8
8
  import path from "node:path";
9
9
  import { downloadPackageManager } from "../binding/index.js";
10
10
  import { stripVTControlCharacters, styleText } from "node:util";
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,12 @@
1
+ import { createRequire } from "node:module";
2
+ import * as workerThreads from "node:worker_threads";
3
+ // src/register.ts
4
+ /**
5
+ * Public `node --import vite-plus/register` entry. Reuse the emitted loader files
6
+ * so Node.js caches registration together with the two flags passed by `vpx`.
7
+ */
8
+ if (!workerThreads.isInternalThread) {
9
+ createRequire(import.meta.url)("./script-preload.cjs");
10
+ await import(new URL("./script-register.js", import.meta.url).href);
11
+ }
12
+ export {};
@@ -15,6 +15,8 @@ function createMigrationReport() {
15
15
  eslintMigrated: false,
16
16
  tsupMigrated: false,
17
17
  tsxMigrated: false,
18
+ oxnodeMigrated: false,
19
+ tsNodeMigrated: false,
18
20
  prettierMigrated: false,
19
21
  nodeVersionFileMigrated: false,
20
22
  setupVpVersionUpdatedFileCount: 0,
@@ -1 +1 @@
1
- export { i as resolveUniversalViteConfig } from "./resolve-vite-config-Dn5896A4.js";
1
+ export { i as resolveUniversalViteConfig } from "./resolve-vite-config-Cx3cnVVI.js";
@@ -1,5 +1,5 @@
1
- import { l as VITE_CONFIG_FILES } from "./constants-DRUnJ_Dz.js";
2
- import { u as withConfigMetadataResolution } from "./define-config-ChwJcu5e.js";
1
+ import { d as withConfigMetadataResolution } from "./define-config-wR57OZG_.js";
2
+ import { l as VITE_CONFIG_FILES } from "./constants-D2P2aVKb.js";
3
3
  import path from "node:path";
4
4
  import { findMonorepoRoot } from "../binding/index.js";
5
5
  import fs from "node:fs";
@@ -1,8 +1,11 @@
1
1
  import { InitializeHook, LoadHook, ResolveHook } from "node:module";
2
+ import { FrozenTsconfig } from "../binding/index.js";
2
3
  import { MessagePort } from "node:worker_threads";
3
- /** Receives the port `script-register.ts` relays watch reports through. */
4
+ /** Receives the frozen loader settings and watch relay from `script-register.ts`. */
4
5
  export declare const initialize: InitializeHook<{
6
+ tsconfig: FrozenTsconfig;
7
+ transformDeps: string;
5
8
  watchPort?: MessagePort;
6
- } | undefined>;
9
+ }>;
7
10
  export declare const resolve: ResolveHook;
8
11
  export declare const load: LoadHook;
@@ -7,9 +7,11 @@ const resolveHook = (specifier, context, nextResolve) => resolveWithOxcNode(oxcN
7
7
  const loadHook = (url, context, nextLoad) => oxcNode.load(url, context, nextLoad, HELPER_MODULE_NAME);
8
8
  /** Under watch mode, the hooks wrapped to report what each call read or looked for. */
9
9
  let watchHooks;
10
- /** Receives the port `script-register.ts` relays watch reports through. */
10
+ /** Receives the frozen loader settings and watch relay from `script-register.ts`. */
11
11
  const initialize = (data) => {
12
- const port = data?.watchPort;
12
+ oxcNode.initializeLoader(data.tsconfig.path, data.tsconfig.source);
13
+ oxcNode.setTransformDeps(data.transformDeps);
14
+ const port = data.watchPort;
13
15
  if (port) {
14
16
  port.unref();
15
17
  const sink = (message) => port.postMessage(message);
@@ -17,6 +19,7 @@ const initialize = (data) => {
17
19
  resolve: withFlush(resolveHook, sink, oxcNode.takeWatchDependencies),
18
20
  load: withFlush(loadHook, sink, oxcNode.takeWatchDependencies)
19
21
  };
22
+ oxcNode.enableWatchReport();
20
23
  }
21
24
  };
22
25
  const resolve = (specifier, context, nextResolve) => (watchHooks?.resolve ?? resolveHook)(specifier, context, nextResolve);
@@ -292,6 +292,28 @@ function loadOxcNode() {
292
292
  return (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href)("../binding/index.cjs").oxcNode;
293
293
  }
294
294
  const WATCH_SINK = Symbol.for("vite-plus:script-watch-sink");
295
+ const SCRIPT_CONFIG = Symbol.for("vite-plus:script-config");
296
+ /**
297
+ * Capture this JavaScript thread's configuration before its first resolve. Worker
298
+ * environments can differ from the native process environment, including clearing
299
+ * the parent's variables. Both emitted preload entries share this selection.
300
+ */
301
+ function threadScriptConfig() {
302
+ const holder = globalThis;
303
+ if (holder[SCRIPT_CONFIG] === void 0) {
304
+ const source = [
305
+ "VP_SCRIPT_TSCONFIG",
306
+ "TSX_TSCONFIG_PATH",
307
+ "TS_NODE_PROJECT",
308
+ "OXC_TSCONFIG_PATH"
309
+ ].find((name) => process.env[name]);
310
+ holder[SCRIPT_CONFIG] = {
311
+ path: source ? process.env[source] : void 0,
312
+ source: source === "TS_NODE_PROJECT" || source === "OXC_TSCONFIG_PATH" ? source : void 0
313
+ };
314
+ }
315
+ return holder[SCRIPT_CONFIG];
316
+ }
295
317
  /**
296
318
  * Where this thread reports the files watch mode restarts on, or `null` when nobody is
297
319
  * watching (see oxc-node's `watchSink()`). It opens a channel, so it runs once per thread:
@@ -409,7 +431,8 @@ if (node_worker_threads.isMainThread) installSignalAck();
409
431
  const oxcNode = loadOxcNode();
410
432
  const watch = threadWatchSink();
411
433
  if (watch) oxcNode.enableWatchReport();
412
- oxcNode.setTsconfigPath(process.env.VP_SCRIPT_TSCONFIG);
434
+ const tsconfig = threadScriptConfig();
435
+ oxcNode.initializeLoader(tsconfig.path, tsconfig.source);
413
436
  oxcNode.setTransformDeps("typescript");
414
437
  (0, node_module.setSourceMapsSupport)(true, {
415
438
  nodeModules: true,
@@ -12,10 +12,15 @@ import * as NodeModule from "node:module";
12
12
  */
13
13
  const { register } = NodeModule;
14
14
  if (!canRegisterSyncHooks(process.versions.node)) {
15
+ const oxcNode = loadOxcNode();
15
16
  const watch = threadWatchSink();
16
- const watchPort = watch ? createRelay(watch, loadOxcNode().takeWatchDependencies) : void 0;
17
+ const watchPort = watch ? createRelay(watch, oxcNode.takeWatchDependencies) : void 0;
17
18
  register(new URL("./script-esm-hooks.js", import.meta.url), {
18
- data: { watchPort },
19
+ data: {
20
+ tsconfig: oxcNode.freezeTsconfig(process.cwd()),
21
+ transformDeps: oxcNode.freezeTransformDeps(),
22
+ watchPort
23
+ },
19
24
  transferList: watchPort ? [watchPort] : []
20
25
  });
21
26
  }
@@ -427,12 +427,18 @@ function childNodeOptions(env, envFiles, read) {
427
427
  }
428
428
  return fromFiles;
429
429
  }
430
- /** The child env for `--tsconfig`: oxc-node reads TS_NODE_PROJECT before OXC_TSCONFIG_PATH. */
430
+ /**
431
+ * The child env for `--tsconfig`. oxc-node reads TS_NODE_PROJECT before OXC_TSCONFIG_PATH,
432
+ * so both name the config: Node.js keeps a variable the environment already has, so an
433
+ * `--env-file` that sets either one cannot override it (issue #876).
434
+ */
431
435
  function tsconfigEnv(tsconfig, cwd) {
432
- return tsconfig ? {
433
- OXC_TSCONFIG_PATH: resolve(cwd, tsconfig),
434
- TS_NODE_PROJECT: void 0
435
- } : {};
436
+ if (!tsconfig) return {};
437
+ const path = resolve(cwd, tsconfig);
438
+ return {
439
+ OXC_TSCONFIG_PATH: path,
440
+ TS_NODE_PROJECT: path
441
+ };
436
442
  }
437
443
  // ../../oxc-node/packages/cli/src/run.ts
438
444
  /** The signals oxnode passes on to the app. On Windows it only listens, so it outlives the app. */
@@ -1255,20 +1261,26 @@ function parseProcStat(text) {
1255
1261
  const close = text.lastIndexOf(")");
1256
1262
  if (close === -1) return null;
1257
1263
  const pid = Number.parseInt(text, 10);
1258
- const ppid = Number(text.slice(close + 1).trim().split(/\s+/)[1]);
1259
- return Number.isInteger(pid) && Number.isInteger(ppid) ? {
1264
+ const fields = text.slice(close + 1).trim().split(/\s+/);
1265
+ const ppid = Number(fields[1]);
1266
+ if (!Number.isInteger(pid) || !Number.isInteger(ppid)) return null;
1267
+ return {
1260
1268
  pid,
1261
- ppid
1262
- } : null;
1269
+ ppid,
1270
+ zombie: /^[ZXx]/.test(fields[0]) || void 0,
1271
+ start: fields[19]
1272
+ };
1263
1273
  }
1264
- /** The output of `ps -A -o pid=,ppid=`. */
1274
+ /** The output of `ps -A -o pid=,ppid=,stat=,lstart=`, or of `ps -A -o pid=,ppid=`. */
1265
1275
  function parsePs(text) {
1266
1276
  const rows = [];
1267
1277
  for (const line of text.split("\n")) {
1268
- const m = /^\s*(\d+)\s+(\d+)\s*$/.exec(line);
1278
+ const m = /^\s*(\d+)\s+(\d+)(?:\s+(\S+)(?:\s+(\S.*?))?)?\s*$/.exec(line);
1269
1279
  if (m) rows.push({
1270
1280
  pid: Number(m[1]),
1271
- ppid: Number(m[2])
1281
+ ppid: Number(m[2]),
1282
+ zombie: m[3]?.startsWith("Z") || void 0,
1283
+ start: m[4]
1272
1284
  });
1273
1285
  }
1274
1286
  return rows;
@@ -1292,35 +1304,82 @@ function descendants(table, pid) {
1292
1304
  }
1293
1305
  return out;
1294
1306
  }
1307
+ /** The rows of every process below `pid`, parents first. */
1308
+ function subtree(table, pid) {
1309
+ const byPid = new Map(table.map((r) => [r.pid, r]));
1310
+ return descendants(table, pid).map((p) => byPid.get(p));
1311
+ }
1295
1312
  /** Every process on the machine: `/proc` on Linux, where `ps` may be missing (slim containers), `ps` elsewhere. */
1296
1313
  function processTable() {
1297
- try {
1298
- if (process.platform === "linux") {
1299
- const rows = [];
1300
- for (const name of readdirSync("/proc")) {
1301
- if (!/^\d+$/.test(name)) continue;
1302
- try {
1303
- const row = parseProcStat(readFileSync(`/proc/${name}/stat`, "utf8"));
1304
- if (row) rows.push(row);
1305
- } catch {}
1306
- }
1307
- return rows;
1314
+ if (process.platform === "linux") try {
1315
+ const rows = [];
1316
+ for (const name of readdirSync("/proc")) {
1317
+ if (!/^\d+$/.test(name)) continue;
1318
+ try {
1319
+ const row = parseProcStat(readFileSync(`/proc/${name}/stat`, "utf8"));
1320
+ if (row) rows.push(row);
1321
+ } catch {}
1308
1322
  }
1323
+ return rows;
1324
+ } catch {
1325
+ return [];
1326
+ }
1327
+ for (const columns of ["pid=,ppid=,stat=,lstart=", "pid=,ppid="]) try {
1309
1328
  return parsePs(execFileSync("ps", [
1310
1329
  "-A",
1311
1330
  "-o",
1312
- "pid=,ppid="
1313
- ], { encoding: "utf8" }));
1314
- } catch {
1315
- return [];
1331
+ columns
1332
+ ], {
1333
+ encoding: "utf8",
1334
+ stdio: [
1335
+ "ignore",
1336
+ "pipe",
1337
+ "ignore"
1338
+ ]
1339
+ }));
1340
+ } catch {}
1341
+ return [];
1342
+ }
1343
+ /**
1344
+ * Which of `rows` still run, by `table`, plus what they started since, parents first.
1345
+ * Gone: no row, a zombie, or another start (the PID was reused). A failed read (`[]`) means none.
1346
+ */
1347
+ function stillRunning(rows, table) {
1348
+ const now = new Map(table.map((r) => [r.pid, r]));
1349
+ const out = [];
1350
+ const seen = /* @__PURE__ */ new Set();
1351
+ for (const r of rows) {
1352
+ const row = now.get(r.pid);
1353
+ if (!row || row.start !== r.start || seen.has(r.pid)) continue;
1354
+ for (const p of [row.pid, ...descendants(table, row.pid)]) {
1355
+ const found = now.get(p);
1356
+ if (seen.has(p) || found.zombie) continue;
1357
+ seen.add(p);
1358
+ out.push(found);
1359
+ }
1316
1360
  }
1361
+ return out;
1317
1362
  }
1318
- /** SIGKILL the child and everything it started, so a grandchild cannot keep a port busy. */
1319
- function killTree(child) {
1320
- const pid = child.pid;
1321
- if (pid === void 0) return;
1363
+ /** Send `sig` to each, and keep the ones it reached: ESRCH is gone, EPERM is not ours to wait on. */
1364
+ function signalAll(rows, sig) {
1365
+ return rows.filter((r) => {
1366
+ try {
1367
+ process.kill(r.pid, sig);
1368
+ return true;
1369
+ } catch {
1370
+ return false;
1371
+ }
1372
+ });
1373
+ }
1374
+ /**
1375
+ * SIGKILL the child, everything it started, and what is left of `known` with what that
1376
+ * started since, so a grandchild cannot keep a port busy. Returns what it reached besides
1377
+ * the child.
1378
+ */
1379
+ function killTree(child, known = []) {
1380
+ const pid = child?.pid;
1322
1381
  if (process.platform === "win32") {
1323
- spawn("taskkill", [
1382
+ if (child && pid !== void 0) spawn("taskkill", [
1324
1383
  "/pid",
1325
1384
  String(pid),
1326
1385
  "/T",
@@ -1329,11 +1388,12 @@ function killTree(child) {
1329
1388
  stdio: "ignore",
1330
1389
  windowsHide: true
1331
1390
  }).on("error", () => child.kill());
1332
- return;
1391
+ return [];
1333
1392
  }
1334
- for (const p of [pid, ...descendants(processTable(), pid)]) try {
1335
- process.kill(p, "SIGKILL");
1336
- } catch {}
1393
+ const table = processTable();
1394
+ const rows = stillRunning(pid === void 0 ? known : [...subtree(table, pid), ...known], table);
1395
+ child?.kill("SIGKILL");
1396
+ return signalAll(rows, "SIGKILL");
1337
1397
  }
1338
1398
  // ../../oxc-node/packages/cli/src/watch/log.ts
1339
1399
  let color;
@@ -1623,6 +1683,11 @@ function parseWatchMessage(msg) {
1623
1683
  }
1624
1684
  // ../../oxc-node/packages/cli/src/watch/command.ts
1625
1685
  const isBareReturn = (chunk) => /[\r\n]/.test(chunk) && chunk.replace(/[\r\n]/g, "") === "";
1686
+ /** How soon a rerun looks again for what the app left running: fast first, then every 250 ms. */
1687
+ const TREE_POLL_MS = 25;
1688
+ const TREE_POLL_MAX_MS = 250;
1689
+ /** How long after a force kill oxnode waits for what is left: SIGKILL cannot end a process stuck on a hung mount. */
1690
+ const FORCE_WAIT_MS = 1e3;
1626
1691
  /**
1627
1692
  * Run the watcher until it stops, and resolve with the exit code. Until then it owns
1628
1693
  * SIGINT, SIGTERM and SIGHUP, stdin (for Return) and the process's IPC channel.
@@ -1697,6 +1762,26 @@ function runWatch(argv, options = {}) {
1697
1762
  const nodeArgs = [...loaderArgs, ...args.nodeArgs];
1698
1763
  const timers = /* @__PURE__ */ new Map();
1699
1764
  let state = { k: "idle" };
1765
+ let tree = [];
1766
+ let forcedAt;
1767
+ let treeTimer;
1768
+ /** Signal what is left of `tree` once, and call `then` when all of it is gone. */
1769
+ const afterTree = (then, tick = 0) => {
1770
+ if (tree.length) {
1771
+ tree = stillRunning(tree, processTable());
1772
+ if (tick === 0 || forcedAt !== void 0) {
1773
+ const sig = forcedAt === void 0 ? cfg.killSignal : "SIGKILL";
1774
+ tree = signalAll(tree, sig);
1775
+ }
1776
+ }
1777
+ if (tree.length && forcedAt !== void 0 && Date.now() - forcedAt >= FORCE_WAIT_MS) {
1778
+ log(`${tree.map((r) => r.pid).join(" ")} did not stop after a force kill, going on`);
1779
+ tree = [];
1780
+ }
1781
+ if (tree.length === 0) return then();
1782
+ if (tick === 0) debug(`waiting for ${tree.map((r) => r.pid).join(" ")}`);
1783
+ treeTimer = setTimeout(() => afterTree(then, tick + 1), Math.min(TREE_POLL_MAX_MS, TREE_POLL_MS * 2 ** tick));
1784
+ };
1700
1785
  const display = (p) => {
1701
1786
  const rel = path.relative(cwd, p);
1702
1787
  return rel && !rel.startsWith("..") && !path.isAbsolute(rel) ? `.${path.sep}${rel}` : p;
@@ -1754,6 +1839,8 @@ function runWatch(argv, options = {}) {
1754
1839
  }));
1755
1840
  return;
1756
1841
  }
1842
+ tree = [];
1843
+ forcedAt = void 0;
1757
1844
  newRun();
1758
1845
  const c = spawn(process$1.execPath, nodeArgs, {
1759
1846
  env,
@@ -1786,11 +1873,11 @@ function runWatch(argv, options = {}) {
1786
1873
  c.on("exit", (code, signal) => {
1787
1874
  if (child !== c) return;
1788
1875
  child = void 0;
1789
- dispatch({
1876
+ afterTree(() => dispatch({
1790
1877
  t: "childExit",
1791
1878
  code,
1792
1879
  signal
1793
- });
1880
+ }));
1794
1881
  });
1795
1882
  if (c.pid !== void 0) debug(`spawn ${c.pid}`);
1796
1883
  };
@@ -1800,11 +1887,16 @@ function runWatch(argv, options = {}) {
1800
1887
  spawnChild();
1801
1888
  break;
1802
1889
  case "kill":
1803
- if (child && process$1.platform === "win32") killTree(child);
1804
- else child?.kill(e.sig);
1890
+ if (!child) break;
1891
+ if (process$1.platform === "win32") killTree(child);
1892
+ else {
1893
+ if (child.pid !== void 0) tree = subtree(processTable(), child.pid);
1894
+ child.kill(e.sig);
1895
+ }
1805
1896
  break;
1806
1897
  case "killTree":
1807
- if (child) killTree(child);
1898
+ forcedAt ??= Date.now();
1899
+ tree = killTree(child, tree);
1808
1900
  break;
1809
1901
  case "clearScreen":
1810
1902
  process$1.stdout.write("\x1Bc");
@@ -1856,6 +1948,8 @@ function runWatch(argv, options = {}) {
1856
1948
  process$1.stdin.unref?.();
1857
1949
  };
1858
1950
  function finish(code) {
1951
+ clearTimeout(treeTimer);
1952
+ tree = [];
1859
1953
  for (const t of timers.values()) clearTimeout(t);
1860
1954
  timers.clear();
1861
1955
  signals.dispose();
@@ -1,8 +1,8 @@
1
1
  import { r as __toESM } from "../rolldown-runtime-DegdyBIC.js";
2
- import { i as log, n as errorMsg, o as printHeader } from "../terminal-BcuPUy-j.js";
3
- import { a as resolveViteConfig } from "../resolve-vite-config-Dn5896A4.js";
4
2
  import { t as require_picomatch } from "../picomatch-DEUoj81q.js";
3
+ import { a as resolveViteConfig } from "../resolve-vite-config-Cx3cnVVI.js";
5
4
  import { t as unwrapCliParseOutcome } from "../cli-parse-aeUeFDlC.js";
5
+ import { i as log, n as errorMsg, o as printHeader } from "../terminal-BcuPUy-j.js";
6
6
  import { createRequire } from "node:module";
7
7
  import path, { basename, delimiter, dirname, normalize, resolve } from "node:path";
8
8
  import { fileURLToPath, pathToFileURL } from "node:url";
@@ -1,7 +1,7 @@
1
1
  import { c as modify, l as parse$1, o as applyEdits, t as detectFormattingOptions } from "../json-kl84kDyH.js";
2
- import { n as isAlignableVitestEcosystemPackage } from "../vitest-ecosystem-BeEYz-qF.js";
3
2
  import { i as normalizeRange, t as extractOverrideTargetName } from "../package-overrides-Ci8GXouY.js";
4
3
  import { t as require_dist } from "../dist-Bs0SObNC.js";
4
+ import { n as isAlignableVitestEcosystemPackage } from "../vitest-ecosystem-BeEYz-qF.js";
5
5
  import path from "node:path";
6
6
  import fsPromises from "node:fs/promises";
7
7
  import { Buffer } from "node:buffer";