@polkadot-apps/statement-store 0.2.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.
@@ -0,0 +1,117 @@
1
+ import type { StatementStoreClient } from "./client.js";
2
+ import type { Unsubscribable } from "./types.js";
3
+ /**
4
+ * Higher-level abstraction providing last-write-wins channel semantics
5
+ * over the statement store.
6
+ *
7
+ * Each channel name maps to a single value. When a new value is written
8
+ * to a channel, it replaces the previous one if its timestamp is newer.
9
+ * This is ideal for presence announcements, signaling, and ephemeral state.
10
+ *
11
+ * @typeParam T - The type of values stored in channels.
12
+ * Values should include a `timestamp` field for ordering;
13
+ * if omitted, the current time is used automatically.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * interface Presence {
18
+ * type: "presence";
19
+ * peerId: string;
20
+ * timestamp: number;
21
+ * }
22
+ *
23
+ * const channels = new ChannelStore<Presence>(client, { topic2: "doc-123" });
24
+ *
25
+ * // Write presence
26
+ * await channels.write("presence/peer-abc", {
27
+ * type: "presence",
28
+ * peerId: "abc",
29
+ * timestamp: Date.now(),
30
+ * });
31
+ *
32
+ * // Read all presences
33
+ * for (const [name, value] of channels.readAll()) {
34
+ * console.log(`${name}: ${value.peerId}`);
35
+ * }
36
+ *
37
+ * // React to changes
38
+ * channels.onChange((name, value, previous) => {
39
+ * console.log(`Channel ${name} updated`);
40
+ * });
41
+ *
42
+ * channels.destroy();
43
+ * ```
44
+ */
45
+ export declare class ChannelStore<T extends {
46
+ timestamp?: number;
47
+ }> {
48
+ private readonly client;
49
+ private readonly topic2;
50
+ private readonly values;
51
+ /** Maps human-readable channel names to their hex hash keys, for consistent lookup. */
52
+ private readonly nameToHash;
53
+ private readonly changeCallbacks;
54
+ private subscription;
55
+ /**
56
+ * @param client - The connected {@link StatementStoreClient} to use.
57
+ * @param options - Optional secondary topic for scoping channels.
58
+ */
59
+ constructor(client: StatementStoreClient, options?: {
60
+ topic2?: string;
61
+ });
62
+ /**
63
+ * Write a value to a named channel.
64
+ *
65
+ * If the value doesn't include a `timestamp`, one is added automatically
66
+ * using `Date.now()`. The value is published to the statement store
67
+ * with the channel name as the statement channel.
68
+ *
69
+ * @param channelName - The channel name (e.g., "presence/peer-abc").
70
+ * @param value - The value to write.
71
+ * @returns `true` if the statement was accepted by the network.
72
+ */
73
+ write(channelName: string, value: T): Promise<boolean>;
74
+ /**
75
+ * Read the latest value for a channel by its human-readable name.
76
+ *
77
+ * Looks up the channel hash from the name, then retrieves the value.
78
+ * Also checks the hash directly for values received from the network
79
+ * before any local write established the name mapping.
80
+ *
81
+ * @param channelName - The channel name (e.g., "presence/peer-abc").
82
+ * @returns The latest value, or `undefined` if no value has been received.
83
+ */
84
+ read(channelName: string): T | undefined;
85
+ /**
86
+ * Read all channel values as a read-only map.
87
+ *
88
+ * Keys are hex-encoded channel hashes. Use {@link read} for
89
+ * lookup by human-readable name.
90
+ *
91
+ * @returns A map of channel hash to latest value.
92
+ */
93
+ readAll(): ReadonlyMap<string, T>;
94
+ /**
95
+ * Get the number of channels currently tracked.
96
+ */
97
+ get size(): number;
98
+ /**
99
+ * Subscribe to channel value changes.
100
+ *
101
+ * The callback is invoked whenever a channel value is updated
102
+ * (either from the network or from a local write).
103
+ *
104
+ * @param callback - Called with the channel key (hex hash for network-received, hex hash for local writes), new value, and previous value.
105
+ * @returns A handle to unsubscribe.
106
+ */
107
+ onChange(callback: (channelName: string, value: T, previous: T | undefined) => void): Unsubscribable;
108
+ /**
109
+ * Destroy the channel store and clean up subscriptions.
110
+ *
111
+ * Does not destroy the underlying client.
112
+ */
113
+ destroy(): void;
114
+ private handleStatement;
115
+ private updateChannel;
116
+ }
117
+ //# sourceMappingURL=channels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../src/channels.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,KAAK,EAAqC,cAAc,EAAE,MAAM,YAAY,CAAC;AAIpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,qBAAa,YAAY,CAAC,CAAC,SAAS;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,uFAAuF;IACvF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAEzB;IACP,OAAO,CAAC,YAAY,CAA+B;IAEnD;;;OAGG;gBACS,MAAM,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAWvE;;;;;;;;;;OAUG;IACG,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAoB5D;;;;;;;;;OASG;IACH,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAKxC;;;;;;;OAOG;IACH,OAAO,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;IAIjC;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;;;;OAQG;IACH,QAAQ,CACJ,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,GAC3E,cAAc;IAYjB;;;;OAIG;IACH,OAAO,IAAI,IAAI;IAef,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,aAAa;CA0BxB"}
@@ -0,0 +1,422 @@
1
+ import { createLogger } from "@polkadot-apps/logger";
2
+ import { createChannel, topicToHex } from "./topics.js";
3
+ const log = createLogger("statement-store:channels");
4
+ /**
5
+ * Higher-level abstraction providing last-write-wins channel semantics
6
+ * over the statement store.
7
+ *
8
+ * Each channel name maps to a single value. When a new value is written
9
+ * to a channel, it replaces the previous one if its timestamp is newer.
10
+ * This is ideal for presence announcements, signaling, and ephemeral state.
11
+ *
12
+ * @typeParam T - The type of values stored in channels.
13
+ * Values should include a `timestamp` field for ordering;
14
+ * if omitted, the current time is used automatically.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * interface Presence {
19
+ * type: "presence";
20
+ * peerId: string;
21
+ * timestamp: number;
22
+ * }
23
+ *
24
+ * const channels = new ChannelStore<Presence>(client, { topic2: "doc-123" });
25
+ *
26
+ * // Write presence
27
+ * await channels.write("presence/peer-abc", {
28
+ * type: "presence",
29
+ * peerId: "abc",
30
+ * timestamp: Date.now(),
31
+ * });
32
+ *
33
+ * // Read all presences
34
+ * for (const [name, value] of channels.readAll()) {
35
+ * console.log(`${name}: ${value.peerId}`);
36
+ * }
37
+ *
38
+ * // React to changes
39
+ * channels.onChange((name, value, previous) => {
40
+ * console.log(`Channel ${name} updated`);
41
+ * });
42
+ *
43
+ * channels.destroy();
44
+ * ```
45
+ */
46
+ export class ChannelStore {
47
+ client;
48
+ topic2;
49
+ values = new Map();
50
+ /** Maps human-readable channel names to their hex hash keys, for consistent lookup. */
51
+ nameToHash = new Map();
52
+ changeCallbacks = [];
53
+ subscription = null;
54
+ /**
55
+ * @param client - The connected {@link StatementStoreClient} to use.
56
+ * @param options - Optional secondary topic for scoping channels.
57
+ */
58
+ constructor(client, options) {
59
+ this.client = client;
60
+ this.topic2 = options?.topic2;
61
+ // Subscribe to incoming statements
62
+ this.subscription = this.client.subscribe((statement) => this.handleStatement(statement), { topic2: this.topic2 });
63
+ }
64
+ /**
65
+ * Write a value to a named channel.
66
+ *
67
+ * If the value doesn't include a `timestamp`, one is added automatically
68
+ * using `Date.now()`. The value is published to the statement store
69
+ * with the channel name as the statement channel.
70
+ *
71
+ * @param channelName - The channel name (e.g., "presence/peer-abc").
72
+ * @param value - The value to write.
73
+ * @returns `true` if the statement was accepted by the network.
74
+ */
75
+ async write(channelName, value) {
76
+ const timestamped = value.timestamp != null ? value : { ...value, timestamp: Date.now() };
77
+ const options = {
78
+ channel: channelName,
79
+ topic2: this.topic2,
80
+ };
81
+ const success = await this.client.publish(timestamped, options);
82
+ if (success) {
83
+ // Store by hash key so local writes and network echoes use the same key
84
+ const hashKey = topicToHex(createChannel(channelName));
85
+ this.nameToHash.set(channelName, hashKey);
86
+ this.updateChannel(hashKey, timestamped);
87
+ }
88
+ return success;
89
+ }
90
+ /**
91
+ * Read the latest value for a channel by its human-readable name.
92
+ *
93
+ * Looks up the channel hash from the name, then retrieves the value.
94
+ * Also checks the hash directly for values received from the network
95
+ * before any local write established the name mapping.
96
+ *
97
+ * @param channelName - The channel name (e.g., "presence/peer-abc").
98
+ * @returns The latest value, or `undefined` if no value has been received.
99
+ */
100
+ read(channelName) {
101
+ const hashKey = this.nameToHash.get(channelName) ?? topicToHex(createChannel(channelName));
102
+ return this.values.get(hashKey);
103
+ }
104
+ /**
105
+ * Read all channel values as a read-only map.
106
+ *
107
+ * Keys are hex-encoded channel hashes. Use {@link read} for
108
+ * lookup by human-readable name.
109
+ *
110
+ * @returns A map of channel hash to latest value.
111
+ */
112
+ readAll() {
113
+ return this.values;
114
+ }
115
+ /**
116
+ * Get the number of channels currently tracked.
117
+ */
118
+ get size() {
119
+ return this.values.size;
120
+ }
121
+ /**
122
+ * Subscribe to channel value changes.
123
+ *
124
+ * The callback is invoked whenever a channel value is updated
125
+ * (either from the network or from a local write).
126
+ *
127
+ * @param callback - Called with the channel key (hex hash for network-received, hex hash for local writes), new value, and previous value.
128
+ * @returns A handle to unsubscribe.
129
+ */
130
+ onChange(callback) {
131
+ this.changeCallbacks.push(callback);
132
+ return {
133
+ unsubscribe: () => {
134
+ const index = this.changeCallbacks.indexOf(callback);
135
+ if (index >= 0) {
136
+ this.changeCallbacks.splice(index, 1);
137
+ }
138
+ },
139
+ };
140
+ }
141
+ /**
142
+ * Destroy the channel store and clean up subscriptions.
143
+ *
144
+ * Does not destroy the underlying client.
145
+ */
146
+ destroy() {
147
+ if (this.subscription) {
148
+ this.subscription.unsubscribe();
149
+ this.subscription = null;
150
+ }
151
+ this.values.clear();
152
+ this.nameToHash.clear();
153
+ this.changeCallbacks.length = 0;
154
+ log.debug("ChannelStore destroyed");
155
+ }
156
+ // ========================================================================
157
+ // Internal
158
+ // ========================================================================
159
+ handleStatement(statement) {
160
+ // We need a channel to determine the channel name.
161
+ // Without a channel, we can't do last-write-wins deduplication.
162
+ if (!statement.channel)
163
+ return;
164
+ // The channel hash is the blake2b of the channel name.
165
+ // We store by the hex representation of the hash since we
166
+ // don't have the original channel name from incoming statements.
167
+ const channelKey = topicToHex(statement.channel);
168
+ this.updateChannel(channelKey, statement.data);
169
+ }
170
+ updateChannel(channelName, value) {
171
+ const existing = this.values.get(channelName);
172
+ // Last-write-wins: only update if newer
173
+ if (existing) {
174
+ const existingTs = existing.timestamp ?? 0;
175
+ const newTs = value.timestamp ?? 0;
176
+ if (newTs <= existingTs) {
177
+ return; // Same or older value, skip (idempotent)
178
+ }
179
+ }
180
+ const previous = existing;
181
+ this.values.set(channelName, value);
182
+ // Fire change callbacks (snapshot to handle mid-iteration unsubscribes)
183
+ for (const callback of [...this.changeCallbacks]) {
184
+ try {
185
+ callback(channelName, value, previous);
186
+ }
187
+ catch (error) {
188
+ log.error("onChange callback error", {
189
+ error: error instanceof Error ? error.message : String(error),
190
+ });
191
+ }
192
+ }
193
+ }
194
+ }
195
+ if (import.meta.vitest) {
196
+ const { describe, test, expect, vi, beforeEach } = import.meta.vitest;
197
+ const { configure } = await import("@polkadot-apps/logger");
198
+ beforeEach(() => {
199
+ configure({ handler: () => { } });
200
+ });
201
+ // Minimal mock of StatementStoreClient
202
+ function createMockClient() {
203
+ const subscribeCallbacks = [];
204
+ return {
205
+ subscribe: vi.fn((callback, _options) => {
206
+ subscribeCallbacks.push(callback);
207
+ return {
208
+ unsubscribe: () => {
209
+ const idx = subscribeCallbacks.indexOf(callback);
210
+ if (idx >= 0)
211
+ subscribeCallbacks.splice(idx, 1);
212
+ },
213
+ };
214
+ }),
215
+ publish: vi.fn(async () => true),
216
+ // Helper to simulate incoming statement
217
+ _simulateStatement(stmt) {
218
+ for (const cb of subscribeCallbacks) {
219
+ cb(stmt);
220
+ }
221
+ },
222
+ };
223
+ }
224
+ describe("ChannelStore", () => {
225
+ test("write publishes and updates local state", async () => {
226
+ const mockClient = createMockClient();
227
+ const store = new ChannelStore(mockClient);
228
+ await store.write("presence/abc", { type: "presence", timestamp: 1000 });
229
+ expect(mockClient.publish).toHaveBeenCalledOnce();
230
+ // read by name resolves through the hash
231
+ expect(store.read("presence/abc")).toEqual({ type: "presence", timestamp: 1000 });
232
+ });
233
+ test("write adds timestamp if missing", async () => {
234
+ const mockClient = createMockClient();
235
+ const store = new ChannelStore(mockClient);
236
+ const before = Date.now();
237
+ await store.write("ch", { type: "test" });
238
+ const calls = mockClient.publish.mock.calls;
239
+ const published = calls[0][0];
240
+ expect(published.timestamp).toBeGreaterThanOrEqual(before);
241
+ });
242
+ test("write returns false on publish failure", async () => {
243
+ const mockClient = createMockClient();
244
+ mockClient.publish = vi.fn(async () => false);
245
+ const store = new ChannelStore(mockClient);
246
+ const result = await store.write("ch", { type: "test", timestamp: 1 });
247
+ expect(result).toBe(false);
248
+ expect(store.read("ch")).toBeUndefined(); // Not stored on failure
249
+ });
250
+ test("read returns undefined for unknown channel", () => {
251
+ const mockClient = createMockClient();
252
+ const store = new ChannelStore(mockClient);
253
+ expect(store.read("unknown")).toBeUndefined();
254
+ });
255
+ test("readAll returns all values keyed by hash", async () => {
256
+ const mockClient = createMockClient();
257
+ const store = new ChannelStore(mockClient);
258
+ await store.write("a", { type: "a", timestamp: 1 });
259
+ await store.write("b", { type: "b", timestamp: 2 });
260
+ const all = store.readAll();
261
+ expect(all.size).toBe(2);
262
+ });
263
+ test("size returns channel count", async () => {
264
+ const mockClient = createMockClient();
265
+ const store = new ChannelStore(mockClient);
266
+ expect(store.size).toBe(0);
267
+ await store.write("a", { type: "a", timestamp: 1 });
268
+ expect(store.size).toBe(1);
269
+ await store.write("b", { type: "b", timestamp: 2 });
270
+ expect(store.size).toBe(2);
271
+ });
272
+ test("last-write-wins: newer timestamp replaces older", async () => {
273
+ const mockClient = createMockClient();
274
+ const store = new ChannelStore(mockClient);
275
+ await store.write("ch", { type: "old", timestamp: 100 });
276
+ await store.write("ch", { type: "new", timestamp: 200 });
277
+ expect(store.read("ch")?.type).toBe("new");
278
+ });
279
+ test("last-write-wins: older timestamp is ignored", async () => {
280
+ const mockClient = createMockClient();
281
+ const store = new ChannelStore(mockClient);
282
+ await store.write("ch", { type: "new", timestamp: 200 });
283
+ await store.write("ch", { type: "old", timestamp: 100 });
284
+ expect(store.read("ch")?.type).toBe("new");
285
+ });
286
+ test("equal timestamp does not trigger update (idempotent)", async () => {
287
+ const mockClient = createMockClient();
288
+ const store = new ChannelStore(mockClient);
289
+ const onChange = vi.fn();
290
+ store.onChange(onChange);
291
+ await store.write("ch", { type: "first", timestamp: 100 });
292
+ expect(onChange).toHaveBeenCalledOnce();
293
+ await store.write("ch", { type: "second", timestamp: 100 });
294
+ // Equal timestamp = skip, onChange should NOT fire again
295
+ expect(onChange).toHaveBeenCalledOnce();
296
+ expect(store.read("ch")?.type).toBe("first");
297
+ });
298
+ test("onChange fires on update with previous value", async () => {
299
+ const mockClient = createMockClient();
300
+ const store = new ChannelStore(mockClient);
301
+ const onChange = vi.fn();
302
+ store.onChange(onChange);
303
+ await store.write("ch", { type: "first", timestamp: 1 });
304
+ // onChange is called with hash key, not human-readable name
305
+ expect(onChange).toHaveBeenCalledOnce();
306
+ expect(onChange.mock.calls[0][1]).toEqual({ type: "first", timestamp: 1 });
307
+ expect(onChange.mock.calls[0][2]).toBeUndefined();
308
+ await store.write("ch", { type: "second", timestamp: 2 });
309
+ expect(onChange).toHaveBeenCalledTimes(2);
310
+ expect(onChange.mock.calls[1][1]).toEqual({ type: "second", timestamp: 2 });
311
+ expect(onChange.mock.calls[1][2]).toEqual({ type: "first", timestamp: 1 });
312
+ });
313
+ test("onChange unsubscribe stops notifications", async () => {
314
+ const mockClient = createMockClient();
315
+ const store = new ChannelStore(mockClient);
316
+ const onChange = vi.fn();
317
+ const sub = store.onChange(onChange);
318
+ await store.write("ch", { type: "first", timestamp: 1 });
319
+ expect(onChange).toHaveBeenCalledOnce();
320
+ sub.unsubscribe();
321
+ await store.write("ch", { type: "second", timestamp: 2 });
322
+ expect(onChange).toHaveBeenCalledOnce(); // No additional call
323
+ });
324
+ test("onChange callback error does not break other callbacks", async () => {
325
+ const mockClient = createMockClient();
326
+ const store = new ChannelStore(mockClient);
327
+ const badCallback = vi.fn(() => {
328
+ throw new Error("boom");
329
+ });
330
+ const goodCallback = vi.fn();
331
+ store.onChange(badCallback);
332
+ store.onChange(goodCallback);
333
+ await store.write("ch", { type: "test", timestamp: 1 });
334
+ expect(badCallback).toHaveBeenCalledOnce();
335
+ expect(goodCallback).toHaveBeenCalledOnce();
336
+ });
337
+ test("incoming statement updates channel by hash", () => {
338
+ const mockClient = createMockClient();
339
+ const store = new ChannelStore(mockClient);
340
+ const channelHash = new Uint8Array(32).fill(0xab);
341
+ mockClient._simulateStatement({
342
+ data: { type: "remote", timestamp: 500 },
343
+ channel: channelHash,
344
+ raw: {},
345
+ });
346
+ // Channel is stored by hex of hash, accessible via readAll
347
+ const hexKey = "0x" + "ab".repeat(32);
348
+ expect(store.readAll().get(hexKey)?.type).toBe("remote");
349
+ expect(store.size).toBe(1);
350
+ });
351
+ test("local write and network echo use same key", async () => {
352
+ const { createChannel: mkCh, topicToHex: toHex } = await import("./topics.js");
353
+ const mockClient = createMockClient();
354
+ const store = new ChannelStore(mockClient);
355
+ // Local write
356
+ await store.write("presence/abc", { type: "local", timestamp: 100 });
357
+ expect(store.size).toBe(1);
358
+ // Network echo arrives with same channel hash
359
+ const channelHash = mkCh("presence/abc");
360
+ mockClient._simulateStatement({
361
+ data: { type: "network-echo", timestamp: 200 },
362
+ channel: channelHash,
363
+ raw: {},
364
+ });
365
+ // Should replace (not duplicate) since same hash key
366
+ expect(store.size).toBe(1);
367
+ expect(store.read("presence/abc")?.type).toBe("network-echo");
368
+ });
369
+ test("incoming statement without channel is ignored", () => {
370
+ const mockClient = createMockClient();
371
+ const store = new ChannelStore(mockClient);
372
+ const onChange = vi.fn();
373
+ store.onChange(onChange);
374
+ mockClient._simulateStatement({
375
+ data: { type: "no-channel", timestamp: 1 },
376
+ raw: {},
377
+ });
378
+ expect(onChange).not.toHaveBeenCalled();
379
+ });
380
+ test("destroy cleans up", async () => {
381
+ const mockClient = createMockClient();
382
+ const store = new ChannelStore(mockClient);
383
+ await store.write("ch", { type: "test", timestamp: 1 });
384
+ store.destroy();
385
+ expect(store.readAll().size).toBe(0);
386
+ });
387
+ test("destroy is safe when subscription is already null", () => {
388
+ const mockClient = createMockClient();
389
+ const store = new ChannelStore(mockClient);
390
+ store.destroy();
391
+ // Second destroy — subscription is already null
392
+ expect(() => store.destroy()).not.toThrow();
393
+ });
394
+ test("handles values with undefined timestamps via ?? 0 fallback", async () => {
395
+ const mockClient = createMockClient();
396
+ const store = new ChannelStore(mockClient);
397
+ // Write without timestamp — write() will add one via Date.now()
398
+ await store.write("ch", { type: "first" });
399
+ // Simulate incoming with explicit undefined timestamp via network
400
+ const channelHash = (await import("./topics.js")).createChannel("ch");
401
+ mockClient._simulateStatement({
402
+ data: { type: "network", timestamp: undefined },
403
+ channel: channelHash,
404
+ raw: {},
405
+ });
406
+ // The undefined timestamp falls back to 0 via ?? 0
407
+ // and is less than the Date.now() timestamp, so it should be skipped
408
+ expect(store.read("ch")?.type).toBe("first");
409
+ });
410
+ test("onChange error with non-Error value is stringified", async () => {
411
+ const mockClient = createMockClient();
412
+ const store = new ChannelStore(mockClient);
413
+ store.onChange(() => {
414
+ throw "string error"; // eslint-disable-line no-throw-literal
415
+ });
416
+ // Should not throw — the string error is caught and logged
417
+ await store.write("ch", { type: "test", timestamp: 1 });
418
+ expect(store.read("ch")).toBeDefined();
419
+ });
420
+ });
421
+ }
422
+ //# sourceMappingURL=channels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels.js","sourceRoot":"","sources":["../src/channels.ts"],"names":[],"mappings":"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"}