import { values } from '@s-libs/micro-dash' export type Unsubscribe = () => void export type EventSubscriber = ( cb: EventHandler, ) => Unsubscribe export type EventEmitter = ( payload: TPayload, stopOnHandled?: boolean, ) => Promise export type EventHandler = ( payload: TPayload, isHandled: boolean, ) => boolean | void | Promise /** * * @param defaultHandler Optional handler to call if no handler calls `handled()` * @returns void */ export const createEvent = ( defaultHandler?: EventHandler, ): [EventSubscriber, EventEmitter] => { let i = 0 const callbacks: any = {} let callbacksArray: EventHandler[] = [] const onEvent = (cb: EventHandler) => { const id = i++ callbacks[id] = cb callbacksArray = values(callbacks) return () => { delete callbacks[id] } } const fireEvent = async (payload: TPayload, stopOnHandled = false) => { let _handled = false for (let i = 0; i < callbacksArray.length; i++) { const cb = callbacksArray[i] if (!cb) continue const res: boolean = !!(await cb(payload, _handled)) _handled = _handled || res if (stopOnHandled && _handled) break } if (!_handled) { await defaultHandler?.(payload, false) } return _handled } return [onEvent, fireEvent] }