npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jamx-framework/events

v1.0.0

Published

JAMX Framework — Typed event bus

Downloads

116

Readme

@jamx-framework/events

Descripción

Sistema de eventos (Event Bus) para JAMX Framework. Proporciona un mecanismo de comunicación desacoplada entre componentes de la aplicación mediante publicación/suscripción (pub/sub). Permite que diferentes partes de la aplicación se comuniquen sin tener dependencias directas, ideal para arquitecturas modulares y microservicios.

Cómo funciona

El EventBus implementa el patrón pub/sub:

  1. Registro de listeners: Los componentes se suscriben a eventos específicos con un callback.
  2. Emisión de eventos: Cualquier componente puede publicar un evento en el bus.
  3. Distribución: El bus invoca todos los listeners registrados para ese tipo de evento.
  4. Filtrado: Soporta filtros por tipo de evento y datos adicionales.
  5. Async por defecto: Los listeners pueden ser síncronos o asíncronos (retornan Promise).

Componentes principales

  • src/event-bus.ts: Clase EventBus que gestiona suscripciones y emisión
  • src/index.ts: Punto de exportación

Uso básico

import { EventBus } from '@jamx-framework/events';

// Crear instancia global
const bus = new EventBus();

// Suscribirse a un evento
bus.on('user.created', (data) => {
  console.log('Usuario creado:', data.userId);
});

// Suscribirse una sola vez
bus.once('order.completed', (data) => {
  console.log('Orden completada:', data.orderId);
});

// Emitir evento
bus.emit('user.created', { userId: 123, email: '[email protected]' });

// Emitir evento async
await bus.emitAsync('order.processing', { orderId: 456 });

Ejemplos

Comunicación entre módulos

// En módulo de usuarios
bus.emit('user.registered', { userId: 1, email: '[email protected]' });

// En módulo de notificaciones
bus.on('user.registered', async (data) => {
  await mailer.sendWelcomeEmail(data.email);
});

// En módulo de analytics
bus.on('user.registered', (data) => {
  analytics.track('signup', { userId: data.userId });
});

Eventos con datos estructurados

// Definir tipo para evento
interface UserCreatedEvent {
  userId: number;
  email: string;
  timestamp: Date;
}

// Emitir con tipo
bus.emit<UserCreatedEvent>('user.created', {
  userId: 1,
  email: '[email protected]',
  timestamp: new Date(),
});

// Escuchar con tipo
bus.on('user.created', (event) => {
  console.log(`Usuario ${event.userId} registrado a las ${event.timestamp}`);
});

Manejo de errores en listeners

bus.on('payment.processed', async (data) => {
  try {
    await processPayment(data);
  } catch (error) {
    console.error('Error procesando pago:', error);
    // Opcional: emitir evento de error
    bus.emit('payment.error', { orderId: data.orderId, error });
  }
});

Remover listeners

// Suscribirse y guardar referencia
const handler = (data) => console.log(data);
bus.on('user.updated', handler);

// Remover listener específico
bus.off('user.updated', handler);

// Remover todos los listeners de un evento
bus.off('user.updated');

// Remover todos los listeners de todos los eventos
bus.removeAllListeners();

Eventos con prioridad

// Añadir listener con prioridad (menor número = mayor prioridad)
bus.on('critical.event', (data) => {
  // Se ejecuta primero
}, { priority: 1 });

bus.on('critical.event', (data) => {
  // Se ejecuta después
}, { priority: 10 });

Eventos con wildcard

// Suscribirse a todos los eventos de usuarios
bus.on('user.*', (eventName, data) => {
  console.log(`Evento de usuario: ${eventName}`, data);
});

// Suscribirse a eventos de una jerarquía
bus.on('order.**', (eventName, data) => {
  // Captura order.created, order.updated, order.cancelled, etc.
});

Flujo interno

  1. Registro: on(event, callback, options?) añade el callback a un array de listeners para ese evento.
  2. Emisión: emit(event, data) recorre todos los listeners del evento y los ejecuta en orden de registro (o prioridad).
  3. Async: Si un listener retorna una Promise, se espera a que se resuelva (en emitAsync).
  4. Filtrado: Antes de ejecutar, se pueden aplicar filtros por tipo de evento o datos.
  5. Error handling: Los errores en listeners no detienen la ejecución de otros listeners (se capturan y se emiten opcionalmente en error event).
  6. Memory management: off() y removeAllListeners() permiten limpiar listeners para evitar memory leaks.

API Reference (Resumen)

EventBus

  • on(event: string, callback: Function, options?: ListenerOptions): () => void
  • once(event: string, callback: Function, options?: ListenerOptions): () => void
  • off(event: string, callback?: Function): void
  • emit(event: string, data?: any): void
  • emitAsync(event: string, data?: any): Promise<void>
  • removeAllListeners(event?: string): void
  • listenerCount(event: string): number
  • eventNames(): string[]

ListenerOptions

  • priority?: number — Orden de ejecución (default: 0)
  • once?: boolean — Se ejecuta solo una vez (alternativa a once())
  • async?: boolean — Si se debe esperar a que termine (default: true)

Performance Considerations

  • Listener lookup: Los listeners se almacenan en un Map por evento, O(1) para búsqueda.
  • Async execution: emitAsync espera todos los listeners; emit no espera.
  • Wildcard matching: Los wildcards (*, **) se evalúan con regex y pueden ser costosos con muchos listeners.
  • Memory leaks: Los listeners deben removerse explícitamente cuando el componente se destruye.

Testing

Tests en packages/events/tests/unit/event-bus.test.ts:

pnpm test

Cubre:

  • Registro y desregistración de listeners
  • Emisión síncrona y asíncrona
  • Eventos con wildcard
  • Prioridades de listeners
  • Manejo de errores
  • Conteo de listeners

Compatibility

  • Compatible con Node.js 18+
  • Funciona en navegadores (si se polyfill)
  • No requiere dependencias externas
  • Type-safe con genéricos

Use Cases

  • Comunicación entre módulos: Desacoplar módulos que necesitan comunicarse
  • Eventos de dominio: UserCreated, OrderCompleted, PaymentProcessed
  • Hooks del sistema: beforeStart, afterInit, onShutdown
  • Logging y auditoría: Capturar eventos para registro
  • Reacción a cambios: Actualizar UI cuando cambian datos

Best Practices

  1. Usar nombres de evento consistentes: module.action (ej: user.created, order.updated)
  2. Estructurar datos de eventos: Objetos con campos claros y tipados
  3. Limpiar listeners: En componentes con ciclo de vida, remover listeners al destruir
  4. No abusar: Para comunicación directa entre clases cercanas, usa inyección de dependencias
  5. Documentar eventos: Mantener un registro de eventos que emite cada módulo

This event bus provides a lightweight, type-safe pub/sub system for JAMX applications, enabling loose coupling and reactive architectures with minimal overhead.