diff --git a/src/web/log-broadcaster.ts b/src/web/log-broadcaster.ts index ceeff95..094b8a8 100644 --- a/src/web/log-broadcaster.ts +++ b/src/web/log-broadcaster.ts @@ -1,6 +1,10 @@ import type { Request, RequestHandler, Response } from 'express'; import type { LogEntry } from './types.js'; -import { RealtimeEventHub } from './events/index.js'; +import { + createDashboardEventAdapters, + createDashboardEventPublisher, + RealtimeEventHub, +} from './events/index.js'; import { createExpressSseHandler } from './events/express-sse-adapter.js'; const MAX_LOGS = 500; @@ -15,10 +19,12 @@ export class LogBroadcaster { private clients = new Set(); private readonly eventHub: RealtimeEventHub; readonly events: RequestHandler; + readonly dashboardEvents: ReturnType; constructor(eventHub?: RealtimeEventHub) { this.eventHub = eventHub ?? new RealtimeEventHub({ capacity: MAX_LOGS }); this.events = createExpressSseHandler({ hub: this.eventHub }); + this.dashboardEvents = createDashboardEventAdapters(createDashboardEventPublisher(this.eventHub)); } push(level: LogEntry['level'], message: string, data?: unknown): void { diff --git a/tests/web/dashboard-event-wiring.test.ts b/tests/web/dashboard-event-wiring.test.ts new file mode 100644 index 0000000..fbbe365 --- /dev/null +++ b/tests/web/dashboard-event-wiring.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from 'vitest'; +import { LogBroadcaster } from '../../src/web/log-broadcaster.js'; +import { RealtimeEventHub } from '../../src/web/events/index.js'; + +describe('dashboard event wiring', () => { + it('publishes domain and log events through the same ordered hub', () => { + const hub = new RealtimeEventHub({ capacity: 20 }); + const broadcaster = new LogBroadcaster(hub); + const received: string[] = []; + const subscription = hub.subscribe((event) => received.push(event.type)); + + broadcaster.dashboardEvents.bot({ running: true, dryRun: false }); + broadcaster.push('info', 'Bot started'); + + expect(received).toEqual(['bot.status.changed', 'log.created']); + subscription.unsubscribe(); + broadcaster.closeAll(); + }); +});