| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
loro-protocol is a small, transport-agnostic syncing protocol for collaborative CRDT documents. This repo hosts the protocol implementation, a WebSocket client, and minimal servers for local testing or self‑hosting.
See protocol.md for the full wire spec.
Rust workspace (MIT):
Use the minimal WebSocket server for local development and tests.
pnpm install
pnpm -r buildpnpm dev-simple-server// examples/client.ts
import { LoroWebsocketClient } from "loro-websocket";
import { LoroAdaptor } from "loro-adaptors/loro";
// In Node, provide a WebSocket implementation
import { WebSocket } from "ws";
(globalThis as any).WebSocket = WebSocket;
const client = new LoroWebsocketClient({ url: "ws://localhost:8787" });
await client.waitConnected();
const adaptor = new LoroAdaptor();
const room = await client.join({ roomId: "demo-room", crdtAdaptor: adaptor });
// Edit the shared doc
const text = adaptor.getDoc().getText("content");
text.insert(0, "Hello, Loro!");
adaptor.getDoc().commit();
// Later…
await room.destroy();Tip: For a working reference, see packages/loro-websocket/src/e2e.test.ts which spins up SimpleServer and syncs two clients end‑to‑end.
%ELO adds end‑to‑end encryption to Loro sync. The server never decrypts; it indexes plaintext headers only to support backfill and routing. Clients encrypt/decrypt using AES‑GCM with a 12‑byte IV and the exact encoded header bytes as AAD.
Example (Node 18+):
import { LoroWebsocketClient } from "loro-websocket/client";
import { EloAdaptor } from "loro-adaptors/loro";
import { WebSocket } from "ws";
(globalThis as any).WebSocket =
WebSocket as unknown as typeof globalThis.WebSocket;
const key = new Uint8Array([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
]);
const client = new LoroWebsocketClient({ url: "ws://localhost:8787" });
await client.waitConnected();
const adaptor = new EloAdaptor({
getPrivateKey: async () => ({ keyId: "k1", key }),
});
const room = await client.join({ roomId: "elo-room", crdtAdaptor: adaptor });
// Edit the encrypted doc
const text = adaptor.getDoc().getText("t");
text.insert(0, "hello");
adaptor.getDoc().commit();
await room.destroy();Notes:
We provide cross‑language tests to verify %ELO interoperability between the TS and Rust implementations.
pnpm run test:cross-langThis will:
Requirements:
SimpleServer accepts optional hooks for basic join metadata/auth handling and persistence:
const server = new SimpleServer({
port: 8787,
authenticate: async (roomId, crdt, auth) => {
// join metadata arrives as `auth`; return 'read' | 'write' | null to deny
return "write";
},
onLoadDocument: async (roomId, crdt) => null, // return snapshot bytes
onSaveDocument: async (roomId, crdt, data) => {
// persist snapshot bytes somewhere (e.g., filesystem/db)
},
saveInterval: 60_000, // ms
});The Rust workspace contains a minimal async WebSocket server (loro-websocket-server) with optional SQLite persistence. See rust/loro-websocket-server/examples/simple-server.rs for a CLI example.
See protocol.md for the full description and error codes.
Node 18+ is required for local development.
. ├── protocol.md # Wire protocol spec ├── packages/ │ ├── loro-protocol/ # Core encoders/decoders (MIT) │ ├── loro-websocket/ # Client + SimpleServer (MIT) │ ├── loro-adaptors/ # Shared CRDT adaptors (MIT) ├── rust/ # Rust implementations (MIT) │ ├── loro-protocol/ │ ├── loro-websocket-client/ │ └── loro-websocket-server/ └── pnpm-workspace.yaml
| Back | FazBrowse Home | New Git URL |