/** * @file Unified Event Utilities * @description Best-of-breed event handling with type safety, middleware, coordination, * and reliability features. Consolidates 4 previous implementations into one canonical version. * * @module shared/event-utils * @author Agent 5 - PhD TypeScript Architect * @version 2.0.0 */ /** * Generic event handler function type. */ export type EventHandler = (data: T) => void | Promise; /** * Synchronous event handler. */ export type SyncEventHandler = (data: T) => void; /** * Async event handler. */ export type AsyncEventHandler = (data: T) => Promise; /** * Unsubscribe function returned by event subscriptions. */ export type Unsubscribe = () => void; /** * Event middleware function. */ export type EventMiddleware = (data: T, next: (data: T) => void | Promise) => void | Promise; /** * Event listener options. */ export interface EventListenerOptions { /** Call handler only once then auto-remove */ once?: boolean; /** Priority (higher executes first) */ priority?: number; /** Abort signal to auto-remove listener */ signal?: AbortSignal; /** Debounce delay in milliseconds */ debounce?: number; /** Throttle interval in milliseconds */ throttle?: number; /** Source filter (string, regex, or array) */ sourceFilter?: string | RegExp | string[]; /** Target filter */ targetFilter?: string; /** Transform data before passing to handler */ transform?: (data: unknown) => unknown; /** Filter events */ filter?: (data: unknown) => boolean; } /** * Unified event emitter configuration. */ export interface UnifiedEventEmitterOptions { /** Maximum listeners per event (warning threshold) */ maxListeners?: number; /** Enable debug logging */ debug?: boolean; /** Error handler for listener errors */ onError?: (error: Error, event: string) => void; /** Enable middleware support */ enableMiddleware?: boolean; /** Enable event deduplication */ enableDeduplication?: boolean; /** Enable event persistence/history */ enablePersistence?: boolean; /** Enable statistics tracking */ enableStatistics?: boolean; /** Enable dead letter queue */ enableDeadLetters?: boolean; /** Deduplication window in milliseconds */ deduplicationWindow?: number; /** Maximum events to persist in history */ maxPersistedEvents?: number; /** Maximum dead letters to keep */ maxDeadLetters?: number; /** Maximum retries for failed deliveries */ maxRetries?: number; /** Retry delay in milliseconds */ retryDelayMs?: number; } /** * Event metadata for advanced features. */ export interface EventMetadata { /** Unique event ID */ id: string; /** Event timestamp */ timestamp: number; /** Source identifier */ source?: string; /** Target identifier */ target?: string | null; /** Event priority */ priority: number; /** Correlation ID for request-response pattern */ correlationId?: string; /** Whether acknowledgment is required */ requiresAck?: boolean; /** Custom metadata */ custom?: Record; } /** * Event with metadata. */ export interface EventWithMetadata { /** Event name/type */ event: string; /** Event payload */ payload: T; /** Event metadata */ metadata: EventMetadata; } /** * Event bus statistics. */ export interface EventBusStats { /** Total events published */ totalPublished: number; /** Total events delivered */ totalDelivered: number; /** Total delivery failures */ totalFailures: number; /** Current active subscriptions */ activeSubscriptions: number; /** Dead letters count */ deadLettersCount: number; /** Events by type */ eventsByType: Map; /** Events by priority */ eventsByPriority: Record; /** Average delivery time in milliseconds */ avgDeliveryTime: number; } /** * Dead letter entry for failed deliveries. */ interface DeadLetterEntry { event: string; data: unknown; metadata: EventMetadata; reason: string; timestamp: number; retryCount: number; } /** * Standard application events that can be used across modules. */ export type AppEvents = { 'auth:login': { userId: string; timestamp: number; }; 'auth:logout': { userId: string; reason?: string; }; 'auth:sessionExpired': { userId: string; }; 'auth:tokenRefreshed': { accessToken: string; }; 'navigation:beforeNavigate': { from: string; to: string; }; 'navigation:afterNavigate': { from: string; to: string; }; 'navigation:blocked': { from: string; to: string; reason: string; }; 'data:invalidate': { keys: string[]; }; 'data:update': { key: string; value: unknown; }; 'data:refresh': { source: string; }; 'ui:themeChange': { theme: 'light' | 'dark' | 'system'; }; 'ui:notification': { type: 'info' | 'success' | 'warning' | 'error'; message: string; duration?: number; }; 'ui:modalOpen': { id: string; data?: Record; }; 'ui:modalClose': { id: string; result?: unknown; }; 'error:global': { error: Error; context?: string; }; 'error:network': { url: string; status: number; message: string; }; 'error:validation': { field: string; message: string; }; 'performance:slowOperation': { operation: string; durationMs: number; }; 'performance:memoryPressure': { level: 'low' | 'moderate' | 'critical'; }; 'feature:flagChange': { key: string; value: unknown; previousValue: unknown; }; 'offlineQueue:expired': { id: string; url: string; }; 'offlineQueue:enqueued': { id: string; url: string; }; 'offlineQueue:processing': { count: number; }; 'offlineQueue:completed': { id: string; url: string; response: unknown; }; 'offlineQueue:failed': { id: string; url: string; error: Error; }; 'service:stateChange': { service: string; from: string; to: string; health: unknown; }; 'service:error': { service: string; error: Error; }; 'service:healthCheck': { service: string; health: unknown; }; 'analytics:consentChanged': { consent: unknown; }; 'network:online': undefined; 'network:offline': undefined; 'network:qualityChange': { quality: string; }; }; /** * Type-safe event emitter interface. */ export interface IEventEmitter> { /** * Subscribe to an event. */ on(event: K, handler: EventHandler, options?: EventListenerOptions): Unsubscribe; /** * Subscribe to an event for a single emission. */ once(event: K, handler: EventHandler, options?: Omit): Unsubscribe; /** * Unsubscribe from an event. */ off(event: K, handler: EventHandler): void; /** * Emit an event. */ emit(event: K, data: Events[K]): void | Promise; /** * Remove all listeners for an event (or all events if no event specified). */ removeAllListeners(event?: K): void; /** * Get listener count for an event. */ listenerCount(event: K): number; } /** * Unified event emitter with all best-of-breed features. * * Features: * - Type-safe event maps * - Priority listeners * - Once-only listeners * - Wildcard listeners * - Async event handling * - Memory leak prevention * - Middleware support * - Event namespacing * - Request-response pattern * - Event deduplication * - Event persistence and replay * - Dead letter queue * - Statistics tracking * - Debounce/throttle support * - AbortSignal support * * @example * ```typescript * interface MyEvents { * 'user:created': { id: string; name: string }; * 'user:deleted': { id: string }; * } * * const emitter = new UnifiedEventEmitter(); * * emitter.on('user:created', (data) => { * console.log(`User ${data.name} created`); * }); * * emitter.emit('user:created', { id: '1', name: 'John' }); * ``` */ export declare class UnifiedEventEmitter> implements IEventEmitter { private readonly config; private readonly listeners; private readonly middlewares; private readonly deduplicationCache; private readonly eventHistory; private readonly deadLetters; private readonly pendingRequests; private stats; private totalDeliveryTime; private cleanupInterval; private contextSource?; constructor(options?: UnifiedEventEmitterOptions); /** * Subscribe to an event. */ on(event: K, handler: EventHandler, options?: EventListenerOptions): Unsubscribe; /** * Subscribe to an event for a single emission. */ once(event: K, handler: EventHandler, options?: Omit): Unsubscribe; /** * Unsubscribe from an event. */ off(event: K, handler: EventHandler): void; /** * Emit an event. */ emit(event: K, data: Events[K]): Promise; /** * Emit synchronously (fire and forget). */ emitSync(event: K, data: Events[K]): void; /** * Remove all listeners for an event (or all events if no event specified). */ removeAllListeners(event?: K): void; /** * Get listener count for an event. */ listenerCount(event: K): number; /** * Get all registered event names. */ eventNames(): (keyof Events)[]; /** * Wait for an event to be emitted. */ waitFor(event: K, options?: { timeout?: number; filter?: (data: Events[K]) => boolean; }): Promise; /** * Add middleware for an event. */ use(event: K, middleware: EventMiddleware): Unsubscribe; /** * Pipe events from another emitter. */ pipe(event: K, source: UnifiedEventEmitter): Unsubscribe; /** * Set context source for emitted events. */ setContext(source: string): void; /** * Get context source. */ getContext(): string | undefined; /** * Request-response pattern: send request and wait for response. */ request(requestEvent: TReq, responseEvent: TRes, payload: Events[TReq], timeout?: number): Promise; /** * Get event history. */ getHistory(): ReadonlyArray>; /** * Replay events from history. */ replay(filter?: (event: EventWithMetadata) => boolean): void; /** * Clear event history. */ clearHistory(): void; /** * Get dead letters. */ getDeadLetters(): ReadonlyArray; /** * Retry a dead letter. */ retryDeadLetter(index: number): boolean; /** * Clear dead letters. */ clearDeadLetters(): void; /** * Get statistics. */ getStats(): EventBusStats; /** * Reset statistics. */ resetStats(): void; /** * Clear all data and reset emitter. */ clear(): void; /** * Dispose the emitter and clean up resources. */ dispose(): void; /** * Apply middleware chain. */ private applyMiddleware; /** * Add message to dead letter queue. */ private addDeadLetter; /** * Clean up deduplication cache. */ private cleanupDeduplicationCache; } /** * Create a unified event emitter. */ export declare function createEventEmitter>(options?: UnifiedEventEmitterOptions): UnifiedEventEmitter; /** * Create a scoped event emitter with namespace. */ export declare function createScopedEmitter>(namespace: string, baseEmitter?: UnifiedEventEmitter>): UnifiedEventEmitter; /** * Global event bus instance. */ export declare const globalEventBus: UnifiedEventEmitter; /** * Shorthand for common event operations. */ export declare const events: { emit: (event: K, data: AppEvents[K]) => Promise; on: (event: K, handler: EventHandler, options?: EventListenerOptions) => Unsubscribe; once: (event: K, handler: EventHandler, options?: Omit) => Unsubscribe; off: (event: K, handler: EventHandler) => void; waitFor: (event: K, options?: { timeout?: number; filter?: ((data: AppEvents[K]) => boolean) | undefined; }) => Promise; }; /** * Create a handler that only executes once per unique key within a time window. */ export declare function dedupeHandler(handler: EventHandler, keyFn: (data: T) => string, windowMs: number): EventHandler; /** * Create a handler that batches events and calls the handler with all events. */ export declare function batchHandler(handler: (events: T[]) => void | Promise, intervalMs: number): EventHandler; /** * Create a handler that filters events based on a predicate. */ export declare function filterHandler(handler: EventHandler, predicate: (data: T) => boolean): EventHandler; /** * Create a handler that transforms event data before passing to handler. */ export declare function mapHandler(handler: EventHandler, transform: (data: T) => U): EventHandler; /** * Combine multiple handlers into one. */ export declare function combineHandlers(...handlers: EventHandler[]): EventHandler; /** * Add event listener with automatic cleanup. */ export declare function addEventListener(target: Window, event: K, handler: (event: WindowEventMap[K]) => void, options?: boolean | AddEventListenerOptions): Unsubscribe; export declare function addEventListener(target: Document, event: K, handler: (event: DocumentEventMap[K]) => void, options?: boolean | AddEventListenerOptions): Unsubscribe; export declare function addEventListener(target: HTMLElement, event: K, handler: (event: HTMLElementEventMap[K]) => void, options?: boolean | AddEventListenerOptions): Unsubscribe; /** * Create a disposable event listener that cleans up when signal is aborted. */ export declare function addDisposableEventListener(target: Window, event: K, handler: (event: WindowEventMap[K]) => void, signal: AbortSignal, options?: Omit): void; /** * Create and dispatch a custom event. */ export declare function dispatchCustomEvent(target: EventTarget, eventName: string, detail: T, options?: Omit, 'detail'>): boolean; /** * Listen for a custom event with typed detail. */ export declare function onCustomEvent(target: EventTarget, eventName: string, handler: (detail: T) => void, options?: boolean | AddEventListenerOptions): Unsubscribe; /** * Constructor type for mixin pattern. */ type Constructor = new (...args: unknown[]) => T; /** * Event emitter mixin for classes. */ export declare function withEvents>(Base: T): T & Constructor<{ events: UnifiedEventEmitter; }>; /** * @deprecated Use UnifiedEventEmitter instead */ export declare const SimpleEventEmitter: typeof UnifiedEventEmitter; /** * @deprecated Use UnifiedEventEmitter instead */ export declare const EventEmitter: typeof UnifiedEventEmitter; export {};