UNPKG

alepha

Version:

Easy-to-use modern TypeScript framework for building many kind of applications.

110 lines (96 loc) 2.89 kB
import type { Hooks } from "../Alepha.ts"; import { KIND } from "../constants/KIND.ts"; import { createPrimitive, Primitive } from "../helpers/primitive.ts"; import type { Async } from "../interfaces/Async.ts"; import type { Service } from "../interfaces/Service.ts"; /** * Registers a new hook. * * ```ts * import { $hook } from "alepha"; * * class MyProvider { * onStart = $hook({ * name: "start", // or "configure", "ready", "stop", ... * handler: async (app) => { * // await db.connect(); ... * } * }); * } * ``` * * Hooks are used to run async functions from all registered providers/services. * * You can't register a hook after the App has started. * * It's used under the hood by the `configure`, `start`, and `stop` methods. * Some modules also use hooks to run their own logic. (e.g. `alepha/server`). * * You can create your own hooks by using module augmentation: * * ```ts * declare module "alepha" { * * interface Hooks { * "my:custom:hook": { * arg1: string; * } * } * } * * await alepha.events.emit("my:custom:hook", { arg1: "value" }); * ``` * */ export const $hook = <T extends keyof Hooks>(options: HookOptions<T>) => createPrimitive(HookPrimitive<T>, options); // --------------------------------------------------------------------------------------------------------------------- export interface HookOptions<T extends keyof Hooks> { /** * The name of the hook. "configure", "start", "ready", "stop", ... */ on: T; /** * The handler to run when the hook is triggered. */ handler: (args: Hooks[T]) => Async<any>; /** * Force the hook to run first or last on the list of hooks. */ priority?: "first" | "last"; /** * Run this hook before the hooks owned by the specified services. */ before?: object | Array<object>; /** * Run this hook after the hooks owned by the specified services. */ after?: object | Array<object>; } // --------------------------------------------------------------------------------------------------------------------- export class HookPrimitive<T extends keyof Hooks> extends Primitive< HookOptions<T> > { public called = 0; protected onInit() { const handler = this.options.handler; const resolveDeps = ( deps?: object | Array<object>, ): Service[] | undefined => { if (!deps) return undefined; const arr = Array.isArray(deps) ? deps : [deps]; return arr.map((dep) => dep.constructor as Service); }; this.alepha.events.on(this.options.on, { caller: this.config.service, priority: this.options.priority, before: resolveDeps(this.options.before), after: resolveDeps(this.options.after), callback: (args: any) => { this.called += 1; return handler(args); }, }); } } $hook[KIND] = HookPrimitive;