UNPKG

@xec-sh/core

Version:

Universal shell execution engine

146 lines 5.41 kB
import { EventEmitter } from 'events'; export class EnhancedEventEmitter extends EventEmitter { constructor() { super(...arguments); this.filteredListeners = new Map(); this.wildcardListeners = new Map(); this.wildcardSetupMap = new Map(); } onFiltered(event, filterOrListener, listener) { let filter; let handler; if (typeof filterOrListener === 'function') { handler = filterOrListener; } else { filter = filterOrListener; handler = listener; } const eventStr = String(event); if (eventStr.includes('*')) { const pattern = eventStr.replace(/\*/g, '.*'); const regex = new RegExp(`^${pattern}$`); if (!this.wildcardListeners.has(eventStr)) { this.wildcardListeners.set(eventStr, []); } this.wildcardListeners.get(eventStr).push({ listener: handler, filter }); this.setupWildcardListener(regex, eventStr); } else { if (!this.filteredListeners.has(eventStr)) { this.filteredListeners.set(eventStr, []); super.on(eventStr, (data) => { this.handleFilteredEvent(eventStr, data); }); } this.filteredListeners.get(eventStr).push({ listener: handler, filter }); } return this; } handleFilteredEvent(event, data) { const listeners = this.filteredListeners.get(event) || []; for (const { listener, filter } of listeners) { if (this.matchesFilter(data, filter)) { listener(data); } } } setupWildcardListener(regex, pattern) { const eventNames = this.eventNames(); for (const eventName of eventNames) { if (regex.test(eventName) && !this.hasWildcardListenerSetup(eventName, pattern)) { this.markWildcardListenerSetup(eventName, pattern); super.on(eventName, (data) => { this.handleWildcardEvent(pattern, eventName, data); }); } } const originalEmit = this.emit.bind(this); this.emit = (event, ...args) => { const eventStr = String(event); for (const [pattern, listeners] of this.wildcardListeners.entries()) { const regex = new RegExp(`^${pattern.replace(/\*/g, '.*')}$`); if (regex.test(eventStr) && !this.hasWildcardListenerSetup(eventStr, pattern)) { this.markWildcardListenerSetup(eventStr, pattern); super.on(eventStr, (data) => { this.handleWildcardEvent(pattern, eventStr, data); }); } } return originalEmit(event, ...args); }; } hasWildcardListenerSetup(event, pattern) { return this.wildcardSetupMap.get(event)?.has(pattern) || false; } markWildcardListenerSetup(event, pattern) { if (!this.wildcardSetupMap.has(event)) { this.wildcardSetupMap.set(event, new Set()); } this.wildcardSetupMap.get(event).add(pattern); } handleWildcardEvent(pattern, actualEvent, data) { const listeners = this.wildcardListeners.get(pattern) || []; for (const { listener, filter } of listeners) { if (this.matchesFilter(data, filter)) { listener(data); } } } matchesFilter(data, filter) { if (!filter) return true; for (const [key, value] of Object.entries(filter)) { if (key === 'adapter') { const adapters = Array.isArray(value) ? value : [value]; if (!adapters.includes(data.adapter)) { return false; } } else if (data[key] !== value) { return false; } } return true; } offFiltered(event, listener) { const eventStr = String(event); if (eventStr.includes('*')) { const listeners = this.wildcardListeners.get(eventStr); if (listeners) { const index = listeners.findIndex(l => l.listener === listener); if (index !== -1) { listeners.splice(index, 1); } if (listeners.length === 0) { this.wildcardListeners.delete(eventStr); } } } else { const listeners = this.filteredListeners.get(eventStr); if (listeners) { const index = listeners.findIndex(l => l.listener === listener); if (index !== -1) { listeners.splice(index, 1); } if (listeners.length === 0) { this.filteredListeners.delete(eventStr); this.removeAllListeners(eventStr); } } } return this; } emitEnhanced(event, data, adapter) { return this.emit(event, { ...data, timestamp: new Date(), adapter }); } } export function createEnhancedEventEmitter() { return new EnhancedEventEmitter(); } //# sourceMappingURL=event-emitter.js.map