59 lines
2.8 KiB
TypeScript
59 lines
2.8 KiB
TypeScript
import { closeSync, mkdirSync, openSync, readFileSync } from "node:fs";
|
|
import { resolve } from "node:path";
|
|
|
|
const webRoot = process.cwd();
|
|
const repoRoot = resolve(webRoot, "../..");
|
|
const stateDir = resolve(webRoot, ".state/tasktree-native");
|
|
const databaseEnvFile = process.env.TASKTREE_NATIVE_DATABASE_ENV_FILE;
|
|
const temporalAddress = process.env.TASKTREE_TEMPORAL_ADDRESS;
|
|
|
|
if (!databaseEnvFile) throw new Error("TASKTREE_NATIVE_DATABASE_ENV_FILE is required");
|
|
if (!temporalAddress) throw new Error("TASKTREE_TEMPORAL_ADDRESS is required");
|
|
|
|
function readEnvValue(path: string, key: string): string {
|
|
const line = readFileSync(path, "utf8")
|
|
.split(/\r?\n/u)
|
|
.find((candidate) => candidate.startsWith(`${key}=`));
|
|
if (!line) throw new Error(`${key} is missing from the configured env source`);
|
|
const raw = line.slice(key.length + 1).trim();
|
|
if ((raw.startsWith('"') && raw.endsWith('"')) || (raw.startsWith("'") && raw.endsWith("'"))) return raw.slice(1, -1);
|
|
return raw;
|
|
}
|
|
|
|
mkdirSync(stateDir, { recursive: true });
|
|
const logFd = openSync(resolve(stateDir, "services.log"), "a");
|
|
const databaseUrl = readEnvValue(databaseEnvFile, "DATABASE_URL");
|
|
const commonEnv = {
|
|
...process.env,
|
|
TASKTREE_DATABASE_URL: databaseUrl,
|
|
TASKTREE_TEMPORAL_ADDRESS: temporalAddress,
|
|
TASKTREE_TEMPORAL_NAMESPACE: process.env.TASKTREE_TEMPORAL_NAMESPACE ?? "unidesk",
|
|
TASKTREE_TEMPORAL_TASK_QUEUE: process.env.TASKTREE_TEMPORAL_TASK_QUEUE ?? "hwlab-v03-tasktree"
|
|
};
|
|
|
|
const children = [
|
|
Bun.spawn([process.execPath, "cmd/hwlab-tasktree-worker/main.ts"], { cwd: repoRoot, env: commonEnv, stdin: "ignore", stdout: logFd, stderr: logFd }),
|
|
Bun.spawn([process.execPath, "cmd/hwlab-tasktree-api/main.ts"], { cwd: repoRoot, env: { ...commonEnv, TASKTREE_API_HOST: "127.0.0.1", TASKTREE_API_PORT: "6673" }, stdin: "ignore", stdout: logFd, stderr: logFd }),
|
|
Bun.spawn([process.execPath, "x", "vite", "--config", "scripts/tasktree-native-vite.config.ts"], { cwd: webRoot, env: { ...process.env, HWLAB_TASKTREE_NATIVE_API_URL: "http://127.0.0.1:6673" }, stdin: "ignore", stdout: logFd, stderr: logFd })
|
|
];
|
|
|
|
process.stdout.write(`${JSON.stringify({ serviceId: "hwlab-tasktree-native", status: "started", pids: children.map((child) => child.pid), valuesPrinted: false })}\n`);
|
|
|
|
let stopping = false;
|
|
async function stop(): Promise<void> {
|
|
if (stopping) return;
|
|
stopping = true;
|
|
for (const child of children) child.kill("SIGTERM");
|
|
await Promise.allSettled(children.map((child) => child.exited));
|
|
closeSync(logFd);
|
|
process.exit(0);
|
|
}
|
|
|
|
process.once("SIGINT", stop);
|
|
process.once("SIGTERM", stop);
|
|
const exited = await Promise.race(children.map(async (child, index) => ({ index, code: await child.exited })));
|
|
if (!stopping) {
|
|
process.stderr.write(`${JSON.stringify({ serviceId: "hwlab-tasktree-native", status: "child-exited", ...exited })}\n`);
|
|
await stop();
|
|
}
|