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