// Starts the gateway: connects to every T3 host in the database, serves the watch API, and pushes // notifications. import { mkdirSync } from "node:fs"; import { dirname } from "node:path"; import { Apns } from "./apns.ts"; import { createRoutes } from "./api.ts"; import { loadConfig } from "./config.ts"; import { openDb } from "./db.ts"; import { Hub } from "./hub.ts"; import { Notifier } from "./notify.ts"; import { Pusher } from "./push.ts"; import { SummaryCache } from "./views.ts"; const HOST_SYNC_MS = 15_000; const TOKEN_CHECK_MS = 6 * 60 * 60_000; const log = (message: string) => console.log(`${new Date().toISOString()} ${message}`); const startedAt = new Date().toISOString(); const config = loadConfig(); mkdirSync(dirname(config.dbPath), { recursive: true }); const db = openDb(config.dbPath); const cache = new SummaryCache(log); const apns = config.apns ? new Apns(config.apns) : null; if (!apns) log("APNs is not configured. Pushes will only be logged."); const pusher = new Pusher(db, apns, log); const notifier = new Notifier(pusher.sendAll, cache, log); const hub = new Hub(db, { onThreadChange: notifier.onThreadChange, onStatus: notifier.onHostStatus, log }); hub.sync(); setInterval(() => hub.sync(), HOST_SYNC_MS); notifier.checkTokenExpiry(hub.rows()); setInterval(() => notifier.checkTokenExpiry(hub.rows()), TOKEN_CHECK_MS); const server = Bun.serve({ port: config.port, routes: createRoutes({ db, hub, cache, pusher, startedAt, log }), fetch: () => Response.json({ error: "Not found." }, { status: 404 }), }); log(`WristCode gateway listening on :${server.port} with ${hub.list().length} host(s)`); for (const signal of ["SIGINT", "SIGTERM"] as const) { process.on(signal, () => { log(`${signal}: shutting down`); void server.stop(); hub.stop(); apns?.close(); db.close(); process.exit(0); }); }