f6fcf4dbb6
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
// server/index.ts
|
|
import { serve } from "@hono/node-server";
|
|
import { Hono } from "hono";
|
|
import { WebSocketServer } from "ws";
|
|
import type { IncomingMessage } from "node:http";
|
|
import type { Duplex } from "node:stream";
|
|
import { env } from "./env.js";
|
|
import { runMigrations } from "./db/migrate.js";
|
|
import { api } from "./routes/index.js";
|
|
import { outputHub } from "./ws/outputHub.js";
|
|
import { startWorker } from "./jobs/worker.js";
|
|
|
|
env.requireMasterKey();
|
|
runMigrations();
|
|
|
|
const app = new Hono();
|
|
app.route("/api", api);
|
|
app.get("/health", (c) => c.json({ ok: true }));
|
|
|
|
const server = serve({ fetch: app.fetch, port: env.port }, (info) =>
|
|
console.log(`[server] http://localhost:${info.port}`),
|
|
);
|
|
|
|
// WebSocket: /api/ws/machines/:id/output
|
|
const wss = new WebSocketServer({ noServer: true });
|
|
server.on("upgrade", (req: IncomingMessage, socket: Duplex, head: Buffer) => {
|
|
const match = /^\/api\/ws\/machines\/([^/]+)\/output$/.exec(req.url ?? "");
|
|
if (!match) {
|
|
socket.destroy();
|
|
return;
|
|
}
|
|
const machineId = match[1]!;
|
|
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
const unsub = outputHub.subscribe(machineId, (chunk) => {
|
|
if (ws.readyState === ws.OPEN) ws.send(chunk);
|
|
});
|
|
ws.on("close", unsub);
|
|
});
|
|
});
|
|
|
|
startWorker();
|