Skip to content

Class: 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]

Constructors

Constructor

ts
new Hooks<Events>(): Hooks<Events>;

Returns

Hooks<Events>

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);