Storage
CRDT primitives for conflict-free collaborative state. The @waits/lively-storage package provides LiveObject, LiveMap, and LiveList — nestable data structures that automatically resolve conflicts using last-writer-wins semantics and Lamport clocks.
Install
StorageDocument
The top-level container that owns the CRDT tree, manages subscriptions, and coordinates serialization.
Create a document with a root object:
getRoot() returns the root LiveObject:
Serialize and deserialize for persistence:
Subscribe to changes — shallow or deep:
LiveObject
A conflict-free replicated object. Each field uses last-writer-wins with Lamport clocks. Supports nested CRDT values.
Constructor and basic operations:
get(key) — read a field:
set(key, value) — write a field. Generates an op, ticks the clock, and notifies subscribers:
delete(key) — remove a field:
toObject() — snapshot as a plain JS object:
toImmutable() — frozen snapshot (cached until next mutation):
Nesting CRDTs inside a LiveObject:
LiveMap
A conflict-free replicated map with string keys. Uses tombstones for deletes so concurrent set/delete pairs resolve correctly.
Constructor:
get(key) / set(key, value) / delete(key) / has(key):
size — number of live (non-deleted) entries:
Iteration — entries(), keys(), values(), forEach():
toImmutable() — frozen ReadonlyMap snapshot:
LiveList
A conflict-free replicated list. Uses fractional indexing so concurrent inserts never collide — items interleave deterministically without shifting indices.
Constructor:
push(item) — append to end:
insert(item, index) — insert at position:
delete(index) — remove by index:
move(from, to) — reorder an item:
get(index) / length:
toArray() — snapshot as plain array. toImmutable() — frozen readonly T[]:
Subscribe to list changes:
HistoryManager
Built-in undo/redo with automatic inverse-op computation. Every mutation on a StorageDocument is recorded. Group related mutations into a single undo step with batch().
Access from the document:
undo() / redo():
canUndo() / canRedo():
startBatch() / endBatch() — group mutations into one undo entry:
subscribe(cb) — listen for undo/redo stack changes:
Constructor config:
Utilities
generateKeyBetween(a, b) — fractional indexing. Returns a string key that sorts between a and b. Pass null for start/end of list:
generateNKeysBetween(a, b, n) — generate n evenly-spaced keys:
computeInverseOp(op) — compute the inverse of a storage op (used internally by HistoryManager):
LamportClock — logical clock for causal ordering:
Types
Exported TypeScript types for advanced usage.