forked from trypsynth/qn
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.ts
More file actions
60 lines (53 loc) · 1.61 KB
/
main.ts
File metadata and controls
60 lines (53 loc) · 1.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import { serveDir } from "serveDir";
import * as Y from "yjs";
const PORT = 8000;
const SAVE_FILE = "yjs_state.bin";
const doc = new Y.Doc();
const connections = new Set<WebSocket>();
try {
const saved = await Deno.readFile(SAVE_FILE);
Y.applyUpdate(doc, saved);
} catch (_) {
// This just means no note has been created yet, we don't care.
}
doc.on("update", async (update: Uint8Array, origin) => {
for (const socket of connections) {
if (socket !== origin && socket.readyState === WebSocket.OPEN) {
socket.send(update);
}
}
const fullState = Y.encodeStateAsUpdate(doc);
await Deno.writeFile(SAVE_FILE, fullState);
});
function handleWebSocket(req: Request): Response {
const { socket, response } = Deno.upgradeWebSocket(req);
connections.add(socket);
const sendState = () => {
if (socket.readyState === WebSocket.OPEN) {
socket.send(Y.encodeStateAsUpdate(doc));
}
};
if (socket.readyState === WebSocket.OPEN) {
sendState();
} else {
socket.addEventListener("open", sendState, { once: true });
}
socket.onmessage = (event: MessageEvent) => {
if (typeof event.data !== "string") {
const update = new Uint8Array(event.data as ArrayBuffer);
Y.applyUpdate(doc, update, socket);
}
};
const cleanup = () => connections.delete(socket);
socket.onclose = cleanup;
socket.onerror = cleanup;
return response;
}
const handler = (req: Request) => {
const { pathname } = new URL(req.url);
if (pathname === "/ws") {
return handleWebSocket(req);
}
return serveDir(req, { fsRoot: "public", quiet: true });
};
Deno.serve({ port: PORT }, handler);