Route awareness messages between peers
This commit is contained in:
parent
93bb462ffa
commit
56aa8dc9bd
3 changed files with 66 additions and 4 deletions
55
src/awareness.test.ts
Normal file
55
src/awareness.test.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { describe, test, expect, beforeAll, afterAll } from "bun:test";
|
||||||
|
import type { Server } from "bun";
|
||||||
|
|
||||||
|
describe("awareness routing", () => {
|
||||||
|
let server: Server;
|
||||||
|
const PORT = 4042;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
// Import and start server on test port
|
||||||
|
process.env.PORT = String(PORT);
|
||||||
|
const mod = await import("./index");
|
||||||
|
server = mod.server;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
server?.stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("awareness message routes to other peers in same room", async () => {
|
||||||
|
const ws1 = new WebSocket(`ws://localhost:${PORT}/ws`);
|
||||||
|
const ws2 = new WebSocket(`ws://localhost:${PORT}/ws`);
|
||||||
|
|
||||||
|
const received: unknown[] = [];
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
new Promise(r => ws1.onopen = r),
|
||||||
|
new Promise(r => ws2.onopen = r),
|
||||||
|
]);
|
||||||
|
|
||||||
|
ws2.onmessage = (e) => {
|
||||||
|
received.push(JSON.parse(e.data));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Both join same room
|
||||||
|
ws1.send(JSON.stringify({ type: "join", room: "test" }));
|
||||||
|
ws2.send(JSON.stringify({ type: "join", room: "test" }));
|
||||||
|
|
||||||
|
await Bun.sleep(50);
|
||||||
|
|
||||||
|
// ws1 sends awareness
|
||||||
|
ws1.send(JSON.stringify({
|
||||||
|
type: "awareness",
|
||||||
|
data: { clientId: 1, cursor: { line: 10, col: 5 } }
|
||||||
|
}));
|
||||||
|
|
||||||
|
await Bun.sleep(50);
|
||||||
|
|
||||||
|
const awareness = received.find(m => m.type === "awareness");
|
||||||
|
expect(awareness).toBeDefined();
|
||||||
|
expect(awareness.data.cursor).toEqual({ line: 10, col: 5 });
|
||||||
|
|
||||||
|
ws1.close();
|
||||||
|
ws2.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
11
src/index.ts
11
src/index.ts
|
|
@ -14,7 +14,7 @@ function isValidRoomName(name: unknown): name is string {
|
||||||
return /^[a-zA-Z0-9_-]+$/.test(name);
|
return /^[a-zA-Z0-9_-]+$/.test(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bun.serve<WsData>({
|
export const server = Bun.serve<WsData>({
|
||||||
port: PORT,
|
port: PORT,
|
||||||
fetch(req, server) {
|
fetch(req, server) {
|
||||||
const url = new URL(req.url);
|
const url = new URL(req.url);
|
||||||
|
|
@ -77,6 +77,15 @@ Bun.serve<WsData>({
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "awareness": {
|
||||||
|
if (ws.data.room) {
|
||||||
|
const session = getSession(ws.data.room);
|
||||||
|
if (session && "data" in msg) {
|
||||||
|
session.broadcastAwareness(client, msg.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
close(ws) {
|
close(ws) {
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,7 @@ function isClientMessage(obj: unknown): obj is ClientMessage {
|
||||||
Array.isArray(msg.data) && msg.data.every((n) => typeof n === "number")
|
Array.isArray(msg.data) && msg.data.every((n) => typeof n === "number")
|
||||||
);
|
);
|
||||||
case "awareness":
|
case "awareness":
|
||||||
return (
|
return typeof msg.data === "object" && msg.data !== null;
|
||||||
Array.isArray(msg.data) && msg.data.every((n) => typeof n === "number")
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue