UNPKG

ziko

Version:

A versatile JavaScript library offering a rich set of Hyperscript Based UI components, advanced mathematical utilities, interactivity ,animations, client side routing and more ...

84 lines (81 loc) 3.04 kB
class UseIPC { #channel; #eventData; #handlers; #uuid; #subscribers; #currentRooms; constructor(name = "") { this.#channel = new BroadcastChannel(name); this.#eventData = new Map(); this.#handlers = new Map(); // Map<event, Array<{fn, rooms}>> this.#uuid = "ziko-channel:" + (Math.random()*10e16); // To Be Replaced by UUID this.#subscribers = new Set([this.#uuid]); this.#currentRooms = new Set(); this.#channel.addEventListener("message", (e) => { const { last_sent_event, userId, eventData, rooms } = e.data; if (userId === this.#uuid) return; // ignore own messages // broadcast if no rooms, else check intersection if (rooms && rooms.length && !rooms.some(r => this.#currentRooms.has(r))) return; this.#subscribers.add(userId); this.#eventData = new Map(eventData); const handlersList = this.#handlers.get(last_sent_event); if (!handlersList) return; handlersList.forEach(({ fn, rooms: handlerRooms }) => { // trigger if listener has no room filter, or intersects subscriber rooms if (!handlerRooms || handlerRooms.length === 0 || !rooms || rooms.some(r => handlerRooms.includes(r))) { fn(this.#eventData.get(last_sent_event)); } }); }); } emit(event, data, rooms) { this.#eventData.set(event, data); if(typeof rooms === 'string') rooms = [rooms] this.#channel.postMessage({ eventData: Array.from(this.#eventData.entries()), last_sent_event: event, userId: this.#uuid, rooms: rooms && rooms.length ? rooms : undefined }); return this; } on(event, handler = console.log, rooms) { if (!this.#handlers.has(event)) this.#handlers.set(event, []); if(typeof rooms === 'string') rooms = [rooms] this.#handlers.get(event).push({ fn: handler, rooms }); return this; } off(event, handler) { if (!this.#handlers.has(event)) return this; this.#handlers.set( event, this.#handlers.get(event).filter(h => h.fn !== handler) ); return this; } once(event, handler, rooms) { const wrapper = (data) => { handler(data); this.off(event, wrapper); }; this.on(event, wrapper, rooms); return this; } join(...rooms) { rooms.forEach(r => this.#currentRooms.add(r)); return this; } leave(...rooms) { if (!rooms.length) this.#currentRooms.clear(); else rooms.forEach(r => this.#currentRooms.delete(r)); return this; } close() { this.#channel.close(); return this; } } const useIPC = (name) => new UseIPC(name); export { useIPC };