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