@simplito/privmx-webendpoint
Version:
PrivMX Web Endpoint library
271 lines (270 loc) • 10.1 kB
JavaScript
"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;