import "./src/bootstrap/async-local-storage-polyfill"; import { createServer } from "node:http"; import next from "next"; import { WebSocketServer } from "ws"; import { getConfig } from "./src/lib/config/load"; import { migrateOnBoot } from "./src/lib/db/client"; import { syncAuthFromConfig } from "./src/lib/auth/sync"; import { reconcileOrphanedRuns } from "./src/lib/runner/engine"; import { killAllRuns } from "./src/lib/runner/registry"; import { attachWsServer, authenticateUpgrade } from "./src/lib/ws/server"; const dev = process.env.NODE_ENV !== "production"; const { config } = getConfig(); const port = Number(process.env.PORT ?? config.server.port); const hostname = process.env.HOST ?? config.server.host; migrateOnBoot(); syncAuthFromConfig(); reconcileOrphanedRuns(); const app = next({ dev, hostname, port }); const handle = app.getRequestHandler(); app.prepare().then(() => { const httpServer = createServer((req, res) => { handle(req, res); }); const wss = new WebSocketServer({ noServer: true }); attachWsServer(wss); httpServer.on("upgrade", (req, socket, head) => { const { pathname } = new URL(req.url ?? "/", "http://internal"); if (pathname !== "/ws/runs") { socket.destroy(); return; } authenticateUpgrade(req) .then((ok) => { if (!ok) { socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n"); socket.destroy(); return; } wss.handleUpgrade(req, socket, head, (ws) => { wss.emit("connection", ws, req); }); }) .catch(() => socket.destroy()); }); httpServer.listen(port, hostname, () => { console.log( `> triggershell ready on http://${hostname}:${port} (${dev ? "development" : "production"})`, ); }); const shutdown = (signal: string) => { console.log(`> received ${signal}, shutting down...`); killAllRuns(); httpServer.close(() => process.exit(0)); // Force-exit if graceful shutdown hangs (e.g. a stuck WS connection). setTimeout(() => process.exit(1), 5000).unref(); }; process.on("SIGTERM", () => shutdown("SIGTERM")); process.on("SIGINT", () => shutdown("SIGINT")); });