import { ServerWebSocket } from "bun"; import { WSData } from "../../../../../pkgs/core/server/create"; import { conns, wconns } from "./conn"; import { sendWS } from "../sync-handler"; import { SyncType } from "../type"; export const RoomList = class> { rooms = new Map>(); name = ""; constructor(name: string) { this.name = name; } joined(ws: ServerWebSocket) { const rooms = new Set>(); this.rooms.forEach((room) => { room.clients.forEach((_, roomws) => { if (roomws === ws) { rooms.add(room); } }); }); return rooms; } disconnect(ws: ServerWebSocket) { this.rooms.forEach((room) => { room.clients.forEach((_, roomws) => { if (roomws === ws) { room.leave({ ws }); } }); }); } async set( id: string, ws: ServerWebSocket, fn: (data: Partial) => Promise> ) { const room = this.room(id); if (room) { await room.set({ ws }, async (ws, data) => { return await fn(data); }); room.broadcastState("set", ws); } } room(id: string) { if (!id) { throw new Error("room id is empty"); } let room = this.rooms.get(id); if (!room) { this.rooms.set(id, new Room(this.name, id)); room = this.rooms.get(id); } return room as Room; } }; export class Room> { name = ""; id = ""; clients = new Map, Partial>(); constructor(name: string, id: string) { this.name = name; this.id = id; } findAll(where: Partial) { const clients = new Map, Partial>(); for (const [ws, data] of this.clients) { let match = true; for (const key in where) { if (data[key] !== where[key]) { match = false; break; } } if (match) clients.set(ws, data); } return clients; } async set( client: { ws?: ServerWebSocket; id?: string }, action: ( ws: ServerWebSocket, data: Partial ) => Promise> ) { const ws = this.identify(client); if (ws) { const data = this.clients.get(ws); if (data) { const newdata = await action(ws, data); this.clients.set(ws, newdata); } } } private identify(client: { ws?: ServerWebSocket; id?: string }) { let ws = null as ServerWebSocket | null; if (client.ws) { ws = client.ws; } else if (client.id) { const connws = conns.get(client.id)?.ws; if (connws) ws = connws; } return ws; } join(client: { ws?: ServerWebSocket; id?: string }) { const ws = this.identify(client); if (ws) { this.clients.set(ws, {}); this.broadcastState("join", ws); } } leave(client: { ws?: ServerWebSocket; id?: string }) { const ws = this.identify(client); if (ws) { this.clients.delete(ws); this.broadcastState("leave", ws); } } broadcastState = ( event_name: string, triggeredBy?: ServerWebSocket | null ) => { const clients: any = []; this.clients.forEach((data, ws) => { const client_id = wconns.get(ws); if (client_id) { const client = conns.get(client_id); if (client) clients.push({ user: { client_id, user_id: client.user?.id, username: client.user?.username, }, data, }); } }); this.clients.forEach((_, ws) => { sendWS(ws, { type: SyncType.Event, event: `activity`, data: { activity: event_name, room_id: this.id, clients }, }); }); }; }