cojson 0.18.27 → 0.18.28

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 (60) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +10 -0
  3. package/dist/coValueCore/branching.d.ts +2 -1
  4. package/dist/coValueCore/branching.d.ts.map +1 -1
  5. package/dist/coValueCore/branching.js +20 -2
  6. package/dist/coValueCore/branching.js.map +1 -1
  7. package/dist/coValueCore/coValueCore.d.ts +26 -23
  8. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  9. package/dist/coValueCore/coValueCore.js +161 -123
  10. package/dist/coValueCore/coValueCore.js.map +1 -1
  11. package/dist/coValueCore/decryptTransactionChangesAndMeta.d.ts +3 -0
  12. package/dist/coValueCore/decryptTransactionChangesAndMeta.d.ts.map +1 -0
  13. package/dist/coValueCore/decryptTransactionChangesAndMeta.js +34 -0
  14. package/dist/coValueCore/decryptTransactionChangesAndMeta.js.map +1 -0
  15. package/dist/localNode.js +1 -1
  16. package/dist/localNode.js.map +1 -1
  17. package/dist/permissions.d.ts.map +1 -1
  18. package/dist/permissions.js +18 -20
  19. package/dist/permissions.js.map +1 -1
  20. package/dist/sync.js +2 -2
  21. package/dist/sync.js.map +1 -1
  22. package/dist/tests/branching.test.js +237 -28
  23. package/dist/tests/branching.test.js.map +1 -1
  24. package/dist/tests/coValueCore.loadFromStorage.test.d.ts +2 -0
  25. package/dist/tests/coValueCore.loadFromStorage.test.d.ts.map +1 -0
  26. package/dist/tests/coValueCore.loadFromStorage.test.js +395 -0
  27. package/dist/tests/coValueCore.loadFromStorage.test.js.map +1 -0
  28. package/dist/tests/coValueCore.loadingState.test.d.ts +2 -0
  29. package/dist/tests/coValueCore.loadingState.test.d.ts.map +1 -0
  30. package/dist/tests/{coValueCoreLoadingState.test.js → coValueCore.loadingState.test.js} +4 -12
  31. package/dist/tests/coValueCore.loadingState.test.js.map +1 -0
  32. package/dist/tests/coValueCore.test.js +2 -5
  33. package/dist/tests/coValueCore.test.js.map +1 -1
  34. package/dist/tests/sync.mesh.test.js +4 -34
  35. package/dist/tests/sync.mesh.test.js.map +1 -1
  36. package/dist/tests/testUtils.d.ts +7 -1
  37. package/dist/tests/testUtils.d.ts.map +1 -1
  38. package/dist/tests/testUtils.js +12 -0
  39. package/dist/tests/testUtils.js.map +1 -1
  40. package/package.json +3 -3
  41. package/src/coValueCore/branching.ts +28 -3
  42. package/src/coValueCore/coValueCore.ts +215 -167
  43. package/src/coValueCore/decryptTransactionChangesAndMeta.ts +56 -0
  44. package/src/localNode.ts +1 -1
  45. package/src/permissions.ts +21 -19
  46. package/src/sync.ts +2 -2
  47. package/src/tests/branching.test.ts +392 -45
  48. package/src/tests/coValueCore.loadFromStorage.test.ts +540 -0
  49. package/src/tests/{coValueCoreLoadingState.test.ts → coValueCore.loadingState.test.ts} +3 -16
  50. package/src/tests/coValueCore.test.ts +2 -5
  51. package/src/tests/sync.mesh.test.ts +11 -38
  52. package/src/tests/testUtils.ts +21 -0
  53. package/dist/coValueCore/decodeTransactionChangesAndMeta.d.ts +0 -3
  54. package/dist/coValueCore/decodeTransactionChangesAndMeta.d.ts.map +0 -1
  55. package/dist/coValueCore/decodeTransactionChangesAndMeta.js +0 -59
  56. package/dist/coValueCore/decodeTransactionChangesAndMeta.js.map +0 -1
  57. package/dist/tests/coValueCoreLoadingState.test.d.ts +0 -2
  58. package/dist/tests/coValueCoreLoadingState.test.d.ts.map +0 -1
  59. package/dist/tests/coValueCoreLoadingState.test.js.map +0 -1
  60. package/src/coValueCore/decodeTransactionChangesAndMeta.ts +0 -81
@@ -0,0 +1,540 @@
1
+ import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { RawCoID } from "../ids";
3
+ import { StorageAPI } from "../storage/types";
4
+ import {
5
+ createTestMetricReader,
6
+ createTestNode,
7
+ createUnloadedCoValue,
8
+ tearDownTestMetricReader,
9
+ } from "./testUtils";
10
+
11
+ let metricReader: ReturnType<typeof createTestMetricReader>;
12
+
13
+ beforeEach(() => {
14
+ metricReader = createTestMetricReader();
15
+ });
16
+
17
+ afterEach(() => {
18
+ tearDownTestMetricReader();
19
+ });
20
+
21
+ function setup() {
22
+ const node = createTestNode();
23
+
24
+ const { coValue, id, header } = createUnloadedCoValue(node);
25
+
26
+ return { node, state: coValue, id, header };
27
+ }
28
+
29
+ function createMockStorage(
30
+ opts: {
31
+ load?: (
32
+ id: RawCoID,
33
+ callback: (data: any) => void,
34
+ done: (found: boolean) => void,
35
+ ) => void;
36
+ store?: (data: any, correctionCallback: any) => void;
37
+ getKnownState?: (id: RawCoID) => any;
38
+ waitForSync?: (id: string, coValue: any) => Promise<void>;
39
+ close?: () => Promise<unknown> | undefined;
40
+ } = {},
41
+ ): StorageAPI {
42
+ return {
43
+ load: opts.load || vi.fn(),
44
+ store: opts.store || vi.fn(),
45
+ getKnownState: opts.getKnownState || vi.fn(),
46
+ waitForSync: opts.waitForSync || vi.fn().mockResolvedValue(undefined),
47
+ close: opts.close || vi.fn().mockResolvedValue(undefined),
48
+ };
49
+ }
50
+
51
+ describe("CoValueCore.loadFromStorage", () => {
52
+ describe("when storage is not configured", () => {
53
+ test("should call done callback with false immediately", () => {
54
+ const { state } = setup();
55
+ const doneSpy = vi.fn();
56
+
57
+ state.loadFromStorage(doneSpy);
58
+
59
+ expect(doneSpy).toHaveBeenCalledTimes(1);
60
+ expect(doneSpy).toHaveBeenCalledWith(false);
61
+ });
62
+
63
+ test("should not crash when done callback is not provided", () => {
64
+ const { state } = setup();
65
+
66
+ expect(() => state.loadFromStorage()).not.toThrow();
67
+ });
68
+ });
69
+
70
+ describe("when current state is pending", () => {
71
+ test("should return early when done callback is not provided", () => {
72
+ const { state, node } = setup();
73
+ const loadSpy = vi.fn();
74
+ const storage = createMockStorage({ load: loadSpy });
75
+ node.setStorage(storage);
76
+
77
+ // Mark as pending
78
+ state.markPending("storage");
79
+
80
+ // Call without done callback
81
+ state.loadFromStorage();
82
+
83
+ // Should not call storage.load again
84
+ expect(loadSpy).not.toHaveBeenCalled();
85
+ });
86
+
87
+ test("should wait for loading to complete and call done(true) when becomes available", async () => {
88
+ const { state, node, header } = setup();
89
+ let storageCallback: any;
90
+ let storageDone: any;
91
+
92
+ const storage = createMockStorage({
93
+ load: (id, callback, done) => {
94
+ storageCallback = callback;
95
+ storageDone = done;
96
+ },
97
+ });
98
+ node.setStorage(storage);
99
+
100
+ // Start initial load (will mark as pending)
101
+ state.loadFromStorage();
102
+
103
+ // Now try to load again with a done callback while pending
104
+ const doneSpy = vi.fn();
105
+ state.loadFromStorage(doneSpy);
106
+
107
+ // Should not call done yet
108
+ expect(doneSpy).not.toHaveBeenCalled();
109
+
110
+ // Simulate storage providing header and marking as found
111
+ const previousState = state.loadingState;
112
+ state.provideHeader(header);
113
+ state.markFoundInPeer("storage", previousState);
114
+
115
+ // Wait a tick for subscription to fire
116
+ await new Promise((resolve) => setImmediate(resolve));
117
+
118
+ expect(doneSpy).toHaveBeenCalledTimes(1);
119
+ expect(doneSpy).toHaveBeenCalledWith(true);
120
+ });
121
+
122
+ test("should wait for loading to complete and call done(false) when becomes errored", async () => {
123
+ const { state, node } = setup();
124
+ const storage = createMockStorage({
125
+ load: vi.fn(),
126
+ });
127
+ node.setStorage(storage);
128
+
129
+ // Start initial load (will mark as pending)
130
+ state.loadFromStorage();
131
+
132
+ // Now try to load again with a done callback while pending
133
+ const doneSpy = vi.fn();
134
+ state.loadFromStorage(doneSpy);
135
+
136
+ // Should not call done yet
137
+ expect(doneSpy).not.toHaveBeenCalled();
138
+
139
+ // Simulate error
140
+ state.markErrored("storage", {} as any);
141
+
142
+ // Wait a tick for subscription to fire
143
+ await new Promise((resolve) => setImmediate(resolve));
144
+
145
+ expect(doneSpy).toHaveBeenCalledTimes(1);
146
+ expect(doneSpy).toHaveBeenCalledWith(false);
147
+ });
148
+
149
+ test("should wait for loading to complete and call done(false) when becomes unavailable", async () => {
150
+ const { state, node } = setup();
151
+ const storage = createMockStorage({
152
+ load: vi.fn(),
153
+ });
154
+ node.setStorage(storage);
155
+
156
+ // Start initial load (will mark as pending)
157
+ state.loadFromStorage();
158
+
159
+ // Now try to load again with a done callback while pending
160
+ const doneSpy = vi.fn();
161
+ state.loadFromStorage(doneSpy);
162
+
163
+ // Should not call done yet
164
+ expect(doneSpy).not.toHaveBeenCalled();
165
+
166
+ // Simulate not found
167
+ state.markNotFoundInPeer("storage");
168
+
169
+ // Wait a tick for subscription to fire
170
+ await new Promise((resolve) => setImmediate(resolve));
171
+
172
+ expect(doneSpy).toHaveBeenCalledTimes(1);
173
+ expect(doneSpy).toHaveBeenCalledWith(false);
174
+ });
175
+
176
+ test("should unsubscribe after receiving result", async () => {
177
+ const { state, node, header } = setup();
178
+ const storage = createMockStorage({
179
+ load: vi.fn(),
180
+ });
181
+ node.setStorage(storage);
182
+
183
+ // Start initial load (will mark as pending)
184
+ state.loadFromStorage();
185
+
186
+ // Now try to load again with a done callback while pending
187
+ const doneSpy = vi.fn();
188
+ state.loadFromStorage(doneSpy);
189
+
190
+ // Simulate becoming available
191
+ const previousState = state.loadingState;
192
+ state.provideHeader(header);
193
+ state.markFoundInPeer("storage", previousState);
194
+
195
+ // Wait a tick for subscription to fire
196
+ await new Promise((resolve) => setImmediate(resolve));
197
+
198
+ expect(doneSpy).toHaveBeenCalledTimes(1);
199
+
200
+ // Further state changes should not trigger the callback again
201
+ state.markNotFoundInPeer("another_peer");
202
+ await new Promise((resolve) => setImmediate(resolve));
203
+
204
+ expect(doneSpy).toHaveBeenCalledTimes(1); // Still only called once
205
+ });
206
+ });
207
+
208
+ describe("when current state is not unknown", () => {
209
+ test("should call done(true) immediately when state is available", () => {
210
+ const { state, node, header } = setup();
211
+ const storage = createMockStorage();
212
+ node.setStorage(storage);
213
+
214
+ // Mark as available
215
+ const previousState = state.loadingState;
216
+ state.provideHeader(header);
217
+ state.markFoundInPeer("storage", previousState);
218
+
219
+ const doneSpy = vi.fn();
220
+ state.loadFromStorage(doneSpy);
221
+
222
+ expect(doneSpy).toHaveBeenCalledTimes(1);
223
+ expect(doneSpy).toHaveBeenCalledWith(true);
224
+ });
225
+
226
+ test("should call done(false) immediately when state is unavailable", () => {
227
+ const { state, node } = setup();
228
+ const storage = createMockStorage();
229
+ node.setStorage(storage);
230
+
231
+ // Mark as unavailable
232
+ state.markNotFoundInPeer("storage");
233
+
234
+ const doneSpy = vi.fn();
235
+ state.loadFromStorage(doneSpy);
236
+
237
+ expect(doneSpy).toHaveBeenCalledTimes(1);
238
+ expect(doneSpy).toHaveBeenCalledWith(false);
239
+ });
240
+
241
+ test("should call done(false) immediately when state is errored", () => {
242
+ const { state, node } = setup();
243
+ const storage = createMockStorage();
244
+ node.setStorage(storage);
245
+
246
+ // Mark as errored
247
+ state.markErrored("storage", {} as any);
248
+
249
+ const doneSpy = vi.fn();
250
+ state.loadFromStorage(doneSpy);
251
+
252
+ expect(doneSpy).toHaveBeenCalledTimes(1);
253
+ expect(doneSpy).toHaveBeenCalledWith(false);
254
+ });
255
+
256
+ test("should not call storage.load when state is already known", () => {
257
+ const { state, node, header } = setup();
258
+ const loadSpy = vi.fn();
259
+ const storage = createMockStorage({ load: loadSpy });
260
+ node.setStorage(storage);
261
+
262
+ // Mark as available
263
+ const previousState = state.loadingState;
264
+ state.provideHeader(header);
265
+ state.markFoundInPeer("storage", previousState);
266
+
267
+ state.loadFromStorage(vi.fn());
268
+
269
+ expect(loadSpy).not.toHaveBeenCalled();
270
+ });
271
+
272
+ test("should handle missing done callback when state is available", () => {
273
+ const { state, node, header } = setup();
274
+ const storage = createMockStorage();
275
+ node.setStorage(storage);
276
+
277
+ // Mark as available
278
+ const previousState = state.loadingState;
279
+ state.provideHeader(header);
280
+ state.markFoundInPeer("storage", previousState);
281
+
282
+ expect(() => state.loadFromStorage()).not.toThrow();
283
+ });
284
+ });
285
+
286
+ describe("when current state is unknown", () => {
287
+ test("should mark as pending and call storage.load", () => {
288
+ const { state, node, id } = setup();
289
+ const loadSpy = vi.fn();
290
+ const storage = createMockStorage({ load: loadSpy });
291
+ node.setStorage(storage);
292
+
293
+ state.loadFromStorage();
294
+
295
+ expect(state.getLoadingStateForPeer("storage")).toBe("pending");
296
+ expect(loadSpy).toHaveBeenCalledTimes(1);
297
+ expect(loadSpy).toHaveBeenCalledWith(
298
+ id,
299
+ expect.any(Function),
300
+ expect.any(Function),
301
+ );
302
+ });
303
+
304
+ test("should call done(true) when storage finds the value", async () => {
305
+ const { state, node, id, header } = setup();
306
+ let storageCallback: any;
307
+ let storageDone: any;
308
+
309
+ const storage = createMockStorage({
310
+ load: (id, callback, done) => {
311
+ storageCallback = callback;
312
+ storageDone = done;
313
+ },
314
+ });
315
+ node.setStorage(storage);
316
+
317
+ const doneSpy = vi.fn();
318
+ state.loadFromStorage(doneSpy);
319
+
320
+ // Simulate storage finding the value
321
+ // First provide the content through callback
322
+ state.provideHeader(header);
323
+
324
+ // Then call done with true
325
+ storageDone(true);
326
+
327
+ expect(doneSpy).toHaveBeenCalledTimes(1);
328
+ expect(doneSpy).toHaveBeenCalledWith(true);
329
+ });
330
+
331
+ test("should call done(false) and mark as not found when storage doesn't find the value", async () => {
332
+ const { state, node } = setup();
333
+ let storageDone: any;
334
+
335
+ const storage = createMockStorage({
336
+ load: (id, callback, done) => {
337
+ storageDone = done;
338
+ },
339
+ });
340
+ node.setStorage(storage);
341
+
342
+ const doneSpy = vi.fn();
343
+ state.loadFromStorage(doneSpy);
344
+
345
+ // Simulate storage not finding the value
346
+ storageDone(false);
347
+
348
+ expect(doneSpy).toHaveBeenCalledTimes(1);
349
+ expect(doneSpy).toHaveBeenCalledWith(false);
350
+ expect(state.getLoadingStateForPeer("storage")).toBe("unavailable");
351
+ });
352
+
353
+ test("should pass content to syncManager when storage provides it", async () => {
354
+ const { state, node } = setup();
355
+ let storageCallback: any;
356
+
357
+ const storage = createMockStorage({
358
+ load: (id, callback, done) => {
359
+ storageCallback = callback;
360
+ },
361
+ });
362
+ node.setStorage(storage);
363
+
364
+ const handleNewContentSpy = vi.spyOn(
365
+ node.syncManager,
366
+ "handleNewContent",
367
+ );
368
+
369
+ state.loadFromStorage();
370
+
371
+ // Simulate storage providing content with proper format
372
+ const mockData = {
373
+ action: "content" as const,
374
+ id: state.id,
375
+ priority: 0,
376
+ new: {},
377
+ };
378
+ storageCallback(mockData);
379
+
380
+ expect(handleNewContentSpy).toHaveBeenCalledTimes(1);
381
+ expect(handleNewContentSpy).toHaveBeenCalledWith(mockData, "storage");
382
+ });
383
+
384
+ test("should handle missing done callback when loading from storage", () => {
385
+ const { state, node } = setup();
386
+ let storageDone: any;
387
+
388
+ const storage = createMockStorage({
389
+ load: (id, callback, done) => {
390
+ storageDone = done;
391
+ },
392
+ });
393
+ node.setStorage(storage);
394
+
395
+ expect(() => {
396
+ state.loadFromStorage();
397
+ storageDone(true);
398
+ }).not.toThrow();
399
+ });
400
+
401
+ test("should not mark as not found when storage finds the value", async () => {
402
+ const { state, node, header } = setup();
403
+ let storageDone: any;
404
+
405
+ const storage = createMockStorage({
406
+ load: (id, callback, done) => {
407
+ storageDone = done;
408
+ },
409
+ });
410
+ node.setStorage(storage);
411
+
412
+ state.loadFromStorage();
413
+
414
+ // Provide header first
415
+ state.provideHeader(header);
416
+ const previousState = state.loadingState;
417
+ state.markFoundInPeer("storage", previousState);
418
+
419
+ // Call done with true
420
+ storageDone(true);
421
+
422
+ // State should be available, not unavailable
423
+ expect(state.getLoadingStateForPeer("storage")).not.toBe("unavailable");
424
+ });
425
+
426
+ test("should handle multiple concurrent loadFromStorage calls", async () => {
427
+ const { state, node, id } = setup();
428
+ const loadSpy = vi.fn();
429
+ const storage = createMockStorage({ load: loadSpy });
430
+ node.setStorage(storage);
431
+
432
+ const done1 = vi.fn();
433
+ const done2 = vi.fn();
434
+ const done3 = vi.fn();
435
+
436
+ // All three calls should work together
437
+ state.loadFromStorage(done1);
438
+ state.loadFromStorage(done2);
439
+ state.loadFromStorage(done3);
440
+
441
+ // Storage.load should only be called once (first call)
442
+ expect(loadSpy).toHaveBeenCalledTimes(1);
443
+
444
+ // The other calls should be waiting (pending state)
445
+ expect(done1).not.toHaveBeenCalled();
446
+ expect(done2).not.toHaveBeenCalled();
447
+ expect(done3).not.toHaveBeenCalled();
448
+ });
449
+ });
450
+
451
+ describe("edge cases and integration", () => {
452
+ test("should handle transition from unknown to pending to available", async () => {
453
+ const { state, node, header } = setup();
454
+ let storageCallback: any;
455
+ let storageDone: any;
456
+
457
+ const storage = createMockStorage({
458
+ load: (id, callback, done) => {
459
+ storageCallback = callback;
460
+ storageDone = done;
461
+ },
462
+ });
463
+ node.setStorage(storage);
464
+
465
+ const doneSpy = vi.fn();
466
+
467
+ // Start as unknown
468
+ expect(state.getLoadingStateForPeer("storage")).toBe("unknown");
469
+
470
+ // Load from storage
471
+ state.loadFromStorage(doneSpy);
472
+
473
+ // Should now be pending
474
+ expect(state.getLoadingStateForPeer("storage")).toBe("pending");
475
+
476
+ // Simulate storage providing the header
477
+ state.provideHeader(header);
478
+ const previousState = state.loadingState;
479
+ state.markFoundInPeer("storage", previousState);
480
+
481
+ // Call done
482
+ storageDone(true);
483
+
484
+ // Should be available
485
+ expect(state.getLoadingStateForPeer("storage")).toBe("available");
486
+ expect(doneSpy).toHaveBeenCalledWith(true);
487
+ });
488
+
489
+ test("should properly clean up subscriptions when state becomes available through isAvailable()", async () => {
490
+ const { state, node, header } = setup();
491
+ const storage = createMockStorage({
492
+ load: vi.fn(),
493
+ });
494
+ node.setStorage(storage);
495
+
496
+ // Start initial load (will mark as pending)
497
+ state.loadFromStorage();
498
+
499
+ // Now try to load again with a done callback while pending
500
+ const doneSpy = vi.fn();
501
+ state.loadFromStorage(doneSpy);
502
+
503
+ // Make the whole state available (not just from storage peer)
504
+ state.provideHeader(header);
505
+ const previousState = state.loadingState;
506
+ state.markFoundInPeer("some_other_peer", previousState);
507
+
508
+ // Wait for subscription to process
509
+ await new Promise((resolve) => setImmediate(resolve));
510
+
511
+ // Should have called done(true) because isAvailable() is true
512
+ expect(doneSpy).toHaveBeenCalledTimes(1);
513
+ expect(doneSpy).toHaveBeenCalledWith(true);
514
+ });
515
+
516
+ test("should handle rapid state changes", async () => {
517
+ const { state, node, header } = setup();
518
+ const storage = createMockStorage({
519
+ load: vi.fn(),
520
+ });
521
+ node.setStorage(storage);
522
+
523
+ const doneSpy = vi.fn();
524
+
525
+ // Start loading
526
+ state.loadFromStorage(doneSpy);
527
+
528
+ // Rapid state changes
529
+ state.markPending("storage");
530
+ state.markNotFoundInPeer("storage");
531
+
532
+ const previousState = state.loadingState;
533
+ state.provideHeader(header);
534
+ state.markFoundInPeer("storage", previousState);
535
+
536
+ // Should have the final state
537
+ expect(state.getLoadingStateForPeer("storage")).toBe("available");
538
+ });
539
+ });
540
+ });
@@ -1,16 +1,12 @@
1
1
  import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
2
  import { PeerState } from "../PeerState";
3
- import { CoValueCore, idforHeader } from "../coValueCore/coValueCore";
4
- import { CoValueHeader, VerifiedState } from "../coValueCore/verifiedState";
5
- import { RawCoID } from "../ids";
6
- import { LocalNode } from "../localNode";
7
3
  import { Peer } from "../sync";
8
4
  import {
9
5
  createTestMetricReader,
10
6
  createTestNode,
7
+ createUnloadedCoValue,
11
8
  tearDownTestMetricReader,
12
9
  } from "./testUtils";
13
- import { WasmCrypto } from "../crypto/WasmCrypto";
14
10
 
15
11
  let metricReader: ReturnType<typeof createTestMetricReader>;
16
12
 
@@ -25,18 +21,9 @@ afterEach(() => {
25
21
  function setup() {
26
22
  const node = createTestNode();
27
23
 
28
- const header = {
29
- type: "comap",
30
- ruleset: { type: "ownedByGroup", group: "co_ztest123" },
31
- meta: null,
32
- ...node.crypto.createdNowUnique(),
33
- } as CoValueHeader;
24
+ const { coValue, id, header } = createUnloadedCoValue(node);
34
25
 
35
- const id = idforHeader(header, node.crypto);
36
-
37
- const state = CoValueCore.fromID(id, node);
38
-
39
- return { node, state, id, header };
26
+ return { node, state: coValue, id, header };
40
27
  }
41
28
 
42
29
  describe("CoValueCore loading state", () => {
@@ -451,9 +451,7 @@ describe("markErrored and isErroredInPeer", () => {
451
451
  expect(coValue.isErroredInPeer(peerId)).toBe(true);
452
452
 
453
453
  // Verify the peer state contains the error
454
- const peerState = coValue.getStateForPeer(peerId);
455
- expect(peerState).toBeDefined();
456
- expect(peerState?.type).toBe("errored");
454
+ expect(coValue.getLoadingStateForPeer(peerId)).toBe("errored");
457
455
  });
458
456
 
459
457
  test("markErrored should update loading state and notify listeners", () => {
@@ -632,8 +630,7 @@ describe("markErrored and isErroredInPeer", () => {
632
630
  // Verify the peer is now errored
633
631
  expect(coValue.isErroredInPeer(peerId)).toBe(true);
634
632
 
635
- const peerState = coValue.getStateForPeer(peerId);
636
- expect(peerState?.type).toBe("errored");
633
+ expect(coValue.getLoadingStateForPeer(peerId)).toBe("errored");
637
634
  });
638
635
 
639
636
  test("markErrored should work with different error types", () => {
@@ -276,44 +276,17 @@ describe("multiple clients syncing with the a cloud-like server mesh", () => {
276
276
  expect(coValue.get("fromClient")).toEqual("updated");
277
277
  });
278
278
 
279
- expect(
280
- SyncMessagesLog.getMessages({
281
- Group: group.core,
282
- Map: map.core,
283
- }),
284
- ).toMatchInlineSnapshot(`
285
- [
286
- "client -> edge-italy | LOAD Map sessions: empty",
287
- "edge-italy -> storage | CONTENT Group header: true new: After: 0 New: 5",
288
- "edge-italy -> core | CONTENT Group header: true new: After: 0 New: 5",
289
- "edge-italy -> storage | CONTENT Map header: true new: After: 0 New: 1",
290
- "edge-italy -> core | CONTENT Map header: true new: After: 0 New: 1",
291
- "edge-italy -> client | CONTENT Group header: true new: After: 0 New: 5",
292
- "edge-italy -> client | CONTENT Map header: true new: After: 0 New: 1",
293
- "core -> edge-italy | KNOWN Group sessions: header/5",
294
- "core -> storage | CONTENT Group header: true new: After: 0 New: 5",
295
- "core -> edge-italy | KNOWN Map sessions: header/1",
296
- "core -> storage | CONTENT Map header: true new: After: 0 New: 1",
297
- "client -> edge-italy | KNOWN Group sessions: header/5",
298
- "client -> edge-italy | KNOWN Map sessions: header/1",
299
- "client -> edge-italy | CONTENT Map header: false new: After: 0 New: 1",
300
- "core -> storage | CONTENT Map header: false new: After: 0 New: 1",
301
- "core -> edge-italy | CONTENT Map header: false new: After: 0 New: 1",
302
- "edge-italy -> client | KNOWN CORRECTION Map sessions: empty",
303
- "edge-italy -> core | KNOWN CORRECTION Map sessions: empty",
304
- "client -> edge-italy | CONTENT Map header: true new: After: 0 New: 1 | After: 0 New: 1",
305
- "core -> edge-italy | CONTENT Map header: true new: After: 0 New: 1 | After: 0 New: 1",
306
- "edge-italy -> client | KNOWN Map sessions: header/2",
307
- "edge-italy -> storage | CONTENT Map header: true new: After: 0 New: 1 | After: 0 New: 1",
308
- "edge-italy -> core | CONTENT Map header: false new: After: 0 New: 1",
309
- "edge-italy -> core | KNOWN Map sessions: header/3",
310
- "edge-italy -> storage | CONTENT Map header: true new: After: 0 New: 1",
311
- "edge-italy -> client | CONTENT Map header: false new: After: 0 New: 1",
312
- "core -> edge-italy | KNOWN Map sessions: header/3",
313
- "core -> storage | CONTENT Map header: false new: After: 0 New: 1",
314
- "client -> edge-italy | KNOWN Map sessions: header/3",
315
- ]
316
- `);
279
+ const syncLog = SyncMessagesLog.getMessages({
280
+ Group: group.core,
281
+ Map: map.core,
282
+ });
283
+
284
+ expect(syncLog).toContain(
285
+ "edge-italy -> client | KNOWN CORRECTION Map sessions: empty",
286
+ );
287
+ expect(syncLog).toContain(
288
+ "edge-italy -> core | KNOWN CORRECTION Map sessions: empty",
289
+ );
317
290
  });
318
291
 
319
292
  test("sync of changes of a coValue with bad signatures should be blocked", async () => {
@@ -10,6 +10,7 @@ import { ControlledAccount, ControlledAgent } from "../coValues/account.js";
10
10
  import { WasmCrypto } from "../crypto/WasmCrypto.js";
11
11
  import {
12
12
  type AgentSecret,
13
+ AnyRawCoValue,
13
14
  type CoID,
14
15
  type CoValueCore,
15
16
  type RawAccount,
@@ -24,6 +25,8 @@ import { expectGroup } from "../typeUtils/expectGroup.js";
24
25
  import { toSimplifiedMessages } from "./messagesTestUtils.js";
25
26
  import { createAsyncStorage, createSyncStorage } from "./testStorage.js";
26
27
  import { PureJSCrypto } from "../crypto/PureJSCrypto.js";
28
+ import { CoValueHeader } from "../coValueCore/verifiedState.js";
29
+ import { idforHeader } from "../coValueCore/coValueCore.js";
27
30
 
28
31
  let Crypto = await WasmCrypto.create();
29
32
 
@@ -722,3 +725,21 @@ export function createAccountInNode(node: LocalNode) {
722
725
  accountOnTempNode.core.node.agentSecret,
723
726
  );
724
727
  }
728
+
729
+ export function createUnloadedCoValue(
730
+ node: LocalNode,
731
+ type: AnyRawCoValue["type"] = "comap",
732
+ ) {
733
+ const header = {
734
+ type,
735
+ ruleset: { type: "ownedByGroup", group: node.getCurrentAccountOrAgentID() },
736
+ meta: null,
737
+ ...node.crypto.createdNowUnique(),
738
+ } as CoValueHeader;
739
+
740
+ const id = idforHeader(header, node.crypto);
741
+
742
+ const state = node.getCoValue(id);
743
+
744
+ return { coValue: state, id, header };
745
+ }
@@ -1,3 +0,0 @@
1
- import { AvailableCoValueCore, VerifiedTransaction } from "./coValueCore.js";
2
- export declare function decodeTransactionChangesAndMeta(coValue: AvailableCoValueCore, transaction: VerifiedTransaction, ignorePrivateTransactions: boolean): void;
3
- //# sourceMappingURL=decodeTransactionChangesAndMeta.d.ts.map