API Reference
Complete reference for all exported functions, types, and hooks in Vuer-RTC.
Core Exports
Graph Factory
createGraph
Create a graph store for managing CRDT-based scene graph state.
function createGraph(options: CreateGraphOptions): GraphStoreParameters:
| Parameter | Type | Description |
|---|---|---|
options.sessionId | string | Unique session identifier |
options.onSend | (msg: CRDTMessage) => void | Callback invoked when a message is ready to send to the server |
options.onStateChange | (state: ClientState) => void | Optional callback invoked on every state change |
options.initialSnapshot | Snapshot | Optional initial snapshot to restore from |
Returns: GraphStore - A store with methods to edit, commit, undo/redo, and sync state.
Example:
const store = createGraph({
sessionId: 'user-123',
onSend: (msg) => websocket.send(JSON.stringify(msg)),
});
store.edit({ otype: 'vector3.add', key: 'cube', path: 'position', value: [1, 0, 0] });
store.commit('Move cube');createGraphFromServer
Create a graph store initialized from server state (snapshot + journal).
function createGraphFromServer(
sessionId: string,
snapshot: Snapshot,
journal: CRDTMessage[],
onSend?: (msg: CRDTMessage) => void
): GraphStoreParameters:
| Parameter | Type | Description |
|---|---|---|
sessionId | string | Unique session identifier |
snapshot | Snapshot | Server snapshot containing graph state and metadata |
journal | CRDTMessage[] | Array of uncompacted messages from server |
onSend | (msg: CRDTMessage) => void | Optional callback for outgoing messages |
Returns: GraphStore
Client Actions
Low-level state manipulation functions. Most users should use createGraph or React hooks instead.
State Initialization
createInitialState
Create initial client state.
function createInitialState(sessionId: string, initialSnapshot?: Snapshot): ClientStateinitFromServer
Initialize client state from server snapshot and journal.
function initFromServer(
sessionId: string,
snapshot: Snapshot,
journal: CRDTMessage[]
): ClientStateEdit Buffer Operations
onEdit
Add an operation to the edit buffer (uncommitted).
function onEdit(state: ClientState, op: Operation): ClientStatecommitEdits
Commit pending edits as a single message.
function commitEdits(
state: ClientState,
description?: string
): { state: ClientState; msg: CRDTMessage | null }Returns: New state and the message to send (or null if no edits).
cancelEdits
Discard all uncommitted edits.
function cancelEdits(state: ClientState): ClientStateServer Communication
onRemoteMessage
Process an incoming message from another client or server.
function onRemoteMessage(state: ClientState, msg: CRDTMessage): ClientStateonServerAck
Mark a message as acknowledged by the server.
function onServerAck(state: ClientState, msgId: string): ClientStateUndo/Redo
undo
Undo the last committed message.
function undo(state: ClientState): { state: ClientState; undoMsg: CRDTMessage | null }redo
Redo the last undone message.
function redo(state: ClientState): { state: ClientState; redoMsg: CRDTMessage | null }Compaction
compact
Compact the journal by creating a new snapshot at the current watermark.
function compact(state: ClientState): ClientStateRemoves all acknowledged messages from the journal and updates the snapshot.
compactToWatermark
Compact to a specific watermark (lamport timestamp).
function compactToWatermark(state: ClientState, watermark: number): ClientStateUtilities
generateUUID
Generate a compact session ID (12-character nanoid).
function generateUUID(): stringgetUnackedMessages
Get all messages that have not been acknowledged by the server.
function getUnackedMessages(state: ClientState): CRDTMessage[]hasPendingMessages
Check if there are any unacknowledged messages.
function hasPendingMessages(state: ClientState): booleangetPendingCount
Get the count of unacknowledged messages.
function getPendingCount(state: ClientState): numberReact Hooks
Available from @vuer-ai/vuer-rtc/hooks subpath.
Provider
GraphProvider
Wrap your app to provide graph context.
function GraphProvider(props: GraphProviderProps): JSX.ElementProps:
| Prop | Type | Description |
|---|---|---|
sessionId | string | Unique session identifier |
onSend | (msg: CRDTMessage) => void | Callback for outgoing messages |
children | ReactNode | Child components |
Example:
<GraphProvider sessionId="user-123" onSend={sendToServer}>
<Scene />
</GraphProvider>State Access Hooks
useGraphStore
Access the underlying graph store.
function useGraphStore(): GraphStoreuseGraph
Get the current graph state. Re-renders on any graph change.
function useGraph(): SceneGraphuseNode
Subscribe to a specific node. Re-renders only when that node changes.
function useNode(key: string): SceneNode | undefineduseNodeProperty
Subscribe to a specific property of a node. Re-renders only when that property changes.
function useNodeProperty<T>(key: string, path: string): T | undefinedExample:
const position = useNodeProperty<[number, number, number]>('cube-1', 'position');Action Hooks
useGraphActions
Get actions to modify the graph.
function useGraphActions(): {
edit: (op: Operation) => void;
commit: (description?: string) => CRDTMessage | null;
cancelEdits: () => void;
undo: () => void;
redo: () => void;
receive: (msg: CRDTMessage) => void;
compact: () => void;
compactToWatermark: (watermark: number) => void;
}Example:
const { edit, commit, undo, redo } = useGraphActions();
const onDrag = (delta: [number, number, number]) => {
edit({ otype: 'vector3.add', key: 'cube', path: 'position', value: delta });
};
const onDragEnd = () => {
commit('Move cube');
};useDrag
Helper hook for drag operations with automatic edit buffering.
function useDrag(
key: string,
path: string,
description: string
): {
onDragStart: () => void;
onDrag: (delta: [number, number, number]) => void;
onDragEnd: () => void;
}Example:
const { onDragStart, onDrag, onDragEnd } = useDrag('cube-1', 'position', 'Move cube');useUndoRedoShortcuts
Enable keyboard shortcuts for undo/redo (Cmd/Ctrl+Z, Cmd/Ctrl+Shift+Z).
function useUndoRedoShortcuts(): voidOperations
High-level operation dispatcher and validator.
Dispatcher
applyOperation
Apply a single operation to the graph.
function applyOperation(graph: SceneGraph, op: Operation): SceneGraphapplyMessage
Apply all operations in a message to the graph.
function applyMessage(graph: SceneGraph, msg: CRDTMessage): SceneGraphapplyMessages
Apply multiple messages to the graph.
function applyMessages(graph: SceneGraph, messages: CRDTMessage[]): SceneGraphcreateEmptyGraph
Create an empty scene graph with root node.
function createEmptyGraph(): SceneGraphValidation
OperationValidator
Validator for operation schemas.
class OperationValidator {
validate(op: Operation): ValidationResult;
}Example:
const validator = new OperationValidator();
const result = validator.validate({ otype: 'vector3.set', key: 'cube', path: 'position', value: [1, 2, 3] });
if (!result.valid) {
console.error(result.errors);
}Text CRDT Utilities
getTextDocument
Get the TextRope instance from a node property.
function getTextDocument(graph: SceneGraph, key: string, path: string): TextRope | nullCRDT - TextRope
High-performance text CRDT with B-tree storage. Available from @vuer-ai/vuer-rtc/crdt.
Factory
create
Create a new TextRope instance.
function create(agentId: string): TextRopeQueries
getText
Get the visible text content.
function getText(rope: TextRope): stringgetLength
Get the visible character count.
function getLength(rope: TextRope): numbergetItems
Get all items (including deleted).
function getItems(rope: TextRope): Item[]getStats
Get statistics about the rope structure.
function getStats(rope: TextRope): {
items: number;
visibleChars: number;
deletedChars: number;
agents: number;
maxSeq: number;
}Local Edits
insert
Insert text at a position.
function insert(rope: TextRope, pos: number, content: string): TextRoperemove
Remove text range.
function remove(rope: TextRope, from: number, to: number): DeleteOpreplace
Replace text range.
function replace(rope: TextRope, from: number, to: number, content: string): ReplaceOpmove
Move text range to a new position.
function move(rope: TextRope, from: number, to: number, targetPos: number): MoveOpRemote Operations
apply
Apply a remote insert operation.
function apply(rope: TextRope, op: InsertOp): TextRopeapplyDelete
Apply a remote delete operation.
function applyDelete(rope: TextRope, op: DeleteOp): TextRopeapplyReplace
Apply a remote replace operation.
function applyReplace(rope: TextRope, op: ReplaceOp): TextRopeapplyMove
Apply a remote move operation.
function applyMove(rope: TextRope, op: MoveOp): TextRopeMerging & Snapshots
merge
Merge two ropes (used for reconciliation).
function merge(rope1: TextRope, rope2: TextRope): TextRopesnapshot
Create a deep copy of the rope.
function snapshot(rope: TextRope): TextRopecompact
Remove tombstones (deleted items) from the rope.
function compact(rope: TextRope): TextRopeSerialization
toRaw
Serialize to plain object.
function toRaw(rope: TextRope): RawTextRopefromRaw
Deserialize from plain object.
function fromRaw(raw: RawTextRope): TextRopefromSnapshot
Create from a snapshot object.
function fromSnapshot(snapshot: RawTextRope): TextRopeItem Utilities
findItemById
Find an item by its ID.
function findItemById(rope: TextRope, id: ItemId): Item | nullitemIdEquals
Compare two item IDs for equality.
function itemIdEquals(a: ItemId | null, b: ItemId | null): booleanitemIdCompare
Compare two item IDs for ordering.
function itemIdCompare(a: ItemId, b: ItemId): numberRangeTree (B-tree)
Low-level B-tree implementation used by TextRope.
class RangeTree {
constructor(order?: number);
insert(item: Item, ord: number): void;
splitAt(ord: number): void;
getAt(ord: number): Item | null;
totalVisible(): number;
totalItems(): number;
// ... additional methods
}State Management
VectorClockManager
Causal ordering utilities.
class VectorClockManager {
create(sessionId: string): VectorClock;
increment(clock: VectorClock, sessionId: string): VectorClock;
merge(clock1: VectorClock, clock2: VectorClock): VectorClock;
compare(clock1: VectorClock, clock2: VectorClock): number;
}Example:
const manager = new VectorClockManager();
const clock = manager.create('session-1');
const newClock = manager.increment(clock, 'session-1');
const merged = manager.merge(clock, remoteClock);DType
Data type registry for server-side conflict resolution.
class DType {
static register<T>(
dtype: string,
defaultValue: T,
mergeFn: MergeFn<T>
): void;
static getDefault(dtype: string): unknown;
static merge<T>(dtype: string, a: ValueWithMeta<T>, b: ValueWithMeta<T>): ValueWithMeta<T>;
}ConflictResolver
Server-side conflict resolution.
class ConflictResolver {
resolve(existing: PropertyLWW, incoming: PropertyLWW, otype: string): PropertyLWW;
}
function parseOtype(otype: string): { dtype: string; verb: string }Sync Utilities
Efficient message reconciliation using bloom filters.
BloomFilter
Probabilistic set for message ID reconciliation.
class BloomFilter {
constructor(numBits: number, numHashes: number);
static create(expectedItems: number, falsePositiveRate?: number): BloomFilter;
add(key: string): void;
has(key: string): boolean;
toBytes(): Uint8Array;
static fromBytes(bytes: Uint8Array): BloomFilter;
}Example:
const filter = BloomFilter.create(1000, 0.01); // 1000 items, 1% false positive rate
filter.add('msg-123');
filter.add('msg-456');
if (filter.has('msg-123')) {
console.log('Message probably in set');
}Sync Digest
buildSyncDigest
Build a sync digest from client state for reconciliation.
function buildSyncDigest(state: ClientState): SyncDigestReturns: SyncDigest object containing:
vectorClock: Covers all compacted messagesfilter: Bloom filter covering uncompacted journalcount: Journal length
Example:
const digest = buildSyncDigest(state);
websocket.send(JSON.stringify(digest));Types
Core Types
interface CRDTMessage {
id: string;
sessionId: string;
clock: VectorClock;
lamportTime: number;
timestamp: number;
ops: Operation[];
}
interface SceneGraph {
nodes: Record<string, SceneNode>;
rootKey: string;
}
interface SceneNode {
key: string;
tag?: string;
children?: string[];
_crdt: CRDTEnvelope;
[key: string]: unknown; // Dynamic properties
}
interface ClientState {
graph: SceneGraph;
journal: JournalEntry[];
edits: EditBuffer;
snapshot: Snapshot;
lamportTime: number;
vectorClock: VectorClock;
sessionId: string;
}
interface Snapshot {
graph: SceneGraph;
vectorClock: VectorClock;
lamportTime: number;
journalIndex: number;
}TextRope Types
interface ItemId {
agent: string;
seq: number;
}
interface Item {
id: ItemId;
content: string;
isDeleted: boolean;
parentId: ItemId | null;
seq: number;
}
interface InsertOp {
id: ItemId;
content: string;
parentId: ItemId | null;
seq: number;
}
interface DeleteOp {
deletions: Array<{ id: ItemId; length: number }>;
}Operation Types
All operations extend BaseOp:
interface BaseOp {
otype: string; // e.g., 'vector3.add', 'string.set'
key?: string; // Target node key ('.' = root)
path?: string; // Property path ('.' = node root)
value?: unknown;
// Additional fields per operation type
}See the Operations page for the complete list of operation types.
Wire Serialization
encode
Serialize a message using msgpack.
function encode(msg: CRDTMessage | SyncDigest): Uint8Arraydecode
Deserialize a message from msgpack.
function decode(bytes: Uint8Array): CRDTMessage | SyncDigestExample:
import { encode, decode } from '@vuer-ai/vuer-rtc';
const msg: CRDTMessage = { /* ... */ };
const bytes = encode(msg);
websocket.send(bytes);
// On receive:
const received = decode(new Uint8Array(event.data));Advanced Usage
Edit Buffer Utilities
isAdditiveOp
Check if an operation is additive (can be merged).
function isAdditiveOp(op: Operation): booleanmergeValues
Merge two operation values for the same key+path.
function mergeValues(otype: string, prev: unknown, next: unknown): unknownGraph Rebuilding
rebuildGraph
Rebuild the graph from snapshot + journal (used internally after undo/redo).
function rebuildGraph(state: ClientState): ClientStateRelated Pages
- Getting Started - Installation and basic usage
- Operations - Complete operation reference
- React Hooks - Detailed hook examples
- Rope (Text CRDT) - In-depth TextRope documentation
- Architecture - System design and concepts