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

@vydra-js/bus

v0.0.1

Published

Event Bus system with scoped pub/sub and RPC capabilities for microfrontend communication. Provides isolation between microfrontends while enabling event-driven interaction.

Downloads

19

Readme

@vydra-js/bus

Event Bus system with scoped pub/sub and RPC capabilities for microfrontend communication. Provides isolation between microfrontends while enabling event-driven interaction.

Installation

npm install @vydra-js/bus

Quick Start

import { VydraBus } from '@vydra-js/bus';

// Create a scoped event bus
const bus = new VydraBus('global');

// Subscribe to events
bus.subscribe('user:login', (event) => {
  console.log('User logged in:', event.detail);
});

// Publish events
bus.emit('user:login', { userId: '123' });

API

VydraBus

Main event bus class with scoped isolation.

new VydraBus(scope: string)

Constructor

new VydraBus(scope: string)

The scope parameter defines the isolation level:

  • "global" - All microfrontends can communicate
  • "mfe:<name>" - Isolated to specific microfrontend
  • Any custom scope for targeted communication

Methods

subscribe<T>(event: string, handler: EventHandler<T>): () => void

Subscribes to an event. Returns unsubscribe function.

const unsubscribe = bus.subscribe('user:login', (event) => {
  console.log(event.detail);
});

// Later, unsubscribe
unsubscribe();
subscribeOnce<T>(event: string, handler: EventHandler<T>): void

Subscribes for exactly one emission.

bus.subscribeOnce('app:ready', (event) => {
  console.log('Ready!');
});
emit<T>(event: string, detail?: T): void

Emits an event to all subscribers.

bus.emit('user:login', { userId: '123' });
unsubscribe(event?: string, handler?: EventHandler): void

Unsubscribes from events.

// Unsubscribe specific handler
bus.unsubscribe('user:login', myHandler);

// Unsubscribe all handlers for event
bus.unsubscribe('user:login');

// Unsubscribe all handlers
bus.unsubscribe();

RPC Methods

rpc<T>(event: string, detail?: any): Promise<T>

Request-response pattern over the event bus.

const result = await bus.rpc<string>('compute:add', { a: 1, b: 2 });
console.log(result); // 3
respond<T>(event: string, handler: RpcHandler<T>): void

Registers an RPC handler.

bus.respond<{ a: number; b: number }, number>('compute:add', async ({ detail }) => {
  return detail.a + detail.b;
});

Concepts

Why Event Bus?

  • Decoupled communication: Components don't reference each other directly
  • Scoped isolation: Events stay within their scope
  • Built-in RPC: Request-response over events
  • Type-safe: Full TypeScript support

Scopes

| Scope | Description | | -------------- | ----------------------------- | | "global" | All MFEs can subscribe/emit | | "mfe:<name>" | Specific MFE only | | Custom | Any custom isolation boundary |

Event Flow

  1. Component A calls bus.emit("event", data)
  2. Bus dispatches to all handlers in matching scope
  3. Each handler receives CustomEvent
  4. detail property contains data

Usage Examples

Basic Pub/Sub

// In component A
const bus = new VydraBus('global');
bus.emit('theme:change', 'dark');

// In component B
const bus = new VydraBus('global');
bus.subscribe('theme:change', (event) => {
  document.body.setAttribute('data-theme', event.detail);
});

Cross-MF Communication

// In MFE "auth"
const authBus = new VydraBus('global');
authBus.emit('auth:login', { user: getCurrentUser() });

// In MFE "cart"
const cartBus = new VydraBus('global');
cartBus.subscribe('auth:login', (event) => {
  // Update cart with logged-in user
  loadUserCart(event.detail.user.id);
});
cartBus.subscribe('auth:logout', () => {
  clearCart();
});

RPC Usage

// Handler (in MFE "api")
bus.respond<{ id: string }, User | null>('user:get', async ({ detail }) => {
  return await fetchUser(detail.id);
});

// Request (in MFE "ui")
const bus = new VydraBus('global');
const user = await bus.rpc<User | null>('user:get', { id: '123' });

Cleanup

class MyComponent extends LitElement {
  private bus = new VydraBus('global');
  private unsubscribe?: () => void;

  connectedCallback() {
    super.connectedCallback();
    this.unsubscribe = this.bus.subscribe('data:update', () => this.requestUpdate());
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    this.unsubscribe?.();
  }
}

Event Bus Factory

For convenience, you can create a factory function:

function useBus(scope = 'global') {
  return new VydraBus(scope);
}

// Usage
const globalBus = useBus();
const mfeBus = useBus('mfe:app1');

Scoped Communication

Within a Microfrontend

const bus = new VydraBus('mfe:dashboard');
bus.subscribe('internal:event', handleInternal);

Cross Microfrontends

const bus = new VydraBus('global');
bus.emit('cart:add', { productId: '123', quantity: 1 });

Isolated Events

// In shell
const shellBus = new VydraBus('global');

// In MFE - emit to shell only
const mfeBus = new VydraBus('mfe:cart');

Integration

With Router

Router emits navigation events:

const bus = new VydraBus('global');
bus.subscribe('router:navigate', (event) => {
  analytics.track('page_view', { path: event.detail.path });
});

With Forms

const bus = new VydraBus('global');
bus.subscribe('form:submit', async (event) => {
  const response = await submitForm(event.detail);
  bus.emit('form:success', response);
});

With HTTP

const bus = new VydraBus('global');
bus.subscribe('http:request', (event) => {
  // Add auth token
  event.detail.headers.Authorization = getToken();
});

Best Practices

  1. Use meaningful event names

    // Good
    'user:login';
    'cart:item-added';
    
    // Bad
    'event1';
    'update';
  2. Unsubscribe when done

    disconnectedCallback() {
      super.disconnectedCallback();
      this.unsubscribe?.();
    }
  3. Use scopes appropriately

    // For cross-MF use global
    const bus = new VydraBus('global');
    
    // For internal MFE use scoped
    const bus = new VydraBus('mfe:myapp');
  4. Avoid creating new instances

    // Good - reuse
    const globalBus = new VydraBus("global");
    
    // Bad - create in render
    render() {
      new VydraBus("global") // Creates new each render
    }

Type Definitions

type EventHandler<T = any> = (event: CustomEvent<T>) => void;

type RpcHandler<T = any, R = any> = (event: CustomEvent<T>) => R | Promise<R>;

interface VydraBusOptions {
  strict?: boolean;
}

interface EventMap {
  [event: string]: EventHandler[];
}

Events Reference

Common events used in Vydra ecosystem:

| Event | Description | Detail | | ------------------- | ------------------- | ------------------ | | router:navigate | Navigation occurred | { path, params } | | auth:login | User logged in | { user } | | auth:logout | User logged out | - | | i18n:change | Language changed | { lang } | | theme:change | Theme changed | { theme } | | mf:switch-request | Cross-MF navigation | { path, mf } |

See Also