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

@roostjs/broadcast

v0.2.0

Published

Real-time broadcasting via Durable Objects and WebSocket hibernation.

Readme

@roostjs/broadcast

Real-time broadcasting via Durable Objects and WebSocket hibernation.

Part of Roost — the Laravel of Cloudflare Workers.

Installation

bun add @roostjs/broadcast

Quick Start

// Server: define a broadcastable event
import { Event } from '@roostjs/events';
import { Channel, PrivateChannel } from '@roostjs/broadcast';
import type { BroadcastableEvent } from '@roostjs/broadcast';

class OrderShipped extends Event implements BroadcastableEvent {
  constructor(public orderId: string, public userId: string) { super(); }

  broadcastOn() {
    return [new PrivateChannel(`orders.${this.userId}`)];
  }

  broadcastWith() {
    return { orderId: this.orderId };
  }
}

// Dispatching the event auto-broadcasts when @roostjs/broadcast is registered
await OrderShipped.dispatch(new OrderShipped('ord_1', 'usr_42'));

// Client (browser/edge)
import { createBroadcastClient } from '@roostjs/broadcast/client';

const client = createBroadcastClient('/ws/channel');
const unsub = client.subscribe('orders.usr_42', (event, data) => {
  console.log(event, data);
});

Features

  • Channel, PrivateChannel, PresenceChannel — same API as Laravel Broadcasting
  • ChannelDO Durable Object with WebSocket hibernation — zero cost at idle
  • Private and presence channel authorization hooks built in
  • Presence member tracking: presence:join / presence:leave events
  • Whisper support for client-to-client ephemeral messages
  • createBroadcastClient with exponential backoff auto-reconnect
  • BroadcastManager.fake() / assertBroadcast() / assertBroadcastOn() for testing

Setup

Add the Durable Object binding to wrangler.jsonc and export ChannelDO:

// worker.ts
export { ChannelDO } from '@roostjs/broadcast';

Register the provider in your app bootstrap:

import { BroadcastServiceProvider } from '@roostjs/broadcast';
app.register(BroadcastServiceProvider);

The provider expects a Durable Object binding named BROADCAST_DO by default.

API

// Channels
class Channel { constructor(name: string) }
class PrivateChannel extends Channel {}
class PresenceChannel extends Channel {}

// Event contract
interface BroadcastableEvent {
  broadcastOn(): Channel[]
  broadcastWith(): Record<string, unknown>
  broadcastAs?(): string
}

// Manager
class BroadcastManager {
  static get(): BroadcastManager
  static fake(): void
  static restore(): void
  static assertBroadcast(eventClass: new (...args) => BroadcastableEvent): void
  static assertBroadcastOn(channel: string): void
  broadcast(event: BroadcastableEvent): Promise<void>
}

// Client (import from @roostjs/broadcast/client)
function createBroadcastClient(
  url: string | (() => string),
  options?: BroadcastClientOptions
): BroadcastClient

interface BroadcastClient {
  subscribe(channel: string, handler: (event: string, data: unknown) => void): () => void
  unsubscribe(channel: string): void
  whisper(channel: string, event: string, data?: unknown): void
  close(): void
}

Override authorize() on ChannelDO to validate private/presence channel access with real JWT or session checks — the default accepts any bearer token.

Documentation

Full documentation at roost.birdcar.dev/docs/reference/broadcast

License

MIT