unplugin-https-reverse-proxy 4.0.4 → 4.1.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +30 -6
  2. package/dist/{chunk-5R33PUJP.js → chunk-7CA3EIIX.js} +681 -223
  3. package/dist/{chunk-2P7SUCQ3.js → chunk-EY3HXBJ4.js} +0 -26
  4. package/dist/chunk-RKHJN6KY.js +53 -0
  5. package/dist/esbuild.cjs +781 -300
  6. package/dist/esbuild.js +3 -2
  7. package/dist/index.cjs +781 -300
  8. package/dist/index.js +3 -2
  9. package/dist/nuxt.cjs +779 -290
  10. package/dist/nuxt.js +5 -9
  11. package/dist/privileged-helper.cjs +668 -0
  12. package/dist/privileged-helper.d.cts +2 -0
  13. package/dist/privileged-helper.d.ts +2 -0
  14. package/dist/privileged-helper.js +641 -0
  15. package/dist/rollup.cjs +781 -300
  16. package/dist/rollup.js +3 -2
  17. package/dist/rspack.cjs +781 -300
  18. package/dist/rspack.js +3 -2
  19. package/dist/utils.cjs +0 -28
  20. package/dist/utils.d.cts +1 -3
  21. package/dist/utils.d.ts +1 -3
  22. package/dist/utils.js +1 -5
  23. package/dist/vite.cjs +781 -300
  24. package/dist/vite.js +3 -2
  25. package/dist/webpack.cjs +781 -300
  26. package/dist/webpack.js +3 -2
  27. package/package.json +1 -4
  28. package/src/caddy/caddyfile.ts +1 -0
  29. package/src/caddy/index.ts +183 -110
  30. package/src/caddy/privileged.ts +118 -0
  31. package/src/caddy/utils.ts +0 -43
  32. package/src/index.ts +1 -15
  33. package/src/nuxt.ts +1 -6
  34. package/src/privileged/bootstrap.ts +174 -0
  35. package/src/privileged/client.ts +287 -0
  36. package/src/privileged/entry.ts +45 -0
  37. package/src/privileged/hosts-file.ts +142 -0
  38. package/src/privileged/launch.ts +193 -0
  39. package/src/privileged/ports.ts +45 -0
  40. package/src/privileged/protocol.ts +111 -0
  41. package/src/privileged/server.ts +465 -0
  42. package/src/privileged/session.ts +114 -0
  43. package/src/privileged/validation.ts +38 -0
  44. package/src/privileged/windows-elevation.ts +80 -0
  45. package/src/privileged-helper.ts +109 -0
  46. package/src/utils.ts +0 -28
  47. package/src/host/index.ts +0 -52
@@ -1,29 +1,32 @@
1
1
  import {
2
- hmrSseBridgeClientScript,
3
- setupHmrSseBridge
4
- } from "./chunk-C5A7XLKL.js";
5
- import {
6
- chmodRecursive,
7
2
  consola,
8
3
  generateQrcode,
9
4
  getIpv4List,
10
- isAdmin,
11
5
  once
12
- } from "./chunk-2P7SUCQ3.js";
6
+ } from "./chunk-EY3HXBJ4.js";
7
+ import {
8
+ hmrSseBridgeClientScript,
9
+ setupHmrSseBridge
10
+ } from "./chunk-C5A7XLKL.js";
11
+ import {
12
+ decodeMessage,
13
+ serializeMessage,
14
+ splitLines
15
+ } from "./chunk-RKHJN6KY.js";
13
16
 
14
17
  // src/index.ts
15
- import process5 from "node:process";
18
+ import process8 from "node:process";
16
19
  import { Table } from "console-table-printer";
17
20
  import c from "picocolors";
18
21
  import { createUnplugin } from "unplugin";
19
22
 
20
23
  // src/caddy/index.ts
21
- import { spawn } from "node:child_process";
22
- import { chmodSync as chmodSync2, createWriteStream, existsSync as existsSync3, mkdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
23
- import { readFile as readFile2, unlink as unlink3, writeFile } from "node:fs/promises";
24
- import { platform } from "node:os";
25
- import { join as join3 } from "node:path";
26
- import process4 from "node:process";
24
+ import { execFile } from "node:child_process";
25
+ import { chmodSync, createWriteStream, existsSync as existsSync5, mkdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
26
+ import { readFile as readFile3, unlink as unlink3, writeFile as writeFile2 } from "node:fs/promises";
27
+ import { platform as platform3 } from "node:os";
28
+ import { join as join6 } from "node:path";
29
+ import process7 from "node:process";
27
30
 
28
31
  // node_modules/.pnpm/alien-signals@2.0.7/node_modules/alien-signals/esm/system.mjs
29
32
  var ReactiveFlags;
@@ -465,49 +468,6 @@ import { HttpProxyAgent } from "http-proxy-agent";
465
468
  import { HttpsProxyAgent } from "https-proxy-agent";
466
469
  import * as lockfile from "proper-lockfile";
467
470
 
468
- // src/host/index.ts
469
- import { exec } from "node:child_process";
470
- import { chmodSync } from "node:fs";
471
- import process2 from "node:process";
472
- import { promisify } from "node:util";
473
- import hostile from "hostile";
474
- var _setHost = promisify(hostile.set);
475
- var _removeHost = promisify(hostile.remove);
476
- function getPathOfSystemHostsPath() {
477
- return process2.platform === "win32" ? `${process2.env.windir || "C:\\WINDOWS"}\\system32\\drivers\\etc\\hosts` : "/etc/hosts";
478
- }
479
- async function syncHost() {
480
- return new Promise((resolve2, _reject) => {
481
- exec(
482
- process2.platform === "win32" ? "ipconfig /flushdns" : "sudo -E killall -HUP mDNSResponder",
483
- (error, _stdout, _stderr) => {
484
- if (error) {
485
- consola.error(`exec error: ${error}`);
486
- return resolve2(false);
487
- }
488
- return resolve2(true);
489
- }
490
- );
491
- });
492
- }
493
- async function addHost(ip2, host) {
494
- if (process2.platform !== "win32")
495
- chmodSync(getPathOfSystemHostsPath(), 511);
496
- await _setHost("127.0.0.1", "localhost");
497
- await _setHost(ip2, host);
498
- if (ip2 === "localhost")
499
- await _setHost("127.0.0.1", host);
500
- return await syncHost();
501
- }
502
- async function removeHost(ip2, host) {
503
- if (process2.platform !== "win32")
504
- chmodSync(getPathOfSystemHostsPath(), 511);
505
- await _removeHost(ip2, host);
506
- if (ip2 === "localhost")
507
- await _removeHost("127.0.0.1", host);
508
- return await syncHost();
509
- }
510
-
511
471
  // node_modules/.pnpm/@ark+util@0.46.0/node_modules/@ark/util/out/arrays.js
512
472
  var liftArray = (data) => Array.isArray(data) ? data : [data];
513
473
  var spliterate = (arr, predicate) => {
@@ -8831,7 +8791,7 @@ function isIterator(val) {
8831
8791
  function escapeRegex(str) {
8832
8792
  return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
8833
8793
  }
8834
- function promisify2(fn) {
8794
+ function promisify(fn) {
8835
8795
  return function(...args2) {
8836
8796
  return new Promise((resolve2, reject2) => {
8837
8797
  fn(...args2, (err, result) => {
@@ -10167,8 +10127,8 @@ function requireResolve(file) {
10167
10127
  const require2 = createRequire(process.cwd() + "/");
10168
10128
  return require2.resolve(file);
10169
10129
  }
10170
- var statAsync = promisify2(stat);
10171
- var readFileAsync = promisify2(readFile$1);
10130
+ var statAsync = promisify(stat);
10131
+ var readFileAsync = promisify(readFile$1);
10172
10132
  function exists(filepath) {
10173
10133
  return __awaiter(this, void 0, void 0, function* () {
10174
10134
  try {
@@ -13375,6 +13335,7 @@ function validateTemplateContext(ctx) {
13375
13335
  var caddyTemplate = `{
13376
13336
  debug
13377
13337
  auto_https disable_redirects ignore_loaded_certs
13338
+ skip_install_trust
13378
13339
  }
13379
13340
 
13380
13341
  :7601 {
@@ -13461,7 +13422,7 @@ import { unlink as unlink2 } from "node:fs/promises";
13461
13422
  // src/caddy/constants.ts
13462
13423
  import os from "node:os";
13463
13424
  import { join as join2 } from "node:path";
13464
- import process3 from "node:process";
13425
+ import process2 from "node:process";
13465
13426
  import dotenvFlow from "dotenv-flow";
13466
13427
  dotenvFlow.config({
13467
13428
  silent: true
@@ -13471,8 +13432,8 @@ function resolvePath(path) {
13471
13432
  return join2(os.homedir() || "", path.slice(1));
13472
13433
  return path;
13473
13434
  }
13474
- var TEMP_DIR = resolvePath(process3.env.UHRP_CADDY_PATH || process3.env.TEMP || process3.env.TMPDIR || "/tmp");
13475
- var caddyPath = join2(TEMP_DIR, `caddy${process3.platform === "win32" ? ".exe" : ""}`);
13435
+ var TEMP_DIR = resolvePath(process2.env.UHRP_CADDY_PATH || process2.env.TEMP || process2.env.TMPDIR || "/tmp");
13436
+ var caddyPath = join2(TEMP_DIR, `caddy${process2.platform === "win32" ? ".exe" : ""}`);
13476
13437
  var caddyFilePath = join2(TEMP_DIR, "CADDYFILE");
13477
13438
  var caddyConfigPath = join2(TEMP_DIR, ".CADDYFILE.config.json");
13478
13439
  var caddyLockFilePath = join2(TEMP_DIR, "caddylock");
@@ -13651,8 +13612,502 @@ function isCaddyReloadCancellation(line) {
13651
13612
  }
13652
13613
  }
13653
13614
 
13615
+ // src/caddy/privileged.ts
13616
+ import { Buffer as Buffer2 } from "node:buffer";
13617
+ import { EventEmitter } from "node:events";
13618
+ import { dirname as dirname2, join as join5 } from "node:path";
13619
+ import process6 from "node:process";
13620
+ import { fileURLToPath } from "node:url";
13621
+
13622
+ // src/privileged/entry.ts
13623
+ import { existsSync as existsSync3 } from "node:fs";
13624
+ import { join as join3 } from "node:path";
13625
+ import process3 from "node:process";
13626
+ function resolveHelperEntry(options) {
13627
+ const { moduleDir, nodeBin = process3.execPath, exists: exists2 = existsSync3 } = options;
13628
+ for (const name of ["privileged-helper.js", "privileged-helper.cjs", "privileged-helper.mjs"]) {
13629
+ const candidate = join3(moduleDir, name);
13630
+ if (exists2(candidate))
13631
+ return { entry: nodeBin, args: [candidate] };
13632
+ }
13633
+ const source = join3(moduleDir, "privileged-helper.ts");
13634
+ const tsxCli = join3(moduleDir, "../node_modules/tsx/dist/cli.mjs");
13635
+ if (exists2(source) && exists2(tsxCli))
13636
+ return { entry: nodeBin, args: [tsxCli, source] };
13637
+ throw new Error(`privileged helper entry not found in ${moduleDir}. Build the package first.`);
13638
+ }
13639
+
13640
+ // src/privileged/session.ts
13641
+ import { Buffer } from "node:buffer";
13642
+ import { existsSync as existsSync4 } from "node:fs";
13643
+ import { readFile as readFile2, writeFile } from "node:fs/promises";
13644
+ import { platform as platform2 } from "node:os";
13645
+ import { join as join4 } from "node:path";
13646
+
13647
+ // src/privileged/launch.ts
13648
+ import { spawn as spawn2, spawnSync } from "node:child_process";
13649
+ import { randomBytes } from "node:crypto";
13650
+ import { platform } from "node:os";
13651
+ import process5 from "node:process";
13652
+
13653
+ // src/privileged/client.ts
13654
+ import { connect } from "node:net";
13655
+ import process4 from "node:process";
13656
+ var FORWARDED_ENV_KEYS = [
13657
+ "HOME",
13658
+ "USER",
13659
+ "LOGNAME",
13660
+ "TMPDIR",
13661
+ "HTTP_PROXY",
13662
+ "HTTPS_PROXY",
13663
+ "http_proxy",
13664
+ "https_proxy",
13665
+ "NO_PROXY",
13666
+ "no_proxy"
13667
+ ];
13668
+ function collectForwardedEnv(source = process4.env) {
13669
+ const result = {};
13670
+ for (const key of FORWARDED_ENV_KEYS) {
13671
+ const value2 = source[key];
13672
+ if (typeof value2 === "string" && value2 !== "")
13673
+ result[key] = value2;
13674
+ }
13675
+ return result;
13676
+ }
13677
+ var HelperConnectionError = class extends Error {
13678
+ constructor(message) {
13679
+ super(message);
13680
+ this.name = "HelperConnectionError";
13681
+ }
13682
+ };
13683
+ function openSocket(socketPath) {
13684
+ return new Promise((resolve2, reject2) => {
13685
+ const socket = connect(socketPath);
13686
+ function onConnect() {
13687
+ socket.removeListener("error", onError);
13688
+ resolve2(socket);
13689
+ }
13690
+ function onError(error) {
13691
+ socket.removeListener("connect", onConnect);
13692
+ reject2(error);
13693
+ }
13694
+ socket.once("error", onError);
13695
+ socket.once("connect", onConnect);
13696
+ });
13697
+ }
13698
+ async function connectClient(options) {
13699
+ const {
13700
+ socketPath,
13701
+ token,
13702
+ timeoutMs = 12e4,
13703
+ retryIntervalMs = 100,
13704
+ callTimeoutMs = 3e4
13705
+ } = options;
13706
+ const deadline = Date.now() + timeoutMs;
13707
+ let lastError;
13708
+ while (Date.now() < deadline) {
13709
+ try {
13710
+ return await handshake(socketPath, token, callTimeoutMs);
13711
+ } catch (error) {
13712
+ lastError = error;
13713
+ const code = lastError.code;
13714
+ if (code === "EACCES" || lastError instanceof HelperConnectionError)
13715
+ throw lastError;
13716
+ await new Promise((resolve2) => setTimeout(resolve2, retryIntervalMs));
13717
+ }
13718
+ }
13719
+ throw new HelperConnectionError(
13720
+ `privileged helper is not reachable at ${socketPath}: ${(lastError == null ? void 0 : lastError.message) ?? "timed out"}`
13721
+ );
13722
+ }
13723
+ function handshake(socketPath, token, callTimeoutMs) {
13724
+ return new Promise((resolve2, reject2) => {
13725
+ void openSocket(socketPath).then((socket) => {
13726
+ let buffer = "";
13727
+ let settled = false;
13728
+ const fail = (error) => {
13729
+ if (settled)
13730
+ return;
13731
+ settled = true;
13732
+ socket.destroy();
13733
+ reject2(error);
13734
+ };
13735
+ const onData = (chunk) => {
13736
+ if (settled)
13737
+ return;
13738
+ const split2 = splitLines(buffer, chunk.toString("utf8"));
13739
+ buffer = split2.rest;
13740
+ const line = split2.lines[0];
13741
+ if (line === void 0)
13742
+ return;
13743
+ let hello;
13744
+ try {
13745
+ hello = JSON.parse(line);
13746
+ } catch (error) {
13747
+ return fail(new HelperConnectionError(`invalid handshake reply: ${error.message}`));
13748
+ }
13749
+ if (hello.type !== "handshake")
13750
+ return fail(new HelperConnectionError("helper did not answer the handshake"));
13751
+ if (!hello.ok)
13752
+ return fail(new HelperConnectionError(hello.reason ?? "helper rejected the handshake"));
13753
+ settled = true;
13754
+ socket.removeListener("data", onData);
13755
+ socket.removeListener("error", onError);
13756
+ const remaining = split2.lines.slice(1);
13757
+ resolve2(createClient(socket, [split2.rest, ...remaining].filter(Boolean).join("\n"), callTimeoutMs));
13758
+ };
13759
+ function onError(error) {
13760
+ fail(error);
13761
+ }
13762
+ socket.on("data", onData);
13763
+ socket.on("error", onError);
13764
+ const greeting = { type: "handshake", token };
13765
+ socket.write(serializeMessage(greeting));
13766
+ }, reject2);
13767
+ });
13768
+ }
13769
+ function createClient(socket, initialBuffer, callTimeoutMs) {
13770
+ let buffer = initialBuffer;
13771
+ let connected = true;
13772
+ let nextId = 1;
13773
+ const pending = /* @__PURE__ */ new Map();
13774
+ const listeners = /* @__PURE__ */ new Set();
13775
+ socket.on("data", (chunk) => {
13776
+ const split2 = splitLines(buffer, chunk.toString("utf8"));
13777
+ buffer = split2.rest;
13778
+ for (const line of split2.lines) {
13779
+ const decoded = decodeMessage(line);
13780
+ if (!decoded.ok)
13781
+ continue;
13782
+ const message = decoded.message;
13783
+ if (!("id" in message)) {
13784
+ for (const listener of listeners)
13785
+ listener(message);
13786
+ continue;
13787
+ }
13788
+ const entry = pending.get(message.id);
13789
+ if (!entry)
13790
+ continue;
13791
+ pending.delete(message.id);
13792
+ clearTimeout(entry.timer);
13793
+ if (message.ok)
13794
+ entry.resolve(message.result);
13795
+ else
13796
+ entry.reject(new Error(message.error.message));
13797
+ }
13798
+ });
13799
+ const disconnect = () => {
13800
+ if (!connected)
13801
+ return;
13802
+ connected = false;
13803
+ for (const [id, entry] of pending) {
13804
+ clearTimeout(entry.timer);
13805
+ pending.delete(id);
13806
+ entry.reject(new HelperConnectionError("privileged helper connection closed"));
13807
+ }
13808
+ };
13809
+ socket.on("close", disconnect);
13810
+ socket.on("error", disconnect);
13811
+ function call(method, params) {
13812
+ if (!connected)
13813
+ return Promise.reject(new HelperConnectionError("privileged helper is not connected"));
13814
+ const id = nextId++;
13815
+ const request = { id, method, params };
13816
+ return new Promise((resolve2, reject2) => {
13817
+ const timer = setTimeout(() => {
13818
+ pending.delete(id);
13819
+ reject2(new HelperConnectionError(`privileged helper did not answer "${method}" in time`));
13820
+ }, callTimeoutMs);
13821
+ pending.set(id, { resolve: resolve2, reject: reject2, timer });
13822
+ socket.write(serializeMessage(request));
13823
+ });
13824
+ }
13825
+ return {
13826
+ get connected() {
13827
+ return connected;
13828
+ },
13829
+ call,
13830
+ onEvent(listener) {
13831
+ listeners.add(listener);
13832
+ return () => {
13833
+ listeners.delete(listener);
13834
+ };
13835
+ },
13836
+ async close() {
13837
+ disconnect();
13838
+ socket.destroy();
13839
+ }
13840
+ };
13841
+ }
13842
+
13843
+ // src/privileged/windows-elevation.ts
13844
+ import { spawn } from "node:child_process";
13845
+ function quotePowerShell(value2) {
13846
+ return `'${value2.replace(/'/g, "''")}'`;
13847
+ }
13848
+ function buildElevationCommand(options) {
13849
+ const argumentList = options.args.map(quotePowerShell).join(",");
13850
+ const parts = [
13851
+ "Start-Process",
13852
+ "-FilePath",
13853
+ quotePowerShell(options.file)
13854
+ ];
13855
+ if (argumentList)
13856
+ parts.push("-ArgumentList", argumentList);
13857
+ if (options.cwd)
13858
+ parts.push("-WorkingDirectory", quotePowerShell(options.cwd));
13859
+ parts.push("-Verb", "RunAs");
13860
+ parts.push("-WindowStyle", "Hidden");
13861
+ return parts.join(" ");
13862
+ }
13863
+ function spawnElevatedOnWindows(options) {
13864
+ return new Promise((resolve2, reject2) => {
13865
+ const script = buildElevationCommand(options);
13866
+ const child = spawn(
13867
+ "powershell.exe",
13868
+ ["-NoProfile", "-NonInteractive", "-Command", script],
13869
+ { stdio: "ignore", windowsHide: true }
13870
+ );
13871
+ child.once("error", reject2);
13872
+ child.once("exit", (code) => {
13873
+ if (code === 0)
13874
+ return resolve2(child);
13875
+ reject2(new Error(
13876
+ `administrator permission was not granted (PowerShell exited with ${code}). Accept the UAC prompt to let the plugin edit the hosts file and bind ports 80/443.`
13877
+ ));
13878
+ });
13879
+ });
13880
+ }
13881
+
13882
+ // src/privileged/launch.ts
13883
+ function createHelperToken() {
13884
+ return randomBytes(24).toString("hex");
13885
+ }
13886
+ function authenticateSudo(sudoCommand = "sudo") {
13887
+ if (platform() === "win32")
13888
+ return { ok: true };
13889
+ if (spawnSync(sudoCommand, ["-n", "true"], { stdio: "ignore" }).status === 0)
13890
+ return { ok: true };
13891
+ if (spawnSync(sudoCommand, ["-v"], { stdio: "inherit" }).status === 0)
13892
+ return { ok: true };
13893
+ return {
13894
+ ok: false,
13895
+ message: "administrator permission is required to edit the hosts file and bind ports 80/443"
13896
+ };
13897
+ }
13898
+ async function startPrivilegedHelper(options) {
13899
+ var _a4, _b3;
13900
+ const {
13901
+ socketPath,
13902
+ token,
13903
+ helperEntry,
13904
+ helperArgs = [],
13905
+ sudoCommand = "sudo",
13906
+ skipAuth = false,
13907
+ direct = false,
13908
+ env: env2 = process5.env,
13909
+ log,
13910
+ connectTimeoutMs = 12e4
13911
+ } = options;
13912
+ if (!skipAuth && !direct) {
13913
+ const auth = authenticateSudo(sudoCommand);
13914
+ if (!auth.ok)
13915
+ throw new Error(auth.message);
13916
+ }
13917
+ const forwarded = collectForwardedEnv(env2);
13918
+ const forwardedArgs = Object.entries(forwarded).map(([key, value2]) => `${key}=${value2}`);
13919
+ const childArgv = [
13920
+ ...helperArgs,
13921
+ "--socket",
13922
+ socketPath,
13923
+ "--token",
13924
+ token,
13925
+ ...typeof process5.getuid === "function" ? ["--owner-uid", String(process5.getuid())] : [],
13926
+ ...typeof process5.getgid === "function" ? ["--owner-gid", String(process5.getgid())] : [],
13927
+ ...options.caddyStoragePath ? ["--caddy-storage", options.caddyStoragePath] : [],
13928
+ "--caddy",
13929
+ options.caddyBin,
13930
+ "--caddy-config",
13931
+ options.caddyConfigPath
13932
+ ];
13933
+ let child;
13934
+ if (!direct && platform() === "win32") {
13935
+ await spawnElevatedOnWindows({ file: helperEntry, args: childArgv, cwd: process5.cwd() });
13936
+ } else {
13937
+ const command = direct ? helperEntry : sudoCommand;
13938
+ const spawnArgs = direct ? childArgv : ["-n", "env", ...forwardedArgs, helperEntry, ...childArgv];
13939
+ child = spawn2(command, spawnArgs, {
13940
+ stdio: ["ignore", "pipe", "pipe"]
13941
+ });
13942
+ (_a4 = child.stdout) == null ? void 0 : _a4.on("data", (data) => log == null ? void 0 : log(data.toString().trimEnd()));
13943
+ (_b3 = child.stderr) == null ? void 0 : _b3.on("data", (data) => log == null ? void 0 : log(data.toString().trimEnd()));
13944
+ const exited = new Promise((resolve2) => child.once("exit", (code) => resolve2(code)));
13945
+ const earlyExit = await Promise.race([
13946
+ exited,
13947
+ new Promise((resolve2) => setTimeout(() => resolve2(void 0), 500))
13948
+ ]);
13949
+ if (earlyExit !== void 0 && earlyExit !== 0) {
13950
+ throw new Error(
13951
+ `privileged helper exited with code ${earlyExit}. Administrator permission was refused, or sudo is not available.`
13952
+ );
13953
+ }
13954
+ }
13955
+ try {
13956
+ const client = await connectClient({ socketPath, token, timeoutMs: connectTimeoutMs });
13957
+ return {
13958
+ client,
13959
+ async close() {
13960
+ await client.close().catch(() => {
13961
+ });
13962
+ child == null ? void 0 : child.unref();
13963
+ }
13964
+ };
13965
+ } catch (error) {
13966
+ try {
13967
+ child == null ? void 0 : child.kill();
13968
+ } catch {
13969
+ }
13970
+ throw error;
13971
+ }
13972
+ }
13973
+ async function connectExistingHelper(socketPath, token, timeoutMs = 1500) {
13974
+ try {
13975
+ return await connectClient({ socketPath, token, timeoutMs });
13976
+ } catch {
13977
+ return void 0;
13978
+ }
13979
+ }
13980
+
13981
+ // src/privileged/session.ts
13982
+ function tokenPath(runtimeDir) {
13983
+ return join4(runtimeDir, "helper.token");
13984
+ }
13985
+ function sessionSocketPath(runtimeDir) {
13986
+ if (platform2() === "win32")
13987
+ return `\\\\.\\pipe\\uhrp-${Buffer.from(runtimeDir).toString("hex").slice(0, 40)}`;
13988
+ return join4(runtimeDir, "helper.sock");
13989
+ }
13990
+ async function openHelperSession(scope2) {
13991
+ const socketPath = sessionSocketPath(scope2.runtimeDir);
13992
+ if (existsSync4(socketPath) || platform2() === "win32") {
13993
+ const token2 = await readToken(scope2.runtimeDir);
13994
+ if (token2) {
13995
+ const reused = await connectExistingHelper(socketPath, token2);
13996
+ if (reused) {
13997
+ return {
13998
+ client: reused,
13999
+ reused: true,
14000
+ close: async () => {
14001
+ await reused.close();
14002
+ }
14003
+ };
14004
+ }
14005
+ }
14006
+ }
14007
+ const token = createHelperToken();
14008
+ const started = await startPrivilegedHelper({
14009
+ socketPath,
14010
+ token,
14011
+ helperEntry: scope2.helperEntry,
14012
+ helperArgs: scope2.helperArgs,
14013
+ sudoCommand: scope2.sudoCommand,
14014
+ skipAuth: scope2.skipAuth,
14015
+ direct: scope2.direct,
14016
+ env: scope2.env,
14017
+ caddyStoragePath: scope2.caddyStoragePath,
14018
+ caddyBin: scope2.caddyBin,
14019
+ caddyConfigPath: scope2.caddyConfigPath,
14020
+ log: scope2.log
14021
+ });
14022
+ await writeToken(scope2.runtimeDir, token);
14023
+ return {
14024
+ client: started.client,
14025
+ reused: false,
14026
+ close: async () => {
14027
+ await started.close();
14028
+ }
14029
+ };
14030
+ }
14031
+ async function readToken(runtimeDir) {
14032
+ try {
14033
+ const content = await readFile2(tokenPath(runtimeDir), "utf8");
14034
+ const token = content.trim();
14035
+ return token === "" ? void 0 : token;
14036
+ } catch {
14037
+ return void 0;
14038
+ }
14039
+ }
14040
+ async function writeToken(runtimeDir, token) {
14041
+ try {
14042
+ await writeFile(tokenPath(runtimeDir), token, { mode: 384 });
14043
+ } catch {
14044
+ }
14045
+ }
14046
+
14047
+ // src/caddy/privileged.ts
14048
+ function resolvePrivilegedEnv() {
14049
+ const moduleDir = typeof __dirname === "string" ? __dirname : dirname2(fileURLToPath(import.meta.url));
14050
+ const resolved = resolveHelperEntry({ moduleDir });
14051
+ return { helperEntry: resolved.entry, helperArgs: resolved.args };
14052
+ }
14053
+ var HelperCaddyProcess = class extends EventEmitter {
14054
+ constructor(client) {
14055
+ super();
14056
+ this.client = client;
14057
+ this.stdout = new EventEmitter();
14058
+ this.stderr = new EventEmitter();
14059
+ this.finished = false;
14060
+ this.unsubscribe = client.onEvent((event) => this.handleEvent(event));
14061
+ }
14062
+ handleEvent(event) {
14063
+ if (event.type !== "event")
14064
+ return;
14065
+ if (event.kind === "caddy.stdout") {
14066
+ this.stdout.emit("data", Buffer2.from(event.data));
14067
+ return;
14068
+ }
14069
+ if (event.kind === "caddy.stderr") {
14070
+ this.stderr.emit("data", Buffer2.from(event.data));
14071
+ return;
14072
+ }
14073
+ if (event.kind === "caddy.exit") {
14074
+ this.finished = true;
14075
+ this.emit("exit", event.code, event.signal);
14076
+ }
14077
+ }
14078
+ /** Asks the helper to stop Caddy; the helper also stops it on disconnect. */
14079
+ kill() {
14080
+ this.unsubscribe();
14081
+ if (this.finished)
14082
+ return;
14083
+ this.finished = true;
14084
+ void this.client.call("caddy.stop").catch(() => {
14085
+ });
14086
+ }
14087
+ };
14088
+ function caddyStoragePath() {
14089
+ return process6.platform === "win32" ? join5(process6.env.AppData ?? "", "Caddy") : join5(process6.env.HOME ?? "", "Library/Application Support/Caddy");
14090
+ }
14091
+ function openPrivilegedSession(runtimeDir, options) {
14092
+ const env2 = resolvePrivilegedEnv();
14093
+ return openHelperSession({
14094
+ runtimeDir,
14095
+ helperEntry: env2.helperEntry,
14096
+ helperArgs: env2.helperArgs,
14097
+ direct: options.direct,
14098
+ // Caddy keeps its PKI under the user's home; the helper runs it as root, so
14099
+ // it must know which tree to hand back afterwards.
14100
+ caddyStoragePath: caddyStoragePath(),
14101
+ // The binary and Caddyfile are fixed here: the privileged helper must never
14102
+ // execute a path supplied over the socket.
14103
+ caddyBin: options.caddyBin,
14104
+ caddyConfigPath: options.caddyConfigPath,
14105
+ log: options.log
14106
+ });
14107
+ }
14108
+
13654
14109
  // src/caddy/tls-health.ts
13655
- import { checkServerIdentity, connect } from "node:tls";
14110
+ import { checkServerIdentity, connect as connect2 } from "node:tls";
13656
14111
  function assessTlsCertificate(certificate, hostname, now = Date.now(), verifyHostname = checkServerIdentity) {
13657
14112
  if (!certificate.valid_to)
13658
14113
  return { healthy: false, reason: "certificate_missing" };
@@ -13671,7 +14126,7 @@ function assessTlsCertificate(certificate, hostname, now = Date.now(), verifyHos
13671
14126
  }
13672
14127
  function probeLocalTls(hostname, options = {}) {
13673
14128
  const {
13674
- connect: openTlsConnection = connect,
14129
+ connect: openTlsConnection = connect2,
13675
14130
  port = 443,
13676
14131
  timeoutMs = 1e3
13677
14132
  } = options;
@@ -13733,40 +14188,8 @@ function formatTlsHealthFailure(hostname, result) {
13733
14188
  }
13734
14189
 
13735
14190
  // src/caddy/utils.ts
13736
- import { exec as exec2 } from "node:child_process";
13737
- import { createServer } from "node:net";
13738
14191
  import ora from "ora";
13739
14192
  var spinner;
13740
- function tryPort(port) {
13741
- return new Promise((resolve2, _reject) => {
13742
- try {
13743
- const server = createServer().listen(port);
13744
- server.on("listening", () => {
13745
- server.close();
13746
- resolve2(false);
13747
- });
13748
- server.on("error", (err) => {
13749
- if (err.code === "EADDRINUSE")
13750
- resolve2(true);
13751
- server.close();
13752
- });
13753
- } catch {
13754
- resolve2(true);
13755
- }
13756
- });
13757
- }
13758
- async function kill(port) {
13759
- return new Promise((resolve2, reject2) => {
13760
- exec2(`npx @maxbo/free-port ${port} -s`, (err, stdout, _stderr) => {
13761
- if (err) {
13762
- reject2(err);
13763
- } else {
13764
- consola.log(stdout);
13765
- resolve2();
13766
- }
13767
- });
13768
- });
13769
- }
13770
14193
  function getNumber(number2) {
13771
14194
  if (number2 <= 0)
13772
14195
  return "0%";
@@ -13805,26 +14228,26 @@ async function download() {
13805
14228
  if (await testCaddy())
13806
14229
  return caddyPath;
13807
14230
  return new Promise((resolve2, reject2) => {
13808
- if (!existsSync3(TEMP_DIR)) {
14231
+ if (!existsSync5(TEMP_DIR)) {
13809
14232
  mkdirSync(TEMP_DIR, { recursive: true });
13810
- chmodSync2(TEMP_DIR, 511);
14233
+ chmodSync(TEMP_DIR, 448);
13811
14234
  }
13812
14235
  const file = createWriteStream(caddyPath);
13813
- let _platform = platform().toString();
14236
+ let _platform = platform3().toString();
13814
14237
  _platform === "win32" && (_platform = "windows");
13815
- let _arch = process4.arch.toString();
14238
+ let _arch = process7.arch.toString();
13816
14239
  _arch === "x64" && (_arch = "amd64");
13817
14240
  const support = supportList.find((item) => item.platform === _platform && item.arch === _arch);
13818
14241
  if (!support)
13819
14242
  return reject2(new Error("not support"));
13820
14243
  const dowmloadLink = `https://caddyserver.com/api/download?os=${support.platform}&arch=${support.arch}&p=github.com%2Fcaddyserver%2Fforwardproxy`;
13821
- existsSync3(caddyPath) && unlinkSync(caddyPath);
13822
- const httpProxy = process4.env.HTTP_PROXY || process4.env.http_proxy;
13823
- const httpsProxy = process4.env.HTTPS_PROXY || process4.env.https_proxy;
14244
+ existsSync5(caddyPath) && unlinkSync(caddyPath);
14245
+ const httpProxy = process7.env.HTTP_PROXY || process7.env.http_proxy;
14246
+ const httpsProxy = process7.env.HTTPS_PROXY || process7.env.https_proxy;
13824
14247
  const httpAgent = httpProxy ? new HttpProxyAgent(httpProxy) : void 0;
13825
14248
  const httpsAgent = httpsProxy ? new HttpsProxyAgent(httpsProxy) : void 0;
13826
14249
  const chmodCaddyOnce = once(() => {
13827
- chmodSync2(caddyPath, 511);
14250
+ chmodSync(caddyPath, 493);
13828
14251
  });
13829
14252
  got.stream(dowmloadLink, {
13830
14253
  agent: {
@@ -13836,9 +14259,9 @@ async function download() {
13836
14259
  chmodCaddyOnce();
13837
14260
  }).pipe(file).on("finish", () => {
13838
14261
  logProgressOver();
13839
- if (process4.platform === "win32")
14262
+ if (process7.platform === "win32")
13840
14263
  return resolve2(caddyPath);
13841
- chmodSync2(caddyPath, 511);
14264
+ chmodSync(caddyPath, 493);
13842
14265
  resolve2(caddyPath);
13843
14266
  }).on("error", (err) => {
13844
14267
  reject2(err);
@@ -13846,19 +14269,17 @@ async function download() {
13846
14269
  });
13847
14270
  }
13848
14271
  function testCaddy() {
13849
- return new Promise((resolve2, reject2) => {
13850
- if (!existsSync3(caddyPath))
13851
- return resolve2(false);
13852
- chmodSync2(caddyPath, 511);
13853
- const child = process4.platform === "win32" ? spawn(caddyPath, []) : spawn("sudo", ["-E", caddyPath]);
13854
- child.on("close", () => {
14272
+ return new Promise((resolve2) => {
14273
+ if (!existsSync5(caddyPath))
13855
14274
  return resolve2(false);
13856
- });
13857
- child.on("error", (err) => {
13858
- return reject2(err);
13859
- });
13860
- child.stdout.on("data", (_data) => {
13861
- return resolve2(true);
14275
+ try {
14276
+ chmodSync(caddyPath, 493);
14277
+ } catch {
14278
+ }
14279
+ execFile(caddyPath, [], { timeout: 1e4 }, (error, stdout) => {
14280
+ if (error && !stdout)
14281
+ return resolve2(false);
14282
+ resolve2(stdout.length > 0);
13862
14283
  });
13863
14284
  });
13864
14285
  }
@@ -13880,39 +14301,62 @@ function splitHostPort(addr) {
13880
14301
  }
13881
14302
  return { host: addr.slice(0, lastColon), port: addr.slice(lastColon + 1) };
13882
14303
  }
14304
+ var defaultDependencies = {
14305
+ openSession: (runtimeDir) => openPrivilegedSession(runtimeDir, {
14306
+ log: (message) => consola.debug(message),
14307
+ // Both paths are fixed here, before any socket traffic: the privileged
14308
+ // helper must never execute something named in a request.
14309
+ caddyBin: caddyPath,
14310
+ caddyConfigPath: caddyFilePath
14311
+ })
14312
+ };
13883
14313
  var CaddyInstant = class {
13884
- constructor() {
14314
+ constructor(deps = {}) {
13885
14315
  this.inited = false;
13886
14316
  this.stoped = false;
13887
14317
  /** has locked when start */
13888
14318
  this.locked = false;
13889
14319
  this._stopEffects = [];
13890
- testCaddy().then(async () => {
13891
- this.inited = true;
13892
- });
14320
+ this.deps = { ...defaultDependencies, ...deps };
13893
14321
  this.locked = this.checkLock();
13894
14322
  }
13895
14323
  checkLock() {
13896
- if (!existsSync3(caddyLockFilePath))
14324
+ if (!existsSync5(caddyLockFilePath))
13897
14325
  writeFileSync2(caddyLockFilePath, "");
13898
- return lockfile.checkSync(caddyLockFilePath);
14326
+ try {
14327
+ return lockfile.checkSync(caddyLockFilePath);
14328
+ } catch {
14329
+ return false;
14330
+ }
14331
+ }
14332
+ /**
14333
+ * Connects to the privileged helper, starting it once if needed. It is
14334
+ * reused across instances so a second dev server does not ask for a
14335
+ * password again.
14336
+ */
14337
+ async session() {
14338
+ if (this._session && !this._session.client.connected)
14339
+ this._session = void 0;
14340
+ if (!this._session)
14341
+ this._session = await this.deps.openSession(TEMP_DIR);
14342
+ return this._session;
13899
14343
  }
13900
14344
  async getCaddyfile() {
13901
- if (!existsSync3(caddyFilePath)) {
14345
+ if (!existsSync5(caddyFilePath)) {
13902
14346
  this.caddyfile = "";
13903
14347
  return "";
13904
14348
  }
13905
- this.caddyfile = await readFile2(caddyFilePath, "utf-8");
14349
+ this.caddyfile = await readFile3(caddyFilePath, "utf-8");
13906
14350
  return this.caddyfile;
13907
14351
  }
13908
14352
  get caddyRoot() {
13909
- return join3(
13910
- process4.platform === "win32" ? `${process4.env.AppData}/Caddy` : `${process4.env.HOME}/Library/Application Support/Caddy`,
14353
+ return join6(
14354
+ process7.platform === "win32" ? `${process7.env.AppData}/Caddy` : `${process7.env.HOME}/Library/Application Support/Caddy`,
13911
14355
  "./pki/authorities/local"
13912
14356
  );
13913
14357
  }
13914
14358
  async writeCaddyfile() {
13915
- return await writeFile(caddyFilePath, this.caddyfile || "");
14359
+ return await writeFile2(caddyFilePath, this.caddyfile || "");
13916
14360
  }
13917
14361
  async deleteCaddyfile() {
13918
14362
  return await unlink3(caddyFilePath);
@@ -13921,6 +14365,33 @@ var CaddyInstant = class {
13921
14365
  await download();
13922
14366
  this.inited = true;
13923
14367
  }
14368
+ /**
14369
+ * Hands the Caddy storage directory back to the developer. Local CA data
14370
+ * created by an earlier root-owned run must stay readable for `tls internal`
14371
+ * to keep serving the same certificate the browser already trusts.
14372
+ */
14373
+ /**
14374
+ * Installs Caddy's local root CA so the browser stops warning about
14375
+ * `tls internal` certificates. Generating the CA and trusting it are separate
14376
+ * steps: a new CA appears whenever the previous one expires or the storage is
14377
+ * replaced, so this runs on every start instead of once.
14378
+ *
14379
+ * The helper owns both the binary path and the command, so nothing here can
14380
+ * be turned into an arbitrary root execution.
14381
+ */
14382
+ async trustLocalCa(session) {
14383
+ try {
14384
+ const result = await session.client.call("ca.trust");
14385
+ if (result.trusted)
14386
+ consola.debug(`Caddy local CA is trusted
14387
+ ${result.output}`);
14388
+ } catch (error) {
14389
+ consola.warn(
14390
+ `could not install the Caddy root certificate automatically: ${error.message}
14391
+ Run \`${caddyPath} trust\` manually if the browser warns about the certificate.`
14392
+ );
14393
+ }
14394
+ }
13924
14395
  async ensureTlsReady(targetHost) {
13925
14396
  const health = await waitForLocalTls(targetHost);
13926
14397
  if (!health.healthy)
@@ -13972,10 +14443,10 @@ var CaddyInstant = class {
13972
14443
  this._target = target;
13973
14444
  if (!this.inited)
13974
14445
  await this.init();
14446
+ const session = await this.session();
13975
14447
  const sourceHost = splitHostPort(source).host;
13976
14448
  const targetHost = splitHostPort(target).host;
13977
- if (!await addHost(sourceHost, targetHost))
13978
- throw new Error("update host failed");
14449
+ await session.client.call("hosts.add", { ip: sourceHost, host: targetHost });
13979
14450
  consola.success("update host success\n");
13980
14451
  const normalizeBase = (b) => {
13981
14452
  let out = b || "/";
@@ -14010,24 +14481,24 @@ var CaddyInstant = class {
14010
14481
  void this.updateCaddyfile();
14011
14482
  })
14012
14483
  );
14013
- if (!existsSync3(caddyLockFilePath))
14484
+ if (!existsSync5(caddyLockFilePath))
14014
14485
  writeFileSync2(caddyLockFilePath, "");
14015
14486
  if (!this.locked) {
14016
- if (await tryPort(443))
14017
- await kill(443);
14018
- if ((process4.platform === "win32" || !https) && await tryPort(80))
14019
- await kill(80);
14487
+ await session.client.call("port.free", { port: 443 });
14488
+ if (process7.platform === "win32" || !https)
14489
+ await session.client.call("port.free", { port: 80 });
14020
14490
  }
14021
14491
  return new Promise((resolve2, reject2) => {
14022
- var _a4, _b3;
14023
14492
  let startupCheckStarted = false;
14024
14493
  const resolveWhenReady = async () => {
14025
14494
  if (startupCheckStarted)
14026
14495
  return;
14027
14496
  startupCheckStarted = true;
14028
14497
  try {
14029
- if (https)
14498
+ if (https) {
14499
+ await this.trustLocalCa(session);
14030
14500
  await this.ensureTlsReady(targetHost);
14501
+ }
14031
14502
  resolve2();
14032
14503
  } catch (error) {
14033
14504
  if (!this.locked)
@@ -14036,96 +14507,87 @@ var CaddyInstant = class {
14036
14507
  }
14037
14508
  };
14038
14509
  const setupCleanup = () => {
14039
- process4.on("SIGINT", async () => {
14510
+ process7.on("SIGINT", async () => {
14040
14511
  if (this.stoped)
14041
14512
  return;
14042
- process4.stdin.resume();
14513
+ process7.stdin.resume();
14043
14514
  try {
14044
14515
  await this.baseCleanup(restore);
14045
14516
  } finally {
14046
14517
  this.stoped = true;
14047
- process4.nextTick(() => {
14048
- process4.exit();
14518
+ process7.nextTick(() => {
14519
+ process7.exit();
14049
14520
  });
14050
14521
  }
14051
14522
  });
14052
- const originalExit = process4.exit.bind(process4);
14053
- process4.exit = async (code) => {
14054
- const port = Number(splitHostPort(source).port);
14055
- if (!Number.isNaN(port) && await tryPort(port))
14056
- await kill(port);
14057
- const pwd = process4.cwd();
14058
- const viteCacheDir = `${pwd}/node_modules/.vite`;
14059
- if (existsSync3(viteCacheDir))
14060
- await chmodRecursive(viteCacheDir, 511).catch(() => {
14061
- });
14062
- const viteTempCacheDir = `${pwd}/node_modules/.vite-temp`;
14063
- if (existsSync3(viteTempCacheDir))
14064
- await chmodRecursive(viteTempCacheDir, 511).catch(() => {
14065
- });
14066
- const nuxtCacheDir = `${pwd}/.nuxt`;
14067
- if (existsSync3(nuxtCacheDir))
14068
- await chmodRecursive(nuxtCacheDir, 511).catch(() => {
14069
- });
14070
- const webpackCacheDir = `${pwd}/node_modules/.cache`;
14071
- if (existsSync3(webpackCacheDir))
14072
- await chmodRecursive(webpackCacheDir, 511).catch(() => {
14073
- });
14523
+ const originalExit = process7.exit.bind(process7);
14524
+ process7.exit = async (code) => {
14074
14525
  if (this.stoped)
14075
14526
  return originalExit(code);
14076
- process4.stdin.resume();
14527
+ process7.stdin.resume();
14077
14528
  try {
14078
14529
  await this.baseCleanup();
14079
14530
  } finally {
14080
14531
  this.stoped = true;
14081
- process4.nextTick(() => {
14532
+ process7.nextTick(() => {
14082
14533
  originalExit(code);
14083
14534
  });
14084
14535
  }
14085
14536
  };
14086
14537
  };
14087
14538
  if (!this.locked) {
14088
- this._caddyChild = process4.platform !== "win32" ? spawn("sudo", ["-E", caddyPath, "run", "--config", caddyFilePath, "--watch"]) : spawn(caddyPath, ["run", "--config", caddyFilePath, "--watch"]);
14089
14539
  lockfile.lockSync(caddyLockFilePath);
14090
- this._caddyChild.on("error", (err) => {
14091
- return reject2(err);
14092
- });
14093
- (_a4 = this._caddyChild.stderr) == null ? void 0 : _a4.on("data", async (data) => {
14094
- const lines = data.toString().split("\n").map((line) => line.trim());
14095
- for (const line of lines) {
14096
- showCaddyLog && line && console.info(line);
14097
- if (isCaddyReloadCancellation(line)) {
14098
- consola.info("Caddy restarted before TLS issuance completed; retrying.\n");
14099
- continue;
14100
- }
14101
- try {
14102
- if (line.includes("Error:") || line && JSON.parse(line).level === "error") {
14103
- if (line.includes("parsing caddyfile tokens")) {
14104
- consola.error("Caddyfile syntax error, please contact the author:\n", `${this.caddyfile}
14540
+ setupCleanup();
14541
+ void (async () => {
14542
+ try {
14543
+ const child = new HelperCaddyProcess(session.client);
14544
+ this._caddyChild = child;
14545
+ await session.client.call("caddy.start");
14546
+ child.on("exit", (code) => {
14547
+ if (code !== null && code !== 0)
14548
+ reject2(new Error(`Caddy exited with code ${code}`));
14549
+ });
14550
+ child.stderr.on("data", async (data) => {
14551
+ const lines = data.toString().split("\n").map((line) => line.trim());
14552
+ for (const line of lines) {
14553
+ showCaddyLog && line && console.info(line);
14554
+ if (isCaddyReloadCancellation(line)) {
14555
+ consola.info("Caddy restarted before TLS issuance completed; retrying.\n");
14556
+ continue;
14557
+ }
14558
+ try {
14559
+ if (line.includes("Error:") || line && JSON.parse(line).level === "error") {
14560
+ if (line.includes("parsing caddyfile tokens")) {
14561
+ consola.error("Caddyfile syntax error, please contact the author:\n", `${this.caddyfile}
14105
14562
 
14106
14563
  ${line}
14107
14564
  `);
14108
- await this.baseCleanup();
14109
- process4.exit();
14110
- } else {
14111
- consola.error(`${line}
14565
+ await this.baseCleanup();
14566
+ process7.exit();
14567
+ } else {
14568
+ consola.error(`${line}
14112
14569
  `);
14113
- return reject2(line);
14570
+ return reject2(line);
14571
+ }
14572
+ }
14573
+ } catch {
14114
14574
  }
14575
+ if (line.includes("config file changed"))
14576
+ consola.success("Detect added a new reverse proxy config, restarted.\n");
14577
+ if (line.includes("caddy proxying") || line.includes("serving initial"))
14578
+ void resolveWhenReady();
14115
14579
  }
14116
- } catch {
14117
- }
14118
- if (line.includes("config file changed"))
14119
- consola.success("Detect added a new reverse proxy config, restarted.\n");
14120
- if (line.includes("caddy proxying") || line.includes("serving initial"))
14580
+ });
14581
+ child.stdout.on("data", (data) => {
14582
+ consola.info(data.toString());
14121
14583
  void resolveWhenReady();
14584
+ });
14585
+ } catch (error) {
14586
+ if (!this.locked)
14587
+ await this.baseCleanup(restore);
14588
+ reject2(error);
14122
14589
  }
14123
- });
14124
- (_b3 = this._caddyChild.stdout) == null ? void 0 : _b3.on("data", (_data) => {
14125
- consola.info(_data.toString());
14126
- void resolveWhenReady();
14127
- });
14128
- setupCleanup();
14590
+ })();
14129
14591
  } else {
14130
14592
  consola.info("Caddy is running in another process.");
14131
14593
  void (async () => {
@@ -14142,17 +14604,25 @@ ${line}
14142
14604
  });
14143
14605
  }
14144
14606
  async baseCleanup(restore = true) {
14607
+ var _a4;
14145
14608
  this._stopEffects.forEach((fn) => fn());
14609
+ this._stopEffects.length = 0;
14146
14610
  try {
14147
- if (restore && this._source && this._target) {
14148
- if (await removeHost(splitHostPort(this._source).host, splitHostPort(this._target).host))
14149
- consola.success("Restore host success.\n");
14150
- else
14151
- consola.fail("Restore host failed.\n");
14611
+ if (restore && this._source && this._target && this._session) {
14612
+ const sourceHost = splitHostPort(this._source).host;
14613
+ const targetHost = splitHostPort(this._target).host;
14614
+ await this._session.client.call("hosts.remove", { ip: sourceHost, host: targetHost });
14615
+ if (sourceHost === "localhost")
14616
+ await this._session.client.call("hosts.remove", { ip: "127.0.0.1", host: targetHost });
14617
+ consola.success("Restore host success.\n");
14152
14618
  }
14153
14619
  } catch (e) {
14154
- consola.error(e);
14155
- consola.fail("Restore host failed.\n");
14620
+ if (((_a4 = this._session) == null ? void 0 : _a4.client.connected) === false) {
14621
+ consola.debug("hosts entries are restored by the privileged helper on disconnect");
14622
+ } else {
14623
+ consola.error(e);
14624
+ consola.fail("Restore host failed.\n");
14625
+ }
14156
14626
  }
14157
14627
  if (!this.locked && !this.stoped) {
14158
14628
  await this.stopCaddy();
@@ -14177,7 +14647,7 @@ ${line}
14177
14647
  var config;
14178
14648
  var caddy;
14179
14649
  var hmrSseBridgeActive = false;
14180
- var cwd = process5.cwd();
14650
+ var cwd = process8.cwd();
14181
14651
  function colorUrl(url2) {
14182
14652
  return c.green(url2.replace(/:(\d+)\//, (_, port) => `:${c.bold(port)}/`));
14183
14653
  }
@@ -14242,10 +14712,6 @@ var unpluginFactory = (options) => ({
14242
14712
  } = options;
14243
14713
  if (!enable)
14244
14714
  return;
14245
- if (!isAdmin()) {
14246
- consola.warn("please run as administrator");
14247
- return;
14248
- }
14249
14715
  if (!target) {
14250
14716
  consola.fail("please provide target");
14251
14717
  return;
@@ -14281,7 +14747,7 @@ var unpluginFactory = (options) => ({
14281
14747
  },
14282
14748
  webpack(compiler) {
14283
14749
  var _a4, _b3, _c2;
14284
- if (process5.env.NODE_ENV !== "development")
14750
+ if (process8.env.NODE_ENV !== "development")
14285
14751
  return;
14286
14752
  const {
14287
14753
  enable = true,
@@ -14289,10 +14755,6 @@ var unpluginFactory = (options) => ({
14289
14755
  } = options;
14290
14756
  if (!enable)
14291
14757
  return;
14292
- if (!isAdmin()) {
14293
- consola.warn("please run as administrator");
14294
- return;
14295
- }
14296
14758
  if (!target) {
14297
14759
  consola.fail("please provide target");
14298
14760
  return;
@@ -14306,7 +14768,7 @@ var unpluginFactory = (options) => ({
14306
14768
  port: 8080,
14307
14769
  ...compiler.options.devServer,
14308
14770
  // @ts-expect-error vuecli
14309
- ...(_a4 = process5.VUE_CLI_SERVICE) == null ? void 0 : _a4.projectOptions.devServer
14771
+ ...(_a4 = process8.VUE_CLI_SERVICE) == null ? void 0 : _a4.projectOptions.devServer
14310
14772
  };
14311
14773
  const source = `${devServer.host}:${devServer.port}`;
14312
14774
  if (caddy)
@@ -14323,7 +14785,7 @@ var unpluginFactory = (options) => ({
14323
14785
  const _close = (_c2 = compiler.close) == null ? void 0 : _c2.bind(compiler);
14324
14786
  if (_close) {
14325
14787
  compiler.close = async (callback) => {
14326
- process5.on("exit", () => {
14788
+ process8.on("exit", () => {
14327
14789
  _close && _close(callback);
14328
14790
  });
14329
14791
  };
@@ -14345,7 +14807,7 @@ var unpluginFactory = (options) => ({
14345
14807
  },
14346
14808
  async rspack(compiler) {
14347
14809
  var _a4, _b3, _c2, _d2;
14348
- if (process5.env.NODE_ENV !== "development")
14810
+ if (process8.env.NODE_ENV !== "development")
14349
14811
  return;
14350
14812
  const {
14351
14813
  enable = true,
@@ -14353,10 +14815,6 @@ var unpluginFactory = (options) => ({
14353
14815
  } = options;
14354
14816
  if (!enable)
14355
14817
  return;
14356
- if (!isAdmin()) {
14357
- consola.warn("please run as administrator");
14358
- return;
14359
- }
14360
14818
  if (!target) {
14361
14819
  consola.fail("please provide target");
14362
14820
  return;