or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

ace-commands.mdapplication.mdauth-hash.mdcommands.mdconfig-env.mdevents.mdhelpers.mdhttp-server.mdindex.mdlogging.mdtest-utils.md
tile.json

events.mddocs/

Event System

Pub/sub event system for building loosely coupled applications. AdonisJS Core re-exports the complete @adonisjs/events package for creating reactive applications with type-safe event handling.

Capabilities

Event Emitter

Type-safe event emitter for publishing and subscribing to application events.

/**
 * Event emitter for type-safe pub/sub communication
 */
class Emitter {
  /**
   * Emit an event with data
   * @param event - Event name (must be keyof EventsList)
   * @param data - Event data payload
   */
  emit<T extends keyof EventsList>(event: T, data: EventsList[T]): void;

  /**
   * Listen for events
   * @param event - Event name to listen for
   * @param handler - Event handler function
   */
  on<T extends keyof EventsList>(
    event: T, 
    handler: EventHandler<EventsList[T]>
  ): void;

  /**
   * Listen for events once (auto-unsubscribe after first emission)
   * @param event - Event name to listen for
   * @param handler - Event handler function
   */
  once<T extends keyof EventsList>(
    event: T, 
    handler: EventHandler<EventsList[T]>
  ): void;

  /**
   * Remove event listener
   * @param event - Event name
   * @param handler - Handler function to remove
   */
  off<T extends keyof EventsList>(
    event: T, 
    handler: EventHandler<EventsList[T]>
  ): void;

  /**
   * Remove all listeners for an event
   * @param event - Event name to clear listeners for
   */
  removeAllListeners<T extends keyof EventsList>(event: T): void;

  /**
   * Get list of listeners for an event
   * @param event - Event name
   * @returns Array of handler functions
   */
  listeners<T extends keyof EventsList>(event: T): EventHandler<EventsList[T]>[];

  /**
   * Get number of listeners for an event
   * @param event - Event name
   * @returns Number of listeners
   */
  listenerCount<T extends keyof EventsList>(event: T): number;

  /**
   * Check if event has listeners
   * @param event - Event name
   * @returns True if event has listeners
   */
  hasListeners<T extends keyof EventsList>(event: T): boolean;
}

Usage Examples:

import { Emitter } from "@adonisjs/core/events";

const emitter = new Emitter();

// Listen for user registration
emitter.on('user:registered', (data) => {
  console.log(`New user registered: ${data.email}`);
  // Send welcome email
});

// Listen once for server ready
emitter.once('http:server_ready', (data) => {
  console.log(`Server started on ${data.host}:${data.port}`);
});

// Emit events
emitter.emit('user:registered', {
  id: 1,
  email: 'user@example.com',
  name: 'John Doe'
});

emitter.emit('http:server_ready', {
  host: 'localhost',
  port: 3333,
  duration: [0, 150000000] // hrtime
});

Event Listeners

Class-based event listeners for organizing event handling logic.

/**
 * Base event listener class
 */
abstract class BaseEventListener {
  /**
   * Handle the event
   * @param data - Event data
   */
  abstract handle(data: any): Promise<void> | void;

  /**
   * Handle event failures
   * @param error - Error that occurred
   * @param data - Event data that caused the error
   */
  failed?(error: Error, data: any): Promise<void> | void;
}

/**
 * Event listener decorator for method-based handlers
 * @param event - Event name to listen for
 */
function eventListener(event: string): MethodDecorator;

Usage Examples:

import { BaseEventListener, eventListener } from "@adonisjs/core/events";

// Class-based event listener
export default class UserRegisteredListener extends BaseEventListener {
  async handle(data: { id: number; email: string; name: string }) {
    // Send welcome email
    await this.sendWelcomeEmail(data.email, data.name);
    
    // Create user profile
    await this.createUserProfile(data.id);
  }

  async failed(error: Error, data: any) {
    console.error('Failed to handle user registration:', error);
    // Log to error tracking service
  }

  private async sendWelcomeEmail(email: string, name: string) {
    // Email sending logic
  }

  private async createUserProfile(userId: number) {
    // Profile creation logic
  }
}

// Method-based event handling
export default class NotificationService {
  @eventListener('user:registered')
  async onUserRegistered(data: { email: string; name: string }) {
    await this.sendWelcomeNotification(data.email, data.name);
  }

  @eventListener('order:placed')
  async onOrderPlaced(data: { orderId: string; userId: number }) {
    await this.sendOrderConfirmation(data.orderId, data.userId);
  }
}

Event Bus

Advanced event bus for complex event handling scenarios.

/**
 * Event bus for advanced event management
 */
class EventBus extends Emitter {
  /**
   * Register event listener class
   * @param listener - Event listener class instance
   */
  registerListener(listener: BaseEventListener): void;

  /**
   * Register multiple listeners
   * @param listeners - Array of listener instances
   */
  registerListeners(listeners: BaseEventListener[]): void;

  /**
   * Emit event with error handling
   * @param event - Event name
   * @param data - Event data
   * @param options - Emission options
   */
  emitSafely<T extends keyof EventsList>(
    event: T,
    data: EventsList[T],
    options?: EmitOptions
  ): Promise<void>;

  /**
   * Create event namespace
   * @param namespace - Namespace prefix
   * @returns Namespaced event bus
   */
  namespace(namespace: string): NamespacedEventBus;

  /**
   * Add middleware for event processing
   * @param middleware - Middleware function
   */
  use(middleware: EventMiddleware): void;
}

/**
 * Namespaced event bus for modular event handling
 */
class NamespacedEventBus {
  /**
   * Emit namespaced event
   * @param event - Event name (will be prefixed with namespace)
   * @param data - Event data
   */
  emit(event: string, data: any): void;

  /**
   * Listen for namespaced events
   * @param event - Event name
   * @param handler - Event handler
   */
  on(event: string, handler: EventHandler<any>): void;

  /**
   * Remove namespace prefix and emit on main bus
   * @param event - Event name
   * @param data - Event data
   */
  bubble(event: string, data: any): void;
}

Event Middleware

Middleware system for event processing pipeline.

/**
 * Event middleware function type
 */
type EventMiddleware = (
  event: string,
  data: any,
  next: () => Promise<void>
) => Promise<void>;

/**
 * Pre-built event middleware
 */
namespace EventMiddleware {
  /**
   * Logging middleware for events
   * @param logger - Logger instance
   * @returns Middleware function
   */
  function logging(logger: Logger): EventMiddleware;

  /**
   * Rate limiting middleware for events
   * @param options - Rate limiting options
   * @returns Middleware function
   */
  function rateLimit(options: RateLimitOptions): EventMiddleware;

  /**
   * Error handling middleware
   * @param errorHandler - Error handler function
   * @returns Middleware function
   */
  function errorHandler(
    errorHandler: (error: Error, event: string, data: any) => void
  ): EventMiddleware;

  /**
   * Event validation middleware
   * @param schemas - Validation schemas for events
   * @returns Middleware function
   */
  function validation(schemas: Record<string, any>): EventMiddleware;
}

Usage Examples:

import { EventBus, EventMiddleware } from "@adonisjs/core/events";

const eventBus = new EventBus();

// Add middleware
eventBus.use(EventMiddleware.logging(logger));
eventBus.use(EventMiddleware.rateLimit({ maxEvents: 100, windowMs: 60000 }));

// Create namespaced bus
const userEvents = eventBus.namespace('user');

// Emit namespaced events
userEvents.emit('registered', { email: 'user@example.com' });
// This emits 'user:registered' on the main bus

// Listen for namespaced events
userEvents.on('registered', (data) => {
  console.log('User registered:', data.email);
});

Built-in Events

Pre-defined events emitted by AdonisJS Core framework.

/**
 * Built-in event types in AdonisJS Core
 */
interface EventsList {
  /** Container binding resolved */
  'container_binding:resolved': ContainerResolveEventData<ContainerBindings>;
  
  /** HTTP server ready */
  'http:server_ready': {
    port: number;
    host: string;
    duration: [number, number]; // hrtime
  };

  /** HTTP request received */
  'http:request_received': {
    method: string;
    url: string;
    headers: Record<string, string>;
  };

  /** HTTP response sent */
  'http:response_sent': {
    method: string;
    url: string;
    statusCode: number;
    duration: [number, number]; // hrtime
  };

  /** Application booted */
  'app:booted': {
    environment: string;
    bootDuration: [number, number]; // hrtime
  };

  /** Application terminating */
  'app:terminating': {
    reason: string;
  };
}

Event Contracts

Interfaces for extending the event system.

/**
 * Event handler function type
 */
type EventHandler<T> = (data: T) => Promise<void> | void;

/**
 * Container resolve event data
 */
interface ContainerResolveEventData<T> {
  binding: keyof T;
  value: T[keyof T];
  resolver: Function;
}

/**
 * Event emission options
 */
interface EmitOptions {
  /** Continue on error */
  continueOnError?: boolean;
  /** Maximum concurrent handlers */
  concurrency?: number;
  /** Timeout for handlers */
  timeout?: number;
}

/**
 * Rate limiting options for events
 */
interface RateLimitOptions {
  /** Maximum events per window */
  maxEvents: number;
  /** Time window in milliseconds */
  windowMs: number;
  /** Skip function for selective rate limiting */
  skip?: (event: string, data: any) => boolean;
}

Usage Examples:

// Extending event types in user code
declare module "@adonisjs/core/events" {
  interface EventsList {
    'user:registered': {
      id: number;
      email: string;
      name: string;
    };
    'order:placed': {
      orderId: string;
      userId: number;
      total: number;
    };
    'payment:processed': {
      paymentId: string;
      orderId: string;
      amount: number;
      status: 'success' | 'failed';
    };
  }
}

// Now these events are type-safe
emitter.emit('user:registered', {
  id: 1,
  email: 'user@example.com',
  name: 'John Doe'
});

Types

interface ContainerBindings {
  [key: string]: any;
}

type Logger = {
  info(message: string, meta?: any): void;
  error(message: string, meta?: any): void;
  warn(message: string, meta?: any): void;
  debug(message: string, meta?: any): void;
};