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

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 (53) hide show
  1. package/README.md +30 -6
  2. package/dist/{chunk-2P7SUCQ3.js → chunk-EY3HXBJ4.js} +0 -26
  3. package/dist/{chunk-5R33PUJP.js → chunk-HBXMM25C.js} +765 -229
  4. package/dist/chunk-RKHJN6KY.js +53 -0
  5. package/dist/chunk-WOMR3ZLM.js +17 -0
  6. package/dist/esbuild.cjs +870 -306
  7. package/dist/esbuild.js +4 -2
  8. package/dist/index.cjs +870 -306
  9. package/dist/index.js +4 -2
  10. package/dist/nuxt.cjs +842 -292
  11. package/dist/nuxt.js +6 -9
  12. package/dist/privilege-state.cjs +44 -0
  13. package/dist/privilege-state.d.cts +7 -0
  14. package/dist/privilege-state.d.ts +7 -0
  15. package/dist/privilege-state.js +10 -0
  16. package/dist/privileged-helper.cjs +668 -0
  17. package/dist/privileged-helper.d.cts +2 -0
  18. package/dist/privileged-helper.d.ts +2 -0
  19. package/dist/privileged-helper.js +641 -0
  20. package/dist/rollup.cjs +870 -306
  21. package/dist/rollup.js +4 -2
  22. package/dist/rspack.cjs +870 -306
  23. package/dist/rspack.js +4 -2
  24. package/dist/utils.cjs +0 -28
  25. package/dist/utils.d.cts +1 -3
  26. package/dist/utils.d.ts +1 -3
  27. package/dist/utils.js +1 -5
  28. package/dist/vite.cjs +870 -306
  29. package/dist/vite.js +4 -2
  30. package/dist/webpack.cjs +870 -306
  31. package/dist/webpack.js +4 -2
  32. package/package.json +1 -4
  33. package/src/caddy/caddyfile.ts +1 -0
  34. package/src/caddy/index.ts +184 -110
  35. package/src/caddy/privileged.ts +121 -0
  36. package/src/caddy/utils.ts +0 -43
  37. package/src/index.ts +49 -22
  38. package/src/nuxt.ts +1 -6
  39. package/src/privilege-state.ts +23 -0
  40. package/src/privileged/bootstrap.ts +174 -0
  41. package/src/privileged/client.ts +287 -0
  42. package/src/privileged/entry.ts +73 -0
  43. package/src/privileged/hosts-file.ts +142 -0
  44. package/src/privileged/launch.ts +235 -0
  45. package/src/privileged/ports.ts +45 -0
  46. package/src/privileged/protocol.ts +111 -0
  47. package/src/privileged/server.ts +465 -0
  48. package/src/privileged/session.ts +117 -0
  49. package/src/privileged/validation.ts +38 -0
  50. package/src/privileged/windows-elevation.ts +80 -0
  51. package/src/privileged-helper.ts +109 -0
  52. package/src/utils.ts +0 -28
  53. package/src/host/index.ts +0 -52
package/dist/index.cjs CHANGED
@@ -36,18 +36,18 @@ __export(src_exports, {
36
36
  vitePrintUrls: () => vitePrintUrls
37
37
  });
38
38
  module.exports = __toCommonJS(src_exports);
39
- var import_node_process5 = __toESM(require("process"), 1);
39
+ var import_node_process8 = __toESM(require("process"), 1);
40
40
  var import_console_table_printer = require("console-table-printer");
41
41
  var import_picocolors2 = __toESM(require("picocolors"), 1);
42
42
  var import_unplugin = require("unplugin");
43
43
 
44
44
  // src/caddy/index.ts
45
- var import_node_child_process4 = require("child_process");
46
- var import_node_fs3 = require("fs");
45
+ var import_node_child_process3 = require("child_process");
46
+ var import_node_fs4 = require("fs");
47
47
  var import_promises3 = require("fs/promises");
48
- var import_node_os3 = require("os");
49
- var import_node_path3 = require("path");
50
- var import_node_process4 = __toESM(require("process"), 1);
48
+ var import_node_os5 = require("os");
49
+ var import_node_path5 = require("path");
50
+ var import_node_process7 = __toESM(require("process"), 1);
51
51
 
52
52
  // node_modules/.pnpm/alien-signals@2.0.7/node_modules/alien-signals/esm/system.mjs
53
53
  var ReactiveFlags;
@@ -489,33 +489,14 @@ var import_http_proxy_agent = require("http-proxy-agent");
489
489
  var import_https_proxy_agent = require("https-proxy-agent");
490
490
  var lockfile = __toESM(require("proper-lockfile"), 1);
491
491
 
492
- // src/host/index.ts
493
- var import_node_child_process2 = require("child_process");
494
- var import_node_fs = require("fs");
495
- var import_node_process2 = __toESM(require("process"), 1);
496
- var import_node_util = require("util");
497
- var import_hostile = __toESM(require("hostile"), 1);
498
-
499
492
  // src/utils.ts
500
- var import_node_child_process = require("child_process");
501
- var import_promises = require("fs/promises");
502
493
  var import_node_os = require("os");
503
- var import_node_path = __toESM(require("path"), 1);
504
- var import_node_process = __toESM(require("process"), 1);
505
494
  var import_consola = require("consola");
506
495
  var import_picocolors = __toESM(require("picocolors"), 1);
507
496
  var import_qrcode_terminal = __toESM(require("qrcode-terminal"), 1);
508
497
  var consola = (0, import_consola.createConsola)({
509
498
  level: 3
510
499
  }).withTag("reverse-proxy");
511
- async function chmodRecursive(_path, mode) {
512
- await (0, import_promises.chmod)(_path, mode);
513
- if ((await (0, import_promises.stat)(_path)).isDirectory()) {
514
- const children = await (0, import_promises.readdir)(_path);
515
- for (const child of children)
516
- await chmodRecursive(import_node_path.default.join(_path, child), mode);
517
- }
518
- }
519
500
  function once(fn) {
520
501
  let called = false;
521
502
  return (...args2) => {
@@ -525,18 +506,6 @@ function once(fn) {
525
506
  return fn(...args2);
526
507
  };
527
508
  }
528
- function isAdmin() {
529
- if (import_node_process.default.platform === "win32") {
530
- try {
531
- (0, import_node_child_process.execSync)("net session", { stdio: "ignore" });
532
- return true;
533
- } catch {
534
- return false;
535
- }
536
- } else {
537
- return !!(import_node_process.default.getuid && import_node_process.default.getuid() === 0);
538
- }
539
- }
540
509
  function getIpv4List() {
541
510
  const interfaces = (0, import_node_os.networkInterfaces)();
542
511
  return Object.values(interfaces).flatMap((nInterface) => nInterface ?? []).filter(
@@ -551,44 +520,6 @@ async function generateQrcode(input) {
551
520
  });
552
521
  }
553
522
 
554
- // src/host/index.ts
555
- var _setHost = (0, import_node_util.promisify)(import_hostile.default.set);
556
- var _removeHost = (0, import_node_util.promisify)(import_hostile.default.remove);
557
- function getPathOfSystemHostsPath() {
558
- return import_node_process2.default.platform === "win32" ? `${import_node_process2.default.env.windir || "C:\\WINDOWS"}\\system32\\drivers\\etc\\hosts` : "/etc/hosts";
559
- }
560
- async function syncHost() {
561
- return new Promise((resolve2, _reject) => {
562
- (0, import_node_child_process2.exec)(
563
- import_node_process2.default.platform === "win32" ? "ipconfig /flushdns" : "sudo -E killall -HUP mDNSResponder",
564
- (error, _stdout, _stderr) => {
565
- if (error) {
566
- consola.error(`exec error: ${error}`);
567
- return resolve2(false);
568
- }
569
- return resolve2(true);
570
- }
571
- );
572
- });
573
- }
574
- async function addHost(ip2, host) {
575
- if (import_node_process2.default.platform !== "win32")
576
- (0, import_node_fs.chmodSync)(getPathOfSystemHostsPath(), 511);
577
- await _setHost("127.0.0.1", "localhost");
578
- await _setHost(ip2, host);
579
- if (ip2 === "localhost")
580
- await _setHost("127.0.0.1", host);
581
- return await syncHost();
582
- }
583
- async function removeHost(ip2, host) {
584
- if (import_node_process2.default.platform !== "win32")
585
- (0, import_node_fs.chmodSync)(getPathOfSystemHostsPath(), 511);
586
- await _removeHost(ip2, host);
587
- if (ip2 === "localhost")
588
- await _removeHost("127.0.0.1", host);
589
- return await syncHost();
590
- }
591
-
592
523
  // node_modules/.pnpm/@ark+util@0.46.0/node_modules/@ark/util/out/arrays.js
593
524
  var liftArray = (data) => Array.isArray(data) ? data : [data];
594
525
  var spliterate = (arr, predicate) => {
@@ -1216,29 +1147,29 @@ var timeWithUnnecessarySeconds = /:\d\d:00$/;
1216
1147
  var pad = (value2, length) => String(value2).padStart(length, "0");
1217
1148
 
1218
1149
  // node_modules/.pnpm/@ark+util@0.46.0/node_modules/@ark/util/out/path.js
1219
- var appendStringifiedKey = (path2, prop, ...[opts]) => {
1150
+ var appendStringifiedKey = (path, prop, ...[opts]) => {
1220
1151
  const stringifySymbol = (opts == null ? void 0 : opts.stringifySymbol) ?? printable;
1221
- let propAccessChain = path2;
1152
+ let propAccessChain = path;
1222
1153
  switch (typeof prop) {
1223
1154
  case "string":
1224
- propAccessChain = isDotAccessible(prop) ? path2 === "" ? prop : `${path2}.${prop}` : `${path2}[${JSON.stringify(prop)}]`;
1155
+ propAccessChain = isDotAccessible(prop) ? path === "" ? prop : `${path}.${prop}` : `${path}[${JSON.stringify(prop)}]`;
1225
1156
  break;
1226
1157
  case "number":
1227
- propAccessChain = `${path2}[${prop}]`;
1158
+ propAccessChain = `${path}[${prop}]`;
1228
1159
  break;
1229
1160
  case "symbol":
1230
- propAccessChain = `${path2}[${stringifySymbol(prop)}]`;
1161
+ propAccessChain = `${path}[${stringifySymbol(prop)}]`;
1231
1162
  break;
1232
1163
  default:
1233
1164
  if (opts == null ? void 0 : opts.stringifyNonKey)
1234
- propAccessChain = `${path2}[${opts.stringifyNonKey(prop)}]`;
1165
+ propAccessChain = `${path}[${opts.stringifyNonKey(prop)}]`;
1235
1166
  else {
1236
1167
  throwParseError(`${printable(prop)} must be a PropertyKey or stringifyNonKey must be passed to options`);
1237
1168
  }
1238
1169
  }
1239
1170
  return propAccessChain;
1240
1171
  };
1241
- var stringifyPath = (path2, ...opts) => path2.reduce((s, k) => appendStringifiedKey(s, k, ...opts), "");
1172
+ var stringifyPath = (path, ...opts) => path.reduce((s, k) => appendStringifiedKey(s, k, ...opts), "");
1242
1173
  var ReadonlyPath = class extends ReadonlyArray {
1243
1174
  // alternate strategy for caching since the base object is frozen
1244
1175
  cache = {};
@@ -1265,8 +1196,8 @@ var ReadonlyPath = class extends ReadonlyArray {
1265
1196
  return this.cache.stringifyAncestors;
1266
1197
  let propString = "";
1267
1198
  const result = [propString];
1268
- for (const path2 of this) {
1269
- propString = appendStringifiedKey(propString, path2);
1199
+ for (const path of this) {
1200
+ propString = appendStringifiedKey(propString, path);
1270
1201
  result.push(propString);
1271
1202
  }
1272
1203
  return this.cache.stringifyAncestors = result;
@@ -1859,15 +1790,15 @@ var ArkErrors = class _ArkErrors extends ReadonlyArray {
1859
1790
  /**
1860
1791
  * @internal
1861
1792
  */
1862
- affectsPath(path2) {
1793
+ affectsPath(path) {
1863
1794
  if (this.length === 0)
1864
1795
  return false;
1865
1796
  return (
1866
1797
  // this would occur if there is an existing error at a prefix of path
1867
1798
  // e.g. the path is ["foo", "bar"] and there is an error at ["foo"]
1868
- path2.stringifyAncestors().some((s) => s in this.byPath) || // this would occur if there is an existing error at a suffix of path
1799
+ path.stringifyAncestors().some((s) => s in this.byPath) || // this would occur if there is an existing error at a suffix of path
1869
1800
  // e.g. the path is ["foo"] and there is an error at ["foo", "bar"]
1870
- path2.stringify() in this.byAncestorPath
1801
+ path.stringify() in this.byAncestorPath
1871
1802
  );
1872
1803
  }
1873
1804
  /**
@@ -2074,22 +2005,22 @@ var Traversal = class {
2074
2005
  while (this.queuedMorphs.length) {
2075
2006
  const queuedMorphs = this.queuedMorphs;
2076
2007
  this.queuedMorphs = [];
2077
- for (const { path: path2, morphs } of queuedMorphs) {
2078
- if (this.errors.affectsPath(path2))
2008
+ for (const { path, morphs } of queuedMorphs) {
2009
+ if (this.errors.affectsPath(path))
2079
2010
  continue;
2080
- this.applyMorphsAtPath(path2, morphs);
2011
+ this.applyMorphsAtPath(path, morphs);
2081
2012
  }
2082
2013
  }
2083
2014
  }
2084
- applyMorphsAtPath(path2, morphs) {
2085
- const key = path2.at(-1);
2015
+ applyMorphsAtPath(path, morphs) {
2016
+ const key = path.at(-1);
2086
2017
  let parent;
2087
2018
  if (key !== void 0) {
2088
2019
  parent = this.root;
2089
- for (let pathIndex = 0; pathIndex < path2.length - 1; pathIndex++)
2090
- parent = parent[path2[pathIndex]];
2020
+ for (let pathIndex = 0; pathIndex < path.length - 1; pathIndex++)
2021
+ parent = parent[path[pathIndex]];
2091
2022
  }
2092
- this.path = [...path2];
2023
+ this.path = [...path];
2093
2024
  for (const morph of morphs) {
2094
2025
  const morphIsNode = isNode(morph);
2095
2026
  const result = morph(parent === void 0 ? this.root : parent[key], this);
@@ -2459,15 +2390,15 @@ var NodeSelector = {
2459
2390
  normalize: (selector) => typeof selector === "function" ? { boundary: "references", method: "filter", where: selector } : typeof selector === "string" ? isKeyOf(selector, NodeSelector.applyBoundary) ? { method: "filter", boundary: selector } : { boundary: "references", method: "filter", kind: selector } : { boundary: "references", method: "filter", ...selector }
2460
2391
  };
2461
2392
  var writeSelectAssertionMessage = (from, selector) => `${from} had no references matching ${printable(selector)}.`;
2462
- var typePathToPropString = (path2) => stringifyPath(path2, {
2393
+ var typePathToPropString = (path) => stringifyPath(path, {
2463
2394
  stringifyNonKey: (node2) => node2.expression
2464
2395
  });
2465
2396
  var referenceMatcher = /"(\$ark\.[^"]+)"/g;
2466
2397
  var compileMeta = (metaJson) => JSON.stringify(metaJson).replaceAll(referenceMatcher, "$1");
2467
- var flatRef = (path2, node2) => ({
2468
- path: path2,
2398
+ var flatRef = (path, node2) => ({
2399
+ path,
2469
2400
  node: node2,
2470
- propString: typePathToPropString(path2)
2401
+ propString: typePathToPropString(path)
2471
2402
  });
2472
2403
  var flatRefsAreEqual = (l, r) => l.propString === r.propString && l.node.equals(r.node);
2473
2404
  var appendUniqueFlatRefs = (existing, refs) => appendUnique(existing, refs, {
@@ -2503,12 +2434,12 @@ var Disjoint = class _Disjoint extends Array {
2503
2434
  }
2504
2435
  describeReasons() {
2505
2436
  if (this.length === 1) {
2506
- const { path: path2, l, r } = this[0];
2507
- const pathString = stringifyPath(path2);
2437
+ const { path, l, r } = this[0];
2438
+ const pathString = stringifyPath(path);
2508
2439
  return writeUnsatisfiableExpressionError(`Intersection${pathString && ` at ${pathString}`} of ${describeReasons(l, r)}`);
2509
2440
  }
2510
2441
  return `The following intersections result in unsatisfiable types:
2511
- \u2022 ${this.map(({ path: path2, l, r }) => `${path2}: ${describeReasons(l, r)}`).join("\n\u2022 ")}`;
2442
+ \u2022 ${this.map(({ path, l, r }) => `${path}: ${describeReasons(l, r)}`).join("\n\u2022 ")}`;
2512
2443
  }
2513
2444
  throw() {
2514
2445
  return throwParseError(this.describeReasons());
@@ -3868,10 +3799,10 @@ var BaseRoot = class extends BaseNode {
3868
3799
  });
3869
3800
  });
3870
3801
  }
3871
- get(...path2) {
3872
- if (path2[0] === void 0)
3802
+ get(...path) {
3803
+ if (path[0] === void 0)
3873
3804
  return this;
3874
- return this.$.schema(this.applyStructuralOperation("get", path2));
3805
+ return this.$.schema(this.applyStructuralOperation("get", path));
3875
3806
  }
3876
3807
  extract(r) {
3877
3808
  const rNode = this.$.parseDefinition(r);
@@ -4806,13 +4737,13 @@ var implementation17 = implementNode({
4806
4737
  description: (node2) => node2.distribute((branch) => branch.description, describeBranches),
4807
4738
  expected: (ctx) => {
4808
4739
  const byPath = groupBy(ctx.errors, "propString");
4809
- const pathDescriptions = Object.entries(byPath).map(([path2, errors]) => {
4740
+ const pathDescriptions = Object.entries(byPath).map(([path, errors]) => {
4810
4741
  const branchesAtPath = [];
4811
4742
  for (const errorAtPath of errors)
4812
4743
  appendUnique(branchesAtPath, errorAtPath.expected);
4813
4744
  const expected = describeBranches(branchesAtPath);
4814
4745
  const actual = errors.every((e) => e.actual === errors[0].actual) ? errors[0].actual : printable(errors[0].data);
4815
- return `${path2 && `${path2} `}must be ${expected}${actual && ` (was ${actual})`}`;
4746
+ return `${path && `${path} `}must be ${expected}${actual && ` (was ${actual})`}`;
4816
4747
  });
4817
4748
  return describeBranches(pathDescriptions);
4818
4749
  },
@@ -5176,10 +5107,10 @@ var orderCandidates = (candidates, originalBranches) => {
5176
5107
  });
5177
5108
  return viableCandidates;
5178
5109
  };
5179
- var discriminantCaseToNode = (caseDiscriminant, path2, $) => {
5110
+ var discriminantCaseToNode = (caseDiscriminant, path, $) => {
5180
5111
  let node2 = caseDiscriminant === "undefined" ? $.node("unit", { unit: void 0 }) : caseDiscriminant === "null" ? $.node("unit", { unit: null }) : caseDiscriminant === "boolean" ? $.units([true, false]) : caseDiscriminant;
5181
- for (let i = path2.length - 1; i >= 0; i--) {
5182
- const key = path2[i];
5112
+ for (let i = path.length - 1; i >= 0; i--) {
5113
+ const key = path[i];
5183
5114
  node2 = $.node("intersection", typeof key === "number" ? {
5184
5115
  proto: "Array",
5185
5116
  // create unknown for preceding elements (could be optimized with safe imports)
@@ -5191,7 +5122,7 @@ var discriminantCaseToNode = (caseDiscriminant, path2, $) => {
5191
5122
  }
5192
5123
  return node2;
5193
5124
  };
5194
- var optionallyChainPropString = (path2) => path2.reduce((acc, k) => acc + compileLiteralPropAccess(k, true), "data");
5125
+ var optionallyChainPropString = (path) => path.reduce((acc, k) => acc + compileLiteralPropAccess(k, true), "data");
5195
5126
  var serializedTypeOfDescriptions = registeredReference(jsTypeOfDescriptions);
5196
5127
  var serializedPrintable = registeredReference(printable);
5197
5128
  var Union = {
@@ -6149,7 +6080,7 @@ var StructureNode = class extends BaseConstraint {
6149
6080
  return throwParseError(writeInvalidKeysMessage(this.expression, invalidKeys));
6150
6081
  }
6151
6082
  }
6152
- get(indexer, ...path2) {
6083
+ get(indexer, ...path) {
6153
6084
  var _a4;
6154
6085
  let value2;
6155
6086
  let required = false;
@@ -6186,7 +6117,7 @@ var StructureNode = class extends BaseConstraint {
6186
6117
  }
6187
6118
  return throwParseError(writeInvalidKeysMessage(this.expression, [key]));
6188
6119
  }
6189
- const result = value2.get(...path2);
6120
+ const result = value2.get(...path);
6190
6121
  return required ? result : result.or($ark.intrinsic.undefined);
6191
6122
  }
6192
6123
  pick(...keys) {
@@ -8912,7 +8843,7 @@ function isIterator(val) {
8912
8843
  function escapeRegex(str) {
8913
8844
  return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
8914
8845
  }
8915
- function promisify2(fn) {
8846
+ function promisify(fn) {
8916
8847
  return function(...args2) {
8917
8848
  return new Promise((resolve2, reject2) => {
8918
8849
  fn(...args2, (err, result) => {
@@ -10248,8 +10179,8 @@ function requireResolve(file) {
10248
10179
  const require2 = (0, import_module3.createRequire)(process.cwd() + "/");
10249
10180
  return require2.resolve(file);
10250
10181
  }
10251
- var statAsync = promisify2(import_fs.stat);
10252
- var readFileAsync = promisify2(import_fs.readFile);
10182
+ var statAsync = promisify(import_fs.stat);
10183
+ var readFileAsync = promisify(import_fs.readFile);
10253
10184
  function exists(filepath) {
10254
10185
  return __awaiter(this, void 0, void 0, function* () {
10255
10186
  try {
@@ -11491,10 +11422,10 @@ var Loader = class {
11491
11422
  yield filepath;
11492
11423
  }
11493
11424
  }
11494
- dirname(path2) {
11425
+ dirname(path) {
11495
11426
  const fs2 = this.options.fs;
11496
11427
  assert(fs2.dirname, "`fs.dirname` is required for relative reference");
11497
- return fs2.dirname(path2);
11428
+ return fs2.dirname(path);
11498
11429
  }
11499
11430
  lookupError(file, roots) {
11500
11431
  const err = new Error("ENOENT");
@@ -13456,6 +13387,7 @@ function validateTemplateContext(ctx) {
13456
13387
  var caddyTemplate = `{
13457
13388
  debug
13458
13389
  auto_https disable_redirects ignore_loaded_certs
13390
+ skip_install_trust
13459
13391
  }
13460
13392
 
13461
13393
  :7601 {
@@ -13536,27 +13468,27 @@ async function genCaddyfile(ctx) {
13536
13468
  }
13537
13469
 
13538
13470
  // src/caddy/config.ts
13539
- var import_node_fs2 = require("fs");
13540
- var import_promises2 = require("fs/promises");
13471
+ var import_node_fs = require("fs");
13472
+ var import_promises = require("fs/promises");
13541
13473
 
13542
13474
  // src/caddy/constants.ts
13543
13475
  var import_node_os2 = __toESM(require("os"), 1);
13544
- var import_node_path2 = require("path");
13545
- var import_node_process3 = __toESM(require("process"), 1);
13476
+ var import_node_path = require("path");
13477
+ var import_node_process = __toESM(require("process"), 1);
13546
13478
  var import_dotenv_flow = __toESM(require("dotenv-flow"), 1);
13547
13479
  import_dotenv_flow.default.config({
13548
13480
  silent: true
13549
13481
  });
13550
- function resolvePath(path2) {
13551
- if (path2.startsWith("~"))
13552
- return (0, import_node_path2.join)(import_node_os2.default.homedir() || "", path2.slice(1));
13553
- return path2;
13554
- }
13555
- var TEMP_DIR = resolvePath(import_node_process3.default.env.UHRP_CADDY_PATH || import_node_process3.default.env.TEMP || import_node_process3.default.env.TMPDIR || "/tmp");
13556
- var caddyPath = (0, import_node_path2.join)(TEMP_DIR, `caddy${import_node_process3.default.platform === "win32" ? ".exe" : ""}`);
13557
- var caddyFilePath = (0, import_node_path2.join)(TEMP_DIR, "CADDYFILE");
13558
- var caddyConfigPath = (0, import_node_path2.join)(TEMP_DIR, ".CADDYFILE.config.json");
13559
- var caddyLockFilePath = (0, import_node_path2.join)(TEMP_DIR, "caddylock");
13482
+ function resolvePath(path) {
13483
+ if (path.startsWith("~"))
13484
+ return (0, import_node_path.join)(import_node_os2.default.homedir() || "", path.slice(1));
13485
+ return path;
13486
+ }
13487
+ var TEMP_DIR = resolvePath(import_node_process.default.env.UHRP_CADDY_PATH || import_node_process.default.env.TEMP || import_node_process.default.env.TMPDIR || "/tmp");
13488
+ var caddyPath = (0, import_node_path.join)(TEMP_DIR, `caddy${import_node_process.default.platform === "win32" ? ".exe" : ""}`);
13489
+ var caddyFilePath = (0, import_node_path.join)(TEMP_DIR, "CADDYFILE");
13490
+ var caddyConfigPath = (0, import_node_path.join)(TEMP_DIR, ".CADDYFILE.config.json");
13491
+ var caddyLockFilePath = (0, import_node_path.join)(TEMP_DIR, "caddylock");
13560
13492
  var supportList = [
13561
13493
  {
13562
13494
  platform: "dragonfly",
@@ -13679,19 +13611,19 @@ function useCaddyConfig() {
13679
13611
  }
13680
13612
  });
13681
13613
  function setConfigContent() {
13682
- if (!(0, import_node_fs2.existsSync)(caddyConfigPath)) {
13683
- (0, import_node_fs2.writeFileSync)(caddyConfigPath, "{}");
13614
+ if (!(0, import_node_fs.existsSync)(caddyConfigPath)) {
13615
+ (0, import_node_fs.writeFileSync)(caddyConfigPath, "{}");
13684
13616
  }
13685
13617
  try {
13686
- configContentRef((0, import_node_fs2.readFileSync)(caddyConfigPath, "utf-8"));
13618
+ configContentRef((0, import_node_fs.readFileSync)(caddyConfigPath, "utf-8"));
13687
13619
  } catch {
13688
13620
  configContentRef("");
13689
13621
  }
13690
13622
  }
13691
- if (!(0, import_node_fs2.existsSync)(caddyConfigPath)) {
13692
- (0, import_node_fs2.writeFileSync)(caddyConfigPath, "{}");
13623
+ if (!(0, import_node_fs.existsSync)(caddyConfigPath)) {
13624
+ (0, import_node_fs.writeFileSync)(caddyConfigPath, "{}");
13693
13625
  }
13694
- const watchCaddyConfig = (0, import_node_fs2.watch)(caddyConfigPath, () => {
13626
+ const watchCaddyConfig = (0, import_node_fs.watch)(caddyConfigPath, () => {
13695
13627
  setConfigContent();
13696
13628
  });
13697
13629
  function writeCaddyConfig(_proxies) {
@@ -13707,10 +13639,10 @@ function useCaddyConfig() {
13707
13639
  });
13708
13640
  const content = JSON.stringify(proxies, null, 2);
13709
13641
  configContentRef(content);
13710
- return (0, import_node_fs2.writeFileSync)(caddyConfigPath, content);
13642
+ return (0, import_node_fs.writeFileSync)(caddyConfigPath, content);
13711
13643
  }
13712
13644
  async function cleanUp() {
13713
- await (0, import_promises2.unlink)(caddyConfigPath).catch(() => {
13645
+ await (0, import_promises.unlink)(caddyConfigPath).catch(() => {
13714
13646
  });
13715
13647
  configContentRef("{}");
13716
13648
  watchCaddyConfig.close();
@@ -13732,6 +13664,592 @@ function isCaddyReloadCancellation(line) {
13732
13664
  }
13733
13665
  }
13734
13666
 
13667
+ // src/caddy/privileged.ts
13668
+ var import_node_buffer2 = require("buffer");
13669
+ var import_node_events = require("events");
13670
+ var import_node_path4 = require("path");
13671
+ var import_node_process6 = __toESM(require("process"), 1);
13672
+ var import_node_url = require("url");
13673
+
13674
+ // src/privileged/entry.ts
13675
+ var import_node_fs2 = require("fs");
13676
+ var import_node_path2 = require("path");
13677
+ var import_node_process2 = __toESM(require("process"), 1);
13678
+ function resolveHelperEntry(options) {
13679
+ const { moduleDir, nodeBin = import_node_process2.default.execPath, exists: exists2 = import_node_fs2.existsSync } = options;
13680
+ for (const name of ["privileged-helper.js", "privileged-helper.cjs", "privileged-helper.mjs"]) {
13681
+ const candidate = findUp(moduleDir, name, exists2);
13682
+ if (candidate)
13683
+ return { entry: nodeBin, args: [candidate] };
13684
+ }
13685
+ const source = findUp(moduleDir, "privileged-helper.ts", exists2);
13686
+ const tsxCli = findUp(moduleDir, "node_modules/tsx/dist/cli.mjs", exists2);
13687
+ if (source && tsxCli)
13688
+ return { entry: nodeBin, args: [tsxCli, source] };
13689
+ throw new Error(`privileged helper entry not found in ${moduleDir}. Build the package first.`);
13690
+ }
13691
+ function findUp(from, relative, exists2) {
13692
+ let current = from;
13693
+ while (true) {
13694
+ const candidate = (0, import_node_path2.join)(current, relative);
13695
+ if (exists2(candidate))
13696
+ return candidate;
13697
+ const parent = (0, import_node_path2.dirname)(current);
13698
+ if (parent === current)
13699
+ return void 0;
13700
+ current = parent;
13701
+ }
13702
+ }
13703
+
13704
+ // src/privileged/session.ts
13705
+ var import_node_buffer = require("buffer");
13706
+ var import_node_fs3 = require("fs");
13707
+ var import_promises2 = require("fs/promises");
13708
+ var import_node_os4 = require("os");
13709
+ var import_node_path3 = require("path");
13710
+
13711
+ // src/privileged/launch.ts
13712
+ var import_node_child_process2 = require("child_process");
13713
+ var import_node_crypto = require("crypto");
13714
+ var import_node_os3 = require("os");
13715
+ var import_node_process5 = __toESM(require("process"), 1);
13716
+
13717
+ // src/privileged/client.ts
13718
+ var import_node_net = require("net");
13719
+ var import_node_process3 = __toESM(require("process"), 1);
13720
+
13721
+ // src/privileged/protocol.ts
13722
+ function serializeMessage(message) {
13723
+ return `${JSON.stringify(message)}
13724
+ `;
13725
+ }
13726
+ function splitLines(buffer, chunk) {
13727
+ const parts = (buffer + chunk).split("\n");
13728
+ const rest = parts.pop() ?? "";
13729
+ return { lines: parts.filter((line) => line.trim() !== ""), rest };
13730
+ }
13731
+ function isRecord(value2) {
13732
+ return typeof value2 === "object" && value2 !== null;
13733
+ }
13734
+ function decodeMessage(line) {
13735
+ let parsed2;
13736
+ try {
13737
+ parsed2 = JSON.parse(line);
13738
+ } catch (error) {
13739
+ return { ok: false, error: `invalid JSON: ${error.message}` };
13740
+ }
13741
+ if (!isRecord(parsed2))
13742
+ return { ok: false, error: "message must be an object" };
13743
+ if (parsed2.type === "event") {
13744
+ if (typeof parsed2.kind !== "string")
13745
+ return { ok: false, error: "event.kind must be a string" };
13746
+ return { ok: true, message: parsed2 };
13747
+ }
13748
+ if (typeof parsed2.id !== "number")
13749
+ return { ok: false, error: "response.id must be a number" };
13750
+ if (parsed2.ok === true)
13751
+ return { ok: true, message: { id: parsed2.id, ok: true, result: parsed2.result } };
13752
+ if (parsed2.ok === false) {
13753
+ const error = isRecord(parsed2.error) ? parsed2.error : {};
13754
+ return {
13755
+ ok: true,
13756
+ message: {
13757
+ id: parsed2.id,
13758
+ ok: false,
13759
+ error: {
13760
+ message: typeof error.message === "string" ? error.message : "helper request failed",
13761
+ code: typeof error.code === "string" ? error.code : void 0
13762
+ }
13763
+ }
13764
+ };
13765
+ }
13766
+ return { ok: false, error: "response.ok must be a boolean" };
13767
+ }
13768
+
13769
+ // src/privileged/client.ts
13770
+ var FORWARDED_ENV_KEYS = [
13771
+ "HOME",
13772
+ "USER",
13773
+ "LOGNAME",
13774
+ "TMPDIR",
13775
+ "HTTP_PROXY",
13776
+ "HTTPS_PROXY",
13777
+ "http_proxy",
13778
+ "https_proxy",
13779
+ "NO_PROXY",
13780
+ "no_proxy"
13781
+ ];
13782
+ function collectForwardedEnv(source = import_node_process3.default.env) {
13783
+ const result = {};
13784
+ for (const key of FORWARDED_ENV_KEYS) {
13785
+ const value2 = source[key];
13786
+ if (typeof value2 === "string" && value2 !== "")
13787
+ result[key] = value2;
13788
+ }
13789
+ return result;
13790
+ }
13791
+ var HelperConnectionError = class extends Error {
13792
+ constructor(message) {
13793
+ super(message);
13794
+ this.name = "HelperConnectionError";
13795
+ }
13796
+ };
13797
+ function openSocket(socketPath) {
13798
+ return new Promise((resolve2, reject2) => {
13799
+ const socket = (0, import_node_net.connect)(socketPath);
13800
+ function onConnect() {
13801
+ socket.removeListener("error", onError);
13802
+ resolve2(socket);
13803
+ }
13804
+ function onError(error) {
13805
+ socket.removeListener("connect", onConnect);
13806
+ reject2(error);
13807
+ }
13808
+ socket.once("error", onError);
13809
+ socket.once("connect", onConnect);
13810
+ });
13811
+ }
13812
+ async function connectClient(options) {
13813
+ const {
13814
+ socketPath,
13815
+ token,
13816
+ timeoutMs = 12e4,
13817
+ retryIntervalMs = 100,
13818
+ callTimeoutMs = 3e4
13819
+ } = options;
13820
+ const deadline = Date.now() + timeoutMs;
13821
+ let lastError;
13822
+ while (Date.now() < deadline) {
13823
+ try {
13824
+ return await handshake(socketPath, token, callTimeoutMs);
13825
+ } catch (error) {
13826
+ lastError = error;
13827
+ const code = lastError.code;
13828
+ if (code === "EACCES" || lastError instanceof HelperConnectionError)
13829
+ throw lastError;
13830
+ await new Promise((resolve2) => setTimeout(resolve2, retryIntervalMs));
13831
+ }
13832
+ }
13833
+ throw new HelperConnectionError(
13834
+ `privileged helper is not reachable at ${socketPath}: ${(lastError == null ? void 0 : lastError.message) ?? "timed out"}`
13835
+ );
13836
+ }
13837
+ function handshake(socketPath, token, callTimeoutMs) {
13838
+ return new Promise((resolve2, reject2) => {
13839
+ void openSocket(socketPath).then((socket) => {
13840
+ let buffer = "";
13841
+ let settled = false;
13842
+ const fail = (error) => {
13843
+ if (settled)
13844
+ return;
13845
+ settled = true;
13846
+ socket.destroy();
13847
+ reject2(error);
13848
+ };
13849
+ const onData = (chunk) => {
13850
+ if (settled)
13851
+ return;
13852
+ const split2 = splitLines(buffer, chunk.toString("utf8"));
13853
+ buffer = split2.rest;
13854
+ const line = split2.lines[0];
13855
+ if (line === void 0)
13856
+ return;
13857
+ let hello;
13858
+ try {
13859
+ hello = JSON.parse(line);
13860
+ } catch (error) {
13861
+ return fail(new HelperConnectionError(`invalid handshake reply: ${error.message}`));
13862
+ }
13863
+ if (hello.type !== "handshake")
13864
+ return fail(new HelperConnectionError("helper did not answer the handshake"));
13865
+ if (!hello.ok)
13866
+ return fail(new HelperConnectionError(hello.reason ?? "helper rejected the handshake"));
13867
+ settled = true;
13868
+ socket.removeListener("data", onData);
13869
+ socket.removeListener("error", onError);
13870
+ const remaining = split2.lines.slice(1);
13871
+ resolve2(createClient(socket, [split2.rest, ...remaining].filter(Boolean).join("\n"), callTimeoutMs));
13872
+ };
13873
+ function onError(error) {
13874
+ fail(error);
13875
+ }
13876
+ socket.on("data", onData);
13877
+ socket.on("error", onError);
13878
+ const greeting = { type: "handshake", token };
13879
+ socket.write(serializeMessage(greeting));
13880
+ }, reject2);
13881
+ });
13882
+ }
13883
+ function createClient(socket, initialBuffer, callTimeoutMs) {
13884
+ let buffer = initialBuffer;
13885
+ let connected = true;
13886
+ let nextId = 1;
13887
+ const pending = /* @__PURE__ */ new Map();
13888
+ const listeners = /* @__PURE__ */ new Set();
13889
+ socket.on("data", (chunk) => {
13890
+ const split2 = splitLines(buffer, chunk.toString("utf8"));
13891
+ buffer = split2.rest;
13892
+ for (const line of split2.lines) {
13893
+ const decoded = decodeMessage(line);
13894
+ if (!decoded.ok)
13895
+ continue;
13896
+ const message = decoded.message;
13897
+ if (!("id" in message)) {
13898
+ for (const listener of listeners)
13899
+ listener(message);
13900
+ continue;
13901
+ }
13902
+ const entry = pending.get(message.id);
13903
+ if (!entry)
13904
+ continue;
13905
+ pending.delete(message.id);
13906
+ clearTimeout(entry.timer);
13907
+ if (message.ok)
13908
+ entry.resolve(message.result);
13909
+ else
13910
+ entry.reject(new Error(message.error.message));
13911
+ }
13912
+ });
13913
+ const disconnect = () => {
13914
+ if (!connected)
13915
+ return;
13916
+ connected = false;
13917
+ for (const [id, entry] of pending) {
13918
+ clearTimeout(entry.timer);
13919
+ pending.delete(id);
13920
+ entry.reject(new HelperConnectionError("privileged helper connection closed"));
13921
+ }
13922
+ };
13923
+ socket.on("close", disconnect);
13924
+ socket.on("error", disconnect);
13925
+ function call(method, params) {
13926
+ if (!connected)
13927
+ return Promise.reject(new HelperConnectionError("privileged helper is not connected"));
13928
+ const id = nextId++;
13929
+ const request = { id, method, params };
13930
+ return new Promise((resolve2, reject2) => {
13931
+ const timer = setTimeout(() => {
13932
+ pending.delete(id);
13933
+ reject2(new HelperConnectionError(`privileged helper did not answer "${method}" in time`));
13934
+ }, callTimeoutMs);
13935
+ pending.set(id, { resolve: resolve2, reject: reject2, timer });
13936
+ socket.write(serializeMessage(request));
13937
+ });
13938
+ }
13939
+ return {
13940
+ get connected() {
13941
+ return connected;
13942
+ },
13943
+ call,
13944
+ onEvent(listener) {
13945
+ listeners.add(listener);
13946
+ return () => {
13947
+ listeners.delete(listener);
13948
+ };
13949
+ },
13950
+ async close() {
13951
+ disconnect();
13952
+ socket.destroy();
13953
+ }
13954
+ };
13955
+ }
13956
+
13957
+ // src/privileged/windows-elevation.ts
13958
+ var import_node_child_process = require("child_process");
13959
+ var import_node_process4 = __toESM(require("process"), 1);
13960
+ function quotePowerShell(value2) {
13961
+ return `'${value2.replace(/'/g, "''")}'`;
13962
+ }
13963
+ function buildElevationCommand(options) {
13964
+ const argumentList = options.args.map(quotePowerShell).join(",");
13965
+ const parts = [
13966
+ "Start-Process",
13967
+ "-FilePath",
13968
+ quotePowerShell(options.file)
13969
+ ];
13970
+ if (argumentList)
13971
+ parts.push("-ArgumentList", argumentList);
13972
+ if (options.cwd)
13973
+ parts.push("-WorkingDirectory", quotePowerShell(options.cwd));
13974
+ parts.push("-Verb", "RunAs");
13975
+ parts.push("-WindowStyle", "Hidden");
13976
+ return parts.join(" ");
13977
+ }
13978
+ function spawnElevatedOnWindows(options) {
13979
+ return new Promise((resolve2, reject2) => {
13980
+ const script = buildElevationCommand(options);
13981
+ const child = (0, import_node_child_process.spawn)(
13982
+ "powershell.exe",
13983
+ ["-NoProfile", "-NonInteractive", "-Command", script],
13984
+ { stdio: "ignore", windowsHide: true }
13985
+ );
13986
+ child.once("error", reject2);
13987
+ child.once("exit", (code) => {
13988
+ if (code === 0)
13989
+ return resolve2(child);
13990
+ reject2(new Error(
13991
+ `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.`
13992
+ ));
13993
+ });
13994
+ });
13995
+ }
13996
+
13997
+ // src/privileged/launch.ts
13998
+ function createHelperToken() {
13999
+ return (0, import_node_crypto.randomBytes)(24).toString("hex");
14000
+ }
14001
+ function describePasswordReason(target, https) {
14002
+ const port = https ? "443" : "80";
14003
+ return [
14004
+ `reverse proxy needs administrator permission for ${target}`,
14005
+ ` \xB7 bind port ${port}${https ? ` for https://${target}` : ""}`,
14006
+ ` \xB7 add ${target} to the hosts file`,
14007
+ "",
14008
+ "This is the only prompt; the rest of the dev server keeps running as you.",
14009
+ "Press Ctrl+C at the prompt to skip the proxy and keep the dev server."
14010
+ ];
14011
+ }
14012
+ function authenticateSudo(sudoCommand = "sudo", options = {}) {
14013
+ if ((0, import_node_os3.platform)() === "win32")
14014
+ return { ok: true };
14015
+ if ((0, import_node_child_process2.spawnSync)(sudoCommand, ["-n", "true"], { stdio: "ignore" }).status === 0)
14016
+ return { ok: true };
14017
+ if (options.target) {
14018
+ for (const line of describePasswordReason(options.target, options.https ?? false))
14019
+ import_node_process5.default.stderr.write(`${line}
14020
+ `);
14021
+ import_node_process5.default.stderr.write("\n");
14022
+ }
14023
+ if ((0, import_node_child_process2.spawnSync)(sudoCommand, ["-v"], { stdio: "inherit" }).status === 0)
14024
+ return { ok: true };
14025
+ return {
14026
+ ok: false,
14027
+ denied: true,
14028
+ message: "administrator permission is required to edit the hosts file and bind ports 80/443"
14029
+ };
14030
+ }
14031
+ var PrivilegeDeniedError = class extends Error {
14032
+ constructor(message) {
14033
+ super(message);
14034
+ this.name = "PrivilegeDeniedError";
14035
+ }
14036
+ };
14037
+ async function startPrivilegedHelper(options) {
14038
+ var _a4, _b3;
14039
+ const {
14040
+ socketPath,
14041
+ token,
14042
+ helperEntry,
14043
+ helperArgs = [],
14044
+ sudoCommand = "sudo",
14045
+ skipAuth = false,
14046
+ direct = false,
14047
+ env: env2 = import_node_process5.default.env,
14048
+ log,
14049
+ connectTimeoutMs = 12e4
14050
+ } = options;
14051
+ if (!skipAuth && !direct) {
14052
+ const auth = authenticateSudo(sudoCommand, options.reason);
14053
+ if (!auth.ok) {
14054
+ const message = auth.message ?? "administrator permission is required";
14055
+ throw auth.denied ? new PrivilegeDeniedError(message) : new Error(message);
14056
+ }
14057
+ }
14058
+ const forwarded = collectForwardedEnv(env2);
14059
+ const forwardedArgs = Object.entries(forwarded).map(([key, value2]) => `${key}=${value2}`);
14060
+ const childArgv = [
14061
+ ...helperArgs,
14062
+ "--socket",
14063
+ socketPath,
14064
+ "--token",
14065
+ token,
14066
+ ...typeof import_node_process5.default.getuid === "function" ? ["--owner-uid", String(import_node_process5.default.getuid())] : [],
14067
+ ...typeof import_node_process5.default.getgid === "function" ? ["--owner-gid", String(import_node_process5.default.getgid())] : [],
14068
+ ...options.caddyStoragePath ? ["--caddy-storage", options.caddyStoragePath] : [],
14069
+ "--caddy",
14070
+ options.caddyBin,
14071
+ "--caddy-config",
14072
+ options.caddyConfigPath
14073
+ ];
14074
+ let child;
14075
+ if (!direct && (0, import_node_os3.platform)() === "win32") {
14076
+ await spawnElevatedOnWindows({ file: helperEntry, args: childArgv, cwd: import_node_process5.default.cwd() });
14077
+ } else {
14078
+ const command = direct ? helperEntry : sudoCommand;
14079
+ const spawnArgs = direct ? childArgv : ["-n", "env", ...forwardedArgs, helperEntry, ...childArgv];
14080
+ child = (0, import_node_child_process2.spawn)(command, spawnArgs, {
14081
+ stdio: ["ignore", "pipe", "pipe"]
14082
+ });
14083
+ (_a4 = child.stdout) == null ? void 0 : _a4.on("data", (data) => log == null ? void 0 : log(data.toString().trimEnd()));
14084
+ (_b3 = child.stderr) == null ? void 0 : _b3.on("data", (data) => log == null ? void 0 : log(data.toString().trimEnd()));
14085
+ const exited = new Promise((resolve2) => child.once("exit", (code) => resolve2(code)));
14086
+ const earlyExit = await Promise.race([
14087
+ exited,
14088
+ new Promise((resolve2) => setTimeout(() => resolve2(void 0), 500))
14089
+ ]);
14090
+ if (earlyExit !== void 0 && earlyExit !== 0) {
14091
+ throw new Error(
14092
+ `privileged helper exited with code ${earlyExit}. Administrator permission was refused, or sudo is not available.`
14093
+ );
14094
+ }
14095
+ }
14096
+ try {
14097
+ const client = await connectClient({ socketPath, token, timeoutMs: connectTimeoutMs });
14098
+ return {
14099
+ client,
14100
+ async close() {
14101
+ await client.close().catch(() => {
14102
+ });
14103
+ child == null ? void 0 : child.unref();
14104
+ }
14105
+ };
14106
+ } catch (error) {
14107
+ try {
14108
+ child == null ? void 0 : child.kill();
14109
+ } catch {
14110
+ }
14111
+ throw error;
14112
+ }
14113
+ }
14114
+ async function connectExistingHelper(socketPath, token, timeoutMs = 1500) {
14115
+ try {
14116
+ return await connectClient({ socketPath, token, timeoutMs });
14117
+ } catch {
14118
+ return void 0;
14119
+ }
14120
+ }
14121
+
14122
+ // src/privileged/session.ts
14123
+ function tokenPath(runtimeDir) {
14124
+ return (0, import_node_path3.join)(runtimeDir, "helper.token");
14125
+ }
14126
+ function sessionSocketPath(runtimeDir) {
14127
+ if ((0, import_node_os4.platform)() === "win32")
14128
+ return `\\\\.\\pipe\\uhrp-${import_node_buffer.Buffer.from(runtimeDir).toString("hex").slice(0, 40)}`;
14129
+ return (0, import_node_path3.join)(runtimeDir, "helper.sock");
14130
+ }
14131
+ async function openHelperSession(scope2) {
14132
+ const socketPath = sessionSocketPath(scope2.runtimeDir);
14133
+ if ((0, import_node_fs3.existsSync)(socketPath) || (0, import_node_os4.platform)() === "win32") {
14134
+ const token2 = await readToken(scope2.runtimeDir);
14135
+ if (token2) {
14136
+ const reused = await connectExistingHelper(socketPath, token2);
14137
+ if (reused) {
14138
+ return {
14139
+ client: reused,
14140
+ reused: true,
14141
+ close: async () => {
14142
+ await reused.close();
14143
+ }
14144
+ };
14145
+ }
14146
+ }
14147
+ }
14148
+ const token = createHelperToken();
14149
+ const started = await startPrivilegedHelper({
14150
+ socketPath,
14151
+ token,
14152
+ helperEntry: scope2.helperEntry,
14153
+ helperArgs: scope2.helperArgs,
14154
+ sudoCommand: scope2.sudoCommand,
14155
+ skipAuth: scope2.skipAuth,
14156
+ direct: scope2.direct,
14157
+ env: scope2.env,
14158
+ caddyStoragePath: scope2.caddyStoragePath,
14159
+ caddyBin: scope2.caddyBin,
14160
+ caddyConfigPath: scope2.caddyConfigPath,
14161
+ reason: scope2.reason,
14162
+ log: scope2.log
14163
+ });
14164
+ await writeToken(scope2.runtimeDir, token);
14165
+ return {
14166
+ client: started.client,
14167
+ reused: false,
14168
+ close: async () => {
14169
+ await started.close();
14170
+ }
14171
+ };
14172
+ }
14173
+ async function readToken(runtimeDir) {
14174
+ try {
14175
+ const content = await (0, import_promises2.readFile)(tokenPath(runtimeDir), "utf8");
14176
+ const token = content.trim();
14177
+ return token === "" ? void 0 : token;
14178
+ } catch {
14179
+ return void 0;
14180
+ }
14181
+ }
14182
+ async function writeToken(runtimeDir, token) {
14183
+ try {
14184
+ await (0, import_promises2.writeFile)(tokenPath(runtimeDir), token, { mode: 384 });
14185
+ } catch {
14186
+ }
14187
+ }
14188
+
14189
+ // src/caddy/privileged.ts
14190
+ var import_meta = {};
14191
+ function resolvePrivilegedEnv() {
14192
+ const moduleDir = typeof __dirname === "string" ? __dirname : (0, import_node_path4.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
14193
+ const resolved = resolveHelperEntry({ moduleDir });
14194
+ return { helperEntry: resolved.entry, helperArgs: resolved.args };
14195
+ }
14196
+ var HelperCaddyProcess = class extends import_node_events.EventEmitter {
14197
+ constructor(client) {
14198
+ super();
14199
+ this.client = client;
14200
+ this.stdout = new import_node_events.EventEmitter();
14201
+ this.stderr = new import_node_events.EventEmitter();
14202
+ this.finished = false;
14203
+ this.unsubscribe = client.onEvent((event) => this.handleEvent(event));
14204
+ }
14205
+ handleEvent(event) {
14206
+ if (event.type !== "event")
14207
+ return;
14208
+ if (event.kind === "caddy.stdout") {
14209
+ this.stdout.emit("data", import_node_buffer2.Buffer.from(event.data));
14210
+ return;
14211
+ }
14212
+ if (event.kind === "caddy.stderr") {
14213
+ this.stderr.emit("data", import_node_buffer2.Buffer.from(event.data));
14214
+ return;
14215
+ }
14216
+ if (event.kind === "caddy.exit") {
14217
+ this.finished = true;
14218
+ this.emit("exit", event.code, event.signal);
14219
+ }
14220
+ }
14221
+ /** Asks the helper to stop Caddy; the helper also stops it on disconnect. */
14222
+ kill() {
14223
+ this.unsubscribe();
14224
+ if (this.finished)
14225
+ return;
14226
+ this.finished = true;
14227
+ void this.client.call("caddy.stop").catch(() => {
14228
+ });
14229
+ }
14230
+ };
14231
+ function caddyStoragePath() {
14232
+ return import_node_process6.default.platform === "win32" ? (0, import_node_path4.join)(import_node_process6.default.env.AppData ?? "", "Caddy") : (0, import_node_path4.join)(import_node_process6.default.env.HOME ?? "", "Library/Application Support/Caddy");
14233
+ }
14234
+ function openPrivilegedSession(runtimeDir, options) {
14235
+ const env2 = resolvePrivilegedEnv();
14236
+ return openHelperSession({
14237
+ runtimeDir,
14238
+ helperEntry: env2.helperEntry,
14239
+ helperArgs: env2.helperArgs,
14240
+ direct: options.direct,
14241
+ // Caddy keeps its PKI under the user's home; the helper runs it as root, so
14242
+ // it must know which tree to hand back afterwards.
14243
+ caddyStoragePath: caddyStoragePath(),
14244
+ // The binary and Caddyfile are fixed here: the privileged helper must never
14245
+ // execute a path supplied over the socket.
14246
+ caddyBin: options.caddyBin,
14247
+ caddyConfigPath: options.caddyConfigPath,
14248
+ reason: options.reason,
14249
+ log: options.log
14250
+ });
14251
+ }
14252
+
13735
14253
  // src/caddy/tls-health.ts
13736
14254
  var import_node_tls = require("tls");
13737
14255
  function assessTlsCertificate(certificate, hostname, now = Date.now(), verifyHostname = import_node_tls.checkServerIdentity) {
@@ -13814,40 +14332,8 @@ function formatTlsHealthFailure(hostname, result) {
13814
14332
  }
13815
14333
 
13816
14334
  // src/caddy/utils.ts
13817
- var import_node_child_process3 = require("child_process");
13818
- var import_node_net = require("net");
13819
14335
  var import_ora = __toESM(require("ora"), 1);
13820
14336
  var spinner;
13821
- function tryPort(port) {
13822
- return new Promise((resolve2, _reject) => {
13823
- try {
13824
- const server = (0, import_node_net.createServer)().listen(port);
13825
- server.on("listening", () => {
13826
- server.close();
13827
- resolve2(false);
13828
- });
13829
- server.on("error", (err) => {
13830
- if (err.code === "EADDRINUSE")
13831
- resolve2(true);
13832
- server.close();
13833
- });
13834
- } catch {
13835
- resolve2(true);
13836
- }
13837
- });
13838
- }
13839
- async function kill(port) {
13840
- return new Promise((resolve2, reject2) => {
13841
- (0, import_node_child_process3.exec)(`npx @maxbo/free-port ${port} -s`, (err, stdout, _stderr) => {
13842
- if (err) {
13843
- reject2(err);
13844
- } else {
13845
- consola.log(stdout);
13846
- resolve2();
13847
- }
13848
- });
13849
- });
13850
- }
13851
14337
  function getNumber(number2) {
13852
14338
  if (number2 <= 0)
13853
14339
  return "0%";
@@ -13886,26 +14372,26 @@ async function download() {
13886
14372
  if (await testCaddy())
13887
14373
  return caddyPath;
13888
14374
  return new Promise((resolve2, reject2) => {
13889
- if (!(0, import_node_fs3.existsSync)(TEMP_DIR)) {
13890
- (0, import_node_fs3.mkdirSync)(TEMP_DIR, { recursive: true });
13891
- (0, import_node_fs3.chmodSync)(TEMP_DIR, 511);
14375
+ if (!(0, import_node_fs4.existsSync)(TEMP_DIR)) {
14376
+ (0, import_node_fs4.mkdirSync)(TEMP_DIR, { recursive: true });
14377
+ (0, import_node_fs4.chmodSync)(TEMP_DIR, 448);
13892
14378
  }
13893
- const file = (0, import_node_fs3.createWriteStream)(caddyPath);
13894
- let _platform = (0, import_node_os3.platform)().toString();
14379
+ const file = (0, import_node_fs4.createWriteStream)(caddyPath);
14380
+ let _platform = (0, import_node_os5.platform)().toString();
13895
14381
  _platform === "win32" && (_platform = "windows");
13896
- let _arch = import_node_process4.default.arch.toString();
14382
+ let _arch = import_node_process7.default.arch.toString();
13897
14383
  _arch === "x64" && (_arch = "amd64");
13898
14384
  const support = supportList.find((item) => item.platform === _platform && item.arch === _arch);
13899
14385
  if (!support)
13900
14386
  return reject2(new Error("not support"));
13901
14387
  const dowmloadLink = `https://caddyserver.com/api/download?os=${support.platform}&arch=${support.arch}&p=github.com%2Fcaddyserver%2Fforwardproxy`;
13902
- (0, import_node_fs3.existsSync)(caddyPath) && (0, import_node_fs3.unlinkSync)(caddyPath);
13903
- const httpProxy = import_node_process4.default.env.HTTP_PROXY || import_node_process4.default.env.http_proxy;
13904
- const httpsProxy = import_node_process4.default.env.HTTPS_PROXY || import_node_process4.default.env.https_proxy;
14388
+ (0, import_node_fs4.existsSync)(caddyPath) && (0, import_node_fs4.unlinkSync)(caddyPath);
14389
+ const httpProxy = import_node_process7.default.env.HTTP_PROXY || import_node_process7.default.env.http_proxy;
14390
+ const httpsProxy = import_node_process7.default.env.HTTPS_PROXY || import_node_process7.default.env.https_proxy;
13905
14391
  const httpAgent = httpProxy ? new import_http_proxy_agent.HttpProxyAgent(httpProxy) : void 0;
13906
14392
  const httpsAgent = httpsProxy ? new import_https_proxy_agent.HttpsProxyAgent(httpsProxy) : void 0;
13907
14393
  const chmodCaddyOnce = once(() => {
13908
- (0, import_node_fs3.chmodSync)(caddyPath, 511);
14394
+ (0, import_node_fs4.chmodSync)(caddyPath, 493);
13909
14395
  });
13910
14396
  import_got_cjs.got.stream(dowmloadLink, {
13911
14397
  agent: {
@@ -13917,9 +14403,9 @@ async function download() {
13917
14403
  chmodCaddyOnce();
13918
14404
  }).pipe(file).on("finish", () => {
13919
14405
  logProgressOver();
13920
- if (import_node_process4.default.platform === "win32")
14406
+ if (import_node_process7.default.platform === "win32")
13921
14407
  return resolve2(caddyPath);
13922
- (0, import_node_fs3.chmodSync)(caddyPath, 511);
14408
+ (0, import_node_fs4.chmodSync)(caddyPath, 493);
13923
14409
  resolve2(caddyPath);
13924
14410
  }).on("error", (err) => {
13925
14411
  reject2(err);
@@ -13927,19 +14413,17 @@ async function download() {
13927
14413
  });
13928
14414
  }
13929
14415
  function testCaddy() {
13930
- return new Promise((resolve2, reject2) => {
13931
- if (!(0, import_node_fs3.existsSync)(caddyPath))
13932
- return resolve2(false);
13933
- (0, import_node_fs3.chmodSync)(caddyPath, 511);
13934
- const child = import_node_process4.default.platform === "win32" ? (0, import_node_child_process4.spawn)(caddyPath, []) : (0, import_node_child_process4.spawn)("sudo", ["-E", caddyPath]);
13935
- child.on("close", () => {
14416
+ return new Promise((resolve2) => {
14417
+ if (!(0, import_node_fs4.existsSync)(caddyPath))
13936
14418
  return resolve2(false);
13937
- });
13938
- child.on("error", (err) => {
13939
- return reject2(err);
13940
- });
13941
- child.stdout.on("data", (_data) => {
13942
- return resolve2(true);
14419
+ try {
14420
+ (0, import_node_fs4.chmodSync)(caddyPath, 493);
14421
+ } catch {
14422
+ }
14423
+ (0, import_node_child_process3.execFile)(caddyPath, [], { timeout: 1e4 }, (error, stdout) => {
14424
+ if (error && !stdout)
14425
+ return resolve2(false);
14426
+ resolve2(stdout.length > 0);
13943
14427
  });
13944
14428
  });
13945
14429
  }
@@ -13961,25 +14445,49 @@ function splitHostPort(addr) {
13961
14445
  }
13962
14446
  return { host: addr.slice(0, lastColon), port: addr.slice(lastColon + 1) };
13963
14447
  }
14448
+ var defaultDependencies = {
14449
+ openSession: (runtimeDir, reason) => openPrivilegedSession(runtimeDir, {
14450
+ log: (message) => consola.debug(message),
14451
+ // Both paths are fixed here, before any socket traffic: the privileged
14452
+ // helper must never execute something named in a request.
14453
+ caddyBin: caddyPath,
14454
+ caddyConfigPath: caddyFilePath,
14455
+ reason
14456
+ })
14457
+ };
13964
14458
  var CaddyInstant = class {
13965
- constructor() {
14459
+ constructor(deps = {}) {
13966
14460
  this.inited = false;
13967
14461
  this.stoped = false;
13968
14462
  /** has locked when start */
13969
14463
  this.locked = false;
13970
14464
  this._stopEffects = [];
13971
- testCaddy().then(async () => {
13972
- this.inited = true;
13973
- });
14465
+ this.deps = { ...defaultDependencies, ...deps };
13974
14466
  this.locked = this.checkLock();
13975
14467
  }
13976
14468
  checkLock() {
13977
- if (!(0, import_node_fs3.existsSync)(caddyLockFilePath))
13978
- (0, import_node_fs3.writeFileSync)(caddyLockFilePath, "");
13979
- return lockfile.checkSync(caddyLockFilePath);
14469
+ if (!(0, import_node_fs4.existsSync)(caddyLockFilePath))
14470
+ (0, import_node_fs4.writeFileSync)(caddyLockFilePath, "");
14471
+ try {
14472
+ return lockfile.checkSync(caddyLockFilePath);
14473
+ } catch {
14474
+ return false;
14475
+ }
14476
+ }
14477
+ /**
14478
+ * Connects to the privileged helper, starting it once if needed. It is
14479
+ * reused across instances so a second dev server does not ask for a
14480
+ * password again.
14481
+ */
14482
+ async session(reason) {
14483
+ if (this._session && !this._session.client.connected)
14484
+ this._session = void 0;
14485
+ if (!this._session)
14486
+ this._session = await this.deps.openSession(TEMP_DIR, reason);
14487
+ return this._session;
13980
14488
  }
13981
14489
  async getCaddyfile() {
13982
- if (!(0, import_node_fs3.existsSync)(caddyFilePath)) {
14490
+ if (!(0, import_node_fs4.existsSync)(caddyFilePath)) {
13983
14491
  this.caddyfile = "";
13984
14492
  return "";
13985
14493
  }
@@ -13987,8 +14495,8 @@ var CaddyInstant = class {
13987
14495
  return this.caddyfile;
13988
14496
  }
13989
14497
  get caddyRoot() {
13990
- return (0, import_node_path3.join)(
13991
- import_node_process4.default.platform === "win32" ? `${import_node_process4.default.env.AppData}/Caddy` : `${import_node_process4.default.env.HOME}/Library/Application Support/Caddy`,
14498
+ return (0, import_node_path5.join)(
14499
+ import_node_process7.default.platform === "win32" ? `${import_node_process7.default.env.AppData}/Caddy` : `${import_node_process7.default.env.HOME}/Library/Application Support/Caddy`,
13992
14500
  "./pki/authorities/local"
13993
14501
  );
13994
14502
  }
@@ -14002,6 +14510,33 @@ var CaddyInstant = class {
14002
14510
  await download();
14003
14511
  this.inited = true;
14004
14512
  }
14513
+ /**
14514
+ * Hands the Caddy storage directory back to the developer. Local CA data
14515
+ * created by an earlier root-owned run must stay readable for `tls internal`
14516
+ * to keep serving the same certificate the browser already trusts.
14517
+ */
14518
+ /**
14519
+ * Installs Caddy's local root CA so the browser stops warning about
14520
+ * `tls internal` certificates. Generating the CA and trusting it are separate
14521
+ * steps: a new CA appears whenever the previous one expires or the storage is
14522
+ * replaced, so this runs on every start instead of once.
14523
+ *
14524
+ * The helper owns both the binary path and the command, so nothing here can
14525
+ * be turned into an arbitrary root execution.
14526
+ */
14527
+ async trustLocalCa(session) {
14528
+ try {
14529
+ const result = await session.client.call("ca.trust");
14530
+ if (result.trusted)
14531
+ consola.debug(`Caddy local CA is trusted
14532
+ ${result.output}`);
14533
+ } catch (error) {
14534
+ consola.warn(
14535
+ `could not install the Caddy root certificate automatically: ${error.message}
14536
+ Run \`${caddyPath} trust\` manually if the browser warns about the certificate.`
14537
+ );
14538
+ }
14539
+ }
14005
14540
  async ensureTlsReady(targetHost) {
14006
14541
  const health = await waitForLocalTls(targetHost);
14007
14542
  if (!health.healthy)
@@ -14055,8 +14590,8 @@ var CaddyInstant = class {
14055
14590
  await this.init();
14056
14591
  const sourceHost = splitHostPort(source).host;
14057
14592
  const targetHost = splitHostPort(target).host;
14058
- if (!await addHost(sourceHost, targetHost))
14059
- throw new Error("update host failed");
14593
+ const session = await this.session({ target: targetHost, https });
14594
+ await session.client.call("hosts.add", { ip: sourceHost, host: targetHost });
14060
14595
  consola.success("update host success\n");
14061
14596
  const normalizeBase = (b) => {
14062
14597
  let out = b || "/";
@@ -14091,24 +14626,24 @@ var CaddyInstant = class {
14091
14626
  void this.updateCaddyfile();
14092
14627
  })
14093
14628
  );
14094
- if (!(0, import_node_fs3.existsSync)(caddyLockFilePath))
14095
- (0, import_node_fs3.writeFileSync)(caddyLockFilePath, "");
14629
+ if (!(0, import_node_fs4.existsSync)(caddyLockFilePath))
14630
+ (0, import_node_fs4.writeFileSync)(caddyLockFilePath, "");
14096
14631
  if (!this.locked) {
14097
- if (await tryPort(443))
14098
- await kill(443);
14099
- if ((import_node_process4.default.platform === "win32" || !https) && await tryPort(80))
14100
- await kill(80);
14632
+ await session.client.call("port.free", { port: 443 });
14633
+ if (import_node_process7.default.platform === "win32" || !https)
14634
+ await session.client.call("port.free", { port: 80 });
14101
14635
  }
14102
14636
  return new Promise((resolve2, reject2) => {
14103
- var _a4, _b3;
14104
14637
  let startupCheckStarted = false;
14105
14638
  const resolveWhenReady = async () => {
14106
14639
  if (startupCheckStarted)
14107
14640
  return;
14108
14641
  startupCheckStarted = true;
14109
14642
  try {
14110
- if (https)
14643
+ if (https) {
14644
+ await this.trustLocalCa(session);
14111
14645
  await this.ensureTlsReady(targetHost);
14646
+ }
14112
14647
  resolve2();
14113
14648
  } catch (error) {
14114
14649
  if (!this.locked)
@@ -14117,96 +14652,87 @@ var CaddyInstant = class {
14117
14652
  }
14118
14653
  };
14119
14654
  const setupCleanup = () => {
14120
- import_node_process4.default.on("SIGINT", async () => {
14655
+ import_node_process7.default.on("SIGINT", async () => {
14121
14656
  if (this.stoped)
14122
14657
  return;
14123
- import_node_process4.default.stdin.resume();
14658
+ import_node_process7.default.stdin.resume();
14124
14659
  try {
14125
14660
  await this.baseCleanup(restore);
14126
14661
  } finally {
14127
14662
  this.stoped = true;
14128
- import_node_process4.default.nextTick(() => {
14129
- import_node_process4.default.exit();
14663
+ import_node_process7.default.nextTick(() => {
14664
+ import_node_process7.default.exit();
14130
14665
  });
14131
14666
  }
14132
14667
  });
14133
- const originalExit = import_node_process4.default.exit.bind(import_node_process4.default);
14134
- import_node_process4.default.exit = async (code) => {
14135
- const port = Number(splitHostPort(source).port);
14136
- if (!Number.isNaN(port) && await tryPort(port))
14137
- await kill(port);
14138
- const pwd = import_node_process4.default.cwd();
14139
- const viteCacheDir = `${pwd}/node_modules/.vite`;
14140
- if ((0, import_node_fs3.existsSync)(viteCacheDir))
14141
- await chmodRecursive(viteCacheDir, 511).catch(() => {
14142
- });
14143
- const viteTempCacheDir = `${pwd}/node_modules/.vite-temp`;
14144
- if ((0, import_node_fs3.existsSync)(viteTempCacheDir))
14145
- await chmodRecursive(viteTempCacheDir, 511).catch(() => {
14146
- });
14147
- const nuxtCacheDir = `${pwd}/.nuxt`;
14148
- if ((0, import_node_fs3.existsSync)(nuxtCacheDir))
14149
- await chmodRecursive(nuxtCacheDir, 511).catch(() => {
14150
- });
14151
- const webpackCacheDir = `${pwd}/node_modules/.cache`;
14152
- if ((0, import_node_fs3.existsSync)(webpackCacheDir))
14153
- await chmodRecursive(webpackCacheDir, 511).catch(() => {
14154
- });
14668
+ const originalExit = import_node_process7.default.exit.bind(import_node_process7.default);
14669
+ import_node_process7.default.exit = async (code) => {
14155
14670
  if (this.stoped)
14156
14671
  return originalExit(code);
14157
- import_node_process4.default.stdin.resume();
14672
+ import_node_process7.default.stdin.resume();
14158
14673
  try {
14159
14674
  await this.baseCleanup();
14160
14675
  } finally {
14161
14676
  this.stoped = true;
14162
- import_node_process4.default.nextTick(() => {
14677
+ import_node_process7.default.nextTick(() => {
14163
14678
  originalExit(code);
14164
14679
  });
14165
14680
  }
14166
14681
  };
14167
14682
  };
14168
14683
  if (!this.locked) {
14169
- this._caddyChild = import_node_process4.default.platform !== "win32" ? (0, import_node_child_process4.spawn)("sudo", ["-E", caddyPath, "run", "--config", caddyFilePath, "--watch"]) : (0, import_node_child_process4.spawn)(caddyPath, ["run", "--config", caddyFilePath, "--watch"]);
14170
14684
  lockfile.lockSync(caddyLockFilePath);
14171
- this._caddyChild.on("error", (err) => {
14172
- return reject2(err);
14173
- });
14174
- (_a4 = this._caddyChild.stderr) == null ? void 0 : _a4.on("data", async (data) => {
14175
- const lines = data.toString().split("\n").map((line) => line.trim());
14176
- for (const line of lines) {
14177
- showCaddyLog && line && console.info(line);
14178
- if (isCaddyReloadCancellation(line)) {
14179
- consola.info("Caddy restarted before TLS issuance completed; retrying.\n");
14180
- continue;
14181
- }
14182
- try {
14183
- if (line.includes("Error:") || line && JSON.parse(line).level === "error") {
14184
- if (line.includes("parsing caddyfile tokens")) {
14185
- consola.error("Caddyfile syntax error, please contact the author:\n", `${this.caddyfile}
14685
+ setupCleanup();
14686
+ void (async () => {
14687
+ try {
14688
+ const child = new HelperCaddyProcess(session.client);
14689
+ this._caddyChild = child;
14690
+ await session.client.call("caddy.start");
14691
+ child.on("exit", (code) => {
14692
+ if (code !== null && code !== 0)
14693
+ reject2(new Error(`Caddy exited with code ${code}`));
14694
+ });
14695
+ child.stderr.on("data", async (data) => {
14696
+ const lines = data.toString().split("\n").map((line) => line.trim());
14697
+ for (const line of lines) {
14698
+ showCaddyLog && line && console.info(line);
14699
+ if (isCaddyReloadCancellation(line)) {
14700
+ consola.info("Caddy restarted before TLS issuance completed; retrying.\n");
14701
+ continue;
14702
+ }
14703
+ try {
14704
+ if (line.includes("Error:") || line && JSON.parse(line).level === "error") {
14705
+ if (line.includes("parsing caddyfile tokens")) {
14706
+ consola.error("Caddyfile syntax error, please contact the author:\n", `${this.caddyfile}
14186
14707
 
14187
14708
  ${line}
14188
14709
  `);
14189
- await this.baseCleanup();
14190
- import_node_process4.default.exit();
14191
- } else {
14192
- consola.error(`${line}
14710
+ await this.baseCleanup();
14711
+ import_node_process7.default.exit();
14712
+ } else {
14713
+ consola.error(`${line}
14193
14714
  `);
14194
- return reject2(line);
14715
+ return reject2(line);
14716
+ }
14717
+ }
14718
+ } catch {
14195
14719
  }
14720
+ if (line.includes("config file changed"))
14721
+ consola.success("Detect added a new reverse proxy config, restarted.\n");
14722
+ if (line.includes("caddy proxying") || line.includes("serving initial"))
14723
+ void resolveWhenReady();
14196
14724
  }
14197
- } catch {
14198
- }
14199
- if (line.includes("config file changed"))
14200
- consola.success("Detect added a new reverse proxy config, restarted.\n");
14201
- if (line.includes("caddy proxying") || line.includes("serving initial"))
14725
+ });
14726
+ child.stdout.on("data", (data) => {
14727
+ consola.info(data.toString());
14202
14728
  void resolveWhenReady();
14729
+ });
14730
+ } catch (error) {
14731
+ if (!this.locked)
14732
+ await this.baseCleanup(restore);
14733
+ reject2(error);
14203
14734
  }
14204
- });
14205
- (_b3 = this._caddyChild.stdout) == null ? void 0 : _b3.on("data", (_data) => {
14206
- consola.info(_data.toString());
14207
- void resolveWhenReady();
14208
- });
14209
- setupCleanup();
14735
+ })();
14210
14736
  } else {
14211
14737
  consola.info("Caddy is running in another process.");
14212
14738
  void (async () => {
@@ -14223,17 +14749,25 @@ ${line}
14223
14749
  });
14224
14750
  }
14225
14751
  async baseCleanup(restore = true) {
14752
+ var _a4;
14226
14753
  this._stopEffects.forEach((fn) => fn());
14754
+ this._stopEffects.length = 0;
14227
14755
  try {
14228
- if (restore && this._source && this._target) {
14229
- if (await removeHost(splitHostPort(this._source).host, splitHostPort(this._target).host))
14230
- consola.success("Restore host success.\n");
14231
- else
14232
- consola.fail("Restore host failed.\n");
14756
+ if (restore && this._source && this._target && this._session) {
14757
+ const sourceHost = splitHostPort(this._source).host;
14758
+ const targetHost = splitHostPort(this._target).host;
14759
+ await this._session.client.call("hosts.remove", { ip: sourceHost, host: targetHost });
14760
+ if (sourceHost === "localhost")
14761
+ await this._session.client.call("hosts.remove", { ip: "127.0.0.1", host: targetHost });
14762
+ consola.success("Restore host success.\n");
14233
14763
  }
14234
14764
  } catch (e) {
14235
- consola.error(e);
14236
- consola.fail("Restore host failed.\n");
14765
+ if (((_a4 = this._session) == null ? void 0 : _a4.client.connected) === false) {
14766
+ consola.debug("hosts entries are restored by the privileged helper on disconnect");
14767
+ } else {
14768
+ consola.error(e);
14769
+ consola.fail("Restore host failed.\n");
14770
+ }
14237
14771
  }
14238
14772
  if (!this.locked && !this.stoped) {
14239
14773
  await this.stopCaddy();
@@ -14488,11 +15022,20 @@ var hmrSseBridgeClientScript = `
14488
15022
  })();
14489
15023
  `;
14490
15024
 
15025
+ // src/privilege-state.ts
15026
+ var denied = false;
15027
+ function markPrivilegeDenied() {
15028
+ denied = true;
15029
+ }
15030
+ function isPrivilegeDenied() {
15031
+ return denied;
15032
+ }
15033
+
14491
15034
  // src/index.ts
14492
15035
  var config;
14493
15036
  var caddy;
14494
15037
  var hmrSseBridgeActive = false;
14495
- var cwd = import_node_process5.default.cwd();
15038
+ var cwd = import_node_process8.default.cwd();
14496
15039
  function colorUrl(url2) {
14497
15040
  return import_picocolors2.default.green(url2.replace(/:(\d+)\//, (_, port) => `:${import_picocolors2.default.bold(port)}/`));
14498
15041
  }
@@ -14527,16 +15070,27 @@ async function printForwardProxy() {
14527
15070
  }
14528
15071
  var vitePrintUrls = once((options, source, target, base = "/", _printUrls) => {
14529
15072
  _printUrls == null ? void 0 : _printUrls();
15073
+ if (isPrivilegeDenied())
15074
+ return;
14530
15075
  if (caddy)
14531
15076
  return;
14532
- caddy = new CaddyInstant();
14533
- caddy.run(source, target, {
15077
+ const instance = new CaddyInstant();
15078
+ caddy = instance;
15079
+ instance.run(source, target, {
14534
15080
  base,
14535
15081
  ...options
14536
15082
  }).then(async () => {
14537
15083
  await printForwardProxy();
14538
15084
  consola.success(` ${import_picocolors2.default.green("\u279C")} ${import_picocolors2.default.bold("run caddy reverse proxy success")}: ${colorUrl(`${options.https ? "https" : "http"}://${target}${base}`)}`);
14539
15085
  }).catch((e) => {
15086
+ if (caddy === instance)
15087
+ caddy = void 0;
15088
+ if (e instanceof PrivilegeDeniedError) {
15089
+ markPrivilegeDenied();
15090
+ consola.warn("reverse proxy skipped: administrator permission was not granted.");
15091
+ consola.info("Restart the dev server to enable it again.");
15092
+ return;
15093
+ }
14540
15094
  throw e;
14541
15095
  });
14542
15096
  });
@@ -14557,10 +15111,6 @@ var unpluginFactory = (options) => ({
14557
15111
  } = options;
14558
15112
  if (!enable)
14559
15113
  return;
14560
- if (!isAdmin()) {
14561
- consola.warn("please run as administrator");
14562
- return;
14563
- }
14564
15114
  if (!target) {
14565
15115
  consola.fail("please provide target");
14566
15116
  return;
@@ -14596,7 +15146,7 @@ var unpluginFactory = (options) => ({
14596
15146
  },
14597
15147
  webpack(compiler) {
14598
15148
  var _a4, _b3, _c2;
14599
- if (import_node_process5.default.env.NODE_ENV !== "development")
15149
+ if (import_node_process8.default.env.NODE_ENV !== "development")
14600
15150
  return;
14601
15151
  const {
14602
15152
  enable = true,
@@ -14604,10 +15154,6 @@ var unpluginFactory = (options) => ({
14604
15154
  } = options;
14605
15155
  if (!enable)
14606
15156
  return;
14607
- if (!isAdmin()) {
14608
- consola.warn("please run as administrator");
14609
- return;
14610
- }
14611
15157
  if (!target) {
14612
15158
  consola.fail("please provide target");
14613
15159
  return;
@@ -14621,9 +15167,11 @@ var unpluginFactory = (options) => ({
14621
15167
  port: 8080,
14622
15168
  ...compiler.options.devServer,
14623
15169
  // @ts-expect-error vuecli
14624
- ...(_a4 = import_node_process5.default.VUE_CLI_SERVICE) == null ? void 0 : _a4.projectOptions.devServer
15170
+ ...(_a4 = import_node_process8.default.VUE_CLI_SERVICE) == null ? void 0 : _a4.projectOptions.devServer
14625
15171
  };
14626
15172
  const source = `${devServer.host}:${devServer.port}`;
15173
+ if (isPrivilegeDenied())
15174
+ return;
14627
15175
  if (caddy)
14628
15176
  return;
14629
15177
  let base = "/";
@@ -14638,15 +15186,16 @@ var unpluginFactory = (options) => ({
14638
15186
  const _close = (_c2 = compiler.close) == null ? void 0 : _c2.bind(compiler);
14639
15187
  if (_close) {
14640
15188
  compiler.close = async (callback) => {
14641
- import_node_process5.default.on("exit", () => {
15189
+ import_node_process8.default.on("exit", () => {
14642
15190
  _close && _close(callback);
14643
15191
  });
14644
15192
  };
14645
15193
  } else {
14646
15194
  options.https = false;
14647
15195
  }
14648
- caddy = new CaddyInstant();
14649
- caddy.run(source, target, {
15196
+ const instance = new CaddyInstant();
15197
+ caddy = instance;
15198
+ instance.run(source, target, {
14650
15199
  base,
14651
15200
  ...options
14652
15201
  }).then(() => {
@@ -14655,12 +15204,20 @@ var unpluginFactory = (options) => ({
14655
15204
  consola.success(` ${import_picocolors2.default.green("\u279C")} ${import_picocolors2.default.bold("run caddy reverse proxy success")}: ${colorUrl(`${options.https ? "https" : "http"}://${target}${base}`)}`);
14656
15205
  });
14657
15206
  }).catch((e) => {
15207
+ if (caddy === instance)
15208
+ caddy = void 0;
15209
+ if (e instanceof PrivilegeDeniedError) {
15210
+ markPrivilegeDenied();
15211
+ consola.warn("reverse proxy skipped: administrator permission was not granted.");
15212
+ consola.info("Restart the dev server to enable it again.");
15213
+ return;
15214
+ }
14658
15215
  throw e;
14659
15216
  });
14660
15217
  },
14661
15218
  async rspack(compiler) {
14662
15219
  var _a4, _b3, _c2, _d2;
14663
- if (import_node_process5.default.env.NODE_ENV !== "development")
15220
+ if (import_node_process8.default.env.NODE_ENV !== "development")
14664
15221
  return;
14665
15222
  const {
14666
15223
  enable = true,
@@ -14668,10 +15225,6 @@ var unpluginFactory = (options) => ({
14668
15225
  } = options;
14669
15226
  if (!enable)
14670
15227
  return;
14671
- if (!isAdmin()) {
14672
- consola.warn("please run as administrator");
14673
- return;
14674
- }
14675
15228
  if (!target) {
14676
15229
  consola.fail("please provide target");
14677
15230
  return;
@@ -14689,9 +15242,10 @@ var unpluginFactory = (options) => ({
14689
15242
  }))) == null ? void 0 : _b3.content) == null ? void 0 : _c2.server
14690
15243
  };
14691
15244
  const source = `${devServer.host}:${devServer.port}`;
15245
+ if (isPrivilegeDenied())
15246
+ return;
14692
15247
  if (caddy)
14693
15248
  return;
14694
- caddy = new CaddyInstant();
14695
15249
  let base = "/";
14696
15250
  const publicPath = (_d2 = compiler.options.output) == null ? void 0 : _d2.publicPath;
14697
15251
  if (typeof publicPath === "string" && publicPath) {
@@ -14701,13 +15255,23 @@ var unpluginFactory = (options) => ({
14701
15255
  base = `/${base}`;
14702
15256
  if (base !== "/" && !base.endsWith("/"))
14703
15257
  base = `${base}/`;
14704
- caddy.run(source, target, {
15258
+ const instance = new CaddyInstant();
15259
+ caddy = instance;
15260
+ instance.run(source, target, {
14705
15261
  base,
14706
15262
  ...options
14707
15263
  }).then(async () => {
14708
15264
  await printForwardProxy();
14709
15265
  consola.success(` ${import_picocolors2.default.green("\u279C")} ${import_picocolors2.default.bold("run caddy reverse proxy success")}: ${colorUrl(`${options.https ? "https" : "http"}://${target}${base}`)}`);
14710
15266
  }).catch((e) => {
15267
+ if (caddy === instance)
15268
+ caddy = void 0;
15269
+ if (e instanceof PrivilegeDeniedError) {
15270
+ markPrivilegeDenied();
15271
+ consola.warn("reverse proxy skipped: administrator permission was not granted.");
15272
+ consola.info("Restart the dev server to enable it again.");
15273
+ return;
15274
+ }
14711
15275
  throw e;
14712
15276
  });
14713
15277
  }