import { Application, Router } from "@oak/oak"; import { Packet } from "./proto.ts"; import { CausalTree } from "./sync/ordt/causal-tree.ts"; import { PlainTextORDT } from "./sync/ordt/plain-text.ts"; const app = new Application(); const router = new Router(); const pt = new PlainTextORDT(); const sockets = new Set(); // simple websocket broadcast router.get("/api/connect", ctx => { const socket = ctx.upgrade(); sockets.add(socket); socket.addEventListener("message", event => { if (typeof event.data !== "string") return; const op = JSON.parse(event.data); pt.apply(op); // mutates op to strong const weakOp = CausalTree.toWeakOp(op); for (const other of sockets) { if (other === socket) continue; other.send(JSON.stringify({ t: "op", op: weakOp })); } }); socket.addEventListener("close", () => { sockets.delete(socket); }); const onReady = () => { socket.send( JSON.stringify({ t: "init", ops: pt.operations.map(it => CausalTree.toWeakOp(it)), you: crypto.randomUUID(), } satisfies Packet), ); }; if (socket.readyState === WebSocket.OPEN) { onReady(); } else { socket.addEventListener("open", () => onReady()); } }); router.get("/:path*", async ctx => { try { await ctx.send({ root: "./client", index: "index.html" }); } catch { // ignore } }); app.use(router.routes()); app.use(router.allowedMethods()); console.log("Listening at: http://127.0.0.1:3000/ ..."); app.listen({ port: 3000 });