feat(crdt): add @robonen/crdt package

Hand-built CRDT primitives: Lamport clock + version vectors, op-log,
LWW register/map, RGA sequence, fractional indexing, marks store, sync
encode, and doc/replica. Includes eslint flat config + composite tsconfig.
This commit is contained in:
2026-06-07 16:28:58 +07:00
parent 70a8678743
commit 008d85a8fd
35 changed files with 1152 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
import type { OpId, SiteId } from './id';
/**
* Tracks the highest clock seen per site, assuming each site emits dense clocks
* (1, 2, 3, …). Used to deduplicate ops and to compute deltas during sync.
*/
export class VersionVector {
private readonly clocks = new Map<SiteId, number>();
/** Record that an op has been seen. */
observe(id: OpId): void {
if (id.clock > this.get(id.site))
this.clocks.set(id.site, id.clock);
}
/** Highest clock seen for a site (0 if none). */
get(site: SiteId): number {
return this.clocks.get(site) ?? 0;
}
/** Whether an op id has already been seen. */
has(id: OpId): boolean {
return this.get(id.site) >= id.clock;
}
/** Plain-object snapshot for transport. */
toJSON(): Record<SiteId, number> {
return Object.fromEntries(this.clocks);
}
static fromJSON(snapshot: Record<SiteId, number>): VersionVector {
const vv = new VersionVector();
for (const site in snapshot)
vv.clocks.set(site, snapshot[site]!);
return vv;
}
clone(): VersionVector {
return VersionVector.fromJSON(this.toJSON());
}
}