cojson 0.16.5 → 0.17.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 (117) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +12 -0
  3. package/dist/GarbageCollector.d.ts +12 -0
  4. package/dist/GarbageCollector.d.ts.map +1 -0
  5. package/dist/GarbageCollector.js +37 -0
  6. package/dist/GarbageCollector.js.map +1 -0
  7. package/dist/coValue.d.ts +1 -1
  8. package/dist/coValueContentMessage.d.ts +1 -0
  9. package/dist/coValueContentMessage.d.ts.map +1 -1
  10. package/dist/coValueContentMessage.js +11 -3
  11. package/dist/coValueContentMessage.js.map +1 -1
  12. package/dist/coValueCore/coValueCore.d.ts +2 -1
  13. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  14. package/dist/coValueCore/coValueCore.js +15 -0
  15. package/dist/coValueCore/coValueCore.js.map +1 -1
  16. package/dist/coValueCore/utils.d.ts.map +1 -1
  17. package/dist/coValueCore/utils.js.map +1 -1
  18. package/dist/coValueCore/verifiedState.d.ts +1 -0
  19. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  20. package/dist/coValueCore/verifiedState.js.map +1 -1
  21. package/dist/coValues/coMap.d.ts +3 -3
  22. package/dist/coValues/coPlainText.d.ts +1 -0
  23. package/dist/coValues/coPlainText.d.ts.map +1 -1
  24. package/dist/coValues/coPlainText.js +27 -8
  25. package/dist/coValues/coPlainText.js.map +1 -1
  26. package/dist/coValues/coStream.d.ts +2 -2
  27. package/dist/coValues/group.d.ts +1 -1
  28. package/dist/config.d.ts +10 -1
  29. package/dist/config.d.ts.map +1 -1
  30. package/dist/config.js +16 -1
  31. package/dist/config.js.map +1 -1
  32. package/dist/exports.d.ts +11 -4
  33. package/dist/exports.d.ts.map +1 -1
  34. package/dist/exports.js +8 -3
  35. package/dist/exports.js.map +1 -1
  36. package/dist/localNode.d.ts +3 -0
  37. package/dist/localNode.d.ts.map +1 -1
  38. package/dist/localNode.js +11 -0
  39. package/dist/localNode.js.map +1 -1
  40. package/dist/queue/LocalTransactionsSyncQueue.js +1 -1
  41. package/dist/queue/LocalTransactionsSyncQueue.js.map +1 -1
  42. package/dist/queue/StoreQueue.d.ts +7 -1
  43. package/dist/queue/StoreQueue.d.ts.map +1 -1
  44. package/dist/queue/StoreQueue.js +35 -13
  45. package/dist/queue/StoreQueue.js.map +1 -1
  46. package/dist/storage/sqlite/client.d.ts +4 -4
  47. package/dist/storage/sqlite/client.d.ts.map +1 -1
  48. package/dist/storage/sqlite/client.js +13 -4
  49. package/dist/storage/sqlite/client.js.map +1 -1
  50. package/dist/storage/sqliteAsync/client.d.ts +3 -3
  51. package/dist/storage/sqliteAsync/client.d.ts.map +1 -1
  52. package/dist/storage/sqliteAsync/client.js +12 -3
  53. package/dist/storage/sqliteAsync/client.js.map +1 -1
  54. package/dist/storage/storageAsync.d.ts.map +1 -1
  55. package/dist/storage/storageAsync.js +2 -7
  56. package/dist/storage/storageAsync.js.map +1 -1
  57. package/dist/storage/storageSync.d.ts.map +1 -1
  58. package/dist/storage/storageSync.js +2 -7
  59. package/dist/storage/storageSync.js.map +1 -1
  60. package/dist/storage/types.d.ts +2 -2
  61. package/dist/storage/types.d.ts.map +1 -1
  62. package/dist/sync.d.ts.map +1 -1
  63. package/dist/sync.js +17 -3
  64. package/dist/sync.js.map +1 -1
  65. package/dist/tests/GarbageCollector.test.d.ts +2 -0
  66. package/dist/tests/GarbageCollector.test.d.ts.map +1 -0
  67. package/dist/tests/GarbageCollector.test.js +85 -0
  68. package/dist/tests/GarbageCollector.test.js.map +1 -0
  69. package/dist/tests/coPlainText.test.js +142 -4
  70. package/dist/tests/coPlainText.test.js.map +1 -1
  71. package/dist/tests/coStream.test.js +3 -3
  72. package/dist/tests/coStream.test.js.map +1 -1
  73. package/dist/tests/sync.garbageCollection.test.d.ts +2 -0
  74. package/dist/tests/sync.garbageCollection.test.d.ts.map +1 -0
  75. package/dist/tests/sync.garbageCollection.test.js +133 -0
  76. package/dist/tests/sync.garbageCollection.test.js.map +1 -0
  77. package/dist/tests/sync.mesh.test.js +48 -34
  78. package/dist/tests/sync.mesh.test.js.map +1 -1
  79. package/dist/tests/sync.storage.test.js +31 -21
  80. package/dist/tests/sync.storage.test.js.map +1 -1
  81. package/dist/tests/sync.storageAsync.test.js +76 -29
  82. package/dist/tests/sync.storageAsync.test.js.map +1 -1
  83. package/dist/tests/testStorage.d.ts +1 -0
  84. package/dist/tests/testStorage.d.ts.map +1 -1
  85. package/dist/tests/testStorage.js +1 -1
  86. package/dist/tests/testStorage.js.map +1 -1
  87. package/dist/tests/testUtils.d.ts +1 -0
  88. package/dist/tests/testUtils.d.ts.map +1 -1
  89. package/dist/tests/testUtils.js +1 -0
  90. package/dist/tests/testUtils.js.map +1 -1
  91. package/package.json +1 -1
  92. package/src/GarbageCollector.ts +48 -0
  93. package/src/coValueContentMessage.ts +16 -3
  94. package/src/coValueCore/coValueCore.ts +27 -10
  95. package/src/coValueCore/utils.ts +1 -0
  96. package/src/coValueCore/verifiedState.ts +1 -0
  97. package/src/coValues/coPlainText.ts +40 -8
  98. package/src/config.ts +20 -1
  99. package/src/exports.ts +13 -5
  100. package/src/localNode.ts +15 -1
  101. package/src/queue/LocalTransactionsSyncQueue.ts +1 -1
  102. package/src/queue/StoreQueue.ts +45 -12
  103. package/src/storage/sqlite/client.ts +24 -10
  104. package/src/storage/sqliteAsync/client.ts +26 -5
  105. package/src/storage/storageAsync.ts +5 -9
  106. package/src/storage/storageSync.ts +2 -9
  107. package/src/storage/types.ts +7 -4
  108. package/src/sync.ts +19 -3
  109. package/src/tests/GarbageCollector.test.ts +127 -0
  110. package/src/tests/coPlainText.test.ts +176 -4
  111. package/src/tests/coStream.test.ts +7 -3
  112. package/src/tests/sync.garbageCollection.test.ts +178 -0
  113. package/src/tests/sync.mesh.test.ts +49 -34
  114. package/src/tests/sync.storage.test.ts +31 -21
  115. package/src/tests/sync.storageAsync.test.ts +81 -29
  116. package/src/tests/testStorage.ts +11 -3
  117. package/src/tests/testUtils.ts +4 -1
@@ -1,5 +1,6 @@
1
1
  import { assert, beforeEach, describe, expect, test, vi } from "vitest";
2
2
 
3
+ import { setMaxRecommendedTxSize } from "../config";
3
4
  import { emptyKnownState } from "../exports";
4
5
  import {
5
6
  SyncMessagesLog,
@@ -8,6 +9,7 @@ import {
8
9
  setupTestNode,
9
10
  waitFor,
10
11
  } from "./testUtils";
12
+ import { getDbPath } from "./testStorage";
11
13
 
12
14
  // We want to simulate a real world communication that happens asynchronously
13
15
  TEST_NODE_CONFIG.withAsyncPeers = true;
@@ -17,6 +19,7 @@ describe("client with storage syncs with server", () => {
17
19
 
18
20
  beforeEach(async () => {
19
21
  vi.resetAllMocks();
22
+ setMaxRecommendedTxSize(100 * 1024);
20
23
  SyncMessagesLog.clear();
21
24
  jazzCloud = setupTestNode({
22
25
  isSyncServer: true,
@@ -262,6 +265,7 @@ describe("client syncs with a server with storage", () => {
262
265
  });
263
266
 
264
267
  test("large coValue streaming", async () => {
268
+ setMaxRecommendedTxSize(1000);
265
269
  const client = setupTestNode();
266
270
 
267
271
  client.connectToSyncServer({
@@ -278,11 +282,9 @@ describe("client syncs with a server with storage", () => {
278
282
  const largeMap = group.createMap();
279
283
 
280
284
  // Generate a large amount of data (about 100MB)
281
- const dataSize = 1 * 200 * 1024;
282
- const chunkSize = 1024; // 1KB chunks
283
- const chunks = dataSize / chunkSize;
285
+ const chunks = 100;
284
286
 
285
- const value = Buffer.alloc(chunkSize, `value$`).toString("base64");
287
+ const value = "1".repeat(10);
286
288
 
287
289
  for (let i = 0; i < chunks; i++) {
288
290
  const key = `key${i}`;
@@ -300,20 +302,28 @@ describe("client syncs with a server with storage", () => {
300
302
  [
301
303
  "client -> storage | CONTENT Group header: true new: After: 0 New: 5",
302
304
  "client -> server | CONTENT Group header: true new: After: 0 New: 5",
303
- "client -> storage | CONTENT Map header: true new: After: 0 New: 73",
304
- "client -> server | CONTENT Map header: true new: After: 0 New: 73",
305
- "client -> storage | CONTENT Map header: false new: After: 73 New: 73",
306
- "client -> server | CONTENT Map header: false new: After: 73 New: 73",
307
- "client -> storage | CONTENT Map header: false new: After: 146 New: 54",
308
- "client -> server | CONTENT Map header: false new: After: 146 New: 54",
305
+ "client -> storage | CONTENT Map header: true new: After: 0 New: 20",
306
+ "client -> server | CONTENT Map header: true new: After: 0 New: 20",
307
+ "client -> storage | CONTENT Map header: false new: After: 20 New: 21",
308
+ "client -> server | CONTENT Map header: false new: After: 20 New: 21",
309
+ "client -> storage | CONTENT Map header: false new: After: 41 New: 21",
310
+ "client -> server | CONTENT Map header: false new: After: 41 New: 21",
311
+ "client -> storage | CONTENT Map header: false new: After: 62 New: 21",
312
+ "client -> server | CONTENT Map header: false new: After: 62 New: 21",
313
+ "client -> storage | CONTENT Map header: false new: After: 83 New: 17",
314
+ "client -> server | CONTENT Map header: false new: After: 83 New: 17",
309
315
  "server -> client | KNOWN Group sessions: header/5",
310
316
  "server -> storage | CONTENT Group header: true new: After: 0 New: 5",
311
- "server -> client | KNOWN Map sessions: header/73",
312
- "server -> storage | CONTENT Map header: true new: After: 0 New: 73",
313
- "server -> client | KNOWN Map sessions: header/146",
314
- "server -> storage | CONTENT Map header: false new: After: 73 New: 73",
315
- "server -> client | KNOWN Map sessions: header/200",
316
- "server -> storage | CONTENT Map header: false new: After: 146 New: 54",
317
+ "server -> client | KNOWN Map sessions: header/20",
318
+ "server -> storage | CONTENT Map header: true new: After: 0 New: 20",
319
+ "server -> client | KNOWN Map sessions: header/41",
320
+ "server -> storage | CONTENT Map header: false new: After: 20 New: 21",
321
+ "server -> client | KNOWN Map sessions: header/62",
322
+ "server -> storage | CONTENT Map header: false new: After: 41 New: 21",
323
+ "server -> client | KNOWN Map sessions: header/83",
324
+ "server -> storage | CONTENT Map header: false new: After: 62 New: 21",
325
+ "server -> client | KNOWN Map sessions: header/100",
326
+ "server -> storage | CONTENT Map header: false new: After: 83 New: 17",
317
327
  ]
318
328
  `);
319
329
 
@@ -345,12 +355,13 @@ describe("client syncs with a server with storage", () => {
345
355
  "client -> storage | LOAD Map sessions: empty",
346
356
  "storage -> client | CONTENT Group header: true new: After: 0 New: 5",
347
357
  "client -> server | LOAD Group sessions: header/5",
348
- "storage -> client | CONTENT Map header: true new: After: 0 New: 73 expectContentUntil: header/200",
349
- "client -> server | LOAD Map sessions: header/200",
350
- "storage -> client | CONTENT Map header: true new: After: 73 New: 73",
351
- "storage -> client | CONTENT Map header: true new: After: 146 New: 54",
358
+ "storage -> client | CONTENT Map header: true new: After: 0 New: 41 expectContentUntil: header/100",
359
+ "client -> server | LOAD Map sessions: header/100",
360
+ "storage -> client | CONTENT Map header: true new: After: 41 New: 21",
361
+ "storage -> client | CONTENT Map header: true new: After: 62 New: 21",
362
+ "storage -> client | CONTENT Map header: true new: After: 83 New: 17",
352
363
  "server -> client | KNOWN Group sessions: header/5",
353
- "server -> client | KNOWN Map sessions: header/200",
364
+ "server -> client | KNOWN Map sessions: header/100",
354
365
  ]
355
366
  `);
356
367
  });
@@ -446,8 +457,8 @@ describe("client syncs with a server with storage", () => {
446
457
 
447
458
  const largeMap = group.createMap();
448
459
 
449
- // Generate a large amount of data (about 100MB)
450
- const dataSize = 1 * 200 * 1024;
460
+ // Generate a large amount of data
461
+ const dataSize = 1 * 10 * 1024;
451
462
  const chunkSize = 1024; // 1KB chunks
452
463
  const chunks = dataSize / chunkSize;
453
464
 
@@ -495,17 +506,58 @@ describe("client syncs with a server with storage", () => {
495
506
  "client -> storage | LOAD Map sessions: empty",
496
507
  "storage -> client | CONTENT Group header: true new: After: 0 New: 5",
497
508
  "client -> server | LOAD Group sessions: header/5",
498
- "storage -> client | CONTENT Map header: true new: After: 0 New: 73 expectContentUntil: header/200",
499
- "client -> server | LOAD Map sessions: header/200",
500
- "storage -> client | CONTENT Map header: true new: After: 73 New: 73",
501
- "storage -> client | CONTENT Map header: true new: After: 146 New: 54",
509
+ "storage -> client | CONTENT Map header: true new: After: 0 New: 1 expectContentUntil: header/10",
510
+ "client -> server | LOAD Map sessions: header/10",
511
+ "storage -> client | CONTENT Map header: true new: After: 1 New: 1",
512
+ "storage -> client | CONTENT Map header: true new: After: 2 New: 1",
513
+ "storage -> client | CONTENT Map header: true new: After: 3 New: 1",
514
+ "storage -> client | CONTENT Map header: true new: After: 4 New: 1",
515
+ "storage -> client | CONTENT Map header: true new: After: 5 New: 1",
516
+ "storage -> client | CONTENT Map header: true new: After: 6 New: 1",
517
+ "storage -> client | CONTENT Map header: true new: After: 7 New: 1",
518
+ "storage -> client | CONTENT Map header: true new: After: 8 New: 1",
519
+ "storage -> client | CONTENT Map header: true new: After: 9 New: 1",
520
+ "storage -> client | CONTENT Map header: true new: After: 10 New: 0",
502
521
  "server -> storage | LOAD Group sessions: empty",
503
522
  "storage -> server | CONTENT Group header: true new: After: 0 New: 5",
504
523
  "server -> client | KNOWN Group sessions: header/5",
505
524
  "server -> storage | LOAD Map sessions: empty",
506
- "storage -> server | CONTENT Map header: true new: After: 0 New: 73 expectContentUntil: header/200",
507
- "server -> client | KNOWN Map sessions: header/200",
525
+ "storage -> server | CONTENT Map header: true new: After: 0 New: 1 expectContentUntil: header/10",
526
+ "server -> client | KNOWN Map sessions: header/10",
508
527
  ]
509
528
  `);
510
529
  });
530
+
531
+ test("two storage instances open on the same file should not conflict with each other", async () => {
532
+ const client = setupTestNode();
533
+
534
+ client.connectToSyncServer({
535
+ syncServer: jazzCloud.node,
536
+ });
537
+ const dbPath = getDbPath();
538
+ await client.addAsyncStorage({
539
+ ourName: "client",
540
+ filename: dbPath,
541
+ });
542
+
543
+ const client2 = setupTestNode();
544
+ client2.connectToSyncServer({
545
+ syncServer: jazzCloud.node,
546
+ });
547
+ await client2.addAsyncStorage({
548
+ ourName: "client2",
549
+ filename: dbPath,
550
+ });
551
+
552
+ for (let i = 0; i < 10; i++) {
553
+ for (const node of [client.node, client2.node]) {
554
+ const group = node.createGroup();
555
+ const map = group.createMap();
556
+ map.set("hello", "world", "trusting");
557
+ }
558
+ }
559
+
560
+ await client.node.syncManager.waitForAllCoValuesSync();
561
+ await client2.node.syncManager.waitForAllCoValuesSync();
562
+ });
511
563
  });
@@ -95,7 +95,11 @@ export async function createAsyncStorage({
95
95
  filename,
96
96
  nodeName = "client",
97
97
  storageName = "storage",
98
- }: { filename?: string; nodeName: string; storageName: string }) {
98
+ }: {
99
+ filename?: string;
100
+ nodeName: string;
101
+ storageName: string;
102
+ }) {
99
103
  const storage = await getSqliteStorageAsync(
100
104
  new LibSQLSqliteAsyncDriver(getDbPath(filename)),
101
105
  );
@@ -113,7 +117,11 @@ export function createSyncStorage({
113
117
  filename,
114
118
  nodeName = "client",
115
119
  storageName = "storage",
116
- }: { filename?: string; nodeName: string; storageName: string }) {
120
+ }: {
121
+ filename?: string;
122
+ nodeName: string;
123
+ storageName: string;
124
+ }) {
117
125
  const storage = getSqliteStorage(
118
126
  new LibSQLSqliteSyncDriver(getDbPath(filename)),
119
127
  );
@@ -123,7 +131,7 @@ export function createSyncStorage({
123
131
  return storage;
124
132
  }
125
133
 
126
- function getDbPath(defaultDbPath?: string) {
134
+ export function getDbPath(defaultDbPath?: string) {
127
135
  const dbPath = defaultDbPath ?? join(tmpdir(), `test-${randomUUID()}.db`);
128
136
 
129
137
  if (!defaultDbPath) {
@@ -530,10 +530,13 @@ export function setupTestNode(
530
530
  return { storage };
531
531
  }
532
532
 
533
- async function addAsyncStorage(opts: { ourName?: string } = {}) {
533
+ async function addAsyncStorage(
534
+ opts: { ourName?: string; filename?: string } = {},
535
+ ) {
534
536
  const storage = await createAsyncStorage({
535
537
  nodeName: opts.ourName ?? "client",
536
538
  storageName: "storage",
539
+ filename: opts.filename,
537
540
  });
538
541
  node.setStorage(storage);
539
542