cojson 0.15.7 → 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.
Files changed (218) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +12 -0
  3. package/dist/IncomingMessagesQueue.d.ts +27 -0
  4. package/dist/IncomingMessagesQueue.d.ts.map +1 -0
  5. package/dist/IncomingMessagesQueue.js +114 -0
  6. package/dist/IncomingMessagesQueue.js.map +1 -0
  7. package/dist/PeerState.d.ts +2 -10
  8. package/dist/PeerState.d.ts.map +1 -1
  9. package/dist/PeerState.js +9 -90
  10. package/dist/PeerState.js.map +1 -1
  11. package/dist/PriorityBasedMessageQueue.d.ts +2 -1
  12. package/dist/PriorityBasedMessageQueue.d.ts.map +1 -1
  13. package/dist/PriorityBasedMessageQueue.js +9 -6
  14. package/dist/PriorityBasedMessageQueue.js.map +1 -1
  15. package/dist/SyncStateManager.d.ts +1 -0
  16. package/dist/SyncStateManager.d.ts.map +1 -1
  17. package/dist/SyncStateManager.js +1 -1
  18. package/dist/SyncStateManager.js.map +1 -1
  19. package/dist/coValue.d.ts +1 -1
  20. package/dist/coValueCore/coValueCore.d.ts +9 -17
  21. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  22. package/dist/coValueCore/coValueCore.js +75 -50
  23. package/dist/coValueCore/coValueCore.js.map +1 -1
  24. package/dist/coValueCore/verifiedState.d.ts +10 -3
  25. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  26. package/dist/coValueCore/verifiedState.js +73 -14
  27. package/dist/coValueCore/verifiedState.js.map +1 -1
  28. package/dist/coValues/coMap.d.ts +3 -3
  29. package/dist/coValues/coStream.d.ts +2 -2
  30. package/dist/coValues/group.d.ts +1 -1
  31. package/dist/coValues/group.d.ts.map +1 -1
  32. package/dist/coValues/group.js +2 -4
  33. package/dist/coValues/group.js.map +1 -1
  34. package/dist/config.d.ts +19 -0
  35. package/dist/config.d.ts.map +1 -0
  36. package/dist/config.js +23 -0
  37. package/dist/config.js.map +1 -0
  38. package/dist/crypto/WasmCrypto.d.ts.map +1 -1
  39. package/dist/crypto/WasmCrypto.js +2 -1
  40. package/dist/crypto/WasmCrypto.js.map +1 -1
  41. package/dist/exports.d.ts +18 -7
  42. package/dist/exports.d.ts.map +1 -1
  43. package/dist/exports.js +11 -8
  44. package/dist/exports.js.map +1 -1
  45. package/dist/localNode.d.ts +8 -2
  46. package/dist/localNode.d.ts.map +1 -1
  47. package/dist/localNode.js +19 -12
  48. package/dist/localNode.js.map +1 -1
  49. package/dist/storage/StoreQueue.d.ts +15 -0
  50. package/dist/storage/StoreQueue.d.ts.map +1 -0
  51. package/dist/storage/StoreQueue.js +35 -0
  52. package/dist/storage/StoreQueue.js.map +1 -0
  53. package/dist/storage/index.d.ts +6 -0
  54. package/dist/storage/index.d.ts.map +1 -0
  55. package/dist/storage/index.js +6 -0
  56. package/dist/storage/index.js.map +1 -0
  57. package/dist/storage/knownState.d.ts +18 -0
  58. package/dist/storage/knownState.d.ts.map +1 -0
  59. package/dist/storage/knownState.js +63 -0
  60. package/dist/storage/knownState.js.map +1 -0
  61. package/dist/storage/sqlite/client.d.ts +37 -0
  62. package/dist/storage/sqlite/client.d.ts.map +1 -0
  63. package/dist/storage/sqlite/client.js +89 -0
  64. package/dist/storage/sqlite/client.js.map +1 -0
  65. package/dist/storage/sqlite/index.d.ts +5 -0
  66. package/dist/storage/sqlite/index.d.ts.map +1 -0
  67. package/dist/storage/sqlite/index.js +13 -0
  68. package/dist/storage/sqlite/index.js.map +1 -0
  69. package/dist/storage/sqlite/sqliteMigrations.d.ts +3 -0
  70. package/dist/storage/sqlite/sqliteMigrations.d.ts.map +1 -0
  71. package/dist/storage/sqlite/sqliteMigrations.js +44 -0
  72. package/dist/storage/sqlite/sqliteMigrations.js.map +1 -0
  73. package/dist/storage/sqlite/types.d.ts +8 -0
  74. package/dist/storage/sqlite/types.d.ts.map +1 -0
  75. package/dist/storage/sqlite/types.js +2 -0
  76. package/dist/storage/sqlite/types.js.map +1 -0
  77. package/dist/storage/sqliteAsync/client.d.ts +37 -0
  78. package/dist/storage/sqliteAsync/client.d.ts.map +1 -0
  79. package/dist/storage/sqliteAsync/client.js +88 -0
  80. package/dist/storage/sqliteAsync/client.js.map +1 -0
  81. package/dist/storage/sqliteAsync/index.d.ts +6 -0
  82. package/dist/storage/sqliteAsync/index.d.ts.map +1 -0
  83. package/dist/storage/sqliteAsync/index.js +15 -0
  84. package/dist/storage/sqliteAsync/index.js.map +1 -0
  85. package/dist/storage/sqliteAsync/types.d.ts +9 -0
  86. package/dist/storage/sqliteAsync/types.d.ts.map +1 -0
  87. package/dist/storage/sqliteAsync/types.js +2 -0
  88. package/dist/storage/sqliteAsync/types.js.map +1 -0
  89. package/dist/storage/storageAsync.d.ts +22 -0
  90. package/dist/storage/storageAsync.d.ts.map +1 -0
  91. package/dist/storage/storageAsync.js +214 -0
  92. package/dist/storage/storageAsync.js.map +1 -0
  93. package/dist/storage/storageSync.d.ts +21 -0
  94. package/dist/storage/storageSync.d.ts.map +1 -0
  95. package/dist/storage/storageSync.js +206 -0
  96. package/dist/storage/storageSync.js.map +1 -0
  97. package/dist/storage/syncUtils.d.ts +13 -0
  98. package/dist/storage/syncUtils.d.ts.map +1 -0
  99. package/dist/storage/syncUtils.js +25 -0
  100. package/dist/storage/syncUtils.js.map +1 -0
  101. package/dist/storage/types.d.ts +82 -0
  102. package/dist/storage/types.d.ts.map +1 -0
  103. package/dist/storage/types.js +2 -0
  104. package/dist/storage/types.js.map +1 -0
  105. package/dist/streamUtils.d.ts +13 -9
  106. package/dist/streamUtils.d.ts.map +1 -1
  107. package/dist/streamUtils.js +46 -13
  108. package/dist/streamUtils.js.map +1 -1
  109. package/dist/sync.d.ts +22 -14
  110. package/dist/sync.d.ts.map +1 -1
  111. package/dist/sync.js +143 -125
  112. package/dist/sync.js.map +1 -1
  113. package/dist/tests/IncomingMessagesQueue.test.d.ts +2 -0
  114. package/dist/tests/IncomingMessagesQueue.test.d.ts.map +1 -0
  115. package/dist/tests/IncomingMessagesQueue.test.js +437 -0
  116. package/dist/tests/IncomingMessagesQueue.test.js.map +1 -0
  117. package/dist/tests/PeerState.test.js +6 -94
  118. package/dist/tests/PeerState.test.js.map +1 -1
  119. package/dist/tests/PriorityBasedMessageQueue.test.js +14 -14
  120. package/dist/tests/PriorityBasedMessageQueue.test.js.map +1 -1
  121. package/dist/tests/StoreQueue.test.d.ts +2 -0
  122. package/dist/tests/StoreQueue.test.d.ts.map +1 -0
  123. package/dist/tests/StoreQueue.test.js +208 -0
  124. package/dist/tests/StoreQueue.test.js.map +1 -0
  125. package/dist/tests/SyncStateManager.test.js +3 -1
  126. package/dist/tests/SyncStateManager.test.js.map +1 -1
  127. package/dist/tests/account.test.js +9 -9
  128. package/dist/tests/account.test.js.map +1 -1
  129. package/dist/tests/coStream.test.js +1 -1
  130. package/dist/tests/coStream.test.js.map +1 -1
  131. package/dist/tests/coValueCore.test.js +208 -1
  132. package/dist/tests/coValueCore.test.js.map +1 -1
  133. package/dist/tests/coValueCoreLoadingState.test.js +2 -2
  134. package/dist/tests/coValueCoreLoadingState.test.js.map +1 -1
  135. package/dist/tests/group.addMember.test.js.map +1 -1
  136. package/dist/tests/group.removeMember.test.js +1 -1
  137. package/dist/tests/group.removeMember.test.js.map +1 -1
  138. package/dist/tests/messagesTestUtils.js +1 -1
  139. package/dist/tests/messagesTestUtils.js.map +1 -1
  140. package/dist/tests/sync.auth.test.js +23 -15
  141. package/dist/tests/sync.auth.test.js.map +1 -1
  142. package/dist/tests/sync.invite.test.js +10 -16
  143. package/dist/tests/sync.invite.test.js.map +1 -1
  144. package/dist/tests/sync.load.test.js +52 -50
  145. package/dist/tests/sync.load.test.js.map +1 -1
  146. package/dist/tests/sync.mesh.test.js +173 -56
  147. package/dist/tests/sync.mesh.test.js.map +1 -1
  148. package/dist/tests/sync.peerReconciliation.test.js +42 -32
  149. package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
  150. package/dist/tests/sync.storage.test.js +162 -62
  151. package/dist/tests/sync.storage.test.js.map +1 -1
  152. package/dist/tests/sync.storageAsync.test.d.ts +2 -0
  153. package/dist/tests/sync.storageAsync.test.d.ts.map +1 -0
  154. package/dist/tests/sync.storageAsync.test.js +361 -0
  155. package/dist/tests/sync.storageAsync.test.js.map +1 -0
  156. package/dist/tests/sync.test.js +16 -21
  157. package/dist/tests/sync.test.js.map +1 -1
  158. package/dist/tests/sync.upload.test.js +28 -25
  159. package/dist/tests/sync.upload.test.js.map +1 -1
  160. package/dist/tests/testStorage.d.ts +12 -0
  161. package/dist/tests/testStorage.d.ts.map +1 -0
  162. package/dist/tests/testStorage.js +151 -0
  163. package/dist/tests/testStorage.js.map +1 -0
  164. package/dist/tests/testUtils.d.ts +20 -15
  165. package/dist/tests/testUtils.d.ts.map +1 -1
  166. package/dist/tests/testUtils.js +79 -45
  167. package/dist/tests/testUtils.js.map +1 -1
  168. package/package.json +2 -2
  169. package/src/IncomingMessagesQueue.ts +142 -0
  170. package/src/PeerState.ts +11 -110
  171. package/src/PriorityBasedMessageQueue.ts +13 -5
  172. package/src/SyncStateManager.ts +1 -1
  173. package/src/coValueCore/coValueCore.ts +100 -66
  174. package/src/coValueCore/verifiedState.ts +91 -21
  175. package/src/coValues/group.ts +2 -4
  176. package/src/config.ts +26 -0
  177. package/src/crypto/WasmCrypto.ts +3 -1
  178. package/src/exports.ts +20 -27
  179. package/src/localNode.ts +27 -12
  180. package/src/storage/StoreQueue.ts +56 -0
  181. package/src/storage/index.ts +5 -0
  182. package/src/storage/knownState.ts +88 -0
  183. package/src/storage/sqlite/client.ts +180 -0
  184. package/src/storage/sqlite/index.ts +19 -0
  185. package/src/storage/sqlite/sqliteMigrations.ts +44 -0
  186. package/src/storage/sqlite/types.ts +7 -0
  187. package/src/storage/sqliteAsync/client.ts +179 -0
  188. package/src/storage/sqliteAsync/index.ts +25 -0
  189. package/src/storage/sqliteAsync/types.ts +8 -0
  190. package/src/storage/storageAsync.ts +367 -0
  191. package/src/storage/storageSync.ts +343 -0
  192. package/src/storage/syncUtils.ts +50 -0
  193. package/src/storage/types.ts +162 -0
  194. package/src/streamUtils.ts +61 -19
  195. package/src/sync.ts +191 -160
  196. package/src/tests/IncomingMessagesQueue.test.ts +626 -0
  197. package/src/tests/PeerState.test.ts +6 -118
  198. package/src/tests/PriorityBasedMessageQueue.test.ts +18 -14
  199. package/src/tests/StoreQueue.test.ts +283 -0
  200. package/src/tests/SyncStateManager.test.ts +4 -1
  201. package/src/tests/account.test.ts +11 -12
  202. package/src/tests/coStream.test.ts +1 -3
  203. package/src/tests/coValueCore.test.ts +270 -1
  204. package/src/tests/coValueCoreLoadingState.test.ts +2 -2
  205. package/src/tests/group.addMember.test.ts +1 -0
  206. package/src/tests/group.removeMember.test.ts +2 -8
  207. package/src/tests/messagesTestUtils.ts +2 -2
  208. package/src/tests/sync.auth.test.ts +24 -14
  209. package/src/tests/sync.invite.test.ts +11 -17
  210. package/src/tests/sync.load.test.ts +53 -49
  211. package/src/tests/sync.mesh.test.ts +198 -56
  212. package/src/tests/sync.peerReconciliation.test.ts +44 -34
  213. package/src/tests/sync.storage.test.ts +231 -64
  214. package/src/tests/sync.storageAsync.test.ts +486 -0
  215. package/src/tests/sync.test.ts +17 -23
  216. package/src/tests/sync.upload.test.ts +29 -24
  217. package/src/tests/testStorage.ts +216 -0
  218. package/src/tests/testUtils.ts +89 -54
@@ -1,11 +1,29 @@
1
- import { beforeEach, describe, expect, test } from "vitest";
2
-
3
- import { SyncMessagesLog, loadCoValueOrFail, setupTestNode } from "./testUtils";
1
+ import {
2
+ assert,
3
+ afterEach,
4
+ beforeEach,
5
+ describe,
6
+ expect,
7
+ test,
8
+ vi,
9
+ } from "vitest";
10
+
11
+ import { emptyKnownState } from "../exports";
12
+ import {
13
+ SyncMessagesLog,
14
+ TEST_NODE_CONFIG,
15
+ createTestMetricReader,
16
+ loadCoValueOrFail,
17
+ setupTestNode,
18
+ tearDownTestMetricReader,
19
+ waitFor,
20
+ } from "./testUtils";
21
+
22
+ // We want to simulate a real world communication that happens asynchronously
23
+ TEST_NODE_CONFIG.withAsyncPeers = true;
4
24
 
5
25
  describe("client with storage syncs with server", () => {
6
- let jazzCloud = setupTestNode({
7
- isSyncServer: true,
8
- });
26
+ let jazzCloud: ReturnType<typeof setupTestNode>;
9
27
 
10
28
  beforeEach(async () => {
11
29
  SyncMessagesLog.clear();
@@ -18,7 +36,7 @@ describe("client with storage syncs with server", () => {
18
36
  const client = setupTestNode();
19
37
 
20
38
  client.connectToSyncServer();
21
- client.addStoragePeer();
39
+ client.addStorage();
22
40
 
23
41
  const group = jazzCloud.node.createGroup();
24
42
  const map = group.createMap();
@@ -38,15 +56,11 @@ describe("client with storage syncs with server", () => {
38
56
  "storage -> client | KNOWN Map sessions: empty",
39
57
  "client -> server | LOAD Map sessions: empty",
40
58
  "server -> client | CONTENT Group header: true new: After: 0 New: 3",
41
- "client -> server | KNOWN Group sessions: header/3",
42
- "client -> storage | LOAD Group sessions: header/3",
43
59
  "server -> client | CONTENT Map header: true new: After: 0 New: 1",
44
- "storage -> client | KNOWN Group sessions: empty",
45
- "client -> server | KNOWN Map sessions: header/1",
60
+ "client -> server | KNOWN Group sessions: header/3",
46
61
  "client -> storage | CONTENT Group header: true new: After: 0 New: 3",
47
- "storage -> client | KNOWN Group sessions: header/3",
62
+ "client -> server | KNOWN Map sessions: header/1",
48
63
  "client -> storage | CONTENT Map header: true new: After: 0 New: 1",
49
- "storage -> client | KNOWN Map sessions: header/1",
50
64
  ]
51
65
  `);
52
66
  });
@@ -55,15 +69,24 @@ describe("client with storage syncs with server", () => {
55
69
  const client = setupTestNode();
56
70
 
57
71
  client.connectToSyncServer();
58
- const { storage } = client.addStoragePeer();
59
-
60
- // biome-ignore lint/suspicious/noExplicitAny: Super ugly, might have unintended side effects
61
- (storage as any).coValues = (jazzCloud.node as any).coValues;
72
+ const { storage } = client.addStorage();
62
73
 
63
74
  const group = jazzCloud.node.createGroup();
64
75
  const map = group.createMap();
65
76
  map.set("hello", "world", "trusting");
66
77
 
78
+ await loadCoValueOrFail(client.node, map.id);
79
+
80
+ client.restart();
81
+
82
+ client.connectToSyncServer();
83
+ client.addStorage({
84
+ ourName: "client",
85
+ storage,
86
+ });
87
+
88
+ SyncMessagesLog.clear();
89
+
67
90
  const mapOnClient = await loadCoValueOrFail(client.node, map.id);
68
91
  expect(mapOnClient.get("hello")).toEqual("world");
69
92
 
@@ -76,13 +99,9 @@ describe("client with storage syncs with server", () => {
76
99
  [
77
100
  "client -> storage | LOAD Map sessions: empty",
78
101
  "storage -> client | CONTENT Group header: true new: After: 0 New: 3",
79
- "client -> storage | KNOWN Group sessions: header/3",
80
102
  "client -> server | LOAD Group sessions: header/3",
81
103
  "storage -> client | CONTENT Map header: true new: After: 0 New: 1",
82
- "server -> client | KNOWN Group sessions: header/3",
83
- "client -> storage | KNOWN Map sessions: header/1",
84
104
  "client -> server | LOAD Map sessions: header/1",
85
- "server -> client | KNOWN Map sessions: header/1",
86
105
  ]
87
106
  `);
88
107
  });
@@ -91,7 +110,7 @@ describe("client with storage syncs with server", () => {
91
110
  const client = setupTestNode();
92
111
 
93
112
  client.connectToSyncServer();
94
- client.addStoragePeer();
113
+ client.addStorage();
95
114
 
96
115
  const group = jazzCloud.node.createGroup();
97
116
  const parentGroup = jazzCloud.node.createGroup();
@@ -117,21 +136,14 @@ describe("client with storage syncs with server", () => {
117
136
  "storage -> client | KNOWN Map sessions: empty",
118
137
  "client -> server | LOAD Map sessions: empty",
119
138
  "server -> client | CONTENT ParentGroup header: true new: After: 0 New: 6",
120
- "client -> server | KNOWN ParentGroup sessions: header/6",
121
- "client -> storage | LOAD ParentGroup sessions: header/6",
122
139
  "server -> client | CONTENT Group header: true new: After: 0 New: 5",
123
- "storage -> client | KNOWN ParentGroup sessions: empty",
124
- "client -> server | KNOWN Group sessions: header/5",
125
- "client -> storage | LOAD Group sessions: header/5",
126
140
  "server -> client | CONTENT Map header: true new: After: 0 New: 1",
127
- "storage -> client | KNOWN Group sessions: empty",
141
+ "client -> server | KNOWN ParentGroup sessions: header/6",
128
142
  "client -> storage | CONTENT ParentGroup header: true new: After: 0 New: 6",
129
- "client -> server | KNOWN Map sessions: header/1",
130
- "storage -> client | KNOWN ParentGroup sessions: header/6",
143
+ "client -> server | KNOWN Group sessions: header/5",
131
144
  "client -> storage | CONTENT Group header: true new: After: 0 New: 5",
132
- "storage -> client | KNOWN Group sessions: header/5",
145
+ "client -> server | KNOWN Map sessions: header/1",
133
146
  "client -> storage | CONTENT Map header: true new: After: 0 New: 1",
134
- "storage -> client | KNOWN Map sessions: header/1",
135
147
  ]
136
148
  `);
137
149
  });
@@ -140,7 +152,7 @@ describe("client with storage syncs with server", () => {
140
152
  const client = setupTestNode();
141
153
 
142
154
  client.connectToSyncServer();
143
- client.addStoragePeer();
155
+ client.addStorage();
144
156
 
145
157
  const group = jazzCloud.node.createGroup();
146
158
  const map = group.createMap();
@@ -168,34 +180,40 @@ describe("client with storage syncs with server", () => {
168
180
  ).toMatchInlineSnapshot(`
169
181
  [
170
182
  "client -> server | LOAD Group sessions: header/3",
171
- "server -> client | KNOWN Group sessions: header/3",
172
183
  "client -> server | LOAD Map sessions: header/1",
184
+ "server -> client | CONTENT Group header: true new: After: 0 New: 3",
185
+ "server -> client | CONTENT Map header: true new: After: 0 New: 2",
173
186
  "server -> client | CONTENT Map header: false new: After: 1 New: 1",
187
+ "client -> server | KNOWN Group sessions: header/3",
188
+ "client -> storage | CONTENT Group header: true new: After: 0 New: 3",
174
189
  "client -> server | KNOWN Map sessions: header/2",
175
- "client -> storage | CONTENT Map header: false new: After: 1 New: 1",
176
- "server -> client | CONTENT Map header: false new: After: 1 New: 1",
177
- "storage -> client | KNOWN Map sessions: header/2",
190
+ "client -> storage | CONTENT Map header: true new: After: 0 New: 2",
178
191
  "client -> server | KNOWN Map sessions: header/2",
192
+ "client -> storage | CONTENT Map header: false new: After: 1 New: 1",
179
193
  ]
180
194
  `);
181
195
  });
182
196
  });
183
197
 
184
198
  describe("client syncs with a server with storage", () => {
185
- let jazzCloud = setupTestNode({
186
- isSyncServer: true,
187
- });
199
+ let jazzCloud: ReturnType<typeof setupTestNode>;
200
+ let metricReader: ReturnType<typeof createTestMetricReader>;
188
201
 
189
202
  beforeEach(async () => {
190
203
  SyncMessagesLog.clear();
204
+ metricReader = createTestMetricReader();
191
205
  jazzCloud = setupTestNode({
192
206
  isSyncServer: true,
193
207
  });
194
- jazzCloud.addStoragePeer({
208
+ jazzCloud.addStorage({
195
209
  ourName: "server",
196
210
  });
197
211
  });
198
212
 
213
+ afterEach(() => {
214
+ tearDownTestMetricReader();
215
+ });
216
+
199
217
  test("coValue uploading", async () => {
200
218
  const client = setupTestNode();
201
219
 
@@ -218,53 +236,202 @@ describe("client syncs with a server with storage", () => {
218
236
  ).toMatchInlineSnapshot(`
219
237
  [
220
238
  "client -> server | CONTENT Group header: true new: After: 0 New: 3",
221
- "server -> client | KNOWN Group sessions: header/3",
222
- "server -> storage | LOAD Group sessions: header/3",
223
239
  "client -> server | CONTENT Map header: true new: After: 0 New: 1",
224
- "storage -> server | KNOWN Group sessions: empty",
225
- "server -> client | KNOWN Map sessions: header/1",
226
- "server -> storage | LOAD Map sessions: header/1",
227
- "storage -> server | KNOWN Map sessions: empty",
240
+ "server -> client | KNOWN Group sessions: header/3",
228
241
  "server -> storage | CONTENT Group header: true new: After: 0 New: 3",
229
- "storage -> server | KNOWN Group sessions: header/3",
242
+ "server -> client | KNOWN Map sessions: header/1",
230
243
  "server -> storage | CONTENT Map header: true new: After: 0 New: 1",
231
- "storage -> server | KNOWN Map sessions: header/1",
232
244
  ]
233
245
  `);
234
246
  });
235
247
 
236
- test.skip("server restarts", async () => {
248
+ test("loading a large coValue from storage", async () => {
237
249
  const client = setupTestNode();
238
250
 
239
- client.addStoragePeer();
251
+ client.connectToSyncServer({
252
+ syncServer: jazzCloud.node,
253
+ });
254
+
255
+ const { storage } = client.addStorage({
256
+ ourName: "client",
257
+ });
240
258
 
241
259
  const group = client.node.createGroup();
242
- const map = group.createMap();
243
- map.set("hello", "world", "trusting");
260
+ group.addMember("everyone", "writer");
244
261
 
245
- await map.core.waitForSync();
262
+ const largeMap = group.createMap();
246
263
 
247
- jazzCloud.restart();
264
+ // Generate a large amount of data (about 100MB)
265
+ const dataSize = 1 * 200 * 1024;
266
+ const chunkSize = 1024; // 1KB chunks
267
+ const chunks = dataSize / chunkSize;
268
+
269
+ const value = Buffer.alloc(chunkSize, `value$`).toString("base64");
270
+
271
+ for (let i = 0; i < chunks; i++) {
272
+ const key = `key${i}`;
273
+ largeMap.set(key, value, "trusting");
274
+ }
275
+
276
+ await largeMap.core.waitForSync();
277
+
278
+ // Test streaming counter during initial sync
279
+ // The streaming counter should be 0 after the sync is complete
280
+ const streamingCounterAfterSync = await metricReader.getMetricValue(
281
+ "jazz.storage.streaming",
282
+ );
283
+ expect(streamingCounterAfterSync).toBe(0);
284
+
285
+ expect(
286
+ SyncMessagesLog.getMessages({
287
+ Group: group.core,
288
+ Map: largeMap.core,
289
+ }),
290
+ ).toMatchInlineSnapshot(`
291
+ [
292
+ "client -> storage | CONTENT Group header: true new: After: 0 New: 5",
293
+ "client -> server | CONTENT Group header: true new: After: 0 New: 5",
294
+ "client -> storage | CONTENT Map header: true new: expectContentUntil: header/200",
295
+ "client -> storage | CONTENT Map header: false new: After: 0 New: 73",
296
+ "client -> storage | CONTENT Map header: false new: After: 73 New: 73",
297
+ "client -> storage | CONTENT Map header: false new: After: 146 New: 54",
298
+ "client -> server | CONTENT Map header: true new: expectContentUntil: header/200",
299
+ "client -> server | CONTENT Map header: false new: After: 0 New: 73",
300
+ "client -> server | CONTENT Map header: false new: After: 73 New: 73",
301
+ "client -> server | CONTENT Map header: false new: After: 146 New: 54",
302
+ "server -> client | KNOWN Group sessions: header/5",
303
+ "server -> storage | CONTENT Group header: true new: After: 0 New: 5",
304
+ "server -> client | KNOWN Map sessions: header/0",
305
+ "server -> storage | CONTENT Map header: true new: expectContentUntil: header/200",
306
+ "server -> client | KNOWN Map sessions: header/73",
307
+ "server -> storage | CONTENT Map header: false new: After: 0 New: 73",
308
+ "server -> client | KNOWN Map sessions: header/146",
309
+ "server -> storage | CONTENT Map header: false new: After: 73 New: 73",
310
+ "server -> client | KNOWN Map sessions: header/200",
311
+ "server -> storage | CONTENT Map header: false new: After: 146 New: 54",
312
+ ]
313
+ `);
248
314
 
249
315
  SyncMessagesLog.clear();
250
- client.addStoragePeer();
251
316
 
252
- const mapOnServer = await loadCoValueOrFail(jazzCloud.node, map.id);
253
- expect(mapOnServer.get("hello")).toEqual("world");
317
+ client.restart();
318
+
319
+ client.connectToSyncServer({
320
+ ourName: "client",
321
+ syncServer: jazzCloud.node,
322
+ });
323
+
324
+ client.addStorage({
325
+ ourName: "client",
326
+ storage,
327
+ });
328
+
329
+ // Test streaming counter before loading the large coValue
330
+ const streamingCounterBeforeLoad = await metricReader.getMetricValue(
331
+ "jazz.storage.streaming",
332
+ );
333
+ expect(streamingCounterBeforeLoad).toBe(0);
334
+
335
+ const promise = loadCoValueOrFail(client.node, largeMap.id);
336
+
337
+ // Test streaming counter during loading (should be 1 during streaming)
338
+ const streamingCounterDuringLoad = await metricReader.getMetricValue(
339
+ "jazz.storage.streaming",
340
+ );
341
+ expect(streamingCounterDuringLoad).toBe(1);
342
+
343
+ const mapOnClient2 = await promise;
344
+ await mapOnClient2.core.waitForSync();
345
+
346
+ // Test streaming counter after loading is complete (should be 0)
347
+ await waitFor(async () => {
348
+ const streamingCounterAfterLoad = await metricReader.getMetricValue(
349
+ "jazz.storage.streaming",
350
+ );
351
+ expect(streamingCounterAfterLoad).toBe(0);
352
+ });
254
353
 
255
354
  expect(
256
355
  SyncMessagesLog.getMessages({
257
356
  Group: group.core,
258
- Map: map.core,
357
+ Map: largeMap.core,
259
358
  }),
260
359
  ).toMatchInlineSnapshot(`
261
360
  [
262
- "server -> storage | LOAD Group sessions: header/3",
263
- "storage -> server | KNOWN Map sessions: header/1",
264
- "storage -> server | KNOWN Group sessions: empty",
265
- "server -> storage | LOAD Map sessions: header/1",
266
- "storage -> server | KNOWN Map sessions: empty",
361
+ "client -> storage | LOAD Map sessions: empty",
362
+ "storage -> client | CONTENT Group header: true new: After: 0 New: 5",
363
+ "client -> server | LOAD Group sessions: header/5",
364
+ "storage -> client | CONTENT Map header: true new: After: 0 New: 73 expectContentUntil: header/200",
365
+ "client -> server | LOAD Map sessions: header/200",
366
+ "server -> client | KNOWN Group sessions: header/5",
367
+ "server -> client | KNOWN Map sessions: header/200",
368
+ "storage -> client | CONTENT Map header: true new: After: 73 New: 73",
369
+ "storage -> client | CONTENT Map header: true new: After: 146 New: 54",
267
370
  ]
268
371
  `);
269
372
  });
373
+
374
+ test("storing stale data should not compromise the signatures", async () => {
375
+ const client = setupTestNode();
376
+
377
+ client.connectToSyncServer({
378
+ syncServer: jazzCloud.node,
379
+ });
380
+
381
+ const { storage } = client.addStorage({
382
+ ourName: "client",
383
+ });
384
+
385
+ const group = client.node.createGroup();
386
+ group.addMember("everyone", "writer");
387
+
388
+ const largeMap = group.createMap();
389
+
390
+ // Generate a large amount of data (about 100MB)
391
+ const dataSize = 1 * 200 * 1024;
392
+ const chunkSize = 1024; // 1KB chunks
393
+ const chunks = dataSize / chunkSize;
394
+
395
+ const value = Buffer.alloc(chunkSize, `value$`).toString("base64");
396
+
397
+ for (let i = 0; i < chunks; i++) {
398
+ const key = `key${i}`;
399
+ largeMap.set(key, value, "trusting");
400
+ }
401
+
402
+ await largeMap.core.waitForSync();
403
+
404
+ const newContentChunks = largeMap.core.verified.newContentSince(
405
+ emptyKnownState(largeMap.id),
406
+ );
407
+
408
+ assert(newContentChunks);
409
+ assert(newContentChunks.length > 1);
410
+
411
+ const correctionSpy = vi.fn();
412
+
413
+ client.node.storage?.store(newContentChunks.slice(1, 2), correctionSpy);
414
+
415
+ expect(correctionSpy).not.toHaveBeenCalled();
416
+
417
+ client.restart();
418
+
419
+ client.connectToSyncServer({
420
+ ourName: "client",
421
+ syncServer: jazzCloud.node,
422
+ });
423
+
424
+ client.addStorage({
425
+ ourName: "client",
426
+ storage,
427
+ });
428
+
429
+ const mapOnClient2 = await loadCoValueOrFail(client.node, largeMap.id);
430
+
431
+ await waitFor(async () => {
432
+ expect(mapOnClient2.core.knownState()).toEqual(
433
+ largeMap.core.knownState(),
434
+ );
435
+ });
436
+ });
270
437
  });