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

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 (56) hide show
  1. package/README.md +30 -6
  2. package/dist/{chunk-2P7SUCQ3.js → chunk-EY3HXBJ4.js} +0 -26
  3. package/dist/chunk-RKHJN6KY.js +53 -0
  4. package/dist/{chunk-5R33PUJP.js → chunk-U7KAIPZC.js} +981 -796
  5. package/dist/chunk-WOMR3ZLM.js +17 -0
  6. package/dist/esbuild.cjs +1077 -864
  7. package/dist/esbuild.js +4 -2
  8. package/dist/index.cjs +1077 -864
  9. package/dist/index.js +4 -2
  10. package/dist/nuxt.cjs +1049 -850
  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 +824 -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 +797 -0
  20. package/dist/rollup.cjs +1077 -864
  21. package/dist/rollup.js +4 -2
  22. package/dist/rspack.cjs +1077 -864
  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 +1077 -864
  29. package/dist/vite.js +4 -2
  30. package/dist/webpack.cjs +1077 -864
  31. package/dist/webpack.js +4 -2
  32. package/package.json +1 -4
  33. package/src/caddy/caddyfile.ts +3 -0
  34. package/src/caddy/config.ts +195 -53
  35. package/src/caddy/constants.ts +30 -1
  36. package/src/caddy/index.ts +239 -206
  37. package/src/caddy/privileged.ts +124 -0
  38. package/src/caddy/utils.ts +0 -43
  39. package/src/index.ts +49 -22
  40. package/src/nuxt.ts +1 -6
  41. package/src/privilege-state.ts +23 -0
  42. package/src/privileged/bootstrap.ts +289 -0
  43. package/src/privileged/client.ts +288 -0
  44. package/src/privileged/entry.ts +73 -0
  45. package/src/privileged/hosts-file.ts +142 -0
  46. package/src/privileged/launch.ts +332 -0
  47. package/src/privileged/path-guard.ts +74 -0
  48. package/src/privileged/ports.ts +45 -0
  49. package/src/privileged/protocol.ts +111 -0
  50. package/src/privileged/server.ts +578 -0
  51. package/src/privileged/session.ts +169 -0
  52. package/src/privileged/validation.ts +38 -0
  53. package/src/privileged/windows-elevation.ts +80 -0
  54. package/src/privileged-helper.ts +123 -0
  55. package/src/utils.ts +0 -28
  56. package/src/host/index.ts +0 -52
package/dist/index.cjs CHANGED
@@ -36,486 +36,30 @@ __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_process9 = __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");
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);
51
-
52
- // node_modules/.pnpm/alien-signals@2.0.7/node_modules/alien-signals/esm/system.mjs
53
- var ReactiveFlags;
54
- (function(ReactiveFlags2) {
55
- ReactiveFlags2[ReactiveFlags2["None"] = 0] = "None";
56
- ReactiveFlags2[ReactiveFlags2["Mutable"] = 1] = "Mutable";
57
- ReactiveFlags2[ReactiveFlags2["Watching"] = 2] = "Watching";
58
- ReactiveFlags2[ReactiveFlags2["RecursedCheck"] = 4] = "RecursedCheck";
59
- ReactiveFlags2[ReactiveFlags2["Recursed"] = 8] = "Recursed";
60
- ReactiveFlags2[ReactiveFlags2["Dirty"] = 16] = "Dirty";
61
- ReactiveFlags2[ReactiveFlags2["Pending"] = 32] = "Pending";
62
- })(ReactiveFlags || (ReactiveFlags = {}));
63
- function createReactiveSystem({ update, notify: notify2, unwatched }) {
64
- let currentVersion = 0;
65
- return {
66
- link: link2,
67
- unlink: unlink4,
68
- propagate: propagate2,
69
- checkDirty: checkDirty2,
70
- endTracking: endTracking2,
71
- startTracking: startTracking2,
72
- shallowPropagate: shallowPropagate2
73
- };
74
- function link2(dep, sub) {
75
- const prevDep = sub.depsTail;
76
- if (prevDep !== void 0 && prevDep.dep === dep) {
77
- return;
78
- }
79
- const nextDep = prevDep !== void 0 ? prevDep.nextDep : sub.deps;
80
- if (nextDep !== void 0 && nextDep.dep === dep) {
81
- nextDep.version = currentVersion;
82
- sub.depsTail = nextDep;
83
- return;
84
- }
85
- const prevSub = dep.subsTail;
86
- if (prevSub !== void 0 && prevSub.version === currentVersion && prevSub.sub === sub) {
87
- return;
88
- }
89
- const newLink = sub.depsTail = dep.subsTail = {
90
- version: currentVersion,
91
- dep,
92
- sub,
93
- prevDep,
94
- nextDep,
95
- prevSub,
96
- nextSub: void 0
97
- };
98
- if (nextDep !== void 0) {
99
- nextDep.prevDep = newLink;
100
- }
101
- if (prevDep !== void 0) {
102
- prevDep.nextDep = newLink;
103
- } else {
104
- sub.deps = newLink;
105
- }
106
- if (prevSub !== void 0) {
107
- prevSub.nextSub = newLink;
108
- } else {
109
- dep.subs = newLink;
110
- }
111
- }
112
- function unlink4(link3, sub = link3.sub) {
113
- const dep = link3.dep;
114
- const prevDep = link3.prevDep;
115
- const nextDep = link3.nextDep;
116
- const nextSub = link3.nextSub;
117
- const prevSub = link3.prevSub;
118
- if (nextDep !== void 0) {
119
- nextDep.prevDep = prevDep;
120
- } else {
121
- sub.depsTail = prevDep;
122
- }
123
- if (prevDep !== void 0) {
124
- prevDep.nextDep = nextDep;
125
- } else {
126
- sub.deps = nextDep;
127
- }
128
- if (nextSub !== void 0) {
129
- nextSub.prevSub = prevSub;
130
- } else {
131
- dep.subsTail = prevSub;
132
- }
133
- if (prevSub !== void 0) {
134
- prevSub.nextSub = nextSub;
135
- } else if ((dep.subs = nextSub) === void 0) {
136
- unwatched(dep);
137
- }
138
- return nextDep;
139
- }
140
- function propagate2(link3) {
141
- let next2 = link3.nextSub;
142
- let stack;
143
- top:
144
- do {
145
- const sub = link3.sub;
146
- let flags = sub.flags;
147
- if (!(flags & 60)) {
148
- sub.flags = flags | 32;
149
- } else if (!(flags & 12)) {
150
- flags = 0;
151
- } else if (!(flags & 4)) {
152
- sub.flags = flags & ~8 | 32;
153
- } else if (!(flags & 48) && isValidLink(link3, sub)) {
154
- sub.flags = flags | 40;
155
- flags &= 1;
156
- } else {
157
- flags = 0;
158
- }
159
- if (flags & 2) {
160
- notify2(sub);
161
- }
162
- if (flags & 1) {
163
- const subSubs = sub.subs;
164
- if (subSubs !== void 0) {
165
- const nextSub = (link3 = subSubs).nextSub;
166
- if (nextSub !== void 0) {
167
- stack = { value: next2, prev: stack };
168
- next2 = nextSub;
169
- }
170
- continue;
171
- }
172
- }
173
- if ((link3 = next2) !== void 0) {
174
- next2 = link3.nextSub;
175
- continue;
176
- }
177
- while (stack !== void 0) {
178
- link3 = stack.value;
179
- stack = stack.prev;
180
- if (link3 !== void 0) {
181
- next2 = link3.nextSub;
182
- continue top;
183
- }
184
- }
185
- break;
186
- } while (true);
187
- }
188
- function startTracking2(sub) {
189
- ++currentVersion;
190
- sub.depsTail = void 0;
191
- sub.flags = sub.flags & ~56 | 4;
192
- }
193
- function endTracking2(sub) {
194
- const depsTail = sub.depsTail;
195
- let toRemove = depsTail !== void 0 ? depsTail.nextDep : sub.deps;
196
- while (toRemove !== void 0) {
197
- toRemove = unlink4(toRemove, sub);
198
- }
199
- sub.flags &= ~4;
200
- }
201
- function checkDirty2(link3, sub) {
202
- let stack;
203
- let checkDepth = 0;
204
- top:
205
- do {
206
- const dep = link3.dep;
207
- const flags = dep.flags;
208
- let dirty = false;
209
- if (sub.flags & 16) {
210
- dirty = true;
211
- } else if ((flags & 17) === 17) {
212
- if (update(dep)) {
213
- const subs = dep.subs;
214
- if (subs.nextSub !== void 0) {
215
- shallowPropagate2(subs);
216
- }
217
- dirty = true;
218
- }
219
- } else if ((flags & 33) === 33) {
220
- if (link3.nextSub !== void 0 || link3.prevSub !== void 0) {
221
- stack = { value: link3, prev: stack };
222
- }
223
- link3 = dep.deps;
224
- sub = dep;
225
- ++checkDepth;
226
- continue;
227
- }
228
- if (!dirty) {
229
- const nextDep = link3.nextDep;
230
- if (nextDep !== void 0) {
231
- link3 = nextDep;
232
- continue;
233
- }
234
- }
235
- while (checkDepth--) {
236
- const firstSub = sub.subs;
237
- const hasMultipleSubs = firstSub.nextSub !== void 0;
238
- if (hasMultipleSubs) {
239
- link3 = stack.value;
240
- stack = stack.prev;
241
- } else {
242
- link3 = firstSub;
243
- }
244
- if (dirty) {
245
- if (update(sub)) {
246
- if (hasMultipleSubs) {
247
- shallowPropagate2(firstSub);
248
- }
249
- sub = link3.sub;
250
- continue;
251
- }
252
- } else {
253
- sub.flags &= ~32;
254
- }
255
- sub = link3.sub;
256
- const nextDep = link3.nextDep;
257
- if (nextDep !== void 0) {
258
- link3 = nextDep;
259
- continue top;
260
- }
261
- dirty = false;
262
- }
263
- return dirty;
264
- } while (true);
265
- }
266
- function shallowPropagate2(link3) {
267
- do {
268
- const sub = link3.sub;
269
- const flags = sub.flags;
270
- if ((flags & 48) === 32) {
271
- sub.flags = flags | 16;
272
- if (flags & 2) {
273
- notify2(sub);
274
- }
275
- }
276
- } while ((link3 = link3.nextSub) !== void 0);
277
- }
278
- function isValidLink(checkLink, sub) {
279
- let link3 = sub.depsTail;
280
- while (link3 !== void 0) {
281
- if (link3 === checkLink) {
282
- return true;
283
- }
284
- link3 = link3.prevDep;
285
- }
286
- return false;
287
- }
288
- }
289
-
290
- // node_modules/.pnpm/alien-signals@2.0.7/node_modules/alien-signals/esm/index.mjs
291
- var queuedEffects = [];
292
- var { link, unlink, propagate, checkDirty, endTracking, startTracking, shallowPropagate } = createReactiveSystem({
293
- update(signal2) {
294
- if ("getter" in signal2) {
295
- return updateComputed(signal2);
296
- } else {
297
- return updateSignal(signal2, signal2.value);
298
- }
299
- },
300
- notify,
301
- unwatched(node2) {
302
- if ("getter" in node2) {
303
- let toRemove = node2.deps;
304
- if (toRemove !== void 0) {
305
- node2.flags = 17;
306
- do {
307
- toRemove = unlink(toRemove, node2);
308
- } while (toRemove !== void 0);
309
- }
310
- } else if (!("previousValue" in node2)) {
311
- effectOper.call(node2);
312
- }
313
- }
314
- });
315
- var batchDepth = 0;
316
- var notifyIndex = 0;
317
- var queuedEffectsLength = 0;
318
- var activeSub;
319
- var activeScope;
320
- function setCurrentSub(sub) {
321
- const prevSub = activeSub;
322
- activeSub = sub;
323
- return prevSub;
324
- }
325
- function signal(initialValue) {
326
- return signalOper.bind({
327
- previousValue: initialValue,
328
- value: initialValue,
329
- subs: void 0,
330
- subsTail: void 0,
331
- flags: 1
332
- });
333
- }
334
- function computed(getter) {
335
- return computedOper.bind({
336
- value: void 0,
337
- subs: void 0,
338
- subsTail: void 0,
339
- deps: void 0,
340
- depsTail: void 0,
341
- flags: 17,
342
- getter
343
- });
344
- }
345
- function effect(fn) {
346
- const e = {
347
- fn,
348
- subs: void 0,
349
- subsTail: void 0,
350
- deps: void 0,
351
- depsTail: void 0,
352
- flags: 2
353
- };
354
- if (activeSub !== void 0) {
355
- link(e, activeSub);
356
- } else if (activeScope !== void 0) {
357
- link(e, activeScope);
358
- }
359
- const prev = setCurrentSub(e);
360
- try {
361
- e.fn();
362
- } finally {
363
- setCurrentSub(prev);
364
- }
365
- return effectOper.bind(e);
366
- }
367
- function updateComputed(c3) {
368
- const prevSub = setCurrentSub(c3);
369
- startTracking(c3);
370
- try {
371
- const oldValue = c3.value;
372
- return oldValue !== (c3.value = c3.getter(oldValue));
373
- } finally {
374
- setCurrentSub(prevSub);
375
- endTracking(c3);
376
- }
377
- }
378
- function updateSignal(s, value2) {
379
- s.flags = 1;
380
- return s.previousValue !== (s.previousValue = value2);
381
- }
382
- function notify(e) {
383
- const flags = e.flags;
384
- if (!(flags & 64)) {
385
- e.flags = flags | 64;
386
- const subs = e.subs;
387
- if (subs !== void 0) {
388
- notify(subs.sub);
389
- } else {
390
- queuedEffects[queuedEffectsLength++] = e;
391
- }
392
- }
393
- }
394
- function run(e, flags) {
395
- if (flags & 16 || flags & 32 && checkDirty(e.deps, e)) {
396
- const prev = setCurrentSub(e);
397
- startTracking(e);
398
- try {
399
- e.fn();
400
- } finally {
401
- setCurrentSub(prev);
402
- endTracking(e);
403
- }
404
- return;
405
- } else if (flags & 32) {
406
- e.flags = flags & ~32;
407
- }
408
- let link2 = e.deps;
409
- while (link2 !== void 0) {
410
- const dep = link2.dep;
411
- const depFlags = dep.flags;
412
- if (depFlags & 64) {
413
- run(dep, dep.flags = depFlags & ~64);
414
- }
415
- link2 = link2.nextDep;
416
- }
417
- }
418
- function flush() {
419
- while (notifyIndex < queuedEffectsLength) {
420
- const effect2 = queuedEffects[notifyIndex];
421
- queuedEffects[notifyIndex++] = void 0;
422
- run(effect2, effect2.flags &= ~64);
423
- }
424
- notifyIndex = 0;
425
- queuedEffectsLength = 0;
426
- }
427
- function computedOper() {
428
- const flags = this.flags;
429
- if (flags & 16 || flags & 32 && checkDirty(this.deps, this)) {
430
- if (updateComputed(this)) {
431
- const subs = this.subs;
432
- if (subs !== void 0) {
433
- shallowPropagate(subs);
434
- }
435
- }
436
- } else if (flags & 32) {
437
- this.flags = flags & ~32;
438
- }
439
- if (activeSub !== void 0) {
440
- link(this, activeSub);
441
- } else if (activeScope !== void 0) {
442
- link(this, activeScope);
443
- }
444
- return this.value;
445
- }
446
- function signalOper(...value2) {
447
- if (value2.length) {
448
- if (this.value !== (this.value = value2[0])) {
449
- this.flags = 17;
450
- const subs = this.subs;
451
- if (subs !== void 0) {
452
- propagate(subs);
453
- if (!batchDepth) {
454
- flush();
455
- }
456
- }
457
- }
458
- } else {
459
- const value3 = this.value;
460
- if (this.flags & 16) {
461
- if (updateSignal(this, value3)) {
462
- const subs = this.subs;
463
- if (subs !== void 0) {
464
- shallowPropagate(subs);
465
- }
466
- }
467
- }
468
- if (activeSub !== void 0) {
469
- link(this, activeSub);
470
- }
471
- return value3;
472
- }
473
- }
474
- function effectOper() {
475
- let dep = this.deps;
476
- while (dep !== void 0) {
477
- dep = unlink(dep, this);
478
- }
479
- const sub = this.subs;
480
- if (sub !== void 0) {
481
- unlink(sub);
482
- }
483
- this.flags = 0;
484
- }
485
-
486
- // src/caddy/index.ts
45
+ var import_node_child_process3 = require("child_process");
46
+ var import_node_fs4 = require("fs");
47
+ var import_promises2 = require("fs/promises");
48
+ var import_node_os5 = require("os");
49
+ var import_node_path5 = require("path");
50
+ var import_node_process8 = __toESM(require("process"), 1);
487
51
  var import_got_cjs = require("got-cjs");
488
52
  var import_http_proxy_agent = require("http-proxy-agent");
489
53
  var import_https_proxy_agent = require("https-proxy-agent");
490
- var lockfile = __toESM(require("proper-lockfile"), 1);
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
54
 
499
55
  // src/utils.ts
500
- var import_node_child_process = require("child_process");
501
- var import_promises = require("fs/promises");
502
56
  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
57
  var import_consola = require("consola");
506
58
  var import_picocolors = __toESM(require("picocolors"), 1);
507
59
  var import_qrcode_terminal = __toESM(require("qrcode-terminal"), 1);
508
60
  var consola = (0, import_consola.createConsola)({
509
61
  level: 3
510
62
  }).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
63
  function once(fn) {
520
64
  let called = false;
521
65
  return (...args2) => {
@@ -525,18 +69,6 @@ function once(fn) {
525
69
  return fn(...args2);
526
70
  };
527
71
  }
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
72
  function getIpv4List() {
541
73
  const interfaces = (0, import_node_os.networkInterfaces)();
542
74
  return Object.values(interfaces).flatMap((nInterface) => nInterface ?? []).filter(
@@ -551,44 +83,6 @@ async function generateQrcode(input) {
551
83
  });
552
84
  }
553
85
 
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
86
  // node_modules/.pnpm/@ark+util@0.46.0/node_modules/@ark/util/out/arrays.js
593
87
  var liftArray = (data) => Array.isArray(data) ? data : [data];
594
88
  var spliterate = (arr, predicate) => {
@@ -1216,29 +710,29 @@ var timeWithUnnecessarySeconds = /:\d\d:00$/;
1216
710
  var pad = (value2, length) => String(value2).padStart(length, "0");
1217
711
 
1218
712
  // node_modules/.pnpm/@ark+util@0.46.0/node_modules/@ark/util/out/path.js
1219
- var appendStringifiedKey = (path2, prop, ...[opts]) => {
713
+ var appendStringifiedKey = (path, prop, ...[opts]) => {
1220
714
  const stringifySymbol = (opts == null ? void 0 : opts.stringifySymbol) ?? printable;
1221
- let propAccessChain = path2;
715
+ let propAccessChain = path;
1222
716
  switch (typeof prop) {
1223
717
  case "string":
1224
- propAccessChain = isDotAccessible(prop) ? path2 === "" ? prop : `${path2}.${prop}` : `${path2}[${JSON.stringify(prop)}]`;
718
+ propAccessChain = isDotAccessible(prop) ? path === "" ? prop : `${path}.${prop}` : `${path}[${JSON.stringify(prop)}]`;
1225
719
  break;
1226
720
  case "number":
1227
- propAccessChain = `${path2}[${prop}]`;
721
+ propAccessChain = `${path}[${prop}]`;
1228
722
  break;
1229
723
  case "symbol":
1230
- propAccessChain = `${path2}[${stringifySymbol(prop)}]`;
724
+ propAccessChain = `${path}[${stringifySymbol(prop)}]`;
1231
725
  break;
1232
726
  default:
1233
727
  if (opts == null ? void 0 : opts.stringifyNonKey)
1234
- propAccessChain = `${path2}[${opts.stringifyNonKey(prop)}]`;
728
+ propAccessChain = `${path}[${opts.stringifyNonKey(prop)}]`;
1235
729
  else {
1236
730
  throwParseError(`${printable(prop)} must be a PropertyKey or stringifyNonKey must be passed to options`);
1237
731
  }
1238
732
  }
1239
733
  return propAccessChain;
1240
734
  };
1241
- var stringifyPath = (path2, ...opts) => path2.reduce((s, k) => appendStringifiedKey(s, k, ...opts), "");
735
+ var stringifyPath = (path, ...opts) => path.reduce((s, k) => appendStringifiedKey(s, k, ...opts), "");
1242
736
  var ReadonlyPath = class extends ReadonlyArray {
1243
737
  // alternate strategy for caching since the base object is frozen
1244
738
  cache = {};
@@ -1265,8 +759,8 @@ var ReadonlyPath = class extends ReadonlyArray {
1265
759
  return this.cache.stringifyAncestors;
1266
760
  let propString = "";
1267
761
  const result = [propString];
1268
- for (const path2 of this) {
1269
- propString = appendStringifiedKey(propString, path2);
762
+ for (const path of this) {
763
+ propString = appendStringifiedKey(propString, path);
1270
764
  result.push(propString);
1271
765
  }
1272
766
  return this.cache.stringifyAncestors = result;
@@ -1859,15 +1353,15 @@ var ArkErrors = class _ArkErrors extends ReadonlyArray {
1859
1353
  /**
1860
1354
  * @internal
1861
1355
  */
1862
- affectsPath(path2) {
1356
+ affectsPath(path) {
1863
1357
  if (this.length === 0)
1864
1358
  return false;
1865
1359
  return (
1866
1360
  // this would occur if there is an existing error at a prefix of path
1867
1361
  // 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
1362
+ path.stringifyAncestors().some((s) => s in this.byPath) || // this would occur if there is an existing error at a suffix of path
1869
1363
  // e.g. the path is ["foo"] and there is an error at ["foo", "bar"]
1870
- path2.stringify() in this.byAncestorPath
1364
+ path.stringify() in this.byAncestorPath
1871
1365
  );
1872
1366
  }
1873
1367
  /**
@@ -2074,22 +1568,22 @@ var Traversal = class {
2074
1568
  while (this.queuedMorphs.length) {
2075
1569
  const queuedMorphs = this.queuedMorphs;
2076
1570
  this.queuedMorphs = [];
2077
- for (const { path: path2, morphs } of queuedMorphs) {
2078
- if (this.errors.affectsPath(path2))
1571
+ for (const { path, morphs } of queuedMorphs) {
1572
+ if (this.errors.affectsPath(path))
2079
1573
  continue;
2080
- this.applyMorphsAtPath(path2, morphs);
1574
+ this.applyMorphsAtPath(path, morphs);
2081
1575
  }
2082
1576
  }
2083
1577
  }
2084
- applyMorphsAtPath(path2, morphs) {
2085
- const key = path2.at(-1);
1578
+ applyMorphsAtPath(path, morphs) {
1579
+ const key = path.at(-1);
2086
1580
  let parent;
2087
1581
  if (key !== void 0) {
2088
1582
  parent = this.root;
2089
- for (let pathIndex = 0; pathIndex < path2.length - 1; pathIndex++)
2090
- parent = parent[path2[pathIndex]];
1583
+ for (let pathIndex = 0; pathIndex < path.length - 1; pathIndex++)
1584
+ parent = parent[path[pathIndex]];
2091
1585
  }
2092
- this.path = [...path2];
1586
+ this.path = [...path];
2093
1587
  for (const morph of morphs) {
2094
1588
  const morphIsNode = isNode(morph);
2095
1589
  const result = morph(parent === void 0 ? this.root : parent[key], this);
@@ -2459,15 +1953,15 @@ var NodeSelector = {
2459
1953
  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
1954
  };
2461
1955
  var writeSelectAssertionMessage = (from, selector) => `${from} had no references matching ${printable(selector)}.`;
2462
- var typePathToPropString = (path2) => stringifyPath(path2, {
1956
+ var typePathToPropString = (path) => stringifyPath(path, {
2463
1957
  stringifyNonKey: (node2) => node2.expression
2464
1958
  });
2465
1959
  var referenceMatcher = /"(\$ark\.[^"]+)"/g;
2466
1960
  var compileMeta = (metaJson) => JSON.stringify(metaJson).replaceAll(referenceMatcher, "$1");
2467
- var flatRef = (path2, node2) => ({
2468
- path: path2,
1961
+ var flatRef = (path, node2) => ({
1962
+ path,
2469
1963
  node: node2,
2470
- propString: typePathToPropString(path2)
1964
+ propString: typePathToPropString(path)
2471
1965
  });
2472
1966
  var flatRefsAreEqual = (l, r) => l.propString === r.propString && l.node.equals(r.node);
2473
1967
  var appendUniqueFlatRefs = (existing, refs) => appendUnique(existing, refs, {
@@ -2503,12 +1997,12 @@ var Disjoint = class _Disjoint extends Array {
2503
1997
  }
2504
1998
  describeReasons() {
2505
1999
  if (this.length === 1) {
2506
- const { path: path2, l, r } = this[0];
2507
- const pathString = stringifyPath(path2);
2000
+ const { path, l, r } = this[0];
2001
+ const pathString = stringifyPath(path);
2508
2002
  return writeUnsatisfiableExpressionError(`Intersection${pathString && ` at ${pathString}`} of ${describeReasons(l, r)}`);
2509
2003
  }
2510
2004
  return `The following intersections result in unsatisfiable types:
2511
- \u2022 ${this.map(({ path: path2, l, r }) => `${path2}: ${describeReasons(l, r)}`).join("\n\u2022 ")}`;
2005
+ \u2022 ${this.map(({ path, l, r }) => `${path}: ${describeReasons(l, r)}`).join("\n\u2022 ")}`;
2512
2006
  }
2513
2007
  throw() {
2514
2008
  return throwParseError(this.describeReasons());
@@ -3868,10 +3362,10 @@ var BaseRoot = class extends BaseNode {
3868
3362
  });
3869
3363
  });
3870
3364
  }
3871
- get(...path2) {
3872
- if (path2[0] === void 0)
3365
+ get(...path) {
3366
+ if (path[0] === void 0)
3873
3367
  return this;
3874
- return this.$.schema(this.applyStructuralOperation("get", path2));
3368
+ return this.$.schema(this.applyStructuralOperation("get", path));
3875
3369
  }
3876
3370
  extract(r) {
3877
3371
  const rNode = this.$.parseDefinition(r);
@@ -4806,13 +4300,13 @@ var implementation17 = implementNode({
4806
4300
  description: (node2) => node2.distribute((branch) => branch.description, describeBranches),
4807
4301
  expected: (ctx) => {
4808
4302
  const byPath = groupBy(ctx.errors, "propString");
4809
- const pathDescriptions = Object.entries(byPath).map(([path2, errors]) => {
4303
+ const pathDescriptions = Object.entries(byPath).map(([path, errors]) => {
4810
4304
  const branchesAtPath = [];
4811
4305
  for (const errorAtPath of errors)
4812
4306
  appendUnique(branchesAtPath, errorAtPath.expected);
4813
4307
  const expected = describeBranches(branchesAtPath);
4814
4308
  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})`}`;
4309
+ return `${path && `${path} `}must be ${expected}${actual && ` (was ${actual})`}`;
4816
4310
  });
4817
4311
  return describeBranches(pathDescriptions);
4818
4312
  },
@@ -5176,10 +4670,10 @@ var orderCandidates = (candidates, originalBranches) => {
5176
4670
  });
5177
4671
  return viableCandidates;
5178
4672
  };
5179
- var discriminantCaseToNode = (caseDiscriminant, path2, $) => {
4673
+ var discriminantCaseToNode = (caseDiscriminant, path, $) => {
5180
4674
  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];
4675
+ for (let i = path.length - 1; i >= 0; i--) {
4676
+ const key = path[i];
5183
4677
  node2 = $.node("intersection", typeof key === "number" ? {
5184
4678
  proto: "Array",
5185
4679
  // create unknown for preceding elements (could be optimized with safe imports)
@@ -5191,7 +4685,7 @@ var discriminantCaseToNode = (caseDiscriminant, path2, $) => {
5191
4685
  }
5192
4686
  return node2;
5193
4687
  };
5194
- var optionallyChainPropString = (path2) => path2.reduce((acc, k) => acc + compileLiteralPropAccess(k, true), "data");
4688
+ var optionallyChainPropString = (path) => path.reduce((acc, k) => acc + compileLiteralPropAccess(k, true), "data");
5195
4689
  var serializedTypeOfDescriptions = registeredReference(jsTypeOfDescriptions);
5196
4690
  var serializedPrintable = registeredReference(printable);
5197
4691
  var Union = {
@@ -6149,7 +5643,7 @@ var StructureNode = class extends BaseConstraint {
6149
5643
  return throwParseError(writeInvalidKeysMessage(this.expression, invalidKeys));
6150
5644
  }
6151
5645
  }
6152
- get(indexer, ...path2) {
5646
+ get(indexer, ...path) {
6153
5647
  var _a4;
6154
5648
  let value2;
6155
5649
  let required = false;
@@ -6186,7 +5680,7 @@ var StructureNode = class extends BaseConstraint {
6186
5680
  }
6187
5681
  return throwParseError(writeInvalidKeysMessage(this.expression, [key]));
6188
5682
  }
6189
- const result = value2.get(...path2);
5683
+ const result = value2.get(...path);
6190
5684
  return required ? result : result.or($ark.intrinsic.undefined);
6191
5685
  }
6192
5686
  pick(...keys) {
@@ -8912,7 +8406,7 @@ function isIterator(val) {
8912
8406
  function escapeRegex(str) {
8913
8407
  return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
8914
8408
  }
8915
- function promisify2(fn) {
8409
+ function promisify(fn) {
8916
8410
  return function(...args2) {
8917
8411
  return new Promise((resolve2, reject2) => {
8918
8412
  fn(...args2, (err, result) => {
@@ -10248,8 +9742,8 @@ function requireResolve(file) {
10248
9742
  const require2 = (0, import_module3.createRequire)(process.cwd() + "/");
10249
9743
  return require2.resolve(file);
10250
9744
  }
10251
- var statAsync = promisify2(import_fs.stat);
10252
- var readFileAsync = promisify2(import_fs.readFile);
9745
+ var statAsync = promisify(import_fs.stat);
9746
+ var readFileAsync = promisify(import_fs.readFile);
10253
9747
  function exists(filepath) {
10254
9748
  return __awaiter(this, void 0, void 0, function* () {
10255
9749
  try {
@@ -11491,10 +10985,10 @@ var Loader = class {
11491
10985
  yield filepath;
11492
10986
  }
11493
10987
  }
11494
- dirname(path2) {
10988
+ dirname(path) {
11495
10989
  const fs2 = this.options.fs;
11496
10990
  assert(fs2.dirname, "`fs.dirname` is required for relative reference");
11497
- return fs2.dirname(path2);
10991
+ return fs2.dirname(path);
11498
10992
  }
11499
10993
  lookupError(file, roots) {
11500
10994
  const err = new Error("ENOENT");
@@ -13445,6 +12939,7 @@ var ProxyType = type({
13445
12939
  });
13446
12940
  var CaddyContext = type({
13447
12941
  caddy_root: "string",
12942
+ admin_socket: "string",
13448
12943
  proxies: ProxyType.array()
13449
12944
  });
13450
12945
  function validateTemplateContext(ctx) {
@@ -13456,6 +12951,8 @@ function validateTemplateContext(ctx) {
13456
12951
  var caddyTemplate = `{
13457
12952
  debug
13458
12953
  auto_https disable_redirects ignore_loaded_certs
12954
+ skip_install_trust
12955
+ admin unix/{{ admin_socket }}
13459
12956
  }
13460
12957
 
13461
12958
  :7601 {
@@ -13536,27 +13033,37 @@ async function genCaddyfile(ctx) {
13536
13033
  }
13537
13034
 
13538
13035
  // src/caddy/config.ts
13539
- var import_node_fs2 = require("fs");
13540
- var import_promises2 = require("fs/promises");
13036
+ var import_node_fs = require("fs");
13037
+ var import_node_process2 = __toESM(require("process"), 1);
13038
+ var lockfile = __toESM(require("proper-lockfile"), 1);
13541
13039
 
13542
13040
  // src/caddy/constants.ts
13543
13041
  var import_node_os2 = __toESM(require("os"), 1);
13544
- var import_node_path2 = require("path");
13545
- var import_node_process3 = __toESM(require("process"), 1);
13042
+ var import_node_path = require("path");
13043
+ var import_node_process = __toESM(require("process"), 1);
13546
13044
  var import_dotenv_flow = __toESM(require("dotenv-flow"), 1);
13547
13045
  import_dotenv_flow.default.config({
13548
13046
  silent: true
13549
13047
  });
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");
13048
+ function resolvePath(path) {
13049
+ if (path.startsWith("~"))
13050
+ return (0, import_node_path.join)(import_node_os2.default.homedir() || "", path.slice(1));
13051
+ return path;
13052
+ }
13053
+ function defaultTempDir() {
13054
+ const fromEnv = import_node_process.default.env.TEMP || import_node_process.default.env.TMPDIR;
13055
+ if (fromEnv)
13056
+ return resolvePath(fromEnv);
13057
+ if (import_node_process.default.platform === "linux")
13058
+ return (0, import_node_path.join)(import_node_process.default.env.XDG_CACHE_HOME || (0, import_node_path.join)(import_node_os2.default.homedir(), ".cache"), "uhrp");
13059
+ return "/tmp";
13060
+ }
13061
+ var TEMP_DIR = resolvePath(import_node_process.default.env.UHRP_CADDY_PATH || defaultTempDir());
13062
+ var caddyPath = (0, import_node_path.join)(TEMP_DIR, `caddy${import_node_process.default.platform === "win32" ? ".exe" : ""}`);
13063
+ var caddyFilePath = (0, import_node_path.join)(TEMP_DIR, "CADDYFILE");
13064
+ var caddyConfigPath = (0, import_node_path.join)(TEMP_DIR, ".CADDYFILE.config.json");
13065
+ var caddyLockFilePath = (0, import_node_path.join)(TEMP_DIR, "caddylock");
13066
+ var caddyAdminSocketPath = (0, import_node_path.join)(TEMP_DIR, "caddy-admin.sock");
13560
13067
  var supportList = [
13561
13068
  {
13562
13069
  platform: "dragonfly",
@@ -13669,67 +13176,786 @@ var supportList = [
13669
13176
  ];
13670
13177
 
13671
13178
  // src/caddy/config.ts
13672
- function useCaddyConfig() {
13673
- const configContentRef = signal("{}");
13674
- const configJsonRef = computed(() => {
13179
+ function isAlive(pid) {
13180
+ if (pid === void 0)
13181
+ return true;
13182
+ try {
13183
+ import_node_process2.default.kill(pid, 0);
13184
+ return true;
13185
+ } catch {
13186
+ return false;
13187
+ }
13188
+ }
13189
+ function readConfig(path = caddyConfigPath) {
13190
+ if (!(0, import_node_fs.existsSync)(path))
13191
+ return {};
13192
+ let parsed2;
13193
+ try {
13194
+ parsed2 = JSON.parse((0, import_node_fs.readFileSync)(path, "utf-8"));
13195
+ } catch {
13196
+ return {};
13197
+ }
13198
+ const alive = {};
13199
+ for (const [key, entry] of Object.entries(parsed2)) {
13200
+ if (isAlive(entry == null ? void 0 : entry.ownerPid))
13201
+ alive[key] = entry;
13202
+ }
13203
+ return alive;
13204
+ }
13205
+ function writeConfig(proxies, path = caddyConfigPath) {
13206
+ const content = JSON.stringify(proxies, null, 2);
13207
+ const temp = `${path}.${import_node_process2.default.pid}.tmp`;
13208
+ (0, import_node_fs.writeFileSync)(temp, content);
13209
+ (0, import_node_fs.renameSync)(temp, path);
13210
+ }
13211
+ function useCaddyConfig(options = {}) {
13212
+ const lock3 = options.lock ?? createFileLock();
13213
+ const configPath = options.configPath ?? caddyConfigPath;
13214
+ async function mutate(apply) {
13215
+ var _a4;
13216
+ const release = await lock3.acquire();
13675
13217
  try {
13676
- return JSON.parse(configContentRef());
13677
- } catch {
13218
+ const proxies = readConfig(configPath);
13219
+ apply(proxies);
13220
+ writeConfig(proxies, configPath);
13221
+ await ((_a4 = options.renderCaddyfile) == null ? void 0 : _a4.call(options, proxies));
13222
+ return proxies;
13223
+ } finally {
13224
+ release();
13225
+ }
13226
+ }
13227
+ return {
13228
+ configJsonRef: () => (0, import_node_fs.existsSync)(configPath) ? readConfig(configPath) : void 0,
13229
+ async writeCaddyConfig(_proxies, key) {
13230
+ await mutate((proxies) => {
13231
+ for (const p of _proxies)
13232
+ proxies[routeKey(p, key)] = { ...p, base: normalizeBase(p.base), ownerPid: import_node_process2.default.pid };
13233
+ });
13234
+ },
13235
+ async removeProxy(key) {
13236
+ await mutate((current) => {
13237
+ for (const route of Object.keys(current)) {
13238
+ if (route.endsWith(`#${key}`))
13239
+ delete current[route];
13240
+ }
13241
+ });
13242
+ },
13243
+ readProxies: () => readConfig(configPath),
13244
+ async cleanUp() {
13245
+ removeConfigFile(configPath);
13246
+ }
13247
+ };
13248
+ }
13249
+ function removeConfigFile(path = caddyConfigPath) {
13250
+ try {
13251
+ if ((0, import_node_fs.existsSync)(path))
13252
+ (0, import_node_fs.unlinkSync)(path);
13253
+ } catch {
13254
+ }
13255
+ }
13256
+ function normalizeBase(base) {
13257
+ let out = base || "/";
13258
+ if (!out.startsWith("/"))
13259
+ out = `/${out}`;
13260
+ if (out !== "/" && !out.endsWith("/"))
13261
+ out = `${out}/`;
13262
+ return out;
13263
+ }
13264
+ function routeKey(proxy, ownerKey) {
13265
+ return `${proxy.target}${proxy.portSuffix}${normalizeBase(proxy.base)}#${ownerKey}`;
13266
+ }
13267
+ function createFileLock() {
13268
+ return {
13269
+ async acquire() {
13270
+ if (!(0, import_node_fs.existsSync)(caddyConfigPath))
13271
+ (0, import_node_fs.writeFileSync)(caddyConfigPath, "{}");
13272
+ const release = await lockfile.lock(caddyConfigPath, {
13273
+ realpath: false,
13274
+ stale: 1e4,
13275
+ retries: { retries: 20, minTimeout: 10, maxTimeout: 100 }
13276
+ });
13277
+ return () => {
13278
+ void release().catch(() => {
13279
+ });
13280
+ };
13281
+ }
13282
+ };
13283
+ }
13284
+
13285
+ // src/caddy/log.ts
13286
+ function isCaddyReloadCancellation(line) {
13287
+ try {
13288
+ const entry = JSON.parse(line);
13289
+ return entry.logger === "tls" && typeof entry.error === "string" && entry.error.endsWith("context canceled");
13290
+ } catch {
13291
+ return false;
13292
+ }
13293
+ }
13294
+
13295
+ // src/caddy/privileged.ts
13296
+ var import_node_buffer2 = require("buffer");
13297
+ var import_node_events = require("events");
13298
+ var import_node_path4 = require("path");
13299
+ var import_node_process7 = __toESM(require("process"), 1);
13300
+ var import_node_url = require("url");
13301
+
13302
+ // src/privileged/entry.ts
13303
+ var import_node_fs2 = require("fs");
13304
+ var import_node_path2 = require("path");
13305
+ var import_node_process3 = __toESM(require("process"), 1);
13306
+ function resolveHelperEntry(options) {
13307
+ const { moduleDir, nodeBin = import_node_process3.default.execPath, exists: exists2 = import_node_fs2.existsSync } = options;
13308
+ for (const name of ["privileged-helper.js", "privileged-helper.cjs", "privileged-helper.mjs"]) {
13309
+ const candidate = findUp(moduleDir, name, exists2);
13310
+ if (candidate)
13311
+ return { entry: nodeBin, args: [candidate] };
13312
+ }
13313
+ const source = findUp(moduleDir, "privileged-helper.ts", exists2);
13314
+ const tsxCli = findUp(moduleDir, "node_modules/tsx/dist/cli.mjs", exists2);
13315
+ if (source && tsxCli)
13316
+ return { entry: nodeBin, args: [tsxCli, source] };
13317
+ throw new Error(`privileged helper entry not found in ${moduleDir}. Build the package first.`);
13318
+ }
13319
+ function findUp(from, relative, exists2) {
13320
+ let current = from;
13321
+ while (true) {
13322
+ const candidate = (0, import_node_path2.join)(current, relative);
13323
+ if (exists2(candidate))
13324
+ return candidate;
13325
+ const parent = (0, import_node_path2.dirname)(current);
13326
+ if (parent === current)
13678
13327
  return void 0;
13328
+ current = parent;
13329
+ }
13330
+ }
13331
+
13332
+ // src/privileged/session.ts
13333
+ var import_node_buffer = require("buffer");
13334
+ var import_node_fs3 = require("fs");
13335
+ var import_promises = require("fs/promises");
13336
+ var import_node_os4 = require("os");
13337
+ var import_node_path3 = require("path");
13338
+ var lockfile2 = __toESM(require("proper-lockfile"), 1);
13339
+
13340
+ // src/privileged/launch.ts
13341
+ var import_node_child_process2 = require("child_process");
13342
+ var import_node_crypto = require("crypto");
13343
+ var import_node_os3 = require("os");
13344
+ var import_node_process6 = __toESM(require("process"), 1);
13345
+
13346
+ // src/privileged/client.ts
13347
+ var import_node_net = require("net");
13348
+ var import_node_process4 = __toESM(require("process"), 1);
13349
+
13350
+ // src/privileged/protocol.ts
13351
+ function serializeMessage(message) {
13352
+ return `${JSON.stringify(message)}
13353
+ `;
13354
+ }
13355
+ function splitLines(buffer, chunk) {
13356
+ const parts = (buffer + chunk).split("\n");
13357
+ const rest = parts.pop() ?? "";
13358
+ return { lines: parts.filter((line) => line.trim() !== ""), rest };
13359
+ }
13360
+ function isRecord(value2) {
13361
+ return typeof value2 === "object" && value2 !== null;
13362
+ }
13363
+ function decodeMessage(line) {
13364
+ let parsed2;
13365
+ try {
13366
+ parsed2 = JSON.parse(line);
13367
+ } catch (error) {
13368
+ return { ok: false, error: `invalid JSON: ${error.message}` };
13369
+ }
13370
+ if (!isRecord(parsed2))
13371
+ return { ok: false, error: "message must be an object" };
13372
+ if (parsed2.type === "event") {
13373
+ if (typeof parsed2.kind !== "string")
13374
+ return { ok: false, error: "event.kind must be a string" };
13375
+ return { ok: true, message: parsed2 };
13376
+ }
13377
+ if (typeof parsed2.id !== "number")
13378
+ return { ok: false, error: "response.id must be a number" };
13379
+ if (parsed2.ok === true)
13380
+ return { ok: true, message: { id: parsed2.id, ok: true, result: parsed2.result } };
13381
+ if (parsed2.ok === false) {
13382
+ const error = isRecord(parsed2.error) ? parsed2.error : {};
13383
+ return {
13384
+ ok: true,
13385
+ message: {
13386
+ id: parsed2.id,
13387
+ ok: false,
13388
+ error: {
13389
+ message: typeof error.message === "string" ? error.message : "helper request failed",
13390
+ code: typeof error.code === "string" ? error.code : void 0
13391
+ }
13392
+ }
13393
+ };
13394
+ }
13395
+ return { ok: false, error: "response.ok must be a boolean" };
13396
+ }
13397
+
13398
+ // src/privileged/client.ts
13399
+ var FORWARDED_ENV_KEYS = [
13400
+ "HOME",
13401
+ "USER",
13402
+ "LOGNAME",
13403
+ "TMPDIR",
13404
+ "HTTP_PROXY",
13405
+ "HTTPS_PROXY",
13406
+ "http_proxy",
13407
+ "https_proxy",
13408
+ "NO_PROXY",
13409
+ "no_proxy"
13410
+ ];
13411
+ function collectForwardedEnv(source = import_node_process4.default.env) {
13412
+ const result = {};
13413
+ for (const key of FORWARDED_ENV_KEYS) {
13414
+ const value2 = source[key];
13415
+ if (typeof value2 === "string" && value2 !== "")
13416
+ result[key] = value2;
13417
+ }
13418
+ return result;
13419
+ }
13420
+ var HelperConnectionError = class extends Error {
13421
+ constructor(message) {
13422
+ super(message);
13423
+ this.name = "HelperConnectionError";
13424
+ }
13425
+ };
13426
+ function openSocket(socketPath) {
13427
+ return new Promise((resolve2, reject2) => {
13428
+ const socket = (0, import_node_net.connect)(socketPath);
13429
+ function onConnect() {
13430
+ socket.removeListener("error", onError);
13431
+ resolve2(socket);
13679
13432
  }
13680
- });
13681
- function setConfigContent() {
13682
- if (!(0, import_node_fs2.existsSync)(caddyConfigPath)) {
13683
- (0, import_node_fs2.writeFileSync)(caddyConfigPath, "{}");
13433
+ function onError(error) {
13434
+ socket.removeListener("connect", onConnect);
13435
+ reject2(error);
13684
13436
  }
13437
+ socket.once("error", onError);
13438
+ socket.once("connect", onConnect);
13439
+ });
13440
+ }
13441
+ async function connectClient(options) {
13442
+ const {
13443
+ socketPath,
13444
+ token,
13445
+ timeoutMs = 12e4,
13446
+ retryIntervalMs = 100,
13447
+ callTimeoutMs = 3e4
13448
+ } = options;
13449
+ const deadline = Date.now() + timeoutMs;
13450
+ let lastError;
13451
+ while (Date.now() < deadline) {
13685
13452
  try {
13686
- configContentRef((0, import_node_fs2.readFileSync)(caddyConfigPath, "utf-8"));
13687
- } catch {
13688
- configContentRef("");
13453
+ return await handshake(socketPath, token, callTimeoutMs);
13454
+ } catch (error) {
13455
+ lastError = error;
13456
+ const code = lastError.code;
13457
+ if (code === "EACCES" || lastError instanceof HelperConnectionError)
13458
+ throw lastError;
13459
+ await new Promise((resolve2) => setTimeout(resolve2, retryIntervalMs));
13689
13460
  }
13690
13461
  }
13691
- if (!(0, import_node_fs2.existsSync)(caddyConfigPath)) {
13692
- (0, import_node_fs2.writeFileSync)(caddyConfigPath, "{}");
13693
- }
13694
- const watchCaddyConfig = (0, import_node_fs2.watch)(caddyConfigPath, () => {
13695
- setConfigContent();
13462
+ throw new HelperConnectionError(
13463
+ `privileged helper is not reachable at ${socketPath}: ${(lastError == null ? void 0 : lastError.message) ?? "timed out"}`
13464
+ );
13465
+ }
13466
+ function handshake(socketPath, token, callTimeoutMs) {
13467
+ return new Promise((resolve2, reject2) => {
13468
+ void openSocket(socketPath).then((socket) => {
13469
+ let buffer = "";
13470
+ let settled = false;
13471
+ const fail = (error) => {
13472
+ if (settled)
13473
+ return;
13474
+ settled = true;
13475
+ socket.destroy();
13476
+ reject2(error);
13477
+ };
13478
+ const onData = (chunk) => {
13479
+ if (settled)
13480
+ return;
13481
+ const split2 = splitLines(buffer, chunk.toString("utf8"));
13482
+ buffer = split2.rest;
13483
+ const line = split2.lines[0];
13484
+ if (line === void 0)
13485
+ return;
13486
+ let hello;
13487
+ try {
13488
+ hello = JSON.parse(line);
13489
+ } catch (error) {
13490
+ return fail(new HelperConnectionError(`invalid handshake reply: ${error.message}`));
13491
+ }
13492
+ if (hello.type !== "handshake")
13493
+ return fail(new HelperConnectionError("helper did not answer the handshake"));
13494
+ if (!hello.ok)
13495
+ return fail(new HelperConnectionError(hello.reason ?? "helper rejected the handshake"));
13496
+ settled = true;
13497
+ socket.removeListener("data", onData);
13498
+ socket.removeListener("error", onError);
13499
+ const remaining = split2.lines.slice(1);
13500
+ resolve2(createClient(socket, [split2.rest, ...remaining].filter(Boolean).join("\n"), callTimeoutMs));
13501
+ };
13502
+ function onError(error) {
13503
+ fail(error);
13504
+ }
13505
+ socket.on("data", onData);
13506
+ socket.on("error", onError);
13507
+ const greeting = { type: "handshake", token };
13508
+ socket.write(serializeMessage(greeting));
13509
+ }, reject2);
13510
+ });
13511
+ }
13512
+ function createClient(socket, initialBuffer, callTimeoutMs) {
13513
+ let buffer = initialBuffer;
13514
+ let connected = true;
13515
+ let nextId = 1;
13516
+ const pending = /* @__PURE__ */ new Map();
13517
+ const listeners = /* @__PURE__ */ new Set();
13518
+ socket.on("data", (chunk) => {
13519
+ const split2 = splitLines(buffer, chunk.toString("utf8"));
13520
+ buffer = split2.rest;
13521
+ for (const line of split2.lines) {
13522
+ const decoded = decodeMessage(line);
13523
+ if (!decoded.ok)
13524
+ continue;
13525
+ const message = decoded.message;
13526
+ if (!("id" in message)) {
13527
+ for (const listener of listeners)
13528
+ listener(message);
13529
+ continue;
13530
+ }
13531
+ const entry = pending.get(message.id);
13532
+ if (!entry)
13533
+ continue;
13534
+ pending.delete(message.id);
13535
+ clearTimeout(entry.timer);
13536
+ if (message.ok)
13537
+ entry.resolve(message.result);
13538
+ else
13539
+ entry.reject(new Error(message.error.message));
13540
+ }
13696
13541
  });
13697
- function writeCaddyConfig(_proxies) {
13698
- const proxies = configJsonRef() || {};
13699
- _proxies.forEach((p) => {
13700
- let base = p.base || "/";
13701
- if (!base.startsWith("/"))
13702
- base = `/${base}`;
13703
- if (base !== "/" && !base.endsWith("/"))
13704
- base = `${base}/`;
13705
- const index = `${p.target}${p.portSuffix}${base}`;
13706
- proxies[index] = { ...p, base };
13542
+ const disconnect = () => {
13543
+ if (!connected)
13544
+ return;
13545
+ connected = false;
13546
+ for (const [id, entry] of pending) {
13547
+ clearTimeout(entry.timer);
13548
+ pending.delete(id);
13549
+ entry.reject(new HelperConnectionError("privileged helper connection closed"));
13550
+ }
13551
+ };
13552
+ socket.on("close", disconnect);
13553
+ socket.on("error", disconnect);
13554
+ function call(method, params) {
13555
+ if (!connected)
13556
+ return Promise.reject(new HelperConnectionError("privileged helper is not connected"));
13557
+ const id = nextId++;
13558
+ const request = { id, method, params };
13559
+ return new Promise((resolve2, reject2) => {
13560
+ const timer = setTimeout(() => {
13561
+ pending.delete(id);
13562
+ reject2(new HelperConnectionError(`privileged helper did not answer "${method}" in time`));
13563
+ }, callTimeoutMs);
13564
+ pending.set(id, { resolve: resolve2, reject: reject2, timer });
13565
+ socket.write(serializeMessage(request));
13707
13566
  });
13708
- const content = JSON.stringify(proxies, null, 2);
13709
- configContentRef(content);
13710
- return (0, import_node_fs2.writeFileSync)(caddyConfigPath, content);
13711
13567
  }
13712
- async function cleanUp() {
13713
- await (0, import_promises2.unlink)(caddyConfigPath).catch(() => {
13568
+ return {
13569
+ get connected() {
13570
+ return connected;
13571
+ },
13572
+ call,
13573
+ onEvent(listener) {
13574
+ listeners.add(listener);
13575
+ return () => {
13576
+ listeners.delete(listener);
13577
+ };
13578
+ },
13579
+ async close() {
13580
+ disconnect();
13581
+ socket.destroy();
13582
+ }
13583
+ };
13584
+ }
13585
+
13586
+ // src/privileged/windows-elevation.ts
13587
+ var import_node_child_process = require("child_process");
13588
+ var import_node_process5 = __toESM(require("process"), 1);
13589
+ function quotePowerShell(value2) {
13590
+ return `'${value2.replace(/'/g, "''")}'`;
13591
+ }
13592
+ function buildElevationCommand(options) {
13593
+ const argumentList = options.args.map(quotePowerShell).join(",");
13594
+ const parts = [
13595
+ "Start-Process",
13596
+ "-FilePath",
13597
+ quotePowerShell(options.file)
13598
+ ];
13599
+ if (argumentList)
13600
+ parts.push("-ArgumentList", argumentList);
13601
+ if (options.cwd)
13602
+ parts.push("-WorkingDirectory", quotePowerShell(options.cwd));
13603
+ parts.push("-Verb", "RunAs");
13604
+ parts.push("-WindowStyle", "Hidden");
13605
+ return parts.join(" ");
13606
+ }
13607
+ function spawnElevatedOnWindows(options) {
13608
+ return new Promise((resolve2, reject2) => {
13609
+ const script = buildElevationCommand(options);
13610
+ const child = (0, import_node_child_process.spawn)(
13611
+ "powershell.exe",
13612
+ ["-NoProfile", "-NonInteractive", "-Command", script],
13613
+ { stdio: "ignore", windowsHide: true }
13614
+ );
13615
+ child.once("error", reject2);
13616
+ child.once("exit", (code) => {
13617
+ if (code === 0)
13618
+ return resolve2(child);
13619
+ reject2(new Error(
13620
+ `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.`
13621
+ ));
13714
13622
  });
13715
- configContentRef("{}");
13716
- watchCaddyConfig.close();
13623
+ });
13624
+ }
13625
+
13626
+ // src/privileged/launch.ts
13627
+ function createHelperToken() {
13628
+ return (0, import_node_crypto.randomBytes)(24).toString("hex");
13629
+ }
13630
+ function describePasswordReason(target, https) {
13631
+ const port = https ? "443" : "80";
13632
+ return [
13633
+ `reverse proxy needs administrator permission for ${target}`,
13634
+ ` \xB7 bind port ${port}${https ? ` for https://${target}` : ""}`,
13635
+ ` \xB7 add ${target} to the hosts file`,
13636
+ "",
13637
+ "This is the only prompt; the rest of the dev server keeps running as you.",
13638
+ "Press Ctrl+C at the prompt to skip the proxy and keep the dev server."
13639
+ ];
13640
+ }
13641
+ async function authenticateSudo(sudoCommand = "sudo", options = {}) {
13642
+ if ((0, import_node_os3.platform)() === "win32")
13643
+ return { ok: true };
13644
+ if ((0, import_node_child_process2.spawnSync)(sudoCommand, ["-n", "true"], { stdio: "ignore" }).status === 0)
13645
+ return { ok: true };
13646
+ if (options.target && !options.quiet) {
13647
+ for (const line of describePasswordReason(options.target, options.https ?? false))
13648
+ import_node_process6.default.stderr.write(`${line}
13649
+ `);
13650
+ import_node_process6.default.stderr.write("\n");
13717
13651
  }
13718
- return {
13719
- configJsonRef,
13720
- writeCaddyConfig,
13721
- cleanUp
13652
+ let interrupted = false;
13653
+ const onSigint = () => {
13654
+ interrupted = true;
13655
+ };
13656
+ import_node_process6.default.on("SIGINT", onSigint);
13657
+ try {
13658
+ const { status, signal } = await runPrompt(sudoCommand);
13659
+ if (status === 0)
13660
+ return { ok: true };
13661
+ const cancelled = interrupted || signal === "SIGINT";
13662
+ return {
13663
+ ok: false,
13664
+ denied: true,
13665
+ message: cancelled ? "administrator permission was cancelled" : "administrator permission is required to edit the hosts file and bind ports 80/443"
13666
+ };
13667
+ } finally {
13668
+ import_node_process6.default.off("SIGINT", onSigint);
13669
+ }
13670
+ }
13671
+ function runPrompt(sudoCommand) {
13672
+ return new Promise((resolve2) => {
13673
+ const restore = takeBackTerminal();
13674
+ const child = (0, import_node_child_process2.spawn)(sudoCommand, ["-v"], { stdio: "inherit" });
13675
+ const finish = (result) => {
13676
+ restore();
13677
+ resolve2(result);
13678
+ };
13679
+ child.on("error", () => finish({ status: 1, signal: null }));
13680
+ child.on("exit", (status, signal) => finish({ status, signal }));
13681
+ });
13682
+ }
13683
+ function takeBackTerminal() {
13684
+ const stdin = import_node_process6.default.stdin;
13685
+ if (!stdin.isTTY || typeof stdin.setRawMode !== "function")
13686
+ return () => {
13687
+ };
13688
+ const wasRaw = stdin.isRaw === true;
13689
+ stdin.pause();
13690
+ try {
13691
+ stdin.setRawMode(false);
13692
+ } catch {
13693
+ stdin.resume();
13694
+ return () => {
13695
+ };
13696
+ }
13697
+ return () => {
13698
+ if (wasRaw) {
13699
+ try {
13700
+ stdin.setRawMode(true);
13701
+ } catch {
13702
+ }
13703
+ }
13704
+ stdin.resume();
13722
13705
  };
13723
13706
  }
13707
+ var PrivilegeDeniedError = class extends Error {
13708
+ constructor(message) {
13709
+ super(message);
13710
+ this.name = "PrivilegeDeniedError";
13711
+ }
13712
+ };
13713
+ async function startPrivilegedHelper(options) {
13714
+ var _a4, _b3;
13715
+ const {
13716
+ socketPath,
13717
+ token,
13718
+ helperEntry,
13719
+ helperArgs = [],
13720
+ sudoCommand = "sudo",
13721
+ skipAuth = false,
13722
+ direct = false,
13723
+ env: env2 = import_node_process6.default.env,
13724
+ log,
13725
+ connectTimeoutMs = 12e4
13726
+ } = options;
13727
+ if (!skipAuth && !direct) {
13728
+ const auth = await authenticateSudo(sudoCommand, options.reason);
13729
+ if (!auth.ok) {
13730
+ const message = auth.message ?? "administrator permission is required";
13731
+ throw auth.denied ? new PrivilegeDeniedError(message) : new Error(message);
13732
+ }
13733
+ }
13734
+ const forwarded = collectForwardedEnv(env2);
13735
+ const forwardedArgs = Object.entries(forwarded).map(([key, value2]) => `${key}=${value2}`);
13736
+ const childArgv = [
13737
+ ...helperArgs,
13738
+ "--socket",
13739
+ socketPath,
13740
+ "--token",
13741
+ token,
13742
+ ...typeof import_node_process6.default.getuid === "function" ? ["--owner-uid", String(import_node_process6.default.getuid())] : [],
13743
+ ...typeof import_node_process6.default.getgid === "function" ? ["--owner-gid", String(import_node_process6.default.getgid())] : [],
13744
+ ...options.caddyStoragePath ? ["--caddy-storage", options.caddyStoragePath] : [],
13745
+ "--caddy",
13746
+ options.caddyBin,
13747
+ "--caddy-config",
13748
+ options.caddyConfigPath,
13749
+ ...options.caddyAdminSocket ? ["--caddy-admin", options.caddyAdminSocket] : []
13750
+ ];
13751
+ let child;
13752
+ if (!direct && (0, import_node_os3.platform)() === "win32") {
13753
+ await spawnElevatedOnWindows({ file: helperEntry, args: childArgv, cwd: import_node_process6.default.cwd() });
13754
+ } else {
13755
+ const command = direct ? helperEntry : sudoCommand;
13756
+ const spawnArgs = direct ? childArgv : ["-n", "env", ...forwardedArgs, helperEntry, ...childArgv];
13757
+ child = (0, import_node_child_process2.spawn)(command, spawnArgs, {
13758
+ stdio: ["ignore", "pipe", "pipe"]
13759
+ });
13760
+ (_a4 = child.stdout) == null ? void 0 : _a4.on("data", (data) => log == null ? void 0 : log(data.toString().trimEnd()));
13761
+ (_b3 = child.stderr) == null ? void 0 : _b3.on("data", (data) => log == null ? void 0 : log(data.toString().trimEnd()));
13762
+ const exited = new Promise((resolve2) => child.once("exit", (code) => resolve2(code)));
13763
+ const earlyExit = await Promise.race([
13764
+ exited,
13765
+ new Promise((resolve2) => setTimeout(() => resolve2(void 0), 500))
13766
+ ]);
13767
+ if (earlyExit !== void 0 && earlyExit !== 0) {
13768
+ throw new Error(
13769
+ `privileged helper exited with code ${earlyExit}. Administrator permission was refused, or sudo is not available.`
13770
+ );
13771
+ }
13772
+ }
13773
+ try {
13774
+ const client = await connectClient({ socketPath, token, timeoutMs: connectTimeoutMs });
13775
+ return {
13776
+ client,
13777
+ async close() {
13778
+ await client.close().catch(() => {
13779
+ });
13780
+ child == null ? void 0 : child.unref();
13781
+ }
13782
+ };
13783
+ } catch (error) {
13784
+ try {
13785
+ child == null ? void 0 : child.kill();
13786
+ } catch {
13787
+ }
13788
+ throw error;
13789
+ }
13790
+ }
13791
+ async function connectExistingHelper(socketPath, token, timeoutMs = 1500) {
13792
+ try {
13793
+ return await connectClient({ socketPath, token, timeoutMs });
13794
+ } catch {
13795
+ return void 0;
13796
+ }
13797
+ }
13724
13798
 
13725
- // src/caddy/log.ts
13726
- function isCaddyReloadCancellation(line) {
13799
+ // src/privileged/session.ts
13800
+ function tokenPath(runtimeDir) {
13801
+ return (0, import_node_path3.join)(runtimeDir, "helper.token");
13802
+ }
13803
+ function sessionSocketPath(runtimeDir) {
13804
+ if ((0, import_node_os4.platform)() === "win32")
13805
+ return `\\\\.\\pipe\\uhrp-${import_node_buffer.Buffer.from(runtimeDir).toString("hex").slice(0, 40)}`;
13806
+ return (0, import_node_path3.join)(runtimeDir, "helper.sock");
13807
+ }
13808
+ async function openHelperSession(scope2) {
13809
+ const socketPath = sessionSocketPath(scope2.runtimeDir);
13810
+ const release = await acquireStartLock(scope2.runtimeDir);
13727
13811
  try {
13728
- const entry = JSON.parse(line);
13729
- return entry.logger === "tls" && typeof entry.error === "string" && entry.error.endsWith("context canceled");
13812
+ const reused = await tryReuse(socketPath, scope2);
13813
+ if (reused)
13814
+ return reused;
13815
+ return await startNew(socketPath, scope2);
13816
+ } finally {
13817
+ release();
13818
+ }
13819
+ }
13820
+ async function tryReuse(socketPath, scope2) {
13821
+ if (!(0, import_node_fs3.existsSync)(socketPath) && (0, import_node_os4.platform)() !== "win32")
13822
+ return void 0;
13823
+ const token = await readToken(scope2.runtimeDir);
13824
+ if (!token)
13825
+ return void 0;
13826
+ const reused = await connectExistingHelper(socketPath, token);
13827
+ if (!reused)
13828
+ return void 0;
13829
+ return {
13830
+ client: reused,
13831
+ reused: true,
13832
+ close: async () => {
13833
+ await reused.close();
13834
+ }
13835
+ };
13836
+ }
13837
+ async function startNew(socketPath, scope2) {
13838
+ const token = createHelperToken();
13839
+ const started = await startPrivilegedHelper({
13840
+ socketPath,
13841
+ token,
13842
+ helperEntry: scope2.helperEntry,
13843
+ helperArgs: scope2.helperArgs,
13844
+ sudoCommand: scope2.sudoCommand,
13845
+ skipAuth: scope2.skipAuth,
13846
+ direct: scope2.direct,
13847
+ env: scope2.env,
13848
+ caddyStoragePath: scope2.caddyStoragePath,
13849
+ caddyBin: scope2.caddyBin,
13850
+ caddyConfigPath: scope2.caddyConfigPath,
13851
+ caddyAdminSocket: scope2.caddyAdminSocket,
13852
+ reason: scope2.reason,
13853
+ log: scope2.log
13854
+ });
13855
+ await writeToken(scope2.runtimeDir, token);
13856
+ return {
13857
+ client: started.client,
13858
+ reused: false,
13859
+ close: async () => {
13860
+ await started.close();
13861
+ }
13862
+ };
13863
+ }
13864
+ async function acquireStartLock(runtimeDir) {
13865
+ const lockPath = (0, import_node_path3.join)(runtimeDir, "helper.start.lock");
13866
+ try {
13867
+ await (0, import_promises.writeFile)(lockPath, "", { flag: "a" });
13730
13868
  } catch {
13731
- return false;
13732
13869
  }
13870
+ const release = await lockfile2.lock(lockPath, {
13871
+ realpath: false,
13872
+ stale: 3e4,
13873
+ retries: { retries: 100, minTimeout: 50, maxTimeout: 200 }
13874
+ });
13875
+ return () => {
13876
+ void release().catch(() => {
13877
+ });
13878
+ };
13879
+ }
13880
+ async function readToken(runtimeDir) {
13881
+ try {
13882
+ const content = await (0, import_promises.readFile)(tokenPath(runtimeDir), "utf8");
13883
+ const token = content.trim();
13884
+ return token === "" ? void 0 : token;
13885
+ } catch {
13886
+ return void 0;
13887
+ }
13888
+ }
13889
+ async function writeToken(runtimeDir, token) {
13890
+ try {
13891
+ await (0, import_promises.writeFile)(tokenPath(runtimeDir), token, { mode: 384 });
13892
+ } catch {
13893
+ }
13894
+ }
13895
+
13896
+ // src/caddy/privileged.ts
13897
+ var import_meta = {};
13898
+ function resolvePrivilegedEnv() {
13899
+ const moduleDir = typeof __dirname === "string" ? __dirname : (0, import_node_path4.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
13900
+ const resolved = resolveHelperEntry({ moduleDir });
13901
+ return { helperEntry: resolved.entry, helperArgs: resolved.args };
13902
+ }
13903
+ var HelperCaddyProcess = class extends import_node_events.EventEmitter {
13904
+ constructor(client) {
13905
+ super();
13906
+ this.client = client;
13907
+ this.stdout = new import_node_events.EventEmitter();
13908
+ this.stderr = new import_node_events.EventEmitter();
13909
+ this.finished = false;
13910
+ this.unsubscribe = client.onEvent((event) => this.handleEvent(event));
13911
+ }
13912
+ handleEvent(event) {
13913
+ if (event.type !== "event")
13914
+ return;
13915
+ if (event.kind === "caddy.stdout") {
13916
+ this.stdout.emit("data", import_node_buffer2.Buffer.from(event.data));
13917
+ return;
13918
+ }
13919
+ if (event.kind === "caddy.stderr") {
13920
+ this.stderr.emit("data", import_node_buffer2.Buffer.from(event.data));
13921
+ return;
13922
+ }
13923
+ if (event.kind === "caddy.exit") {
13924
+ this.finished = true;
13925
+ this.emit("exit", event.code, event.signal);
13926
+ }
13927
+ }
13928
+ /** Asks the helper to stop Caddy; the helper also stops it on disconnect. */
13929
+ kill() {
13930
+ this.unsubscribe();
13931
+ if (this.finished)
13932
+ return;
13933
+ this.finished = true;
13934
+ void this.client.call("caddy.stop").catch(() => {
13935
+ });
13936
+ }
13937
+ };
13938
+ function caddyStoragePath() {
13939
+ return import_node_process7.default.platform === "win32" ? (0, import_node_path4.join)(import_node_process7.default.env.AppData ?? "", "Caddy") : (0, import_node_path4.join)(import_node_process7.default.env.HOME ?? "", "Library/Application Support/Caddy");
13940
+ }
13941
+ function openPrivilegedSession(runtimeDir, options) {
13942
+ const env2 = resolvePrivilegedEnv();
13943
+ return openHelperSession({
13944
+ runtimeDir,
13945
+ helperEntry: env2.helperEntry,
13946
+ helperArgs: env2.helperArgs,
13947
+ direct: options.direct,
13948
+ // Caddy keeps its PKI under the user's home; the helper runs it as root, so
13949
+ // it must know which tree to hand back afterwards.
13950
+ caddyStoragePath: caddyStoragePath(),
13951
+ // The binary and Caddyfile are fixed here: the privileged helper must never
13952
+ // execute a path supplied over the socket.
13953
+ caddyBin: options.caddyBin,
13954
+ caddyConfigPath: options.caddyConfigPath,
13955
+ caddyAdminSocket: options.caddyAdminSocket,
13956
+ reason: options.reason,
13957
+ log: options.log
13958
+ });
13733
13959
  }
13734
13960
 
13735
13961
  // src/caddy/tls-health.ts
@@ -13814,40 +14040,8 @@ function formatTlsHealthFailure(hostname, result) {
13814
14040
  }
13815
14041
 
13816
14042
  // src/caddy/utils.ts
13817
- var import_node_child_process3 = require("child_process");
13818
- var import_node_net = require("net");
13819
14043
  var import_ora = __toESM(require("ora"), 1);
13820
14044
  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
14045
  function getNumber(number2) {
13852
14046
  if (number2 <= 0)
13853
14047
  return "0%";
@@ -13886,26 +14080,26 @@ async function download() {
13886
14080
  if (await testCaddy())
13887
14081
  return caddyPath;
13888
14082
  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);
14083
+ if (!(0, import_node_fs4.existsSync)(TEMP_DIR)) {
14084
+ (0, import_node_fs4.mkdirSync)(TEMP_DIR, { recursive: true });
14085
+ (0, import_node_fs4.chmodSync)(TEMP_DIR, 448);
13892
14086
  }
13893
- const file = (0, import_node_fs3.createWriteStream)(caddyPath);
13894
- let _platform = (0, import_node_os3.platform)().toString();
14087
+ const file = (0, import_node_fs4.createWriteStream)(caddyPath);
14088
+ let _platform = (0, import_node_os5.platform)().toString();
13895
14089
  _platform === "win32" && (_platform = "windows");
13896
- let _arch = import_node_process4.default.arch.toString();
14090
+ let _arch = import_node_process8.default.arch.toString();
13897
14091
  _arch === "x64" && (_arch = "amd64");
13898
14092
  const support = supportList.find((item) => item.platform === _platform && item.arch === _arch);
13899
14093
  if (!support)
13900
14094
  return reject2(new Error("not support"));
13901
14095
  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;
14096
+ (0, import_node_fs4.existsSync)(caddyPath) && (0, import_node_fs4.unlinkSync)(caddyPath);
14097
+ const httpProxy = import_node_process8.default.env.HTTP_PROXY || import_node_process8.default.env.http_proxy;
14098
+ const httpsProxy = import_node_process8.default.env.HTTPS_PROXY || import_node_process8.default.env.https_proxy;
13905
14099
  const httpAgent = httpProxy ? new import_http_proxy_agent.HttpProxyAgent(httpProxy) : void 0;
13906
14100
  const httpsAgent = httpsProxy ? new import_https_proxy_agent.HttpsProxyAgent(httpsProxy) : void 0;
13907
14101
  const chmodCaddyOnce = once(() => {
13908
- (0, import_node_fs3.chmodSync)(caddyPath, 511);
14102
+ (0, import_node_fs4.chmodSync)(caddyPath, 493);
13909
14103
  });
13910
14104
  import_got_cjs.got.stream(dowmloadLink, {
13911
14105
  agent: {
@@ -13917,9 +14111,9 @@ async function download() {
13917
14111
  chmodCaddyOnce();
13918
14112
  }).pipe(file).on("finish", () => {
13919
14113
  logProgressOver();
13920
- if (import_node_process4.default.platform === "win32")
14114
+ if (import_node_process8.default.platform === "win32")
13921
14115
  return resolve2(caddyPath);
13922
- (0, import_node_fs3.chmodSync)(caddyPath, 511);
14116
+ (0, import_node_fs4.chmodSync)(caddyPath, 493);
13923
14117
  resolve2(caddyPath);
13924
14118
  }).on("error", (err) => {
13925
14119
  reject2(err);
@@ -13927,26 +14121,41 @@ async function download() {
13927
14121
  });
13928
14122
  }
13929
14123
  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", () => {
14124
+ return new Promise((resolve2) => {
14125
+ if (!(0, import_node_fs4.existsSync)(caddyPath))
13936
14126
  return resolve2(false);
14127
+ try {
14128
+ (0, import_node_fs4.chmodSync)(caddyPath, 493);
14129
+ } catch {
14130
+ }
14131
+ (0, import_node_child_process3.execFile)(caddyPath, [], { timeout: 1e4 }, (error, stdout) => {
14132
+ if (error && !stdout)
14133
+ return resolve2(false);
14134
+ resolve2(stdout.length > 0);
13937
14135
  });
13938
- child.on("error", (err) => {
13939
- return reject2(err);
13940
- });
13941
- child.stdout.on("data", (_data) => {
13942
- return resolve2(true);
13943
- });
13944
14136
  });
13945
14137
  }
14138
+ function caddyRootPath() {
14139
+ return (0, import_node_path5.join)(
14140
+ import_node_process8.default.platform === "win32" ? `${import_node_process8.default.env.AppData}/Caddy` : `${import_node_process8.default.env.HOME}/Library/Application Support/Caddy`,
14141
+ "./pki/authorities/local"
14142
+ );
14143
+ }
14144
+ async function renderCaddyfile(proxies) {
14145
+ const ctx = validateTemplateContext({
14146
+ caddy_root: caddyRootPath(),
14147
+ admin_socket: caddyAdminSocketPath,
14148
+ proxies: Object.values(proxies)
14149
+ });
14150
+ const content = await genCaddyfile(ctx);
14151
+ const temp = `${caddyFilePath}.${import_node_process8.default.pid}.tmp`;
14152
+ await (0, import_promises2.writeFile)(temp, content);
14153
+ await (0, import_promises2.rename)(temp, caddyFilePath);
14154
+ }
13946
14155
  var caddyConfig;
13947
14156
  function getCaddyConfig() {
13948
14157
  if (!caddyConfig) {
13949
- caddyConfig = useCaddyConfig();
14158
+ caddyConfig = useCaddyConfig({ renderCaddyfile });
13950
14159
  }
13951
14160
  return caddyConfig;
13952
14161
  }
@@ -13961,80 +14170,92 @@ function splitHostPort(addr) {
13961
14170
  }
13962
14171
  return { host: addr.slice(0, lastColon), port: addr.slice(lastColon + 1) };
13963
14172
  }
14173
+ var defaultDependencies = {
14174
+ openSession: (runtimeDir, reason) => openPrivilegedSession(runtimeDir, {
14175
+ log: (message) => consola.debug(message),
14176
+ // Both paths are fixed here, before any socket traffic: the privileged
14177
+ // helper must never execute something named in a request.
14178
+ caddyBin: caddyPath,
14179
+ caddyConfigPath: caddyFilePath,
14180
+ caddyAdminSocket: caddyAdminSocketPath,
14181
+ reason
14182
+ }),
14183
+ config: () => getCaddyConfig()
14184
+ };
13964
14185
  var CaddyInstant = class {
13965
- constructor() {
14186
+ constructor(deps = {}) {
13966
14187
  this.inited = false;
13967
14188
  this.stoped = false;
13968
- /** has locked when start */
13969
- this.locked = false;
13970
14189
  this._stopEffects = [];
13971
- testCaddy().then(async () => {
13972
- this.inited = true;
13973
- });
13974
- this.locked = this.checkLock();
14190
+ /** Identifies this instance's routes in the shared config. */
14191
+ this.proxyKey = `${import_node_process8.default.pid}-${Math.random().toString(36).slice(2, 8)}`;
14192
+ this.deps = { ...defaultDependencies, ...deps };
13975
14193
  }
13976
- checkLock() {
13977
- if (!(0, import_node_fs3.existsSync)(caddyLockFilePath))
13978
- (0, import_node_fs3.writeFileSync)(caddyLockFilePath, "");
13979
- return lockfile.checkSync(caddyLockFilePath);
14194
+ /**
14195
+ * Connects to the privileged helper, starting it once if needed. It is
14196
+ * reused across instances so a second dev server does not ask for a
14197
+ * password again.
14198
+ */
14199
+ async session(reason) {
14200
+ if (this._session && !this._session.client.connected)
14201
+ this._session = void 0;
14202
+ if (!this._session)
14203
+ this._session = await this.deps.openSession(TEMP_DIR, reason);
14204
+ return this._session;
13980
14205
  }
13981
14206
  async getCaddyfile() {
13982
- if (!(0, import_node_fs3.existsSync)(caddyFilePath)) {
14207
+ if (!(0, import_node_fs4.existsSync)(caddyFilePath)) {
13983
14208
  this.caddyfile = "";
13984
14209
  return "";
13985
14210
  }
13986
- this.caddyfile = await (0, import_promises3.readFile)(caddyFilePath, "utf-8");
14211
+ this.caddyfile = await (0, import_promises2.readFile)(caddyFilePath, "utf-8");
13987
14212
  return this.caddyfile;
13988
14213
  }
13989
14214
  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`,
13992
- "./pki/authorities/local"
13993
- );
14215
+ return caddyRootPath();
13994
14216
  }
13995
14217
  async writeCaddyfile() {
13996
- return await (0, import_promises3.writeFile)(caddyFilePath, this.caddyfile || "");
14218
+ return await (0, import_promises2.writeFile)(caddyFilePath, this.caddyfile || "");
13997
14219
  }
13998
14220
  async deleteCaddyfile() {
13999
- return await (0, import_promises3.unlink)(caddyFilePath);
14221
+ return await (0, import_promises2.unlink)(caddyFilePath);
14000
14222
  }
14001
14223
  async init() {
14002
14224
  await download();
14003
14225
  this.inited = true;
14004
14226
  }
14227
+ /**
14228
+ * Hands the Caddy storage directory back to the developer. Local CA data
14229
+ * created by an earlier root-owned run must stay readable for `tls internal`
14230
+ * to keep serving the same certificate the browser already trusts.
14231
+ */
14232
+ /**
14233
+ * Installs Caddy's local root CA so the browser stops warning about
14234
+ * `tls internal` certificates. Generating the CA and trusting it are separate
14235
+ * steps: a new CA appears whenever the previous one expires or the storage is
14236
+ * replaced, so this runs on every start instead of once.
14237
+ *
14238
+ * The helper owns both the binary path and the command, so nothing here can
14239
+ * be turned into an arbitrary root execution.
14240
+ */
14241
+ async trustLocalCa(session) {
14242
+ try {
14243
+ const result = await session.client.call("ca.trust");
14244
+ if (result.trusted)
14245
+ consola.debug(`Caddy local CA is trusted
14246
+ ${result.output}`);
14247
+ } catch (error) {
14248
+ consola.warn(
14249
+ `could not install the Caddy root certificate automatically: ${error.message}
14250
+ Run \`${caddyPath} trust\` manually if the browser warns about the certificate.`
14251
+ );
14252
+ }
14253
+ }
14005
14254
  async ensureTlsReady(targetHost) {
14006
14255
  const health = await waitForLocalTls(targetHost);
14007
14256
  if (!health.healthy)
14008
14257
  throw new Error(formatTlsHealthFailure(targetHost, health));
14009
14258
  }
14010
- async updateCaddyfile() {
14011
- const { configJsonRef } = getCaddyConfig();
14012
- const proxies = Object.values(configJsonRef() || {});
14013
- const ctx = validateTemplateContext({
14014
- caddy_root: this.caddyRoot,
14015
- proxies
14016
- });
14017
- this.caddyfile = await genCaddyfile(ctx);
14018
- await this.writeCaddyfile();
14019
- }
14020
- async stopCaddy() {
14021
- var _a4;
14022
- try {
14023
- await import_got_cjs.got.post("http://127.0.0.1:2019/stop", {
14024
- headers: {
14025
- Origin: "http://localhost:2019"
14026
- },
14027
- retry: {
14028
- limit: 0
14029
- },
14030
- timeout: {
14031
- request: 2e3
14032
- }
14033
- });
14034
- } catch {
14035
- }
14036
- (_a4 = this._caddyChild) == null ? void 0 : _a4.kill();
14037
- }
14038
14259
  /**
14039
14260
  * @param source like `127.0.0.1:8080`
14040
14261
  * @param target like `test.abc.com`. And if you provide a port ,it will be ignore.
@@ -14055,10 +14276,10 @@ var CaddyInstant = class {
14055
14276
  await this.init();
14056
14277
  const sourceHost = splitHostPort(source).host;
14057
14278
  const targetHost = splitHostPort(target).host;
14058
- if (!await addHost(sourceHost, targetHost))
14059
- throw new Error("update host failed");
14279
+ const session = await this.session({ target: targetHost, https });
14280
+ await session.client.call("hosts.add", { ip: sourceHost, host: targetHost });
14060
14281
  consola.success("update host success\n");
14061
- const normalizeBase = (b) => {
14282
+ const normalizeBase2 = (b) => {
14062
14283
  let out = b || "/";
14063
14284
  if (!out.startsWith("/"))
14064
14285
  out = `/${out}`;
@@ -14066,7 +14287,7 @@ var CaddyInstant = class {
14066
14287
  out = `${out}/`;
14067
14288
  return out;
14068
14289
  };
14069
- const baseNormalized = normalizeBase(base);
14290
+ const baseNormalized = normalizeBase2(base);
14070
14291
  const proxies = [
14071
14292
  {
14072
14293
  target: targetHost,
@@ -14077,176 +14298,138 @@ var CaddyInstant = class {
14077
14298
  healthCheck
14078
14299
  }
14079
14300
  ];
14080
- const { writeCaddyConfig } = getCaddyConfig();
14081
- writeCaddyConfig(proxies);
14082
- await this.updateCaddyfile();
14083
- let skipInitialCaddyfileEffect = true;
14084
- this._stopEffects.push(
14085
- effect(() => {
14086
- getCaddyConfig().configJsonRef();
14087
- if (skipInitialCaddyfileEffect) {
14088
- skipInitialCaddyfileEffect = false;
14089
- return;
14090
- }
14091
- void this.updateCaddyfile();
14092
- })
14093
- );
14094
- if (!(0, import_node_fs3.existsSync)(caddyLockFilePath))
14095
- (0, import_node_fs3.writeFileSync)(caddyLockFilePath, "");
14096
- 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);
14101
- }
14301
+ const { writeCaddyConfig } = this.deps.config();
14302
+ await writeCaddyConfig(proxies, this.proxyKey);
14303
+ await session.client.call("port.free", { port: 443 });
14304
+ if (import_node_process8.default.platform === "win32" || !https)
14305
+ await session.client.call("port.free", { port: 80 });
14102
14306
  return new Promise((resolve2, reject2) => {
14103
- var _a4, _b3;
14104
14307
  let startupCheckStarted = false;
14105
14308
  const resolveWhenReady = async () => {
14106
14309
  if (startupCheckStarted)
14107
14310
  return;
14108
14311
  startupCheckStarted = true;
14109
14312
  try {
14110
- if (https)
14313
+ if (https) {
14314
+ await this.trustLocalCa(session);
14111
14315
  await this.ensureTlsReady(targetHost);
14316
+ }
14112
14317
  resolve2();
14113
14318
  } catch (error) {
14114
- if (!this.locked)
14115
- await this.baseCleanup(restore);
14319
+ await this.baseCleanup(restore);
14116
14320
  reject2(error);
14117
14321
  }
14118
14322
  };
14119
14323
  const setupCleanup = () => {
14120
- import_node_process4.default.on("SIGINT", async () => {
14324
+ import_node_process8.default.on("SIGINT", async () => {
14121
14325
  if (this.stoped)
14122
14326
  return;
14123
- import_node_process4.default.stdin.resume();
14327
+ import_node_process8.default.stdin.resume();
14124
14328
  try {
14125
14329
  await this.baseCleanup(restore);
14126
14330
  } finally {
14127
14331
  this.stoped = true;
14128
- import_node_process4.default.nextTick(() => {
14129
- import_node_process4.default.exit();
14332
+ import_node_process8.default.nextTick(() => {
14333
+ import_node_process8.default.exit();
14130
14334
  });
14131
14335
  }
14132
14336
  });
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
- });
14337
+ const originalExit = import_node_process8.default.exit.bind(import_node_process8.default);
14338
+ import_node_process8.default.exit = async (code) => {
14155
14339
  if (this.stoped)
14156
14340
  return originalExit(code);
14157
- import_node_process4.default.stdin.resume();
14341
+ import_node_process8.default.stdin.resume();
14158
14342
  try {
14159
14343
  await this.baseCleanup();
14160
14344
  } finally {
14161
14345
  this.stoped = true;
14162
- import_node_process4.default.nextTick(() => {
14346
+ import_node_process8.default.nextTick(() => {
14163
14347
  originalExit(code);
14164
14348
  });
14165
14349
  }
14166
14350
  };
14167
14351
  };
14168
- 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
- 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}
14352
+ setupCleanup();
14353
+ void (async () => {
14354
+ try {
14355
+ const child = new HelperCaddyProcess(session.client);
14356
+ this._caddyChild = child;
14357
+ const started = await session.client.call("caddy.start");
14358
+ child.on("exit", (code) => {
14359
+ if (code !== null && code !== 0)
14360
+ reject2(new Error(`Caddy exited with code ${code}`));
14361
+ });
14362
+ if ((started == null ? void 0 : started.started) === false) {
14363
+ consola.info("Caddy is already running; added this route to it.");
14364
+ void resolveWhenReady();
14365
+ return;
14366
+ }
14367
+ child.stderr.on("data", async (data) => {
14368
+ const lines = data.toString().split("\n").map((line) => line.trim());
14369
+ for (const line of lines) {
14370
+ showCaddyLog && line && console.info(line);
14371
+ if (isCaddyReloadCancellation(line)) {
14372
+ consola.info("Caddy restarted before TLS issuance completed; retrying.\n");
14373
+ continue;
14374
+ }
14375
+ try {
14376
+ if (line.includes("Error:") || line && JSON.parse(line).level === "error") {
14377
+ if (line.includes("parsing caddyfile tokens")) {
14378
+ consola.error("Caddyfile syntax error, please contact the author:\n", `${this.caddyfile}
14186
14379
 
14187
14380
  ${line}
14188
14381
  `);
14189
- await this.baseCleanup();
14190
- import_node_process4.default.exit();
14191
- } else {
14192
- consola.error(`${line}
14382
+ await this.baseCleanup();
14383
+ import_node_process8.default.exit();
14384
+ } else {
14385
+ consola.error(`${line}
14193
14386
  `);
14194
- return reject2(line);
14387
+ return reject2(line);
14388
+ }
14195
14389
  }
14390
+ } catch {
14196
14391
  }
14197
- } catch {
14392
+ if (line.includes("config file changed"))
14393
+ consola.success("Detect added a new reverse proxy config, restarted.\n");
14394
+ if (line.includes("caddy proxying") || line.includes("serving initial"))
14395
+ void resolveWhenReady();
14198
14396
  }
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"))
14202
- void resolveWhenReady();
14203
- }
14204
- });
14205
- (_b3 = this._caddyChild.stdout) == null ? void 0 : _b3.on("data", (_data) => {
14206
- consola.info(_data.toString());
14207
- void resolveWhenReady();
14208
- });
14209
- setupCleanup();
14210
- } else {
14211
- consola.info("Caddy is running in another process.");
14212
- void (async () => {
14213
- try {
14214
- if (https)
14215
- await this.ensureTlsReady(targetHost);
14216
- setupCleanup();
14217
- resolve2();
14218
- } catch (error) {
14219
- reject2(error);
14220
- }
14221
- })();
14222
- }
14397
+ });
14398
+ child.stdout.on("data", (data) => {
14399
+ consola.info(data.toString());
14400
+ void resolveWhenReady();
14401
+ });
14402
+ } catch (error) {
14403
+ await this.baseCleanup(restore);
14404
+ reject2(error);
14405
+ }
14406
+ })();
14223
14407
  });
14224
14408
  }
14225
14409
  async baseCleanup(restore = true) {
14410
+ var _a4;
14226
14411
  this._stopEffects.forEach((fn) => fn());
14412
+ this._stopEffects.length = 0;
14227
14413
  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");
14414
+ if (restore && this._source && this._target && this._session) {
14415
+ const sourceHost = splitHostPort(this._source).host;
14416
+ const targetHost = splitHostPort(this._target).host;
14417
+ await this._session.client.call("hosts.remove", { ip: sourceHost, host: targetHost });
14418
+ if (sourceHost === "localhost")
14419
+ await this._session.client.call("hosts.remove", { ip: "127.0.0.1", host: targetHost });
14420
+ consola.success("Restore host success.\n");
14233
14421
  }
14234
14422
  } catch (e) {
14235
- consola.error(e);
14236
- consola.fail("Restore host failed.\n");
14423
+ if (((_a4 = this._session) == null ? void 0 : _a4.client.connected) === false) {
14424
+ consola.debug("hosts entries are restored by the privileged helper on disconnect");
14425
+ } else {
14426
+ consola.error(e);
14427
+ consola.fail("Restore host failed.\n");
14428
+ }
14237
14429
  }
14238
- if (!this.locked && !this.stoped) {
14239
- await this.stopCaddy();
14430
+ if (!this.stoped) {
14240
14431
  try {
14241
- await lockfile.unlock(caddyLockFilePath).catch(() => {
14242
- });
14243
- await (0, import_promises3.unlink)(caddyFilePath).catch(() => {
14244
- });
14245
- await (0, import_promises3.unlink)(caddyLockFilePath).catch(() => {
14246
- });
14247
- if (caddyConfig) {
14248
- await caddyConfig.cleanUp();
14249
- }
14432
+ await this.deps.config().removeProxy(this.proxyKey);
14250
14433
  } catch (e) {
14251
14434
  consola.error(e);
14252
14435
  }
@@ -14488,11 +14671,20 @@ var hmrSseBridgeClientScript = `
14488
14671
  })();
14489
14672
  `;
14490
14673
 
14674
+ // src/privilege-state.ts
14675
+ var denied = false;
14676
+ function markPrivilegeDenied() {
14677
+ denied = true;
14678
+ }
14679
+ function isPrivilegeDenied() {
14680
+ return denied;
14681
+ }
14682
+
14491
14683
  // src/index.ts
14492
14684
  var config;
14493
14685
  var caddy;
14494
14686
  var hmrSseBridgeActive = false;
14495
- var cwd = import_node_process5.default.cwd();
14687
+ var cwd = import_node_process9.default.cwd();
14496
14688
  function colorUrl(url2) {
14497
14689
  return import_picocolors2.default.green(url2.replace(/:(\d+)\//, (_, port) => `:${import_picocolors2.default.bold(port)}/`));
14498
14690
  }
@@ -14527,16 +14719,27 @@ async function printForwardProxy() {
14527
14719
  }
14528
14720
  var vitePrintUrls = once((options, source, target, base = "/", _printUrls) => {
14529
14721
  _printUrls == null ? void 0 : _printUrls();
14722
+ if (isPrivilegeDenied())
14723
+ return;
14530
14724
  if (caddy)
14531
14725
  return;
14532
- caddy = new CaddyInstant();
14533
- caddy.run(source, target, {
14726
+ const instance = new CaddyInstant();
14727
+ caddy = instance;
14728
+ instance.run(source, target, {
14534
14729
  base,
14535
14730
  ...options
14536
14731
  }).then(async () => {
14537
14732
  await printForwardProxy();
14538
14733
  consola.success(` ${import_picocolors2.default.green("\u279C")} ${import_picocolors2.default.bold("run caddy reverse proxy success")}: ${colorUrl(`${options.https ? "https" : "http"}://${target}${base}`)}`);
14539
14734
  }).catch((e) => {
14735
+ if (caddy === instance)
14736
+ caddy = void 0;
14737
+ if (e instanceof PrivilegeDeniedError) {
14738
+ markPrivilegeDenied();
14739
+ consola.warn("reverse proxy skipped: administrator permission was not granted.");
14740
+ consola.info("Restart the dev server to enable it again.");
14741
+ return;
14742
+ }
14540
14743
  throw e;
14541
14744
  });
14542
14745
  });
@@ -14557,10 +14760,6 @@ var unpluginFactory = (options) => ({
14557
14760
  } = options;
14558
14761
  if (!enable)
14559
14762
  return;
14560
- if (!isAdmin()) {
14561
- consola.warn("please run as administrator");
14562
- return;
14563
- }
14564
14763
  if (!target) {
14565
14764
  consola.fail("please provide target");
14566
14765
  return;
@@ -14596,7 +14795,7 @@ var unpluginFactory = (options) => ({
14596
14795
  },
14597
14796
  webpack(compiler) {
14598
14797
  var _a4, _b3, _c2;
14599
- if (import_node_process5.default.env.NODE_ENV !== "development")
14798
+ if (import_node_process9.default.env.NODE_ENV !== "development")
14600
14799
  return;
14601
14800
  const {
14602
14801
  enable = true,
@@ -14604,10 +14803,6 @@ var unpluginFactory = (options) => ({
14604
14803
  } = options;
14605
14804
  if (!enable)
14606
14805
  return;
14607
- if (!isAdmin()) {
14608
- consola.warn("please run as administrator");
14609
- return;
14610
- }
14611
14806
  if (!target) {
14612
14807
  consola.fail("please provide target");
14613
14808
  return;
@@ -14621,9 +14816,11 @@ var unpluginFactory = (options) => ({
14621
14816
  port: 8080,
14622
14817
  ...compiler.options.devServer,
14623
14818
  // @ts-expect-error vuecli
14624
- ...(_a4 = import_node_process5.default.VUE_CLI_SERVICE) == null ? void 0 : _a4.projectOptions.devServer
14819
+ ...(_a4 = import_node_process9.default.VUE_CLI_SERVICE) == null ? void 0 : _a4.projectOptions.devServer
14625
14820
  };
14626
14821
  const source = `${devServer.host}:${devServer.port}`;
14822
+ if (isPrivilegeDenied())
14823
+ return;
14627
14824
  if (caddy)
14628
14825
  return;
14629
14826
  let base = "/";
@@ -14638,15 +14835,16 @@ var unpluginFactory = (options) => ({
14638
14835
  const _close = (_c2 = compiler.close) == null ? void 0 : _c2.bind(compiler);
14639
14836
  if (_close) {
14640
14837
  compiler.close = async (callback) => {
14641
- import_node_process5.default.on("exit", () => {
14838
+ import_node_process9.default.on("exit", () => {
14642
14839
  _close && _close(callback);
14643
14840
  });
14644
14841
  };
14645
14842
  } else {
14646
14843
  options.https = false;
14647
14844
  }
14648
- caddy = new CaddyInstant();
14649
- caddy.run(source, target, {
14845
+ const instance = new CaddyInstant();
14846
+ caddy = instance;
14847
+ instance.run(source, target, {
14650
14848
  base,
14651
14849
  ...options
14652
14850
  }).then(() => {
@@ -14655,12 +14853,20 @@ var unpluginFactory = (options) => ({
14655
14853
  consola.success(` ${import_picocolors2.default.green("\u279C")} ${import_picocolors2.default.bold("run caddy reverse proxy success")}: ${colorUrl(`${options.https ? "https" : "http"}://${target}${base}`)}`);
14656
14854
  });
14657
14855
  }).catch((e) => {
14856
+ if (caddy === instance)
14857
+ caddy = void 0;
14858
+ if (e instanceof PrivilegeDeniedError) {
14859
+ markPrivilegeDenied();
14860
+ consola.warn("reverse proxy skipped: administrator permission was not granted.");
14861
+ consola.info("Restart the dev server to enable it again.");
14862
+ return;
14863
+ }
14658
14864
  throw e;
14659
14865
  });
14660
14866
  },
14661
14867
  async rspack(compiler) {
14662
14868
  var _a4, _b3, _c2, _d2;
14663
- if (import_node_process5.default.env.NODE_ENV !== "development")
14869
+ if (import_node_process9.default.env.NODE_ENV !== "development")
14664
14870
  return;
14665
14871
  const {
14666
14872
  enable = true,
@@ -14668,10 +14874,6 @@ var unpluginFactory = (options) => ({
14668
14874
  } = options;
14669
14875
  if (!enable)
14670
14876
  return;
14671
- if (!isAdmin()) {
14672
- consola.warn("please run as administrator");
14673
- return;
14674
- }
14675
14877
  if (!target) {
14676
14878
  consola.fail("please provide target");
14677
14879
  return;
@@ -14689,9 +14891,10 @@ var unpluginFactory = (options) => ({
14689
14891
  }))) == null ? void 0 : _b3.content) == null ? void 0 : _c2.server
14690
14892
  };
14691
14893
  const source = `${devServer.host}:${devServer.port}`;
14894
+ if (isPrivilegeDenied())
14895
+ return;
14692
14896
  if (caddy)
14693
14897
  return;
14694
- caddy = new CaddyInstant();
14695
14898
  let base = "/";
14696
14899
  const publicPath = (_d2 = compiler.options.output) == null ? void 0 : _d2.publicPath;
14697
14900
  if (typeof publicPath === "string" && publicPath) {
@@ -14701,13 +14904,23 @@ var unpluginFactory = (options) => ({
14701
14904
  base = `/${base}`;
14702
14905
  if (base !== "/" && !base.endsWith("/"))
14703
14906
  base = `${base}/`;
14704
- caddy.run(source, target, {
14907
+ const instance = new CaddyInstant();
14908
+ caddy = instance;
14909
+ instance.run(source, target, {
14705
14910
  base,
14706
14911
  ...options
14707
14912
  }).then(async () => {
14708
14913
  await printForwardProxy();
14709
14914
  consola.success(` ${import_picocolors2.default.green("\u279C")} ${import_picocolors2.default.bold("run caddy reverse proxy success")}: ${colorUrl(`${options.https ? "https" : "http"}://${target}${base}`)}`);
14710
14915
  }).catch((e) => {
14916
+ if (caddy === instance)
14917
+ caddy = void 0;
14918
+ if (e instanceof PrivilegeDeniedError) {
14919
+ markPrivilegeDenied();
14920
+ consola.warn("reverse proxy skipped: administrator permission was not granted.");
14921
+ consola.info("Restart the dev server to enable it again.");
14922
+ return;
14923
+ }
14711
14924
  throw e;
14712
14925
  });
14713
14926
  }