Skip to content

Interface: Hooks<Events> ​

A simple yet effective implementation for registering and executing lifecycle hooks around specific events.

The Hooks class allows you to register hook handlers for different events, execute them, and manage cleanup operations. Hooks can be functions or objects with a handle method.

Example ​

ts
// Define event types
type AppEvents = {
  saving: [[User], [Error | null, User]];
  deleting: [[User], [Error | null]];
};

const hooks = new Hooks<AppEvents>();

// Add a function handler
hooks.add("saving", function hashPassword(user) {
  user.password = hash(user.password);
});

// Add a handler provider
hooks.add("saving", {
  name: "validateEmail",
  handle(event, user) {
    if (!isValid(user.email)) {
      throw new Error("Invalid email");
    }
  },
});

// Execute hooks
await hooks.runner("saving").run(user);

Type Parameters ​

Type ParameterDescription
Events extends Record<string, [any[], any[]]>A record mapping event names to tuples of [HookArgs, CleanupArgs]

Methods ​

add() ​

ts
add<Event>(event: Event, handler:
  | HookHandler<Events[Event][0], Events[Event][1]>
  | HookHandlerProvider<Events[Event][0], Events[Event][1]>): this;

Add a hook handler for a given event. Adding the same handler twice will result in a noop.

Type Parameters ​

Type Parameter
Event extends string | number | symbol

Parameters ​

ParameterTypeDescription
eventEventThe event name to add the handler for
handler| HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>The hook handler function or handler provider

Returns ​

this

Example ​

ts
const hooks = new Hooks();

// Add a function handler
hooks.add("saving", function hashPassword(user) {
  user.password = hash(user.password);
});

// Add a handler provider
hooks.add("saving", {
  name: "EmailValidator",
  handle(event, user) {
    validateEmail(user.email);
  },
});

all() ​

ts
all(): { [Event in string | number | symbol]: Map<Event, Set<HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>>> }[keyof Events];

Get access to all the registered hooks. The return value is a map of the event name and a set of handlers.

Returns ​

{ [Event in string | number | symbol]: Map<Event, Set<HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>>> }[keyof Events]

Example ​

ts
const hooks = new Hooks();
const allHooks = hooks.all();
console.log(allHooks.size); // Number of events with handlers

clear() ​

ts
clear(event?: keyof Events): void;

Clear all the hooks for a specific event or all the events.

Parameters ​

ParameterTypeDescription
event?keyof EventsOptional event name to clear hooks for. If not provided, clears all hooks.

Returns ​

void

Example ​

ts
const hooks = new Hooks();

// Clear hooks for specific event
hooks.clear("saving");

// Clear all hooks
hooks.clear();

has() ​

ts
has<Event>(event: Event, handler?:
  | HookHandler<Events[Event][0], Events[Event][1]>
  | HookHandlerProvider<Events[Event][0], Events[Event][1]>): boolean;

Find if a handler for a given event exists.

Type Parameters ​

Type Parameter
Event extends string | number | symbol

Parameters ​

ParameterTypeDescription
eventEventThe event name to check
handler?| HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>Optional specific handler to check for

Returns ​

boolean

Example ​

ts
const hooks = new Hooks();

// Check if any handlers exist for an event
if (hooks.has("saving")) {
  console.log("Saving hooks are registered");
}

// Check if specific handler exists
if (hooks.has("saving", hashPasswordHandler)) {
  console.log("Hash password handler is registered");
}

merge() ​

ts
merge(hooks: Hooks<Events>): void;

Merge hooks from an existing hooks instance.

Parameters ​

ParameterTypeDescription
hooksHooks<Events>The hooks instance to merge from

Returns ​

void

Example ​

ts
const hooks1 = new Hooks();
const hooks2 = new Hooks();

hooks2.add("saving", handler1);
hooks2.add("deleting", handler2);

// Merge hooks2 into hooks1
hooks1.merge(hooks2);

remove() ​

ts
remove<Event>(event: Event, handler:
  | HookHandler<Events[Event][0], Events[Event][1]>
  | HookHandlerProvider<Events[Event][0], Events[Event][1]>): boolean;

Remove hook handler for a given event.

Type Parameters ​

Type Parameter
Event extends string | number | symbol

Parameters ​

ParameterTypeDescription
eventEventThe event name to remove the handler from
handler| HookHandler<Events[Event][0], Events[Event][1]> | HookHandlerProvider<Events[Event][0], Events[Event][1]>The hook handler to remove

Returns ​

boolean

Example ​

ts
const hooks = new Hooks();
const handler = function hashPassword(user) {};

hooks.add("saving", handler);

// Later, remove the handler
const removed = hooks.remove("saving", handler);
console.log(removed); // true if handler was found and removed

runner() ​

ts
runner<Event>(action: Event): Runner<Events[Event][0], Events[Event][1]>;

Returns an instance of the runner to run hooks

Type Parameters ​

Type Parameter
Event extends string

Parameters ​

ParameterTypeDescription
actionEventThe event name to create a runner for

Returns ​

Runner<Events[Event][0], Events[Event][1]>

Example ​

ts
const hooks = new Hooks();

hooks.add("saving", function hashPassword(user) {
  user.password = hash(user.password);
});

// Get a runner and execute hooks
const runner = hooks.runner("saving");
await runner.run(user);