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

@collidor/event

v4.5.0

Published

A small library to create, register and listen to events.

Readme

@collidor/event

Codecov npm version License: MIT

A lightweight event system with cross-context communication. Perfect for modern web apps, workers, and distributed systems.


Installation

npm install @collidor/event

Core Features

  • Class-based event system with strict typing
  • Cross-context communication (Window ↔ Worker ↔ Tab)
  • Built-in support for BroadcastChannel/SharedWorker
  • Context propagation & AbortController integration

Basic Usage

import { Event } from "@collidor/event";

class UserUpdate extends Event<{ id: string }> {}
class SystemAlert extends Event<string> {}
import { EventBus } from "@collidor/event";

const bus = new EventBus();

// Subscribe
bus.on(UserUpdate, (data) => {
  console.log(`User ${data.id} updated`);
});

// Publish
bus.emit(new UserUpdate({ id: "123" }));

Cross-Context Patterns

The PortChannel is the main exported channel, it accepts MessagePortLike ports, which have a postMessage method, and can set and use a onmessage property callback. This means that the browsers APIs like BroadcastChannel, Worker and SharedWorker will work by default.

My plan is to add adapters later so other things can behave like ports, like Websockets, WebRTC, Http+SEE and Datagrams.

The PortChannel will not emit events to ports that didn't send a message first telling that it has a subscriber for such event.

1. BroadcastChannel (Tab-to-Tab)

import { PortChannel, EventBus } from "@collidor/event";

const channel = new PortChannel();
const bus = new EventBus({ channel });
channel.addPort(new BroadcastChannel("app-channel"));

class TabMessage extends Event<string> {}
bus.emit(new TabMessage("Hello from Tab A!"));
import { PortChannel, EventBus } from "@collidor/event";

const channel = new PortChannel();
const bus = new EventBus({ channel });
channel.addPort(new BroadcastChannel("app-channel"));

bus.on(TabMessage, (msg) => {
  console.log("Received:", msg); // "Hello from Tab A!"
});

2. SharedWorker (Multi-Context)

import { PortChannel, EventBus } from "@collidor/event";

const channel = new PortChannel();
const bus = new EventBus({ channel });
const worker = new SharedWorker("worker.js");

channel.addPort(worker.port);

class TaskEvent extends Event<{ id: string }> {}
bus.emit(new TaskEvent({ id: "shared-task" }));
import { PortChannel, EventBus } from "@collidor/event";

const channel = new PortChannel();
const bus = new EventBus({ channel });

// Handle new connections
self.onconnect = (event) => {
  const port = event.ports[0];
  channel.addPort(port);
};

self.start();

bus.on(TaskEvent, ({ id }) => {
  console.log("Processing shared task:", id);
});

Advanced Patterns

Context Propagation

const bus = new EventBus({
  context: { requestId: "123" }
});

bus.on(DataEvent, (data, ctx) => {
  console.log(ctx.requestId); // "123"
});

// Override per emission
bus.emit(new DataEvent(), { requestId: "temp" });

API Overview

EventBus

  • on(event, handler, signal?)
  • off(event, handler)
  • emit(event, context?)
  • emitByName(name, data, context?)

PortChannel

  • addPort(port)
  • removePort(port)
  • publish(event)
  • subscribe(name, callback)
  • unsubscribe(name, callback)

PortChannel sequence diagram

sequenceDiagram
    participant S as Server PortChannel
    participant MP as MessagePort
    participant C as Client PortChannel

    %% Server adds a MessagePort (acts as connecting port)
    S->>MP: addPort(port)
    Note over S,MP: Server attaches MessagePort

    %% MessagePort forwards startEvent to the Client
    MP->>C: onmessage({type: "startEvent"})
    Note over C: Client receives startEvent and sets up message handlers

    %% Client subscribes to "TestEvent"
    C->>MP: postMessage({type:"subscribeEvent", name:"TestEvent"})
    Note over C: Client tells that it has a subscription for "TestEvent"

    %% MessagePort delivers subscribeEvent to Server
    MP->>S: onmessage({type:"subscribeEvent", name:"TestEvent"})
    Note over S: Server calls addPortSubscription("TestEvent")

    %% If the Server had buffered events for "TestEvent", flush them:
    alt Buffered events exist for "TestEvent"
      S->>MP: postMessage(buffered dataEvent for "TestEvent")
      MP->>C: onmessage(buffered dataEvent for "TestEvent")
    else
      Note over S: No buffered events to flush
    end

    %% Now, the Server publishes a new event "TestEvent"
    S->>S: publish("TestEvent", data)
    alt Subscriber exists
      S->>MP: postMessage({type:"dataEvent", name:"TestEvent", data})
      MP->>C: onmessage({type:"dataEvent", name:"TestEvent", data})
      Note over C: Client processes the dataEvent
    else
      S->>S: Buffer event "TestEvent" with timeout
      Note over S: Event buffered until a subscriber appears
    end

Development

# Install dependencies
npm install

# Run tests (requires Deno)
npm test

# Build project
npm run build

MIT License | © 2024 Alykam Burdzaki Report Issues