wyvrn-message-hub
v0.1.1
Published
Wyvrn message hub client: BinaryArchive codec, hub framing, sans-IO protocol core, transports
Downloads
270
Maintainers
Readme
wyvrn-message-hub
Client library for the Wyvrn message hub wire protocol: a length-prefixed binary
framing layer, a sans-IO protocol state machine, a BinaryArchive value codec,
and pluggable transports.
The core is transport-agnostic. HubProtocol never touches a socket — you feed
it bytes and drain events — so it can be driven from a WebSocket, a test
harness, or a replayed capture with identical behavior.
Install
npm install wyvrn-message-hubRequires Node >= 22 (native WebSocket) or any modern browser. ESM only.
Quick start
import { HubClient } from 'wyvrn-message-hub'
import { webSocketTransport } from 'wyvrn-message-hub/transport-websocket'
const client = new HubClient(webSocketTransport('ws://127.0.0.1:9270'))
const hello = await client.connect()
console.log(hello.protocolVersion, hello.maxFramePayload)
const scene = await client.register('chroma2.scene')
const unsubscribe = scene.onMessage((bytes) => {
// decode with BinaryArchiveReader, or handle raw bytes
})
await scene.send(new Uint8Array([1, 2, 3]))
client.onLifecycle(ev => console.log(ev)) // 'open' | 'closed' | 'error'
unsubscribe()
client.close()register() resolves once the hub acknowledges the channel. Messages that
arrive on a channel before your first onMessage listener attaches are buffered
and replayed to that listener in arrival order (up to 256 messages), so a
channel's connect snapshot is never lost to a subscribe race.
send() resolves once the hub grants credit for the message; it rejects with
SendTooLargeError if the message can never fit the channel's maximum window.
Entry points
| Import | Contents |
| --- | --- |
| wyvrn-message-hub | HubClient, and the Transport / TransportFactory / TransportHandlers / ChannelHandle / LifecycleEvent / HubHello types |
| wyvrn-message-hub/codec | BinaryArchiveWriter, BinaryArchiveReader, BinaryTag, fnv1a32 |
| wyvrn-message-hub/framing | encodeFrame, FrameParser, MessageAssembler, FrameType, decodeHello, encodeRegister, decodeRegisterAck, decodeWindowUpdate |
| wyvrn-message-hub/protocol | HubProtocol, HubEvent, HubProtocolState, ChannelInfo, SendTooLargeError |
| wyvrn-message-hub/transport-websocket | webSocketTransport(url) |
| wyvrn-message-hub/testing | memoryTransport() — in-memory transport pair for tests |
Wire format
Frames are [u32 LE length][u8 type][u8 flags][u16 LE channelId][payload].
Frame types: Data=0, Hello=1, Register=2, RegisterAck=3, WindowUpdate=4.
Flag 0x01 marks the end of a logical message, so payloads larger than the
frame limit split across frames and reassemble via MessageAssembler. Flow
control is credit-based: each send charges max(bytes, minMessageCharge)
against the channel window, replenished by WindowUpdate frames.
Testing against the protocol without a socket
import { HubClient } from 'wyvrn-message-hub'
import { memoryTransport } from 'wyvrn-message-hub/testing'
const { factory, host } = memoryTransport()
const client = new HubClient(factory)
const connected = client.connect()
host.receive(helloBytes) // inject inbound bytes
await connected
host.sent // inspect what the client wrote
host.dropConnection() // simulate a close
host.fail('boom') // simulate a transport errorDevelopment
npm install
npm test # vitest
npm run build # tsc -> dist/License
MIT
