import { Elysia } from "elysia"; import { ingest } from "./routes/pings"; import { monitors } from "./routes/monitors"; import { account } from "./routes/auth"; import { internal } from "./routes/internal"; import { channels } from "./routes/channels"; import { statusPages } from "./routes/status_pages"; import { incidents } from "./routes/incidents"; import { startRollupJob } from "./jobs/rollup"; import { migrate } from "./db"; import { SECURITY_HEADERS } from "../../shared/auth"; // Global safety net: never let an unhandled rejection take down the API process. // We'd rather log loudly and stay up than 502 every monitor on a single bug. process.on("unhandledRejection", (reason) => { console.error("[unhandledRejection]", reason); }); process.on("uncaughtException", (err) => { console.error("[uncaughtException]", err); }); await migrate(); await startRollupJob(); const elysia = new Elysia() .get("/", () => ({ name: "PingQL API", version: "1", docs: "https://pingql.com/docs", })) .use(account) .use(monitors) .use(channels) .use(statusPages) .use(incidents) .use(ingest) .use(internal); const server = Bun.serve({ port: 3001, async fetch(req) { const origin = req.headers.get("origin") || "*"; const corsHeaders: Record = { "access-control-allow-origin": origin, "access-control-allow-credentials": "true", "access-control-allow-methods": "GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS", "access-control-allow-headers": "Content-Type, Authorization", ...SECURITY_HEADERS, }; if (req.method === "OPTIONS") { return new Response(null, { status: 204, headers: corsHeaders }); } const res = await elysia.handle(req); for (const [k, v] of Object.entries(corsHeaders)) { res.headers.set(k, v); } return res; }, }); console.log(`PingQL API running at http://localhost:${server.port}`);