import express from "express"; import path from "path"; import { fileURLToPath } from "url"; import { sessionsRouter } from "./routes/sessions.js"; import { exportRouter } from "./routes/export.js"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); export function createApp() { const app = express(); app.use(express.json({ limit: "50mb" })); app.get("/api/health", (_req, res) => { res.json({ status: "ok" }); }); app.use("/api/sessions", sessionsRouter); app.use("/api/export", exportRouter); // Serve static client files in production const clientDist = path.resolve(__dirname, "../../dist/client"); app.use(express.static(clientDist)); app.get("*", (_req, res) => { res.sendFile(path.join(clientDist, "index.html")); }); return app; } export function startServer() { const PORT = parseInt(process.env.PORT || "3848", 10); const app = createApp(); const server = app.listen(PORT, "127.0.0.1", async () => { console.log(`Session Viewer API running on http://localhost:${PORT}`); if (process.env.SESSION_VIEWER_OPEN_BROWSER === "1") { const { default: open } = await import("open"); open(`http://localhost:${PORT}`); } }); // Graceful shutdown so tsx watch can restart cleanly function shutdown() { server.close(); } process.on("SIGINT", shutdown); process.on("SIGTERM", shutdown); return server; } // Only auto-start when run directly (not imported by tests) const thisFile = fileURLToPath(import.meta.url); const entryFile = process.argv[1]; if (entryFile && path.resolve(entryFile) === path.resolve(thisFile)) { startServer(); }