CRDT-based local-first sync engine inspired by EG-Walker
┌──────────────────────────────────────────────────┐
│ Application │
├───────────────────────┬──────────────────────────┤
│ Durable Layer │ Ephemeral Layer │
│ (CrdtDoc) │ (EphemeralStore) │
│ │ │
│ - Event Graph │ - LWW Register Map │
│ - Causal ordering │ - Timestamp + PeerId │
│ - RLE compressed │ - No history │
│ - Conflict-free │ - Overwrite semantics │
│ merge (EG-Walker) │ │
│ │ │
│ Use: DB CRUD, │ Use: Cursors, presence, │
│ document edits │ player positions, typing │
│ │ indicators │
├───────────────────────┴──────────────────────────┤
│ Sync Transport │
│ HTTP (push/pull) │ WebSocket (broadcast) │
└──────────────────────────────────────────────────┘src/
├── types/ Core type definitions (PeerId, EventId, Value, RowOp, Event, EventRun)
├── clock/ Lamport logical clock
├── graph/ Event DAG with frontier tracking and LCA computation
├── oplog/ Operation log with RLE compression
├── merge/ EG-Walker conflict resolution (LWW per column)
├── doc/ CrdtDoc — high-level Durable Layer API
├── ephemeral/ EphemeralStore — LWW Register Map (Ephemeral Layer)
├── bft/ BFT-CRDT adapter (Byzantine fault detection)
├── sync/ Sync protocol (PushRequest, PullRequest, PullResponse)
├── topology/ Network topology simulations (Star, Gossip, Mesh, etc.)
├── wasm/ WASM/JS exports for both layers
└── e2e/ End-to-end integration testsmoon build --target wasm-gc # WASM-GC output
moon build --target js # JavaScript output
moon test # Run all testscreate_doc(peer_id) -> handle
doc_insert(handle, tbl, row_id, values_json)
doc_update(handle, tbl, row_id, col, value_json)
doc_delete(handle, tbl, row_id)
doc_merge_remote(handle, events_json)
doc_get_pending(handle, known_json)
doc_sync_state(handle)ephemeral_set(handle, ns, key, value_json, timestamp)
ephemeral_get(handle, ns, key)
ephemeral_get_all(handle, ns)
ephemeral_merge(handle, entries_json)cd component
just build # Build .wasm component
just test # Build + jco transpile + Node.js testimport { converge } from './gen/converge-component.js';
const handle = converge.createDoc("peer-A");
converge.docInsert(handle, "users", "row1", [
{ key: "name", val: { tag: "val-str", val: "Alice" } },
{ key: "age", val: { tag: "val-int", val: 30 } },
]);
const h2 = converge.createDoc("peer-B");
const pending = converge.docGetPending(handle, []);
const ops = converge.docMergeRemote(h2, pending);[Application]
|
[CrdtDoc] <- unchanged
|
[BFTAdapter] <- validates before passing to CrdtDoc
|
[Transport] <- unchanged| Platform | Layers | WASM Target | Sync | Example |
|---|---|---|---|---|
| Cloudflare Workers + Durable Objects | Durable + Ephemeral | js | HTTP push/pull + WebSocket | examples/cf-do/ |
| Deno Deploy + Deno KV | Durable | wasm-gc | HTTP push/pull | examples/deno-deploy/ |
CRDT-based local-first sync engine inspired by EG-Walker