@daiso-tech/core
Version:
The library offers flexible, framework-agnostic solutions for modern web applications, built on adaptable components that integrate seamlessly with popular frameworks like Next Js.
118 lines • 4 kB
JavaScript
/**
* @module Utilities
*/
import { getInvokableName, resolveInvokable, resolveOneOrMore, } from "../../../utilities/_module-exports.js";
/**
* The `Hooks` class provides a convenient way to change and inspect arguments and return value of both only sync functions.
* For example `Hooks` class can be used to log function arguments and return values. Note this class will always return promise and is immutable.
*
* Middlewares apply left to right: each wraps the next, with the leftmost being the outermost layer and the rightmost wrapping the original function.
*
* IMPORT_PATH: `"@daiso-tech/core/utilities"`
* @group Hooks
*/
export class Hooks {
invokable;
middlewares;
settings;
static init(invokable, middlewares, { name = getInvokableName(invokable), context = {}, }) {
let func = resolveInvokable(invokable);
for (const hook of resolveOneOrMore(middlewares)
.map(resolveInvokable)
.reverse()) {
const prevFunc = func;
const next = (...arguments_) => prevFunc(...arguments_);
func = (...arguments_) => {
return hook(arguments_, next, {
name,
context,
});
};
}
return func;
}
func;
/**
* @example
* ```ts
* import { Hooks, type MiddlewareFn } from "@daiso-tech/core/utilities";
*
* function log<TParameters extends unknown[], TReturn>(): MiddlewareFn<TParameters, TReturn, { funcName: string; }> {
* return (args, next, { name: funcName }) => {
* console.log("FUNCTION_NAME:", funcName);
* console.log("ARGUMENTS:", args);
* const value = next(...args);
* console.log("RETURN:", value);
* return value;
* }
* }
*
* function time<TParameters extends unknown[], TReturn>(): MiddlewareFn<TParameters, TReturn> {
* return (args, next) => {
* const start = performance.now();
* const value = next(...args);
* const end = performance.now();
* const time = end - start;
* console.log("TIME:", `${String(time)}ms`);
* return value;
* }
* }
*
* function add(a: number, b: number): number {
* return a + b;
* }
*
* const enhancedAdd = new Hooks(add, [
* log(),
* time()
* ], {
* // You can provide addtional data to be used the middleware.
* context: {},
* });
*
* // Will log the function name, arguments and return value.
* // Will also log the execution time.
* const result = enhancedAdd.invoke(1, 2);
*
* // Will be 3.
* console.log(result);
* ```
*/
constructor(invokable, middlewares, settings = {}) {
this.invokable = invokable;
this.middlewares = middlewares;
this.settings = settings;
this.func = Hooks.init(invokable, middlewares, this.settings);
}
/**
* The `pipe` method returns a new `Hooks` instance with the additional `middlewares` applied.
*/
pipe(middlewares) {
return new Hooks(this.invokable, [
...resolveOneOrMore(this.middlewares),
...resolveOneOrMore(middlewares),
], this.settings);
}
/**
* The `pipeWhen` method conditionally applies additional `middlewares`, returning a new `Hooks` instance only if the specified condition is met.
*/
pipeWhen(condition, middlewares) {
if (condition) {
return this.pipe(middlewares);
}
return this;
}
/**
* The `toFunc` will return the function with all middlewares applied.
*/
toFunc() {
return (...args) => this.invoke(...args);
}
/**
* The `invoke` method executes the constructor's input function, applying all middlewares.
*/
invoke(...arguments_) {
return this.func(...arguments_);
}
}
//# sourceMappingURL=hooks.js.map