cojson 0.18.26 → 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 (161) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +17 -0
  3. package/dist/PeerKnownStates.d.ts +4 -3
  4. package/dist/PeerKnownStates.d.ts.map +1 -1
  5. package/dist/PeerKnownStates.js +27 -18
  6. package/dist/PeerKnownStates.js.map +1 -1
  7. package/dist/PeerState.d.ts +3 -2
  8. package/dist/PeerState.d.ts.map +1 -1
  9. package/dist/PeerState.js.map +1 -1
  10. package/dist/SyncStateManager.d.ts +2 -2
  11. package/dist/SyncStateManager.d.ts.map +1 -1
  12. package/dist/SyncStateManager.js +2 -10
  13. package/dist/SyncStateManager.js.map +1 -1
  14. package/dist/coValueContentMessage.d.ts +1 -1
  15. package/dist/coValueContentMessage.d.ts.map +1 -1
  16. package/dist/coValueContentMessage.js +1 -1
  17. package/dist/coValueContentMessage.js.map +1 -1
  18. package/dist/coValueCore/SessionMap.d.ts +6 -3
  19. package/dist/coValueCore/SessionMap.d.ts.map +1 -1
  20. package/dist/coValueCore/SessionMap.js +41 -8
  21. package/dist/coValueCore/SessionMap.js.map +1 -1
  22. package/dist/coValueCore/branching.d.ts +5 -4
  23. package/dist/coValueCore/branching.d.ts.map +1 -1
  24. package/dist/coValueCore/branching.js +22 -4
  25. package/dist/coValueCore/branching.js.map +1 -1
  26. package/dist/coValueCore/coValueCore.d.ts +29 -25
  27. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  28. package/dist/coValueCore/coValueCore.js +163 -126
  29. package/dist/coValueCore/coValueCore.js.map +1 -1
  30. package/dist/coValueCore/decryptTransactionChangesAndMeta.d.ts +3 -0
  31. package/dist/coValueCore/decryptTransactionChangesAndMeta.d.ts.map +1 -0
  32. package/dist/coValueCore/decryptTransactionChangesAndMeta.js +34 -0
  33. package/dist/coValueCore/decryptTransactionChangesAndMeta.js.map +1 -0
  34. package/dist/coValueCore/verifiedState.d.ts +12 -6
  35. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  36. package/dist/coValueCore/verifiedState.js +28 -56
  37. package/dist/coValueCore/verifiedState.js.map +1 -1
  38. package/dist/coValues/coMap.d.ts.map +1 -1
  39. package/dist/coValues/coMap.js.map +1 -1
  40. package/dist/coValues/coStream.d.ts.map +1 -1
  41. package/dist/coValues/coStream.js.map +1 -1
  42. package/dist/exports.d.ts +3 -2
  43. package/dist/exports.d.ts.map +1 -1
  44. package/dist/exports.js +2 -1
  45. package/dist/exports.js.map +1 -1
  46. package/dist/knownState.d.ts +58 -2
  47. package/dist/knownState.d.ts.map +1 -1
  48. package/dist/knownState.js +79 -5
  49. package/dist/knownState.js.map +1 -1
  50. package/dist/localNode.js +1 -1
  51. package/dist/localNode.js.map +1 -1
  52. package/dist/permissions.d.ts.map +1 -1
  53. package/dist/permissions.js +18 -20
  54. package/dist/permissions.js.map +1 -1
  55. package/dist/storage/knownState.d.ts +1 -1
  56. package/dist/storage/knownState.d.ts.map +1 -1
  57. package/dist/storage/knownState.js +2 -3
  58. package/dist/storage/knownState.js.map +1 -1
  59. package/dist/storage/storageAsync.d.ts +2 -1
  60. package/dist/storage/storageAsync.d.ts.map +1 -1
  61. package/dist/storage/storageAsync.js +5 -6
  62. package/dist/storage/storageAsync.js.map +1 -1
  63. package/dist/storage/storageSync.d.ts +2 -1
  64. package/dist/storage/storageSync.d.ts.map +1 -1
  65. package/dist/storage/storageSync.js +5 -5
  66. package/dist/storage/storageSync.js.map +1 -1
  67. package/dist/storage/types.d.ts +2 -1
  68. package/dist/storage/types.d.ts.map +1 -1
  69. package/dist/sync.d.ts +2 -12
  70. package/dist/sync.d.ts.map +1 -1
  71. package/dist/sync.js +9 -38
  72. package/dist/sync.js.map +1 -1
  73. package/dist/tests/PeerKnownStates.test.js +1 -1
  74. package/dist/tests/PeerKnownStates.test.js.map +1 -1
  75. package/dist/tests/PeerState.test.js +19 -0
  76. package/dist/tests/PeerState.test.js.map +1 -1
  77. package/dist/tests/PureJSCrypto.test.js.map +1 -1
  78. package/dist/tests/StorageApiAsync.test.js +1 -1
  79. package/dist/tests/StorageApiAsync.test.js.map +1 -1
  80. package/dist/tests/StorageApiSync.test.js +1 -2
  81. package/dist/tests/StorageApiSync.test.js.map +1 -1
  82. package/dist/tests/StoreQueue.test.js.map +1 -1
  83. package/dist/tests/SyncStateManager.test.js +1 -1
  84. package/dist/tests/SyncStateManager.test.js.map +1 -1
  85. package/dist/tests/branching.test.js +237 -28
  86. package/dist/tests/branching.test.js.map +1 -1
  87. package/dist/tests/coValueContentMessage.test.js +1 -1
  88. package/dist/tests/coValueContentMessage.test.js.map +1 -1
  89. package/dist/tests/coValueCore.loadFromStorage.test.d.ts +2 -0
  90. package/dist/tests/coValueCore.loadFromStorage.test.d.ts.map +1 -0
  91. package/dist/tests/coValueCore.loadFromStorage.test.js +395 -0
  92. package/dist/tests/coValueCore.loadFromStorage.test.js.map +1 -0
  93. package/dist/tests/coValueCore.loadingState.test.d.ts +2 -0
  94. package/dist/tests/coValueCore.loadingState.test.d.ts.map +1 -0
  95. package/dist/tests/{coValueCoreLoadingState.test.js → coValueCore.loadingState.test.js} +4 -12
  96. package/dist/tests/coValueCore.loadingState.test.js.map +1 -0
  97. package/dist/tests/coValueCore.test.js +30 -5
  98. package/dist/tests/coValueCore.test.js.map +1 -1
  99. package/dist/tests/knownState.test.d.ts +2 -0
  100. package/dist/tests/knownState.test.d.ts.map +1 -0
  101. package/dist/tests/knownState.test.js +510 -0
  102. package/dist/tests/knownState.test.js.map +1 -0
  103. package/dist/tests/messagesTestUtils.d.ts.map +1 -1
  104. package/dist/tests/messagesTestUtils.js.map +1 -1
  105. package/dist/tests/priority.test.js.map +1 -1
  106. package/dist/tests/sync.mesh.test.js +4 -34
  107. package/dist/tests/sync.mesh.test.js.map +1 -1
  108. package/dist/tests/sync.storage.test.js.map +1 -1
  109. package/dist/tests/sync.upload.test.js.map +1 -1
  110. package/dist/tests/testUtils.d.ts +7 -1
  111. package/dist/tests/testUtils.d.ts.map +1 -1
  112. package/dist/tests/testUtils.js +12 -0
  113. package/dist/tests/testUtils.js.map +1 -1
  114. package/package.json +3 -3
  115. package/src/PeerKnownStates.ts +36 -22
  116. package/src/PeerState.ts +2 -1
  117. package/src/SyncStateManager.ts +4 -17
  118. package/src/coValueContentMessage.ts +2 -1
  119. package/src/coValueCore/SessionMap.ts +66 -11
  120. package/src/coValueCore/branching.ts +37 -13
  121. package/src/coValueCore/coValueCore.ts +224 -177
  122. package/src/coValueCore/decryptTransactionChangesAndMeta.ts +56 -0
  123. package/src/coValueCore/verifiedState.ts +32 -64
  124. package/src/coValues/coMap.ts +1 -5
  125. package/src/coValues/coStream.ts +1 -5
  126. package/src/exports.ts +2 -2
  127. package/src/knownState.ts +118 -12
  128. package/src/localNode.ts +1 -1
  129. package/src/permissions.ts +21 -22
  130. package/src/storage/knownState.ts +9 -3
  131. package/src/storage/storageAsync.ts +15 -7
  132. package/src/storage/storageSync.ts +16 -8
  133. package/src/storage/types.ts +2 -1
  134. package/src/sync.ts +14 -60
  135. package/src/tests/PeerKnownStates.test.ts +1 -1
  136. package/src/tests/PeerState.test.ts +29 -3
  137. package/src/tests/PureJSCrypto.test.ts +0 -1
  138. package/src/tests/StorageApiAsync.test.ts +3 -6
  139. package/src/tests/StorageApiSync.test.ts +2 -6
  140. package/src/tests/StoreQueue.test.ts +3 -2
  141. package/src/tests/SyncStateManager.test.ts +1 -1
  142. package/src/tests/branching.test.ts +392 -45
  143. package/src/tests/coValueContentMessage.test.ts +2 -2
  144. package/src/tests/coValueCore.loadFromStorage.test.ts +540 -0
  145. package/src/tests/{coValueCoreLoadingState.test.ts → coValueCore.loadingState.test.ts} +3 -16
  146. package/src/tests/coValueCore.test.ts +40 -5
  147. package/src/tests/knownState.test.ts +665 -0
  148. package/src/tests/messagesTestUtils.ts +2 -1
  149. package/src/tests/priority.test.ts +0 -2
  150. package/src/tests/sync.mesh.test.ts +11 -38
  151. package/src/tests/sync.storage.test.ts +0 -1
  152. package/src/tests/sync.upload.test.ts +0 -1
  153. package/src/tests/testUtils.ts +22 -2
  154. package/dist/coValueCore/decodeTransactionChangesAndMeta.d.ts +0 -3
  155. package/dist/coValueCore/decodeTransactionChangesAndMeta.d.ts.map +0 -1
  156. package/dist/coValueCore/decodeTransactionChangesAndMeta.js +0 -59
  157. package/dist/coValueCore/decodeTransactionChangesAndMeta.js.map +0 -1
  158. package/dist/tests/coValueCoreLoadingState.test.d.ts +0 -2
  159. package/dist/tests/coValueCoreLoadingState.test.d.ts.map +0 -1
  160. package/dist/tests/coValueCoreLoadingState.test.js.map +0 -1
  161. package/src/coValueCore/decodeTransactionChangesAndMeta.ts +0 -81
@@ -1,11 +1,21 @@
1
- import { assert, beforeEach, describe, expect, test } from "vitest";
1
+ import {
2
+ assert,
3
+ beforeEach,
4
+ describe,
5
+ expect,
6
+ onTestFinished,
7
+ test,
8
+ vi,
9
+ } from "vitest";
2
10
  import {
3
11
  createTestNode,
4
12
  setupTestNode,
5
13
  loadCoValueOrFail,
14
+ setupTestAccount,
15
+ waitFor,
6
16
  } from "./testUtils.js";
7
17
  import { expectList, expectMap, expectPlainText } from "../coValue.js";
8
- import { RawCoMap } from "../exports.js";
18
+ import { RawAccount, RawCoMap } from "../exports.js";
9
19
 
10
20
  let jazzCloud: ReturnType<typeof setupTestNode>;
11
21
 
@@ -237,6 +247,7 @@ describe("Branching Logic", () => {
237
247
  loadedBranch2.core.mergeBranch();
238
248
 
239
249
  await loadedBranch2.core.waitForSync();
250
+ await new Promise((resolve) => setTimeout(resolve, 5));
240
251
 
241
252
  branch1.core.mergeBranch();
242
253
 
@@ -289,6 +300,385 @@ describe("Branching Logic", () => {
289
300
 
290
301
  expect(plainText.toString()).toEqual("hello world people");
291
302
  });
303
+
304
+ test("should preserve the conflict resolution that was applied to the branch", async () => {
305
+ const dateNowMock = vi.spyOn(Date, "now");
306
+
307
+ dateNowMock.mockReturnValue(1);
308
+
309
+ const client = setupTestNode({
310
+ connected: true,
311
+ });
312
+ const group = client.node.createGroup();
313
+ const map = group.createMap();
314
+ const branchName = "feature-branch";
315
+
316
+ onTestFinished(() => {
317
+ dateNowMock.mockRestore();
318
+ });
319
+
320
+ // Add initial transactions to original map
321
+ map.set("value", 1, "trusting");
322
+
323
+ // Create branch from original map
324
+ const branch = expectMap(
325
+ map.core.createBranch(branchName, group.id).getCurrentContent(),
326
+ );
327
+
328
+ dateNowMock.mockReturnValue(2);
329
+
330
+ // Add new transaction to branch
331
+ branch.set("value", 2, "trusting");
332
+
333
+ const newSession = client.spawnNewSession();
334
+
335
+ const loadedBranch = await loadCoValueOrFail(newSession.node, branch.id);
336
+
337
+ dateNowMock.mockReturnValue(3);
338
+
339
+ loadedBranch.set("value", 3, "trusting");
340
+
341
+ expect(loadedBranch.get("value")).toBe(3);
342
+
343
+ await loadedBranch.core.waitForSync();
344
+
345
+ // Push back the change, so it doesn't win the conflict
346
+ dateNowMock.mockReturnValue(1);
347
+
348
+ branch.set("value", 4, "trusting");
349
+
350
+ expect(branch.get("value")).toBe(3);
351
+
352
+ dateNowMock.mockReturnValue(4);
353
+ branch.core.mergeBranch();
354
+
355
+ // The conflict resolution should be preserved, so we should have 3 and not 4
356
+ expect(map.get("value")).toBe(3);
357
+ });
358
+
359
+ test("should preserve the original madeAt of the branch", async () => {
360
+ const client = setupTestNode();
361
+ const group = client.node.createGroup();
362
+ const map = group.createMap();
363
+
364
+ // Add initial transactions to original map
365
+ map.set("value", 1, "trusting");
366
+
367
+ // Create branch from original map
368
+ const branch = expectMap(
369
+ map.core.createBranch("feature-branch", group.id).getCurrentContent(),
370
+ );
371
+
372
+ // Add new transaction to branch
373
+ branch.set("value", 2, "trusting");
374
+
375
+ await new Promise((resolve) => setTimeout(resolve, 5));
376
+
377
+ const result = branch.core.mergeBranch();
378
+
379
+ // The merge should be successful
380
+ expect(map.get("value")).toBe(2);
381
+
382
+ const lastBranchTransaction = branch.core
383
+ .getValidSortedTransactions()
384
+ .at(-1);
385
+ const lastMapTransaction = result
386
+ .getValidSortedTransactions()
387
+ .findLast((tx) => tx.txID.branch === branch.id);
388
+
389
+ expect(lastMapTransaction?.currentMadeAt).not.toBe(
390
+ lastMapTransaction?.madeAt,
391
+ );
392
+
393
+ expect(lastBranchTransaction?.madeAt).toBe(lastMapTransaction?.madeAt);
394
+ });
395
+
396
+ test("should not load the merged transactions into the branch (regression test)", async () => {
397
+ const client = setupTestNode();
398
+ const group = client.node.createGroup();
399
+ const map = group.createMap();
400
+
401
+ // Add initial transactions to original map
402
+ map.set("value", 1, "trusting");
403
+
404
+ // Create branch from original map
405
+ const branch = expectMap(
406
+ map.core.createBranch("feature-branch", group.id).getCurrentContent(),
407
+ );
408
+
409
+ await new Promise((resolve) => setTimeout(resolve, 5));
410
+
411
+ // Add new transaction to branch
412
+ branch.set("value", 2, "trusting");
413
+
414
+ await new Promise((resolve) => setTimeout(resolve, 5));
415
+
416
+ const result = branch.core.mergeBranch();
417
+
418
+ // The merge should be successful
419
+ expect(map.get("value")).toBe(2);
420
+
421
+ const lastBranchTransaction = branch.core
422
+ .getValidSortedTransactions()
423
+ .at(-1);
424
+ expect(lastBranchTransaction?.madeAt).toBe(
425
+ lastBranchTransaction?.currentMadeAt,
426
+ );
427
+
428
+ const lastMapTransaction = result
429
+ .getValidSortedTransactions()
430
+ .findLast((tx) => tx.txID.branch === branch.id);
431
+ expect(lastMapTransaction?.madeAt).not.toBe(
432
+ lastMapTransaction?.currentMadeAt,
433
+ );
434
+ });
435
+
436
+ test("write permissions should be validated against the time of the merge and not the original madeAt", async () => {
437
+ const alice = setupTestNode({
438
+ connected: true,
439
+ });
440
+ const bob = await setupTestAccount({
441
+ connected: true,
442
+ });
443
+ const group = alice.node.createGroup();
444
+ const map = group.createMap();
445
+ const branchName = "feature-branch";
446
+
447
+ map.set("value", 1, "trusting");
448
+
449
+ const branch = expectMap(
450
+ map.core.createBranch(branchName, group.id).getCurrentContent(),
451
+ );
452
+
453
+ branch.set("value", 2, "trusting");
454
+
455
+ await new Promise((resolve) => setTimeout(resolve, 5));
456
+
457
+ // Grant writer rights to bob after the changes inside the branche
458
+ group.addMember(
459
+ await loadCoValueOrFail(alice.node, bob.accountID),
460
+ "writer",
461
+ );
462
+
463
+ const loadedBranch = await loadCoValueOrFail(bob.node, branch.id);
464
+
465
+ // Bob merges the branch
466
+ const mergeResult = loadedBranch.core.mergeBranch();
467
+
468
+ // The merge should be successful
469
+ expect(expectMap(mergeResult.getCurrentContent()).get("value")).toBe(2);
470
+ });
471
+
472
+ test("should reject edits from kicked out member even with timestamp manipulation", async () => {
473
+ const alice = setupTestNode({
474
+ connected: true,
475
+ });
476
+ const bob = await setupTestAccount({
477
+ connected: true,
478
+ });
479
+ const group = alice.node.createGroup();
480
+ const map = group.createMap();
481
+
482
+ group.addMember(
483
+ await loadCoValueOrFail(alice.node, bob.accountID),
484
+ "writer",
485
+ );
486
+ const timeOnInvitation = Date.now();
487
+
488
+ const bobMap = await loadCoValueOrFail(bob.node, map.id);
489
+
490
+ bobMap.set("value", 1, "trusting");
491
+
492
+ await bobMap.core.waitForSync();
493
+
494
+ const bobGroup = bob.node.createGroup();
495
+ const branch = expectMap(
496
+ bobMap.core
497
+ .createBranch("feature-branch", bobGroup.id)
498
+ .getCurrentContent(),
499
+ );
500
+
501
+ await new Promise((resolve) => setTimeout(resolve, 5));
502
+
503
+ // Alice sets value to 2 and downgrade bob to reader
504
+ map.set("value", 2, "trusting");
505
+ group.addMember(
506
+ await loadCoValueOrFail(alice.node, bob.accountID),
507
+ "reader",
508
+ );
509
+
510
+ await new Promise((resolve) => setTimeout(resolve, 5));
511
+
512
+ branch.set("value", 3, "trusting");
513
+
514
+ // Bob attempts to make an edit after being kicked out by modifying the merge time
515
+ const dateNowMock = vi.spyOn(Date, "now");
516
+ dateNowMock.mockReturnValue(timeOnInvitation + 1);
517
+
518
+ const mergeResult = branch.core.mergeBranch();
519
+
520
+ dateNowMock.mockRestore();
521
+
522
+ // Wait for the full sync to complete
523
+ await waitFor(() => {
524
+ expect(mergeResult.knownState().sessions).toEqual(
525
+ map.core.knownState().sessions,
526
+ );
527
+ });
528
+
529
+ expect(expectMap(map.core.getCurrentContent()).get("value")).toBe(2);
530
+ });
531
+
532
+ test("should alias the txID when a transaction comes from a merge", async () => {
533
+ const client = setupTestNode({
534
+ connected: true,
535
+ });
536
+ const group = client.node.createGroup();
537
+ const map = group.createMap();
538
+
539
+ map.set("key", "value");
540
+
541
+ const branch = map.core
542
+ .createBranch("feature-branch", group.id)
543
+ .getCurrentContent() as RawCoMap;
544
+ branch.set("branchKey", "branchValue");
545
+
546
+ const originalTxID = branch.core
547
+ .getValidTransactions({
548
+ skipBranchSource: true,
549
+ ignorePrivateTransactions: false,
550
+ })
551
+ .at(-1)?.txID;
552
+
553
+ branch.core.mergeBranch();
554
+
555
+ map.set("key2", "value2");
556
+
557
+ const validSortedTransactions = map.core.getValidSortedTransactions();
558
+
559
+ // Only the merged transaction should have the txId changed
560
+ const mergedTransactionIdx = validSortedTransactions.findIndex(
561
+ (tx) => tx.txID.branch,
562
+ );
563
+
564
+ expect(
565
+ validSortedTransactions[mergedTransactionIdx - 1]?.txID.branch,
566
+ ).toBe(undefined);
567
+ expect(validSortedTransactions[mergedTransactionIdx]?.txID).toEqual(
568
+ originalTxID,
569
+ );
570
+ expect(
571
+ validSortedTransactions[mergedTransactionIdx + 1]?.txID.branch,
572
+ ).toBe(undefined);
573
+ });
574
+ });
575
+
576
+ describe("Branching permissions", () => {
577
+ test("should allow the creation of private branches to accounts with read access to the source group", async () => {
578
+ const alice = setupTestNode({
579
+ connected: true,
580
+ });
581
+ const bob = await setupTestAccount({
582
+ connected: true,
583
+ });
584
+ const group = alice.node.createGroup();
585
+ group.addMember(
586
+ await loadCoValueOrFail(alice.node, bob.accountID),
587
+ "reader",
588
+ );
589
+ const map = group.createMap();
590
+ map.set("key", "alice");
591
+
592
+ const bobGroup = bob.node.createGroup();
593
+
594
+ const mapOnBob = await loadCoValueOrFail(bob.node, map.id);
595
+
596
+ const branch = expectMap(
597
+ mapOnBob.core
598
+ .createBranch("feature-branch", bobGroup.id)
599
+ .getCurrentContent(),
600
+ );
601
+
602
+ expect(mapOnBob.core.branches).toEqual([
603
+ {
604
+ branch: "feature-branch",
605
+ ownerId: bobGroup.id,
606
+ },
607
+ ]);
608
+
609
+ expect(branch.id).not.toBe(map.id);
610
+ expect(branch.get("key")).toBe("alice");
611
+ expect(branch.core.getGroup().id).toBe(bobGroup.id);
612
+ expect(branch.core.getGroup().myRole()).toBe("admin");
613
+ branch.set("key", "bob");
614
+
615
+ expect(branch.get("key")).toBe("bob");
616
+ });
617
+
618
+ test("an account with write access to the source and read access to the branch should be able to merge a branch created by a reader", async () => {
619
+ const alice = await setupTestAccount({
620
+ connected: true,
621
+ });
622
+ const bob = await setupTestAccount({
623
+ connected: true,
624
+ });
625
+ const group = alice.node.createGroup();
626
+ group.addMember(
627
+ await loadCoValueOrFail(alice.node, bob.accountID),
628
+ "reader",
629
+ );
630
+ const map = group.createMap();
631
+ map.set("key", "alice");
632
+
633
+ const bobGroup = bob.node.createGroup();
634
+ bobGroup.addMember(
635
+ await loadCoValueOrFail(bob.node, alice.accountID),
636
+ "reader",
637
+ );
638
+
639
+ const mapOnBob = await loadCoValueOrFail(bob.node, map.id);
640
+
641
+ const branch = expectMap(
642
+ mapOnBob.core
643
+ .createBranch("feature-branch", bobGroup.id)
644
+ .getCurrentContent(),
645
+ );
646
+
647
+ branch.set("key", "bob");
648
+
649
+ expect(branch.get("key")).toBe("bob");
650
+
651
+ const branchOnAlice = await loadCoValueOrFail(alice.node, branch.id);
652
+ branchOnAlice.core.mergeBranch();
653
+
654
+ expect(map.get("key")).toBe("bob");
655
+ });
656
+
657
+ test("should not allow the creation of public branches to accounts with read access", async () => {
658
+ const alice = setupTestNode({
659
+ connected: true,
660
+ });
661
+ const bob = await setupTestAccount({
662
+ connected: true,
663
+ });
664
+ const group = alice.node.createGroup();
665
+ group.addMember(
666
+ await loadCoValueOrFail(alice.node, bob.accountID),
667
+ "reader",
668
+ );
669
+ const map = group.createMap();
670
+ map.set("key", "alice");
671
+
672
+ const mapOnBob = await loadCoValueOrFail(bob.node, map.id);
673
+
674
+ const branch = expectMap(
675
+ mapOnBob.core.createBranch("feature-branch").getCurrentContent(),
676
+ );
677
+
678
+ expect(mapOnBob.core.branches).toEqual([]);
679
+
680
+ expect(branch.id).toBe(map.id);
681
+ });
292
682
  });
293
683
 
294
684
  describe("Branch Loading and Checkout", () => {
@@ -560,49 +950,6 @@ describe("Branching Logic", () => {
560
950
  });
561
951
  });
562
952
 
563
- test("should alias the txID when a transaction comes from a merge", async () => {
564
- const client = setupTestNode({
565
- connected: true,
566
- });
567
- const group = client.node.createGroup();
568
- const map = group.createMap();
569
-
570
- map.set("key", "value");
571
-
572
- const branch = map.core
573
- .createBranch("feature-branch", group.id)
574
- .getCurrentContent() as RawCoMap;
575
- branch.set("branchKey", "branchValue");
576
-
577
- const originalTxID = branch.core
578
- .getValidTransactions({
579
- skipBranchSource: true,
580
- ignorePrivateTransactions: false,
581
- })
582
- .at(-1)?.txID;
583
-
584
- branch.core.mergeBranch();
585
-
586
- map.set("key2", "value2");
587
-
588
- const validSortedTransactions = map.core.getValidSortedTransactions();
589
-
590
- // Only the merged transaction should have the txId changed
591
- const mergedTransactionIdx = validSortedTransactions.findIndex(
592
- (tx) => tx.txID.branch,
593
- );
594
-
595
- expect(validSortedTransactions[mergedTransactionIdx - 1]?.txID.branch).toBe(
596
- undefined,
597
- );
598
- expect(validSortedTransactions[mergedTransactionIdx]?.txID).toEqual(
599
- originalTxID,
600
- );
601
- expect(validSortedTransactions[mergedTransactionIdx + 1]?.txID.branch).toBe(
602
- undefined,
603
- );
604
- });
605
-
606
953
  describe("hasBranch", () => {
607
954
  test("should work when the branch owner is the source owner", () => {
608
955
  const client = setupTestNode({
@@ -1,7 +1,7 @@
1
1
  import { describe, expect, test } from "vitest";
2
2
  import { knownStateFromContent } from "../coValueContentMessage.js";
3
- import { emptyKnownState } from "../sync.js";
4
- import type { NewContentMessage } from "../sync.js";
3
+ import { emptyKnownState } from "../knownState.js";
4
+ import { NewContentMessage } from "../sync.js";
5
5
  import type { RawCoID, SessionID } from "../ids.js";
6
6
  import { stableStringify } from "../jsonStringify.js";
7
7
  import { CO_VALUE_PRIORITY } from "../priority.js";