Skip to content

The Event Emitter module provides a type-safe, async-capable event system with optional wildcard pattern matching. Methods decorated with @OnEvent() are automatically discovered and wired during bootstrap — no manual registration required.

Installation

No extra dependencies needed — the module is included in nestelia.

Setup

typescript
import { Module } from "nestelia";
import { EventEmitterModule } from "nestelia/event-emitter";

@Module({
  imports: [
    EventEmitterModule.forRoot({
      wildcard: true,  // enable "order.*" and "**" patterns
      global: true,    // make EventEmitterService available everywhere
    }),
  ],
})
export class AppModule {}

Emitting events

Inject EventEmitterService and call emitAsync (awaits all handlers) or emit (fire-and-forget):

typescript
import { Injectable } from "nestelia";
import { EventEmitterService } from "nestelia/event-emitter";
import type { Order } from "./order.schema";

@Injectable()
export class OrdersService {
  constructor(private readonly events: EventEmitterService) {}

  async placeOrder(order: Order) {
    // ... persist order ...
    await this.events.emitAsync("order.created", order);
    return order;
  }
}

@InjectEventEmitter()

Shorthand for @Inject(EVENT_EMITTER_TOKEN):

typescript
import { Injectable } from "nestelia";
import { InjectEventEmitter, EventEmitterService } from "nestelia/event-emitter";

@Injectable()
export class NotificationService {
  constructor(
    @InjectEventEmitter() private readonly events: EventEmitterService,
  ) {}
}

Listening to events

Decorate any method in any @Injectable() provider with @OnEvent(). The module scans all providers during onApplicationBootstrap and registers the handlers automatically.

typescript
import { Injectable } from "nestelia";
import { OnEvent } from "nestelia/event-emitter";
import type { Order } from "./order.schema";

@Injectable()
export class NotificationListener {
  @OnEvent("order.created")
  handleOrderCreated(order: Order) {
    console.log("New order:", order.id);
  }

  @OnEvent("order.shipped")
  handleOrderShipped(order: Order) {
    console.log("Order shipped:", order.id);
  }
}

Register your listener class as a provider in the relevant module:

typescript
@Module({ providers: [NotificationListener] })
export class OrdersModule {}

Once handlers

typescript
@OnEvent("app.initialized", { once: true })
onAppReady(payload: unknown) {
  console.log("Application is ready");
}

Wildcard patterns

Enable wildcard: true in forRoot to use glob-style patterns:

PatternMatches
order.*order.created, order.shipped, …
**.createdorder.created, user.created, …
**every event
typescript
@Injectable()
export class AuditListener {
  @OnEvent("order.*")
  logOrderEvent(order: Order) {
    console.log("Audit:", order.id);
  }

  @OnEvent("**")
  logAll(payload: unknown) {
    console.log("Event fired:", payload);
  }
}

Configuration

EventEmitterModuleOptions

OptionTypeDefaultDescription
wildcardbooleanfalseEnable * / ** wildcard matching
delimiterstring"."Namespace delimiter
maxListenersnumber10Max listeners per event before a warning
globalbooleanfalseRegister as a global module

EventEmitterService API

MethodSignatureDescription
emit(event, payload?) → booleanFire event, don't await handlers
emitAsync(event, payload?) → Promise<unknown[]>Fire event and await all handlers
on(event, handler) → thisRegister persistent handler
once(event, handler) → thisRegister one-time handler
off(event, handler?) → thisRemove handler (or all for event)
removeAllListeners(event?) → thisRemove all listeners
listenerCount(event) → numberNumber of registered handlers

Exports

ExportDescription
EventEmitterModuleModule class
EventEmitterServiceInjectable event emitter service
OnEvent(event, opts?)Method decorator for event handlers
InjectEventEmitter()Parameter decorator shorthand
EVENT_EMITTER_TOKENInjection token
EventEmitterModuleOptionsOptions interface

Released under the MIT License.