From f6fcf4dbb6b6d6064195ff986ff87b6f5fe01375 Mon Sep 17 00:00:00 2001 From: Gilles Soulier Date: Fri, 5 Jun 2026 04:15:42 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20entr=C3=A9e=20serveur=20(Hono=20+=20Web?= =?UTF-8?q?Socket=20/api/ws=20+=20worker)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- server/index.ts | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 server/index.ts diff --git a/server/index.ts b/server/index.ts new file mode 100644 index 0000000..d56efe1 --- /dev/null +++ b/server/index.ts @@ -0,0 +1,41 @@ +// 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();