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.
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
});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);
}
}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;
}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);
});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;
};
}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'
});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;
};