UNPKG

dbl-utils

Version:

Utilities for dbl, adba and others projects

149 lines (148 loc) 6.26 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.EventHandler = void 0; /** * Class EventHandler to manage event subscriptions and dispatching. */ class EventHandler { /** * Construct an instance of EventHandler. */ constructor() { this.events = {}; this.patterns = []; this.cache = {}; } /** * Converts a wildcard string to a regular expression. * @param wildcardString - The wildcard string to convert. * @returns A RegExp object. */ wildcardToRegExp(wildcardString) { return new RegExp('^' + wildcardString.split('*').map(this.escapeRegExp).join('.*') + '$'); } /** * Escapes special characters in a string for use in a regular expression. * @param string - The string to escape. * @return The escaped string. */ escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } /** * Dispatches an event to all subscribed callbacks. * @param event - The event name to dispatch. * @param data - Data to be passed to the callback function. * @returns A promise resolved with an array of callback responses. */ dispatch(event, ...data) { return __awaiter(this, void 0, void 0, function* () { if (this.cache[event]) { const promises = this.cache[event].map(([callback, id]) => callback(...data, id)); return yield Promise.all(promises); } const callbacks = this.events[event] || []; const matchedPatterns = this.patterns.filter(({ pattern }) => pattern.test(event)).flatMap(p => p.callbacks); this.cache[event] = [...callbacks, ...matchedPatterns]; const allCallbacks = [...callbacks, ...matchedPatterns]; const promises = allCallbacks.map(([callback, id]) => callback(...data, id)); return yield Promise.all(promises); }); } /** * Subscribes to an event or a pattern of events. * @param eventString - The event name or pattern to subscribe to. * @param callback - The callback function to execute when the event is dispatched. * @param id - An identifier for the subscription, used for unsubscribing. */ subscribe(eventString, callback, id) { const events = eventString.split(/[\s,]+/); events.forEach(e => { if (e.includes('*')) { // Handle wildcard patterns const regex = this.wildcardToRegExp(e); const existingPattern = this.patterns.find(p => p.pattern.source === regex.source); if (existingPattern) { existingPattern.callbacks.push([callback, id]); } else { this.patterns.push({ pattern: regex, callbacks: [[callback, id]] }); } } else { // Handle direct event subscriptions if (!this.events[e]) this.events[e] = []; this.events[e].push([callback, id]); if (!this.cache[e]) this.cache[e] = []; this.cache[e].push([callback, id]); } }); } /** * Unsubscribes from an event or pattern of events. * @param eventString - The event name or pattern to unsubscribe from. * @param id - The identifier of the subscription to remove. */ unsubscribe(eventString, id) { const events = eventString.split(/[\s,]+/); events.forEach(e => { if (e.includes('*')) { const regex = this.wildcardToRegExp(e); this.patterns = this.patterns.filter(pattern => { if (pattern.pattern.source !== regex.source) return true; pattern.callbacks = pattern.callbacks.filter(([, callbackId]) => callbackId !== id); return pattern.callbacks.length > 0; }); this.updateCacheWithPattern(regex, id); } else { if (!this.events[e]) return; this.events[e] = this.events[e].filter(([, eventId]) => eventId !== id); this.updateCache(e, id); } }); } /** * Remove an event or pattern from the cache based on id. * @param event - The event name or pattern. * @param id - The identifier of the subscription to remove from the cache. */ updateCache(event, id) { if (this.cache[event]) { this.cache[event] = this.cache[event].filter(([, eventId]) => eventId !== id); if (this.cache[event].length === 0) { delete this.cache[event]; } } } /** * Update cache by removing pattern-matching events based on id. * @param regex - The regular expression pattern to match against. * @param id - The identifier for the subscription to be removed from the cache. */ updateCacheWithPattern(regex, id) { Object.keys(this.cache).forEach(cacheEvent => { if (regex.test(cacheEvent)) { this.cache[cacheEvent] = this.cache[cacheEvent].filter(([, callbackId]) => callbackId !== id); if (this.cache[cacheEvent].length === 0) { delete this.cache[cacheEvent]; } } }); } } exports.EventHandler = EventHandler; exports.default = new EventHandler();