alepha@docs:~/docs/guides/core$
cat 3-internal-events.md
2 min read
Last commit:

#Internal Events

Alepha uses a hook-based event system for lifecycle management and cross-service communication.

#Confusion Warning

  • $hook is not a React Hook (e.g. useState) ! But rather event listeners.
  • $hook is not a pub/sub system ! Use $topic for pub/sub.

#Lifecycle

When alepha.start() is called, the framework emits events in this order:

bash
configure  ->  start  ->  ready  ->  (APP RUNNING)  ->  stop
Hook When Typical use
configure Before start, after container is locked Register providers, resolve configuration
start After configure Connect to databases, start listeners
ready After start Application is fully operational
stop On shutdown (SIGINT/SIGTERM or manual) Close connections, flush buffers

configure, start, and ready receive the Alepha instance as payload. stop also receives the Alepha instance.

#Using $hook

Register hooks with the $hook primitive. It must be a class property.

typescript
 1import { $hook, $logger } from "alepha"; 2  3class DatabaseService { 4  log = $logger(); 5  6  onStart = $hook({ 7    on: "start", 8    handler: async () => { 9      await this.connectToDatabase();10      this.log.info("Database connected");11    },12  });13 14  onStop = $hook({15    on: "stop",16    handler: async () => {17      await this.disconnectFromDatabase();18      this.log.info("Database disconnected");19    },20  });21}

#Hook options

typescript
1$hook({2  on: "start",           // required: event name3  handler: async () => { /* ... */ },  // required: callback4  priority: "first",     // optional: "first" | "last" (default: insertion order)5});

priority: "first" places the hook at the front of the execution queue. priority: "last" places it at the end. Without a priority, hooks execute in registration order (which follows dependency order).

#Hook call tracking

Each $hook instance tracks how many times it has been called:

typescript
1const alepha = Alepha.create().with(App);2await alepha.start();3 4const app = alepha.inject(App);5console.log(app.onStart.called); // 1

This is useful for testing to ensure hooks are called the expected number of times.

#Built-in Hooks

The core Hooks interface defines:

typescript
 1interface Hooks { 2  configure: Alepha;                 // configuration phase 3  start: Alepha;                     // start phase 4  ready: Alepha;                     // ready phase 5  stop: Alepha;                      // shutdown phase 6  "state:mutate": {                  // state change notification 7    key: keyof State; 8    value: any; 9    prevValue: any;10  };11}

Other modules extend this interface. For example, alepha/logger adds log, alepha/server adds server-related hooks, and so on.

#Custom Hooks

Define custom hooks using TypeScript module augmentation:

typescript
1declare module "alepha" {2  interface Hooks {3    "billing:invoice:created": {4      invoiceId: string;5      amount: number;6    };7  }8}

#Listening to custom hooks

As a class property with $hook:

typescript
1class NotificationService {2  onInvoice = $hook({3    on: "billing:invoice:created",4    handler: async ({ invoiceId, amount }) => {5      await this.sendReceipt(invoiceId, amount);6    },7  });8}

Or directly on the event manager:

typescript
1alepha.events.on("billing:invoice:created", ({ invoiceId, amount }) => {2  console.log(`Invoice ${invoiceId} created for ${amount}`);3});

alepha.events.on() returns an unsubscribe function:

typescript
1const unsubscribe = alepha.events.on("billing:invoice:created", handler);2// later...3unsubscribe();

#Emitting custom hooks

typescript
1await alepha.events.emit("billing:invoice:created", {2  invoiceId: "inv_123",3  amount: 99.99,4});

The emit method accepts options:

typescript
1await alepha.events.emit("billing:invoice:created", payload, {2  log: true,   // log execution timing of each hook3  catch: true, // catch errors and log them instead of throwing4});

#Compiled Events (advanced)

For hot paths (like HTTP request handling), compile events into optimized executors:

typescript
1// After all hooks are registered (e.g. after start)2const onRequest = alepha.events.compile("server:onRequest", { catch: true });3 4// In the request handler - returns void if sync, Promise if async5const result = onRequest({ request, route });6if (result) await result;

This avoids the overhead of emit() in performance-critical code paths.