loro-repo
v0.12.1
Published
Draft TypeScript definitions for the LoroRepo orchestrator.
Readme
LoroRepo TypeScript bindings
LoroRepo is the collection-sync layer above Flock. It coordinates document metadata and document bodies so apps can:
- fetch metadata first, then open document bodies on demand,
- reuse one API across centralized servers, Durable Objects, and peer meshes,
- keep repo semantics predictable with explicit soft-delete and purge flows.
What you get
- Metadata-first coordination –
repo.listDoc()andrepo.watch()expose LWW metadata quickly. - On-demand documents –
openPersistedDoc()gives a repo-managedLoroDocthat can sync once or join a live room;openDetachedDoc()gives an isolated snapshot. - Pluggable adapters – provide your own
TransportAdapterandStorageAdapter(or use built-ins below). - Consistent events – every event includes
by: "local" | "sync" | "live". - Deletion lifecycle – soft delete (
deleteDoc) and hard purge (purgeDoc/gcDeletedDocs) are separate and explicit.
Quick start
import { LoroRepo } from "loro-repo";
import { BroadcastChannelTransportAdapter } from "loro-repo/transport/broadcast-channel";
import { IndexedDBStorageAdaptor } from "loro-repo/storage/indexeddb";
type DocMeta = { title?: string; tags?: string[] };
const repo = await LoroRepo.create<DocMeta>({
transportAdapter: new BroadcastChannelTransportAdapter({ namespace: "notes" }),
storageAdapter: new IndexedDBStorageAdaptor({ dbName: "notes-db" }),
});
await repo.sync({ scope: "meta" });
await repo.upsertDocMeta("note:welcome", { title: "Welcome" });
const handle = await repo.openPersistedDoc("note:welcome");
await handle.syncOnce();
const room = await handle.joinRoom();
handle.doc.getText("content").insert(0, "Hello from LoroRepo");
handle.doc.commit();
room.unsubscribe();
await repo.unloadDoc("note:welcome");Using the API
- Create a repo with
await LoroRepo.create<Meta>({ transportAdapter?, storageAdapter?, docFrontierDebounceMs? }). - Swap transport later with
await repo.setTransportAdapter(adapter). - Check adapter availability via
repo.hasTransport()andrepo.hasStorage(). - Choose sync lanes using
repo.sync({ scope: "meta" | "doc" | "full", docIds? }). - Work with docs through
openPersistedDoc,openDetachedDoc,joinDocRoom,unloadDoc, andflush. - React to changes with
repo.watch(listener, { docIds, kinds, metadataFields, by }). - Shutdown cleanly by calling
await repo.destroy().
Built-in adapters
BroadcastChannelTransportAdapter(src/transport/broadcast-channel.ts)WebSocketTransportAdapter(src/transport/websocket.ts)IndexedDBStorageAdaptor(src/storage/indexeddb.ts)FileSystemStorageAdaptor(src/storage/filesystem.ts)
Core API surface
Lifecycle
await LoroRepo.create<Meta>(options)await repo.sync(options?)await repo.destroy()
Metadata
await repo.upsertDocMeta(docId, patch)await repo.getDocMeta(docId)await repo.listDoc(query?)repo.getMeta()/repo.getRawMeta()
Documents
await repo.openPersistedDoc(docId)await repo.openDetachedDoc(docId)await repo.joinDocRoom(docId, params?)await repo.unloadDoc(docId)await repo.flush()
Deletion & retention
await repo.deleteDoc(docId, { deletedAt?, force? })await repo.restoreDoc(docId)await repo.purgeDoc(docId)await repo.gcDeletedDocs({ minKeepMs?, now? })
Events
const handle = repo.watch(listener, filter?)handle.unsubscribe()
Doc deletion lifecycle
- Soft delete (
deleteDoc) writests/<docId>and keeps metadata/doc snapshots available. - Retention window (
deletedDocKeepMs) controls when GC can purge. - Hard purge (
purgeDoc/gcDeletedDocs) removes metadata/frontiers/tombstone and drops local doc snapshots. - Legacy cleanup: during purge, legacy
ld/<docId>/*rows are also removed when present.
Commands
| Command | Purpose |
| --- | --- |
| pnpm --filter loro-repo typecheck | Runs tsc with noEmit. |
| pnpm --filter loro-repo test | Runs Vitest suites. |
| pnpm --filter loro-repo check | Runs typecheck + tests. |
Set LORO_WEBSOCKET_E2E=1 when running websocket end-to-end specs.
Examples
- P2P Journal (
examples/p2p-journal/) – Vite + React demo with BroadcastChannel + IndexedDB. - Sync script (
examples/sync-example.ts) – metadata/document synchronization walkthrough.
Contributing
Follow Conventional Commits, run pnpm --filter loro-repo check before opening a PR, and keep prd/ docs aligned with behavior changes.
