New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@fioc/event-bus

Package Overview
Dependencies
Maintainers
2
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fioc/event-bus

Type-safe event bus with CQRS support for FIoC. Build event-driven architectures with commands, queries, notifications, and middleware - fully integrated with dependency injection.

latest
Source
npmnpm
Version
1.0.4
Version published
Weekly downloads
4
-60%
Maintainers
2
Weekly downloads
 
Created
Source

@fioc/event-bus

FIoC Event Bus provides a comprehensive, type-safe event-driven architecture system built on top of @fioc/core.
It enables CQRS (Command Query Responsibility Segregation), domain events, and event-driven patterns with full dependency injection integration — completely reflection-free and decorator-free.

💡 Built for complex event-driven architectures, microservices, and domain-driven design — without reflection or decorators.

🚀 Quick Start

Install via npm, yarn, or pnpm:

npm install @fioc/event-bus @fioc/core

# or

yarn add @fioc/event-bus @fioc/core

# or

pnpm add @fioc/event-bus @fioc/core

📘 Table of Contents

🧩 Core Concepts

The Event Bus package introduces several key abstractions for building event-driven applications:

ConceptDescription
INotificationDomain events that can have multiple handlers
ICommandCommands that perform actions (single handler)
IQueryQueries that retrieve data (single handler)
IEventBusCentral service for publishing events and invoking commands/queries
IHandlerMiddlewareInterceptors for cross-cutting concerns

Everything is fully typed, DI-integrated, and metadata-aware — no decorators, no reflect-metadata.

🔔 Defining Events & Commands

Notifications (Domain Events)

import { createNotificationDIToken } from "@fioc/event-bus";

// Define notification payload type
export type UserRegisteredPayload = {
  userId: string;
  email: string;
  timestamp: Date;
};

export interface UserRegisteredNotification
  extends INotification<UserRegisteredPayload> {}

// Create notification token
export const UserRegisteredNotificationToken =
  createNotificationDIToken<UserRegisteredNotification>().as("UserRegistered", {
    generics: [
      /* Optional payload token */
    ],
  });

Commands

import { createCommandDIToken } from "@fioc/event-bus";

export type CreateUserCommandPayload = {
  email: string;
  password: string;
  name: string;
};

export interface CreateUserCommand
  extends ICommand<CreateUserCommandPayload, string> {}

export const CreateUserCommandToken =
  createCommandDIToken<CreateUserCommand>().as("CreateUser");

Queries

import { createQueryDIToken } from "@fioc/event-bus";

export type GetUserByIdQueryPayload = {
  userId: string;
};

export interface GetUserByIdQuery
  extends IQuery<GetUserByIdQueryPayload, User> {}

export const GetUserByIdQuery =
  createQueryDIToken<GetUserByIdQuery>().as("GetUserById");

🛠️ Creating Handlers

Notification Handlers (Multiple per Event)

import { createNotificationHandlerDIToken } from "@fioc/event-bus";
import { UserRegisteredNotification } from "./events";

export interface SendWelcomeEmailHandler
  extends INotificationHandler<UserRegisteredNotification> {}

export const SendWelcomeEmailHandlerToken =
  createNotificationHandlerDIToken().as("SendWelcomeEmail", {
    generics: [UserRegisteredNotificationToken], // Needs to specify the notification token
  });

// Implementation
const sendWelcomeEmailHandlerImpl: SendWelcomeEmailHandler = {
  async handle(payload) {
    await emailService.sendWelcomeEmail(event.payload.email);
  },
};

Command Handlers (Single per Command)

import { createCommandHandlerDIToken } from "@fioc/event-bus";
import { CreateUserCommand } from "./commands";

export interface CreateUserHandler extends ICommandHandler<CreateUserCommand> {}

export const CreateUserHandlerToken = createCommandHandlerDIToken().as(
  "CreateUserHandler",
  {
    generics: [CreateUserCommandToken], // Needs to specify the command token
  }
);

// Implementation
const createUserHandlerImpl: CreateUserHandler = {
  async handle(command: { payload: CreateUserCommandPayload }) {
    const user = await userService.createUser(command.payload);
    return user.id; // Must match command result type
  },
};

Query Handlers (Single per Query)

import { createQueryHandlerDIToken } from "@fioc/event-bus";
import { GetUserByIdQuery } from "./queries";

export interface GetUserByIdHandler extends IQueryHandler<GetUserByIdQuery> {}

export const GetUserByIdHandlerToken = createQueryHandlerDIToken().as(
  "GetUserByIdHandler",
  {
    generics: [GetUserByIdQueryToken], // Needs to specify the query token
  }
);

// Implementation
const getUserByIdHandlerImpl: GetUserByIdHandler = {
  async handle(query: { payload: GetUserByIdQueryPayload }) {
    return await userRepository.findById(query.payload.userId);
  },
};

📡 Using the Event Bus

Basic Setup

import { buildDIContainer } from "@fioc/core";
import { EventBusFactory, IEventBusToken } from "@fioc/event-bus";

const container = buildDIContainer()
  .registerFactory(IEventBusToken, EventBusFactory)
  .register(SendWelcomeEmailHandlerToken, sendWelcomeEmailHandler)
  .register(CreateUserHandlerToken, createUserHandler)
  .register(GetUserByIdHandlerToken, getUserByIdHandler)
  .getResult();

const eventBus = container.resolve(IEventBusToken);

Publishing Notifications

// Publish a domain event
await eventBus.publish({
  token: UserRegisteredNotification,
  payload: {
    userId: "123",
    email: "user@example.com",
    timestamp: new Date(),
  },
  createdAt: new Date(),
});

// With different execution strategies
await eventBus.publish(notification, "parallel"); // All handlers run concurrently
await eventBus.publish(notification, "sequential"); // Handlers run one after another
await eventBus.publish(notification, "besteffort"); // Parallel but continue on handler errors

Invoking Commands & Queries

// Invoke a command
const userId = await eventBus.invoke({
  token: CreateUserCommand,
  payload: {
    email: "user@example.com",
    password: "securepassword",
    name: "John Doe",
  },
  createdAt: new Date(),
});

// Invoke a query
const user = await eventBus.invoke({
  token: GetUserByIdQuery,
  payload: { userId: "123" },
  createdAt: new Date(),
});

🔌 Middleware & Interceptors

Middleware allows you to implement cross-cutting concerns like logging, validation, and error handling.

Creating Middleware

import { createMiddlewareDIToken, IQueryToken, ICommandToken } from "@fioc/event-bus";

export interface LoggingMiddleware extends IHandlerMiddleware<IQuery<any> | ICommand<any> ,unknown>

export const LoggingMiddleware = createMiddlewareDIToken().as(
  "LoggingMiddleware",
  {
    generics: [IQueryToken, ICommandToken], // Apply to all commands and queries
  }
);

const loggingMiddleware = {
  async handle(request, next: (request: any) => Promise<any>) {
    console.log("Processing request:", request.token.key);
    const startTime = Date.now();

    try {
      const result = await next(request);
      console.log("Request completed in", Date.now() - startTime, "ms");
      return result;
    } catch (error) {
      console.error("Request failed:", error);
      throw error;
    }
  },
};

Middleware Registration & Ordering

import { MiddleWareOrderToken } from "@fioc/event-bus";

const container = buildDIContainer()
  .register(MiddleWareOrderToken, [LoggingMiddleware, ValidationMiddleware]) // Middleware Order declaration
  .registerFactory(IEventBusToken, EventBusFactory)
  .register(LoggingMiddleware, loggingMiddleware)
  .register(ValidationMiddleware, validationMiddleware)
  .getResult();

Applying Middleware to Specific Event Types

// Apply to all notifications
const NotificationLoggingMiddleware = createMiddlewareDIToken().as(
  "NotificationLogging",
  {
    generics: [INotificationToken], // Apply to all notifications
  }
);

// Apply to specific notification
const UserEventMiddleware = createMiddlewareDIToken().as(
  "UserEventMiddleware",
  {
    generics: [UserRegisteredNotification], // Apply only to user registration
  }
);

// Apply to multiple types
const CommandQueryMiddleware = createMiddlewareDIToken().as(
  "CommandQueryMiddleware",
  {
    generics: [ICommandToken, IQueryToken], // Apply to all commands and queries
  }
);

⚡ Execution Strategies

The event bus supports different execution strategies for notification handlers:

Parallel (Default)

await eventBus.publish(notification, "parallel");
  • All handlers execute concurrently
  • Fastest execution time
  • Use when handlers are independent

Sequential

await eventBus.publish(notification, "sequential");
  • Handlers execute one after another
  • Guaranteed order of execution
  • Use when handlers have dependencies

Best Effort (Default)

const errors = await eventBus.publish(notification, "besteffort");
  • All handlers execute concurrently
  • Continues execution even if some handlers fail
  • Returns array of errors from failed handlers
  • Use for non-critical background tasks

📚 API Reference

Core Tokens

TokenDescription
IEventBusTokenThe main event bus service
MiddleWareOrderTokenArray defining middleware execution order
INotificationTokenBase token for all notifications
ICommandTokenBase token for all commands
IQueryTokenBase token for all queries
INotificationHandlerTokenBase token for notification handlers
ICommandHandlerTokenBase token for command handlers
IQueryHandlerTokenBase token for query handlers
IHandlerMiddlewareTokenBase token for middleware

Factory Functions

FunctionDescription
createNotificationDIToken()Creates notification tokens
createCommandDIToken()Creates command tokens
createQueryDIToken()Creates query tokens
createNotificationHandlerDIToken()Creates notification handler tokens
createCommandHandlerDIToken()Creates command handler tokens
createQueryHandlerDIToken()Creates query handler tokens
createMiddlewareDIToken()Creates middleware tokens

Interfaces

InterfaceDescription
IEventBusMain event bus interface
INotification<T>Domain event interface
ICommand<T, R>Command interface
IQuery<T, R>Query interface
INotificationHandler<T>Notification handler interface
ICommandHandler<T>Command handler interface
IQueryHandler<T>Query handler interface
IHandlerMiddleware<T, R>Middleware interface

🤝 Contributing

Contributions are welcome!
Open an issue or submit a PR on GitHub.

Please include tests for new features or fixes and keep commits focused.

📜 License

Licensed under the MIT License.

Keywords

event-bus

FAQs

Package last updated on 24 Nov 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts