cojson 0.17.11 → 0.17.13

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 (97) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +17 -0
  3. package/dist/coValueCore/SessionMap.d.ts +4 -3
  4. package/dist/coValueCore/SessionMap.d.ts.map +1 -1
  5. package/dist/coValueCore/SessionMap.js +15 -4
  6. package/dist/coValueCore/SessionMap.js.map +1 -1
  7. package/dist/coValueCore/coValueCore.d.ts +2 -2
  8. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  9. package/dist/coValueCore/coValueCore.js +33 -32
  10. package/dist/coValueCore/coValueCore.js.map +1 -1
  11. package/dist/coValueCore/utils.d.ts.map +1 -1
  12. package/dist/coValueCore/utils.js.map +1 -1
  13. package/dist/coValueCore/verifiedState.d.ts +8 -2
  14. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  15. package/dist/coValueCore/verifiedState.js +7 -4
  16. package/dist/coValueCore/verifiedState.js.map +1 -1
  17. package/dist/crypto/PureJSCrypto.d.ts +4 -3
  18. package/dist/crypto/PureJSCrypto.d.ts.map +1 -1
  19. package/dist/crypto/PureJSCrypto.js +34 -2
  20. package/dist/crypto/PureJSCrypto.js.map +1 -1
  21. package/dist/crypto/WasmCrypto.d.ts +4 -3
  22. package/dist/crypto/WasmCrypto.d.ts.map +1 -1
  23. package/dist/crypto/WasmCrypto.js +10 -4
  24. package/dist/crypto/WasmCrypto.js.map +1 -1
  25. package/dist/crypto/crypto.d.ts +4 -3
  26. package/dist/crypto/crypto.d.ts.map +1 -1
  27. package/dist/localNode.js +1 -1
  28. package/dist/localNode.js.map +1 -1
  29. package/dist/queue/LocalTransactionsSyncQueue.d.ts +15 -0
  30. package/dist/queue/LocalTransactionsSyncQueue.d.ts.map +1 -1
  31. package/dist/queue/LocalTransactionsSyncQueue.js +25 -0
  32. package/dist/queue/LocalTransactionsSyncQueue.js.map +1 -1
  33. package/dist/sync.d.ts +10 -7
  34. package/dist/sync.d.ts.map +1 -1
  35. package/dist/sync.js +33 -31
  36. package/dist/sync.js.map +1 -1
  37. package/dist/tests/PureJSCrypto.test.js +43 -0
  38. package/dist/tests/PureJSCrypto.test.js.map +1 -1
  39. package/dist/tests/WasmCrypto.test.js +55 -0
  40. package/dist/tests/WasmCrypto.test.js.map +1 -1
  41. package/dist/tests/coList.test.js +13 -0
  42. package/dist/tests/coList.test.js.map +1 -1
  43. package/dist/tests/coMap.test.js +14 -0
  44. package/dist/tests/coMap.test.js.map +1 -1
  45. package/dist/tests/coPlainText.test.js +13 -0
  46. package/dist/tests/coPlainText.test.js.map +1 -1
  47. package/dist/tests/coStream.test.js +25 -0
  48. package/dist/tests/coStream.test.js.map +1 -1
  49. package/dist/tests/coValueCore.test.js +28 -2
  50. package/dist/tests/coValueCore.test.js.map +1 -1
  51. package/dist/tests/coreWasm.test.js +1 -1
  52. package/dist/tests/coreWasm.test.js.map +1 -1
  53. package/dist/tests/sync.known.test.d.ts +2 -0
  54. package/dist/tests/sync.known.test.d.ts.map +1 -0
  55. package/dist/tests/sync.known.test.js +78 -0
  56. package/dist/tests/sync.known.test.js.map +1 -0
  57. package/dist/tests/sync.sharding.test.d.ts +2 -0
  58. package/dist/tests/sync.sharding.test.d.ts.map +1 -0
  59. package/dist/tests/sync.sharding.test.js +85 -0
  60. package/dist/tests/sync.sharding.test.js.map +1 -0
  61. package/dist/tests/sync.storage.test.js +31 -1
  62. package/dist/tests/sync.storage.test.js.map +1 -1
  63. package/dist/tests/sync.storageAsync.test.js +1 -1
  64. package/dist/tests/sync.storageAsync.test.js.map +1 -1
  65. package/dist/tests/sync.test.js +31 -2
  66. package/dist/tests/sync.test.js.map +1 -1
  67. package/dist/tests/sync.upload.test.js +26 -0
  68. package/dist/tests/sync.upload.test.js.map +1 -1
  69. package/dist/tests/testUtils.d.ts.map +1 -1
  70. package/dist/tests/testUtils.js +3 -1
  71. package/dist/tests/testUtils.js.map +1 -1
  72. package/package.json +2 -2
  73. package/src/coValueCore/SessionMap.ts +24 -1
  74. package/src/coValueCore/coValueCore.ts +46 -41
  75. package/src/coValueCore/utils.ts +0 -1
  76. package/src/coValueCore/verifiedState.ts +14 -3
  77. package/src/crypto/PureJSCrypto.ts +49 -1
  78. package/src/crypto/WasmCrypto.ts +15 -1
  79. package/src/crypto/crypto.ts +7 -1
  80. package/src/localNode.ts +1 -1
  81. package/src/queue/LocalTransactionsSyncQueue.ts +32 -1
  82. package/src/sync.ts +50 -36
  83. package/src/tests/PureJSCrypto.test.ts +66 -0
  84. package/src/tests/WasmCrypto.test.ts +88 -0
  85. package/src/tests/coList.test.ts +19 -0
  86. package/src/tests/coMap.test.ts +21 -0
  87. package/src/tests/coPlainText.test.ts +18 -0
  88. package/src/tests/coStream.test.ts +36 -0
  89. package/src/tests/coValueCore.test.ts +49 -0
  90. package/src/tests/coreWasm.test.ts +1 -0
  91. package/src/tests/sync.known.test.ts +109 -0
  92. package/src/tests/sync.sharding.test.ts +119 -0
  93. package/src/tests/sync.storage.test.ts +43 -1
  94. package/src/tests/sync.storageAsync.test.ts +1 -1
  95. package/src/tests/sync.test.ts +49 -2
  96. package/src/tests/sync.upload.test.ts +35 -0
  97. package/src/tests/testUtils.ts +3 -1
@@ -0,0 +1,119 @@
1
+ import { beforeEach, describe, expect, test } from "vitest";
2
+ import { setCoValueLoadingRetryDelay } from "../config";
3
+ import {
4
+ SyncMessagesLog,
5
+ TEST_NODE_CONFIG,
6
+ blockMessageTypeOnOutgoingPeer,
7
+ connectedPeersWithMessagesTracking,
8
+ getSyncServerConnectedPeer,
9
+ loadCoValueOrFail,
10
+ setupTestAccount,
11
+ setupTestNode,
12
+ } from "./testUtils";
13
+ import { Peer } from "../exports";
14
+ import { ServerPeerSelector } from "../sync";
15
+
16
+ beforeEach(async () => {
17
+ // We want to simulate a real world communication that happens asynchronously
18
+ TEST_NODE_CONFIG.withAsyncPeers = true;
19
+
20
+ SyncMessagesLog.clear();
21
+ });
22
+
23
+ describe("sharding", () => {
24
+ test("server peers are not filtered by default", async () => {
25
+ const { node: client } = setupTestNode({
26
+ connected: false,
27
+ });
28
+ const group = client.createGroup();
29
+
30
+ const allPeers: Peer[] = [];
31
+ for (let i = 0; i < 5; i++) {
32
+ const syncServer = await setupTestAccount({ isSyncServer: true });
33
+
34
+ const { peer } = getSyncServerConnectedPeer({
35
+ peerId: client.getCurrentAgent().id,
36
+ syncServer: syncServer.node,
37
+ });
38
+
39
+ client.syncManager.addPeer(peer);
40
+ allPeers.push(peer);
41
+ }
42
+
43
+ const serverPeers = client.syncManager.getServerPeers(group.id);
44
+ expect(serverPeers.map((p) => p.id)).toEqual(allPeers.map((p) => p.id));
45
+ });
46
+
47
+ test("server peers are filtered when a serverPeerSelector is set", async () => {
48
+ const firstAlphabetical: ServerPeerSelector = (id, serverPeers) => {
49
+ return serverPeers.sort((a, b) => a.id.localeCompare(b.id)).slice(0, 1);
50
+ };
51
+ const { node: client } = setupTestNode({
52
+ connected: false,
53
+ });
54
+ client.syncManager.serverPeerSelector = firstAlphabetical;
55
+ const group = client.createGroup();
56
+
57
+ const allPeers: Peer[] = [];
58
+ for (let i = 0; i < 5; i++) {
59
+ const syncServer = await setupTestAccount({ isSyncServer: true });
60
+
61
+ const { peer } = getSyncServerConnectedPeer({
62
+ peerId: client.getCurrentAgent().id,
63
+ syncServer: syncServer.node,
64
+ });
65
+
66
+ client.syncManager.addPeer(peer);
67
+ allPeers.push(peer);
68
+ }
69
+
70
+ const serverPeers = client.syncManager.getServerPeers(group.id);
71
+ expect(serverPeers.length).toBe(1);
72
+ expect(serverPeers[0]!.id).toEqual(
73
+ allPeers.sort((a, b) => a.id.localeCompare(b.id))[0]!.id,
74
+ );
75
+ });
76
+
77
+ test("getPeers respects the serverPeerSelector", async () => {
78
+ const firstPeer: ServerPeerSelector = (id, serverPeers) => {
79
+ return serverPeers.slice(0, 1);
80
+ };
81
+ const { node: edge } = setupTestNode({
82
+ connected: false,
83
+ });
84
+ edge.syncManager.serverPeerSelector = firstPeer;
85
+
86
+ // Connect 2 clients to edge
87
+ for (let i = 0; i < 2; i++) {
88
+ const client = await setupTestAccount({});
89
+ const { peer1, peer2 } = connectedPeersWithMessagesTracking({
90
+ peer1: {
91
+ id: client.node.getCurrentAgent().id,
92
+ role: "client",
93
+ },
94
+ peer2: {
95
+ id: edge.getCurrentAgent().id,
96
+ role: "server",
97
+ },
98
+ });
99
+
100
+ edge.syncManager.addPeer(peer1);
101
+ }
102
+
103
+ // Connect edge to 3 core nodes
104
+ for (let i = 0; i < 3; i++) {
105
+ const syncServer = await setupTestAccount({ isSyncServer: true });
106
+
107
+ const { peer } = getSyncServerConnectedPeer({
108
+ peerId: edge.getCurrentAgent().id,
109
+ syncServer: syncServer.node,
110
+ });
111
+
112
+ edge.syncManager.addPeer(peer);
113
+ }
114
+
115
+ expect(edge.syncManager.getPeers("co_z12345").length).toBe(
116
+ 2 + 1, // 2 clients + 1 selected core
117
+ );
118
+ });
119
+ });
@@ -20,6 +20,7 @@ import {
20
20
  waitFor,
21
21
  } from "./testUtils";
22
22
  import { stableStringify } from "../jsonStringify";
23
+ import { determineValidTransactions } from "../permissions";
23
24
 
24
25
  // We want to simulate a real world communication that happens asynchronously
25
26
  TEST_NODE_CONFIG.withAsyncPeers = true;
@@ -151,6 +152,47 @@ describe("client with storage syncs with server", () => {
151
152
  `);
152
153
  });
153
154
 
155
+ test("persists meta information", async () => {
156
+ const client = setupTestNode();
157
+
158
+ const { storage } = client.addStorage();
159
+
160
+ const group = client.node.createGroup();
161
+ const map = group.createMap();
162
+ map.core.makeTransaction([], "trusting", {
163
+ meta: true,
164
+ });
165
+
166
+ await map.core.waitForSync();
167
+
168
+ client.restart();
169
+
170
+ client.addStorage({
171
+ storage,
172
+ });
173
+
174
+ const loadedValue = await loadCoValueOrFail(client.node, map.id);
175
+
176
+ const validTransactions = determineValidTransactions(loadedValue.core);
177
+
178
+ expect(validTransactions[0]?.tx.meta).toBe(`{"meta":true}`);
179
+
180
+ expect(
181
+ SyncMessagesLog.getMessages({
182
+ Group: group.core,
183
+ Map: map.core,
184
+ }),
185
+ ).toMatchInlineSnapshot(`
186
+ [
187
+ "client -> storage | CONTENT Group header: true new: After: 0 New: 3",
188
+ "client -> storage | CONTENT Map header: true new: After: 0 New: 1",
189
+ "client -> storage | LOAD Map sessions: empty",
190
+ "storage -> client | CONTENT Group header: true new: After: 0 New: 3",
191
+ "storage -> client | CONTENT Map header: true new: After: 0 New: 1",
192
+ ]
193
+ `);
194
+ });
195
+
154
196
  test("updating a coValue while offline", async () => {
155
197
  const client = setupTestNode();
156
198
 
@@ -164,7 +206,7 @@ describe("client with storage syncs with server", () => {
164
206
  const mapOnClient = await loadCoValueOrFail(client.node, map.id);
165
207
  expect(mapOnClient.get("hello")).toEqual("world");
166
208
 
167
- client.node.syncManager.getPeers()[0]?.gracefulShutdown();
209
+ client.node.syncManager.getPeers(map.id)[0]?.gracefulShutdown();
168
210
 
169
211
  SyncMessagesLog.clear();
170
212
  map.set("hello", "updated", "trusting");
@@ -156,7 +156,7 @@ describe("client with storage syncs with server", () => {
156
156
  const mapOnClient = await loadCoValueOrFail(client.node, map.id);
157
157
  expect(mapOnClient.get("hello")).toEqual("world");
158
158
 
159
- client.node.syncManager.getPeers()[0]?.gracefulShutdown();
159
+ client.node.syncManager.getPeers(map.id)[0]?.gracefulShutdown();
160
160
 
161
161
  SyncMessagesLog.clear();
162
162
  map.set("hello", "updated", "trusting");
@@ -599,8 +599,12 @@ describe("SyncManager - knownStates vs optimisticKnownStates", () => {
599
599
  // Wait for the full sync to complete
600
600
  await mapOnClient.core.waitForSync();
601
601
 
602
- const peerStateClient = client.syncManager.getPeers()[0]!;
603
- const peerStateJazzCloud = jazzCloud.node.syncManager.getPeers()[0]!;
602
+ const peerStateClient = client.syncManager.getPeers(
603
+ mapOnClient.core.id,
604
+ )[0]!;
605
+ const peerStateJazzCloud = jazzCloud.node.syncManager.getPeers(
606
+ mapOnClient.core.id,
607
+ )[0]!;
604
608
 
605
609
  // The optimisticKnownStates should be the same as the knownStates after the full sync is complete
606
610
  expect(
@@ -1115,3 +1119,46 @@ describe("SyncManager.handleSyncMessage", () => {
1115
1119
  expect(peerState.knownStates.has(group.id)).toBe(true);
1116
1120
  });
1117
1121
  });
1122
+
1123
+ describe("SyncManager.trackDirtyCoValues", () => {
1124
+ test("should track the dirty coValues", async () => {
1125
+ const node = createTestNode();
1126
+
1127
+ const tracking = node.syncManager.trackDirtyCoValues();
1128
+
1129
+ const group = node.createGroup();
1130
+ const map = group.createMap();
1131
+ map.set("key1", "value1", "trusting");
1132
+
1133
+ const trackedValues = tracking.done();
1134
+ expect(trackedValues.size).toBe(2);
1135
+ expect(trackedValues.has(map.id)).toBe(true);
1136
+ expect(trackedValues.has(group.id)).toBe(true);
1137
+ });
1138
+
1139
+ test("should track the dirty coValues only when active", async () => {
1140
+ const node = createTestNode();
1141
+
1142
+ const group = node.createGroup();
1143
+
1144
+ const tracking1 = node.syncManager.trackDirtyCoValues();
1145
+
1146
+ const map1 = group.createMap();
1147
+ map1.set("key1", "value1", "trusting");
1148
+
1149
+ const tracking2 = node.syncManager.trackDirtyCoValues();
1150
+
1151
+ const map2 = group.createMap();
1152
+ map2.set("key2", "value2", "trusting");
1153
+
1154
+ const tracked1 = tracking1.done();
1155
+
1156
+ const map3 = group.createMap();
1157
+ map3.set("key3", "value3", "trusting");
1158
+
1159
+ const tracked2 = tracking2.done();
1160
+
1161
+ expect(Array.from(tracked1)).toEqual([map1.id, map2.id]);
1162
+ expect(Array.from(tracked2)).toEqual([map2.id, map3.id]);
1163
+ });
1164
+ });
@@ -9,6 +9,7 @@ import {
9
9
  setupTestNode,
10
10
  waitFor,
11
11
  } from "./testUtils";
12
+ import { determineValidTransactions } from "../permissions";
12
13
 
13
14
  // We want to simulate a real world communication that happens asynchronously
14
15
  TEST_NODE_CONFIG.withAsyncPeers = true;
@@ -51,6 +52,40 @@ describe("client to server upload", () => {
51
52
  `);
52
53
  });
53
54
 
55
+ test("syncs meta information", async () => {
56
+ const client = setupTestNode({
57
+ connected: true,
58
+ });
59
+
60
+ const group = client.node.createGroup();
61
+ const map = group.createMap();
62
+ map.core.makeTransaction([], "trusting", {
63
+ meta: true,
64
+ });
65
+
66
+ await map.core.waitForSync();
67
+
68
+ const loadedValue = await loadCoValueOrFail(jazzCloud.node, map.id);
69
+
70
+ const validTransactions = determineValidTransactions(loadedValue.core);
71
+
72
+ expect(validTransactions[0]?.tx.meta).toBe(`{"meta":true}`);
73
+
74
+ expect(
75
+ SyncMessagesLog.getMessages({
76
+ Group: group.core,
77
+ Map: map.core,
78
+ }),
79
+ ).toMatchInlineSnapshot(`
80
+ [
81
+ "client -> server | CONTENT Group header: true new: After: 0 New: 3",
82
+ "client -> server | CONTENT Map header: true new: After: 0 New: 1",
83
+ "server -> client | KNOWN Group sessions: header/3",
84
+ "server -> client | KNOWN Map sessions: header/1",
85
+ ]
86
+ `);
87
+ });
88
+
54
89
  test("coValue with parent groups uploading", async () => {
55
90
  const client = setupTestNode({
56
91
  connected: true,
@@ -669,9 +669,11 @@ export async function setupTestAccount(
669
669
  addStorage,
670
670
  addAsyncStorage,
671
671
  disconnect: () => {
672
- ctx.node.syncManager.getPeers().forEach((peer) => {
672
+ const allPeers = ctx.node.syncManager.getPeers(ctx.accountID);
673
+ allPeers.forEach((peer) => {
673
674
  peer.gracefulShutdown();
674
675
  });
676
+ ctx.node.syncManager.peers = {};
675
677
  },
676
678
  };
677
679
  }