@resk/core
Version:
An innovative TypeScript framework that empowers developers to build applications with a fully decorator-based architecture for efficient resource management. By combining the power of decorators with a resource-oriented design, DecorRes enhances code cla
317 lines (316 loc) • 13.3 kB
TypeScript
/**
* @interface IObservableCallback
* Represents the callback options for observable events.
*
* This type defines a function that can be used as a callback for observable events.
* It accepts a variable number of arguments of any type and returns a value of any type.
*
* Callbacks of this type can be utilized in various event-driven scenarios, allowing
* flexibility in the number and types of parameters passed to the callback.
*
* @example
* ```typescript
* const callback: IObservableCallback = (arg1: string, arg2: number) => {
* console.log(arg1, arg2); // Outputs the string and number passed to the callback
* };
*
* // Invoking the callback with different types of arguments
* callback("Event triggered", 42); // Outputs: Event triggered 42
* callback("Another event", 100); // Outputs: Another event 100
* ```
*/
export type IObservableCallback = (...args: any[]) => any;
/**
* Represents a collection of observable callbacks mapped to their respective event types,
* allowing for optional event handling.
*
* This type defines a record structure where each key corresponds to a specific event type,
* and the value is an array of callback functions associated with that event. The use of
* `Partial` allows for flexibility, meaning that not all event types need to have registered
* callbacks, making it suitable for scenarios where some events may not be utilized.
*
* @template EventType - A generic type parameter that extends from `string`, representing
* the event types. By default, it is set to `string`, allowing for
* any string-based event name.
*
* @example
* // Defining specific event types
* type MyEvent = 'click' | 'hover' | 'scroll';
*
* // Creating a record of callbacks for the defined events
* const callbacks: IObservableCallbacks<MyEvent> = {
* click: [
* (event) => console.log('Click event handler 1', event),
* (event) => console.log('Click event handler 2', event),
* ],
* hover: [
* (event) => console.log('Hover event handler', event),
* ],
* // 'scroll' event has no callbacks registered
* };
*
* // Accessing the callbacks for a specific event
* const clickHandlers = callbacks.click;
* if (clickHandlers) {
* clickHandlers.forEach(handler => handler('click')); // Logs: Click event handler 1 click
* // Logs: Click event handler 2 click
* }
*
* @remarks
* This type is particularly useful in event-driven architectures where multiple callbacks
* need to be associated with different events. The use of `Partial` allows for a more
* flexible design, enabling developers to define only the events they are interested in
* without requiring all possible events to be present.
*/
export type IObservableCallbacks<EventType extends string = string> = Partial<Record<EventType | IObservableAllEventType, IObservableCallback[]>>;
/**
* Represents a wildcard event type for observable systems.
*
* This type is used to signify that a callback should be triggered for all events within
* an observable system. It acts as a catch-all for any event, allowing developers to
* register handlers that respond to every event emitted by the observable.
*
* @example
* // Using the wildcard event type to listen for all events
* observable.on('*', (event, ...args) => {
* console.log(`An event occurred: ${event}`, 'Arguments:', args);
* });
*
* @remarks
* The use of a wildcard event type can be useful for logging, debugging, or handling
* global events that are not specific to a single event type. However, it should be used
* judiciously, as it may lead to performance concerns if many events are emitted frequently.
*/
export type IObservableAllEventType = '*';
export interface IObservable<EventType extends string = string> {
_____isObservable?: boolean;
on: (event: EventType, fn: IObservableCallback) => {
remove: () => any;
};
finally: (event: EventType, fn: IObservableCallback) => IObservable<EventType>;
off: (event: EventType, fn: IObservableCallback) => IObservable<EventType>;
trigger: (event: EventType | IObservableAllEventType, ...args: any[]) => IObservable<EventType>;
offAll: () => IObservable<EventType>;
once: (event: EventType, fn: IObservableCallback) => {
remove: () => any;
};
getEventCallBacks: () => IObservableCallbacks<EventType>;
}
/**
* Returns an instance of the IObservable interface.
* The `observableFactory` function creates a new observable object with methods to manage
* event listeners and trigger events. The returned observable object allows for adding,
* removing, and triggering event callbacks, as well as managing final callbacks that execute
* after all other callbacks for an event.
*
* @returns {IObservable<EventType>} A new instance of the observable object.
*
* @example
* ```typescript
* const observable = observableFactory();
* observable.on("event", (arg1, arg2) => {
* console.log(arg1, arg2);
* });
* observable.trigger("event", "Hello", "World"); // Outputs: Hello World
* observable.on("event",function(){
* console.log("event triggered");
* })
* ```
* @see {@link IObservable} for more information on the observable interface.
* @see {@link IObservableCallbacks} for more information on the observable callbacks interface.
* @see {@link IObservableAllEventType} for more information on the observable all event type.
* @see {@link isObservable} for more information on the observable check function.
*/
export declare const observableFactory: <EventType extends string = string>() => IObservable<EventType>;
/**
* Creates an observable object based on the provided element.
*
* The `observable` function checks if the given element is already observable. If it is,
* the function returns the existing observable instance. If not, it creates a new observable
* instance and extends the provided element with observable methods. This allows the element
* to listen for events, trigger callbacks, and manage event listeners.
*
* @template EventType - The type of the event. This can be any string or a custom type.
* @param {any} element - The element to make observable. This can be any object or value.
* @returns {IObservable<EventType>} The observable object, which includes methods for event handling.
*
* @example
* ```typescript
* import observable from "@resk/core";
* const context = observable({});
* const testCb = (e) => console.log("test");
* context.on("test", testCb);
* context.trigger("test");
* context.off("test", testCb);
* context.offAll();
* ```
* @see {@link IObservable} for more information on the observable interface.
* @see {@link IObservableCallbacks} for more information on the observable callbacks interface.
* @see {@link IObservableAllEventType} for more information on the observable all event type.
* @see {@link isObservable} for more information on the observable check function.
*/
export declare const observable: <EventType extends string = string>(element: any) => IObservable<EventType>;
/**
* Exports the ObservableClass that implements the IObservable interface.
*
* This class provides a way to create observable objects that can emit events and have
* listeners attached to them. It encapsulates the observable functionality, allowing
* users to manage events and their corresponding callbacks in a structured manner.
*
* The ObservableClass is particularly useful in scenarios where you need to implement
* an event-driven architecture, enabling decoupled communication between different parts
* of an application.
* @template EventType - The type of the event. This can be any string or a custom type.
*/
export declare class ObservableClass<EventType extends string = string> implements IObservable<EventType> {
/**
* Flag indicating whether the object is observable.
*
* This property is used internally to identify instances of observable objects.
* It is set to true for all instances of this class.
*/
readonly _____isObservable?: boolean | undefined;
/**
* The internal observable object that provides the observable functionality.
*
* This object is created using the observableFactory function and contains
* the core methods for managing event listeners and triggering events.
*/
readonly _observable: IObservable<EventType>;
/**
* Listen to the given `event` and execute the `callback` each time an event is triggered.
*
* @param {EventType} event - The event to listen to.
* @param {IObservableCallback} fn - The callback function to execute.
* @returns {{ remove: () => any }} An object with a `remove` method to remove the callback.
*
* @example
* ```typescript
* const observable = new ObservableClass();
* const subscription = observable.on("dataReceived", (data) => {
* console.log("Data received:", data);
* });
* ```
*/
on(event: EventType, fn: IObservableCallback): {
remove: () => any;
};
/**
* Add a callback function to an event that will be triggered once.
*
* This method ensures that the callback is executed only the first time the event is triggered.
*
* @param {EventType} event - The event to listen to.
* @param {IObservableCallback} fn - The callback function to execute.
* @returns {IObservable<EventType>} The observable object.
*
* @example
* ```typescript
* observable.finally("dataProcessed", () => {
* console.log("Data has been processed.");
* });
* ```
*/
finally(event: EventType, fn: IObservableCallback): IObservable<EventType>;
/**
* Removes the given `event` listener.
*
* If `fn` is provided, this method removes the specific callback function from the event.
* If `fn` is not provided, it removes all callback functions associated with the event.
*
* @param {EventType} event - The event to remove the listener from.
* @param {IObservableCallback} [fn] - The callback function to remove.
* @returns {IObservable<EventType>} The observable object.
*
* @example
* ```typescript
* observable.off("dataReceived", subscription.remove);
* ```
*/
off(event: EventType, fn: IObservableCallback): IObservable<EventType>;
/**
* Execute all callback functions that listen to the given `event`.
*
* If the last argument is a function, it will be treated as the final callback function
* to be executed after all other callbacks.
*
* @param {EventType} event - The event to trigger.
* @param {...any[]} args - The arguments to pass to the callback functions.
* @returns {IObservable<EventType>} The observable object.
*
* @example
* ```typescript
* observable.trigger("dataReceived", { id: 1, value: "Hello" });
* ```
*/
trigger(event: EventType | IObservableAllEventType, ...args: any[]): IObservable<EventType>;
/**
* Remove all event bindings.
*
* This method clears all event listeners for the observable object.
*
* @returns {IObservable<EventType>} The observable object.
*
* @example
* ```typescript
* observable.offAll();
* ```
*/
offAll(): IObservable<EventType>;
/**
* Listen to the given `event` and execute the `callback` at most once.
*
* This method ensures that the callback is executed only once, even if the event is triggered multiple times.
*
* @param {EventType} event - The event to listen to.
* @param {IObservableCallback} fn - The callback function to execute.
* @returns {{ remove: () => any }} An object with a `remove` method to remove the callback.
*
* @example
* ```typescript
* const subscription = observable.once("dataLoaded", () => {
* console.log("Data has been loaded.");
* });
* ```
*/
once(event: EventType, fn: IObservableCallback): {
remove: () => any;
};
/**
* Get all event callbacks.
*
* This method returns an object with event names as keys and arrays of callback functions as values.
*
* @returns {IObservableCallbacks<EventType>} An object with event names as keys and arrays of callback functions as values.
*
* @example
* ```typescript
* const callbacks = observable.getEventCallBacks();
* console.log(callbacks);
* ```
*/
getEventCallBacks(): IObservableCallbacks<EventType>;
}
/**
* Checks if the given object is an observable element.
*
* An object is considered observable if it implements the IObservable interface and has
* the following properties and methods:
* - `_____isObservable` set to `true`
* - `on` method
* - `trigger` method
* - `off` method
*
* @param {any} obj - The object to check.
* @returns {boolean} `true` if the object is observable, `false` otherwise.
*
* @example
* ```typescript
* const observable = new ObservableClass();
* console.log(isObservable(observable)); // true
*
* const nonObservable = {};
* console.log(isObservable(nonObservable)); // false
* ```
*/
export declare function isObservable(obj: any): boolean;