Skip to main content
zerotal

Documentation


Documentation / @zerotal/broadcasting / PusherCompatManager

Class: PusherCompatManager

Defined in: broadcasting/src/PusherCompatManager.ts:62

Pusher/Reverb-compatible WebSocket broadcast manager.

Implements the Pusher wire protocol on top of BroadcastManager so that Any Pusher-compatible client can connect to a Zerotal backend without modifications.

Key protocol differences from the native Zerotal protocol:

  • Connection event: pusher:connection_established (data is JSON string)
  • Subscribe event: pusher:subscribe (channel inside data object)
  • Subscription succeeded: pusher_internal:subscription_succeeded
  • All server-sent data fields are JSON strings, not objects
  • Auth for private/presence channels uses HMAC-SHA256 signatures

Auth flow:

  1. Echo calls POST /broadcasting/auth with socket_id + channel_name
  2. Server signs with signAuth() and returns {auth: "key:sig"}
  3. Echo includes auth in the pusher:subscribe message
  4. Manager verifies HMAC before allowing subscription

Example

// config/broadcasting.ts
BroadcastConfig({
  driver: 'pusher',
  pusher: {
    appKey:    Bun.env.PUSHER_APP_KEY!,
    appSecret: Bun.env.PUSHER_APP_SECRET!,
  },
});

Extends

Constructors

Constructor

new PusherCompatManager(_appKey, _appSecret): PusherCompatManager

Defined in: broadcasting/src/PusherCompatManager.ts:65

Parameters

_appKey

string

_appSecret

string

Returns

PusherCompatManager

Overrides

BroadcastManager.constructor

Properties

_conns

protected _conns: Map<string, WS>

Defined in: broadcasting/src/BroadcastManager.ts:32

connectionId → live WebSocket

Inherited from

BroadcastManager._conns


_subs

protected _subs: Map<string, Set<string>>

Defined in: broadcasting/src/BroadcastManager.ts:34

channelName → Set

Inherited from

BroadcastManager._subs


_members

protected _members: Map<string, Map<string, PresenceMember>>

Defined in: broadcasting/src/BroadcastManager.ts:36

presence channelName → Map<connectionId, PresenceMember>

Inherited from

BroadcastManager._members


_authSecret

protected _authSecret: string | undefined = undefined

Defined in: broadcasting/src/BroadcastManager.ts:42

Secret for per-subscription HMAC signatures (the app's APP_KEY).

Inherited from

BroadcastManager._authSecret

Accessors

wsHandlers

Get Signature

get wsHandlers(): object

Defined in: broadcasting/src/BroadcastManager.ts:246

Returns

object

open

open: (ws) => void

Parameters
ws

WS

Returns

void

message

message: (ws, msg) => undefined

Parameters
ws

WS

msg

string | Uint8Array<ArrayBufferLike>

Returns

undefined

close

close: (ws) => void

Parameters
ws

WS

Returns

void

Inherited from

BroadcastManager.wsHandlers

Methods

setAuthSecret()

setAuthSecret(secret): void

Defined in: broadcasting/src/BroadcastManager.ts:51

Set the secret used to sign/verify per-subscription auth tokens. Wired from the app's APP_KEY by BroadcastProvider. Without it the signed-auth path is disabled and the server falls back to the connection-level authorize callbacks.

Parameters

secret

string

Returns

void

Inherited from

BroadcastManager.setAuthSecret


verifyAuth()

verifyAuth(socketId, channel, auth, channelData?): boolean

Defined in: broadcasting/src/BroadcastManager.ts:74

Constant-time check that auth is a valid signature for this socket/channel(/data).

Parameters

socketId

string

channel

string

auth

string

channelData?

string

Returns

boolean

Inherited from

BroadcastManager.verifyAuth


authorizeWith()

authorizeWith(fn): void

Defined in: broadcasting/src/BroadcastManager.ts:95

Register an authorization callback for private/presence channels. Return true to allow subscription, false to deny.

Parameters

fn

ChannelAuthFn

Returns

void

Example

broadcast.authorizeWith(async (channel, ws) => {
  if (!ws.data.userId) return false;
  if (channel.startsWith('private-orders.')) {
    const id = channel.split('.')[1];
    return await Order.findOwner(id) === ws.data.userId;
  }
  return true;
});

Inherited from

BroadcastManager.authorizeWith


authorizePresenceWith()

authorizePresenceWith(fn): void

Defined in: broadcasting/src/BroadcastManager.ts:111

Register a presence channel auth callback. Return a PresenceMember object to grant access and track the member, or false to deny.

Parameters

fn

PresenceAuthFn

Returns

void

Example

manager.authorizePresenceWith(async (channel, ws) => {
  const user = await User.find(ws.data.userId);
  if (!user) return false;
  return { id: user.id, info: { name: user.name, avatar: user.avatar } };
});

Inherited from

BroadcastManager.authorizePresenceWith


getMembers()

getMembers(channel): PresenceMember[]

Defined in: broadcasting/src/BroadcastManager.ts:122

Return all members currently subscribed to a presence channel.

Parameters

channel

string

Returns

PresenceMember[]

Example

const members = manager.getMembers('presence-chat.room');
// [{ id: 1, info: { name: 'Alice' } }, ...]

Inherited from

BroadcastManager.getMembers


send()

send(event, opts?): void

Defined in: broadcasting/src/BroadcastManager.ts:214

Dispatch a BroadcastEvent to all its declared channels.

Parameters

event

BroadcastEvent

opts?
exceptSocketId?

string

Returns

void

Example

broadcast.send(new PostUpdated(post));

Inherited from

BroadcastManager.send


subscriptionsFor()

subscriptionsFor(connectionId): string[]

Defined in: broadcasting/src/BroadcastManager.ts:226

Returns the list of channels a connection is subscribed to.

Parameters

connectionId

string

Returns

string[]

Inherited from

BroadcastManager.subscriptionsFor


subscriberCount()

subscriberCount(channel): number

Defined in: broadcasting/src/BroadcastManager.ts:235

Returns the number of subscribers on a channel.

Parameters

channel

string

Returns

number

Inherited from

BroadcastManager.subscriberCount


connectionCount()

connectionCount(): number

Defined in: broadcasting/src/BroadcastManager.ts:240

Total open connections.

Returns

number

Inherited from

BroadcastManager.connectionCount


_onHandlerError()

protected _onHandlerError(ws, error): void

Defined in: broadcasting/src/BroadcastManager.ts:267

Last-resort handler for a rejection escaping handleMessage.

Logs and, where possible, tells the offending client. Never rethrows: the whole point is that one client's bad frame must not terminate the process serving everyone else.

Parameters

ws

WS

error

unknown

Returns

void

Inherited from

BroadcastManager._onHandlerError


upgradeData()

upgradeData(req): Record<string, unknown>

Defined in: broadcasting/src/BroadcastManager.ts:278

Factory for upgradeData passed to app.withWebSocket().

Parameters

req

Request

Returns

Record<string, unknown>

Inherited from

BroadcastManager.upgradeData


resolvePresenceWith()

resolvePresenceWith(fn): void

Defined in: broadcasting/src/PusherCompatManager.ts:85

Register a callback that resolves presence-channel member data for the HTTP auth endpoint. Return false to deny the subscription.

Parameters

fn

PusherPresenceResolver

Returns

void

Example

pusher.resolvePresenceWith(async (req, _channel) => {
  const userId = await getUserIdFromSession(req);
  if (!userId) return false;
  return { id: userId, info: { name: await getUserName(userId) } };
});

signAuth()

signAuth(socketId, channel, channelData?): string

Defined in: broadcasting/src/PusherCompatManager.ts:97

Generate a Pusher auth token for a given socket/channel pair. Called by the HTTP auth endpoint before returning the token to the client.

For private channels: signAuth(socketId, channel) For presence channels: signAuth(socketId, channel, channelData) where channelData = JSON.stringify({ user_id, user_info })

Parameters

socketId

string

channel

string

channelData?

string

Returns

string

Overrides

BroadcastManager.signAuth


resolvePresence()

resolvePresence(req, channel): Promise<false | { id: string | number; info?: Record<string, unknown>; }>

Defined in: broadcasting/src/PusherCompatManager.ts:107

Resolve presence member data for the HTTP auth endpoint. Returns false when no resolver is registered or the resolver denies.

Parameters

req

Request

channel

string

Returns

Promise<false | { id: string | number; info?: Record<string, unknown>; }>


handleOpen()

handleOpen(ws): void

Defined in: broadcasting/src/PusherCompatManager.ts:117

Parameters

ws

WS

Returns

void

Overrides

BroadcastManager.handleOpen


handleMessage()

handleMessage(ws, raw): Promise<void>

Defined in: broadcasting/src/PusherCompatManager.ts:127

Parameters

ws

WS

raw

string | Uint8Array<ArrayBufferLike>

Returns

Promise<void>

Overrides

BroadcastManager.handleMessage


handleClose()

handleClose(ws): void

Defined in: broadcasting/src/PusherCompatManager.ts:165

Parameters

ws

WS

Returns

void

Overrides

BroadcastManager.handleClose


to()

to(channel, eventName, data?, opts?): void

Defined in: broadcasting/src/PusherCompatManager.ts:189

Broadcast an event to all subscribers. Pusher format: data is always a JSON string, not an object.

Parameters

channel

string

eventName

string

data?

unknown = {}

opts?
exceptSocketId?

string

Returns

void

Overrides

BroadcastManager.to