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

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.
package/dist/rspack.cjs CHANGED
@@ -35,7 +35,7 @@ __export(rspack_exports, {
35
35
  module.exports = __toCommonJS(rspack_exports);
36
36
 
37
37
  // src/index.ts
38
- var import_node_process8 = __toESM(require("process"), 1);
38
+ var import_node_process9 = __toESM(require("process"), 1);
39
39
  var import_console_table_printer = require("console-table-printer");
40
40
  var import_picocolors2 = __toESM(require("picocolors"), 1);
41
41
  var import_unplugin = require("unplugin");
@@ -43,450 +43,13 @@ var import_unplugin = require("unplugin");
43
43
  // src/caddy/index.ts
44
44
  var import_node_child_process3 = require("child_process");
45
45
  var import_node_fs4 = require("fs");
46
- var import_promises3 = require("fs/promises");
46
+ var import_promises2 = require("fs/promises");
47
47
  var import_node_os5 = require("os");
48
48
  var import_node_path5 = require("path");
49
- var import_node_process7 = __toESM(require("process"), 1);
50
-
51
- // node_modules/.pnpm/alien-signals@2.0.7/node_modules/alien-signals/esm/system.mjs
52
- var ReactiveFlags;
53
- (function(ReactiveFlags2) {
54
- ReactiveFlags2[ReactiveFlags2["None"] = 0] = "None";
55
- ReactiveFlags2[ReactiveFlags2["Mutable"] = 1] = "Mutable";
56
- ReactiveFlags2[ReactiveFlags2["Watching"] = 2] = "Watching";
57
- ReactiveFlags2[ReactiveFlags2["RecursedCheck"] = 4] = "RecursedCheck";
58
- ReactiveFlags2[ReactiveFlags2["Recursed"] = 8] = "Recursed";
59
- ReactiveFlags2[ReactiveFlags2["Dirty"] = 16] = "Dirty";
60
- ReactiveFlags2[ReactiveFlags2["Pending"] = 32] = "Pending";
61
- })(ReactiveFlags || (ReactiveFlags = {}));
62
- function createReactiveSystem({ update, notify: notify2, unwatched }) {
63
- let currentVersion = 0;
64
- return {
65
- link: link2,
66
- unlink: unlink4,
67
- propagate: propagate2,
68
- checkDirty: checkDirty2,
69
- endTracking: endTracking2,
70
- startTracking: startTracking2,
71
- shallowPropagate: shallowPropagate2
72
- };
73
- function link2(dep, sub) {
74
- const prevDep = sub.depsTail;
75
- if (prevDep !== void 0 && prevDep.dep === dep) {
76
- return;
77
- }
78
- const nextDep = prevDep !== void 0 ? prevDep.nextDep : sub.deps;
79
- if (nextDep !== void 0 && nextDep.dep === dep) {
80
- nextDep.version = currentVersion;
81
- sub.depsTail = nextDep;
82
- return;
83
- }
84
- const prevSub = dep.subsTail;
85
- if (prevSub !== void 0 && prevSub.version === currentVersion && prevSub.sub === sub) {
86
- return;
87
- }
88
- const newLink = sub.depsTail = dep.subsTail = {
89
- version: currentVersion,
90
- dep,
91
- sub,
92
- prevDep,
93
- nextDep,
94
- prevSub,
95
- nextSub: void 0
96
- };
97
- if (nextDep !== void 0) {
98
- nextDep.prevDep = newLink;
99
- }
100
- if (prevDep !== void 0) {
101
- prevDep.nextDep = newLink;
102
- } else {
103
- sub.deps = newLink;
104
- }
105
- if (prevSub !== void 0) {
106
- prevSub.nextSub = newLink;
107
- } else {
108
- dep.subs = newLink;
109
- }
110
- }
111
- function unlink4(link3, sub = link3.sub) {
112
- const dep = link3.dep;
113
- const prevDep = link3.prevDep;
114
- const nextDep = link3.nextDep;
115
- const nextSub = link3.nextSub;
116
- const prevSub = link3.prevSub;
117
- if (nextDep !== void 0) {
118
- nextDep.prevDep = prevDep;
119
- } else {
120
- sub.depsTail = prevDep;
121
- }
122
- if (prevDep !== void 0) {
123
- prevDep.nextDep = nextDep;
124
- } else {
125
- sub.deps = nextDep;
126
- }
127
- if (nextSub !== void 0) {
128
- nextSub.prevSub = prevSub;
129
- } else {
130
- dep.subsTail = prevSub;
131
- }
132
- if (prevSub !== void 0) {
133
- prevSub.nextSub = nextSub;
134
- } else if ((dep.subs = nextSub) === void 0) {
135
- unwatched(dep);
136
- }
137
- return nextDep;
138
- }
139
- function propagate2(link3) {
140
- let next2 = link3.nextSub;
141
- let stack;
142
- top:
143
- do {
144
- const sub = link3.sub;
145
- let flags = sub.flags;
146
- if (!(flags & 60)) {
147
- sub.flags = flags | 32;
148
- } else if (!(flags & 12)) {
149
- flags = 0;
150
- } else if (!(flags & 4)) {
151
- sub.flags = flags & ~8 | 32;
152
- } else if (!(flags & 48) && isValidLink(link3, sub)) {
153
- sub.flags = flags | 40;
154
- flags &= 1;
155
- } else {
156
- flags = 0;
157
- }
158
- if (flags & 2) {
159
- notify2(sub);
160
- }
161
- if (flags & 1) {
162
- const subSubs = sub.subs;
163
- if (subSubs !== void 0) {
164
- const nextSub = (link3 = subSubs).nextSub;
165
- if (nextSub !== void 0) {
166
- stack = { value: next2, prev: stack };
167
- next2 = nextSub;
168
- }
169
- continue;
170
- }
171
- }
172
- if ((link3 = next2) !== void 0) {
173
- next2 = link3.nextSub;
174
- continue;
175
- }
176
- while (stack !== void 0) {
177
- link3 = stack.value;
178
- stack = stack.prev;
179
- if (link3 !== void 0) {
180
- next2 = link3.nextSub;
181
- continue top;
182
- }
183
- }
184
- break;
185
- } while (true);
186
- }
187
- function startTracking2(sub) {
188
- ++currentVersion;
189
- sub.depsTail = void 0;
190
- sub.flags = sub.flags & ~56 | 4;
191
- }
192
- function endTracking2(sub) {
193
- const depsTail = sub.depsTail;
194
- let toRemove = depsTail !== void 0 ? depsTail.nextDep : sub.deps;
195
- while (toRemove !== void 0) {
196
- toRemove = unlink4(toRemove, sub);
197
- }
198
- sub.flags &= ~4;
199
- }
200
- function checkDirty2(link3, sub) {
201
- let stack;
202
- let checkDepth = 0;
203
- top:
204
- do {
205
- const dep = link3.dep;
206
- const flags = dep.flags;
207
- let dirty = false;
208
- if (sub.flags & 16) {
209
- dirty = true;
210
- } else if ((flags & 17) === 17) {
211
- if (update(dep)) {
212
- const subs = dep.subs;
213
- if (subs.nextSub !== void 0) {
214
- shallowPropagate2(subs);
215
- }
216
- dirty = true;
217
- }
218
- } else if ((flags & 33) === 33) {
219
- if (link3.nextSub !== void 0 || link3.prevSub !== void 0) {
220
- stack = { value: link3, prev: stack };
221
- }
222
- link3 = dep.deps;
223
- sub = dep;
224
- ++checkDepth;
225
- continue;
226
- }
227
- if (!dirty) {
228
- const nextDep = link3.nextDep;
229
- if (nextDep !== void 0) {
230
- link3 = nextDep;
231
- continue;
232
- }
233
- }
234
- while (checkDepth--) {
235
- const firstSub = sub.subs;
236
- const hasMultipleSubs = firstSub.nextSub !== void 0;
237
- if (hasMultipleSubs) {
238
- link3 = stack.value;
239
- stack = stack.prev;
240
- } else {
241
- link3 = firstSub;
242
- }
243
- if (dirty) {
244
- if (update(sub)) {
245
- if (hasMultipleSubs) {
246
- shallowPropagate2(firstSub);
247
- }
248
- sub = link3.sub;
249
- continue;
250
- }
251
- } else {
252
- sub.flags &= ~32;
253
- }
254
- sub = link3.sub;
255
- const nextDep = link3.nextDep;
256
- if (nextDep !== void 0) {
257
- link3 = nextDep;
258
- continue top;
259
- }
260
- dirty = false;
261
- }
262
- return dirty;
263
- } while (true);
264
- }
265
- function shallowPropagate2(link3) {
266
- do {
267
- const sub = link3.sub;
268
- const flags = sub.flags;
269
- if ((flags & 48) === 32) {
270
- sub.flags = flags | 16;
271
- if (flags & 2) {
272
- notify2(sub);
273
- }
274
- }
275
- } while ((link3 = link3.nextSub) !== void 0);
276
- }
277
- function isValidLink(checkLink, sub) {
278
- let link3 = sub.depsTail;
279
- while (link3 !== void 0) {
280
- if (link3 === checkLink) {
281
- return true;
282
- }
283
- link3 = link3.prevDep;
284
- }
285
- return false;
286
- }
287
- }
288
-
289
- // node_modules/.pnpm/alien-signals@2.0.7/node_modules/alien-signals/esm/index.mjs
290
- var queuedEffects = [];
291
- var { link, unlink, propagate, checkDirty, endTracking, startTracking, shallowPropagate } = createReactiveSystem({
292
- update(signal2) {
293
- if ("getter" in signal2) {
294
- return updateComputed(signal2);
295
- } else {
296
- return updateSignal(signal2, signal2.value);
297
- }
298
- },
299
- notify,
300
- unwatched(node2) {
301
- if ("getter" in node2) {
302
- let toRemove = node2.deps;
303
- if (toRemove !== void 0) {
304
- node2.flags = 17;
305
- do {
306
- toRemove = unlink(toRemove, node2);
307
- } while (toRemove !== void 0);
308
- }
309
- } else if (!("previousValue" in node2)) {
310
- effectOper.call(node2);
311
- }
312
- }
313
- });
314
- var batchDepth = 0;
315
- var notifyIndex = 0;
316
- var queuedEffectsLength = 0;
317
- var activeSub;
318
- var activeScope;
319
- function setCurrentSub(sub) {
320
- const prevSub = activeSub;
321
- activeSub = sub;
322
- return prevSub;
323
- }
324
- function signal(initialValue) {
325
- return signalOper.bind({
326
- previousValue: initialValue,
327
- value: initialValue,
328
- subs: void 0,
329
- subsTail: void 0,
330
- flags: 1
331
- });
332
- }
333
- function computed(getter) {
334
- return computedOper.bind({
335
- value: void 0,
336
- subs: void 0,
337
- subsTail: void 0,
338
- deps: void 0,
339
- depsTail: void 0,
340
- flags: 17,
341
- getter
342
- });
343
- }
344
- function effect(fn) {
345
- const e = {
346
- fn,
347
- subs: void 0,
348
- subsTail: void 0,
349
- deps: void 0,
350
- depsTail: void 0,
351
- flags: 2
352
- };
353
- if (activeSub !== void 0) {
354
- link(e, activeSub);
355
- } else if (activeScope !== void 0) {
356
- link(e, activeScope);
357
- }
358
- const prev = setCurrentSub(e);
359
- try {
360
- e.fn();
361
- } finally {
362
- setCurrentSub(prev);
363
- }
364
- return effectOper.bind(e);
365
- }
366
- function updateComputed(c3) {
367
- const prevSub = setCurrentSub(c3);
368
- startTracking(c3);
369
- try {
370
- const oldValue = c3.value;
371
- return oldValue !== (c3.value = c3.getter(oldValue));
372
- } finally {
373
- setCurrentSub(prevSub);
374
- endTracking(c3);
375
- }
376
- }
377
- function updateSignal(s, value2) {
378
- s.flags = 1;
379
- return s.previousValue !== (s.previousValue = value2);
380
- }
381
- function notify(e) {
382
- const flags = e.flags;
383
- if (!(flags & 64)) {
384
- e.flags = flags | 64;
385
- const subs = e.subs;
386
- if (subs !== void 0) {
387
- notify(subs.sub);
388
- } else {
389
- queuedEffects[queuedEffectsLength++] = e;
390
- }
391
- }
392
- }
393
- function run(e, flags) {
394
- if (flags & 16 || flags & 32 && checkDirty(e.deps, e)) {
395
- const prev = setCurrentSub(e);
396
- startTracking(e);
397
- try {
398
- e.fn();
399
- } finally {
400
- setCurrentSub(prev);
401
- endTracking(e);
402
- }
403
- return;
404
- } else if (flags & 32) {
405
- e.flags = flags & ~32;
406
- }
407
- let link2 = e.deps;
408
- while (link2 !== void 0) {
409
- const dep = link2.dep;
410
- const depFlags = dep.flags;
411
- if (depFlags & 64) {
412
- run(dep, dep.flags = depFlags & ~64);
413
- }
414
- link2 = link2.nextDep;
415
- }
416
- }
417
- function flush() {
418
- while (notifyIndex < queuedEffectsLength) {
419
- const effect2 = queuedEffects[notifyIndex];
420
- queuedEffects[notifyIndex++] = void 0;
421
- run(effect2, effect2.flags &= ~64);
422
- }
423
- notifyIndex = 0;
424
- queuedEffectsLength = 0;
425
- }
426
- function computedOper() {
427
- const flags = this.flags;
428
- if (flags & 16 || flags & 32 && checkDirty(this.deps, this)) {
429
- if (updateComputed(this)) {
430
- const subs = this.subs;
431
- if (subs !== void 0) {
432
- shallowPropagate(subs);
433
- }
434
- }
435
- } else if (flags & 32) {
436
- this.flags = flags & ~32;
437
- }
438
- if (activeSub !== void 0) {
439
- link(this, activeSub);
440
- } else if (activeScope !== void 0) {
441
- link(this, activeScope);
442
- }
443
- return this.value;
444
- }
445
- function signalOper(...value2) {
446
- if (value2.length) {
447
- if (this.value !== (this.value = value2[0])) {
448
- this.flags = 17;
449
- const subs = this.subs;
450
- if (subs !== void 0) {
451
- propagate(subs);
452
- if (!batchDepth) {
453
- flush();
454
- }
455
- }
456
- }
457
- } else {
458
- const value3 = this.value;
459
- if (this.flags & 16) {
460
- if (updateSignal(this, value3)) {
461
- const subs = this.subs;
462
- if (subs !== void 0) {
463
- shallowPropagate(subs);
464
- }
465
- }
466
- }
467
- if (activeSub !== void 0) {
468
- link(this, activeSub);
469
- }
470
- return value3;
471
- }
472
- }
473
- function effectOper() {
474
- let dep = this.deps;
475
- while (dep !== void 0) {
476
- dep = unlink(dep, this);
477
- }
478
- const sub = this.subs;
479
- if (sub !== void 0) {
480
- unlink(sub);
481
- }
482
- this.flags = 0;
483
- }
484
-
485
- // src/caddy/index.ts
49
+ var import_node_process8 = __toESM(require("process"), 1);
486
50
  var import_got_cjs = require("got-cjs");
487
51
  var import_http_proxy_agent = require("http-proxy-agent");
488
52
  var import_https_proxy_agent = require("https-proxy-agent");
489
- var lockfile = __toESM(require("proper-lockfile"), 1);
490
53
 
491
54
  // src/utils.ts
492
55
  var import_node_os = require("os");
@@ -13468,7 +13031,8 @@ async function genCaddyfile(ctx) {
13468
13031
 
13469
13032
  // src/caddy/config.ts
13470
13033
  var import_node_fs = require("fs");
13471
- var import_promises = require("fs/promises");
13034
+ var import_node_process2 = __toESM(require("process"), 1);
13035
+ var lockfile = __toESM(require("proper-lockfile"), 1);
13472
13036
 
13473
13037
  // src/caddy/constants.ts
13474
13038
  var import_node_os2 = __toESM(require("os"), 1);
@@ -13600,56 +13164,108 @@ var supportList = [
13600
13164
  ];
13601
13165
 
13602
13166
  // src/caddy/config.ts
13603
- function useCaddyConfig() {
13604
- const configContentRef = signal("{}");
13605
- const configJsonRef = computed(() => {
13606
- try {
13607
- return JSON.parse(configContentRef());
13608
- } catch {
13609
- return void 0;
13610
- }
13611
- });
13612
- function setConfigContent() {
13613
- if (!(0, import_node_fs.existsSync)(caddyConfigPath)) {
13614
- (0, import_node_fs.writeFileSync)(caddyConfigPath, "{}");
13615
- }
13616
- try {
13617
- configContentRef((0, import_node_fs.readFileSync)(caddyConfigPath, "utf-8"));
13618
- } catch {
13619
- configContentRef("");
13620
- }
13167
+ function isAlive(pid) {
13168
+ if (pid === void 0)
13169
+ return true;
13170
+ try {
13171
+ import_node_process2.default.kill(pid, 0);
13172
+ return true;
13173
+ } catch {
13174
+ return false;
13621
13175
  }
13622
- if (!(0, import_node_fs.existsSync)(caddyConfigPath)) {
13623
- (0, import_node_fs.writeFileSync)(caddyConfigPath, "{}");
13176
+ }
13177
+ function readConfig() {
13178
+ if (!(0, import_node_fs.existsSync)(caddyConfigPath))
13179
+ return {};
13180
+ let parsed2;
13181
+ try {
13182
+ parsed2 = JSON.parse((0, import_node_fs.readFileSync)(caddyConfigPath, "utf-8"));
13183
+ } catch {
13184
+ return {};
13624
13185
  }
13625
- const watchCaddyConfig = (0, import_node_fs.watch)(caddyConfigPath, () => {
13626
- setConfigContent();
13627
- });
13628
- function writeCaddyConfig(_proxies) {
13629
- const proxies = configJsonRef() || {};
13630
- _proxies.forEach((p) => {
13631
- let base = p.base || "/";
13632
- if (!base.startsWith("/"))
13633
- base = `/${base}`;
13634
- if (base !== "/" && !base.endsWith("/"))
13635
- base = `${base}/`;
13636
- const index = `${p.target}${p.portSuffix}${base}`;
13637
- proxies[index] = { ...p, base };
13638
- });
13639
- const content = JSON.stringify(proxies, null, 2);
13640
- configContentRef(content);
13641
- return (0, import_node_fs.writeFileSync)(caddyConfigPath, content);
13186
+ const alive = {};
13187
+ for (const [key, entry] of Object.entries(parsed2)) {
13188
+ if (isAlive(entry == null ? void 0 : entry.ownerPid))
13189
+ alive[key] = entry;
13642
13190
  }
13643
- async function cleanUp() {
13644
- await (0, import_promises.unlink)(caddyConfigPath).catch(() => {
13645
- });
13646
- configContentRef("{}");
13647
- watchCaddyConfig.close();
13191
+ return alive;
13192
+ }
13193
+ function writeConfig(proxies) {
13194
+ const content = JSON.stringify(proxies, null, 2);
13195
+ const temp = `${caddyConfigPath}.${import_node_process2.default.pid}.tmp`;
13196
+ (0, import_node_fs.writeFileSync)(temp, content);
13197
+ (0, import_node_fs.renameSync)(temp, caddyConfigPath);
13198
+ }
13199
+ async function mutateConfig(lock3, mutate) {
13200
+ const release = await lock3.acquire();
13201
+ try {
13202
+ const proxies = readConfig();
13203
+ mutate(proxies);
13204
+ writeConfig(proxies);
13205
+ return proxies;
13206
+ } finally {
13207
+ release();
13208
+ }
13209
+ }
13210
+ function useCaddyConfig(options = {}) {
13211
+ const lock3 = options.lock ?? createFileLock();
13212
+ return {
13213
+ configJsonRef: () => (0, import_node_fs.existsSync)(caddyConfigPath) ? readConfig() : void 0,
13214
+ async writeCaddyConfig(_proxies, key) {
13215
+ await mutateConfig(lock3, (proxies) => {
13216
+ for (const p of _proxies)
13217
+ proxies[routeKey(p, key)] = { ...p, base: normalizeBase(p.base), ownerPid: import_node_process2.default.pid };
13218
+ });
13219
+ },
13220
+ async removeProxy(key) {
13221
+ const proxies = await mutateConfig(lock3, (current) => {
13222
+ for (const route of Object.keys(current)) {
13223
+ if (route.endsWith(`#${key}`))
13224
+ delete current[route];
13225
+ }
13226
+ });
13227
+ if (Object.keys(proxies).length === 0)
13228
+ removeConfigFile();
13229
+ },
13230
+ readProxies: () => readConfig(),
13231
+ async cleanUp() {
13232
+ removeConfigFile();
13233
+ }
13234
+ };
13235
+ }
13236
+ function removeConfigFile() {
13237
+ try {
13238
+ if ((0, import_node_fs.existsSync)(caddyConfigPath))
13239
+ (0, import_node_fs.unlinkSync)(caddyConfigPath);
13240
+ } catch {
13648
13241
  }
13242
+ }
13243
+ function normalizeBase(base) {
13244
+ let out = base || "/";
13245
+ if (!out.startsWith("/"))
13246
+ out = `/${out}`;
13247
+ if (out !== "/" && !out.endsWith("/"))
13248
+ out = `${out}/`;
13249
+ return out;
13250
+ }
13251
+ function routeKey(proxy, ownerKey) {
13252
+ return `${proxy.target}${proxy.portSuffix}${normalizeBase(proxy.base)}#${ownerKey}`;
13253
+ }
13254
+ function createFileLock() {
13649
13255
  return {
13650
- configJsonRef,
13651
- writeCaddyConfig,
13652
- cleanUp
13256
+ async acquire() {
13257
+ if (!(0, import_node_fs.existsSync)(caddyConfigPath))
13258
+ (0, import_node_fs.writeFileSync)(caddyConfigPath, "{}");
13259
+ const release = await lockfile.lock(caddyConfigPath, {
13260
+ realpath: false,
13261
+ stale: 1e4,
13262
+ retries: { retries: 20, minTimeout: 10, maxTimeout: 100 }
13263
+ });
13264
+ return () => {
13265
+ void release().catch(() => {
13266
+ });
13267
+ };
13268
+ }
13653
13269
  };
13654
13270
  }
13655
13271
 
@@ -13667,43 +13283,56 @@ function isCaddyReloadCancellation(line) {
13667
13283
  var import_node_buffer2 = require("buffer");
13668
13284
  var import_node_events = require("events");
13669
13285
  var import_node_path4 = require("path");
13670
- var import_node_process6 = __toESM(require("process"), 1);
13286
+ var import_node_process7 = __toESM(require("process"), 1);
13671
13287
  var import_node_url = require("url");
13672
13288
 
13673
13289
  // src/privileged/entry.ts
13674
13290
  var import_node_fs2 = require("fs");
13675
13291
  var import_node_path2 = require("path");
13676
- var import_node_process2 = __toESM(require("process"), 1);
13292
+ var import_node_process3 = __toESM(require("process"), 1);
13677
13293
  function resolveHelperEntry(options) {
13678
- const { moduleDir, nodeBin = import_node_process2.default.execPath, exists: exists2 = import_node_fs2.existsSync } = options;
13294
+ const { moduleDir, nodeBin = import_node_process3.default.execPath, exists: exists2 = import_node_fs2.existsSync } = options;
13679
13295
  for (const name of ["privileged-helper.js", "privileged-helper.cjs", "privileged-helper.mjs"]) {
13680
- const candidate = (0, import_node_path2.join)(moduleDir, name);
13681
- if (exists2(candidate))
13296
+ const candidate = findUp(moduleDir, name, exists2);
13297
+ if (candidate)
13682
13298
  return { entry: nodeBin, args: [candidate] };
13683
13299
  }
13684
- const source = (0, import_node_path2.join)(moduleDir, "privileged-helper.ts");
13685
- const tsxCli = (0, import_node_path2.join)(moduleDir, "../node_modules/tsx/dist/cli.mjs");
13686
- if (exists2(source) && exists2(tsxCli))
13300
+ const source = findUp(moduleDir, "privileged-helper.ts", exists2);
13301
+ const tsxCli = findUp(moduleDir, "node_modules/tsx/dist/cli.mjs", exists2);
13302
+ if (source && tsxCli)
13687
13303
  return { entry: nodeBin, args: [tsxCli, source] };
13688
13304
  throw new Error(`privileged helper entry not found in ${moduleDir}. Build the package first.`);
13689
13305
  }
13306
+ function findUp(from, relative, exists2) {
13307
+ let current = from;
13308
+ while (true) {
13309
+ const candidate = (0, import_node_path2.join)(current, relative);
13310
+ if (exists2(candidate))
13311
+ return candidate;
13312
+ const parent = (0, import_node_path2.dirname)(current);
13313
+ if (parent === current)
13314
+ return void 0;
13315
+ current = parent;
13316
+ }
13317
+ }
13690
13318
 
13691
13319
  // src/privileged/session.ts
13692
13320
  var import_node_buffer = require("buffer");
13693
13321
  var import_node_fs3 = require("fs");
13694
- var import_promises2 = require("fs/promises");
13322
+ var import_promises = require("fs/promises");
13695
13323
  var import_node_os4 = require("os");
13696
13324
  var import_node_path3 = require("path");
13325
+ var lockfile2 = __toESM(require("proper-lockfile"), 1);
13697
13326
 
13698
13327
  // src/privileged/launch.ts
13699
13328
  var import_node_child_process2 = require("child_process");
13700
13329
  var import_node_crypto = require("crypto");
13701
13330
  var import_node_os3 = require("os");
13702
- var import_node_process5 = __toESM(require("process"), 1);
13331
+ var import_node_process6 = __toESM(require("process"), 1);
13703
13332
 
13704
13333
  // src/privileged/client.ts
13705
13334
  var import_node_net = require("net");
13706
- var import_node_process3 = __toESM(require("process"), 1);
13335
+ var import_node_process4 = __toESM(require("process"), 1);
13707
13336
 
13708
13337
  // src/privileged/protocol.ts
13709
13338
  function serializeMessage(message) {
@@ -13766,7 +13395,7 @@ var FORWARDED_ENV_KEYS = [
13766
13395
  "NO_PROXY",
13767
13396
  "no_proxy"
13768
13397
  ];
13769
- function collectForwardedEnv(source = import_node_process3.default.env) {
13398
+ function collectForwardedEnv(source = import_node_process4.default.env) {
13770
13399
  const result = {};
13771
13400
  for (const key of FORWARDED_ENV_KEYS) {
13772
13401
  const value2 = source[key];
@@ -13943,7 +13572,7 @@ function createClient(socket, initialBuffer, callTimeoutMs) {
13943
13572
 
13944
13573
  // src/privileged/windows-elevation.ts
13945
13574
  var import_node_child_process = require("child_process");
13946
- var import_node_process4 = __toESM(require("process"), 1);
13575
+ var import_node_process5 = __toESM(require("process"), 1);
13947
13576
  function quotePowerShell(value2) {
13948
13577
  return `'${value2.replace(/'/g, "''")}'`;
13949
13578
  }
@@ -13985,18 +13614,42 @@ function spawnElevatedOnWindows(options) {
13985
13614
  function createHelperToken() {
13986
13615
  return (0, import_node_crypto.randomBytes)(24).toString("hex");
13987
13616
  }
13988
- function authenticateSudo(sudoCommand = "sudo") {
13617
+ function describePasswordReason(target, https) {
13618
+ const port = https ? "443" : "80";
13619
+ return [
13620
+ `reverse proxy needs administrator permission for ${target}`,
13621
+ ` \xB7 bind port ${port}${https ? ` for https://${target}` : ""}`,
13622
+ ` \xB7 add ${target} to the hosts file`,
13623
+ "",
13624
+ "This is the only prompt; the rest of the dev server keeps running as you.",
13625
+ "Press Ctrl+C at the prompt to skip the proxy and keep the dev server."
13626
+ ];
13627
+ }
13628
+ function authenticateSudo(sudoCommand = "sudo", options = {}) {
13989
13629
  if ((0, import_node_os3.platform)() === "win32")
13990
13630
  return { ok: true };
13991
13631
  if ((0, import_node_child_process2.spawnSync)(sudoCommand, ["-n", "true"], { stdio: "ignore" }).status === 0)
13992
13632
  return { ok: true };
13633
+ if (options.target) {
13634
+ for (const line of describePasswordReason(options.target, options.https ?? false))
13635
+ import_node_process6.default.stderr.write(`${line}
13636
+ `);
13637
+ import_node_process6.default.stderr.write("\n");
13638
+ }
13993
13639
  if ((0, import_node_child_process2.spawnSync)(sudoCommand, ["-v"], { stdio: "inherit" }).status === 0)
13994
13640
  return { ok: true };
13995
13641
  return {
13996
13642
  ok: false,
13643
+ denied: true,
13997
13644
  message: "administrator permission is required to edit the hosts file and bind ports 80/443"
13998
13645
  };
13999
13646
  }
13647
+ var PrivilegeDeniedError = class extends Error {
13648
+ constructor(message) {
13649
+ super(message);
13650
+ this.name = "PrivilegeDeniedError";
13651
+ }
13652
+ };
14000
13653
  async function startPrivilegedHelper(options) {
14001
13654
  var _a4, _b3;
14002
13655
  const {
@@ -14007,14 +13660,16 @@ async function startPrivilegedHelper(options) {
14007
13660
  sudoCommand = "sudo",
14008
13661
  skipAuth = false,
14009
13662
  direct = false,
14010
- env: env2 = import_node_process5.default.env,
13663
+ env: env2 = import_node_process6.default.env,
14011
13664
  log,
14012
13665
  connectTimeoutMs = 12e4
14013
13666
  } = options;
14014
13667
  if (!skipAuth && !direct) {
14015
- const auth = authenticateSudo(sudoCommand);
14016
- if (!auth.ok)
14017
- throw new Error(auth.message);
13668
+ const auth = authenticateSudo(sudoCommand, options.reason);
13669
+ if (!auth.ok) {
13670
+ const message = auth.message ?? "administrator permission is required";
13671
+ throw auth.denied ? new PrivilegeDeniedError(message) : new Error(message);
13672
+ }
14018
13673
  }
14019
13674
  const forwarded = collectForwardedEnv(env2);
14020
13675
  const forwardedArgs = Object.entries(forwarded).map(([key, value2]) => `${key}=${value2}`);
@@ -14024,8 +13679,8 @@ async function startPrivilegedHelper(options) {
14024
13679
  socketPath,
14025
13680
  "--token",
14026
13681
  token,
14027
- ...typeof import_node_process5.default.getuid === "function" ? ["--owner-uid", String(import_node_process5.default.getuid())] : [],
14028
- ...typeof import_node_process5.default.getgid === "function" ? ["--owner-gid", String(import_node_process5.default.getgid())] : [],
13682
+ ...typeof import_node_process6.default.getuid === "function" ? ["--owner-uid", String(import_node_process6.default.getuid())] : [],
13683
+ ...typeof import_node_process6.default.getgid === "function" ? ["--owner-gid", String(import_node_process6.default.getgid())] : [],
14029
13684
  ...options.caddyStoragePath ? ["--caddy-storage", options.caddyStoragePath] : [],
14030
13685
  "--caddy",
14031
13686
  options.caddyBin,
@@ -14034,7 +13689,7 @@ async function startPrivilegedHelper(options) {
14034
13689
  ];
14035
13690
  let child;
14036
13691
  if (!direct && (0, import_node_os3.platform)() === "win32") {
14037
- await spawnElevatedOnWindows({ file: helperEntry, args: childArgv, cwd: import_node_process5.default.cwd() });
13692
+ await spawnElevatedOnWindows({ file: helperEntry, args: childArgv, cwd: import_node_process6.default.cwd() });
14038
13693
  } else {
14039
13694
  const command = direct ? helperEntry : sudoCommand;
14040
13695
  const spawnArgs = direct ? childArgv : ["-n", "env", ...forwardedArgs, helperEntry, ...childArgv];
@@ -14091,21 +13746,34 @@ function sessionSocketPath(runtimeDir) {
14091
13746
  }
14092
13747
  async function openHelperSession(scope2) {
14093
13748
  const socketPath = sessionSocketPath(scope2.runtimeDir);
14094
- if ((0, import_node_fs3.existsSync)(socketPath) || (0, import_node_os4.platform)() === "win32") {
14095
- const token2 = await readToken(scope2.runtimeDir);
14096
- if (token2) {
14097
- const reused = await connectExistingHelper(socketPath, token2);
14098
- if (reused) {
14099
- return {
14100
- client: reused,
14101
- reused: true,
14102
- close: async () => {
14103
- await reused.close();
14104
- }
14105
- };
14106
- }
14107
- }
13749
+ const release = await acquireStartLock(scope2.runtimeDir);
13750
+ try {
13751
+ const reused = await tryReuse(socketPath, scope2);
13752
+ if (reused)
13753
+ return reused;
13754
+ return await startNew(socketPath, scope2);
13755
+ } finally {
13756
+ release();
14108
13757
  }
13758
+ }
13759
+ async function tryReuse(socketPath, scope2) {
13760
+ if (!(0, import_node_fs3.existsSync)(socketPath) && (0, import_node_os4.platform)() !== "win32")
13761
+ return void 0;
13762
+ const token = await readToken(scope2.runtimeDir);
13763
+ if (!token)
13764
+ return void 0;
13765
+ const reused = await connectExistingHelper(socketPath, token);
13766
+ if (!reused)
13767
+ return void 0;
13768
+ return {
13769
+ client: reused,
13770
+ reused: true,
13771
+ close: async () => {
13772
+ await reused.close();
13773
+ }
13774
+ };
13775
+ }
13776
+ async function startNew(socketPath, scope2) {
14109
13777
  const token = createHelperToken();
14110
13778
  const started = await startPrivilegedHelper({
14111
13779
  socketPath,
@@ -14119,6 +13787,7 @@ async function openHelperSession(scope2) {
14119
13787
  caddyStoragePath: scope2.caddyStoragePath,
14120
13788
  caddyBin: scope2.caddyBin,
14121
13789
  caddyConfigPath: scope2.caddyConfigPath,
13790
+ reason: scope2.reason,
14122
13791
  log: scope2.log
14123
13792
  });
14124
13793
  await writeToken(scope2.runtimeDir, token);
@@ -14130,9 +13799,25 @@ async function openHelperSession(scope2) {
14130
13799
  }
14131
13800
  };
14132
13801
  }
13802
+ async function acquireStartLock(runtimeDir) {
13803
+ const lockPath = (0, import_node_path3.join)(runtimeDir, "helper.start.lock");
13804
+ try {
13805
+ await (0, import_promises.writeFile)(lockPath, "", { flag: "a" });
13806
+ } catch {
13807
+ }
13808
+ const release = await lockfile2.lock(lockPath, {
13809
+ realpath: false,
13810
+ stale: 3e4,
13811
+ retries: { retries: 100, minTimeout: 50, maxTimeout: 200 }
13812
+ });
13813
+ return () => {
13814
+ void release().catch(() => {
13815
+ });
13816
+ };
13817
+ }
14133
13818
  async function readToken(runtimeDir) {
14134
13819
  try {
14135
- const content = await (0, import_promises2.readFile)(tokenPath(runtimeDir), "utf8");
13820
+ const content = await (0, import_promises.readFile)(tokenPath(runtimeDir), "utf8");
14136
13821
  const token = content.trim();
14137
13822
  return token === "" ? void 0 : token;
14138
13823
  } catch {
@@ -14141,7 +13826,7 @@ async function readToken(runtimeDir) {
14141
13826
  }
14142
13827
  async function writeToken(runtimeDir, token) {
14143
13828
  try {
14144
- await (0, import_promises2.writeFile)(tokenPath(runtimeDir), token, { mode: 384 });
13829
+ await (0, import_promises.writeFile)(tokenPath(runtimeDir), token, { mode: 384 });
14145
13830
  } catch {
14146
13831
  }
14147
13832
  }
@@ -14189,7 +13874,7 @@ var HelperCaddyProcess = class extends import_node_events.EventEmitter {
14189
13874
  }
14190
13875
  };
14191
13876
  function caddyStoragePath() {
14192
- return import_node_process6.default.platform === "win32" ? (0, import_node_path4.join)(import_node_process6.default.env.AppData ?? "", "Caddy") : (0, import_node_path4.join)(import_node_process6.default.env.HOME ?? "", "Library/Application Support/Caddy");
13877
+ 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");
14193
13878
  }
14194
13879
  function openPrivilegedSession(runtimeDir, options) {
14195
13880
  const env2 = resolvePrivilegedEnv();
@@ -14205,6 +13890,7 @@ function openPrivilegedSession(runtimeDir, options) {
14205
13890
  // execute a path supplied over the socket.
14206
13891
  caddyBin: options.caddyBin,
14207
13892
  caddyConfigPath: options.caddyConfigPath,
13893
+ reason: options.reason,
14208
13894
  log: options.log
14209
13895
  });
14210
13896
  }
@@ -14338,15 +14024,15 @@ async function download() {
14338
14024
  const file = (0, import_node_fs4.createWriteStream)(caddyPath);
14339
14025
  let _platform = (0, import_node_os5.platform)().toString();
14340
14026
  _platform === "win32" && (_platform = "windows");
14341
- let _arch = import_node_process7.default.arch.toString();
14027
+ let _arch = import_node_process8.default.arch.toString();
14342
14028
  _arch === "x64" && (_arch = "amd64");
14343
14029
  const support = supportList.find((item) => item.platform === _platform && item.arch === _arch);
14344
14030
  if (!support)
14345
14031
  return reject2(new Error("not support"));
14346
14032
  const dowmloadLink = `https://caddyserver.com/api/download?os=${support.platform}&arch=${support.arch}&p=github.com%2Fcaddyserver%2Fforwardproxy`;
14347
14033
  (0, import_node_fs4.existsSync)(caddyPath) && (0, import_node_fs4.unlinkSync)(caddyPath);
14348
- const httpProxy = import_node_process7.default.env.HTTP_PROXY || import_node_process7.default.env.http_proxy;
14349
- const httpsProxy = import_node_process7.default.env.HTTPS_PROXY || import_node_process7.default.env.https_proxy;
14034
+ const httpProxy = import_node_process8.default.env.HTTP_PROXY || import_node_process8.default.env.http_proxy;
14035
+ const httpsProxy = import_node_process8.default.env.HTTPS_PROXY || import_node_process8.default.env.https_proxy;
14350
14036
  const httpAgent = httpProxy ? new import_http_proxy_agent.HttpProxyAgent(httpProxy) : void 0;
14351
14037
  const httpsAgent = httpsProxy ? new import_https_proxy_agent.HttpsProxyAgent(httpsProxy) : void 0;
14352
14038
  const chmodCaddyOnce = once(() => {
@@ -14362,7 +14048,7 @@ async function download() {
14362
14048
  chmodCaddyOnce();
14363
14049
  }).pipe(file).on("finish", () => {
14364
14050
  logProgressOver();
14365
- if (import_node_process7.default.platform === "win32")
14051
+ if (import_node_process8.default.platform === "win32")
14366
14052
  return resolve2(caddyPath);
14367
14053
  (0, import_node_fs4.chmodSync)(caddyPath, 493);
14368
14054
  resolve2(caddyPath);
@@ -14405,43 +14091,35 @@ function splitHostPort(addr) {
14405
14091
  return { host: addr.slice(0, lastColon), port: addr.slice(lastColon + 1) };
14406
14092
  }
14407
14093
  var defaultDependencies = {
14408
- openSession: (runtimeDir) => openPrivilegedSession(runtimeDir, {
14094
+ openSession: (runtimeDir, reason) => openPrivilegedSession(runtimeDir, {
14409
14095
  log: (message) => consola.debug(message),
14410
14096
  // Both paths are fixed here, before any socket traffic: the privileged
14411
14097
  // helper must never execute something named in a request.
14412
14098
  caddyBin: caddyPath,
14413
- caddyConfigPath: caddyFilePath
14414
- })
14099
+ caddyConfigPath: caddyFilePath,
14100
+ reason
14101
+ }),
14102
+ config: () => getCaddyConfig()
14415
14103
  };
14416
14104
  var CaddyInstant = class {
14417
14105
  constructor(deps = {}) {
14418
14106
  this.inited = false;
14419
14107
  this.stoped = false;
14420
- /** has locked when start */
14421
- this.locked = false;
14422
14108
  this._stopEffects = [];
14109
+ /** Identifies this instance's routes in the shared config. */
14110
+ this.proxyKey = `${import_node_process8.default.pid}-${Math.random().toString(36).slice(2, 8)}`;
14423
14111
  this.deps = { ...defaultDependencies, ...deps };
14424
- this.locked = this.checkLock();
14425
- }
14426
- checkLock() {
14427
- if (!(0, import_node_fs4.existsSync)(caddyLockFilePath))
14428
- (0, import_node_fs4.writeFileSync)(caddyLockFilePath, "");
14429
- try {
14430
- return lockfile.checkSync(caddyLockFilePath);
14431
- } catch {
14432
- return false;
14433
- }
14434
14112
  }
14435
14113
  /**
14436
14114
  * Connects to the privileged helper, starting it once if needed. It is
14437
14115
  * reused across instances so a second dev server does not ask for a
14438
14116
  * password again.
14439
14117
  */
14440
- async session() {
14118
+ async session(reason) {
14441
14119
  if (this._session && !this._session.client.connected)
14442
14120
  this._session = void 0;
14443
14121
  if (!this._session)
14444
- this._session = await this.deps.openSession(TEMP_DIR);
14122
+ this._session = await this.deps.openSession(TEMP_DIR, reason);
14445
14123
  return this._session;
14446
14124
  }
14447
14125
  async getCaddyfile() {
@@ -14449,20 +14127,20 @@ var CaddyInstant = class {
14449
14127
  this.caddyfile = "";
14450
14128
  return "";
14451
14129
  }
14452
- this.caddyfile = await (0, import_promises3.readFile)(caddyFilePath, "utf-8");
14130
+ this.caddyfile = await (0, import_promises2.readFile)(caddyFilePath, "utf-8");
14453
14131
  return this.caddyfile;
14454
14132
  }
14455
14133
  get caddyRoot() {
14456
14134
  return (0, import_node_path5.join)(
14457
- import_node_process7.default.platform === "win32" ? `${import_node_process7.default.env.AppData}/Caddy` : `${import_node_process7.default.env.HOME}/Library/Application Support/Caddy`,
14135
+ import_node_process8.default.platform === "win32" ? `${import_node_process8.default.env.AppData}/Caddy` : `${import_node_process8.default.env.HOME}/Library/Application Support/Caddy`,
14458
14136
  "./pki/authorities/local"
14459
14137
  );
14460
14138
  }
14461
14139
  async writeCaddyfile() {
14462
- return await (0, import_promises3.writeFile)(caddyFilePath, this.caddyfile || "");
14140
+ return await (0, import_promises2.writeFile)(caddyFilePath, this.caddyfile || "");
14463
14141
  }
14464
14142
  async deleteCaddyfile() {
14465
- return await (0, import_promises3.unlink)(caddyFilePath);
14143
+ return await (0, import_promises2.unlink)(caddyFilePath);
14466
14144
  }
14467
14145
  async init() {
14468
14146
  await download();
@@ -14500,9 +14178,15 @@ Run \`${caddyPath} trust\` manually if the browser warns about the certificate.`
14500
14178
  if (!health.healthy)
14501
14179
  throw new Error(formatTlsHealthFailure(targetHost, health));
14502
14180
  }
14181
+ /**
14182
+ * Regenerates the Caddyfile from the config on disk.
14183
+ *
14184
+ * Reading the file rather than a cached view matters here: another project
14185
+ * may have added its route since this instance last looked.
14186
+ */
14503
14187
  async updateCaddyfile() {
14504
- const { configJsonRef } = getCaddyConfig();
14505
- const proxies = Object.values(configJsonRef() || {});
14188
+ const { readProxies } = this.deps.config();
14189
+ const proxies = Object.values(readProxies());
14506
14190
  const ctx = validateTemplateContext({
14507
14191
  caddy_root: this.caddyRoot,
14508
14192
  proxies
@@ -14546,12 +14230,12 @@ Run \`${caddyPath} trust\` manually if the browser warns about the certificate.`
14546
14230
  this._target = target;
14547
14231
  if (!this.inited)
14548
14232
  await this.init();
14549
- const session = await this.session();
14550
14233
  const sourceHost = splitHostPort(source).host;
14551
14234
  const targetHost = splitHostPort(target).host;
14235
+ const session = await this.session({ target: targetHost, https });
14552
14236
  await session.client.call("hosts.add", { ip: sourceHost, host: targetHost });
14553
14237
  consola.success("update host success\n");
14554
- const normalizeBase = (b) => {
14238
+ const normalizeBase2 = (b) => {
14555
14239
  let out = b || "/";
14556
14240
  if (!out.startsWith("/"))
14557
14241
  out = `/${out}`;
@@ -14559,7 +14243,7 @@ Run \`${caddyPath} trust\` manually if the browser warns about the certificate.`
14559
14243
  out = `${out}/`;
14560
14244
  return out;
14561
14245
  };
14562
- const baseNormalized = normalizeBase(base);
14246
+ const baseNormalized = normalizeBase2(base);
14563
14247
  const proxies = [
14564
14248
  {
14565
14249
  target: targetHost,
@@ -14570,27 +14254,12 @@ Run \`${caddyPath} trust\` manually if the browser warns about the certificate.`
14570
14254
  healthCheck
14571
14255
  }
14572
14256
  ];
14573
- const { writeCaddyConfig } = getCaddyConfig();
14574
- writeCaddyConfig(proxies);
14257
+ const { writeCaddyConfig } = this.deps.config();
14258
+ await writeCaddyConfig(proxies, this.proxyKey);
14575
14259
  await this.updateCaddyfile();
14576
- let skipInitialCaddyfileEffect = true;
14577
- this._stopEffects.push(
14578
- effect(() => {
14579
- getCaddyConfig().configJsonRef();
14580
- if (skipInitialCaddyfileEffect) {
14581
- skipInitialCaddyfileEffect = false;
14582
- return;
14583
- }
14584
- void this.updateCaddyfile();
14585
- })
14586
- );
14587
- if (!(0, import_node_fs4.existsSync)(caddyLockFilePath))
14588
- (0, import_node_fs4.writeFileSync)(caddyLockFilePath, "");
14589
- if (!this.locked) {
14590
- await session.client.call("port.free", { port: 443 });
14591
- if (import_node_process7.default.platform === "win32" || !https)
14592
- await session.client.call("port.free", { port: 80 });
14593
- }
14260
+ await session.client.call("port.free", { port: 443 });
14261
+ if (import_node_process8.default.platform === "win32" || !https)
14262
+ await session.client.call("port.free", { port: 80 });
14594
14263
  return new Promise((resolve2, reject2) => {
14595
14264
  let startupCheckStarted = false;
14596
14265
  const resolveWhenReady = async () => {
@@ -14604,106 +14273,89 @@ Run \`${caddyPath} trust\` manually if the browser warns about the certificate.`
14604
14273
  }
14605
14274
  resolve2();
14606
14275
  } catch (error) {
14607
- if (!this.locked)
14608
- await this.baseCleanup(restore);
14276
+ await this.baseCleanup(restore);
14609
14277
  reject2(error);
14610
14278
  }
14611
14279
  };
14612
14280
  const setupCleanup = () => {
14613
- import_node_process7.default.on("SIGINT", async () => {
14281
+ import_node_process8.default.on("SIGINT", async () => {
14614
14282
  if (this.stoped)
14615
14283
  return;
14616
- import_node_process7.default.stdin.resume();
14284
+ import_node_process8.default.stdin.resume();
14617
14285
  try {
14618
14286
  await this.baseCleanup(restore);
14619
14287
  } finally {
14620
14288
  this.stoped = true;
14621
- import_node_process7.default.nextTick(() => {
14622
- import_node_process7.default.exit();
14289
+ import_node_process8.default.nextTick(() => {
14290
+ import_node_process8.default.exit();
14623
14291
  });
14624
14292
  }
14625
14293
  });
14626
- const originalExit = import_node_process7.default.exit.bind(import_node_process7.default);
14627
- import_node_process7.default.exit = async (code) => {
14294
+ const originalExit = import_node_process8.default.exit.bind(import_node_process8.default);
14295
+ import_node_process8.default.exit = async (code) => {
14628
14296
  if (this.stoped)
14629
14297
  return originalExit(code);
14630
- import_node_process7.default.stdin.resume();
14298
+ import_node_process8.default.stdin.resume();
14631
14299
  try {
14632
14300
  await this.baseCleanup();
14633
14301
  } finally {
14634
14302
  this.stoped = true;
14635
- import_node_process7.default.nextTick(() => {
14303
+ import_node_process8.default.nextTick(() => {
14636
14304
  originalExit(code);
14637
14305
  });
14638
14306
  }
14639
14307
  };
14640
14308
  };
14641
- if (!this.locked) {
14642
- lockfile.lockSync(caddyLockFilePath);
14643
- setupCleanup();
14644
- void (async () => {
14645
- try {
14646
- const child = new HelperCaddyProcess(session.client);
14647
- this._caddyChild = child;
14648
- await session.client.call("caddy.start");
14649
- child.on("exit", (code) => {
14650
- if (code !== null && code !== 0)
14651
- reject2(new Error(`Caddy exited with code ${code}`));
14652
- });
14653
- child.stderr.on("data", async (data) => {
14654
- const lines = data.toString().split("\n").map((line) => line.trim());
14655
- for (const line of lines) {
14656
- showCaddyLog && line && console.info(line);
14657
- if (isCaddyReloadCancellation(line)) {
14658
- consola.info("Caddy restarted before TLS issuance completed; retrying.\n");
14659
- continue;
14660
- }
14661
- try {
14662
- if (line.includes("Error:") || line && JSON.parse(line).level === "error") {
14663
- if (line.includes("parsing caddyfile tokens")) {
14664
- consola.error("Caddyfile syntax error, please contact the author:\n", `${this.caddyfile}
14309
+ setupCleanup();
14310
+ void (async () => {
14311
+ try {
14312
+ const child = new HelperCaddyProcess(session.client);
14313
+ this._caddyChild = child;
14314
+ await session.client.call("caddy.start");
14315
+ child.on("exit", (code) => {
14316
+ if (code !== null && code !== 0)
14317
+ reject2(new Error(`Caddy exited with code ${code}`));
14318
+ });
14319
+ child.stderr.on("data", async (data) => {
14320
+ const lines = data.toString().split("\n").map((line) => line.trim());
14321
+ for (const line of lines) {
14322
+ showCaddyLog && line && console.info(line);
14323
+ if (isCaddyReloadCancellation(line)) {
14324
+ consola.info("Caddy restarted before TLS issuance completed; retrying.\n");
14325
+ continue;
14326
+ }
14327
+ try {
14328
+ if (line.includes("Error:") || line && JSON.parse(line).level === "error") {
14329
+ if (line.includes("parsing caddyfile tokens")) {
14330
+ consola.error("Caddyfile syntax error, please contact the author:\n", `${this.caddyfile}
14665
14331
 
14666
14332
  ${line}
14667
14333
  `);
14668
- await this.baseCleanup();
14669
- import_node_process7.default.exit();
14670
- } else {
14671
- consola.error(`${line}
14334
+ await this.baseCleanup();
14335
+ import_node_process8.default.exit();
14336
+ } else {
14337
+ consola.error(`${line}
14672
14338
  `);
14673
- return reject2(line);
14674
- }
14339
+ return reject2(line);
14675
14340
  }
14676
- } catch {
14677
14341
  }
14678
- if (line.includes("config file changed"))
14679
- consola.success("Detect added a new reverse proxy config, restarted.\n");
14680
- if (line.includes("caddy proxying") || line.includes("serving initial"))
14681
- void resolveWhenReady();
14342
+ } catch {
14682
14343
  }
14683
- });
14684
- child.stdout.on("data", (data) => {
14685
- consola.info(data.toString());
14686
- void resolveWhenReady();
14687
- });
14688
- } catch (error) {
14689
- if (!this.locked)
14690
- await this.baseCleanup(restore);
14691
- reject2(error);
14692
- }
14693
- })();
14694
- } else {
14695
- consola.info("Caddy is running in another process.");
14696
- void (async () => {
14697
- try {
14698
- if (https)
14699
- await this.ensureTlsReady(targetHost);
14700
- setupCleanup();
14701
- resolve2();
14702
- } catch (error) {
14703
- reject2(error);
14704
- }
14705
- })();
14706
- }
14344
+ if (line.includes("config file changed"))
14345
+ consola.success("Detect added a new reverse proxy config, restarted.\n");
14346
+ if (line.includes("caddy proxying") || line.includes("serving initial"))
14347
+ void resolveWhenReady();
14348
+ }
14349
+ });
14350
+ child.stdout.on("data", (data) => {
14351
+ consola.info(data.toString());
14352
+ void resolveWhenReady();
14353
+ });
14354
+ } catch (error) {
14355
+ await this.baseCleanup(restore);
14356
+ reject2(error);
14357
+ }
14358
+ })();
14707
14359
  });
14708
14360
  }
14709
14361
  async baseCleanup(restore = true) {
@@ -14727,18 +14379,9 @@ ${line}
14727
14379
  consola.fail("Restore host failed.\n");
14728
14380
  }
14729
14381
  }
14730
- if (!this.locked && !this.stoped) {
14731
- await this.stopCaddy();
14382
+ if (!this.stoped) {
14732
14383
  try {
14733
- await lockfile.unlock(caddyLockFilePath).catch(() => {
14734
- });
14735
- await (0, import_promises3.unlink)(caddyFilePath).catch(() => {
14736
- });
14737
- await (0, import_promises3.unlink)(caddyLockFilePath).catch(() => {
14738
- });
14739
- if (caddyConfig) {
14740
- await caddyConfig.cleanUp();
14741
- }
14384
+ await this.deps.config().removeProxy(this.proxyKey);
14742
14385
  } catch (e) {
14743
14386
  consola.error(e);
14744
14387
  }
@@ -14980,11 +14623,20 @@ var hmrSseBridgeClientScript = `
14980
14623
  })();
14981
14624
  `;
14982
14625
 
14626
+ // src/privilege-state.ts
14627
+ var denied = false;
14628
+ function markPrivilegeDenied() {
14629
+ denied = true;
14630
+ }
14631
+ function isPrivilegeDenied() {
14632
+ return denied;
14633
+ }
14634
+
14983
14635
  // src/index.ts
14984
14636
  var config;
14985
14637
  var caddy;
14986
14638
  var hmrSseBridgeActive = false;
14987
- var cwd = import_node_process8.default.cwd();
14639
+ var cwd = import_node_process9.default.cwd();
14988
14640
  function colorUrl(url2) {
14989
14641
  return import_picocolors2.default.green(url2.replace(/:(\d+)\//, (_, port) => `:${import_picocolors2.default.bold(port)}/`));
14990
14642
  }
@@ -15019,16 +14671,27 @@ async function printForwardProxy() {
15019
14671
  }
15020
14672
  var vitePrintUrls = once((options, source, target, base = "/", _printUrls) => {
15021
14673
  _printUrls == null ? void 0 : _printUrls();
14674
+ if (isPrivilegeDenied())
14675
+ return;
15022
14676
  if (caddy)
15023
14677
  return;
15024
- caddy = new CaddyInstant();
15025
- caddy.run(source, target, {
14678
+ const instance = new CaddyInstant();
14679
+ caddy = instance;
14680
+ instance.run(source, target, {
15026
14681
  base,
15027
14682
  ...options
15028
14683
  }).then(async () => {
15029
14684
  await printForwardProxy();
15030
14685
  consola.success(` ${import_picocolors2.default.green("\u279C")} ${import_picocolors2.default.bold("run caddy reverse proxy success")}: ${colorUrl(`${options.https ? "https" : "http"}://${target}${base}`)}`);
15031
14686
  }).catch((e) => {
14687
+ if (caddy === instance)
14688
+ caddy = void 0;
14689
+ if (e instanceof PrivilegeDeniedError) {
14690
+ markPrivilegeDenied();
14691
+ consola.warn("reverse proxy skipped: administrator permission was not granted.");
14692
+ consola.info("Restart the dev server to enable it again.");
14693
+ return;
14694
+ }
15032
14695
  throw e;
15033
14696
  });
15034
14697
  });
@@ -15084,7 +14747,7 @@ var unpluginFactory = (options) => ({
15084
14747
  },
15085
14748
  webpack(compiler) {
15086
14749
  var _a4, _b3, _c2;
15087
- if (import_node_process8.default.env.NODE_ENV !== "development")
14750
+ if (import_node_process9.default.env.NODE_ENV !== "development")
15088
14751
  return;
15089
14752
  const {
15090
14753
  enable = true,
@@ -15105,9 +14768,11 @@ var unpluginFactory = (options) => ({
15105
14768
  port: 8080,
15106
14769
  ...compiler.options.devServer,
15107
14770
  // @ts-expect-error vuecli
15108
- ...(_a4 = import_node_process8.default.VUE_CLI_SERVICE) == null ? void 0 : _a4.projectOptions.devServer
14771
+ ...(_a4 = import_node_process9.default.VUE_CLI_SERVICE) == null ? void 0 : _a4.projectOptions.devServer
15109
14772
  };
15110
14773
  const source = `${devServer.host}:${devServer.port}`;
14774
+ if (isPrivilegeDenied())
14775
+ return;
15111
14776
  if (caddy)
15112
14777
  return;
15113
14778
  let base = "/";
@@ -15122,15 +14787,16 @@ var unpluginFactory = (options) => ({
15122
14787
  const _close = (_c2 = compiler.close) == null ? void 0 : _c2.bind(compiler);
15123
14788
  if (_close) {
15124
14789
  compiler.close = async (callback) => {
15125
- import_node_process8.default.on("exit", () => {
14790
+ import_node_process9.default.on("exit", () => {
15126
14791
  _close && _close(callback);
15127
14792
  });
15128
14793
  };
15129
14794
  } else {
15130
14795
  options.https = false;
15131
14796
  }
15132
- caddy = new CaddyInstant();
15133
- caddy.run(source, target, {
14797
+ const instance = new CaddyInstant();
14798
+ caddy = instance;
14799
+ instance.run(source, target, {
15134
14800
  base,
15135
14801
  ...options
15136
14802
  }).then(() => {
@@ -15139,12 +14805,20 @@ var unpluginFactory = (options) => ({
15139
14805
  consola.success(` ${import_picocolors2.default.green("\u279C")} ${import_picocolors2.default.bold("run caddy reverse proxy success")}: ${colorUrl(`${options.https ? "https" : "http"}://${target}${base}`)}`);
15140
14806
  });
15141
14807
  }).catch((e) => {
14808
+ if (caddy === instance)
14809
+ caddy = void 0;
14810
+ if (e instanceof PrivilegeDeniedError) {
14811
+ markPrivilegeDenied();
14812
+ consola.warn("reverse proxy skipped: administrator permission was not granted.");
14813
+ consola.info("Restart the dev server to enable it again.");
14814
+ return;
14815
+ }
15142
14816
  throw e;
15143
14817
  });
15144
14818
  },
15145
14819
  async rspack(compiler) {
15146
14820
  var _a4, _b3, _c2, _d2;
15147
- if (import_node_process8.default.env.NODE_ENV !== "development")
14821
+ if (import_node_process9.default.env.NODE_ENV !== "development")
15148
14822
  return;
15149
14823
  const {
15150
14824
  enable = true,
@@ -15169,9 +14843,10 @@ var unpluginFactory = (options) => ({
15169
14843
  }))) == null ? void 0 : _b3.content) == null ? void 0 : _c2.server
15170
14844
  };
15171
14845
  const source = `${devServer.host}:${devServer.port}`;
14846
+ if (isPrivilegeDenied())
14847
+ return;
15172
14848
  if (caddy)
15173
14849
  return;
15174
- caddy = new CaddyInstant();
15175
14850
  let base = "/";
15176
14851
  const publicPath = (_d2 = compiler.options.output) == null ? void 0 : _d2.publicPath;
15177
14852
  if (typeof publicPath === "string" && publicPath) {
@@ -15181,13 +14856,23 @@ var unpluginFactory = (options) => ({
15181
14856
  base = `/${base}`;
15182
14857
  if (base !== "/" && !base.endsWith("/"))
15183
14858
  base = `${base}/`;
15184
- caddy.run(source, target, {
14859
+ const instance = new CaddyInstant();
14860
+ caddy = instance;
14861
+ instance.run(source, target, {
15185
14862
  base,
15186
14863
  ...options
15187
14864
  }).then(async () => {
15188
14865
  await printForwardProxy();
15189
14866
  consola.success(` ${import_picocolors2.default.green("\u279C")} ${import_picocolors2.default.bold("run caddy reverse proxy success")}: ${colorUrl(`${options.https ? "https" : "http"}://${target}${base}`)}`);
15190
14867
  }).catch((e) => {
14868
+ if (caddy === instance)
14869
+ caddy = void 0;
14870
+ if (e instanceof PrivilegeDeniedError) {
14871
+ markPrivilegeDenied();
14872
+ consola.warn("reverse proxy skipped: administrator permission was not granted.");
14873
+ consola.info("Restart the dev server to enable it again.");
14874
+ return;
14875
+ }
15191
14876
  throw e;
15192
14877
  });
15193
14878
  }