import { listen, type UnlistenFn } from '@tauri-apps/api/event' import type { VergeEventPayloads } from './contract' /** Generated wire contract plus the frontend-internal test-all event. */ interface VergeEvents extends VergeEventPayloads { 'verge://test-all': null } type VergeEventName = keyof VergeEvents type VergeEventHandlers = { [Name in VergeEventName]?: (payload: VergeEvents[Name]) => void } /** * Returns synchronous teardown for asynchronous registrations. `onSubscribed` lets callers * reread event-only state after all listeners are live, closing the initial race window. */ export const subscribeVergeEvents = ( handlers: VergeEventHandlers, onSubscribed?: () => void, ): (() => void) => { let disposed = false const unlisteners: UnlistenFn[] = [] const registrations = Object.entries(handlers).map(([name, handler]) => { if (!handler) return Promise.resolve() return listen(name, ({ payload }) => { ;(handler as (payload: unknown) => void)(payload) }) .then((unlisten) => { // Resolved after teardown: unsubscribe immediately rather than leak. if (disposed) { unlisten() return } unlisteners.push(unlisten) }) .catch((error) => { console.error(`[events] failed to subscribe to ${name}:`, error) }) }) if (onSubscribed) { void Promise.all(registrations).then(() => { if (disposed) return onSubscribed() }) } return () => { disposed = true for (const unlisten of unlisteners.splice(0)) { try { unlisten() } catch (error) { console.error('[events] teardown failed:', error) } } } }