#!/usr/bin/env node /** * Wait until DATABASE_URL Postgres accepts TCP connections. * Works with native Postgres or Docker-mapped ports (no docker CLI required). * * Usage: node scripts/wait-postgres.mjs */ import net from "node:net"; import { setTimeout as delay } from "node:timers/promises"; import { loadRootEnv } from "./root-env.mjs"; const maxAttempts = Number(process.env.DESCRYBE_DB_WAIT_ATTEMPTS || 60); const sleepMs = Number(process.env.DESCRYBE_DB_WAIT_MS || 1000); const env = loadRootEnv(process.env); const databaseUrl = env.DATABASE_URL; if (!databaseUrl || !String(databaseUrl).trim()) { console.error( "[db] DATABASE_URL is required (root .env or shell; see .env.example)", ); process.exit(1); } function parsePostgresTarget(urlStr) { let u; try { u = new URL(urlStr); } catch { console.error("[db] DATABASE_URL is not a valid URL"); process.exit(1); } const protocol = (u.protocol || "").replace(/:$/, ""); if (protocol !== "postgres" && protocol !== "postgresql") { console.error(`[db] DATABASE_URL must be postgres(ql)://… (got ${protocol})`); process.exit(1); } const host = u.hostname || "127.0.0.1"; const port = Number(u.port || 5432); if (!Number.isFinite(port) || port <= 0) { console.error("[db] DATABASE_URL has an invalid port"); process.exit(1); } return { host, port }; } function canConnect(host, port) { return new Promise((resolve) => { const socket = net.connect({ host, port }); const done = (ok) => { socket.removeAllListeners(); socket.destroy(); resolve(ok); }; socket.setTimeout(2000); socket.once("connect", () => done(true)); socket.once("timeout", () => done(false)); socket.once("error", () => done(false)); }); } const { host, port } = parsePostgresTarget(databaseUrl); console.log(`[db] waiting for Postgres at ${host}:${port}`); for (let i = 1; i <= maxAttempts; i++) { if (await canConnect(host, port)) { console.log(`[db] postgres ready (attempt ${i})`); process.exit(0); } process.stdout.write(`[db] waiting for postgres… (${i}/${maxAttempts})\r`); await delay(sleepMs); } console.error("\n[db] postgres did not become ready in time"); console.error(`Check: DATABASE_URL host ${host}:${port} is up and listening`); console.error("Native: sudo systemctl status postgresql"); console.error("Docker (optional local): docker compose ps && docker compose logs postgres"); process.exit(1);