cojson 0.13.16 → 0.13.18

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 (168) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +16 -0
  3. package/dist/PeerState.d.ts +3 -0
  4. package/dist/PeerState.d.ts.map +1 -1
  5. package/dist/PeerState.js +9 -0
  6. package/dist/PeerState.js.map +1 -1
  7. package/dist/SyncStateManager.d.ts.map +1 -1
  8. package/dist/SyncStateManager.js +2 -3
  9. package/dist/SyncStateManager.js.map +1 -1
  10. package/dist/coValue.d.ts +6 -4
  11. package/dist/coValue.d.ts.map +1 -1
  12. package/dist/coValue.js +5 -4
  13. package/dist/coValue.js.map +1 -1
  14. package/dist/coValueCore/coValueCore.d.ts +143 -0
  15. package/dist/coValueCore/coValueCore.d.ts.map +1 -0
  16. package/dist/{coValueCore.js → coValueCore/coValueCore.js} +314 -246
  17. package/dist/coValueCore/coValueCore.js.map +1 -0
  18. package/dist/coValueCore/verifiedState.d.ts +65 -0
  19. package/dist/coValueCore/verifiedState.d.ts.map +1 -0
  20. package/dist/coValueCore/verifiedState.js +210 -0
  21. package/dist/coValueCore/verifiedState.js.map +1 -0
  22. package/dist/coValues/account.d.ts +8 -10
  23. package/dist/coValues/account.d.ts.map +1 -1
  24. package/dist/coValues/account.js +12 -13
  25. package/dist/coValues/account.js.map +1 -1
  26. package/dist/coValues/coList.d.ts +10 -6
  27. package/dist/coValues/coList.d.ts.map +1 -1
  28. package/dist/coValues/coList.js +41 -15
  29. package/dist/coValues/coList.js.map +1 -1
  30. package/dist/coValues/coMap.d.ts +4 -3
  31. package/dist/coValues/coMap.d.ts.map +1 -1
  32. package/dist/coValues/coMap.js +5 -3
  33. package/dist/coValues/coMap.js.map +1 -1
  34. package/dist/coValues/coPlainText.d.ts +2 -2
  35. package/dist/coValues/coPlainText.d.ts.map +1 -1
  36. package/dist/coValues/coPlainText.js +5 -5
  37. package/dist/coValues/coPlainText.js.map +1 -1
  38. package/dist/coValues/coStream.d.ts +5 -4
  39. package/dist/coValues/coStream.d.ts.map +1 -1
  40. package/dist/coValues/coStream.js +5 -3
  41. package/dist/coValues/coStream.js.map +1 -1
  42. package/dist/coValues/group.d.ts +7 -2
  43. package/dist/coValues/group.d.ts.map +1 -1
  44. package/dist/coValues/group.js +29 -26
  45. package/dist/coValues/group.js.map +1 -1
  46. package/dist/coreToCoValue.d.ts +4 -3
  47. package/dist/coreToCoValue.d.ts.map +1 -1
  48. package/dist/coreToCoValue.js +10 -14
  49. package/dist/coreToCoValue.js.map +1 -1
  50. package/dist/exports.d.ts +6 -5
  51. package/dist/exports.d.ts.map +1 -1
  52. package/dist/exports.js +3 -4
  53. package/dist/exports.js.map +1 -1
  54. package/dist/localNode.d.ts +30 -24
  55. package/dist/localNode.d.ts.map +1 -1
  56. package/dist/localNode.js +153 -177
  57. package/dist/localNode.js.map +1 -1
  58. package/dist/permissions.d.ts +2 -1
  59. package/dist/permissions.d.ts.map +1 -1
  60. package/dist/permissions.js +15 -11
  61. package/dist/permissions.js.map +1 -1
  62. package/dist/priority.d.ts +1 -1
  63. package/dist/priority.d.ts.map +1 -1
  64. package/dist/sync.d.ts +2 -2
  65. package/dist/sync.d.ts.map +1 -1
  66. package/dist/sync.js +86 -55
  67. package/dist/sync.js.map +1 -1
  68. package/dist/tests/coList.test.js +133 -13
  69. package/dist/tests/coList.test.js.map +1 -1
  70. package/dist/tests/coMap.test.js +43 -14
  71. package/dist/tests/coMap.test.js.map +1 -1
  72. package/dist/tests/coPlainText.test.js +9 -10
  73. package/dist/tests/coPlainText.test.js.map +1 -1
  74. package/dist/tests/coStream.test.js +49 -18
  75. package/dist/tests/coStream.test.js.map +1 -1
  76. package/dist/tests/coValueCore.test.js +22 -28
  77. package/dist/tests/coValueCore.test.js.map +1 -1
  78. package/dist/tests/coValueCoreLoadingState.test.d.ts +2 -0
  79. package/dist/tests/coValueCoreLoadingState.test.d.ts.map +1 -0
  80. package/dist/tests/coValueCoreLoadingState.test.js +227 -0
  81. package/dist/tests/coValueCoreLoadingState.test.js.map +1 -0
  82. package/dist/tests/group.test.js +42 -43
  83. package/dist/tests/group.test.js.map +1 -1
  84. package/dist/tests/messagesTestUtils.d.ts +2 -2
  85. package/dist/tests/messagesTestUtils.d.ts.map +1 -1
  86. package/dist/tests/messagesTestUtils.js +1 -1
  87. package/dist/tests/messagesTestUtils.js.map +1 -1
  88. package/dist/tests/permissions.test.js +224 -292
  89. package/dist/tests/permissions.test.js.map +1 -1
  90. package/dist/tests/priority.test.js +13 -14
  91. package/dist/tests/priority.test.js.map +1 -1
  92. package/dist/tests/sync.auth.test.d.ts +2 -0
  93. package/dist/tests/sync.auth.test.d.ts.map +1 -0
  94. package/dist/tests/sync.auth.test.js +141 -0
  95. package/dist/tests/sync.auth.test.js.map +1 -0
  96. package/dist/tests/sync.load.test.js +60 -2
  97. package/dist/tests/sync.load.test.js.map +1 -1
  98. package/dist/tests/sync.mesh.test.js +70 -10
  99. package/dist/tests/sync.mesh.test.js.map +1 -1
  100. package/dist/tests/sync.peerReconciliation.test.js +19 -19
  101. package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
  102. package/dist/tests/sync.storage.test.js +20 -13
  103. package/dist/tests/sync.storage.test.js.map +1 -1
  104. package/dist/tests/sync.test.js +32 -39
  105. package/dist/tests/sync.test.js.map +1 -1
  106. package/dist/tests/sync.upload.test.js +126 -37
  107. package/dist/tests/sync.upload.test.js.map +1 -1
  108. package/dist/tests/testUtils.d.ts +24 -15
  109. package/dist/tests/testUtils.d.ts.map +1 -1
  110. package/dist/tests/testUtils.js +88 -61
  111. package/dist/tests/testUtils.js.map +1 -1
  112. package/dist/typeUtils/expectGroup.js +1 -1
  113. package/dist/typeUtils/expectGroup.js.map +1 -1
  114. package/package.json +1 -1
  115. package/src/PeerState.ts +11 -0
  116. package/src/SyncStateManager.ts +2 -3
  117. package/src/coValue.ts +14 -8
  118. package/src/{coValueCore.ts → coValueCore/coValueCore.ts} +470 -413
  119. package/src/coValueCore/verifiedState.ts +376 -0
  120. package/src/coValues/account.ts +20 -25
  121. package/src/coValues/coList.ts +63 -29
  122. package/src/coValues/coMap.ts +13 -6
  123. package/src/coValues/coPlainText.ts +10 -8
  124. package/src/coValues/coStream.ts +12 -7
  125. package/src/coValues/group.ts +50 -28
  126. package/src/coreToCoValue.ts +14 -15
  127. package/src/exports.ts +9 -7
  128. package/src/localNode.ts +248 -283
  129. package/src/permissions.ts +18 -12
  130. package/src/priority.ts +1 -1
  131. package/src/sync.ts +96 -63
  132. package/src/tests/coList.test.ts +200 -12
  133. package/src/tests/coMap.test.ts +65 -14
  134. package/src/tests/coPlainText.test.ts +12 -9
  135. package/src/tests/coStream.test.ts +80 -17
  136. package/src/tests/coValueCore.test.ts +30 -27
  137. package/src/tests/coValueCoreLoadingState.test.ts +337 -0
  138. package/src/tests/group.test.ts +44 -68
  139. package/src/tests/messagesTestUtils.ts +3 -8
  140. package/src/tests/permissions.test.ts +283 -449
  141. package/src/tests/priority.test.ts +17 -13
  142. package/src/tests/sync.auth.test.ts +188 -0
  143. package/src/tests/sync.load.test.ts +79 -2
  144. package/src/tests/sync.mesh.test.ts +89 -9
  145. package/src/tests/sync.peerReconciliation.test.ts +25 -25
  146. package/src/tests/sync.storage.test.ts +20 -13
  147. package/src/tests/sync.test.ts +43 -43
  148. package/src/tests/sync.upload.test.ts +157 -37
  149. package/src/tests/testUtils.ts +120 -74
  150. package/src/typeUtils/expectGroup.ts +1 -1
  151. package/dist/CoValuesStore.d.ts +0 -14
  152. package/dist/CoValuesStore.d.ts.map +0 -1
  153. package/dist/CoValuesStore.js +0 -32
  154. package/dist/CoValuesStore.js.map +0 -1
  155. package/dist/coValueCore.d.ts +0 -141
  156. package/dist/coValueCore.d.ts.map +0 -1
  157. package/dist/coValueCore.js.map +0 -1
  158. package/dist/coValueState.d.ts +0 -34
  159. package/dist/coValueState.d.ts.map +0 -1
  160. package/dist/coValueState.js +0 -228
  161. package/dist/coValueState.js.map +0 -1
  162. package/dist/tests/coValueState.test.d.ts +0 -2
  163. package/dist/tests/coValueState.test.d.ts.map +0 -1
  164. package/dist/tests/coValueState.test.js +0 -344
  165. package/dist/tests/coValueState.test.js.map +0 -1
  166. package/src/CoValuesStore.ts +0 -41
  167. package/src/coValueState.ts +0 -300
  168. package/src/tests/coValueState.test.ts +0 -525
@@ -1,13 +1,24 @@
1
- import { expect, test } from "vitest";
1
+ import { beforeEach, expect, test } from "vitest";
2
2
  import { expectList } from "../coValue.js";
3
3
  import { WasmCrypto } from "../crypto/WasmCrypto.js";
4
4
  import { LocalNode } from "../localNode.js";
5
- import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
5
+ import { expectGroup } from "../typeUtils/expectGroup.js";
6
+ import {
7
+ loadCoValueOrFail,
8
+ nodeWithRandomAgentAndSessionID,
9
+ randomAgentAndSessionID,
10
+ setupTestNode,
11
+ waitFor,
12
+ } from "./testUtils.js";
6
13
 
7
14
  const Crypto = await WasmCrypto.create();
8
15
 
16
+ beforeEach(async () => {
17
+ setupTestNode({ isSyncServer: true });
18
+ });
19
+
9
20
  test("Empty CoList works", () => {
10
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
21
+ const node = nodeWithRandomAgentAndSessionID();
11
22
 
12
23
  const coValue = node.createCoValue({
13
24
  type: "colist",
@@ -23,7 +34,7 @@ test("Empty CoList works", () => {
23
34
  });
24
35
 
25
36
  test("Can append, prepend, delete and replace items in CoList", () => {
26
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
37
+ const node = nodeWithRandomAgentAndSessionID();
27
38
 
28
39
  const coValue = node.createCoValue({
29
40
  type: "colist",
@@ -54,7 +65,7 @@ test("Can append, prepend, delete and replace items in CoList", () => {
54
65
  });
55
66
 
56
67
  test("Push is equivalent to append after last item", () => {
57
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
68
+ const node = nodeWithRandomAgentAndSessionID();
58
69
 
59
70
  const coValue = node.createCoValue({
60
71
  type: "colist",
@@ -76,7 +87,7 @@ test("Push is equivalent to append after last item", () => {
76
87
  });
77
88
 
78
89
  test("appendItems add an array of items at the end of the list", () => {
79
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
90
+ const node = nodeWithRandomAgentAndSessionID();
80
91
 
81
92
  const coValue = node.createCoValue({
82
93
  type: "colist",
@@ -96,7 +107,7 @@ test("appendItems add an array of items at the end of the list", () => {
96
107
  });
97
108
 
98
109
  test("appendItems at index", () => {
99
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
110
+ const node = nodeWithRandomAgentAndSessionID();
100
111
 
101
112
  const coValue = node.createCoValue({
102
113
  type: "colist",
@@ -126,7 +137,7 @@ test("appendItems at index", () => {
126
137
  });
127
138
 
128
139
  test("appendItems at index", () => {
129
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
140
+ const node = nodeWithRandomAgentAndSessionID();
130
141
 
131
142
  const coValue = node.createCoValue({
132
143
  type: "colist",
@@ -148,7 +159,7 @@ test("appendItems at index", () => {
148
159
  });
149
160
 
150
161
  test("appendItems with negative index", () => {
151
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
162
+ const node = nodeWithRandomAgentAndSessionID();
152
163
 
153
164
  const coValue = node.createCoValue({
154
165
  type: "colist",
@@ -166,7 +177,7 @@ test("appendItems with negative index", () => {
166
177
  });
167
178
 
168
179
  test("Can push into empty list", () => {
169
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
180
+ const node = nodeWithRandomAgentAndSessionID();
170
181
 
171
182
  const coValue = node.createCoValue({
172
183
  type: "colist",
@@ -184,7 +195,7 @@ test("Can push into empty list", () => {
184
195
  });
185
196
 
186
197
  test("init the list correctly", () => {
187
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
198
+ const node = nodeWithRandomAgentAndSessionID();
188
199
 
189
200
  const group = node.createGroup();
190
201
 
@@ -204,7 +215,7 @@ test("init the list correctly", () => {
204
215
  });
205
216
 
206
217
  test("Items prepended to start appear with latest first", () => {
207
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
218
+ const node = nodeWithRandomAgentAndSessionID();
208
219
 
209
220
  const coValue = node.createCoValue({
210
221
  type: "colist",
@@ -221,3 +232,180 @@ test("Items prepended to start appear with latest first", () => {
221
232
 
222
233
  expect(content.toJSON()).toEqual(["third", "second", "first"]);
223
234
  });
235
+
236
+ test("mixing prepend and append", () => {
237
+ const node = nodeWithRandomAgentAndSessionID();
238
+
239
+ const coValue = node.createCoValue({
240
+ type: "colist",
241
+ ruleset: { type: "unsafeAllowAll" },
242
+ meta: null,
243
+ ...Crypto.createdNowUnique(),
244
+ });
245
+
246
+ const list = expectList(coValue.getCurrentContent());
247
+
248
+ list.append(2, undefined, "trusting");
249
+ list.prepend(1, undefined, "trusting");
250
+ list.append(3, undefined, "trusting");
251
+
252
+ expect(list.toJSON()).toEqual([1, 2, 3]);
253
+ });
254
+
255
+ test("Items appended to start", () => {
256
+ const node = nodeWithRandomAgentAndSessionID();
257
+
258
+ const coValue = node.createCoValue({
259
+ type: "colist",
260
+ ruleset: { type: "unsafeAllowAll" },
261
+ meta: null,
262
+ ...Crypto.createdNowUnique(),
263
+ });
264
+
265
+ const content = expectList(coValue.getCurrentContent());
266
+
267
+ content.append("first", 0, "trusting");
268
+ content.append("second", 0, "trusting");
269
+ content.append("third", 0, "trusting");
270
+
271
+ // This result is correct because "third" is appended after "first"
272
+ // Using the Array methods this would be the same as doing content.splice(1, 0, "third")
273
+ expect(content.toJSON()).toEqual(["first", "third", "second"]);
274
+ });
275
+
276
+ test("syncing appends with an older timestamp", async () => {
277
+ const client = setupTestNode({
278
+ connected: true,
279
+ });
280
+ const otherClient = setupTestNode({});
281
+
282
+ const otherClientConnection = otherClient.connectToSyncServer({
283
+ ourName: "otherClient",
284
+ });
285
+
286
+ const coValue = client.node.createCoValue({
287
+ type: "colist",
288
+ ruleset: { type: "unsafeAllowAll" },
289
+ meta: null,
290
+ ...Crypto.createdNowUnique(),
291
+ });
292
+
293
+ const list = expectList(coValue.getCurrentContent());
294
+
295
+ list.append(1, undefined, "trusting");
296
+ list.append(2, undefined, "trusting");
297
+
298
+ const listOnOtherClient = await loadCoValueOrFail(otherClient.node, list.id);
299
+
300
+ otherClientConnection.peerState.gracefulShutdown();
301
+
302
+ listOnOtherClient.append(3, undefined, "trusting");
303
+
304
+ await new Promise((resolve) => setTimeout(resolve, 50));
305
+
306
+ list.append(4, undefined, "trusting");
307
+
308
+ await new Promise((resolve) => setTimeout(resolve, 50));
309
+
310
+ listOnOtherClient.append(5, undefined, "trusting");
311
+
312
+ await new Promise((resolve) => setTimeout(resolve, 50));
313
+
314
+ list.append(6, undefined, "trusting");
315
+
316
+ otherClient.connectToSyncServer({
317
+ ourName: "otherClient",
318
+ });
319
+
320
+ await waitFor(() => {
321
+ expect(list.toJSON()).toEqual([1, 2, 4, 6, 3, 5]);
322
+ });
323
+
324
+ expect(listOnOtherClient.toJSON()).toEqual(list.toJSON());
325
+ });
326
+
327
+ test("syncing prepends with an older timestamp", async () => {
328
+ const client = setupTestNode({
329
+ connected: true,
330
+ });
331
+ const otherClient = setupTestNode({});
332
+
333
+ const otherClientConnection = otherClient.connectToSyncServer();
334
+
335
+ const coValue = client.node.createCoValue({
336
+ type: "colist",
337
+ ruleset: { type: "unsafeAllowAll" },
338
+ meta: null,
339
+ ...Crypto.createdNowUnique(),
340
+ });
341
+
342
+ const list = expectList(coValue.getCurrentContent());
343
+
344
+ list.prepend(1, undefined, "trusting");
345
+ list.prepend(2, undefined, "trusting");
346
+
347
+ const listOnOtherClient = await loadCoValueOrFail(otherClient.node, list.id);
348
+
349
+ otherClientConnection.peerState.gracefulShutdown();
350
+
351
+ listOnOtherClient.prepend(3, undefined, "trusting");
352
+
353
+ await new Promise((resolve) => setTimeout(resolve, 50));
354
+
355
+ list.prepend(4, undefined, "trusting");
356
+
357
+ await new Promise((resolve) => setTimeout(resolve, 50));
358
+
359
+ listOnOtherClient.prepend(5, undefined, "trusting");
360
+
361
+ await new Promise((resolve) => setTimeout(resolve, 50));
362
+
363
+ list.prepend(6, undefined, "trusting");
364
+
365
+ otherClient.connectToSyncServer();
366
+
367
+ await waitFor(() => {
368
+ expect(list.toJSON()).toEqual([6, 4, 5, 3, 2, 1]);
369
+ });
370
+
371
+ expect(listOnOtherClient.toJSON()).toEqual(list.toJSON());
372
+ });
373
+
374
+ test("totalValidTransactions should return the number of valid transactions processed", async () => {
375
+ const client = setupTestNode({
376
+ connected: true,
377
+ });
378
+ const otherClient = setupTestNode({});
379
+
380
+ const otherClientConnection = otherClient.connectToSyncServer();
381
+
382
+ const group = client.node.createGroup();
383
+ group.addMember("everyone", "reader");
384
+
385
+ const list = group.createList([1, 2]);
386
+
387
+ const listOnOtherClient = await loadCoValueOrFail(otherClient.node, list.id);
388
+
389
+ otherClientConnection.peerState.gracefulShutdown();
390
+
391
+ group.addMember("everyone", "writer");
392
+
393
+ await new Promise((resolve) => setTimeout(resolve, 50));
394
+
395
+ listOnOtherClient.append(3, undefined, "trusting");
396
+
397
+ expect(listOnOtherClient.toJSON()).toEqual([1, 2]);
398
+ expect(listOnOtherClient.totalValidTransactions).toEqual(1);
399
+
400
+ otherClient.connectToSyncServer();
401
+
402
+ await waitFor(() => {
403
+ expect(listOnOtherClient.core.getCurrentContent().toJSON()).toEqual([
404
+ 1, 2, 3,
405
+ ]);
406
+ });
407
+
408
+ expect(
409
+ listOnOtherClient.core.getCurrentContent().totalValidTransactions,
410
+ ).toEqual(2);
411
+ });
@@ -1,15 +1,24 @@
1
- import { expect, test } from "vitest";
1
+ import { beforeEach, expect, test } from "vitest";
2
2
  import { expectMap } from "../coValue.js";
3
3
  import { operationToEditEntry } from "../coValues/coMap.js";
4
4
  import { WasmCrypto } from "../crypto/WasmCrypto.js";
5
- import { LocalNode } from "../localNode.js";
6
5
  import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
7
- import { hotSleep, randomAnonymousAccountAndSessionID } from "./testUtils.js";
6
+ import {
7
+ hotSleep,
8
+ loadCoValueOrFail,
9
+ nodeWithRandomAgentAndSessionID,
10
+ setupTestNode,
11
+ waitFor,
12
+ } from "./testUtils.js";
8
13
 
9
14
  const Crypto = await WasmCrypto.create();
10
15
 
16
+ beforeEach(async () => {
17
+ setupTestNode({ isSyncServer: true });
18
+ });
19
+
11
20
  test("Empty CoMap works", () => {
12
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
21
+ const node = nodeWithRandomAgentAndSessionID();
13
22
 
14
23
  const coValue = node.createCoValue({
15
24
  type: "comap",
@@ -26,7 +35,7 @@ test("Empty CoMap works", () => {
26
35
  });
27
36
 
28
37
  test("Can insert and delete CoMap entries in edit()", () => {
29
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
38
+ const node = nodeWithRandomAgentAndSessionID();
30
39
 
31
40
  const coValue = node.createCoValue({
32
41
  type: "comap",
@@ -50,7 +59,7 @@ test("Can insert and delete CoMap entries in edit()", () => {
50
59
  });
51
60
 
52
61
  test("Can get CoMap entry values at different points in time", () => {
53
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
62
+ const node = nodeWithRandomAgentAndSessionID();
54
63
 
55
64
  const coValue = node.createCoValue({
56
65
  type: "comap",
@@ -100,7 +109,7 @@ test("Can get CoMap entry values at different points in time", () => {
100
109
  });
101
110
 
102
111
  test("Can get all historic values of key in CoMap", () => {
103
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
112
+ const node = nodeWithRandomAgentAndSessionID();
104
113
 
105
114
  const coValue = node.createCoValue({
106
115
  type: "comap",
@@ -124,25 +133,25 @@ test("Can get all historic values of key in CoMap", () => {
124
133
  expect([...content.editsAt("hello")]).toEqual([
125
134
  {
126
135
  tx: editA!.tx,
127
- by: node.account.id,
136
+ by: node.getCurrentAgent().id,
128
137
  value: "A",
129
138
  at: editA?.at,
130
139
  },
131
140
  {
132
141
  tx: editB!.tx,
133
- by: node.account.id,
142
+ by: node.getCurrentAgent().id,
134
143
  value: "B",
135
144
  at: editB?.at,
136
145
  },
137
146
  {
138
147
  tx: editDel!.tx,
139
- by: node.account.id,
148
+ by: node.getCurrentAgent().id,
140
149
  value: undefined,
141
150
  at: editDel?.at,
142
151
  },
143
152
  {
144
153
  tx: editC!.tx,
145
- by: node.account.id,
154
+ by: node.getCurrentAgent().id,
146
155
  value: "C",
147
156
  at: editC?.at,
148
157
  },
@@ -150,7 +159,7 @@ test("Can get all historic values of key in CoMap", () => {
150
159
  });
151
160
 
152
161
  test("Can get last tx ID for a key in CoMap", () => {
153
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
162
+ const node = nodeWithRandomAgentAndSessionID();
154
163
 
155
164
  const coValue = node.createCoValue({
156
165
  type: "comap",
@@ -167,7 +176,7 @@ test("Can get last tx ID for a key in CoMap", () => {
167
176
  content.set("hello", "A", "trusting");
168
177
  const sessionID = content.lastEditAt("hello")?.tx.sessionID;
169
178
  expect(sessionID && accountOrAgentIDfromSessionID(sessionID)).toEqual(
170
- node.account.id,
179
+ node.getCurrentAgent().id,
171
180
  );
172
181
  expect(content.lastEditAt("hello")?.tx.txIndex).toEqual(0);
173
182
  content.set("hello", "B", "trusting");
@@ -177,7 +186,7 @@ test("Can get last tx ID for a key in CoMap", () => {
177
186
  });
178
187
 
179
188
  test("Can set items in bulk with assign", () => {
180
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
189
+ const node = nodeWithRandomAgentAndSessionID();
181
190
 
182
191
  const coValue = node.createCoValue({
183
192
  type: "comap",
@@ -207,3 +216,45 @@ test("Can set items in bulk with assign", () => {
207
216
  key3: "assign3",
208
217
  });
209
218
  });
219
+
220
+ test("totalValidTransactions should return the number of valid transactions processed", async () => {
221
+ const client = setupTestNode({
222
+ connected: true,
223
+ });
224
+ const otherClient = setupTestNode({});
225
+
226
+ const otherClientConnection = otherClient.connectToSyncServer();
227
+
228
+ const group = client.node.createGroup();
229
+ group.addMember("everyone", "reader");
230
+
231
+ const map = group.createMap({ fromClient: true });
232
+
233
+ const mapOnOtherClient = await loadCoValueOrFail(otherClient.node, map.id);
234
+
235
+ otherClientConnection.peerState.gracefulShutdown();
236
+
237
+ group.addMember("everyone", "writer");
238
+
239
+ await new Promise((resolve) => setTimeout(resolve, 50));
240
+
241
+ mapOnOtherClient.set("fromOtherClient", true, "trusting");
242
+
243
+ expect(mapOnOtherClient.totalValidTransactions).toEqual(1);
244
+ expect(mapOnOtherClient.toJSON()).toEqual({
245
+ fromClient: true,
246
+ });
247
+
248
+ otherClient.connectToSyncServer();
249
+
250
+ await waitFor(() => {
251
+ expect(mapOnOtherClient.core.getCurrentContent().toJSON()).toEqual({
252
+ fromClient: true,
253
+ fromOtherClient: true,
254
+ });
255
+ });
256
+
257
+ expect(
258
+ mapOnOtherClient.core.getCurrentContent().totalValidTransactions,
259
+ ).toEqual(2);
260
+ });
@@ -2,7 +2,10 @@ import { afterEach, expect, test, vi } from "vitest";
2
2
  import { expectPlainText } from "../coValue.js";
3
3
  import { WasmCrypto } from "../crypto/WasmCrypto.js";
4
4
  import { LocalNode } from "../localNode.js";
5
- import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
5
+ import {
6
+ nodeWithRandomAgentAndSessionID,
7
+ randomAgentAndSessionID,
8
+ } from "./testUtils.js";
6
9
 
7
10
  const Crypto = await WasmCrypto.create();
8
11
 
@@ -13,7 +16,7 @@ test("should throw on creation if Intl.Segmenter is not available", () => {
13
16
  Segmenter: undefined,
14
17
  });
15
18
 
16
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
19
+ const node = nodeWithRandomAgentAndSessionID();
17
20
  const group = node.createGroup();
18
21
  expect(() => group.createPlainText()).toThrow(
19
22
  "Intl.Segmenter is not supported. Use a polyfill to get coPlainText support in Jazz. (eg. https://formatjs.github.io/docs/polyfills/intl-segmenter/)",
@@ -21,7 +24,7 @@ test("should throw on creation if Intl.Segmenter is not available", () => {
21
24
  });
22
25
 
23
26
  test("Empty CoPlainText works", () => {
24
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
27
+ const node = nodeWithRandomAgentAndSessionID();
25
28
 
26
29
  const coValue = node.createCoValue({
27
30
  type: "coplaintext",
@@ -37,7 +40,7 @@ test("Empty CoPlainText works", () => {
37
40
  });
38
41
 
39
42
  test("Can insert into empty CoPlainText", () => {
40
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
43
+ const node = nodeWithRandomAgentAndSessionID();
41
44
 
42
45
  const coValue = node.createCoValue({
43
46
  type: "coplaintext",
@@ -55,7 +58,7 @@ test("Can insert into empty CoPlainText", () => {
55
58
  });
56
59
 
57
60
  test("Can insert and delete in CoPlainText", () => {
58
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
61
+ const node = nodeWithRandomAgentAndSessionID();
59
62
 
60
63
  const coValue = node.createCoValue({
61
64
  type: "coplaintext",
@@ -88,7 +91,7 @@ test("Can insert and delete in CoPlainText", () => {
88
91
  });
89
92
 
90
93
  test("Multiple items inserted appear in correct order", () => {
91
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
94
+ const node = nodeWithRandomAgentAndSessionID();
92
95
 
93
96
  const coValue = node.createCoValue({
94
97
  type: "coplaintext",
@@ -109,7 +112,7 @@ test("Multiple items inserted appear in correct order", () => {
109
112
  });
110
113
 
111
114
  test("Items inserted at start appear with latest first", () => {
112
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
115
+ const node = nodeWithRandomAgentAndSessionID();
113
116
 
114
117
  const coValue = node.createCoValue({
115
118
  type: "coplaintext",
@@ -131,7 +134,7 @@ test("Items inserted at start appear with latest first", () => {
131
134
  });
132
135
 
133
136
  test("Handles different locales correctly", () => {
134
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
137
+ const node = nodeWithRandomAgentAndSessionID();
135
138
 
136
139
  // Test with explicit locale in meta
137
140
  const coValueJa = node.createCoValue({
@@ -175,7 +178,7 @@ test("Handles different locales correctly", () => {
175
178
  });
176
179
 
177
180
  test("insertBefore and insertAfter work as expected", () => {
178
- const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
181
+ const node = nodeWithRandomAgentAndSessionID();
179
182
  const coValue = node.createCoValue({
180
183
  type: "coplaintext",
181
184
  ruleset: { type: "unsafeAllowAll" },