cojson-storage-indexeddb 0.15.8 → 0.15.9
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +8 -0
- package/dist/idbClient.d.ts +1 -1
- package/dist/idbClient.d.ts.map +1 -1
- package/dist/idbNode.d.ts +2 -10
- package/dist/idbNode.d.ts.map +1 -1
- package/dist/idbNode.js +39 -96
- package/dist/idbNode.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/tests/storage.indexeddb.test.js +36 -86
- package/dist/tests/storage.indexeddb.test.js.map +1 -1
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +36 -15
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +2 -3
- package/src/idbClient.ts +1 -1
- package/src/idbNode.ts +43 -131
- package/src/index.ts +1 -2
- package/src/tests/storage.indexeddb.test.ts +37 -111
- package/src/tests/testUtils.ts +42 -18
- package/dist/tests/idbNode.test.d.ts +0 -2
- package/dist/tests/idbNode.test.d.ts.map +0 -1
- package/dist/tests/idbNode.test.js +0 -29
- package/dist/tests/idbNode.test.js.map +0 -1
- package/src/tests/idbNode.test.ts +0 -61
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { LocalNode } from "cojson";
|
|
2
|
-
import { StorageManagerAsync } from "cojson-storage";
|
|
1
|
+
import { LocalNode, StorageApiAsync } from "cojson";
|
|
3
2
|
import { WasmCrypto } from "cojson/crypto/WasmCrypto";
|
|
4
3
|
import { afterEach, beforeEach, expect, test, vi } from "vitest";
|
|
5
|
-
import {
|
|
4
|
+
import { getIndexedDBStorage } from "../index.js";
|
|
6
5
|
import { toSimplifiedMessages } from "./messagesTestUtils.js";
|
|
7
6
|
import { trackMessages, waitFor } from "./testUtils.js";
|
|
8
7
|
|
|
@@ -17,22 +16,6 @@ afterEach(() => {
|
|
|
17
16
|
syncMessages.restore();
|
|
18
17
|
});
|
|
19
18
|
|
|
20
|
-
test("Should be able to initialize and load from empty DB", async () => {
|
|
21
|
-
const agentSecret = Crypto.newRandomAgentSecret();
|
|
22
|
-
|
|
23
|
-
const node = new LocalNode(
|
|
24
|
-
agentSecret,
|
|
25
|
-
Crypto.newRandomSessionID(Crypto.getAgentID(agentSecret)),
|
|
26
|
-
Crypto,
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
node.syncManager.addPeer(await IDBStorage.asPeer());
|
|
30
|
-
|
|
31
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
32
|
-
|
|
33
|
-
expect(node.syncManager.peers.indexedDB).toBeDefined();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
19
|
test("should sync and load data from storage", async () => {
|
|
37
20
|
const agentSecret = Crypto.newRandomAgentSecret();
|
|
38
21
|
|
|
@@ -41,18 +24,14 @@ test("should sync and load data from storage", async () => {
|
|
|
41
24
|
Crypto.newRandomSessionID(Crypto.getAgentID(agentSecret)),
|
|
42
25
|
Crypto,
|
|
43
26
|
);
|
|
44
|
-
|
|
45
|
-
const peer = await IDBStorage.asPeer();
|
|
46
|
-
|
|
47
|
-
node1.syncManager.addPeer(peer);
|
|
27
|
+
node1.setStorage(await getIndexedDBStorage());
|
|
48
28
|
|
|
49
29
|
const group = node1.createGroup();
|
|
50
|
-
|
|
51
30
|
const map = group.createMap();
|
|
52
31
|
|
|
53
32
|
map.set("hello", "world");
|
|
54
33
|
|
|
55
|
-
await
|
|
34
|
+
await map.core.waitForSync();
|
|
56
35
|
|
|
57
36
|
expect(
|
|
58
37
|
toSimplifiedMessages(
|
|
@@ -65,9 +44,7 @@ test("should sync and load data from storage", async () => {
|
|
|
65
44
|
).toMatchInlineSnapshot(`
|
|
66
45
|
[
|
|
67
46
|
"client -> CONTENT Group header: true new: After: 0 New: 3",
|
|
68
|
-
"storage -> KNOWN Group sessions: header/3",
|
|
69
47
|
"client -> CONTENT Map header: true new: After: 0 New: 1",
|
|
70
|
-
"storage -> KNOWN Map sessions: header/1",
|
|
71
48
|
]
|
|
72
49
|
`);
|
|
73
50
|
|
|
@@ -80,9 +57,7 @@ test("should sync and load data from storage", async () => {
|
|
|
80
57
|
Crypto,
|
|
81
58
|
);
|
|
82
59
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
node2.syncManager.addPeer(peer2);
|
|
60
|
+
node2.setStorage(await getIndexedDBStorage());
|
|
86
61
|
|
|
87
62
|
const map2 = await node2.load(map.id);
|
|
88
63
|
if (map2 === "unavailable") {
|
|
@@ -103,9 +78,7 @@ test("should sync and load data from storage", async () => {
|
|
|
103
78
|
[
|
|
104
79
|
"client -> LOAD Map sessions: empty",
|
|
105
80
|
"storage -> CONTENT Group header: true new: After: 0 New: 3",
|
|
106
|
-
"client -> KNOWN Group sessions: header/3",
|
|
107
81
|
"storage -> CONTENT Map header: true new: After: 0 New: 1",
|
|
108
|
-
"client -> KNOWN Map sessions: header/1",
|
|
109
82
|
]
|
|
110
83
|
`);
|
|
111
84
|
});
|
|
@@ -119,15 +92,12 @@ test("should send an empty content message if there is no content", async () =>
|
|
|
119
92
|
Crypto,
|
|
120
93
|
);
|
|
121
94
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
node1.syncManager.addPeer(peer);
|
|
95
|
+
node1.setStorage(await getIndexedDBStorage());
|
|
125
96
|
|
|
126
97
|
const group = node1.createGroup();
|
|
127
|
-
|
|
128
98
|
const map = group.createMap();
|
|
129
99
|
|
|
130
|
-
await
|
|
100
|
+
await map.core.waitForSync();
|
|
131
101
|
|
|
132
102
|
expect(
|
|
133
103
|
toSimplifiedMessages(
|
|
@@ -140,9 +110,7 @@ test("should send an empty content message if there is no content", async () =>
|
|
|
140
110
|
).toMatchInlineSnapshot(`
|
|
141
111
|
[
|
|
142
112
|
"client -> CONTENT Group header: true new: After: 0 New: 3",
|
|
143
|
-
"storage -> KNOWN Group sessions: header/3",
|
|
144
113
|
"client -> CONTENT Map header: true new: ",
|
|
145
|
-
"storage -> KNOWN Map sessions: header/0",
|
|
146
114
|
]
|
|
147
115
|
`);
|
|
148
116
|
|
|
@@ -155,9 +123,7 @@ test("should send an empty content message if there is no content", async () =>
|
|
|
155
123
|
Crypto,
|
|
156
124
|
);
|
|
157
125
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
node2.syncManager.addPeer(peer2);
|
|
126
|
+
node2.setStorage(await getIndexedDBStorage());
|
|
161
127
|
|
|
162
128
|
const map2 = await node2.load(map.id);
|
|
163
129
|
if (map2 === "unavailable") {
|
|
@@ -176,9 +142,7 @@ test("should send an empty content message if there is no content", async () =>
|
|
|
176
142
|
[
|
|
177
143
|
"client -> LOAD Map sessions: empty",
|
|
178
144
|
"storage -> CONTENT Group header: true new: After: 0 New: 3",
|
|
179
|
-
"client -> KNOWN Group sessions: header/3",
|
|
180
145
|
"storage -> CONTENT Map header: true new: ",
|
|
181
|
-
"client -> KNOWN Map sessions: header/0",
|
|
182
146
|
]
|
|
183
147
|
`);
|
|
184
148
|
});
|
|
@@ -192,10 +156,7 @@ test("should load dependencies correctly (group inheritance)", async () => {
|
|
|
192
156
|
Crypto,
|
|
193
157
|
);
|
|
194
158
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
node1.syncManager.addPeer(peer);
|
|
198
|
-
|
|
159
|
+
node1.setStorage(await getIndexedDBStorage());
|
|
199
160
|
const group = node1.createGroup();
|
|
200
161
|
const parentGroup = node1.createGroup();
|
|
201
162
|
|
|
@@ -205,7 +166,7 @@ test("should load dependencies correctly (group inheritance)", async () => {
|
|
|
205
166
|
|
|
206
167
|
map.set("hello", "world");
|
|
207
168
|
|
|
208
|
-
await
|
|
169
|
+
await map.core.waitForSync();
|
|
209
170
|
|
|
210
171
|
expect(
|
|
211
172
|
toSimplifiedMessages(
|
|
@@ -218,12 +179,9 @@ test("should load dependencies correctly (group inheritance)", async () => {
|
|
|
218
179
|
),
|
|
219
180
|
).toMatchInlineSnapshot(`
|
|
220
181
|
[
|
|
221
|
-
"client -> CONTENT ParentGroup header: true new: After: 0 New: 4",
|
|
222
|
-
"storage -> KNOWN ParentGroup sessions: header/4",
|
|
223
182
|
"client -> CONTENT Group header: true new: After: 0 New: 5",
|
|
224
|
-
"
|
|
183
|
+
"client -> CONTENT ParentGroup header: true new: After: 0 New: 4",
|
|
225
184
|
"client -> CONTENT Map header: true new: After: 0 New: 1",
|
|
226
|
-
"storage -> KNOWN Map sessions: header/1",
|
|
227
185
|
]
|
|
228
186
|
`);
|
|
229
187
|
|
|
@@ -236,9 +194,7 @@ test("should load dependencies correctly (group inheritance)", async () => {
|
|
|
236
194
|
Crypto,
|
|
237
195
|
);
|
|
238
196
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
node2.syncManager.addPeer(peer2);
|
|
197
|
+
node2.setStorage(await getIndexedDBStorage());
|
|
242
198
|
|
|
243
199
|
await node2.load(map.id);
|
|
244
200
|
|
|
@@ -259,11 +215,8 @@ test("should load dependencies correctly (group inheritance)", async () => {
|
|
|
259
215
|
[
|
|
260
216
|
"client -> LOAD Map sessions: empty",
|
|
261
217
|
"storage -> CONTENT ParentGroup header: true new: After: 0 New: 4",
|
|
262
|
-
"client -> KNOWN ParentGroup sessions: header/4",
|
|
263
218
|
"storage -> CONTENT Group header: true new: After: 0 New: 5",
|
|
264
|
-
"client -> KNOWN Group sessions: header/5",
|
|
265
219
|
"storage -> CONTENT Map header: true new: After: 0 New: 1",
|
|
266
|
-
"client -> KNOWN Map sessions: header/1",
|
|
267
220
|
]
|
|
268
221
|
`);
|
|
269
222
|
});
|
|
@@ -277,9 +230,7 @@ test("should not send the same dependency value twice", async () => {
|
|
|
277
230
|
Crypto,
|
|
278
231
|
);
|
|
279
232
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
node1.syncManager.addPeer(peer);
|
|
233
|
+
node1.setStorage(await getIndexedDBStorage());
|
|
283
234
|
|
|
284
235
|
const group = node1.createGroup();
|
|
285
236
|
const parentGroup = node1.createGroup();
|
|
@@ -292,7 +243,8 @@ test("should not send the same dependency value twice", async () => {
|
|
|
292
243
|
map.set("hello", "world");
|
|
293
244
|
mapFromParent.set("hello", "world");
|
|
294
245
|
|
|
295
|
-
await
|
|
246
|
+
await map.core.waitForSync();
|
|
247
|
+
await mapFromParent.core.waitForSync();
|
|
296
248
|
|
|
297
249
|
syncMessages.clear();
|
|
298
250
|
node1.gracefulShutdown();
|
|
@@ -303,9 +255,7 @@ test("should not send the same dependency value twice", async () => {
|
|
|
303
255
|
Crypto,
|
|
304
256
|
);
|
|
305
257
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
node2.syncManager.addPeer(peer2);
|
|
258
|
+
node2.setStorage(await getIndexedDBStorage());
|
|
309
259
|
|
|
310
260
|
await node2.load(map.id);
|
|
311
261
|
await node2.load(mapFromParent.id);
|
|
@@ -329,14 +279,10 @@ test("should not send the same dependency value twice", async () => {
|
|
|
329
279
|
[
|
|
330
280
|
"client -> LOAD Map sessions: empty",
|
|
331
281
|
"storage -> CONTENT ParentGroup header: true new: After: 0 New: 4",
|
|
332
|
-
"client -> KNOWN ParentGroup sessions: header/4",
|
|
333
282
|
"storage -> CONTENT Group header: true new: After: 0 New: 5",
|
|
334
|
-
"client -> KNOWN Group sessions: header/5",
|
|
335
283
|
"storage -> CONTENT Map header: true new: After: 0 New: 1",
|
|
336
|
-
"client -> KNOWN Map sessions: header/1",
|
|
337
284
|
"client -> LOAD MapFromParent sessions: empty",
|
|
338
285
|
"storage -> CONTENT MapFromParent header: true new: After: 0 New: 1",
|
|
339
|
-
"client -> KNOWN MapFromParent sessions: header/1",
|
|
340
286
|
]
|
|
341
287
|
`);
|
|
342
288
|
});
|
|
@@ -350,9 +296,8 @@ test("should recover from data loss", async () => {
|
|
|
350
296
|
Crypto,
|
|
351
297
|
);
|
|
352
298
|
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
node1.syncManager.addPeer(peer);
|
|
299
|
+
const storage = await getIndexedDBStorage();
|
|
300
|
+
node1.setStorage(storage);
|
|
356
301
|
|
|
357
302
|
const group = node1.createGroup();
|
|
358
303
|
|
|
@@ -360,22 +305,25 @@ test("should recover from data loss", async () => {
|
|
|
360
305
|
|
|
361
306
|
map.set("0", 0);
|
|
362
307
|
|
|
363
|
-
await
|
|
308
|
+
await map.core.waitForSync();
|
|
364
309
|
|
|
365
310
|
const mock = vi
|
|
366
|
-
.spyOn(
|
|
367
|
-
.mockImplementation(() => Promise.resolve());
|
|
311
|
+
.spyOn(StorageApiAsync.prototype, "store")
|
|
312
|
+
.mockImplementation(() => Promise.resolve(undefined));
|
|
368
313
|
|
|
369
314
|
map.set("1", 1);
|
|
370
315
|
map.set("2", 2);
|
|
371
316
|
|
|
372
317
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
373
318
|
|
|
319
|
+
const knownState = storage.getKnownState(map.id);
|
|
320
|
+
Object.assign(knownState, map.core.knownState());
|
|
321
|
+
|
|
374
322
|
mock.mockReset();
|
|
375
323
|
|
|
376
324
|
map.set("3", 3);
|
|
377
325
|
|
|
378
|
-
await
|
|
326
|
+
await map.core.waitForSync();
|
|
379
327
|
|
|
380
328
|
expect(
|
|
381
329
|
toSimplifiedMessages(
|
|
@@ -388,13 +336,10 @@ test("should recover from data loss", async () => {
|
|
|
388
336
|
).toMatchInlineSnapshot(`
|
|
389
337
|
[
|
|
390
338
|
"client -> CONTENT Group header: true new: After: 0 New: 3",
|
|
391
|
-
"storage -> KNOWN Group sessions: header/3",
|
|
392
339
|
"client -> CONTENT Map header: true new: After: 0 New: 1",
|
|
393
|
-
"storage -> KNOWN Map sessions: header/1",
|
|
394
340
|
"client -> CONTENT Map header: false new: After: 3 New: 1",
|
|
395
|
-
"storage -> KNOWN CORRECTION Map sessions: header/
|
|
341
|
+
"storage -> KNOWN CORRECTION Map sessions: header/4",
|
|
396
342
|
"client -> CONTENT Map header: false new: After: 1 New: 3",
|
|
397
|
-
"storage -> KNOWN Map sessions: header/4",
|
|
398
343
|
]
|
|
399
344
|
`);
|
|
400
345
|
|
|
@@ -407,9 +352,7 @@ test("should recover from data loss", async () => {
|
|
|
407
352
|
Crypto,
|
|
408
353
|
);
|
|
409
354
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
node2.syncManager.addPeer(peer2);
|
|
355
|
+
node2.setStorage(await getIndexedDBStorage());
|
|
413
356
|
|
|
414
357
|
const map2 = await node2.load(map.id);
|
|
415
358
|
|
|
@@ -436,9 +379,7 @@ test("should recover from data loss", async () => {
|
|
|
436
379
|
[
|
|
437
380
|
"client -> LOAD Map sessions: empty",
|
|
438
381
|
"storage -> CONTENT Group header: true new: After: 0 New: 3",
|
|
439
|
-
"client -> KNOWN Group sessions: header/3",
|
|
440
382
|
"storage -> CONTENT Map header: true new: After: 0 New: 4",
|
|
441
|
-
"client -> KNOWN Map sessions: header/4",
|
|
442
383
|
]
|
|
443
384
|
`);
|
|
444
385
|
});
|
|
@@ -452,7 +393,7 @@ test("should sync multiple sessions in a single content message", async () => {
|
|
|
452
393
|
Crypto,
|
|
453
394
|
);
|
|
454
395
|
|
|
455
|
-
node1.
|
|
396
|
+
node1.setStorage(await getIndexedDBStorage());
|
|
456
397
|
|
|
457
398
|
const group = node1.createGroup();
|
|
458
399
|
|
|
@@ -460,7 +401,7 @@ test("should sync multiple sessions in a single content message", async () => {
|
|
|
460
401
|
|
|
461
402
|
map.set("hello", "world");
|
|
462
403
|
|
|
463
|
-
await
|
|
404
|
+
await map.core.waitForSync();
|
|
464
405
|
|
|
465
406
|
node1.gracefulShutdown();
|
|
466
407
|
|
|
@@ -470,7 +411,7 @@ test("should sync multiple sessions in a single content message", async () => {
|
|
|
470
411
|
Crypto,
|
|
471
412
|
);
|
|
472
413
|
|
|
473
|
-
node2.
|
|
414
|
+
node2.setStorage(await getIndexedDBStorage());
|
|
474
415
|
|
|
475
416
|
const map2 = await node2.load(map.id);
|
|
476
417
|
if (map2 === "unavailable") {
|
|
@@ -493,7 +434,7 @@ test("should sync multiple sessions in a single content message", async () => {
|
|
|
493
434
|
|
|
494
435
|
syncMessages.clear();
|
|
495
436
|
|
|
496
|
-
node3.
|
|
437
|
+
node3.setStorage(await getIndexedDBStorage());
|
|
497
438
|
|
|
498
439
|
const map3 = await node3.load(map.id);
|
|
499
440
|
if (map3 === "unavailable") {
|
|
@@ -514,9 +455,7 @@ test("should sync multiple sessions in a single content message", async () => {
|
|
|
514
455
|
[
|
|
515
456
|
"client -> LOAD Map sessions: empty",
|
|
516
457
|
"storage -> CONTENT Group header: true new: After: 0 New: 3",
|
|
517
|
-
"client -> KNOWN Group sessions: header/3",
|
|
518
458
|
"storage -> CONTENT Map header: true new: After: 0 New: 1 | After: 0 New: 1",
|
|
519
|
-
"client -> KNOWN Map sessions: header/2",
|
|
520
459
|
]
|
|
521
460
|
`);
|
|
522
461
|
});
|
|
@@ -530,7 +469,7 @@ test("large coValue upload streaming", async () => {
|
|
|
530
469
|
Crypto,
|
|
531
470
|
);
|
|
532
471
|
|
|
533
|
-
node1.
|
|
472
|
+
node1.setStorage(await getIndexedDBStorage());
|
|
534
473
|
|
|
535
474
|
const group = node1.createGroup();
|
|
536
475
|
const largeMap = group.createMap();
|
|
@@ -547,6 +486,7 @@ test("large coValue upload streaming", async () => {
|
|
|
547
486
|
largeMap.set(key, value, "trusting");
|
|
548
487
|
}
|
|
549
488
|
|
|
489
|
+
// TODO: Wait for storage to be updated
|
|
550
490
|
await largeMap.core.waitForSync();
|
|
551
491
|
|
|
552
492
|
const knownState = largeMap.core.knownState();
|
|
@@ -561,7 +501,7 @@ test("large coValue upload streaming", async () => {
|
|
|
561
501
|
|
|
562
502
|
syncMessages.clear();
|
|
563
503
|
|
|
564
|
-
node2.
|
|
504
|
+
node2.setStorage(await getIndexedDBStorage());
|
|
565
505
|
|
|
566
506
|
const largeMapOnNode2 = await node2.load(largeMap.id);
|
|
567
507
|
|
|
@@ -586,15 +526,10 @@ test("large coValue upload streaming", async () => {
|
|
|
586
526
|
).toMatchInlineSnapshot(`
|
|
587
527
|
[
|
|
588
528
|
"client -> LOAD Map sessions: empty",
|
|
589
|
-
"storage -> KNOWN Map sessions: header/200",
|
|
590
529
|
"storage -> CONTENT Group header: true new: After: 0 New: 3",
|
|
591
|
-
"client -> KNOWN Group sessions: header/3",
|
|
592
530
|
"storage -> CONTENT Map header: true new: After: 0 New: 97",
|
|
593
|
-
"client -> KNOWN Map sessions: header/97",
|
|
594
531
|
"storage -> CONTENT Map header: true new: After: 97 New: 97",
|
|
595
|
-
"client -> KNOWN Map sessions: header/194",
|
|
596
532
|
"storage -> CONTENT Map header: true new: After: 194 New: 6",
|
|
597
|
-
"client -> KNOWN Map sessions: header/200",
|
|
598
533
|
]
|
|
599
534
|
`);
|
|
600
535
|
});
|
|
@@ -605,7 +540,7 @@ test("should sync and load accounts from storage", async () => {
|
|
|
605
540
|
const { node: node1, accountID } = await LocalNode.withNewlyCreatedAccount({
|
|
606
541
|
crypto: Crypto,
|
|
607
542
|
initialAgentSecret: agentSecret,
|
|
608
|
-
|
|
543
|
+
storage: await getIndexedDBStorage(),
|
|
609
544
|
creationProps: {
|
|
610
545
|
name: "test",
|
|
611
546
|
},
|
|
@@ -615,8 +550,6 @@ test("should sync and load accounts from storage", async () => {
|
|
|
615
550
|
const profile = node1.expectProfileLoaded(accountID);
|
|
616
551
|
const profileGroup = profile.group;
|
|
617
552
|
|
|
618
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
619
|
-
|
|
620
553
|
expect(
|
|
621
554
|
toSimplifiedMessages(
|
|
622
555
|
{
|
|
@@ -629,11 +562,8 @@ test("should sync and load accounts from storage", async () => {
|
|
|
629
562
|
).toMatchInlineSnapshot(`
|
|
630
563
|
[
|
|
631
564
|
"client -> CONTENT Account header: true new: After: 0 New: 4",
|
|
632
|
-
"storage -> KNOWN Account sessions: header/4",
|
|
633
565
|
"client -> CONTENT ProfileGroup header: true new: After: 0 New: 5",
|
|
634
|
-
"storage -> KNOWN ProfileGroup sessions: header/5",
|
|
635
566
|
"client -> CONTENT Profile header: true new: After: 0 New: 1",
|
|
636
|
-
"storage -> KNOWN Profile sessions: header/1",
|
|
637
567
|
]
|
|
638
568
|
`);
|
|
639
569
|
|
|
@@ -645,12 +575,11 @@ test("should sync and load accounts from storage", async () => {
|
|
|
645
575
|
crypto: Crypto,
|
|
646
576
|
accountSecret: agentSecret,
|
|
647
577
|
accountID,
|
|
648
|
-
peersToLoadFrom: [
|
|
578
|
+
peersToLoadFrom: [],
|
|
579
|
+
storage: await getIndexedDBStorage(),
|
|
649
580
|
sessionID: Crypto.newRandomSessionID(Crypto.getAgentID(agentSecret)),
|
|
650
581
|
});
|
|
651
582
|
|
|
652
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
653
|
-
|
|
654
583
|
expect(
|
|
655
584
|
toSimplifiedMessages(
|
|
656
585
|
{
|
|
@@ -664,12 +593,9 @@ test("should sync and load accounts from storage", async () => {
|
|
|
664
593
|
[
|
|
665
594
|
"client -> LOAD Account sessions: empty",
|
|
666
595
|
"storage -> CONTENT Account header: true new: After: 0 New: 4",
|
|
667
|
-
"client -> KNOWN Account sessions: header/4",
|
|
668
596
|
"client -> LOAD Profile sessions: empty",
|
|
669
597
|
"storage -> CONTENT ProfileGroup header: true new: After: 0 New: 5",
|
|
670
|
-
"client -> KNOWN ProfileGroup sessions: header/5",
|
|
671
598
|
"storage -> CONTENT Profile header: true new: After: 0 New: 1",
|
|
672
|
-
"client -> KNOWN Profile sessions: header/1",
|
|
673
599
|
]
|
|
674
600
|
`);
|
|
675
601
|
|
package/src/tests/testUtils.ts
CHANGED
|
@@ -1,39 +1,63 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
import { StorageManagerAsync } from "cojson-storage";
|
|
1
|
+
import type { RawCoID, SyncMessage } from "cojson";
|
|
2
|
+
import { StorageApiAsync } from "cojson";
|
|
4
3
|
import { onTestFinished } from "vitest";
|
|
5
4
|
|
|
6
|
-
const { SyncManager } = cojsonInternals;
|
|
7
|
-
|
|
8
5
|
export function trackMessages() {
|
|
9
6
|
const messages: {
|
|
10
7
|
from: "client" | "server" | "storage";
|
|
11
8
|
msg: SyncMessage;
|
|
12
9
|
}[] = [];
|
|
13
10
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
const originalNodeSyncMessage = SyncManager.prototype.handleSyncMessage;
|
|
11
|
+
const originalLoad = StorageApiAsync.prototype.load;
|
|
12
|
+
const originalStore = StorageApiAsync.prototype.store;
|
|
17
13
|
|
|
18
|
-
|
|
14
|
+
StorageApiAsync.prototype.load = async function (id, callback, done) {
|
|
19
15
|
messages.push({
|
|
20
16
|
from: "client",
|
|
21
|
-
msg
|
|
17
|
+
msg: {
|
|
18
|
+
action: "load",
|
|
19
|
+
id: id as RawCoID,
|
|
20
|
+
header: false,
|
|
21
|
+
sessions: {},
|
|
22
|
+
},
|
|
22
23
|
});
|
|
23
|
-
return
|
|
24
|
+
return originalLoad.call(
|
|
25
|
+
this,
|
|
26
|
+
id,
|
|
27
|
+
(msg) => {
|
|
28
|
+
messages.push({
|
|
29
|
+
from: "storage",
|
|
30
|
+
msg,
|
|
31
|
+
});
|
|
32
|
+
callback(msg);
|
|
33
|
+
},
|
|
34
|
+
done,
|
|
35
|
+
);
|
|
24
36
|
};
|
|
25
37
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
38
|
+
StorageApiAsync.prototype.store = async function (data, correctionCallback) {
|
|
39
|
+
for (const msg of data) {
|
|
40
|
+
messages.push({
|
|
41
|
+
from: "client",
|
|
42
|
+
msg,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return originalStore.call(this, data, (msg) => {
|
|
46
|
+
messages.push({
|
|
47
|
+
from: "storage",
|
|
48
|
+
msg: {
|
|
49
|
+
action: "known",
|
|
50
|
+
isCorrection: true,
|
|
51
|
+
...msg,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
correctionCallback(msg);
|
|
30
55
|
});
|
|
31
|
-
return originalNodeSyncMessage.call(this, msg, peer);
|
|
32
56
|
};
|
|
33
57
|
|
|
34
58
|
const restore = () => {
|
|
35
|
-
|
|
36
|
-
|
|
59
|
+
StorageApiAsync.prototype.load = originalLoad;
|
|
60
|
+
StorageApiAsync.prototype.store = originalStore;
|
|
37
61
|
messages.length = 0;
|
|
38
62
|
};
|
|
39
63
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"idbNode.test.d.ts","sourceRoot":"","sources":["../../src/tests/idbNode.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { LocalNode } from "cojson";
|
|
2
|
-
import { WasmCrypto } from "cojson/crypto/WasmCrypto";
|
|
3
|
-
import { expect, test } from "vitest";
|
|
4
|
-
import { IDBStorage } from "../index.js";
|
|
5
|
-
const Crypto = await WasmCrypto.create();
|
|
6
|
-
test("Should be able to initialize and load from empty DB", async () => {
|
|
7
|
-
const agentSecret = Crypto.newRandomAgentSecret();
|
|
8
|
-
const node = new LocalNode(agentSecret, Crypto.newRandomSessionID(Crypto.getAgentID(agentSecret)), Crypto);
|
|
9
|
-
node.syncManager.addPeer(await IDBStorage.asPeer({}));
|
|
10
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
11
|
-
expect(node.syncManager.peers.indexedDB).toBeDefined();
|
|
12
|
-
});
|
|
13
|
-
test("Should be able to sync data to database and then load that from a new node", async () => {
|
|
14
|
-
const agentSecret = Crypto.newRandomAgentSecret();
|
|
15
|
-
const node1 = new LocalNode(agentSecret, Crypto.newRandomSessionID(Crypto.getAgentID(agentSecret)), Crypto);
|
|
16
|
-
node1.syncManager.addPeer(await IDBStorage.asPeer({ localNodeName: "node1" }));
|
|
17
|
-
const group = node1.createGroup();
|
|
18
|
-
const map = group.createMap();
|
|
19
|
-
map.set("hello", "world");
|
|
20
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
21
|
-
const node2 = new LocalNode(agentSecret, Crypto.newRandomSessionID(Crypto.getAgentID(agentSecret)), Crypto);
|
|
22
|
-
node2.syncManager.addPeer(await IDBStorage.asPeer({ localNodeName: "node2" }));
|
|
23
|
-
const map2 = await node2.load(map.id);
|
|
24
|
-
if (map2 === "unavailable") {
|
|
25
|
-
throw new Error("Map is unavailable");
|
|
26
|
-
}
|
|
27
|
-
expect(map2.get("hello")).toBe("world");
|
|
28
|
-
});
|
|
29
|
-
//# sourceMappingURL=idbNode.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"idbNode.test.js","sourceRoot":"","sources":["../../src/tests/idbNode.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC;AAEzC,IAAI,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;IACrE,MAAM,WAAW,GAAG,MAAM,CAAC,oBAAoB,EAAE,CAAC;IAElD,MAAM,IAAI,GAAG,IAAI,SAAS,CACxB,WAAW,EACX,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EACzD,MAAM,CACP,CAAC;IAEF,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAEtD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IAEzD,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;AACzD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;IAC5F,MAAM,WAAW,GAAG,MAAM,CAAC,oBAAoB,EAAE,CAAC;IAElD,MAAM,KAAK,GAAG,IAAI,SAAS,CACzB,WAAW,EACX,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EACzD,MAAM,CACP,CAAC;IAEF,KAAK,CAAC,WAAW,CAAC,OAAO,CACvB,MAAM,UAAU,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CACpD,CAAC;IAEF,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAElC,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;IAE9B,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAE1B,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IAEzD,MAAM,KAAK,GAAG,IAAI,SAAS,CACzB,WAAW,EACX,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EACzD,MAAM,CACP,CAAC;IAEF,KAAK,CAAC,WAAW,CAAC,OAAO,CACvB,MAAM,UAAU,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CACpD,CAAC;IAEF,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACtC,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC"}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { LocalNode } from "cojson";
|
|
2
|
-
import { WasmCrypto } from "cojson/crypto/WasmCrypto";
|
|
3
|
-
import { expect, test } from "vitest";
|
|
4
|
-
import { IDBStorage } from "../index.js";
|
|
5
|
-
|
|
6
|
-
const Crypto = await WasmCrypto.create();
|
|
7
|
-
|
|
8
|
-
test("Should be able to initialize and load from empty DB", async () => {
|
|
9
|
-
const agentSecret = Crypto.newRandomAgentSecret();
|
|
10
|
-
|
|
11
|
-
const node = new LocalNode(
|
|
12
|
-
agentSecret,
|
|
13
|
-
Crypto.newRandomSessionID(Crypto.getAgentID(agentSecret)),
|
|
14
|
-
Crypto,
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
node.syncManager.addPeer(await IDBStorage.asPeer({}));
|
|
18
|
-
|
|
19
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
20
|
-
|
|
21
|
-
expect(node.syncManager.peers.indexedDB).toBeDefined();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test("Should be able to sync data to database and then load that from a new node", async () => {
|
|
25
|
-
const agentSecret = Crypto.newRandomAgentSecret();
|
|
26
|
-
|
|
27
|
-
const node1 = new LocalNode(
|
|
28
|
-
agentSecret,
|
|
29
|
-
Crypto.newRandomSessionID(Crypto.getAgentID(agentSecret)),
|
|
30
|
-
Crypto,
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
node1.syncManager.addPeer(
|
|
34
|
-
await IDBStorage.asPeer({ localNodeName: "node1" }),
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
const group = node1.createGroup();
|
|
38
|
-
|
|
39
|
-
const map = group.createMap();
|
|
40
|
-
|
|
41
|
-
map.set("hello", "world");
|
|
42
|
-
|
|
43
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
44
|
-
|
|
45
|
-
const node2 = new LocalNode(
|
|
46
|
-
agentSecret,
|
|
47
|
-
Crypto.newRandomSessionID(Crypto.getAgentID(agentSecret)),
|
|
48
|
-
Crypto,
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
node2.syncManager.addPeer(
|
|
52
|
-
await IDBStorage.asPeer({ localNodeName: "node2" }),
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
const map2 = await node2.load(map.id);
|
|
56
|
-
if (map2 === "unavailable") {
|
|
57
|
-
throw new Error("Map is unavailable");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
expect(map2.get("hello")).toBe("world");
|
|
61
|
-
});
|