#!/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); }