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

@contract-kit/provider-event-bus-memory

v0.1.2

Published

In-memory event bus provider for contract-kit - implements EventBusPort for single-process applications

Readme

@contract-kit/provider-event-bus-memory

In-memory event bus provider for contract-kit that implements the EventBusPort interface. Suitable for single-process applications, testing, and development.

For distributed systems, consider implementing EventBusPort with a message broker like RabbitMQ, Kafka, or Redis Pub/Sub.

Installation

npm install @contract-kit/provider-event-bus-memory
# or
bun add @contract-kit/provider-event-bus-memory

TypeScript Requirements

This package requires TypeScript 5.0 or higher for proper type inference.

Usage

Basic Setup

import { createInMemoryEventBus } from "@contract-kit/provider-event-bus-memory";
import { domainEvent } from "@contract-kit/domain";
import { z } from "zod";

// Define your domain events
const UserRegistered = domainEvent(
  "user.registered",
  z.object({
    userId: z.string(),
    email: z.string().email(),
  })
);

// Create the event bus
const eventBus = createInMemoryEventBus();

// Subscribe to events
const unsubscribe = eventBus.subscribe(UserRegistered, (payload) => {
  console.log(`User registered: ${payload.email}`);
  // Send welcome email, update analytics, etc.
});

// Publish events
eventBus.publish(UserRegistered, {
  userId: "123",
  email: "[email protected]",
});

// Unsubscribe when done
unsubscribe();

Integration with Contract Kit

import { createServer } from "@contract-kit/server";
import { createInMemoryEventBus } from "@contract-kit/provider-event-bus-memory";

const basePorts = definePorts({
  eventBus: createInMemoryEventBus(),
  // ... other ports
});

const app = createServer({
  ports: basePorts,
  createContext: ({ ports }) => ({
    ports,
    // ... other context
  }),
  routes: [
    // ... your routes
  ],
});

Using in Use Cases

import { domainEvent } from "@contract-kit/domain";
import { z } from "zod";

const OrderPlaced = domainEvent(
  "order.placed",
  z.object({
    orderId: z.string(),
    total: z.number(),
  })
);

// Subscribe to events in your application setup
ctx.ports.eventBus.subscribe(OrderPlaced, async (payload) => {
  // Send order confirmation email
  await ctx.ports.mailer.sendHtml(
    customer.email,
    "Order Confirmation",
    `Your order ${payload.orderId} has been placed!`
  );
});

// Publish events from your use cases
async function placeOrder(ctx: AppCtx, order: Order) {
  // Save order to database
  await ctx.ports.db.orders.create(order);
  
  // Publish domain event
  ctx.ports.eventBus.publish(OrderPlaced, {
    orderId: order.id,
    total: order.total,
  });
}

EventBus Port API

publish<E>(event: E, payload: InferEventPayload<E>): void

Publish a domain event with a typed payload.

eventBus.publish(UserRegistered, {
  userId: "123",
  email: "[email protected]",
});

Note: Event handlers are executed fire-and-forget. They are not awaited, and errors are not propagated. Wrap your handlers in try/catch for error handling.

subscribe<E>(event: E, handler: (payload) => void | Promise<void>): () => void

Subscribe to a domain event. Returns an unsubscribe function.

const unsubscribe = eventBus.subscribe(UserRegistered, (payload) => {
  console.log(`New user: ${payload.email}`);
});

// Later, when you want to stop listening:
unsubscribe();

TypeScript Support

The event bus provides full type safety:

import type { EventBusPort } from "@contract-kit/ports";

// Type-safe ports definition
const ports = definePorts({
  eventBus: createInMemoryEventBus() as EventBusPort,
  // ... other ports
});

type AppPorts = typeof ports;

Testing

The in-memory event bus is perfect for testing:

import { describe, expect, it, mock } from "bun:test";

describe("User Registration", () => {
  it("should publish UserRegistered event", () => {
    const eventBus = createInMemoryEventBus();
    const handler = mock(() => {});
    
    eventBus.subscribe(UserRegistered, handler);
    
    // Perform registration
    registerUser(ctx, { email: "[email protected]" });
    
    expect(handler).toHaveBeenCalledWith({
      userId: expect.any(String),
      email: "[email protected]",
    });
  });
});

Behavior

  • Fire-and-forget: Event handlers are executed asynchronously and not awaited
  • In-process: Events are only delivered within the same process
  • Memory-only: No persistence - events are lost if the process crashes
  • Order: Handlers are called in the order they were subscribed
  • Multiple handlers: Multiple handlers can subscribe to the same event
  • Error handling: Errors in handlers do not affect other handlers or the publisher

When to Use

Good for:

  • Single-process applications
  • Development and testing
  • Simple event-driven workflows
  • Decoupling application components

Not suitable for:

  • Distributed systems
  • Event persistence requirements
  • Guaranteed delivery needs
  • Cross-service communication

For production distributed systems, implement EventBusPort with a proper message broker.

License

MIT