import { env } from "@/lib/env"; import { router } from "./router"; import type { Server } from "bun"; export class WebServer { private static server: Server | null = null; private static heartbeatInterval: ReturnType | null = null; public static start(port?: number) { this.server = Bun.serve({ port: port ?? (typeof env.PORT === "string" ? parseInt(env.PORT) : 3000), fetch: (req, server) => { const url = new URL(req.url); if (url.pathname === "/ws") { // Upgrade the request to a WebSocket // We pass dummy data for now if (server.upgrade(req, { data: undefined })) { return undefined; } return new Response("WebSocket upgrade failed", { status: 500 }); } return router(req); }, websocket: { open(ws) { // console.log("ws: client connected"); ws.subscribe("status-updates"); ws.send(JSON.stringify({ type: "WELCOME", message: "Connected to Aurora WebSocket" })); }, message(ws, message) { // Handle incoming messages if needed }, close(ws) { // console.log("ws: client disconnected"); ws.unsubscribe("status-updates"); }, }, }); console.log(`🌐 Web server listening on http://localhost:${this.server.port}`); // Start a heartbeat loop this.heartbeatInterval = setInterval(() => { if (this.server) { const uptime = process.uptime(); this.server.publish("status-updates", JSON.stringify({ type: "HEARTBEAT", data: { uptime, timestamp: Date.now() } })); } }, 5000); } public static stop() { if (this.heartbeatInterval) { clearInterval(this.heartbeatInterval); this.heartbeatInterval = null; } if (this.server) { this.server.stop(); console.log("🛑 Web server stopped"); this.server = null; } } public static get port(): number | undefined { return this.server?.port; } public static broadcastLog(type: string, message: string) { if (this.server) { this.server.publish("status-updates", JSON.stringify({ type: "LOG", data: { timestamp: new Date().toLocaleTimeString(), type, message } })); } } }