@forcewire/protocol
v0.1.0
Published
High-performance type-safe message envelopes and binary/JSON codecs for ForceWire
Readme
@forcewire/protocol
High-performance, type-safe message envelopes, codecs, and stream framing for the ForceWire realtime communication framework.
📦 Features
- Generic Message Envelope: Strongly typed
ForceWireMessage<T>envelopes with IDs, timestamps, type identifiers, payload, and auxiliary metadata. - Dual Codecs:
- JSON: Fast UTF-8 JSON serialization for standard structured event payloads.
- Binary Framing: Custom binary format for raw
Uint8Array,ArrayBuffer, embeddings, tensors, and multimedia streams.
- Auto Format Detection: Automatic format negotiation and transparent decoding based on packet magic byte inspection (
0x57). - Stream Framing: 4-byte length-prefix framing (
frameStreamMessageandStreamFrameReader) for reliable QUIC stream message boundary extraction. - Zero Dependencies: Lightweight, tree-shakeable, and compatible with modern browsers, Node.js, Deno, and Edge workers.
🚀 Installation
pnpm add @forcewire/protocol🛠️ Usage
Creating & Encoding Messages
import { createMessage, encodeMessage, decodeMessage } from '@forcewire/protocol';
// 1. JSON Message
const chatMessage = createMessage('chat.message', {
author: 'Alice',
text: 'Hello ForceWire!'
}, {
meta: { traceId: 'tr_123' }
});
const jsonBuffer = encodeMessage(chatMessage);
// 2. Binary Message (Raw ArrayBuffer / Uint8Array)
const audioBuffer = new Uint8Array([0x00, 0x11, 0x22, 0x33]);
const binaryMessage = createMessage('media.audio', audioBuffer, {
meta: { sampleRate: 44100 }
});
const binaryBuffer = encodeMessage(binaryMessage); // Automatically uses binary codec
// 3. Decoding (Auto-detects format)
const decoded = decodeMessage(binaryBuffer);
console.log(decoded.type); // 'media.audio'
console.log(decoded.payload); // Uint8Array(4) [0x00, 0x11, 0x22, 0x33]Stream Framing
import { frameStreamMessage, StreamFrameReader } from '@forcewire/protocol';
// Wrap outgoing message with 4-byte length header
const framed = frameStreamMessage(encodeMessage(msg));
// Process continuous incoming byte chunks from a QUIC / WebTransport stream
const reader = new StreamFrameReader();
for await (const chunk of stream) {
const completeMessages = reader.push(chunk);
for (const rawMessage of completeMessages) {
const msg = decodeMessage(rawMessage);
handleMessage(msg);
}
}