ework-web 0.10.2 → 0.10.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/package.json +1 -1
- package/src/daemon-deploy.ts +11 -7
- package/src/index.ts +19 -13
- package/src/static/daemon-mgr.js +5 -0
package/package.json
CHANGED
package/src/daemon-deploy.ts
CHANGED
|
@@ -78,14 +78,16 @@ function buildEnvBlock(env: Map<string, string>, target: DeployTarget): string {
|
|
|
78
78
|
if (v === undefined) continue;
|
|
79
79
|
lines.push(`${k}=${v}`);
|
|
80
80
|
}
|
|
81
|
-
|
|
81
|
+
const mysqlHost = String(target.mysqlHost).replace(/:\d+$/, "");
|
|
82
|
+
lines.push(`WORK_DB_HOST=${mysqlHost}`);
|
|
82
83
|
lines.push(`DAEMON_PORT=${String(target.daemonPort ?? 3101)}`);
|
|
83
84
|
lines.push(`DAEMON_HOST=0.0.0.0`);
|
|
84
85
|
lines.push(`DAEMON_ENV=production`);
|
|
85
86
|
return lines.join("\n");
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
function buildSetupScript(envBlock: string, daemonPort: number): string {
|
|
89
|
+
function buildSetupScript(envBlock: string, daemonPort: number, mysqlHostRaw: string, mysqlPort: string): string {
|
|
90
|
+
const mysqlHost = mysqlHostRaw.replace(/:\d+$/, "");
|
|
89
91
|
return [
|
|
90
92
|
"set -e",
|
|
91
93
|
`command -v npm >/dev/null 2>&1 || { curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash -; sudo apt-get install -y nodejs; }`,
|
|
@@ -95,9 +97,11 @@ function buildSetupScript(envBlock: string, daemonPort: number): string {
|
|
|
95
97
|
`mkdir -p "$HOME/.local/lib"`,
|
|
96
98
|
`npm config set prefix "$HOME/.local/lib"`,
|
|
97
99
|
`grep -q '.local/lib/bin' "$HOME/.bashrc" 2>/dev/null || echo 'export PATH="$HOME/.local/lib/bin:$HOME/.bun/bin:$PATH"' >> "$HOME/.bashrc"`,
|
|
98
|
-
`echo "[1/
|
|
100
|
+
`echo "[1/5] checking MySQL connectivity to ${mysqlHost}:${mysqlPort}..."`,
|
|
101
|
+
`timeout 5 bash -c "echo > /dev/tcp/${mysqlHost}/${mysqlPort}" 2>/dev/null && echo "MySQL port reachable" || { echo "MySQL UNREACHABLE at ${mysqlHost}:${mysqlPort} — daemon will fail to connect"; exit 1; }`,
|
|
102
|
+
`echo "[2/5] installing ework-aio..."`,
|
|
99
103
|
`npm install -g ework-aio`,
|
|
100
|
-
`echo "[
|
|
104
|
+
`echo "[3/5] writing daemon config..."`,
|
|
101
105
|
`mkdir -p ~/.local/share/ework-aio/ework-daemon`,
|
|
102
106
|
`REMOTE_IP=$(hostname -I 2>/dev/null | awk '{print $1}')`,
|
|
103
107
|
`DAEMON_ENDPOINT_LINE=""`,
|
|
@@ -106,9 +110,9 @@ function buildSetupScript(envBlock: string, daemonPort: number): string {
|
|
|
106
110
|
envBlock,
|
|
107
111
|
`EWORK_DAEMON_ENV_EOF`,
|
|
108
112
|
`echo "$DAEMON_ENDPOINT_LINE"; } > ~/.local/share/ework-aio/ework-daemon/.env`,
|
|
109
|
-
`echo "[
|
|
113
|
+
`echo "[4/5] starting daemon..."`,
|
|
110
114
|
`ework-aio start daemon`,
|
|
111
|
-
`echo "[
|
|
115
|
+
`echo "[5/5] verifying daemon is alive..."`,
|
|
112
116
|
`sleep 2`,
|
|
113
117
|
`curl -sf --max-time 3 http://127.0.0.1:${String(daemonPort)}/api/status >/dev/null 2>&1 && echo "DAEMON_ALIVE" || echo "DAEMON_WARNING: status check failed (may need a moment to boot)"`,
|
|
114
118
|
`echo DAEMON_STARTED`,
|
|
@@ -132,7 +136,7 @@ export async function deployRemoteDaemon(opts: DeployOpts): Promise<DeployResult
|
|
|
132
136
|
}
|
|
133
137
|
const env = parseEnvFile(envContent);
|
|
134
138
|
const envBlock = buildEnvBlock(env, opts);
|
|
135
|
-
const script = buildSetupScript(envBlock, opts.daemonPort ?? 3101);
|
|
139
|
+
const script = buildSetupScript(envBlock, opts.daemonPort ?? 3101, opts.mysqlHost, String(env.get("WORK_DB_PORT") ?? "3306"));
|
|
136
140
|
|
|
137
141
|
const args = [
|
|
138
142
|
"ssh",
|
package/src/index.ts
CHANGED
|
@@ -973,25 +973,31 @@ async function handle(req: Request, url: URL, ip: string, ctx: { authed: boolean
|
|
|
973
973
|
if (targets.length === 0 || !mysqlHost) {
|
|
974
974
|
return json({ ok: false, error: "至少需要一个目标 + mysqlHost" }, 400);
|
|
975
975
|
}
|
|
976
|
-
if (targets.length === 1) {
|
|
977
|
-
const [single] = targets;
|
|
978
|
-
if (!single) return json({ ok: false, error: "no target" }, 400);
|
|
979
|
-
const result = await deployRemoteDaemon({ ...single, timeoutMs });
|
|
980
|
-
return json(result, result.ok ? 200 : 422);
|
|
981
|
-
}
|
|
982
976
|
|
|
983
977
|
const { readable, writable } = new TransformStream();
|
|
984
978
|
const writer = writable.getWriter();
|
|
985
979
|
const enc = new TextEncoder();
|
|
986
980
|
const send = (s: string) => writer.write(enc.encode(`data: ${JSON.stringify(s)}\n\n`));
|
|
987
981
|
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
982
|
+
if (targets.length === 1) {
|
|
983
|
+
const [single] = targets;
|
|
984
|
+
send(`▶ 部署到 ${single!.sshHost}:${single!.daemonPort ?? 3101}(超时 ${timeoutMs / 1000}s)...\n\n`);
|
|
985
|
+
deployRemoteDaemon({ ...single!, timeoutMs, onOutput: (chunk) => send(chunk) })
|
|
986
|
+
.then((result) => {
|
|
987
|
+
send(`\n${result.ok ? "✓ 成功" : "✗ 失败"}: ${result.ok ? "daemon 已部署" : (result.error || "未知错误")}\n`);
|
|
988
|
+
if (result.output) send(result.output);
|
|
989
|
+
})
|
|
990
|
+
.catch((e) => send(`\n✗ 异常: ${e instanceof Error ? e.message : String(e)}\n`))
|
|
991
|
+
.finally(() => writer.close());
|
|
992
|
+
} else {
|
|
993
|
+
deployBatch(targets, timeoutMs, (label, chunk) => send(`[${label}] ${chunk}`))
|
|
994
|
+
.then((results) => {
|
|
995
|
+
const ok = [...results.values()].every((r) => r.ok);
|
|
996
|
+
send(`\n${ok ? "ALL OK" : "SOME FAILED"}: ${[...results.entries()].map(([k, v]) => `${k}=${v.ok ? "✓" : "✗"}`).join(", ")}`);
|
|
997
|
+
})
|
|
998
|
+
.catch((e) => send(`ERROR: ${e instanceof Error ? e.message : String(e)}`))
|
|
999
|
+
.finally(() => writer.close());
|
|
1000
|
+
}
|
|
995
1001
|
|
|
996
1002
|
return new Response(readable, {
|
|
997
1003
|
headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" },
|
package/src/static/daemon-mgr.js
CHANGED
|
@@ -247,6 +247,11 @@
|
|
|
247
247
|
if (deployBtn) deployBtn.disabled = false;
|
|
248
248
|
return;
|
|
249
249
|
}
|
|
250
|
+
if (/^(127\.|localhost$|0\.0\.0\.0$)/.test(mysqlHost)) {
|
|
251
|
+
setDeployResult('✗ MySQL 主机必须是远程机器可达的地址(不能是 ' + mysqlHost + ')。请使用 LAN IP,如 192.168.x.x', 'err');
|
|
252
|
+
if (deployBtn) deployBtn.disabled = false;
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
250
255
|
|
|
251
256
|
deployResultEl.textContent = '';
|
|
252
257
|
appendDeployLog('▶ 部署 ' + targets.length + ' 个目标(超时 ' + (timeoutMs / 1000) + 's/个)...\n\n');
|