Bidirectional actor channels with pub/sub, peer relaying, and RPC.
npm install @sovereignbase/actor-channel
# or
pnpm add @sovereignbase/actor-channel
# or
yarn add @sovereignbase/actor-channel
# or
bun add @sovereignbase/actor-channel
# or
deno add jsr:@sovereignbase/actor-channel
# or
vlt install jsr:@sovereignbase/actor-channel
import { ActorChannel } from '@sovereignbase/actor-channel'
const channel = new ActorChannel<
'documents',
{ id: string },
{ method: string },
{ result: string }
>()
channel.addEventListener('message', (event) => {
const [topic, message] = event.detail
console.log(topic, message)
})
channel.addEventListener('response', (event) => {
const [id, response] = event.detail
console.log(id, response)
})
channel.subscribe('documents')
channel.publish('documents', { id: 'document-1' })
const requestId = channel.request({ method: 'sync' })
console.log(requestId)
void channel.addBroker('wss://broker.example', true)
import { ChannelBroker } from '@sovereignbase/actor-channel'
const broker = new ChannelBroker<
'documents',
{ id: string },
{ method: string },
{ result: string }
>()
broker.addEventListener('request', (event) => {
const [request, respond, sender] = event.detail
if (!request.method) {
broker.dispatchEvent('violation', {
violator: sender,
description: 'Off protocol.',
})
return
}
respond({ result: request.method })
})
broker.addChannel(socket, { rpcEnabled: true })
// Verify application-level identity using your own protocol and policy.
// Transport authentication is handled separately by HTTPS/WebSocket.
broker.markAuthenticated(socket)
socket.addEventListener('message', (event) => {
broker.handleMessage(socket, event.data)
})
socket.addEventListener('close', () => {
broker.deleteChannel(socket)
})
The transport passed to ChannelBroker must expose send(ArrayBuffer) and
readyState. Incoming messages must be provided as ArrayBuffer values.
ActorChannelrpcAvailable reports whether an RPC-enabled broker is available.request(detail) sends a fire-and-forget RPC request and returns its ID.publish(topic, detail) publishes locally and to subscribed broker peers.subscribe(topic) subscribes the current window to a topic.unsubscribe(topic) removes the current window's subscription.addBroker(url, rpcEnabled?) repeatedly attempts to acquire a URL-specific
Web Lock and maintains the WebSocket while it owns the lock.ChannelBrokeraddChannel(channel, attachment?) adds a transport with optional metadata,
RPC access, and initial subscriptions.deleteChannel(channel) removes a transport and its subscriptions.markAuthenticated(channel) records that the host application has verified
the channel's application-level identity and emits an attachment event.
The method is intentionally one-way and provides no unset operation.handleMessage(channel, message) handles an encoded client message.dispatchEvent(type, detail) dispatches a typed broker event to registered
listeners.attachment events receive the channel and its updated attachment.request events receive the request, a response callback, and the sender.violation events receive the violating channel and a description.ActorChannel is window-only and requires Broadcast Channel, Web Locks, Web
Crypto, and WebSocket APIs.rpcAvailable is true when the channel knows of at least one open
RPC-enabled broker WebSocket.ArrayBuffer values.authenticated does not describe HTTPS/WebSocket transport authentication.
The host sets it through markAuthenticated(channel) after verifying an
application-level identity with its own protocol, cryptosuite, and policy.ChannelBroker uses standard web platform primitives and does not require a
specific server framework.ChannelBroker runtime tests in Node.js, Bun, Deno, Vercel Edge Runtime, and
Cloudflare Workers (workerd).Apache-2.0