/* eslint-disable import/export */ /* eslint-disable no-redeclare */ export function LogDispatcher({ initialState = LogDispatcher.initialState, }: { initialState?: LogDispatcher.State; } = {}): LogDispatcher.Module { let state: LogDispatcher.State = initialState; function getState(): LogDispatcher.State { return state; } function setState(updater: (currentState: LogDispatcher.State) => LogDispatcher.State): void { state = updater(state); } async function callHandler(handlerFunction: LogDispatcher.Handler, event: T): Promise { return handlerFunction(event); } function getHandlers(): Array> { return [...state.handlers]; } function setHandlers(handlers: Array>): void { setState((currentState) => ({ ...currentState, handlers: [...handlers] })); } function addHandler(handler: LogDispatcher.Handler): void { setState((currentState) => ({ ...currentState, handlers: [...currentState.handlers, handler] })); } function removeHandler(handler: LogDispatcher.Handler): void { setState((currentState) => ({ ...currentState, handlers: currentState.handlers.filter((_) => _ !== handler) })); } function handle(record: T): Promise { const { handlers } = getState(); const promises = handlers.map((handler) => callHandler(handler, record)); return Promise.all(promises).then((_) => undefined); } return { handle, addHandler, removeHandler, setHandlers, getHandlers, }; } export namespace LogDispatcher { export type Handler = (record: T) => Promise | void; export interface Module { /** * Send a record to all handlers * * @param record - the log record to handle */ handle(record: T): void; /** * Add a new handler to the module handlers * * @param handler - the new handler */ addHandler(handler: Handler): void; /** * Remove a handler from the module handlers * * @param handler - the handler to remove */ removeHandler(handler: Handler): void; /** * Return a list of all handlers */ getHandlers(): Array>; /** * Replace all module handlers by `handlers` * * @param handlers - the new handlers */ setHandlers(handlers: Array>): void; } export type State = { handlers: ReadonlyArray>; }; // eslint-disable-next-line @typescript-eslint/no-explicit-any export const initialState: State = { handlers: [], }; }