sync-playground/server.ts

60 lines
1.5 KiB
TypeScript

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<WebSocket>();
// 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 });