meridian-sdk 0.2.4 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,9 +5,9 @@ TypeScript SDK for [Meridian](../README.md) — Effect-based, fully typed, msgpa
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- bun add meridian-sdk effect msgpackr
8
+ bun add meridian-sdk
9
9
  # or
10
- npm install meridian-sdk effect msgpackr
10
+ npm install meridian-sdk
11
11
  ```
12
12
 
13
13
  ## Quick start
@@ -16,7 +16,6 @@ npm install meridian-sdk effect msgpackr
16
16
  import { Effect, Schema } from "effect";
17
17
  import { MeridianClient } from "meridian-sdk";
18
18
 
19
- // MeridianClient.create() parses + validates the token — returns Effect
20
19
  const client = await Effect.runPromise(
21
20
  MeridianClient.create({
22
21
  url: "http://localhost:3000",
@@ -42,6 +41,11 @@ const room = client.presence("pr:room", Cursor);
42
41
  room.heartbeat({ x: 100, y: 200 }, 30_000);
43
42
  room.onChange(entries => console.log("online:", entries));
44
43
 
44
+ // CRDTMap — composite document with named CRDT fields
45
+ const doc = client.crdtmap("doc:settings");
46
+ doc.lwwSet("theme", "dark");
47
+ doc.incrementCounter("edits");
48
+
45
49
  // Close WebSocket when done
46
50
  client.close();
47
51
  ```
@@ -89,6 +93,7 @@ await Effect.runPromise(
89
93
  | `client.orset(id, schema?)` | `ORSetHandle<T>` | Optional |
90
94
  | `client.lwwregister(id, schema?)` | `LwwRegisterHandle<T>` | Optional |
91
95
  | `client.presence(id, schema?)` | `PresenceHandle<T>` | Optional |
96
+ | `client.crdtmap(id)` | `CRDTMapHandle` | — |
92
97
 
93
98
  Without a schema, `T = unknown`. With a schema, incoming deltas are validated at runtime via `Schema.decodeUnknownSync`.
94
99
 
@@ -97,10 +102,10 @@ Without a schema, `T = unknown`. With a schema, incoming deltas are validated at
97
102
  All methods return `Effect<T, HttpError | NetworkError>`:
98
103
 
99
104
  ```ts
100
- client.http.getCrdt(ns, id) // → Effect<CrdtGetResponse, ...>
101
- client.http.postOp(ns, id, op) // → Effect<CrdtOpResponse, ...>
102
- client.http.syncCrdt(ns, id, sinceVc) // → Effect<CrdtGetResponse, ...>
103
- client.http.issueToken(ns, opts) // → Effect<TokenIssueResponse, ...>
105
+ client.http.getCrdt(ns, id) // → Effect<CrdtGetResponse, ...>
106
+ client.http.postOp(ns, id, op) // → Effect<CrdtOpResponse, ...>
107
+ client.http.syncCrdt(ns, id, sinceVc?) // → Effect<CrdtGetResponse, ...>
108
+ client.http.issueToken(ns, opts) // → Effect<TokenIssueResponse, ...>
104
109
  ```
105
110
 
106
111
  ## Wire protocol
package/dist/client.d.ts CHANGED
@@ -5,6 +5,7 @@ import { PNCounterHandle } from "./crdt/pncounter.js";
5
5
  import { ORSetHandle } from "./crdt/orset.js";
6
6
  import { LwwRegisterHandle } from "./crdt/lwwregister.js";
7
7
  import { PresenceHandle } from "./crdt/presence.js";
8
+ import { CRDTMapHandle } from "./crdt/crdtmap.js";
8
9
  import type { TokenClaims } from "./schema.js";
9
10
  import type { TokenParseError, TokenExpiredError } from "./errors.js";
10
11
  export interface MeridianClientConfig {
@@ -50,6 +51,7 @@ export declare class MeridianClient {
50
51
  private readonly orHandles;
51
52
  private readonly lwHandles;
52
53
  private readonly prHandles;
54
+ private readonly cmHandles;
53
55
  private constructor();
54
56
  /**
55
57
  * Creates and validates a new `MeridianClient` from the supplied configuration.
@@ -164,6 +166,23 @@ export declare class MeridianClient {
164
166
  * ```
165
167
  */
166
168
  presence<T>(crdtId: string, schema?: Schema.Schema<T>): PresenceHandle<T>;
169
+ /**
170
+ * Returns a handle for a CRDTMap — a map of named CRDT values.
171
+ *
172
+ * Handles are cached by `crdtId`; calling this method multiple times with the
173
+ * same id returns the same handle instance and creates only one subscription.
174
+ *
175
+ * @param crdtId - Unique identifier for the CRDT within this namespace.
176
+ *
177
+ * @example
178
+ * ```ts
179
+ * const doc = client.crdtmap('document-1');
180
+ * doc.lwwSet('title', 'Hello World');
181
+ * doc.incrementCounter('views');
182
+ * console.log(doc.value()); // { title: { value: 'Hello World', ... }, views: { total: 1, ... } }
183
+ * ```
184
+ */
185
+ crdtmap(crdtId: string): CRDTMapHandle;
167
186
  waitForConnected(timeoutMs?: number): Promise<void>;
168
187
  /**
169
188
  * Closes the underlying WebSocket connection.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AASpD,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,cAAc;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAE7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAG1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqC;IAC/D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsC;IAChE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2C;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiD;IAC3E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8C;IAExE,OAAO;IAsBP;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,MAAM,CACX,MAAM,EAAE,oBAAoB,GAC3B,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,eAAe,GAAG,iBAAiB,CAAC;IAMrE;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc;IAUxC;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe;IAU1C;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;IAWnE;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC;IAW/E;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC;IAWzE,gBAAgB,CAAC,SAAS,SAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD;;;;;;OAMG;IACH,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,eAAe;CA6BxB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAUlD,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,cAAc;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAE7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAG1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqC;IAC/D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsC;IAChE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2C;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiD;IAC3E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8C;IACxE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoC;IAE9D,OAAO;IAsBP;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,MAAM,CACX,MAAM,EAAE,oBAAoB,GAC3B,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,eAAe,GAAG,iBAAiB,CAAC;IAMrE;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc;IAUxC;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe;IAU1C;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;IAWnE;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC;IAW/E;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC;IAWzE;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa;IAUtC,gBAAgB,CAAC,SAAS,SAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD;;;;;;OAMG;IACH,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,eAAe;CAkCxB"}
package/dist/client.js CHANGED
@@ -6,7 +6,8 @@ import { PNCounterHandle } from "./crdt/pncounter.js";
6
6
  import { ORSetHandle } from "./crdt/orset.js";
7
7
  import { LwwRegisterHandle } from "./crdt/lwwregister.js";
8
8
  import { PresenceHandle } from "./crdt/presence.js";
9
- import { decodeGCounterDelta, decodePNCounterDelta, decodeORSetDelta, decodeLwwDelta, decodePresenceDelta, } from "./sync/delta.js";
9
+ import { CRDTMapHandle } from "./crdt/crdtmap.js";
10
+ import { decodeGCounterDelta, decodePNCounterDelta, decodeORSetDelta, decodeLwwDelta, decodePresenceDelta, decodeCRDTMapDelta, } from "./sync/delta.js";
10
11
  import { parseAndValidateToken } from "./auth/token.js";
11
12
  /**
12
13
  * The main entry point for the Meridian real-time CRDT SDK.
@@ -46,6 +47,7 @@ export class MeridianClient {
46
47
  orHandles = new Map();
47
48
  lwHandles = new Map();
48
49
  prHandles = new Map();
50
+ cmHandles = new Map();
49
51
  constructor(config, claims) {
50
52
  this.namespace = config.namespace;
51
53
  this.claims = claims;
@@ -222,6 +224,31 @@ export class MeridianClient {
222
224
  }
223
225
  return handle;
224
226
  }
227
+ /**
228
+ * Returns a handle for a CRDTMap — a map of named CRDT values.
229
+ *
230
+ * Handles are cached by `crdtId`; calling this method multiple times with the
231
+ * same id returns the same handle instance and creates only one subscription.
232
+ *
233
+ * @param crdtId - Unique identifier for the CRDT within this namespace.
234
+ *
235
+ * @example
236
+ * ```ts
237
+ * const doc = client.crdtmap('document-1');
238
+ * doc.lwwSet('title', 'Hello World');
239
+ * doc.incrementCounter('views');
240
+ * console.log(doc.value()); // { title: { value: 'Hello World', ... }, views: { total: 1, ... } }
241
+ * ```
242
+ */
243
+ crdtmap(crdtId) {
244
+ let handle = this.cmHandles.get(crdtId);
245
+ if (!handle) {
246
+ handle = new CRDTMapHandle({ ns: this.namespace, crdtId, clientId: this.clientId, transport: this.transport });
247
+ this.cmHandles.set(crdtId, handle);
248
+ this.transport.subscribe(crdtId);
249
+ }
250
+ return handle;
251
+ }
225
252
  waitForConnected(timeoutMs = 5_000) {
226
253
  return this.transport.waitForConnected(timeoutMs);
227
254
  }
@@ -277,6 +304,14 @@ export class MeridianClient {
277
304
  prHandle.applyDelta(decodePresenceDelta(delta_bytes));
278
305
  }
279
306
  catch { /* stale */ }
307
+ return;
308
+ }
309
+ const cmHandle = this.cmHandles.get(crdt_id);
310
+ if (cmHandle) {
311
+ try {
312
+ cmHandle.applyDelta(decodeCRDTMapDelta(delta_bytes));
313
+ }
314
+ catch { /* stale */ }
280
315
  }
281
316
  }
282
317
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import type { WsTransport } from "../transport/websocket.js";
2
+ import type { CRDTMapDelta } from "../sync/delta.js";
3
+ export interface CrdtMapValue {
4
+ [key: string]: unknown;
5
+ }
6
+ /**
7
+ * Low-level handle for a CRDTMap — a map of named CRDT values.
8
+ *
9
+ * Each key holds an independent CRDT (GCounter, PNCounter, ORSet, LwwRegister,
10
+ * or Presence). The type of each key is fixed at first write.
11
+ *
12
+ * Obtained via `MeridianClient.crdtmap()`. Prefer the `useCRDTMap` React hook
13
+ * for component-level usage; use this handle directly in non-React environments.
14
+ */
15
+ export declare class CRDTMapHandle {
16
+ private state;
17
+ private readonly crdtId;
18
+ private readonly clientId;
19
+ private readonly transport;
20
+ private readonly listeners;
21
+ constructor(opts: {
22
+ ns: string;
23
+ crdtId: string;
24
+ clientId: number;
25
+ transport: WsTransport;
26
+ initial?: CrdtMapValue;
27
+ });
28
+ /** Returns a snapshot of the current map value (key → CRDT observable value). */
29
+ value(): Readonly<CrdtMapValue>;
30
+ /** Returns the value at a specific key, or `undefined` if absent. */
31
+ get(key: string): unknown;
32
+ /**
33
+ * Registers a listener that is called whenever any key in the map changes.
34
+ *
35
+ * @returns An unsubscribe function — call it to stop receiving updates.
36
+ */
37
+ onChange(listener: (value: CrdtMapValue) => void): () => void;
38
+ /** Increment a GCounter key by `amount` (default `1`). */
39
+ incrementCounter(key: string, amount?: number): void;
40
+ /** Increment a PNCounter key by `amount` (default `1`). */
41
+ incrementPNCounter(key: string, amount?: number): void;
42
+ /** Decrement a PNCounter key by `amount` (default `1`). */
43
+ decrementPNCounter(key: string, amount?: number): void;
44
+ /** Add an element to an ORSet key. `tag` must be a 16-byte UUID as Uint8Array. */
45
+ orsetAdd(key: string, element: unknown, tag: Uint8Array): void;
46
+ /** Remove an element from an ORSet key. `knownTags` is the set of tags to remove. */
47
+ orsetRemove(key: string, element: unknown, knownTags: Uint8Array[]): void;
48
+ /** Write a value to an LWW-Register key. */
49
+ lwwSet(key: string, value: unknown): void;
50
+ applyDelta(delta: CRDTMapDelta): void;
51
+ private emit;
52
+ }
53
+ //# sourceMappingURL=crdtmap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crdtmap.d.ts","sourceRoot":"","sources":["../../src/crdt/crdtmap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,kBAAkB,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IAExC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;gBAE1D,IAAI,EAAE;QAChB,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,WAAW,CAAC;QACvB,OAAO,CAAC,EAAE,YAAY,CAAC;KACxB;IAOD,iFAAiF;IACjF,KAAK,IAAI,QAAQ,CAAC,YAAY,CAAC;IAI/B,qEAAqE;IACrE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI;IAK7D,0DAA0D;IAC1D,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI;IAYvD,2DAA2D;IAC3D,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI;IAYzD,2DAA2D;IAC3D,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI;IAYzD,kFAAkF;IAClF,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI;IAW9D,qFAAqF;IACrF,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI;IAWzE,4CAA4C;IAC5C,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAkBzC,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAYrC,OAAO,CAAC,IAAI;CAGb"}
@@ -0,0 +1,216 @@
1
+ import { encode } from "../codec.js";
2
+ /**
3
+ * Low-level handle for a CRDTMap — a map of named CRDT values.
4
+ *
5
+ * Each key holds an independent CRDT (GCounter, PNCounter, ORSet, LwwRegister,
6
+ * or Presence). The type of each key is fixed at first write.
7
+ *
8
+ * Obtained via `MeridianClient.crdtmap()`. Prefer the `useCRDTMap` React hook
9
+ * for component-level usage; use this handle directly in non-React environments.
10
+ */
11
+ export class CRDTMapHandle {
12
+ state = {};
13
+ crdtId;
14
+ clientId;
15
+ transport;
16
+ listeners = new Set();
17
+ constructor(opts) {
18
+ this.crdtId = opts.crdtId;
19
+ this.clientId = opts.clientId;
20
+ this.transport = opts.transport;
21
+ this.state = opts.initial ?? {};
22
+ }
23
+ /** Returns a snapshot of the current map value (key → CRDT observable value). */
24
+ value() {
25
+ return this.state;
26
+ }
27
+ /** Returns the value at a specific key, or `undefined` if absent. */
28
+ get(key) {
29
+ return this.state[key];
30
+ }
31
+ /**
32
+ * Registers a listener that is called whenever any key in the map changes.
33
+ *
34
+ * @returns An unsubscribe function — call it to stop receiving updates.
35
+ */
36
+ onChange(listener) {
37
+ this.listeners.add(listener);
38
+ return () => { this.listeners.delete(listener); };
39
+ }
40
+ /** Increment a GCounter key by `amount` (default `1`). */
41
+ incrementCounter(key, amount = 1) {
42
+ if (amount <= 0)
43
+ throw new RangeError("CRDTMap.incrementCounter: amount must be > 0");
44
+ const op = encode({
45
+ CRDTMap: {
46
+ key,
47
+ crdt_type: "GCounter",
48
+ op: { GCounter: { client_id: this.clientId, amount } },
49
+ },
50
+ });
51
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
52
+ }
53
+ /** Increment a PNCounter key by `amount` (default `1`). */
54
+ incrementPNCounter(key, amount = 1) {
55
+ if (amount <= 0)
56
+ throw new RangeError("CRDTMap.incrementPNCounter: amount must be > 0");
57
+ const op = encode({
58
+ CRDTMap: {
59
+ key,
60
+ crdt_type: "PNCounter",
61
+ op: { PNCounter: { Increment: { client_id: this.clientId, amount } } },
62
+ },
63
+ });
64
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
65
+ }
66
+ /** Decrement a PNCounter key by `amount` (default `1`). */
67
+ decrementPNCounter(key, amount = 1) {
68
+ if (amount <= 0)
69
+ throw new RangeError("CRDTMap.decrementPNCounter: amount must be > 0");
70
+ const op = encode({
71
+ CRDTMap: {
72
+ key,
73
+ crdt_type: "PNCounter",
74
+ op: { PNCounter: { Decrement: { client_id: this.clientId, amount } } },
75
+ },
76
+ });
77
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
78
+ }
79
+ /** Add an element to an ORSet key. `tag` must be a 16-byte UUID as Uint8Array. */
80
+ orsetAdd(key, element, tag) {
81
+ const op = encode({
82
+ CRDTMap: {
83
+ key,
84
+ crdt_type: "ORSet",
85
+ op: { ORSet: { Add: { element, tag } } },
86
+ },
87
+ });
88
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
89
+ }
90
+ /** Remove an element from an ORSet key. `knownTags` is the set of tags to remove. */
91
+ orsetRemove(key, element, knownTags) {
92
+ const op = encode({
93
+ CRDTMap: {
94
+ key,
95
+ crdt_type: "ORSet",
96
+ op: { ORSet: { Remove: { element, known_tags: knownTags } } },
97
+ },
98
+ });
99
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
100
+ }
101
+ /** Write a value to an LWW-Register key. */
102
+ lwwSet(key, value) {
103
+ const wallMs = Date.now();
104
+ const op = encode({
105
+ CRDTMap: {
106
+ key,
107
+ crdt_type: "LwwRegister",
108
+ op: {
109
+ LwwRegister: {
110
+ value,
111
+ hlc: { wall_ms: wallMs, logical: 0, node_id: this.clientId },
112
+ author: this.clientId,
113
+ },
114
+ },
115
+ },
116
+ });
117
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
118
+ }
119
+ applyDelta(delta) {
120
+ let changed = false;
121
+ for (const [key, valueDelta] of Object.entries(delta.deltas)) {
122
+ const updated = applyValueDelta(this.state[key], valueDelta);
123
+ if (updated !== undefined) {
124
+ this.state[key] = updated;
125
+ changed = true;
126
+ }
127
+ }
128
+ if (changed)
129
+ this.emit();
130
+ }
131
+ emit() {
132
+ for (const listener of this.listeners)
133
+ listener(this.state);
134
+ }
135
+ }
136
+ const applyValueDelta = (current, delta) => {
137
+ if ("GCounter" in delta) {
138
+ // HACK: current is unknown — shape is set by previous applyValueDelta call
139
+ const currentCounts = current?.counts ?? {};
140
+ const merged = { ...currentCounts };
141
+ for (const [clientId, count] of Object.entries(delta.GCounter.counters)) {
142
+ if ((merged[clientId] ?? 0) < count)
143
+ merged[clientId] = count;
144
+ }
145
+ const total = Object.values(merged).reduce((sum, count) => sum + count, 0);
146
+ return { total, counts: merged };
147
+ }
148
+ if ("PNCounter" in delta) {
149
+ // HACK: current is unknown — shape is set by previous applyValueDelta call
150
+ const currentPn = current;
151
+ const pos = mergeCounterMap(currentPn?.pos ?? {}, delta.PNCounter.pos?.counters ?? {});
152
+ const neg = mergeCounterMap(currentPn?.neg ?? {}, delta.PNCounter.neg?.counters ?? {});
153
+ const value = Object.values(pos).reduce((sum, count) => sum + count, 0)
154
+ - Object.values(neg).reduce((sum, count) => sum + count, 0);
155
+ return { value, pos, neg };
156
+ }
157
+ if ("ORSet" in delta) {
158
+ // HACK: current is unknown — shape is set by previous applyValueDelta call
159
+ const currentOrset = current;
160
+ const existing = new Set((currentOrset?.elements ?? []).map((element) => JSON.stringify(element)));
161
+ for (const key of Object.keys(delta.ORSet.adds)) {
162
+ existing.add(key);
163
+ }
164
+ for (const key of Object.keys(delta.ORSet.removes)) {
165
+ existing.delete(key);
166
+ }
167
+ return { elements: Array.from(existing).map((key) => { try {
168
+ return JSON.parse(key);
169
+ }
170
+ catch {
171
+ return key;
172
+ } }) };
173
+ }
174
+ if ("LwwRegister" in delta) {
175
+ const entry = delta.LwwRegister.entry;
176
+ if (entry === null)
177
+ return current;
178
+ // HACK: current is unknown — shape is set by previous applyValueDelta call
179
+ const currentLww = current;
180
+ if (currentLww?.hlc) {
181
+ const currentWallMs = Number(currentLww.hlc.wall_ms);
182
+ const newWallMs = Number(entry.hlc.wall_ms);
183
+ if (newWallMs < currentWallMs)
184
+ return current;
185
+ if (newWallMs === currentWallMs && entry.hlc.logical < (currentLww.hlc.logical ?? 0))
186
+ return current;
187
+ if (newWallMs === currentWallMs && entry.hlc.logical === (currentLww.hlc.logical ?? 0) && Number(entry.author) <= Number(currentLww.author ?? 0))
188
+ return current;
189
+ }
190
+ return { value: entry.value, updatedAtMs: Number(entry.hlc.wall_ms), author: Number(entry.author) };
191
+ }
192
+ if ("Presence" in delta) {
193
+ // HACK: current is unknown — shape is set by previous applyValueDelta call
194
+ const currentPresence = current;
195
+ const entries = { ...(currentPresence?.entries ?? {}) };
196
+ for (const [clientId, entry] of Object.entries(delta.Presence.changes)) {
197
+ if (entry === null) {
198
+ delete entries[clientId];
199
+ }
200
+ else {
201
+ entries[clientId] = { data: entry.data, expiresAtMs: Number(entry.hlc.wall_ms) + Number(entry.ttl_ms) };
202
+ }
203
+ }
204
+ return { entries };
205
+ }
206
+ return current;
207
+ };
208
+ const mergeCounterMap = (source, incoming) => {
209
+ const result = { ...source };
210
+ for (const [clientId, count] of Object.entries(incoming)) {
211
+ if ((result[clientId] ?? 0) < count)
212
+ result[clientId] = count;
213
+ }
214
+ return result;
215
+ };
216
+ //# sourceMappingURL=crdtmap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crdtmap.js","sourceRoot":"","sources":["../../src/crdt/crdtmap.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -6,6 +6,8 @@ export { ORSetHandle } from "./crdt/orset.js";
6
6
  export { LwwRegisterHandle } from "./crdt/lwwregister.js";
7
7
  export { PresenceHandle } from "./crdt/presence.js";
8
8
  export type { PresenceEntry } from "./crdt/presence.js";
9
+ export { CRDTMapHandle } from "./crdt/crdtmap.js";
10
+ export type { CrdtMapValue } from "./crdt/crdtmap.js";
9
11
  export { HttpClient } from "./transport/http.js";
10
12
  export type { HttpClientConfig } from "./transport/http.js";
11
13
  export { WsTransport } from "./transport/websocket.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAG3E,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlG,OAAO,EACL,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,cAAc,GACf,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,SAAS,EACT,SAAS,EACT,aAAa,EACb,cAAc,EACd,UAAU,EACV,QAAQ,EACR,aAAa,EACb,eAAe,EACf,cAAc,EACd,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGzD,OAAO,EACL,MAAM,EACN,MAAM,EACN,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAG3E,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlG,OAAO,EACL,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,cAAc,GACf,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,SAAS,EACT,SAAS,EACT,aAAa,EACb,cAAc,EACd,UAAU,EACV,QAAQ,EACR,aAAa,EACb,eAAe,EACf,cAAc,EACd,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGzD,OAAO,EACL,MAAM,EACN,MAAM,EACN,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ export { PNCounterHandle } from "./crdt/pncounter.js";
6
6
  export { ORSetHandle } from "./crdt/orset.js";
7
7
  export { LwwRegisterHandle } from "./crdt/lwwregister.js";
8
8
  export { PresenceHandle } from "./crdt/presence.js";
9
+ export { CRDTMapHandle } from "./crdt/crdtmap.js";
9
10
  // Transport
10
11
  export { HttpClient } from "./transport/http.js";
11
12
  export { WsTransport } from "./transport/websocket.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,eAAe;AACf,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,YAAY;AACZ,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO;AACP,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElG,iEAAiE;AACjE,OAAO,EACL,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,qEAAqE;AACrE,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,SAAS,EACT,SAAS,EACT,aAAa,EACb,cAAc,EACd,UAAU,EACV,QAAQ,EACR,aAAa,EACb,eAAe,EACf,cAAc,EACd,aAAa,GACd,MAAM,aAAa,CAAC;AAGrB,qCAAqC;AACrC,OAAO,EACL,MAAM,EACN,MAAM,EACN,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,eAAe;AACf,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,YAAY;AACZ,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO;AACP,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElG,iEAAiE;AACjE,OAAO,EACL,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,qEAAqE;AACrE,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,SAAS,EACT,SAAS,EACT,aAAa,EACb,cAAc,EACd,UAAU,EACV,QAAQ,EACR,aAAa,EACb,eAAe,EACf,cAAc,EACd,aAAa,GACd,MAAM,aAAa,CAAC;AAGrB,qCAAqC;AACrC,OAAO,EACL,MAAM,EACN,MAAM,EACN,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
@@ -38,4 +38,19 @@ export interface PresenceDelta {
38
38
  changes: Record<string, PresenceEntryDelta | null>;
39
39
  }
40
40
  export declare const decodePresenceDelta: (bytes: Uint8Array) => PresenceDelta;
41
+ export type CrdtValueDelta = {
42
+ GCounter: GCounterDelta;
43
+ } | {
44
+ PNCounter: PNCounterDelta;
45
+ } | {
46
+ ORSet: ORSetDelta;
47
+ } | {
48
+ LwwRegister: LwwDelta;
49
+ } | {
50
+ Presence: PresenceDelta;
51
+ };
52
+ export interface CRDTMapDelta {
53
+ deltas: Record<string, CrdtValueDelta>;
54
+ }
55
+ export declare const decodeCRDTMapDelta: (bytes: Uint8Array) => CRDTMapDelta;
41
56
  //# sourceMappingURL=delta.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"delta.d.ts","sourceRoot":"","sources":["../../src/sync/delta.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,eAAO,MAAM,mBAAmB,GAAI,OAAO,UAAU,KAAG,aAGvD,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC;IAC1B,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC;CAC3B;AAED,eAAO,MAAM,oBAAoB,GAAI,OAAO,UAAU,KAAG,cASxD,CAAC;AAEF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;CACvC;AAED,eAAO,MAAM,gBAAgB,GAAI,OAAO,UAAU,KAAG,UAUpD,CAAC;AAEF,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC7E,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,cAAc,GAAI,OAAO,UAAU,KAAG,QAGlD,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC7E,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAC,CAAC;CACpD;AAED,eAAO,MAAM,mBAAmB,GAAI,OAAO,UAAU,KAAG,aAGvD,CAAC"}
1
+ {"version":3,"file":"delta.d.ts","sourceRoot":"","sources":["../../src/sync/delta.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,eAAO,MAAM,mBAAmB,GAAI,OAAO,UAAU,KAAG,aAGvD,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC;IAC1B,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC;CAC3B;AAED,eAAO,MAAM,oBAAoB,GAAI,OAAO,UAAU,KAAG,cASxD,CAAC;AAEF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;CACvC;AAED,eAAO,MAAM,gBAAgB,GAAI,OAAO,UAAU,KAAG,UAUpD,CAAC;AAEF,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC7E,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,cAAc,GAAI,OAAO,UAAU,KAAG,QAGlD,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC7E,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAC,CAAC;CACpD;AAED,eAAO,MAAM,mBAAmB,GAAI,OAAO,UAAU,KAAG,aAGvD,CAAC;AAEF,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,EAAE,aAAa,CAAA;CAAE,GAC3B;IAAE,SAAS,EAAE,cAAc,CAAA;CAAE,GAC7B;IAAE,KAAK,EAAE,UAAU,CAAA;CAAE,GACrB;IAAE,WAAW,EAAE,QAAQ,CAAA;CAAE,GACzB;IAAE,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC;AAEhC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACxC;AAED,eAAO,MAAM,kBAAkB,GAAI,OAAO,UAAU,KAAG,YAGtD,CAAC"}
@@ -24,4 +24,8 @@ export const decodePresenceDelta = (bytes) => {
24
24
  const raw = decode(bytes);
25
25
  return { changes: raw.changes ?? {} };
26
26
  };
27
+ export const decodeCRDTMapDelta = (bytes) => {
28
+ const raw = decode(bytes);
29
+ return { deltas: (raw.deltas ?? {}) };
30
+ };
27
31
  //# sourceMappingURL=delta.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"delta.js","sourceRoot":"","sources":["../../src/sync/delta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAiB,EAAiB,EAAE;IACtE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAA0C,CAAC;IACnE,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;AAC1C,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAiB,EAAkB,EAAE;IACxE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAGvB,CAAC;IACF,OAAO;QACL,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI;QAC1D,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI;KAC3D,CAAC;AACJ,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAiB,EAAc,EAAE;IAChE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAGvB,CAAC;IACF,MAAM,OAAO,GAAG,CAAC,KAAc,EAAc,EAAE,CAC7C,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAiB,CAAC,CAAC;IAC1E,MAAM,SAAS,GAAG,CAAC,GAA+B,EAAE,EAAE,CACpD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;AACxE,CAAC,CAAC;AAYF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAiB,EAAY,EAAE;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAgC,CAAC;IACzD,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;AACtC,CAAC,CAAC;AAYF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAiB,EAAiB,EAAE;IACtE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAA4D,CAAC;IACrF,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;AACxC,CAAC,CAAC"}
1
+ {"version":3,"file":"delta.js","sourceRoot":"","sources":["../../src/sync/delta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAiB,EAAiB,EAAE;IACtE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAA0C,CAAC;IACnE,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;AAC1C,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAiB,EAAkB,EAAE;IACxE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAGvB,CAAC;IACF,OAAO;QACL,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI;QAC1D,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI;KAC3D,CAAC;AACJ,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAiB,EAAc,EAAE;IAChE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAGvB,CAAC;IACF,MAAM,OAAO,GAAG,CAAC,KAAc,EAAc,EAAE,CAC7C,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAiB,CAAC,CAAC;IAC1E,MAAM,SAAS,GAAG,CAAC,GAA+B,EAAE,EAAE,CACpD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;AACxE,CAAC,CAAC;AAYF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAiB,EAAY,EAAE;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAgC,CAAC;IACzD,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;AACtC,CAAC,CAAC;AAYF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAiB,EAAiB,EAAE;IACtE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAA4D,CAAC;IACrF,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;AACxC,CAAC,CAAC;AAaF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAiB,EAAgB,EAAE;IACpE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAyC,CAAC;IAClE,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAmC,EAAE,CAAC;AAC1E,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meridian-sdk",
3
- "version": "0.2.4",
3
+ "version": "0.3.1",
4
4
  "description": "TypeScript SDK for Meridian CRDT server",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/client.ts CHANGED
@@ -6,12 +6,14 @@ import { PNCounterHandle } from "./crdt/pncounter.js";
6
6
  import { ORSetHandle } from "./crdt/orset.js";
7
7
  import { LwwRegisterHandle } from "./crdt/lwwregister.js";
8
8
  import { PresenceHandle } from "./crdt/presence.js";
9
+ import { CRDTMapHandle } from "./crdt/crdtmap.js";
9
10
  import {
10
11
  decodeGCounterDelta,
11
12
  decodePNCounterDelta,
12
13
  decodeORSetDelta,
13
14
  decodeLwwDelta,
14
15
  decodePresenceDelta,
16
+ decodeCRDTMapDelta,
15
17
  } from "./sync/delta.js";
16
18
  import { parseAndValidateToken } from "./auth/token.js";
17
19
  import type { ServerMsg, TokenClaims } from "./schema.js";
@@ -64,6 +66,7 @@ export class MeridianClient {
64
66
  private readonly orHandles = new Map<string, ORSetHandle<unknown>>();
65
67
  private readonly lwHandles = new Map<string, LwwRegisterHandle<unknown>>();
66
68
  private readonly prHandles = new Map<string, PresenceHandle<unknown>>();
69
+ private readonly cmHandles = new Map<string, CRDTMapHandle>();
67
70
 
68
71
  private constructor(config: MeridianClientConfig, claims: TokenClaims) {
69
72
  this.namespace = config.namespace;
@@ -255,6 +258,32 @@ export class MeridianClient {
255
258
  return handle;
256
259
  }
257
260
 
261
+ /**
262
+ * Returns a handle for a CRDTMap — a map of named CRDT values.
263
+ *
264
+ * Handles are cached by `crdtId`; calling this method multiple times with the
265
+ * same id returns the same handle instance and creates only one subscription.
266
+ *
267
+ * @param crdtId - Unique identifier for the CRDT within this namespace.
268
+ *
269
+ * @example
270
+ * ```ts
271
+ * const doc = client.crdtmap('document-1');
272
+ * doc.lwwSet('title', 'Hello World');
273
+ * doc.incrementCounter('views');
274
+ * console.log(doc.value()); // { title: { value: 'Hello World', ... }, views: { total: 1, ... } }
275
+ * ```
276
+ */
277
+ crdtmap(crdtId: string): CRDTMapHandle {
278
+ let handle = this.cmHandles.get(crdtId);
279
+ if (!handle) {
280
+ handle = new CRDTMapHandle({ ns: this.namespace, crdtId, clientId: this.clientId, transport: this.transport });
281
+ this.cmHandles.set(crdtId, handle);
282
+ this.transport.subscribe(crdtId);
283
+ }
284
+ return handle;
285
+ }
286
+
258
287
  waitForConnected(timeoutMs = 5_000): Promise<void> {
259
288
  return this.transport.waitForConnected(timeoutMs);
260
289
  }
@@ -297,6 +326,11 @@ export class MeridianClient {
297
326
  const prHandle = this.prHandles.get(crdt_id);
298
327
  if (prHandle) {
299
328
  try { prHandle.applyDelta(decodePresenceDelta(delta_bytes)); } catch { /* stale */ }
329
+ return;
330
+ }
331
+ const cmHandle = this.cmHandles.get(crdt_id);
332
+ if (cmHandle) {
333
+ try { cmHandle.applyDelta(decodeCRDTMapDelta(delta_bytes)); } catch { /* stale */ }
300
334
  }
301
335
  }
302
336
  }
@@ -0,0 +1,231 @@
1
+ import { encode } from "../codec.js";
2
+ import type { WsTransport } from "../transport/websocket.js";
3
+ import type { CRDTMapDelta, CrdtValueDelta } from "../sync/delta.js";
4
+
5
+ export interface CrdtMapValue {
6
+ [key: string]: unknown;
7
+ }
8
+
9
+ /**
10
+ * Low-level handle for a CRDTMap — a map of named CRDT values.
11
+ *
12
+ * Each key holds an independent CRDT (GCounter, PNCounter, ORSet, LwwRegister,
13
+ * or Presence). The type of each key is fixed at first write.
14
+ *
15
+ * Obtained via `MeridianClient.crdtmap()`. Prefer the `useCRDTMap` React hook
16
+ * for component-level usage; use this handle directly in non-React environments.
17
+ */
18
+ export class CRDTMapHandle {
19
+ private state: CrdtMapValue = {};
20
+ private readonly crdtId: string;
21
+ private readonly clientId: number;
22
+ private readonly transport: WsTransport;
23
+
24
+ private readonly listeners = new Set<(value: CrdtMapValue) => void>();
25
+
26
+ constructor(opts: {
27
+ ns: string;
28
+ crdtId: string;
29
+ clientId: number;
30
+ transport: WsTransport;
31
+ initial?: CrdtMapValue;
32
+ }) {
33
+ this.crdtId = opts.crdtId;
34
+ this.clientId = opts.clientId;
35
+ this.transport = opts.transport;
36
+ this.state = opts.initial ?? {};
37
+ }
38
+
39
+ /** Returns a snapshot of the current map value (key → CRDT observable value). */
40
+ value(): Readonly<CrdtMapValue> {
41
+ return this.state;
42
+ }
43
+
44
+ /** Returns the value at a specific key, or `undefined` if absent. */
45
+ get(key: string): unknown {
46
+ return this.state[key];
47
+ }
48
+
49
+ /**
50
+ * Registers a listener that is called whenever any key in the map changes.
51
+ *
52
+ * @returns An unsubscribe function — call it to stop receiving updates.
53
+ */
54
+ onChange(listener: (value: CrdtMapValue) => void): () => void {
55
+ this.listeners.add(listener);
56
+ return () => { this.listeners.delete(listener); };
57
+ }
58
+
59
+ /** Increment a GCounter key by `amount` (default `1`). */
60
+ incrementCounter(key: string, amount: number = 1): void {
61
+ if (amount <= 0) throw new RangeError("CRDTMap.incrementCounter: amount must be > 0");
62
+ const op = encode({
63
+ CRDTMap: {
64
+ key,
65
+ crdt_type: "GCounter",
66
+ op: { GCounter: { client_id: this.clientId, amount } },
67
+ },
68
+ });
69
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
70
+ }
71
+
72
+ /** Increment a PNCounter key by `amount` (default `1`). */
73
+ incrementPNCounter(key: string, amount: number = 1): void {
74
+ if (amount <= 0) throw new RangeError("CRDTMap.incrementPNCounter: amount must be > 0");
75
+ const op = encode({
76
+ CRDTMap: {
77
+ key,
78
+ crdt_type: "PNCounter",
79
+ op: { PNCounter: { Increment: { client_id: this.clientId, amount } } },
80
+ },
81
+ });
82
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
83
+ }
84
+
85
+ /** Decrement a PNCounter key by `amount` (default `1`). */
86
+ decrementPNCounter(key: string, amount: number = 1): void {
87
+ if (amount <= 0) throw new RangeError("CRDTMap.decrementPNCounter: amount must be > 0");
88
+ const op = encode({
89
+ CRDTMap: {
90
+ key,
91
+ crdt_type: "PNCounter",
92
+ op: { PNCounter: { Decrement: { client_id: this.clientId, amount } } },
93
+ },
94
+ });
95
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
96
+ }
97
+
98
+ /** Add an element to an ORSet key. `tag` must be a 16-byte UUID as Uint8Array. */
99
+ orsetAdd(key: string, element: unknown, tag: Uint8Array): void {
100
+ const op = encode({
101
+ CRDTMap: {
102
+ key,
103
+ crdt_type: "ORSet",
104
+ op: { ORSet: { Add: { element, tag } } },
105
+ },
106
+ });
107
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
108
+ }
109
+
110
+ /** Remove an element from an ORSet key. `knownTags` is the set of tags to remove. */
111
+ orsetRemove(key: string, element: unknown, knownTags: Uint8Array[]): void {
112
+ const op = encode({
113
+ CRDTMap: {
114
+ key,
115
+ crdt_type: "ORSet",
116
+ op: { ORSet: { Remove: { element, known_tags: knownTags } } },
117
+ },
118
+ });
119
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
120
+ }
121
+
122
+ /** Write a value to an LWW-Register key. */
123
+ lwwSet(key: string, value: unknown): void {
124
+ const wallMs = Date.now();
125
+ const op = encode({
126
+ CRDTMap: {
127
+ key,
128
+ crdt_type: "LwwRegister",
129
+ op: {
130
+ LwwRegister: {
131
+ value,
132
+ hlc: { wall_ms: wallMs, logical: 0, node_id: this.clientId },
133
+ author: this.clientId,
134
+ },
135
+ },
136
+ },
137
+ });
138
+ this.transport.send({ Op: { crdt_id: this.crdtId, op_bytes: op } });
139
+ }
140
+
141
+ applyDelta(delta: CRDTMapDelta): void {
142
+ let changed = false;
143
+ for (const [key, valueDelta] of Object.entries(delta.deltas)) {
144
+ const updated = applyValueDelta(this.state[key], valueDelta);
145
+ if (updated !== undefined) {
146
+ this.state[key] = updated;
147
+ changed = true;
148
+ }
149
+ }
150
+ if (changed) this.emit();
151
+ }
152
+
153
+ private emit(): void {
154
+ for (const listener of this.listeners) listener(this.state);
155
+ }
156
+ }
157
+
158
+ const applyValueDelta = (current: unknown, delta: CrdtValueDelta): unknown => {
159
+ if ("GCounter" in delta) {
160
+ // HACK: current is unknown — shape is set by previous applyValueDelta call
161
+ const currentCounts = (current as { counts?: Record<string, number> } | undefined)?.counts ?? {};
162
+ const merged: Record<string, number> = { ...currentCounts };
163
+ for (const [clientId, count] of Object.entries(delta.GCounter.counters)) {
164
+ if ((merged[clientId] ?? 0) < count) merged[clientId] = count;
165
+ }
166
+ const total = Object.values(merged).reduce((sum, count) => sum + count, 0);
167
+ return { total, counts: merged };
168
+ }
169
+
170
+ if ("PNCounter" in delta) {
171
+ // HACK: current is unknown — shape is set by previous applyValueDelta call
172
+ const currentPn = current as { pos?: Record<string, number>; neg?: Record<string, number> } | undefined;
173
+ const pos = mergeCounterMap(currentPn?.pos ?? {}, delta.PNCounter.pos?.counters ?? {});
174
+ const neg = mergeCounterMap(currentPn?.neg ?? {}, delta.PNCounter.neg?.counters ?? {});
175
+ const value = Object.values(pos).reduce((sum, count) => sum + count, 0)
176
+ - Object.values(neg).reduce((sum, count) => sum + count, 0);
177
+ return { value, pos, neg };
178
+ }
179
+
180
+ if ("ORSet" in delta) {
181
+ // HACK: current is unknown — shape is set by previous applyValueDelta call
182
+ const currentOrset = current as { elements?: unknown[] } | undefined;
183
+ const existing = new Set((currentOrset?.elements ?? []).map((element) => JSON.stringify(element)));
184
+ for (const key of Object.keys(delta.ORSet.adds)) {
185
+ existing.add(key);
186
+ }
187
+ for (const key of Object.keys(delta.ORSet.removes)) {
188
+ existing.delete(key);
189
+ }
190
+ return { elements: Array.from(existing).map((key) => { try { return JSON.parse(key); } catch { return key; } }) };
191
+ }
192
+
193
+ if ("LwwRegister" in delta) {
194
+ const entry = delta.LwwRegister.entry;
195
+ if (entry === null) return current;
196
+ // HACK: current is unknown — shape is set by previous applyValueDelta call
197
+ const currentLww = current as { hlc?: { wall_ms: number; logical: number }; author?: number } | undefined;
198
+ if (currentLww?.hlc) {
199
+ const currentWallMs = Number(currentLww.hlc.wall_ms);
200
+ const newWallMs = Number(entry.hlc.wall_ms);
201
+ if (newWallMs < currentWallMs) return current;
202
+ if (newWallMs === currentWallMs && entry.hlc.logical < (currentLww.hlc.logical ?? 0)) return current;
203
+ if (newWallMs === currentWallMs && entry.hlc.logical === (currentLww.hlc.logical ?? 0) && Number(entry.author) <= Number(currentLww.author ?? 0)) return current;
204
+ }
205
+ return { value: entry.value, updatedAtMs: Number(entry.hlc.wall_ms), author: Number(entry.author) };
206
+ }
207
+
208
+ if ("Presence" in delta) {
209
+ // HACK: current is unknown — shape is set by previous applyValueDelta call
210
+ const currentPresence = current as { entries?: Record<string, unknown> } | undefined;
211
+ const entries = { ...(currentPresence?.entries ?? {}) };
212
+ for (const [clientId, entry] of Object.entries(delta.Presence.changes)) {
213
+ if (entry === null) {
214
+ delete entries[clientId];
215
+ } else {
216
+ entries[clientId] = { data: entry.data, expiresAtMs: Number(entry.hlc.wall_ms) + Number(entry.ttl_ms) };
217
+ }
218
+ }
219
+ return { entries };
220
+ }
221
+
222
+ return current;
223
+ };
224
+
225
+ const mergeCounterMap = (source: Record<string, number>, incoming: Record<string, number>): Record<string, number> => {
226
+ const result = { ...source };
227
+ for (const [clientId, count] of Object.entries(incoming)) {
228
+ if ((result[clientId] ?? 0) < count) result[clientId] = count;
229
+ }
230
+ return result;
231
+ };
package/src/index.ts CHANGED
@@ -10,6 +10,8 @@ export { ORSetHandle } from "./crdt/orset.js";
10
10
  export { LwwRegisterHandle } from "./crdt/lwwregister.js";
11
11
  export { PresenceHandle } from "./crdt/presence.js";
12
12
  export type { PresenceEntry } from "./crdt/presence.js";
13
+ export { CRDTMapHandle } from "./crdt/crdtmap.js";
14
+ export type { CrdtMapValue } from "./crdt/crdtmap.js";
13
15
 
14
16
  // Transport
15
17
  export { HttpClient } from "./transport/http.js";
package/src/sync/delta.ts CHANGED
@@ -71,3 +71,19 @@ export const decodePresenceDelta = (bytes: Uint8Array): PresenceDelta => {
71
71
  const raw = decode(bytes) as { changes?: Record<string, PresenceEntryDelta | null> };
72
72
  return { changes: raw.changes ?? {} };
73
73
  };
74
+
75
+ export type CrdtValueDelta =
76
+ | { GCounter: GCounterDelta }
77
+ | { PNCounter: PNCounterDelta }
78
+ | { ORSet: ORSetDelta }
79
+ | { LwwRegister: LwwDelta }
80
+ | { Presence: PresenceDelta };
81
+
82
+ export interface CRDTMapDelta {
83
+ deltas: Record<string, CrdtValueDelta>;
84
+ }
85
+
86
+ export const decodeCRDTMapDelta = (bytes: Uint8Array): CRDTMapDelta => {
87
+ const raw = decode(bytes) as { deltas?: Record<string, unknown> };
88
+ return { deltas: (raw.deltas ?? {}) as Record<string, CrdtValueDelta> };
89
+ };