cojson 0.18.28 → 0.18.30

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 (144) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +16 -0
  3. package/dist/PeerState.d.ts +23 -14
  4. package/dist/PeerState.d.ts.map +1 -1
  5. package/dist/PeerState.js +74 -23
  6. package/dist/PeerState.js.map +1 -1
  7. package/dist/SyncStateManager.d.ts +3 -3
  8. package/dist/SyncStateManager.d.ts.map +1 -1
  9. package/dist/SyncStateManager.js +18 -44
  10. package/dist/SyncStateManager.js.map +1 -1
  11. package/dist/coValueContentMessage.d.ts.map +1 -1
  12. package/dist/coValueContentMessage.js +2 -1
  13. package/dist/coValueContentMessage.js.map +1 -1
  14. package/dist/coValueCore/PeerKnownState.d.ts +21 -0
  15. package/dist/coValueCore/PeerKnownState.d.ts.map +1 -0
  16. package/dist/coValueCore/PeerKnownState.js +52 -0
  17. package/dist/coValueCore/PeerKnownState.js.map +1 -0
  18. package/dist/coValueCore/coValueCore.d.ts +39 -8
  19. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  20. package/dist/coValueCore/coValueCore.js +139 -40
  21. package/dist/coValueCore/coValueCore.js.map +1 -1
  22. package/dist/coValueCore/decryptTransactionChangesAndMeta.d.ts.map +1 -1
  23. package/dist/coValueCore/decryptTransactionChangesAndMeta.js +0 -5
  24. package/dist/coValueCore/decryptTransactionChangesAndMeta.js.map +1 -1
  25. package/dist/coValueCore/verifiedState.d.ts +0 -14
  26. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  27. package/dist/coValueCore/verifiedState.js +2 -32
  28. package/dist/coValueCore/verifiedState.js.map +1 -1
  29. package/dist/coValues/coList.d.ts +3 -4
  30. package/dist/coValues/coList.d.ts.map +1 -1
  31. package/dist/coValues/coList.js +4 -4
  32. package/dist/coValues/coList.js.map +1 -1
  33. package/dist/coValues/coMap.d.ts +3 -4
  34. package/dist/coValues/coMap.d.ts.map +1 -1
  35. package/dist/coValues/coMap.js +5 -4
  36. package/dist/coValues/coMap.js.map +1 -1
  37. package/dist/coValues/coStream.d.ts +3 -3
  38. package/dist/coValues/coStream.d.ts.map +1 -1
  39. package/dist/coValues/coStream.js +3 -4
  40. package/dist/coValues/coStream.js.map +1 -1
  41. package/dist/coValues/group.d.ts +3 -3
  42. package/dist/coValues/group.d.ts.map +1 -1
  43. package/dist/coValues/group.js +74 -52
  44. package/dist/coValues/group.js.map +1 -1
  45. package/dist/exports.d.ts +2 -2
  46. package/dist/exports.d.ts.map +1 -1
  47. package/dist/exports.js +2 -2
  48. package/dist/exports.js.map +1 -1
  49. package/dist/localNode.d.ts.map +1 -1
  50. package/dist/localNode.js +7 -5
  51. package/dist/localNode.js.map +1 -1
  52. package/dist/permissions.d.ts +5 -1
  53. package/dist/permissions.d.ts.map +1 -1
  54. package/dist/permissions.js +173 -109
  55. package/dist/permissions.js.map +1 -1
  56. package/dist/sync.d.ts.map +1 -1
  57. package/dist/sync.js +33 -44
  58. package/dist/sync.js.map +1 -1
  59. package/dist/tests/PeerKnownState.test.d.ts +2 -0
  60. package/dist/tests/PeerKnownState.test.d.ts.map +1 -0
  61. package/dist/tests/PeerKnownState.test.js +342 -0
  62. package/dist/tests/PeerKnownState.test.js.map +1 -0
  63. package/dist/tests/PeerState.test.js +17 -16
  64. package/dist/tests/PeerState.test.js.map +1 -1
  65. package/dist/tests/StorageApiAsync.test.js +12 -12
  66. package/dist/tests/StorageApiAsync.test.js.map +1 -1
  67. package/dist/tests/StorageApiSync.test.js +11 -11
  68. package/dist/tests/StorageApiSync.test.js.map +1 -1
  69. package/dist/tests/SyncStateManager.test.js +16 -21
  70. package/dist/tests/SyncStateManager.test.js.map +1 -1
  71. package/dist/tests/coValueCore.dependencies.test.js +59 -0
  72. package/dist/tests/coValueCore.dependencies.test.js.map +1 -1
  73. package/dist/tests/coValueCore.test.js +41 -21
  74. package/dist/tests/coValueCore.test.js.map +1 -1
  75. package/dist/tests/group.addMember.test.js +266 -219
  76. package/dist/tests/group.addMember.test.js.map +1 -1
  77. package/dist/tests/group.inheritance.test.js +12 -0
  78. package/dist/tests/group.inheritance.test.js.map +1 -1
  79. package/dist/tests/group.invite.test.js +77 -0
  80. package/dist/tests/group.invite.test.js.map +1 -1
  81. package/dist/tests/group.removeMember.test.js +64 -7
  82. package/dist/tests/group.removeMember.test.js.map +1 -1
  83. package/dist/tests/group.roleOf.test.js +14 -4
  84. package/dist/tests/group.roleOf.test.js.map +1 -1
  85. package/dist/tests/permissions.test.js +51 -202
  86. package/dist/tests/permissions.test.js.map +1 -1
  87. package/dist/tests/sync.content.test.js +2 -2
  88. package/dist/tests/sync.content.test.js.map +1 -1
  89. package/dist/tests/sync.invite.test.js +6 -6
  90. package/dist/tests/sync.load.test.js +22 -22
  91. package/dist/tests/sync.mesh.test.js +9 -9
  92. package/dist/tests/sync.storage.test.js +13 -7
  93. package/dist/tests/sync.storage.test.js.map +1 -1
  94. package/dist/tests/sync.storageAsync.test.js +3 -3
  95. package/dist/tests/sync.test.js +13 -33
  96. package/dist/tests/sync.test.js.map +1 -1
  97. package/dist/tests/sync.upload.test.js +2 -2
  98. package/package.json +3 -3
  99. package/src/PeerState.ts +86 -34
  100. package/src/SyncStateManager.ts +25 -60
  101. package/src/coValueContentMessage.ts +3 -1
  102. package/src/coValueCore/PeerKnownState.ts +74 -0
  103. package/src/coValueCore/coValueCore.ts +180 -49
  104. package/src/coValueCore/decryptTransactionChangesAndMeta.ts +0 -6
  105. package/src/coValueCore/verifiedState.ts +2 -37
  106. package/src/coValues/coList.ts +7 -7
  107. package/src/coValues/coMap.ts +9 -7
  108. package/src/coValues/coStream.ts +6 -5
  109. package/src/coValues/group.ts +99 -60
  110. package/src/exports.ts +2 -1
  111. package/src/localNode.ts +7 -5
  112. package/src/permissions.ts +204 -123
  113. package/src/sync.ts +37 -53
  114. package/src/tests/PeerKnownState.test.ts +426 -0
  115. package/src/tests/PeerState.test.ts +24 -24
  116. package/src/tests/StorageApiAsync.test.ts +12 -12
  117. package/src/tests/StorageApiSync.test.ts +11 -11
  118. package/src/tests/SyncStateManager.test.ts +23 -53
  119. package/src/tests/coValueCore.dependencies.test.ts +87 -0
  120. package/src/tests/coValueCore.test.ts +64 -22
  121. package/src/tests/group.addMember.test.ts +384 -345
  122. package/src/tests/group.inheritance.test.ts +33 -0
  123. package/src/tests/group.invite.test.ts +117 -0
  124. package/src/tests/group.removeMember.test.ts +95 -9
  125. package/src/tests/group.roleOf.test.ts +16 -4
  126. package/src/tests/permissions.test.ts +56 -295
  127. package/src/tests/sync.content.test.ts +2 -2
  128. package/src/tests/sync.invite.test.ts +6 -6
  129. package/src/tests/sync.load.test.ts +22 -22
  130. package/src/tests/sync.mesh.test.ts +9 -9
  131. package/src/tests/sync.storage.test.ts +13 -8
  132. package/src/tests/sync.storageAsync.test.ts +3 -3
  133. package/src/tests/sync.test.ts +21 -50
  134. package/src/tests/sync.upload.test.ts +2 -2
  135. package/dist/PeerKnownStates.d.ts +0 -19
  136. package/dist/PeerKnownStates.d.ts.map +0 -1
  137. package/dist/PeerKnownStates.js +0 -64
  138. package/dist/PeerKnownStates.js.map +0 -1
  139. package/dist/tests/PeerKnownStates.test.d.ts +0 -2
  140. package/dist/tests/PeerKnownStates.test.d.ts.map +0 -1
  141. package/dist/tests/PeerKnownStates.test.js +0 -77
  142. package/dist/tests/PeerKnownStates.test.js.map +0 -1
  143. package/src/PeerKnownStates.ts +0 -93
  144. package/src/tests/PeerKnownStates.test.ts +0 -99
@@ -154,14 +154,14 @@ describe("multiple clients syncing with the a cloud-like server mesh", () => {
154
154
  [
155
155
  "edge-france -> storage | CONTENT Group header: true new: After: 0 New: 3",
156
156
  "edge-france -> core | CONTENT Group header: true new: After: 0 New: 3",
157
- "edge-france -> storage | CONTENT ParentGroup header: true new: After: 0 New: 6",
158
- "edge-france -> core | CONTENT ParentGroup header: true new: After: 0 New: 6",
157
+ "edge-france -> storage | CONTENT ParentGroup header: true new: After: 0 New: 5",
158
+ "edge-france -> core | CONTENT ParentGroup header: true new: After: 0 New: 5",
159
159
  "edge-france -> storage | CONTENT Group header: false new: After: 3 New: 2",
160
160
  "edge-france -> core | CONTENT Group header: false new: After: 3 New: 2",
161
161
  "core -> edge-france | KNOWN Group sessions: header/3",
162
162
  "core -> storage | CONTENT Group header: true new: After: 0 New: 3",
163
- "core -> edge-france | KNOWN ParentGroup sessions: header/6",
164
- "core -> storage | CONTENT ParentGroup header: true new: After: 0 New: 6",
163
+ "core -> edge-france | KNOWN ParentGroup sessions: header/5",
164
+ "core -> storage | CONTENT ParentGroup header: true new: After: 0 New: 5",
165
165
  "core -> edge-france | KNOWN Group sessions: header/5",
166
166
  "core -> storage | CONTENT Group header: false new: After: 3 New: 2",
167
167
  "edge-france -> storage | CONTENT Map header: true new: After: 0 New: 1",
@@ -172,19 +172,19 @@ describe("multiple clients syncing with the a cloud-like server mesh", () => {
172
172
  "edge-italy -> storage | LOAD Map sessions: empty",
173
173
  "storage -> edge-italy | KNOWN Map sessions: empty",
174
174
  "edge-italy -> core | LOAD Map sessions: empty",
175
- "core -> edge-italy | CONTENT ParentGroup header: true new: After: 0 New: 6",
175
+ "core -> edge-italy | CONTENT ParentGroup header: true new: After: 0 New: 5",
176
176
  "core -> edge-italy | CONTENT Group header: true new: After: 0 New: 5",
177
177
  "core -> edge-italy | CONTENT Map header: true new: After: 0 New: 1",
178
- "edge-italy -> core | KNOWN ParentGroup sessions: header/6",
179
- "edge-italy -> storage | CONTENT ParentGroup header: true new: After: 0 New: 6",
178
+ "edge-italy -> core | KNOWN ParentGroup sessions: header/5",
179
+ "edge-italy -> storage | CONTENT ParentGroup header: true new: After: 0 New: 5",
180
180
  "edge-italy -> core | KNOWN Group sessions: header/5",
181
181
  "edge-italy -> storage | CONTENT Group header: true new: After: 0 New: 5",
182
182
  "edge-italy -> core | KNOWN Map sessions: header/1",
183
183
  "edge-italy -> storage | CONTENT Map header: true new: After: 0 New: 1",
184
- "edge-italy -> client | CONTENT ParentGroup header: true new: After: 0 New: 6",
184
+ "edge-italy -> client | CONTENT ParentGroup header: true new: After: 0 New: 5",
185
185
  "edge-italy -> client | CONTENT Group header: true new: After: 0 New: 5",
186
186
  "edge-italy -> client | CONTENT Map header: true new: After: 0 New: 1",
187
- "client -> edge-italy | KNOWN ParentGroup sessions: header/6",
187
+ "client -> edge-italy | KNOWN ParentGroup sessions: header/5",
188
188
  "client -> edge-italy | KNOWN Group sessions: header/5",
189
189
  "client -> edge-italy | KNOWN Map sessions: header/1",
190
190
  ]
@@ -138,11 +138,11 @@ describe("client with storage syncs with server", () => {
138
138
  "client -> storage | LOAD Map sessions: empty",
139
139
  "storage -> client | KNOWN Map sessions: empty",
140
140
  "client -> server | LOAD Map sessions: empty",
141
- "server -> client | CONTENT ParentGroup header: true new: After: 0 New: 6",
141
+ "server -> client | CONTENT ParentGroup header: true new: After: 0 New: 5",
142
142
  "server -> client | CONTENT Group header: true new: After: 0 New: 5",
143
143
  "server -> client | CONTENT Map header: true new: After: 0 New: 1",
144
- "client -> server | KNOWN ParentGroup sessions: header/6",
145
- "client -> storage | CONTENT ParentGroup header: true new: After: 0 New: 6",
144
+ "client -> server | KNOWN ParentGroup sessions: header/5",
145
+ "client -> storage | CONTENT ParentGroup header: true new: After: 0 New: 5",
146
146
  "client -> server | KNOWN Group sessions: header/5",
147
147
  "client -> storage | CONTENT Group header: true new: After: 0 New: 5",
148
148
  "client -> server | KNOWN Map sessions: header/1",
@@ -436,7 +436,7 @@ describe("client syncs with a server with storage", () => {
436
436
  expect(streamingCounterDuringLoad).toBe(1);
437
437
 
438
438
  const mapOnClient2 = await promise;
439
- await mapOnClient2.core.waitForSync();
439
+ await mapOnClient2.core.waitForFullStreaming();
440
440
 
441
441
  // Test streaming counter after loading is complete (should be 0)
442
442
  await waitFor(async () => {
@@ -649,8 +649,9 @@ describe("client syncs with a server with storage", () => {
649
649
  });
650
650
 
651
651
  test("should store values with no transactions", async () => {
652
- const alice = setupTestNode({
653
- connected: true,
652
+ const alice = setupTestNode();
653
+ alice.connectToSyncServer({
654
+ ourName: "alice",
654
655
  });
655
656
  const group = alice.node.createGroup();
656
657
  group.addMember("everyone", "writer");
@@ -666,8 +667,6 @@ describe("client syncs with a server with storage", () => {
666
667
  ourName: "bob",
667
668
  });
668
669
 
669
- SyncMessagesLog.clear(); // We want to focus on the sync messages happening from now
670
-
671
670
  await loadCoValueOrFail(bob.node, map.id);
672
671
 
673
672
  // The map should be stored in bob's storage
@@ -684,9 +683,15 @@ describe("client syncs with a server with storage", () => {
684
683
  }),
685
684
  ).toMatchInlineSnapshot(`
686
685
  [
686
+ "alice -> server | CONTENT Group header: true new: After: 0 New: 5",
687
+ "alice -> server | CONTENT Map header: true new: ",
687
688
  "bob -> storage | LOAD Map sessions: empty",
688
689
  "storage -> bob | KNOWN Map sessions: empty",
689
690
  "bob -> server | LOAD Map sessions: empty",
691
+ "server -> alice | KNOWN Group sessions: header/5",
692
+ "server -> storage | CONTENT Group header: true new: After: 0 New: 5",
693
+ "server -> alice | KNOWN Map sessions: header/0",
694
+ "server -> storage | CONTENT Map header: true new: ",
690
695
  "server -> bob | CONTENT Group header: true new: After: 0 New: 5",
691
696
  "server -> bob | CONTENT Map header: true new: ",
692
697
  "bob -> server | KNOWN Group sessions: header/5",
@@ -133,11 +133,11 @@ describe("client with storage syncs with server", () => {
133
133
  "client -> storage | LOAD Map sessions: empty",
134
134
  "storage -> client | KNOWN Map sessions: empty",
135
135
  "client -> server | LOAD Map sessions: empty",
136
- "server -> client | CONTENT ParentGroup header: true new: After: 0 New: 6",
136
+ "server -> client | CONTENT ParentGroup header: true new: After: 0 New: 5",
137
137
  "server -> client | CONTENT Group header: true new: After: 0 New: 5",
138
138
  "server -> client | CONTENT Map header: true new: After: 0 New: 1",
139
- "client -> server | KNOWN ParentGroup sessions: header/6",
140
- "client -> storage | CONTENT ParentGroup header: true new: After: 0 New: 6",
139
+ "client -> server | KNOWN ParentGroup sessions: header/5",
140
+ "client -> storage | CONTENT ParentGroup header: true new: After: 0 New: 5",
141
141
  "client -> server | KNOWN Group sessions: header/5",
142
142
  "client -> storage | CONTENT Group header: true new: After: 0 New: 5",
143
143
  "client -> server | KNOWN Map sessions: header/1",
@@ -608,13 +608,13 @@ describe("SyncManager - knownStates vs optimisticKnownStates", () => {
608
608
 
609
609
  // The optimisticKnownStates should be the same as the knownStates after the full sync is complete
610
610
  expect(
611
- peerStateClient.optimisticKnownStates.get(mapOnClient.core.id),
612
- ).toEqual(peerStateClient.knownStates.get(mapOnClient.core.id));
611
+ peerStateClient.getOptimisticKnownState(mapOnClient.core.id),
612
+ ).toEqual(peerStateClient.getKnownState(mapOnClient.core.id));
613
613
 
614
614
  // On the other node the knownStates should be updated correctly based on the messages we received
615
615
  expect(
616
- peerStateJazzCloud.optimisticKnownStates.get(mapOnClient.core.id),
617
- ).toEqual(peerStateJazzCloud.knownStates.get(mapOnClient.core.id));
616
+ peerStateJazzCloud.getOptimisticKnownState(mapOnClient.core.id),
617
+ ).toEqual(peerStateJazzCloud.getKnownState(mapOnClient.core.id));
618
618
  });
619
619
 
620
620
  test("optimisticKnownStates is updated as new transactions are sent, while knownStates only when the updates are acknowledged", async () => {
@@ -642,8 +642,8 @@ describe("SyncManager - knownStates vs optimisticKnownStates", () => {
642
642
 
643
643
  await new Promise<void>(queueMicrotask);
644
644
 
645
- expect(peerState.optimisticKnownStates.get(map.core.id)).not.toEqual(
646
- peerState.knownStates.get(map.core.id),
645
+ expect(peerState.getOptimisticKnownState(map.core.id)).not.toEqual(
646
+ peerState.getKnownState(map.core.id),
647
647
  );
648
648
 
649
649
  // Restore the implementation of push and send the blocked messages
@@ -654,45 +654,13 @@ describe("SyncManager - knownStates vs optimisticKnownStates", () => {
654
654
 
655
655
  await map.core.waitForSync();
656
656
 
657
- expect(peerState.optimisticKnownStates.get(map.core.id)).toEqual(
658
- peerState.knownStates.get(map.core.id),
657
+ expect(peerState.getOptimisticKnownState(map.core.id)).toEqual(
658
+ peerState.getKnownState(map.core.id),
659
659
  );
660
660
  });
661
661
  });
662
662
 
663
663
  describe("SyncManager.addPeer", () => {
664
- test("new peer gets a copy of previous peer's knownStates when replacing it", async () => {
665
- const client = await setupTestAccount();
666
-
667
- const { peerState: firstPeerState, getCurrentPeerState } =
668
- client.connectToSyncServer();
669
-
670
- // Create test data
671
- const group = client.node.createGroup();
672
- const map = group.createMap();
673
- map.set("key1", "value1", "trusting");
674
-
675
- // Wait for initial sync
676
- await map.core.waitForSync();
677
-
678
- // Store the initial known states
679
- const initialKnownStates = firstPeerState.knownStates;
680
-
681
- // Create new connection with same ID
682
- client.connectToSyncServer();
683
-
684
- // Wait for the new peer to be added
685
- await waitFor(() => expect(getCurrentPeerState()).not.toBe(firstPeerState));
686
-
687
- // Verify that the new peer has a copy of the previous known states
688
- const newPeerKnownStates = getCurrentPeerState().knownStates;
689
-
690
- expect(newPeerKnownStates).not.toBe(initialKnownStates); // Should be a different instance
691
- expect(newPeerKnownStates.get(map.core.id)).toEqual(
692
- initialKnownStates.get(map.core.id),
693
- );
694
- });
695
-
696
664
  test("new peer with new ID starts with empty knownStates", async () => {
697
665
  const client = await setupTestAccount({
698
666
  connected: true,
@@ -716,9 +684,8 @@ describe("SyncManager.addPeer", () => {
716
684
  client.node.syncManager.addPeer(brandNewPeer);
717
685
 
718
686
  // Verify that the new peer starts with empty known states
719
- const newPeerKnownStates =
720
- client.node.syncManager.peers["brandNewPeer"]!.knownStates;
721
- expect(newPeerKnownStates.get(map.core.id)).toBe(undefined);
687
+ const newPeerState = client.node.syncManager.peers["brandNewPeer"];
688
+ expect(newPeerState?.getKnownState(map.core.id)).toBe(undefined);
722
689
  });
723
690
 
724
691
  test("when adding a peer with the same ID as a previous peer, the previous peer is closed", async () => {
@@ -1071,8 +1038,10 @@ describe("SyncManager.handleSyncMessage", () => {
1071
1038
  await client.node.syncManager.handleSyncMessage(invalidMessage, peerState);
1072
1039
 
1073
1040
  // Verify that no state changes occurred
1074
- expect(peerState.knownStates.has(invalidMessage.id)).toBe(false);
1075
- expect(peerState.optimisticKnownStates.has(invalidMessage.id)).toBe(false);
1041
+ expect(peerState.getKnownState(invalidMessage.id)).toBe(undefined);
1042
+ expect(peerState.getOptimisticKnownState(invalidMessage.id)).toBe(
1043
+ undefined,
1044
+ );
1076
1045
  });
1077
1046
 
1078
1047
  test("should ignore messages with invalid ID format", async () => {
@@ -1091,8 +1060,10 @@ describe("SyncManager.handleSyncMessage", () => {
1091
1060
  client.node.syncManager.handleSyncMessage(invalidMessage, peerState);
1092
1061
 
1093
1062
  // Verify that no state changes occurred
1094
- expect(peerState.knownStates.has(invalidMessage.id)).toBe(false);
1095
- expect(peerState.optimisticKnownStates.has(invalidMessage.id)).toBe(false);
1063
+ expect(peerState.getKnownState(invalidMessage.id)).toBe(undefined);
1064
+ expect(peerState.getOptimisticKnownState(invalidMessage.id)).toBe(
1065
+ undefined,
1066
+ );
1096
1067
  });
1097
1068
 
1098
1069
  test("should ignore messages for errored coValues", async () => {
@@ -1116,8 +1087,8 @@ describe("SyncManager.handleSyncMessage", () => {
1116
1087
  await client.node.syncManager.handleSyncMessage(message, peerState);
1117
1088
 
1118
1089
  // Verify that no state changes occurred
1119
- expect(peerState.knownStates.has(message.id)).toBe(false);
1120
- expect(peerState.optimisticKnownStates.has(message.id)).toBe(false);
1090
+ expect(peerState.getKnownState(message.id)).toBe(undefined);
1091
+ expect(peerState.getOptimisticKnownState(message.id)).toBe(undefined);
1121
1092
  });
1122
1093
 
1123
1094
  test("should process valid messages", async () => {
@@ -1137,7 +1108,7 @@ describe("SyncManager.handleSyncMessage", () => {
1137
1108
  await client.node.syncManager.handleSyncMessage(validMessage, peerState);
1138
1109
 
1139
1110
  // Verify that the message was processed
1140
- expect(peerState.knownStates.has(group.id)).toBe(true);
1111
+ expect(peerState.getKnownState(group.id)).toBeDefined();
1141
1112
  });
1142
1113
  });
1143
1114
 
@@ -164,11 +164,11 @@ describe("client to server upload", () => {
164
164
  ).toMatchInlineSnapshot(`
165
165
  [
166
166
  "client -> server | CONTENT Group header: true new: After: 0 New: 3",
167
- "client -> server | CONTENT ParentGroup header: true new: After: 0 New: 6",
167
+ "client -> server | CONTENT ParentGroup header: true new: After: 0 New: 5",
168
168
  "client -> server | CONTENT Group header: false new: After: 3 New: 2",
169
169
  "client -> server | CONTENT Map header: true new: After: 0 New: 1",
170
170
  "server -> client | KNOWN Group sessions: header/3",
171
- "server -> client | KNOWN ParentGroup sessions: header/6",
171
+ "server -> client | KNOWN ParentGroup sessions: header/5",
172
172
  "server -> client | KNOWN Group sessions: header/5",
173
173
  "server -> client | KNOWN Map sessions: header/1",
174
174
  ]
@@ -1,19 +0,0 @@
1
- import { RawCoID, SessionID } from "./ids.js";
2
- import { CoValueKnownState } from "./knownState.js";
3
- export declare class PeerKnownStates {
4
- private coValues;
5
- getKnownState(id: RawCoID): CoValueKnownState;
6
- updateHeader(id: RawCoID, header: boolean): void;
7
- combineWith(id: RawCoID, value: CoValueKnownState): void;
8
- updateSessionCounter(id: RawCoID, sessionId: SessionID, value: number): void;
9
- set(id: RawCoID, payload: CoValueKnownState | "empty"): void;
10
- get(id: RawCoID): CoValueKnownState | undefined;
11
- has(id: RawCoID): boolean;
12
- clone(): PeerKnownStates;
13
- listeners: Set<(id: RawCoID, knownState: CoValueKnownState) => void>;
14
- private triggerUpdate;
15
- private trigger;
16
- subscribe(listener: (id: RawCoID, knownState: CoValueKnownState) => void): () => void;
17
- }
18
- export type ReadonlyPeerKnownStates = Pick<PeerKnownStates, "get" | "has" | "clone" | "subscribe">;
19
- //# sourceMappingURL=PeerKnownStates.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PeerKnownStates.d.ts","sourceRoot":"","sources":["../src/PeerKnownStates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAGL,iBAAiB,EAGlB,MAAM,iBAAiB,CAAC;AAEzB,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAyC;IAEzD,aAAa,CAAC,EAAE,EAAE,OAAO;IAYzB,YAAY,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO;IAMzC,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB;IAMjD,oBAAoB,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM;IAOrE,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO;IAOrD,GAAG,CAAC,EAAE,EAAE,OAAO;IAIf,GAAG,CAAC,EAAE,EAAE,OAAO;IAIf,KAAK;IAUL,SAAS,WAAgB,OAAO,cAAc,iBAAiB,KAAK,IAAI,EAAI;IAE5E,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,OAAO;IAMf,SAAS,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB,KAAK,IAAI;CAOzE;AAED,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,eAAe,EACf,KAAK,GAAG,KAAK,GAAG,OAAO,GAAG,WAAW,CACtC,CAAC"}
@@ -1,64 +0,0 @@
1
- import { cloneKnownState, combineKnownStates, emptyKnownState, updateSessionCounter, } from "./knownState.js";
2
- export class PeerKnownStates {
3
- constructor() {
4
- this.coValues = new Map();
5
- this.listeners = new Set();
6
- }
7
- getKnownState(id) {
8
- const knownState = this.coValues.get(id);
9
- if (!knownState) {
10
- const knownState = emptyKnownState(id);
11
- this.coValues.set(id, knownState);
12
- return knownState;
13
- }
14
- return knownState;
15
- }
16
- updateHeader(id, header) {
17
- const knownState = this.getKnownState(id);
18
- knownState.header = header;
19
- this.triggerUpdate(id, knownState);
20
- }
21
- combineWith(id, value) {
22
- const knownState = this.getKnownState(id);
23
- combineKnownStates(knownState, value);
24
- this.triggerUpdate(id, knownState);
25
- }
26
- updateSessionCounter(id, sessionId, value) {
27
- const knownState = this.getKnownState(id);
28
- updateSessionCounter(knownState.sessions, sessionId, value);
29
- this.triggerUpdate(id, knownState);
30
- }
31
- set(id, payload) {
32
- const knownState = payload === "empty" ? emptyKnownState(id) : cloneKnownState(payload);
33
- this.coValues.set(id, knownState);
34
- this.triggerUpdate(id, knownState);
35
- }
36
- get(id) {
37
- return this.coValues.get(id);
38
- }
39
- has(id) {
40
- return this.coValues.has(id);
41
- }
42
- clone() {
43
- const clone = new PeerKnownStates();
44
- for (const [id, knownState] of this.coValues) {
45
- clone.coValues.set(id, cloneKnownState(knownState));
46
- }
47
- return clone;
48
- }
49
- triggerUpdate(id, knownState) {
50
- this.trigger(id, knownState);
51
- }
52
- trigger(id, knownState) {
53
- for (const listener of this.listeners) {
54
- listener(id, knownState);
55
- }
56
- }
57
- subscribe(listener) {
58
- this.listeners.add(listener);
59
- return () => {
60
- this.listeners.delete(listener);
61
- };
62
- }
63
- }
64
- //# sourceMappingURL=PeerKnownStates.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PeerKnownStates.js","sourceRoot":"","sources":["../src/PeerKnownStates.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=PeerKnownStates.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PeerKnownStates.test.d.ts","sourceRoot":"","sources":["../../src/tests/PeerKnownStates.test.ts"],"names":[],"mappings":""}
@@ -1,77 +0,0 @@
1
- import { describe, expect, test, vi } from "vitest";
2
- import { PeerKnownStates } from "../PeerKnownStates.js";
3
- import { emptyKnownState } from "../knownState.js";
4
- describe("PeerKnownStates", () => {
5
- test("should set and get a known state", () => {
6
- const peerKnownStates = new PeerKnownStates();
7
- const id = "test-id";
8
- const knownState = emptyKnownState(id);
9
- peerKnownStates.set(id, knownState);
10
- expect(peerKnownStates.get(id)).toEqual(knownState);
11
- expect(peerKnownStates.has(id)).toBe(true);
12
- });
13
- test("should update header", () => {
14
- const peerKnownStates = new PeerKnownStates();
15
- const id = "test-id";
16
- peerKnownStates.updateHeader(id, true);
17
- const result = peerKnownStates.get(id);
18
- expect(result?.header).toBe(true);
19
- });
20
- test("should update session counter", () => {
21
- const peerKnownStates = new PeerKnownStates();
22
- const id = "test-id";
23
- const sessionId = "session-1";
24
- peerKnownStates.updateSessionCounter(id, sessionId, 5);
25
- const result = peerKnownStates.get(id);
26
- expect(result?.sessions[sessionId]).toBe(5);
27
- });
28
- test("should combine with existing state", () => {
29
- const peerKnownStates = new PeerKnownStates();
30
- const id = "test-id";
31
- const session1 = "session-1";
32
- const session2 = "session-2";
33
- const initialState = {
34
- ...emptyKnownState(id),
35
- sessions: { [session1]: 5 },
36
- };
37
- const combineState = {
38
- ...emptyKnownState(id),
39
- sessions: { [session2]: 10 },
40
- };
41
- peerKnownStates.set(id, initialState);
42
- peerKnownStates.combineWith(id, combineState);
43
- const result = peerKnownStates.get(id);
44
- expect(result?.sessions).toEqual({ [session1]: 5, [session2]: 10 });
45
- });
46
- test("should set as empty", () => {
47
- const peerKnownStates = new PeerKnownStates();
48
- const id = "test-id";
49
- const sessionId = "session-1";
50
- const initialState = {
51
- ...emptyKnownState(id),
52
- sessions: { [sessionId]: 5 },
53
- };
54
- peerKnownStates.set(id, initialState);
55
- peerKnownStates.set(id, "empty");
56
- const result = peerKnownStates.get(id);
57
- expect(result).toEqual(emptyKnownState(id));
58
- });
59
- test("should trigger listeners on dispatch", () => {
60
- const peerKnownStates = new PeerKnownStates();
61
- const id = "test-id";
62
- const listener = vi.fn();
63
- peerKnownStates.subscribe(listener);
64
- peerKnownStates.set(id, "empty");
65
- expect(listener).toHaveBeenCalledWith(id, emptyKnownState(id));
66
- });
67
- test("should unsubscribe listener", () => {
68
- const peerKnownStates = new PeerKnownStates();
69
- const id = "test-id";
70
- const listener = vi.fn();
71
- const unsubscribe = peerKnownStates.subscribe(listener);
72
- unsubscribe();
73
- peerKnownStates.set(id, "empty");
74
- expect(listener).not.toHaveBeenCalled();
75
- });
76
- });
77
- //# sourceMappingURL=PeerKnownStates.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PeerKnownStates.test.js","sourceRoot":"","sources":["../../src/tests/PeerKnownStates.test.ts"],"names":[],"mappings":"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"}
@@ -1,93 +0,0 @@
1
- import { RawCoID, SessionID } from "./ids.js";
2
- import {
3
- cloneKnownState,
4
- combineKnownStates,
5
- CoValueKnownState,
6
- emptyKnownState,
7
- updateSessionCounter,
8
- } from "./knownState.js";
9
-
10
- export class PeerKnownStates {
11
- private coValues = new Map<RawCoID, CoValueKnownState>();
12
-
13
- getKnownState(id: RawCoID) {
14
- const knownState = this.coValues.get(id);
15
-
16
- if (!knownState) {
17
- const knownState = emptyKnownState(id);
18
- this.coValues.set(id, knownState);
19
- return knownState;
20
- }
21
-
22
- return knownState;
23
- }
24
-
25
- updateHeader(id: RawCoID, header: boolean) {
26
- const knownState = this.getKnownState(id);
27
- knownState.header = header;
28
- this.triggerUpdate(id, knownState);
29
- }
30
-
31
- combineWith(id: RawCoID, value: CoValueKnownState) {
32
- const knownState = this.getKnownState(id);
33
- combineKnownStates(knownState, value);
34
- this.triggerUpdate(id, knownState);
35
- }
36
-
37
- updateSessionCounter(id: RawCoID, sessionId: SessionID, value: number) {
38
- const knownState = this.getKnownState(id);
39
- updateSessionCounter(knownState.sessions, sessionId, value);
40
-
41
- this.triggerUpdate(id, knownState);
42
- }
43
-
44
- set(id: RawCoID, payload: CoValueKnownState | "empty") {
45
- const knownState =
46
- payload === "empty" ? emptyKnownState(id) : cloneKnownState(payload);
47
- this.coValues.set(id, knownState);
48
- this.triggerUpdate(id, knownState);
49
- }
50
-
51
- get(id: RawCoID) {
52
- return this.coValues.get(id);
53
- }
54
-
55
- has(id: RawCoID) {
56
- return this.coValues.has(id);
57
- }
58
-
59
- clone() {
60
- const clone = new PeerKnownStates();
61
-
62
- for (const [id, knownState] of this.coValues) {
63
- clone.coValues.set(id, cloneKnownState(knownState));
64
- }
65
-
66
- return clone;
67
- }
68
-
69
- listeners = new Set<(id: RawCoID, knownState: CoValueKnownState) => void>();
70
-
71
- private triggerUpdate(id: RawCoID, knownState: CoValueKnownState) {
72
- this.trigger(id, knownState);
73
- }
74
-
75
- private trigger(id: RawCoID, knownState: CoValueKnownState) {
76
- for (const listener of this.listeners) {
77
- listener(id, knownState);
78
- }
79
- }
80
-
81
- subscribe(listener: (id: RawCoID, knownState: CoValueKnownState) => void) {
82
- this.listeners.add(listener);
83
-
84
- return () => {
85
- this.listeners.delete(listener);
86
- };
87
- }
88
- }
89
-
90
- export type ReadonlyPeerKnownStates = Pick<
91
- PeerKnownStates,
92
- "get" | "has" | "clone" | "subscribe"
93
- >;
@@ -1,99 +0,0 @@
1
- import { describe, expect, test, vi } from "vitest";
2
- import { PeerKnownStates } from "../PeerKnownStates.js";
3
- import { RawCoID, SessionID } from "../ids.js";
4
- import { CoValueKnownState, emptyKnownState } from "../knownState.js";
5
-
6
- describe("PeerKnownStates", () => {
7
- test("should set and get a known state", () => {
8
- const peerKnownStates = new PeerKnownStates();
9
- const id = "test-id" as RawCoID;
10
- const knownState: CoValueKnownState = emptyKnownState(id);
11
-
12
- peerKnownStates.set(id, knownState);
13
-
14
- expect(peerKnownStates.get(id)).toEqual(knownState);
15
- expect(peerKnownStates.has(id)).toBe(true);
16
- });
17
-
18
- test("should update header", () => {
19
- const peerKnownStates = new PeerKnownStates();
20
- const id = "test-id" as RawCoID;
21
-
22
- peerKnownStates.updateHeader(id, true);
23
-
24
- const result = peerKnownStates.get(id);
25
- expect(result?.header).toBe(true);
26
- });
27
-
28
- test("should update session counter", () => {
29
- const peerKnownStates = new PeerKnownStates();
30
- const id = "test-id" as RawCoID;
31
- const sessionId = "session-1" as SessionID;
32
-
33
- peerKnownStates.updateSessionCounter(id, sessionId, 5);
34
-
35
- const result = peerKnownStates.get(id);
36
- expect(result?.sessions[sessionId]).toBe(5);
37
- });
38
-
39
- test("should combine with existing state", () => {
40
- const peerKnownStates = new PeerKnownStates();
41
- const id = "test-id" as RawCoID;
42
- const session1 = "session-1" as SessionID;
43
- const session2 = "session-2" as SessionID;
44
- const initialState: CoValueKnownState = {
45
- ...emptyKnownState(id),
46
- sessions: { [session1]: 5 },
47
- };
48
- const combineState: CoValueKnownState = {
49
- ...emptyKnownState(id),
50
- sessions: { [session2]: 10 },
51
- };
52
-
53
- peerKnownStates.set(id, initialState);
54
- peerKnownStates.combineWith(id, combineState);
55
-
56
- const result = peerKnownStates.get(id);
57
- expect(result?.sessions).toEqual({ [session1]: 5, [session2]: 10 });
58
- });
59
-
60
- test("should set as empty", () => {
61
- const peerKnownStates = new PeerKnownStates();
62
- const id = "test-id" as RawCoID;
63
- const sessionId = "session-1" as SessionID;
64
- const initialState: CoValueKnownState = {
65
- ...emptyKnownState(id),
66
- sessions: { [sessionId]: 5 },
67
- };
68
-
69
- peerKnownStates.set(id, initialState);
70
- peerKnownStates.set(id, "empty");
71
-
72
- const result = peerKnownStates.get(id);
73
- expect(result).toEqual(emptyKnownState(id));
74
- });
75
-
76
- test("should trigger listeners on dispatch", () => {
77
- const peerKnownStates = new PeerKnownStates();
78
- const id = "test-id" as RawCoID;
79
- const listener = vi.fn();
80
-
81
- peerKnownStates.subscribe(listener);
82
- peerKnownStates.set(id, "empty");
83
-
84
- expect(listener).toHaveBeenCalledWith(id, emptyKnownState(id));
85
- });
86
-
87
- test("should unsubscribe listener", () => {
88
- const peerKnownStates = new PeerKnownStates();
89
- const id = "test-id" as RawCoID;
90
- const listener = vi.fn();
91
-
92
- const unsubscribe = peerKnownStates.subscribe(listener);
93
- unsubscribe();
94
-
95
- peerKnownStates.set(id, "empty");
96
-
97
- expect(listener).not.toHaveBeenCalled();
98
- });
99
- });