import {deferPromise} from "./defer-promise.js" export type PubsubListener = (...a: A) => (void | Promise) export interface Pubsub { (fn: PubsubListener): () => void publish(...a: A): Promise once(): Promise clear(): void } /** * simple pub-sub mechanism. * * // create pubsub function * const onCount = pubsub<[string, number]>() * * // subscribe * const stop = onCount((a, b) => console.log(a, b)) * * // publish * onWhatever.publish("count", 123) * * // unsubscribe * stop() * */ export function pubsub(): Pubsub { const set = new Set>() function subscribe(fn: PubsubListener) { set.add(fn) return () => { set.delete(fn) } } subscribe.publish = async(...a: A) => { await Promise.all([...set].map(fn => fn(...a))) } subscribe.clear = () => set.clear() subscribe.once = async() => { const {promise, resolve} = deferPromise() const unsubscribe = subscribe((...a) => { resolve(a) unsubscribe() }) return promise } return subscribe }