/** * Event Bus - Centralized event infrastructure for domain events * * Provides type-safe event emission and listening for decoupling * business logic from transport layer (WebSocket, HTTP, etc.) * * Benefits: * - Type safety: All events are typed via DomainEvents interface * - Testability: Business logic can be tested without Socket.io * - Flexibility: Easy to add new transport layers * - Debugging: Single place to log all events */ import { EventEmitter } from 'events'; import type { ServerToClientEvents } from '../types/events.js'; /** * Extract payload type from WebSocket event function signature * e.g., (data: { sessionId: string }) => void → { sessionId: string } */ type EventPayload = T extends (data: infer P) => void ? P : never; /** * Domain events emitted by business logic * * Events shared with WebSocket clients are derived from ServerToClientEvents. * Internal-only events are defined directly here. */ export interface DomainEvents { 'session:status': EventPayload; 'session:block:start': EventPayload; 'session:block:delta': EventPayload; 'session:block:update': EventPayload; 'session:block:complete': EventPayload; 'session:metadata:update': EventPayload; 'session:options:update': EventPayload; 'session:subagent:discovered': EventPayload; 'session:subagent:completed': EventPayload; 'session:file:created': EventPayload; 'session:file:modified': EventPayload; 'session:file:deleted': EventPayload; /** Sessions list changed - triggers broadcast of sessions:list */ 'sessions:changed': void; /** Transcript changed (for session state sync) */ 'session:transcript:changed': { sessionId: string; content: string; }; /** Subagent transcript changed */ 'session:subagent:changed': { sessionId: string; subagentId: string; content: string; }; /** Session error - transformed to 'error' event for WebSocket */ 'session:error': { sessionId: string; error: { message: string; code?: string; }; }; } /** * Type-safe EventBus for domain events * * Usage: * ```typescript * const eventBus = new EventBus(); * * // Emit event (type-safe) * eventBus.emit('session:created', { sessionId, metadata }); * * // Listen to event (type-safe callback) * eventBus.on('session:created', (data) => { * console.log(data.sessionId); // TypeScript knows this exists * }); * ``` */ export declare class EventBus extends EventEmitter { /** * Emit type-safe domain event * * @param event - Event name (must be key of DomainEvents) * @param args - Event data (typed based on event) * @returns true if the event had listeners, false otherwise */ emit(event: K, ...args: DomainEvents[K] extends void ? [] : [DomainEvents[K]]): boolean; /** * Listen to type-safe domain event * * @param event - Event name (must be key of DomainEvents) * @param listener - Typed callback function * @returns this (for chaining) */ on(event: K, listener: DomainEvents[K] extends void ? () => void : (data: DomainEvents[K]) => void): this; /** * Listen once to type-safe domain event * * @param event - Event name (must be key of DomainEvents) * @param listener - Typed callback function * @returns this (for chaining) */ once(event: K, listener: DomainEvents[K] extends void ? () => void : (data: DomainEvents[K]) => void): this; /** * Remove type-safe event listener * * @param event - Event name (must be key of DomainEvents) * @param listener - Callback function to remove * @returns this (for chaining) */ off(event: K, listener: DomainEvents[K] extends void ? () => void : (data: DomainEvents[K]) => void): this; /** * Remove all listeners for an event, or all listeners if no event specified * * @param event - Optional event name * @returns this (for chaining) */ removeAllListeners(event?: keyof DomainEvents): this; } export {}; //# sourceMappingURL=event-bus.d.ts.map