UNPKG

@simplito/privmx-webendpoint

Version:

PrivMX Web Endpoint library

271 lines (270 loc) 10.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EventManager = exports.ConnectionEventsManager = exports.InboxEventsManager = exports.StoreEventsManager = exports.ThreadEventsManager = exports.BaseEventManager = void 0; class BaseEventManager { _listeners; // event tag - "event@channel" get listeners() { return this._listeners; } channels; constructor() { this._listeners = new Map(); this.channels = new Set(); } /** * Checks whether the user is subscribed to given channel * @param channel Channel * @returns {boolean} `boolean` */ isSubscribedToChannel(channel) { return this.channels.has(channel); } hasEventsOnChannel(channel) { return (Array.from(this._listeners.keys()).findIndex((listenerTag) => listenerTag.split('@')[1] === channel) !== -1); } /** * Removes an event listeners from given `channel` and `eventType` * @param {Channel} channel channel * @param {string} eventType type of the event * @param {function} callback callback function */ removeEventListener = (channel, eventType, callback) => { const eventTag = `${eventType}@${channel}`; if (this._listeners.has(eventTag)) { const channelCallbacks = this._listeners.get(eventTag); const newCallback = channelCallbacks.filter((cb) => cb !== callback); if (newCallback.length === 0) { this._listeners.delete(eventTag); } else { this._listeners.set(eventTag, newCallback); } if (!this.hasEventsOnChannel(channel)) { this.channels.delete(channel); } } }; /** * Removes all listeners from given channel * @param {Channel} channel channel * @returns {void} */ removeChannelEvents = (channel) => { const listenersToRemove = Array.from(this._listeners.keys()).filter((listenerTag) => listenerTag.split('@')[1] === channel); listenersToRemove.forEach((listenerTag) => { this._listeners.delete(listenerTag); }); }; dispatchEvent(event) { if (event.type == 'libConnected' || event.type == 'libDisconnected' || event.type == 'libPlatformDisconnected') { event.channel = `connection/${event.connectionId}`; } const eventTag = `${event.type}@${event.channel}`; if (this._listeners.has(eventTag)) { const callbacks = this._listeners.get(eventTag); if (callbacks) { callbacks.forEach((callback) => callback(event)); } } } /** * Add an event listeners on given channel and eventType * @param {Channel} channel channel * @param {string} eventType type of the event * @param {function} callback callback function * @returns {function} function to remove the event listeners */ addEventListener = (channel, eventType, callback) => { const eventTag = `${eventType}@${channel}`; if (this._listeners.has(eventTag)) { this._listeners.get(eventTag).push(callback); } else { this._listeners.set(eventTag, [callback]); } this.channels.add(channel); return () => { this.removeEventListener(channel, eventType, callback); }; }; addContainerListener = async (channel, eventType, callback) => { if (!this.isSubscribedToChannel(channel)) { await this.subscribeForModuleEvents(); } const removeListener = this.addEventListener(channel, eventType, callback); return async () => { removeListener(); if (!this.hasEventsOnChannel(channel)) { await this.unsubscribeFromModuleEvents(); } }; }; addContainerElementListener = async (containerId, channel, eventType, callback) => { if (!this.isSubscribedToChannel(channel)) { await this.subscribeForModuleElementsEvents(containerId); } const removeListener = this.addEventListener(channel, eventType, callback); return async () => { removeListener(); if (!this.hasEventsOnChannel(channel)) { await this.unsubscribeFromModuleElementsEvents(containerId); } }; }; } exports.BaseEventManager = BaseEventManager; class ThreadEventsManager extends BaseEventManager { threadApi; constructor(threadApi) { super(); this.threadApi = threadApi; } subscribeForModuleEvents() { return this.threadApi.subscribeForThreadEvents(); } subscribeForModuleElementsEvents(id) { return this.threadApi.subscribeForMessageEvents(id); } unsubscribeFromModuleEvents() { return this.threadApi.unsubscribeFromThreadEvents(); } unsubscribeFromModuleElementsEvents(id) { return this.threadApi.unsubscribeFromMessageEvents(id); } async onThreadEvent(handler) { const channel = 'thread'; return this.addContainerListener(channel, handler.event, handler.callback); } async onMessageEvent(threadId, handler) { const channel = `thread/${threadId}/messages`; return this.addContainerElementListener(threadId, channel, handler.event, handler.callback); } } exports.ThreadEventsManager = ThreadEventsManager; class StoreEventsManager extends BaseEventManager { storeApi; constructor(storeApi) { super(); this.storeApi = storeApi; } subscribeForModuleEvents() { return this.storeApi.subscribeForStoreEvents(); } subscribeForModuleElementsEvents(id) { return this.storeApi.subscribeForFileEvents(id); } unsubscribeFromModuleEvents() { return this.storeApi.unsubscribeFromStoreEvents(); } unsubscribeFromModuleElementsEvents(id) { return this.storeApi.unsubscribeFromFileEvents(id); } async onStoreEvent(handler) { const channel = 'store'; return this.addContainerListener(channel, handler.event, handler.callback); } async onFileEvent(storeId, handler) { const channel = `store/${storeId}/files`; return this.addContainerElementListener(storeId, channel, handler.event, handler.callback); } } exports.StoreEventsManager = StoreEventsManager; class InboxEventsManager extends BaseEventManager { inboxApi; constructor(inboxApi) { super(); this.inboxApi = inboxApi; } subscribeForModuleEvents() { return this.inboxApi.subscribeForInboxEvents(); } subscribeForModuleElementsEvents(id) { return this.inboxApi.subscribeForEntryEvents(id); } unsubscribeFromModuleEvents() { return this.inboxApi.unsubscribeFromInboxEvents(); } unsubscribeFromModuleElementsEvents(id) { return this.inboxApi.unsubscribeFromEntryEvents(id); } async onInboxEvent(handler) { const channel = 'inbox'; return this.addContainerListener(channel, handler.event, handler.callback); } async onEntryEvent(inboxId, handler) { const channel = `inbox/${inboxId}/entries`; return this.addContainerElementListener(inboxId, channel, handler.event, handler.callback); } } exports.InboxEventsManager = InboxEventsManager; class ConnectionEventsManager extends BaseEventManager { connectionId; //Connection events don't have subscribe functions subscribeForModuleEvents() { return new Promise((resolve) => resolve()); } subscribeForModuleElementsEvents() { return new Promise((resolve) => resolve()); } unsubscribeFromModuleEvents() { return new Promise((resolve) => resolve()); } unsubscribeFromModuleElementsEvents() { return new Promise((resolve) => resolve()); } constructor(connectionId) { super(); this.connectionId = connectionId; } async onConnectionEvent(handler) { const channel = `connection/${this.connectionId}`; const removeListener = this.addContainerListener(channel, handler.event, handler.callback); return removeListener; } } exports.ConnectionEventsManager = ConnectionEventsManager; class EventManager { _isEventLoopRunning = false; dispatchers = []; eventsQueue = null; constructor() { } listenForEvents() { if (this.eventsQueue) { this.eventsQueue.waitEvent().then((event) => { this.onEvent(event); this.listenForEvents(); }); } } static startEventLoop(eventQueue) { const manager = new EventManager(); manager.eventsQueue = eventQueue; manager._isEventLoopRunning = true; manager.eventsQueue.waitEvent().then((event) => { if (!manager._isEventLoopRunning) return; manager.onEvent(event); manager.listenForEvents(); }); return manager; } stopEventLoop() { this._isEventLoopRunning = false; } removeAllDispatchers = () => { this.dispatchers = []; }; onEvent(event) { this.dispatchers.forEach((cb) => cb(event)); } registerDispatcher(manager) { this.dispatchers.push((e) => manager.dispatchEvent(e)); } getThreadEventManager(threadApi) { const manager = new ThreadEventsManager(threadApi); this.registerDispatcher(manager); return manager; } getStoreEventManager(storeApi) { const manager = new StoreEventsManager(storeApi); this.registerDispatcher(manager); return manager; } getInboxEventManager(inboxApi) { const manager = new InboxEventsManager(inboxApi); this.registerDispatcher(manager); return manager; } getConnectionEventManager(connectionId) { const manager = new ConnectionEventsManager(connectionId); this.registerDispatcher(manager); return manager; } } exports.EventManager = EventManager;