chore: split local development services

This commit is contained in:
2026-09-19 12:22:22 +08:00
parent 8d35318c7e
commit 09f3784e73
6 changed files with 72 additions and 59 deletions
+2 -21
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env node
// dev-backend: 启动 PostgreSQL 依赖,并连接宿主机 native browser gateway 后运行 control-plane。
import { spawn, spawnSync } from "node:child_process";
// backend: 运行带 Air 热加载的 Go control-plane。
import { spawn } from "node:child_process";
import { readFileSync, existsSync } from "node:fs";
import { fileURLToPath } from "node:url";
import path from "node:path";
@@ -37,25 +37,6 @@ if (!overrides.LOG_LEVEL) overrides.LOG_LEVEL = "debug";
if (!overrides.NATIVE_GATEWAY_ENDPOINT) overrides.NATIVE_GATEWAY_ENDPOINT = "http://127.0.0.1:8081";
const env = { ...process.env, ...overrides };
const compose = spawnSync(
"docker",
["compose", "-f", "compose.yaml", "-f", "compose.dev.yaml", "up", "-d", "postgres"],
{ cwd: root, env, stdio: "inherit" },
);
if (compose.status !== 0) {
console.error("启动 PostgreSQL 容器失败,请确认 Docker 只用于数据库依赖。");
process.exit(compose.status ?? 1);
}
try {
const response = await fetch(`${overrides.NATIVE_GATEWAY_ENDPOINT}/healthz`, { signal: AbortSignal.timeout(2000) });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
} catch (error) {
console.error(`[dev-backend] native browser gateway 不可达:${overrides.NATIVE_GATEWAY_ENDPOINT} (${error})`);
console.error("请先以非 root 用户启动 browser_gateway.server.http 或对应的 systemd user service。");
process.exit(1);
}
const air = spawn("air", ["-c", ".air.toml", ...process.argv.slice(2)], {
cwd: root,
env,
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env node
// gateway: 直接运行开发用 native browser gateway;不依赖 systemd。
import { spawn } from "node:child_process";
import { existsSync, readFileSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
const root = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
function readEnvFile(filePath) {
if (!existsSync(filePath)) return {};
const values = {};
for (const line of readFileSync(filePath, "utf8").split("\n")) {
const match = /^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/.exec(line.trim());
if (match) values[match[1]] = match[2];
}
return values;
}
const rootEnv = readEnvFile(path.join(root, ".env"));
const gatewayEnvPath = process.env.CREATORHUB_BROWSER_GATEWAY_ENV
?? path.join(os.homedir(), ".config", "creatorhub", "browser-gateway.env");
const gatewayEnv = readEnvFile(gatewayEnvPath);
const env = { ...process.env, ...rootEnv, ...gatewayEnv };
if (!env.LISTEN_ADDR) env.LISTEN_ADDR = "0.0.0.0:8081";
const gateway = spawn("python3", ["-m", "browser_gateway.server.http"], {
cwd: root,
env,
stdio: "inherit",
});
for (const signal of ["SIGINT", "SIGTERM"]) {
process.on(signal, () => gateway.kill(signal));
}
gateway.on("exit", (code, signal) => {
if (signal) process.exit(1);
process.exit(code ?? 0);
});
-27
View File
@@ -1,27 +0,0 @@
#!/usr/bin/env node
// dev: 同时跑 dev:backendair 热加载 control-plane)与 dev:frontendvite HMR)。
// Ctrl-C 结束两个子进程。
import { spawn } from "node:child_process";
import path from "node:path";
import { fileURLToPath } from "node:url";
const root = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
const pnpm = process.env.npm_execpath || "pnpm";
const procs = [
spawn(pnpm, ["run", "dev:backend"], { cwd: root, stdio: "inherit" }),
spawn(pnpm, ["run", "dev:frontend"], { cwd: root, stdio: "inherit" }),
];
for (const signal of ["SIGINT", "SIGTERM"]) {
process.on(signal, () => {
for (const p of procs) p.kill(signal);
});
}
let remaining = procs.length;
for (const p of procs) {
p.on("exit", (code) => {
if (--remaining === 0) process.exit(code ?? 0);
});
}