/** * Runs once, in its own process, before any spec: confirm every shard's * containerized half is answering, then clear its gateway mock. * * Seeding is NOT here any more. The order is load-bearing — * `seed-users.sql` names its prerequisites as "created by the API's always-on * boot seeders" (iam.organizations / units / positions) — and the freight app * now boots inside the vitest *workers*, which this process cannot reach. So the * template database is seeded once by `scripts/prepare-shards.mjs` (boot the app * → boot seeders → SQL fixtures) and each shard is a clone of it. */ const SHARDS = Number(process.env.IT_SHARDS ?? 1); const PAYMENT_BASE = Number(process.env.IT_PAYMENT_PORT_BASE ?? 3131); const GATEWAY_BASE = Number(process.env.IT_GATEWAY_PORT_BASE ?? 4600); async function waitFor(label: string, url: string, attempts = 60): Promise { for (let i = 0; i < attempts; i++) { try { const res = await fetch(url); if (res.ok) return; } catch { /* not up yet */ } await new Promise((r) => setTimeout(r, 2000)); } throw new Error(`${label} never became healthy at ${url}`); } export async function setup(): Promise { const shards = Array.from({ length: SHARDS }, (_, i) => i); await Promise.all( shards.flatMap((i) => [ waitFor(`payment-api (shard ${i})`, `http://localhost:${PAYMENT_BASE + i}/health`), waitFor(`gateway-mock (shard ${i})`, `http://localhost:${GATEWAY_BASE + i}/__control/health`), ]), ); await Promise.all( shards.map((i) => fetch(`http://localhost:${GATEWAY_BASE + i}/__control/reset`, { method: "POST" }), ), ); console.log(`it: ${SHARDS} shard(s) ready`); }