plugin-engine
Version:
Powership server-utils
89 lines (88 loc) • 4.04 kB
TypeScript
/**
* The PluginEngine class provides a structured way to allow extensibility
* within an application by implementing a Publish-Subscribe pattern with middleware support.
* This pattern is crucial for creating loosely coupled systems,
* which is essential for maintaining a scalable and maintainable
* codebase.
*
* By utilizing a middleware system with event-driven architecture,
* different parts of an application can communicate with each other in a decoupled fashion.
* This enables easier feature additions and modifications without
* causing a ripple effect of changes throughout the codebase.
*
* The PluginEngine class defines a mechanism to register event listeners (subscribers)
* for different named events (publishers) with `enter` and `exit` hooks.
*
* An event with associated data can be executed using the `exec`
* method, which invokes all the registered listeners for that event in
* the order they were added, allowing for potential modifications to
* the event data.
*
* The registered listeners can either process the events synchronously,
* processing one event at a time in the order they are received, or
* asynchronously, processing events in parallel as they are received.
*
* Additionally, a listener can terminate the processing of subsequent
* listeners for a particular event and immediately return the current
* state of the event data by utilizing the `abortWith` method
* provided in the context argument to the listener.
* This provides a mechanism to short-circuit the event processing
* chain when a certain condition is met, like an authorization failure.
*
* The PluginEngine class provides a clean and intuitive API for extending
* the functionality in a systematic way, while maintaining the
* decoupling and scalability of the application architecture.
*/
export type EventHandler<EventData> = (data: EventData, context: {
abortWith: (data: EventData) => void;
}) => MaybePromise<EventData | void>;
export type MiddlewareStep = 'enter' | 'exit';
export type Plugin<EventData> = {
name: string;
enter?: EventHandler<EventData>;
exit?: EventHandler<EventData>;
error?: (error: unknown) => {
message: string;
[K: string]: unknown;
};
};
/**
* Type representing an unsubscribe function.
*/
export type UnsubscribeListener = () => void;
/**
* Class representing a minimalistic Publish-Subscribe system with middleware support.
*
* @template Events - An object type where keys are event names and values are the types of data associated with the events.
*/
export declare class PluginEngine<Events extends {
[K: string]: unknown;
}> {
/**
* Object to hold the event listeners.
*/
private listeners;
/**
* Method to exec an event and wait for possible data modifications from subscribers.
*
* @template EventName - The name of the event.
* @template Events - Record representing all combinations of eventName:eventData
* @param {EventName} eventName - The name of the event to exec.
* @param {Events[EventName]} data - The data associated with the event.
* @returns {Promise<Events[EventName]>} - The potentially modified event data.
*/
exec<EventName extends keyof Events>(eventName: EventName, data: Events[EventName]): Promise<Events[EventName]>;
/**
* Method to register a new event listener.
*
* @template EventName - The name of the event.
* @template Events - Record representing all combinations of eventName:eventData
* @param {EventName} eventName - The name of the event to listen for.
* @param {Plugin<Events[EventName]>} plugin - The event handler.
* will not be awaited to finish before going to the next middleware execution
* @returns {UnsubscribeListener} - A function to unregister the listener.
*/
on: <EventName extends Extract<keyof Events, string>>(eventName: EventName, plugin: Plugin<Events[EventName]>) => UnsubscribeListener;
}
type MaybePromise<T> = T | Promise<T>;
export {};