export type OutputHandler = (payload: T) => void | Promise; export interface OutputHost extends HTMLElement { __wrnexusOutputHandlers?: Map>; } export function registerOutputHandler( host: OutputHost, name: string, handler: OutputHandler, ): () => void { const registry = (host.__wrnexusOutputHandlers ??= new Map()); const handlers = registry.get(name) ?? new Set(); handlers.add(handler as OutputHandler); registry.set(name, handlers); return () => { handlers.delete(handler as OutputHandler); if (!handlers.size) registry.delete(name); }; } export async function invokeOutput(host: OutputHost, name: string, payload?: T): Promise { const handlers = host.__wrnexusOutputHandlers?.get(name); if (handlers?.size) { for (const handler of handlers) await handler(payload); return; } // Compatibility path for legacy listeners outside a hydrated WRN parent. host.dispatchEvent(new CustomEvent(name, { detail: payload })); host.dispatchEvent(new CustomEvent(`wrnexus:${name}`, { detail: payload })); } export function createOutputProxy void>>( host: OutputHost, ): T { return new Proxy({} as T, { get: (_target, property) => (payload?: unknown) => invokeOutput(host, String(property), payload), }); }