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

@esmap/communication

v0.1.0

Published

Inter-app communication primitives: event bus, global state, and app props

Readme

@esmap/communication

Inter-app communication primitives — event bus, global state, and app props.

A standalone package for data sharing between MFEs. Zero external dependencies.

Installation

pnpm add @esmap/communication

Event Bus

Type-safe pub/sub event bus:

import { createEventBus } from '@esmap/communication';
import type { EventBus } from '@esmap/communication';

// Define a typed event map
type AppEvents = {
  'user:login': { userId: string; role: string };
  'cart:update': { itemCount: number };
  'notification:show': { message: string; level: 'info' | 'error' };
};

const bus: EventBus<AppEvents> = createEventBus<AppEvents>({
  maxHistory: 50, // Event history limit (default: 100)
  onHandlerError: (event, error) => {
    // Handler error callback (optional)
    console.error(`Handler error in ${event}:`, error);
  },
});

// Subscribe — payload type is inferred automatically
const unsubscribe = bus.on('user:login', (payload) => {
  console.log(payload.userId); // string
  console.log(payload.role); // string
});

// One-time subscription
bus.once('cart:update', (payload) => {
  console.log(payload.itemCount);
});

// Emit — payload type is checked at compile time
bus.emit('user:login', { userId: '123', role: 'admin' });

// Unsubscribe
unsubscribe();

// Remove all listeners for a specific event
bus.off('cart:update');

// Query history
bus.getHistory(); // all events
bus.getHistory('user:login'); // specific event only

// Listener count
bus.listenerCount('user:login'); // number

// Clear everything
bus.clear();

Handler error isolation: If one handler throws, the remaining handlers still execute.

Global State

Shared state management across apps:

import { createGlobalState } from '@esmap/communication';

const state = createGlobalState({
  currentUser: null as string | null,
  theme: 'light' as 'light' | 'dark',
  locale: 'en',
});

// Read (frozen copy)
const current = state.getState();

// Write (shallow merge)
state.setState({ theme: 'dark' });

// Subscribe
const unsubscribe = state.subscribe((newState, prevState) => {
  console.log('State changed:', prevState, '->', newState);
});

// Subscribe to a specific key only
state.select('theme', (newTheme, prevTheme) => {
  document.body.dataset.theme = newTheme;
});

// Reset to initial state
state.reset();

No-op optimization: Uses Object.is() comparison — subscribers are not notified if no values actually changed.

App Props

Props passing between MFEs:

import { createAppProps } from '@esmap/communication';

const appProps = createAppProps({ userId: '', permissions: [] as string[] });

// Host sets props
appProps.setProps({ userId: '123', permissions: ['read', 'write'] });

// MFE reads props (frozen copy)
const props = appProps.getProps();

// Subscribe to changes
const unsubscribe = appProps.onPropsChange((newProps, prevProps) => {
  console.log('Props changed:', newProps);
});