cojson 0.18.5 → 0.18.7

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 (103) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +18 -0
  3. package/dist/coValueContentMessage.d.ts +2 -0
  4. package/dist/coValueContentMessage.d.ts.map +1 -1
  5. package/dist/coValueContentMessage.js +7 -0
  6. package/dist/coValueContentMessage.js.map +1 -1
  7. package/dist/coValueCore/SessionMap.d.ts +2 -2
  8. package/dist/coValueCore/SessionMap.d.ts.map +1 -1
  9. package/dist/coValueCore/SessionMap.js +2 -4
  10. package/dist/coValueCore/SessionMap.js.map +1 -1
  11. package/dist/coValueCore/branching.d.ts +35 -13
  12. package/dist/coValueCore/branching.d.ts.map +1 -1
  13. package/dist/coValueCore/branching.js +55 -37
  14. package/dist/coValueCore/branching.js.map +1 -1
  15. package/dist/coValueCore/coValueCore.d.ts +15 -7
  16. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  17. package/dist/coValueCore/coValueCore.js +126 -35
  18. package/dist/coValueCore/coValueCore.js.map +1 -1
  19. package/dist/coValueCore/verifiedState.d.ts +4 -2
  20. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  21. package/dist/coValueCore/verifiedState.js +6 -4
  22. package/dist/coValueCore/verifiedState.js.map +1 -1
  23. package/dist/coValues/coList.d.ts +8 -2
  24. package/dist/coValues/coList.d.ts.map +1 -1
  25. package/dist/coValues/coList.js +95 -58
  26. package/dist/coValues/coList.js.map +1 -1
  27. package/dist/coValues/coMap.d.ts +2 -2
  28. package/dist/coValues/coMap.d.ts.map +1 -1
  29. package/dist/coValues/coMap.js +8 -8
  30. package/dist/coValues/coMap.js.map +1 -1
  31. package/dist/coValues/group.d.ts.map +1 -1
  32. package/dist/coValues/group.js +14 -1
  33. package/dist/coValues/group.js.map +1 -1
  34. package/dist/config.d.ts +6 -0
  35. package/dist/config.d.ts.map +1 -1
  36. package/dist/config.js +8 -0
  37. package/dist/config.js.map +1 -1
  38. package/dist/crypto/PureJSCrypto.d.ts.map +1 -1
  39. package/dist/crypto/PureJSCrypto.js +14 -6
  40. package/dist/crypto/PureJSCrypto.js.map +1 -1
  41. package/dist/exports.d.ts +5 -4
  42. package/dist/exports.d.ts.map +1 -1
  43. package/dist/exports.js +3 -3
  44. package/dist/exports.js.map +1 -1
  45. package/dist/ids.d.ts +1 -0
  46. package/dist/ids.d.ts.map +1 -1
  47. package/dist/ids.js.map +1 -1
  48. package/dist/localNode.d.ts.map +1 -1
  49. package/dist/localNode.js +7 -2
  50. package/dist/localNode.js.map +1 -1
  51. package/dist/storage/storageAsync.d.ts.map +1 -1
  52. package/dist/storage/storageAsync.js +7 -4
  53. package/dist/storage/storageAsync.js.map +1 -1
  54. package/dist/storage/storageSync.d.ts.map +1 -1
  55. package/dist/storage/storageSync.js +7 -4
  56. package/dist/storage/storageSync.js.map +1 -1
  57. package/dist/sync.d.ts +1 -3
  58. package/dist/sync.d.ts.map +1 -1
  59. package/dist/sync.js +8 -18
  60. package/dist/sync.js.map +1 -1
  61. package/dist/tests/branching.test.js +166 -4
  62. package/dist/tests/branching.test.js.map +1 -1
  63. package/dist/tests/coList.test.js +367 -1
  64. package/dist/tests/coList.test.js.map +1 -1
  65. package/dist/tests/coValueCore.test.js +45 -1
  66. package/dist/tests/coValueCore.test.js.map +1 -1
  67. package/dist/tests/messagesTestUtils.d.ts +1 -1
  68. package/dist/tests/sync.content.test.d.ts +2 -0
  69. package/dist/tests/sync.content.test.d.ts.map +1 -0
  70. package/dist/tests/sync.content.test.js +120 -0
  71. package/dist/tests/sync.content.test.js.map +1 -0
  72. package/dist/tests/sync.load.test.js +4 -4
  73. package/dist/tests/sync.load.test.js.map +1 -1
  74. package/dist/tests/sync.storage.test.js +1 -1
  75. package/dist/tests/sync.storageAsync.test.js +6 -10
  76. package/dist/tests/sync.storageAsync.test.js.map +1 -1
  77. package/dist/tests/sync.upload.test.js +2 -2
  78. package/dist/tests/testUtils.d.ts +2 -2
  79. package/package.json +2 -2
  80. package/src/coValueContentMessage.ts +13 -0
  81. package/src/coValueCore/SessionMap.ts +2 -2
  82. package/src/coValueCore/branching.ts +105 -60
  83. package/src/coValueCore/coValueCore.ts +163 -41
  84. package/src/coValueCore/verifiedState.ts +8 -0
  85. package/src/coValues/coList.ts +129 -78
  86. package/src/coValues/coMap.ts +10 -12
  87. package/src/coValues/group.ts +14 -1
  88. package/src/config.ts +9 -0
  89. package/src/crypto/PureJSCrypto.ts +25 -13
  90. package/src/exports.ts +13 -2
  91. package/src/ids.ts +1 -0
  92. package/src/localNode.ts +8 -2
  93. package/src/storage/storageAsync.ts +8 -5
  94. package/src/storage/storageSync.ts +8 -4
  95. package/src/sync.ts +8 -32
  96. package/src/tests/branching.test.ts +255 -4
  97. package/src/tests/coList.test.ts +529 -1
  98. package/src/tests/coValueCore.test.ts +62 -2
  99. package/src/tests/sync.content.test.ts +153 -0
  100. package/src/tests/sync.load.test.ts +4 -4
  101. package/src/tests/sync.storage.test.ts +1 -1
  102. package/src/tests/sync.storageAsync.test.ts +9 -12
  103. package/src/tests/sync.upload.test.ts +2 -2
@@ -1,10 +1,11 @@
1
- import { beforeEach, describe, expect, test } from "vitest";
1
+ import { assert, beforeEach, describe, expect, test } from "vitest";
2
2
  import {
3
3
  createTestNode,
4
4
  setupTestNode,
5
5
  loadCoValueOrFail,
6
6
  } from "./testUtils.js";
7
- import { expectMap } from "../coValue.js";
7
+ import { expectList, expectMap, expectPlainText } from "../coValue.js";
8
+ import { RawCoMap } from "../exports.js";
8
9
 
9
10
  let jazzCloud: ReturnType<typeof setupTestNode>;
10
11
 
@@ -94,7 +95,7 @@ describe("Branching Logic", () => {
94
95
  const result = expectMap(branch.core.mergeBranch().getCurrentContent());
95
96
 
96
97
  // Verify only one merge commit was created
97
- expect(result.core.mergeCommits.length).toBe(1);
98
+ expect(branch.core.mergeCommits.length).toBe(1);
98
99
 
99
100
  // Verify source contains branch transactions
100
101
  expect(result.get("key1")).toBe("branchValue1");
@@ -154,12 +155,134 @@ describe("Branching Logic", () => {
154
155
  branch.core.mergeBranch();
155
156
 
156
157
  // Verify two merge commits exist
157
- expect(originalMap.core.mergeCommits.length).toBe(2);
158
+ expect(branch.core.mergeCommits.length).toBe(2);
158
159
 
159
160
  // Verify both changes are now in original map
160
161
  expect(originalMap.get("key1")).toBe("branchValue1");
161
162
  expect(originalMap.get("key2")).toBe("branchValue2");
162
163
  });
164
+
165
+ test("should work with co.list", () => {
166
+ const node = createTestNode();
167
+ const group = node.createGroup();
168
+ const list = group.createList();
169
+
170
+ // Create a shopping list with grocery items
171
+ list.appendItems(["bread", "milk", "eggs"]);
172
+
173
+ // Remove milk from the list
174
+ list.delete(list.asArray().indexOf("milk"));
175
+
176
+ const branch = expectList(
177
+ list.core.createBranch("feature-branch", group.id).getCurrentContent(),
178
+ );
179
+
180
+ // Add more items to the branch
181
+ branch.appendItems(["cheese", "yogurt", "bananas"]);
182
+
183
+ // Remove yogurt from the branch
184
+ branch.delete(branch.asArray().indexOf("yogurt"));
185
+
186
+ const result = expectList(branch.core.mergeBranch().getCurrentContent());
187
+
188
+ expect(result.toJSON()).toEqual(["bread", "eggs", "cheese", "bananas"]);
189
+ });
190
+
191
+ test("should work with co.list when branching from different session", async () => {
192
+ const client = setupTestNode({
193
+ connected: true,
194
+ });
195
+ const group = client.node.createGroup();
196
+ const list = group.createList();
197
+
198
+ // Create a grocery list with initial items
199
+ list.appendItems(["bread", "milk"]);
200
+
201
+ const branch1 = expectList(
202
+ list.core.createBranch("feature-branch", group.id).getCurrentContent(),
203
+ );
204
+
205
+ // Add new items to first branch
206
+ branch1.appendItems(["cheese"]);
207
+
208
+ const branch2 = expectList(
209
+ list.core
210
+ .createBranch("feature-branch-2", group.id)
211
+ .getCurrentContent(),
212
+ );
213
+
214
+ await new Promise((resolve) => setTimeout(resolve, 5));
215
+
216
+ // Add different items to second branch
217
+ branch2.appendItems(["apples", "oranges", "carrots"]);
218
+
219
+ const anotherSession = client.spawnNewSession();
220
+
221
+ const loadedBranch2 = await loadCoValueOrFail(
222
+ anotherSession.node,
223
+ branch2.id,
224
+ );
225
+
226
+ // Add more items and remove some existing ones
227
+ loadedBranch2.appendItems(["tomatoes", "lettuce", "cucumber"]);
228
+ loadedBranch2.delete(loadedBranch2.asArray().indexOf("lettuce"));
229
+ loadedBranch2.delete(loadedBranch2.asArray().indexOf("milk"));
230
+
231
+ loadedBranch2.core.mergeBranch();
232
+
233
+ await loadedBranch2.core.waitForSync();
234
+
235
+ branch1.core.mergeBranch();
236
+
237
+ expect(list.toJSON()).toEqual([
238
+ "bread",
239
+ "apples",
240
+ "oranges",
241
+ "carrots",
242
+ "tomatoes",
243
+ "cucumber",
244
+ "cheese",
245
+ ]);
246
+ });
247
+
248
+ test("should work with co.plainText when merging the same branch twice on different sessions", async () => {
249
+ const client = setupTestNode({
250
+ connected: true,
251
+ });
252
+ const group = client.node.createGroup();
253
+ const plainText = group.createPlainText();
254
+
255
+ plainText.insertAfter(0, "hello");
256
+
257
+ const branch = expectPlainText(
258
+ plainText.core
259
+ .createBranch("feature-branch", group.id)
260
+ .getCurrentContent(),
261
+ );
262
+
263
+ branch.insertAfter("hello".length, " world");
264
+
265
+ const anotherSession = client.spawnNewSession();
266
+
267
+ const loadedBranch = await loadCoValueOrFail(
268
+ anotherSession.node,
269
+ branch.id,
270
+ );
271
+ assert(loadedBranch);
272
+
273
+ anotherSession.connectToSyncServer().peerState.gracefulShutdown();
274
+
275
+ // Add more items to the branch
276
+ loadedBranch.insertAfter("hello world".length, " people");
277
+
278
+ branch.core.mergeBranch();
279
+ const loadedBranchMergeResult = loadedBranch.core.mergeBranch();
280
+
281
+ anotherSession.connectToSyncServer();
282
+ await loadedBranchMergeResult.waitForSync();
283
+
284
+ expect(plainText.toString()).toEqual("hello world people");
285
+ });
163
286
  });
164
287
 
165
288
  describe("Branch Loading and Checkout", () => {
@@ -425,4 +548,132 @@ describe("Branching Logic", () => {
425
548
  expect(aliceBranch.get("bob")).toBe(true);
426
549
  });
427
550
  });
551
+
552
+ test("should alias the txID when a transaction comes from a merge", async () => {
553
+ const client = setupTestNode({
554
+ connected: true,
555
+ });
556
+ const group = client.node.createGroup();
557
+ const map = group.createMap();
558
+
559
+ map.set("key", "value");
560
+
561
+ const branch = map.core
562
+ .createBranch("feature-branch", group.id)
563
+ .getCurrentContent() as RawCoMap;
564
+ branch.set("branchKey", "branchValue");
565
+
566
+ const originalTxID = branch.core
567
+ .getValidTransactions({
568
+ skipBranchSource: true,
569
+ ignorePrivateTransactions: false,
570
+ })
571
+ .at(-1)?.txID;
572
+
573
+ branch.core.mergeBranch();
574
+
575
+ map.set("key2", "value2");
576
+
577
+ const validSortedTransactions = map.core.getValidSortedTransactions();
578
+
579
+ // Only the merged transaction should have the txId changed
580
+ const mergedTransactionIdx = validSortedTransactions.findIndex(
581
+ (tx) => tx.txID.branch,
582
+ );
583
+
584
+ expect(validSortedTransactions[mergedTransactionIdx - 1]?.txID.branch).toBe(
585
+ undefined,
586
+ );
587
+ expect(validSortedTransactions[mergedTransactionIdx]?.txID).toEqual(
588
+ originalTxID,
589
+ );
590
+ expect(validSortedTransactions[mergedTransactionIdx + 1]?.txID.branch).toBe(
591
+ undefined,
592
+ );
593
+ });
594
+
595
+ describe("hasBranch", () => {
596
+ test("should work when the branch owner is the source owner", () => {
597
+ const client = setupTestNode({
598
+ connected: true,
599
+ });
600
+ const group = client.node.createGroup();
601
+ const map = group.createMap();
602
+
603
+ map.set("key", "value");
604
+
605
+ const branch = map.core.createBranch("feature-branch", group.id);
606
+
607
+ expect(map.core.hasBranch("feature-branch")).toBe(true);
608
+ expect(map.core.hasBranch("feature-branch", group.id)).toBe(true);
609
+ expect(branch.hasBranch("feature-branch")).toBe(false);
610
+ });
611
+
612
+ test("should work when the branch onwer is implicit", () => {
613
+ const client = setupTestNode({
614
+ connected: true,
615
+ });
616
+ const group = client.node.createGroup();
617
+ const map = group.createMap();
618
+
619
+ map.set("key", "value");
620
+
621
+ const branch = map.core.createBranch("feature-branch");
622
+
623
+ expect(map.core.hasBranch("feature-branch")).toBe(true);
624
+ expect(map.core.hasBranch("feature-branch", group.id)).toBe(true);
625
+ expect(branch.hasBranch("feature-branch")).toBe(false);
626
+ });
627
+
628
+ test("should return false for non-existent branch name", () => {
629
+ const client = setupTestNode({
630
+ connected: true,
631
+ });
632
+ const group = client.node.createGroup();
633
+ const map = group.createMap();
634
+
635
+ map.set("key", "value");
636
+
637
+ expect(map.core.hasBranch("non-existent-branch")).toBe(false);
638
+ });
639
+
640
+ test("should work with explicit ownerId parameter", () => {
641
+ const client = setupTestNode({
642
+ connected: true,
643
+ });
644
+ const group = client.node.createGroup();
645
+ const map = group.createMap();
646
+
647
+ map.set("key", "value");
648
+
649
+ const differentGroup = client.node.createGroup();
650
+
651
+ map.core.createBranch("feature-branch", differentGroup.id);
652
+
653
+ // Test with explicit ownerId
654
+ expect(map.core.hasBranch("feature-branch", differentGroup.id)).toBe(
655
+ true,
656
+ );
657
+ expect(map.core.hasBranch("feature-branch")).toBe(false);
658
+ });
659
+
660
+ test("should work when the transactions have not been parsed yet", async () => {
661
+ const client = setupTestNode({
662
+ connected: true,
663
+ });
664
+ const group = client.node.createGroup();
665
+ const map = group.createMap();
666
+
667
+ map.set("key", "value");
668
+
669
+ map.core.createBranch("feature-branch", group.id);
670
+
671
+ await map.core.waitForSync();
672
+
673
+ const newSession = client.spawnNewSession();
674
+ const loadedMapCore = await newSession.node.loadCoValueCore(map.core.id);
675
+
676
+ expect(loadedMapCore.hasBranch("feature-branch", group.id)).toBe(true);
677
+ });
678
+ });
428
679
  });