47 lines
1.3 KiB
JavaScript
47 lines
1.3 KiB
JavaScript
#!/usr/bin/env node
|
|||
|
|
/**
|
||
|
|
* Probe API /healthz and /readyz (worker heartbeat required for ready).
|
||
|
|
* Usage: node scripts/health.mjs
|
||
|
|
*/
|
||
|
|
import { DEV_API_PORT, DEV_PUBLIC_API_URL } from "./dev-ports.mjs";
|
||
|
|
import { loadRootEnv } from "./root-env.mjs";
|
||
|
|
|
||
|
|
const env = loadRootEnv(process.env);
|
||
|
|
const base = (
|
||
|
|
env.PUBLIC_API_URL ||
|
||
|
|
env.HEALTH_BASE_URL ||
|
||
|
|
DEV_PUBLIC_API_URL ||
|
||
|
|
`http://127.0.0.1:${DEV_API_PORT}`
|
||
|
|
).replace(/\/$/, "");
|
||
|
|
|
||
|
|
async function probe(path) {
|
||
|
|
const url = `${base}${path}`;
|
||
|
|
const res = await fetch(url);
|
||
|
|
const text = await res.text();
|
||
|
|
console.log(`${path} → ${res.status}`);
|
||
|
|
console.log(text);
|
||
|
|
if (!res.ok) {
|
||
|
|
try {
|
||
|
|
const body = JSON.parse(text);
|
||
|
|
if (typeof body?.reason === "string" && body.reason) {
|
||
|
|
console.error(`reason: ${body.reason}`);
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
/* ignore non-JSON */
|
||
|
|
}
|
||
|
|
throw new Error(`${path} failed with ${res.status}`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
await probe("/healthz");
|
||
|
|
await probe("/readyz");
|
||
|
|
console.log("ok");
|
||
|
|
} catch (err) {
|
||
|
|
console.error(err instanceof Error ? err.message : err);
|
||
|
|
console.error(
|
||
|
|
"Tip: npm run dev (or npm run dev:backend) starts api+worker. Compose is Postgres-only; /readyz needs a live host worker heartbeat. API-only (npm run dev:api) → 503 is expected.",
|
||
|
|
);
|
||
|
|
process.exit(1);
|
||
|
|
}
|