UNPKG

@homer0/events-hub

Version:

A simple implementation of a pubsub service for handling events

124 lines (122 loc) 5.6 kB
type GenericFn = (...args: any[]) => any; type GenericParams = Parameters<GenericFn>; type OnceWrapperFn = GenericFn & { once: boolean; }; /** * When the service receives a "once subscription", it needs to track the listener so it * gets removed after being called once, and to avoid modifying the original function, it * creates a wrapper function that has the "once" property set to true. The wrapper and * the original function are stored in case `off` is called before the wrapper gets * triggered; it will receive the original function, not the wrapper, so the class needs a * way to map them together. */ type OnceWrapper = { /** * A simple wrapper for the original listener, with the difference that it has a `once` * property set to `true`. */ wrapper: OnceWrapperFn; /** * The original listener that will be called once. */ original: GenericFn; }; /** * A minimal implementation of an events handler service. */ declare class EventsHub { /** * A dictionary of the events and their listeners. */ protected events: Record<string, GenericFn[]>; /** * A dictionary of wrappers that were created for "one time subscriptions". This is * used by the {@link EventsHub.off}: if it doesn't find the subscriber as it is, it * will look for a wrapper and remove it. */ protected onceWrappers: Record<string, OnceWrapper[]>; /** * Gets all the listeners for a specific event. * The list is returned by reference, so it can be modified once obtained. * * @param event The name of the event. */ protected getSubscribers(event: string): (GenericFn | OnceWrapperFn)[]; on<ListenerFn extends GenericFn = GenericFn>(event: string, listener: ListenerFn): () => boolean; on<ListenerFn extends GenericFn = GenericFn>(event: string[], listener: ListenerFn): () => boolean[]; on<ListenerFn extends GenericFn = GenericFn>(event: string | string[], listener: ListenerFn): () => boolean | boolean[]; once<ListenerFn extends GenericFn = GenericFn>(event: string, listener: ListenerFn): () => boolean; once<ListenerFn extends GenericFn = GenericFn>(event: string[], listener: ListenerFn): () => boolean[]; once<ListenerFn extends GenericFn = GenericFn>(event: string | string[], listener: ListenerFn): () => boolean | boolean[]; off<ListenerFn extends GenericFn | OnceWrapperFn = GenericFn>(event: string[], listener: ListenerFn): boolean[]; off<ListenerFn extends GenericFn | OnceWrapperFn = GenericFn>(event: string, listener: ListenerFn): boolean; off<ListenerFn extends GenericFn | OnceWrapperFn = GenericFn>(event: string | string[], listener: ListenerFn): boolean | boolean[]; /** * Emits an event and call all its listeners. * * @param event An event name or a list of them. * @param args A list of parameters to send to the listeners. * @template Args The type of the parameters to send to the listeners. * @example * * const events = new EventsHub(); * events.on('event', (arg0) => { * console.log(`Event received: ${arg0}`); * }); * events.emit('event', 'Hello'); // prints "Event received: Hello" * */ emit<Args extends GenericParams>(event: string | string[], ...args: Args): void; /** * Asynchronously reduces a target using an event. It's like emit, but the events * listener return a modified (or not) version of the `target`. * * @param event An event name or a list of them. * @param target The variable to reduce with the reducers/listeners. * @param args A list of parameters to send to the reducers/listeners. * @returns A version of the `target` processed by the listeners. * @template Target The type of the target. * @template Args The type of the parameters to send to the reducers/listeners. * @example * * const events = new EventsHub(); * events.on('event', async (target, arg0) => { * const data = await fetch(`https://api.example.com/${arg0}`); * target.push(data); * return target; * }); * const result = await events.reduce('event', [], 'Hello'); * // result would be a list of data fetched from the API. * */ reduce<Target, Args extends GenericParams>(event: string | string[], target: Target, ...args: Args): Promise<Target>; /** * Synchronously reduces a target using an event. It's like emit, but the events * listener return a modified (or not) version of the `target`. * * @param event An event name or a list of them. * @param target The variable to reduce with the reducers/listeners. * @param args A list of parameters to send to the reducers/listeners. * @returns A version of the `target` processed by the listeners. * @template Target The type of the target. * @template Args The type of the parameters to send to the reducers/listeners. * @example * * const events = new EventsHub(); * events.on('event', (target, arg0) => { * target.push(arg0); * return target; * }); * events.reduce('event', [], 'Hello'); // returns ['Hello'] * */ reduceSync<Target, ReducerArgs extends GenericParams>(event: string | string[], target: Target, ...args: ReducerArgs): Target; } /** * Shorthand for `new EventsHub()`. * * @returns A new instance of {@link EventsHub}. */ declare const eventsHub: () => EventsHub; export { EventsHub, eventsHub };