@doxi/collab
v0.11.0
Published
Doxiva collaboration engine — step-based CRDT and transports.
Maintainers
Readme
@doxi/collab
Real-time collaboration substrate for Doxiva. Step-based concurrency control with per-peer Lamport ordering, pluggable transports, and presence cursors.
Status: v0.10.x preview. v0.6.0 ships sequential + disjoint-position convergence. Same-position concurrent inserts are a known limitation — see below.
What it does
CollabEngine— wraps a localEditorViewso every dispatchedTransactionis mirrored to remote peers, and inbound updates are rebased and applied locally. Per-peer Lamport clock + monotonic local version. Concurrency uses Mapping-based rebase of pending local updates against inbound steps (the ProseMirror-collab model).Transportinterface — pluggable channel forCollabUpdate+RemoteCursormessages. Two implementations ship:InMemoryBroker(@doxi/collab/transports/in-memory) — in-process fan-out, primarily for tests.BroadcastChannelTransport(@doxi/collab/transports/broadcast) — same-origin tab sync via the browserBroadcastChannelAPI. No server, no auth, no persistence.
RemoteCursorTracker+installRemoteCursors(view, engine)— presence cursors painted as a direct-DOM overlay anchored to the view. Caret + peer label, color per peer.
Install
pnpm add @doxi/collab @doxi/coreQuickstart
import { CollabEngine, installRemoteCursors } from '@doxi/collab'
import { BroadcastChannelTransport } from '@doxi/collab/transports/broadcast'
const transport = new BroadcastChannelTransport('doxiva-demo')
const engine = new CollabEngine({
view,
transport,
peer: { id: crypto.randomUUID(), label: 'Alice', color: '#d93025' },
})
const uninstall = installRemoteCursors(view, engine)
// Later: uninstall(); engine.dispose(); transport.dispose()Known limitations
- Same-position concurrent inserts may diverge in ordering. v0.6 is step-based, not character-CRDT. A Logoot/RGA fractional-index variant is on the roadmap.
- No authoritative server / replay log. Peers joining late don't see prior history. v0.6 is peer-to-peer only via
BroadcastChannel(same-origin tabs). - No WebSocket transport in-tree. The transport interface is open; consumers wire their own. WebSocket adapter is planned.
- No RBAC, comments, suggestions, track-changes — these need their own model layer.
See spec §7.2 for the full design and convergence model.
Tests
400 fast-check cases per scenario family across convergence.prop.test.ts (sequential + disjoint-position + cursor-only). Arbitrary async schedules are a v0.6.x follow-up reserved by an it.todo.
