meridian-sdk 1.5.0 → 1.7.0

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.
Files changed (109) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +52 -0
  3. package/dist/auth/permissions.d.ts +1 -0
  4. package/dist/auth/permissions.d.ts.map +1 -1
  5. package/dist/auth/permissions.js +1 -1
  6. package/dist/auth/permissions.js.map +1 -1
  7. package/dist/auth/token.d.ts.map +1 -1
  8. package/dist/auth/token.js +9 -18
  9. package/dist/auth/token.js.map +1 -1
  10. package/dist/client.d.ts +54 -0
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +147 -42
  13. package/dist/client.js.map +1 -1
  14. package/dist/codec.d.ts +3 -3
  15. package/dist/codec.d.ts.map +1 -1
  16. package/dist/codec.js +1 -1
  17. package/dist/codec.js.map +1 -1
  18. package/dist/crdt/awareness.d.ts.map +1 -1
  19. package/dist/crdt/awareness.js +4 -2
  20. package/dist/crdt/awareness.js.map +1 -1
  21. package/dist/crdt/lwwregister.d.ts +4 -0
  22. package/dist/crdt/lwwregister.d.ts.map +1 -1
  23. package/dist/crdt/lwwregister.js +10 -4
  24. package/dist/crdt/lwwregister.js.map +1 -1
  25. package/dist/crdt/orset.d.ts.map +1 -1
  26. package/dist/crdt/orset.js +6 -3
  27. package/dist/crdt/orset.js.map +1 -1
  28. package/dist/crdt/pncounter.d.ts +1 -0
  29. package/dist/crdt/pncounter.d.ts.map +1 -1
  30. package/dist/crdt/pncounter.js +2 -0
  31. package/dist/crdt/pncounter.js.map +1 -1
  32. package/dist/crdt/presence.d.ts +4 -0
  33. package/dist/crdt/presence.d.ts.map +1 -1
  34. package/dist/crdt/presence.js +17 -15
  35. package/dist/crdt/presence.js.map +1 -1
  36. package/dist/crdt/rga.d.ts +21 -11
  37. package/dist/crdt/rga.d.ts.map +1 -1
  38. package/dist/crdt/rga.js +151 -36
  39. package/dist/crdt/rga.js.map +1 -1
  40. package/dist/crdt/tree.d.ts +28 -10
  41. package/dist/crdt/tree.d.ts.map +1 -1
  42. package/dist/crdt/tree.js +233 -73
  43. package/dist/crdt/tree.js.map +1 -1
  44. package/dist/crypto/aes-gcm.d.ts +24 -0
  45. package/dist/crypto/aes-gcm.d.ts.map +1 -0
  46. package/dist/crypto/aes-gcm.js +49 -0
  47. package/dist/crypto/aes-gcm.js.map +1 -0
  48. package/dist/crypto/ed25519.d.ts +30 -0
  49. package/dist/crypto/ed25519.d.ts.map +1 -0
  50. package/dist/crypto/ed25519.js +68 -0
  51. package/dist/crypto/ed25519.js.map +1 -0
  52. package/dist/crypto/index.d.ts +5 -0
  53. package/dist/crypto/index.d.ts.map +1 -0
  54. package/dist/crypto/index.js +3 -0
  55. package/dist/crypto/index.js.map +1 -0
  56. package/dist/index.d.ts +6 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +5 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/persistence/snapshot.js +2 -2
  61. package/dist/persistence/snapshot.js.map +1 -1
  62. package/dist/rpc.js +2 -2
  63. package/dist/rpc.js.map +1 -1
  64. package/dist/schema.d.ts +10 -0
  65. package/dist/schema.d.ts.map +1 -1
  66. package/dist/schema.js +5 -1
  67. package/dist/schema.js.map +1 -1
  68. package/dist/sync/delta.d.ts +56 -2
  69. package/dist/sync/delta.d.ts.map +1 -1
  70. package/dist/sync/delta.js +2 -2
  71. package/dist/sync/delta.js.map +1 -1
  72. package/dist/sync/tab-sync.d.ts +22 -0
  73. package/dist/sync/tab-sync.d.ts.map +1 -0
  74. package/dist/sync/tab-sync.js +32 -0
  75. package/dist/sync/tab-sync.js.map +1 -0
  76. package/dist/transport/http.d.ts +19 -12
  77. package/dist/transport/http.d.ts.map +1 -1
  78. package/dist/transport/http.js +13 -4
  79. package/dist/transport/http.js.map +1 -1
  80. package/dist/transport/websocket.d.ts +8 -0
  81. package/dist/transport/websocket.d.ts.map +1 -1
  82. package/dist/transport/websocket.js +32 -5
  83. package/dist/transport/websocket.js.map +1 -1
  84. package/package.json +4 -4
  85. package/src/auth/permissions.ts +1 -1
  86. package/src/auth/token.ts +9 -16
  87. package/src/client.ts +180 -41
  88. package/src/codec.ts +4 -3
  89. package/src/crdt/awareness.ts +3 -2
  90. package/src/crdt/lwwregister.ts +18 -5
  91. package/src/crdt/orset.ts +7 -4
  92. package/src/crdt/pncounter.ts +2 -0
  93. package/src/crdt/presence.ts +23 -16
  94. package/src/crdt/rga.ts +157 -31
  95. package/src/crdt/tree.ts +245 -84
  96. package/src/crypto/aes-gcm.ts +65 -0
  97. package/src/crypto/ed25519.ts +89 -0
  98. package/src/crypto/index.ts +15 -0
  99. package/src/index.ts +20 -0
  100. package/src/persistence/snapshot.ts +2 -2
  101. package/src/rpc.ts +1 -1
  102. package/src/schema.ts +5 -0
  103. package/src/sync/delta.ts +36 -6
  104. package/src/sync/tab-sync.ts +40 -0
  105. package/src/transport/http.ts +22 -16
  106. package/src/transport/websocket.ts +45 -11
  107. package/test/crypto.test.ts +150 -0
  108. package/test/integration.test.ts +409 -29
  109. package/test/tab-sync.test.ts +164 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # meridian-sdk
2
2
 
3
+ ## 1.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 664b1e4: Add E2E encryption, BFT signing, and cross-SDK feature parity.
8
+
9
+ - AES-GCM-256 envelope encryption and Ed25519 BFT signing in the TypeScript SDK
10
+ - New `packages/python/` — `meridian-crdt` Python package with full CRDT support (GCounter, PNCounter, LwwRegister, Presence), optional AES-GCM-256 encryption and Ed25519 signing, asyncio-native transport with auto-reconnect
11
+ - Rust client SDK (`meridian-client`): AES-GCM-256 encryption and Ed25519 BFT signing on LwwRegister and Presence handles (`--features crypto`), HTTP client for REST endpoints (`--features http`), auth token parsing and permission checks
12
+ - CRDT compactor background task for RGA and Tree tombstone cleanup
13
+
14
+ ## 1.6.0
15
+
16
+ ### Minor Changes
17
+
18
+ - 0360ecc: Upgrade to TypeScript 6, Effect 3.21.4, and Biome 2.5.1. Fix Effect usage across all packages: `getHistory` now returns `Effect` instead of `Promise`, `parseToken` uses proper `yield* Effect.fail` and `Effect.try` patterns, WebSocket message decoding uses `runFork` instead of orphaned `runPromise`. Full type-safety pass for TypeScript 6 strictness (`Uint8Array<ArrayBuffer>`, `exactOptionalPropertyTypes`, DOM lib explicit).
19
+
3
20
  ## 1.5.0
4
21
 
5
22
  ### Minor Changes
package/README.md CHANGED
@@ -83,6 +83,9 @@ await Effect.runPromise(
83
83
  | `namespace` | `string` | Namespace to connect to |
84
84
  | `token` | `string` | Meridian token |
85
85
  | `autoConnect` | `boolean?` | Open WebSocket immediately (default: `true`) |
86
+ | `offline` | `boolean?` | Start without connecting — operate from cache, call `client.connect()` later |
87
+ | `persistence` | `PersistenceConfig?` | Persist CRDT snapshots and the pending op queue across page loads |
88
+ | `tabSync` | `boolean?` | Broadcast deltas to other tabs in the same namespace via `BroadcastChannel` |
86
89
 
87
90
  ### CRDT handles
88
91
 
@@ -203,6 +206,55 @@ unsubDelta();
203
206
 
204
207
  The queue holds up to 500 ops. If the limit is reached, the oldest op is dropped to make room for the newest.
205
208
 
209
+ ### Persistence (offline-first)
210
+
211
+ Enable persistence to cache CRDT state across page loads and survive disconnections:
212
+
213
+ ```ts
214
+ import {
215
+ MeridianClient,
216
+ indexedDbStateStorage,
217
+ localStorageSyncOpsAdapter,
218
+ } from "meridian-sdk";
219
+
220
+ const client = await Effect.runPromise(
221
+ MeridianClient.create({
222
+ url: "http://localhost:3000",
223
+ namespace: "my-room",
224
+ token,
225
+ persistence: {
226
+ state: indexedDbStateStorage(), // CRDT snapshots → IndexedDB
227
+ ops: localStorageSyncOpsAdapter(), // pending op queue → localStorage (sync, survives tab close)
228
+ },
229
+ })
230
+ );
231
+
232
+ const views = client.gcounter("gc:views");
233
+ const cart = client.orset("or:cart");
234
+ await client.waitForRestore(); // wait for IndexedDB reads to complete
235
+
236
+ console.log(views.value()); // populated from cache before the WebSocket connects
237
+ ```
238
+
239
+ The pending op queue is also flushed when the tab becomes hidden (`visibilitychange`), covering most crash and background-kill scenarios.
240
+
241
+ ### Multi-tab sync
242
+
243
+ Pass `tabSync: true` to broadcast CRDT deltas to other open tabs in the same origin and namespace via the [BroadcastChannel API](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel):
244
+
245
+ ```ts
246
+ const client = await Effect.runPromise(
247
+ MeridianClient.create({
248
+ url: "http://localhost:3000",
249
+ namespace: "my-room",
250
+ token,
251
+ tabSync: true,
252
+ })
253
+ );
254
+ ```
255
+
256
+ When Tab A receives a delta from the server it immediately forwards it to Tab B — Tab B applies it without waiting for its own server round-trip. All CRDTs are convergent so applying the same delta twice is safe.
257
+
206
258
  ### Op latency
207
259
 
208
260
  `client.getLatencyStats()` returns P50 and P99 round-trip latency in milliseconds, computed from the last 128 acknowledged ops. Returns `null` if fewer than 2 samples have been collected.
@@ -25,6 +25,7 @@ export declare const OpMasks: {
25
25
  readonly MAP_WRITE: 1;
26
26
  };
27
27
  export type OpMask = number;
28
+ export declare function globMatch(pattern: string, value: string): boolean;
28
29
  /**
29
30
  * Check whether the token's permissions allow reading `crdtId`.
30
31
  *
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/auth/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,cAAc,CAAC;AAE3D,eAAO,MAAM,OAAO;IAClB,yDAAyD;;;;;;;;;;;;;;;;CA8BjD,CAAC;AAEX,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AA4C5B;;;;;;;GAOG;AACH,wBAAgB,OAAO,CACrB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,SAAa,GACjB,OAAO,CAOT;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAoB,EAC5B,KAAK,SAAa,GACjB,OAAO,CAOT"}
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/auth/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,cAAc,CAAC;AAE3D,eAAO,MAAM,OAAO;IAClB,yDAAyD;;;;;;;;;;;;;;;;CA8BjD,CAAC;AAEX,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAE5B,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAcjE;AA4BD;;;;;;;GAOG;AACH,wBAAgB,OAAO,CACrB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,SAAa,GACjB,OAAO,CAOT;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAoB,EAC5B,KAAK,SAAa,GACjB,OAAO,CAOT"}
@@ -30,7 +30,7 @@ export const OpMasks = {
30
30
  // CRDTMap
31
31
  MAP_WRITE: 0b0000_0001,
32
32
  };
33
- function globMatch(pattern, value) {
33
+ export function globMatch(pattern, value) {
34
34
  if (pattern === "*")
35
35
  return true;
36
36
  const starPos = pattern.indexOf("*");
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/auth/permissions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/auth/permissions.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/auth/token.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,eAAe,CA+BjF,CAAC;AAEL,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,WAAW,EACnB,cAAkB,KACjB,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,iBAAiB,CAK9C,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,OAAO,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,eAAe,GAAG,iBAAiB,CACP,CAAC;AAE3D,eAAO,MAAM,UAAU,GAAI,QAAQ,WAAW,EAAE,cAAkB,KAAG,MAC1C,CAAC"}
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/auth/token.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,eAAe,CAwBjF,CAAC;AAEL,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,WAAW,EACnB,cAAkB,KACjB,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,iBAAiB,CAK9C,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,OAAO,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,eAAe,GAAG,iBAAiB,CACP,CAAC;AAE3D,eAAO,MAAM,UAAU,GAAI,QAAQ,WAAW,EAAE,cAAkB,KAAG,MAC1C,CAAC"}
@@ -6,26 +6,17 @@ import { TOKEN_SKEW_MS } from "../constants.js";
6
6
  export const parseToken = (token) => Effect.gen(function* () {
7
7
  const dotIndex = token.indexOf(".");
8
8
  if (dotIndex === -1) {
9
- yield* Effect.fail(new TokenParseError({ message: "Invalid token format: missing '.'" }));
10
- return undefined;
9
+ return yield* Effect.fail(new TokenParseError({ message: "Invalid token format: missing '.'" }));
11
10
  }
12
11
  const payloadB64 = token.slice(0, dotIndex);
13
- let bytes;
14
- try {
15
- bytes = base64urlDecode(payloadB64);
16
- }
17
- catch {
18
- yield* Effect.fail(new TokenParseError({ message: "Invalid token format: base64url decode failed" }));
19
- return undefined;
20
- }
21
- let raw;
22
- try {
23
- raw = decode(bytes);
24
- }
25
- catch {
26
- yield* Effect.fail(new TokenParseError({ message: "Invalid token format: msgpack decode failed" }));
27
- return undefined;
28
- }
12
+ const bytes = yield* Effect.try({
13
+ try: () => base64urlDecode(payloadB64),
14
+ catch: () => new TokenParseError({ message: "Invalid token format: base64url decode failed" }),
15
+ });
16
+ const raw = yield* Effect.try({
17
+ try: () => decode(bytes),
18
+ catch: () => new TokenParseError({ message: "Invalid token format: msgpack decode failed" }),
19
+ });
29
20
  return yield* Schema.decodeUnknown(TokenClaims)(raw).pipe(Effect.mapError((e) => new TokenParseError({ message: `Invalid token format: ${e.message}` })));
30
21
  });
31
22
  export const checkTokenExpiry = (claims, nowMs = Date.now()) => {
@@ -1 +1 @@
1
- {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/auth/token.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/auth/token.ts"],"names":[],"mappings":"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"}
package/dist/client.d.ts CHANGED
@@ -105,6 +105,43 @@ export interface MeridianClientConfig {
105
105
  offline?: boolean;
106
106
  /** Persistence configuration for offline-first support. */
107
107
  persistence?: PersistenceConfig;
108
+ /**
109
+ * If `true`, broadcast CRDT deltas to other tabs in the same origin and namespace
110
+ * via `BroadcastChannel`. Other tabs with the same namespace apply updates instantly
111
+ * without a server round-trip. Safe to enable — re-applying a delta is idempotent.
112
+ */
113
+ tabSync?: boolean;
114
+ /**
115
+ * Client-side AES-256-GCM encryption keys, keyed by CRDT ID pattern (glob supported).
116
+ * Matching CRDTs encrypt their value fields before sending — the server stores and
117
+ * forwards ciphertext and never sees plaintext.
118
+ *
119
+ * Supported CRDT types: `LwwRegister`, `Presence`.
120
+ * Not supported: `GCounter`, `PNCounter`, `RGA` (numeric/structural merge requires plaintext).
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * import { importAesGcmKey } from "meridian-sdk";
125
+ * const key = await importAesGcmKey(base64Key);
126
+ * MeridianClient.create({ ..., encryption: { "lw:profile": key, "pr:room-*": key2 } });
127
+ * ```
128
+ */
129
+ encryption?: Record<string, CryptoKey>;
130
+ /**
131
+ * If `true`, generate (or load from `localStorage`) a per-client Ed25519 keypair and
132
+ * sign every outgoing op before sending.
133
+ *
134
+ * The server verifies the signature against `client_pubkey` embedded in the token.
135
+ * This provides Byzantine fault tolerance in cluster mode: a compromised node cannot
136
+ * forge ops that appear to originate from legitimate clients.
137
+ *
138
+ * **Setup**: when issuing the token (via your app server), include `client_pubkey`
139
+ * (base64url-encoded 32-byte public key) in the token issuance request. Obtain the
140
+ * public key from `client.publicKeyBytes` after `create()` completes.
141
+ *
142
+ * Requires Chrome 113+, Firefox 130+, or Node.js 20+.
143
+ */
144
+ signing?: boolean;
108
145
  }
109
146
  /**
110
147
  * The main entry point for the Meridian real-time CRDT SDK.
@@ -138,6 +175,12 @@ export declare class MeridianClient {
138
175
  readonly claims: TokenClaims;
139
176
  private readonly transport;
140
177
  readonly http: HttpClient;
178
+ /**
179
+ * Raw 32-byte Ed25519 public key for this client, or `null` if `signing` is disabled.
180
+ * Pass this (base64url-encoded) to your app server when issuing tokens so the server
181
+ * can verify op signatures.
182
+ */
183
+ readonly publicKeyBytes: Uint8Array | null;
141
184
  private readonly gcHandles;
142
185
  private readonly pnHandles;
143
186
  private readonly orHandles;
@@ -156,6 +199,8 @@ export declare class MeridianClient {
156
199
  private readonly snapStore;
157
200
  private readonly opsStore;
158
201
  private readonly restorePromises;
202
+ private readonly tabSyncChannel;
203
+ private readonly encKeys;
159
204
  private constructor();
160
205
  /** Explicitly connect to the server. Use when `autoConnect: false` or `offline: true`. */
161
206
  connect(): void;
@@ -178,6 +223,7 @@ export declare class MeridianClient {
178
223
  private scheduleSnapRestore;
179
224
  private saveSnap;
180
225
  private readonly flushOpsToStorage;
226
+ private readonly onVisibilityChange;
181
227
  /**
182
228
  * Creates and validates a new `MeridianClient` from the supplied configuration.
183
229
  *
@@ -200,6 +246,8 @@ export declare class MeridianClient {
200
246
  * ```
201
247
  */
202
248
  static create(config: MeridianClientConfig): Effect.Effect<MeridianClient, TokenParseError | TokenExpiredError>;
249
+ private resolveEncKey;
250
+ private encryptFnFor;
203
251
  /**
204
252
  * Returns a handle for a grow-only counter (GCounter) CRDT.
205
253
  *
@@ -480,6 +528,12 @@ export declare class MeridianClient {
480
528
  private resubscribeLiveQueries;
481
529
  private notifyAnyChange;
482
530
  private handleServerMsg;
531
+ /**
532
+ * Apply a CRDT delta to the appropriate local handle.
533
+ * Called from the server message handler and from tab-sync broadcasts.
534
+ * When `broadcast` is true, the delta is forwarded to other tabs via BroadcastChannel.
535
+ */
536
+ private applyDelta;
483
537
  private notifyDelta;
484
538
  }
485
539
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Effect } from "effect";
2
2
  import { WsTransport } from "./transport/websocket.js";
3
+ import { TabSync } from "./sync/tab-sync.js";
3
4
  import { snapshotFromHandle, snapshotToBytes, bytesToSnapshot, restoreSnapshotToHandle, } from "./persistence/snapshot.js";
4
5
  import { encode, decode } from "./codec.js";
5
6
  import { HttpClient } from "./transport/http.js";
@@ -14,7 +15,9 @@ import { RGAHandle } from "./crdt/rga.js";
14
15
  import { TreeHandle } from "./crdt/tree.js";
15
16
  import { decodeGCounterDelta, decodePNCounterDelta, decodeORSetDelta, decodeLwwDelta, decodePresenceDelta, decodeCRDTMapDelta, decodeRGADelta, decodeTreeDelta, } from "./sync/delta.js";
16
17
  import { parseAndValidateToken } from "./auth/token.js";
17
- import { canRead as evalCanRead, canWrite as evalCanWrite } from "./auth/permissions.js";
18
+ import { canRead as evalCanRead, canWrite as evalCanWrite, globMatch } from "./auth/permissions.js";
19
+ import { encryptJson, decryptJson, isEncryptedValue } from "./crypto/aes-gcm.js";
20
+ import { signOp, loadOrGenerateKeypair } from "./crypto/ed25519.js";
18
21
  /**
19
22
  * The main entry point for the Meridian real-time CRDT SDK.
20
23
  *
@@ -47,6 +50,12 @@ export class MeridianClient {
47
50
  claims;
48
51
  transport;
49
52
  http;
53
+ /**
54
+ * Raw 32-byte Ed25519 public key for this client, or `null` if `signing` is disabled.
55
+ * Pass this (base64url-encoded) to your app server when issuing tokens so the server
56
+ * can verify op signatures.
57
+ */
58
+ publicKeyBytes;
50
59
  // HACK: Generic params are erased at storage level; factories restore them via typed get+cast on retrieval.
51
60
  gcHandles = new Map();
52
61
  pnHandles = new Map();
@@ -68,10 +77,14 @@ export class MeridianClient {
68
77
  snapStore;
69
78
  opsStore;
70
79
  restorePromises = new Set();
71
- constructor(config, claims) {
80
+ tabSyncChannel;
81
+ encKeys;
82
+ constructor(config, claims, keypair) {
72
83
  this.namespace = config.namespace;
73
84
  this.claims = claims;
74
85
  this.clientId = claims.client_id;
86
+ this.publicKeyBytes = keypair?.publicKeyBytes ?? null;
87
+ this.encKeys = new Map(Object.entries(config.encryption ?? {}));
75
88
  this.snapStore = config.persistence?.state ?? null;
76
89
  this.opsStore = config.persistence?.ops ?? null;
77
90
  const httpBase = config.url
@@ -83,7 +96,16 @@ export class MeridianClient {
83
96
  url: wsUrl,
84
97
  token: config.token,
85
98
  onMessage: (msg) => { this.handleServerMsg(msg); },
99
+ ...(keypair !== null && { signFn: (opBytes) => signOp(keypair.privateKey, opBytes) }),
86
100
  });
101
+ this.tabSyncChannel = (config.tabSync === true && typeof BroadcastChannel !== "undefined")
102
+ ? new TabSync(config.namespace)
103
+ : null;
104
+ if (this.tabSyncChannel !== null) {
105
+ this.tabSyncChannel.onDelta(({ crdtId, deltaBytes }) => {
106
+ void this.applyDelta(crdtId, deltaBytes, false);
107
+ });
108
+ }
87
109
  // Restore persisted op queue before connecting.
88
110
  if (this.opsStore !== null) {
89
111
  const bytes = this.opsStore.load(`ops:${this.namespace}`);
@@ -98,6 +120,10 @@ export class MeridianClient {
98
120
  this.opsStore.delete(`ops:${this.namespace}`);
99
121
  }
100
122
  globalThis.addEventListener("beforeunload", this.flushOpsToStorage);
123
+ // Flush when tab is hidden (covers most crash/kill scenarios without IDB complexity).
124
+ if (typeof document !== "undefined") {
125
+ document.addEventListener("visibilitychange", this.onVisibilityChange);
126
+ }
101
127
  }
102
128
  if (config.autoConnect !== false && config.offline !== true) {
103
129
  this.transport.connect();
@@ -161,6 +187,11 @@ export class MeridianClient {
161
187
  }
162
188
  this.opsStore.save(key, encode(msgs));
163
189
  };
190
+ onVisibilityChange = () => {
191
+ if (typeof document !== "undefined" && document.visibilityState === "hidden") {
192
+ this.flushOpsToStorage();
193
+ }
194
+ };
164
195
  /**
165
196
  * Creates and validates a new `MeridianClient` from the supplied configuration.
166
197
  *
@@ -183,7 +214,26 @@ export class MeridianClient {
183
214
  * ```
184
215
  */
185
216
  static create(config) {
186
- return parseAndValidateToken(config.token).pipe(Effect.map((claims) => new MeridianClient(config, claims)));
217
+ return Effect.gen(function* () {
218
+ const claims = yield* parseAndValidateToken(config.token);
219
+ const keypair = config.signing === true
220
+ ? yield* Effect.promise(() => loadOrGenerateKeypair())
221
+ : null;
222
+ return new MeridianClient(config, claims, keypair);
223
+ });
224
+ }
225
+ resolveEncKey(crdtId) {
226
+ if (this.encKeys.size === 0)
227
+ return null;
228
+ for (const [pattern, key] of this.encKeys) {
229
+ if (globMatch(pattern, crdtId))
230
+ return key;
231
+ }
232
+ return null;
233
+ }
234
+ encryptFnFor(crdtId) {
235
+ const key = this.resolveEncKey(crdtId);
236
+ return key !== null ? (v) => encryptJson(key, v) : undefined;
187
237
  }
188
238
  /**
189
239
  * Returns a handle for a grow-only counter (GCounter) CRDT.
@@ -289,7 +339,8 @@ export class MeridianClient {
289
339
  lwwregister(crdtId, schema) {
290
340
  let handle = this.lwHandles.get(crdtId);
291
341
  if (!handle) {
292
- const base = { ns: this.namespace, crdtId, clientId: this.clientId, transport: this.transport };
342
+ const encryptFn = this.encryptFnFor(crdtId);
343
+ const base = { ns: this.namespace, crdtId, clientId: this.clientId, transport: this.transport, ...(encryptFn !== undefined && { encryptFn }) };
293
344
  handle = schema ? new LwwRegisterHandle({ ...base, schema }) : new LwwRegisterHandle(base);
294
345
  this.lwHandles.set(crdtId, handle);
295
346
  this.transport.subscribe(crdtId);
@@ -320,7 +371,8 @@ export class MeridianClient {
320
371
  presence(crdtId, schema) {
321
372
  let handle = this.prHandles.get(crdtId);
322
373
  if (!handle) {
323
- const base = { ns: this.namespace, crdtId, clientId: this.clientId, transport: this.transport };
374
+ const encryptFn = this.encryptFnFor(crdtId);
375
+ const base = { ns: this.namespace, crdtId, clientId: this.clientId, transport: this.transport, ...(encryptFn !== undefined && { encryptFn }) };
324
376
  handle = schema ? new PresenceHandle({ ...base, schema }) : new PresenceHandle(base);
325
377
  this.prHandles.set(crdtId, handle);
326
378
  this.transport.subscribe(crdtId);
@@ -570,7 +622,11 @@ export class MeridianClient {
570
622
  this.flushOpsToStorage();
571
623
  if (this.opsStore !== null) {
572
624
  globalThis.removeEventListener("beforeunload", this.flushOpsToStorage);
625
+ if (typeof document !== "undefined") {
626
+ document.removeEventListener("visibilitychange", this.onVisibilityChange);
627
+ }
573
628
  }
629
+ this.tabSyncChannel?.close();
574
630
  for (const unsub of this.handleUnsubs)
575
631
  unsub();
576
632
  this.handleUnsubs.length = 0;
@@ -678,87 +734,136 @@ export class MeridianClient {
678
734
  }
679
735
  return;
680
736
  }
681
- if (!("Delta" in msg))
682
- return;
683
- const { crdt_id, delta_bytes } = msg.Delta;
684
- const gcHandle = this.gcHandles.get(crdt_id);
737
+ if ("Delta" in msg) {
738
+ const { crdt_id, delta_bytes } = msg.Delta;
739
+ void this.applyDelta(crdt_id, delta_bytes, true);
740
+ }
741
+ }
742
+ /**
743
+ * Apply a CRDT delta to the appropriate local handle.
744
+ * Called from the server message handler and from tab-sync broadcasts.
745
+ * When `broadcast` is true, the delta is forwarded to other tabs via BroadcastChannel.
746
+ */
747
+ async applyDelta(crdtId, deltaBytes, broadcast) {
748
+ const gcHandle = this.gcHandles.get(crdtId);
685
749
  if (gcHandle) {
686
750
  try {
687
- gcHandle.applyDelta(decodeGCounterDelta(delta_bytes));
751
+ gcHandle.applyDelta(decodeGCounterDelta(deltaBytes));
688
752
  }
689
753
  catch { /* stale */ }
690
- this.saveSnap(`snap:gc:${this.namespace}:${this.clientId}:${crdt_id}`, gcHandle);
691
- this.notifyDelta(crdt_id, "gcounter");
754
+ this.saveSnap(`snap:gc:${this.namespace}:${this.clientId}:${crdtId}`, gcHandle);
755
+ this.notifyDelta(crdtId, "gcounter");
756
+ if (broadcast)
757
+ this.tabSyncChannel?.broadcast(crdtId, deltaBytes);
692
758
  return;
693
759
  }
694
- const pnHandle = this.pnHandles.get(crdt_id);
760
+ const pnHandle = this.pnHandles.get(crdtId);
695
761
  if (pnHandle) {
696
762
  try {
697
- pnHandle.applyDelta(decodePNCounterDelta(delta_bytes));
763
+ pnHandle.applyDelta(decodePNCounterDelta(deltaBytes));
698
764
  }
699
765
  catch { /* stale */ }
700
- this.saveSnap(`snap:pn:${this.namespace}:${this.clientId}:${crdt_id}`, pnHandle);
701
- this.notifyDelta(crdt_id, "pncounter");
766
+ this.saveSnap(`snap:pn:${this.namespace}:${this.clientId}:${crdtId}`, pnHandle);
767
+ this.notifyDelta(crdtId, "pncounter");
768
+ if (broadcast)
769
+ this.tabSyncChannel?.broadcast(crdtId, deltaBytes);
702
770
  return;
703
771
  }
704
- const orHandle = this.orHandles.get(crdt_id);
772
+ const orHandle = this.orHandles.get(crdtId);
705
773
  if (orHandle) {
706
774
  try {
707
- orHandle.applyDelta(decodeORSetDelta(delta_bytes));
775
+ orHandle.applyDelta(decodeORSetDelta(deltaBytes));
708
776
  }
709
777
  catch { /* stale */ }
710
- this.saveSnap(`snap:or:${this.namespace}:${this.clientId}:${crdt_id}`, orHandle);
711
- this.notifyDelta(crdt_id, "orset");
778
+ this.saveSnap(`snap:or:${this.namespace}:${this.clientId}:${crdtId}`, orHandle);
779
+ this.notifyDelta(crdtId, "orset");
780
+ if (broadcast)
781
+ this.tabSyncChannel?.broadcast(crdtId, deltaBytes);
712
782
  return;
713
783
  }
714
- const lwHandle = this.lwHandles.get(crdt_id);
784
+ const lwHandle = this.lwHandles.get(crdtId);
715
785
  if (lwHandle) {
716
786
  try {
717
- lwHandle.applyDelta(decodeLwwDelta(delta_bytes));
787
+ let delta = decodeLwwDelta(deltaBytes);
788
+ if (delta.entry !== null && isEncryptedValue(delta.entry.value)) {
789
+ const key = this.resolveEncKey(crdtId);
790
+ if (key !== null) {
791
+ const plain = await decryptJson(key, delta.entry.value);
792
+ delta = { entry: { ...delta.entry, value: plain } };
793
+ }
794
+ }
795
+ lwHandle.applyDelta(delta);
718
796
  }
719
- catch { /* stale */ }
720
- this.saveSnap(`snap:lw:${this.namespace}:${this.clientId}:${crdt_id}`, lwHandle);
721
- this.notifyDelta(crdt_id, "lwwregister");
797
+ catch { /* stale or decrypt failure */ }
798
+ this.saveSnap(`snap:lw:${this.namespace}:${this.clientId}:${crdtId}`, lwHandle);
799
+ this.notifyDelta(crdtId, "lwwregister");
800
+ if (broadcast)
801
+ this.tabSyncChannel?.broadcast(crdtId, deltaBytes);
722
802
  return;
723
803
  }
724
- const prHandle = this.prHandles.get(crdt_id);
804
+ const prHandle = this.prHandles.get(crdtId);
725
805
  if (prHandle) {
726
806
  try {
727
- prHandle.applyDelta(decodePresenceDelta(delta_bytes));
807
+ const delta = decodePresenceDelta(deltaBytes);
808
+ const key = this.resolveEncKey(crdtId);
809
+ if (key !== null) {
810
+ const decrypted = {};
811
+ for (const [clientIdStr, entry] of Object.entries(delta.changes)) {
812
+ if (entry !== null && isEncryptedValue(entry.data)) {
813
+ const plain = await decryptJson(key, entry.data);
814
+ decrypted[clientIdStr] = { ...entry, data: plain };
815
+ }
816
+ else {
817
+ decrypted[clientIdStr] = entry;
818
+ }
819
+ }
820
+ prHandle.applyDelta({ changes: decrypted });
821
+ }
822
+ else {
823
+ prHandle.applyDelta(delta);
824
+ }
728
825
  }
729
- catch { /* stale */ }
730
- this.saveSnap(`snap:pr:${this.namespace}:${this.clientId}:${crdt_id}`, prHandle);
731
- this.notifyDelta(crdt_id, "presence");
826
+ catch { /* stale or decrypt failure */ }
827
+ this.saveSnap(`snap:pr:${this.namespace}:${this.clientId}:${crdtId}`, prHandle);
828
+ this.notifyDelta(crdtId, "presence");
829
+ if (broadcast)
830
+ this.tabSyncChannel?.broadcast(crdtId, deltaBytes);
732
831
  return;
733
832
  }
734
- const cmHandle = this.cmHandles.get(crdt_id);
833
+ const cmHandle = this.cmHandles.get(crdtId);
735
834
  if (cmHandle) {
736
835
  try {
737
- cmHandle.applyDelta(decodeCRDTMapDelta(delta_bytes));
836
+ cmHandle.applyDelta(decodeCRDTMapDelta(deltaBytes));
738
837
  }
739
838
  catch { /* stale */ }
740
- this.saveSnap(`snap:cm:${this.namespace}:${this.clientId}:${crdt_id}`, cmHandle);
741
- this.notifyDelta(crdt_id, "crdtmap");
839
+ this.saveSnap(`snap:cm:${this.namespace}:${this.clientId}:${crdtId}`, cmHandle);
840
+ this.notifyDelta(crdtId, "crdtmap");
841
+ if (broadcast)
842
+ this.tabSyncChannel?.broadcast(crdtId, deltaBytes);
742
843
  return;
743
844
  }
744
- const rgaHandle = this.rgaHandles.get(crdt_id);
845
+ const rgaHandle = this.rgaHandles.get(crdtId);
745
846
  if (rgaHandle) {
746
847
  try {
747
- rgaHandle.applyDelta(decodeRGADelta(delta_bytes));
848
+ rgaHandle.applyDelta(decodeRGADelta(deltaBytes));
748
849
  }
749
850
  catch { /* stale */ }
750
- this.saveSnap(`snap:rg:${this.namespace}:${this.clientId}:${crdt_id}`, rgaHandle);
751
- this.notifyDelta(crdt_id, "rga");
851
+ this.saveSnap(`snap:rg:${this.namespace}:${this.clientId}:${crdtId}`, rgaHandle);
852
+ this.notifyDelta(crdtId, "rga");
853
+ if (broadcast)
854
+ this.tabSyncChannel?.broadcast(crdtId, deltaBytes);
752
855
  return;
753
856
  }
754
- const treeHandle = this.treeHandles.get(crdt_id);
857
+ const treeHandle = this.treeHandles.get(crdtId);
755
858
  if (treeHandle) {
756
859
  try {
757
- treeHandle.applyDelta(decodeTreeDelta(delta_bytes));
860
+ treeHandle.applyDelta(decodeTreeDelta(deltaBytes));
758
861
  }
759
862
  catch { /* stale */ }
760
- this.saveSnap(`snap:tr:${this.namespace}:${this.clientId}:${crdt_id}`, treeHandle);
761
- this.notifyDelta(crdt_id, "tree");
863
+ this.saveSnap(`snap:tr:${this.namespace}:${this.clientId}:${crdtId}`, treeHandle);
864
+ this.notifyDelta(crdtId, "tree");
865
+ if (broadcast)
866
+ this.tabSyncChannel?.broadcast(crdtId, deltaBytes);
762
867
  }
763
868
  }
764
869
  notifyDelta(crdtId, type) {