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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@looqey/eventtide

v1.4.0

Published

An type-save event bus implementation with exception suppressing.

Downloads

36

Readme

Eventtide: Type safe, SSR-friendly event bus

A robust, type-safe event bus library for TypeScript, enabling seamless event-driven communication within your applications. Designed with developer experience in mind, this library leverages TypeScript’s powerful type system to ensure type safety, IntelliSense support, and an intuitive chain-based API.

📦 Features

  • Type-Safe Event Definitions: Define any event with custom payloads, ensuring compile-time type safety.
  • Chain-Based API: Fluent and intuitive syntax for subscribing and emitting events.
  • Subscription Management: Easily unsubscribe or manually trigger listeners.
  • Error Handling Options: Configure the bus to suppress or handle listener errors gracefully.
  • Dependency Injection Friendly: No any global objects. You will rule the initializing and storing bus instances.
  • Minimal Runtime Overhead: Efficient listener management without unnecessary runtime objects.

🚀 Installation

Install the library via npm or yarn:

npm install @looqey/eventtide
# or
yarn @looqey/eventtide

🔧 Usage

1. Define Your Event Schema

Start by defining a TypeScript type that outlines your event names and their corresponding payloads.

// mySchema.ts

export type MyBusSchema = {
  userCreated: { userId: string; name: string };
  orderPlaced: { orderId: string; amount: number };
  paymentProcessed: number; // Example of a simple payload type
};

2. Create an Event Bus Instance

Instantiate the event bus with your defined schema. Optionally, configure error handling behavior.

// main.ts

import { createBus } from '@looqey/eventtide';
import { MyBusSchema } from './mySchema';

const bus = createBus<MyBusSchema>({ suppress: true }); // Suppress listener errors

3. Subscribe to Events

Use the chain-based API to subscribe to events. Subscriptions return an object allowing you to unsubscribe or manually trigger the listener.

// subscribing.ts

const userCreatedSubscription = bus.on().userCreated((payload) => {
  console.log(`User created: ${payload.userId}, Name: ${payload.name}`);
});

const orderPlacedSubscription = bus.on().orderPlaced((payload) => {
  console.log(`Order placed: ${payload.orderId}, Amount: $${payload.amount}`);
});

4. Emit Events

Emit events using the chain-based API. TypeScript ensures that the payload matches the defined schema.

// emitting.ts

// Emit userCreated event
bus.emit().userCreated({ userId: 'u123', name: 'Alice' });

// Emit orderPlaced event
bus.emit().orderPlaced({ orderId: 'o456', amount: 250 });

// Emit paymentProcessed event
bus.emit().paymentProcessed(1000);

5. Manage Subscriptions

Unsubscribe from events or manually trigger listeners as needed.

// managingSubscriptions.ts

// Unsubscribe from userCreated event
userCreatedSubscription.off();

// Manually trigger orderPlaced listener
orderPlacedSubscription.fire({ orderId: 'o789', amount: 300 });

📚 API Reference

createBus<Schema>(options?: BusOptions): EventBus<Schema>

Creates a new event bus instance with the specified schema and options.

  • Generics:

    • Schema: Defines the structure of events and their payloads.
  • Parameters:

    • options (optional): Configuration options for the event bus.
      • suppress?: boolean: If true, errors thrown by listeners during event emission are logged to the console instead of being thrown, preventing the interruption of subsequent listeners. Default is false.
  • Returns:

    • EventBus<Schema>: The event bus instance.

EventBus<Schema>

Interface defining the structure and methods of the event bus.

Methods:

  • on(): OnBuilder<Schema>

    Subscribes to events using a chain-based approach.

    • Usage:

      bus.on().eventName(callback);
    • Returns:

      • An object where each key corresponds to an event name defined in Schema, and each value is a function to register a listener for that event. The listener registration function returns a Subscription object.
  • emit(): EmitBuilder<Schema>

    Emits events using a chain-based approach.

    • Usage:

      bus.emit().eventName(payload);
    • Returns:

      • An object where each key corresponds to an event name defined in Schema, and each value is a function to emit the event with the specified payload.

Subscription<Payload>

Represents a subscription to an event, providing methods to manage the listener.

  • Methods:
    • off(): void
      • Unsubscribes the listener from the event.
    • fire(payload: Payload): void
      • Manually triggers the listener with the provided payload.

BusOptions

Configuration options for creating the event bus.

  • Properties:
    • suppress?: boolean
      • If true, suppresses exceptions thrown by listeners during event emission, logging them to the console instead.

🛠️ Error Handling

By default, if a listener throws an error during event emission, the error propagates, potentially interrupting the execution of subsequent listeners. To change this behavior, enable the suppress option when creating the bus:

const bus = createBus<MyBusSchema>({ suppress: true });

With suppress enabled, errors thrown by listeners are caught and logged to the console, allowing other listeners to continue executing.

🔒 Type Safety

This library leverages TypeScript’s generics and mapped types to ensure:

  • Event Names: Only defined event names in the schema can be subscribed to or emitted.
  • Payloads: Payloads must match the type specified for each event.
  • IntelliSense Support: Full auto-completion for event names and payloads in supported IDEs.

Example of Type Safety in Action

// Correct usage
bus.emit().orderPlaced({ orderId: 'o123', amount: 250 });

// TypeScript Error: Argument of type 'string' is not assignable to parameter of type 'number'.
bus.emit().paymentProcessed('not-a-number');

🧩 Integration

This library is framework-agnostic. Nevertheless, there is at least one catchy moment.

Important Note:
Event bus instances cannot be serialized. If you are using server-side rendering (SSR) frameworks like Nuxt, ensure that event bus instances are only created and used in appropriate contexts. To avoid SSR-related issues, you can use a mock event bus during server-side execution and switch to the real event bus on the client side.

Using a Mock Bus for SSR

For SSR scenarios, we recommend using the createMockBus utility to initialize a no-op event bus instance. This avoids issues with serialization and ensures smooth server-client handoff.

Example Integration in Nuxt

// plugins/buses.ts

import { createBus, createMockBus } from '@looqey/eventtide';
import { MyBusSchema } from '@/mySchema';

export default defineNuxtPlugin((nuxtApp) => {
  // Use the mock bus during SSR
  const isSSR = import.meta.server;
  const bus = isSSR ? createMockBus<MyBusSchema>() : createBus<MyBusSchema>({ suppress: true });

  nuxtApp.provide('bus', bus);
});

Key Benefits of Using the Mock Bus

  1. SSR Safety: Avoids issues with serialization and hydration by ensuring no listeners or events are retained on the server.
  2. Uniform API: Maintains the same API as the real event bus, so no additional changes are required in your client-side or shared logic.
  3. Testing: Useful for environments where you don’t need the real bus, such as tests focused on unrelated logic.

👩‍💻 Contributing

Contributions are welcome! Please open issues or submit pull requests for any enhancements, bug fixes, or new features.

📜 License

This library is licensed under the MIT license.

🙏 Acknowledgements

Inspired by common patterns in event-driven architectures and modern TypeScript practices to ensure type safety and developer productivity.