cojson 0.20.7 → 0.20.9

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 (209) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +26 -0
  3. package/dist/SyncStateManager.d.ts.map +1 -1
  4. package/dist/SyncStateManager.js +0 -2
  5. package/dist/SyncStateManager.js.map +1 -1
  6. package/dist/base64url.d.ts +15 -0
  7. package/dist/base64url.d.ts.map +1 -1
  8. package/dist/base64url.js +101 -5
  9. package/dist/base64url.js.map +1 -1
  10. package/dist/base64url.test.js +76 -1
  11. package/dist/base64url.test.js.map +1 -1
  12. package/dist/coValue.d.ts +2 -1
  13. package/dist/coValue.d.ts.map +1 -1
  14. package/dist/coValue.js.map +1 -1
  15. package/dist/coValueCore/coValueCore.d.ts +9 -11
  16. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  17. package/dist/coValueCore/coValueCore.js +92 -65
  18. package/dist/coValueCore/coValueCore.js.map +1 -1
  19. package/dist/coValueCore/verifiedState.d.ts +38 -7
  20. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  21. package/dist/coValueCore/verifiedState.js +226 -30
  22. package/dist/coValueCore/verifiedState.js.map +1 -1
  23. package/dist/coValues/binaryCoStream.d.ts +63 -0
  24. package/dist/coValues/binaryCoStream.d.ts.map +1 -0
  25. package/dist/coValues/binaryCoStream.js +125 -0
  26. package/dist/coValues/binaryCoStream.js.map +1 -0
  27. package/dist/coValues/coList.d.ts +3 -1
  28. package/dist/coValues/coList.d.ts.map +1 -1
  29. package/dist/coValues/coList.js +15 -6
  30. package/dist/coValues/coList.js.map +1 -1
  31. package/dist/coValues/coMap.d.ts +1 -1
  32. package/dist/coValues/coMap.d.ts.map +1 -1
  33. package/dist/coValues/coMap.js +2 -2
  34. package/dist/coValues/coMap.js.map +1 -1
  35. package/dist/coValues/coStream.d.ts +0 -38
  36. package/dist/coValues/coStream.d.ts.map +1 -1
  37. package/dist/coValues/coStream.js +0 -86
  38. package/dist/coValues/coStream.js.map +1 -1
  39. package/dist/coValues/group.d.ts +44 -6
  40. package/dist/coValues/group.d.ts.map +1 -1
  41. package/dist/coValues/group.js +198 -17
  42. package/dist/coValues/group.js.map +1 -1
  43. package/dist/coreToCoValue.d.ts +2 -1
  44. package/dist/coreToCoValue.d.ts.map +1 -1
  45. package/dist/coreToCoValue.js +2 -1
  46. package/dist/coreToCoValue.js.map +1 -1
  47. package/dist/crypto/NapiCrypto.d.ts +18 -24
  48. package/dist/crypto/NapiCrypto.d.ts.map +1 -1
  49. package/dist/crypto/NapiCrypto.js +98 -60
  50. package/dist/crypto/NapiCrypto.js.map +1 -1
  51. package/dist/crypto/RNCrypto.d.ts +16 -3
  52. package/dist/crypto/RNCrypto.d.ts.map +1 -1
  53. package/dist/crypto/RNCrypto.js +117 -54
  54. package/dist/crypto/RNCrypto.js.map +1 -1
  55. package/dist/crypto/WasmCrypto.d.ts +18 -24
  56. package/dist/crypto/WasmCrypto.d.ts.map +1 -1
  57. package/dist/crypto/WasmCrypto.js +100 -61
  58. package/dist/crypto/WasmCrypto.js.map +1 -1
  59. package/dist/crypto/crypto.d.ts +55 -19
  60. package/dist/crypto/crypto.d.ts.map +1 -1
  61. package/dist/crypto/crypto.js +14 -3
  62. package/dist/crypto/crypto.js.map +1 -1
  63. package/dist/exports.d.ts +7 -3
  64. package/dist/exports.d.ts.map +1 -1
  65. package/dist/exports.js +4 -2
  66. package/dist/exports.js.map +1 -1
  67. package/dist/localNode.d.ts +3 -1
  68. package/dist/localNode.d.ts.map +1 -1
  69. package/dist/localNode.js +10 -3
  70. package/dist/localNode.js.map +1 -1
  71. package/dist/media.d.ts +1 -1
  72. package/dist/media.d.ts.map +1 -1
  73. package/dist/permissions.d.ts +2 -1
  74. package/dist/permissions.d.ts.map +1 -1
  75. package/dist/permissions.js +19 -3
  76. package/dist/permissions.js.map +1 -1
  77. package/dist/storage/sqliteAsync/client.d.ts +24 -12
  78. package/dist/storage/sqliteAsync/client.d.ts.map +1 -1
  79. package/dist/storage/sqliteAsync/client.js +70 -58
  80. package/dist/storage/sqliteAsync/client.js.map +1 -1
  81. package/dist/storage/sqliteAsync/types.d.ts +1 -1
  82. package/dist/storage/sqliteAsync/types.d.ts.map +1 -1
  83. package/dist/storage/types.d.ts +1 -0
  84. package/dist/storage/types.d.ts.map +1 -1
  85. package/dist/sync.d.ts.map +1 -1
  86. package/dist/sync.js +7 -1
  87. package/dist/sync.js.map +1 -1
  88. package/dist/tests/CojsonMessageChannel.test.js +2 -2
  89. package/dist/tests/SQLiteClientAsync.test.d.ts +2 -0
  90. package/dist/tests/SQLiteClientAsync.test.d.ts.map +1 -0
  91. package/dist/tests/SQLiteClientAsync.test.js +64 -0
  92. package/dist/tests/SQLiteClientAsync.test.js.map +1 -0
  93. package/dist/tests/StorageApiAsync.test.js +2 -8
  94. package/dist/tests/StorageApiAsync.test.js.map +1 -1
  95. package/dist/tests/SyncStateManager.test.js +2 -2
  96. package/dist/tests/WasmCrypto.test.js +1 -15
  97. package/dist/tests/WasmCrypto.test.js.map +1 -1
  98. package/dist/tests/coList.test.js +24 -5
  99. package/dist/tests/coList.test.js.map +1 -1
  100. package/dist/tests/coStream.test.js +4 -3
  101. package/dist/tests/coStream.test.js.map +1 -1
  102. package/dist/tests/coValueCore.initTransaction.test.d.ts +2 -0
  103. package/dist/tests/coValueCore.initTransaction.test.d.ts.map +1 -0
  104. package/dist/tests/coValueCore.initTransaction.test.js +438 -0
  105. package/dist/tests/coValueCore.initTransaction.test.js.map +1 -0
  106. package/dist/tests/coValueCore.test.js +11 -19
  107. package/dist/tests/coValueCore.test.js.map +1 -1
  108. package/dist/tests/crypto.test.js +83 -0
  109. package/dist/tests/crypto.test.js.map +1 -1
  110. package/dist/tests/deleteCoValue.test.js +5 -5
  111. package/dist/tests/deleteCoValue.test.js.map +1 -1
  112. package/dist/tests/group.inheritance.test.js +11 -0
  113. package/dist/tests/group.inheritance.test.js.map +1 -1
  114. package/dist/tests/group.test.js +24 -1
  115. package/dist/tests/group.test.js.map +1 -1
  116. package/dist/tests/groupSealer.test.d.ts +2 -0
  117. package/dist/tests/groupSealer.test.d.ts.map +1 -0
  118. package/dist/tests/groupSealer.test.js +913 -0
  119. package/dist/tests/groupSealer.test.js.map +1 -0
  120. package/dist/tests/setup.js +5 -0
  121. package/dist/tests/setup.js.map +1 -1
  122. package/dist/tests/sync.auth.test.js +10 -10
  123. package/dist/tests/sync.concurrentLoad.test.js +12 -12
  124. package/dist/tests/sync.deleted.test.js +8 -8
  125. package/dist/tests/sync.garbageCollection.test.js +10 -10
  126. package/dist/tests/sync.invite.test.js +12 -12
  127. package/dist/tests/sync.known.test.js +2 -2
  128. package/dist/tests/sync.load.test.js +107 -107
  129. package/dist/tests/sync.mesh.test.js +164 -46
  130. package/dist/tests/sync.mesh.test.js.map +1 -1
  131. package/dist/tests/sync.multipleServers.test.js +43 -43
  132. package/dist/tests/sync.peerReconciliation.test.js +29 -29
  133. package/dist/tests/sync.sharding.test.js +3 -3
  134. package/dist/tests/sync.storage.test.js +104 -104
  135. package/dist/tests/sync.storage.test.js.map +1 -1
  136. package/dist/tests/sync.storageAsync.test.js +56 -56
  137. package/dist/tests/sync.upload.test.js +22 -22
  138. package/dist/tests/testStorage.d.ts +2 -0
  139. package/dist/tests/testStorage.d.ts.map +1 -1
  140. package/dist/tests/testStorage.js +30 -6
  141. package/dist/tests/testStorage.js.map +1 -1
  142. package/dist/typeUtils/isCoValue.js +1 -1
  143. package/dist/typeUtils/isCoValue.js.map +1 -1
  144. package/package.json +4 -4
  145. package/src/SyncStateManager.ts +0 -2
  146. package/src/base64url.test.ts +89 -1
  147. package/src/base64url.ts +134 -6
  148. package/src/coValue.ts +2 -1
  149. package/src/coValueCore/coValueCore.ts +126 -84
  150. package/src/coValueCore/verifiedState.ts +335 -53
  151. package/src/coValues/binaryCoStream.ts +217 -0
  152. package/src/coValues/coList.ts +21 -8
  153. package/src/coValues/coMap.ts +3 -0
  154. package/src/coValues/coStream.ts +0 -170
  155. package/src/coValues/group.ts +270 -21
  156. package/src/coreToCoValue.ts +2 -1
  157. package/src/crypto/NapiCrypto.ts +198 -95
  158. package/src/crypto/RNCrypto.ts +229 -102
  159. package/src/crypto/WasmCrypto.ts +201 -95
  160. package/src/crypto/crypto.ts +118 -45
  161. package/src/exports.ts +11 -5
  162. package/src/localNode.ts +17 -1
  163. package/src/media.ts +1 -1
  164. package/src/permissions.ts +30 -7
  165. package/src/storage/sqliteAsync/client.ts +136 -115
  166. package/src/storage/sqliteAsync/types.ts +3 -1
  167. package/src/storage/types.ts +4 -0
  168. package/src/sync.ts +10 -1
  169. package/src/tests/CojsonMessageChannel.test.ts +2 -2
  170. package/src/tests/SQLiteClientAsync.test.ts +75 -0
  171. package/src/tests/StorageApiAsync.test.ts +4 -9
  172. package/src/tests/SyncStateManager.test.ts +2 -2
  173. package/src/tests/WasmCrypto.test.ts +1 -25
  174. package/src/tests/coList.test.ts +39 -5
  175. package/src/tests/coStream.test.ts +4 -5
  176. package/src/tests/coValueCore.initTransaction.test.ts +836 -0
  177. package/src/tests/coValueCore.test.ts +11 -22
  178. package/src/tests/crypto.test.ts +107 -0
  179. package/src/tests/deleteCoValue.test.ts +5 -5
  180. package/src/tests/group.inheritance.test.ts +16 -0
  181. package/src/tests/group.test.ts +29 -1
  182. package/src/tests/groupSealer.test.ts +1473 -0
  183. package/src/tests/setup.ts +6 -0
  184. package/src/tests/sync.auth.test.ts +10 -10
  185. package/src/tests/sync.concurrentLoad.test.ts +12 -12
  186. package/src/tests/sync.deleted.test.ts +8 -8
  187. package/src/tests/sync.garbageCollection.test.ts +10 -10
  188. package/src/tests/sync.invite.test.ts +12 -12
  189. package/src/tests/sync.known.test.ts +2 -2
  190. package/src/tests/sync.load.test.ts +107 -107
  191. package/src/tests/sync.mesh.test.ts +189 -46
  192. package/src/tests/sync.multipleServers.test.ts +43 -43
  193. package/src/tests/sync.peerReconciliation.test.ts +29 -29
  194. package/src/tests/sync.sharding.test.ts +3 -3
  195. package/src/tests/sync.storage.test.ts +104 -104
  196. package/src/tests/sync.storageAsync.test.ts +56 -56
  197. package/src/tests/sync.upload.test.ts +22 -22
  198. package/src/tests/testStorage.ts +39 -9
  199. package/src/typeUtils/isCoValue.ts +1 -1
  200. package/dist/coValueCore/SessionMap.d.ts +0 -55
  201. package/dist/coValueCore/SessionMap.d.ts.map +0 -1
  202. package/dist/coValueCore/SessionMap.js +0 -206
  203. package/dist/coValueCore/SessionMap.js.map +0 -1
  204. package/dist/tests/coreWasm.test.d.ts +0 -2
  205. package/dist/tests/coreWasm.test.d.ts.map +0 -1
  206. package/dist/tests/coreWasm.test.js +0 -203
  207. package/dist/tests/coreWasm.test.js.map +0 -1
  208. package/src/coValueCore/SessionMap.ts +0 -394
  209. package/src/tests/coreWasm.test.ts +0 -452
@@ -4,7 +4,6 @@ import {
4
4
  exceedsRecommendedSize,
5
5
  getTransactionSize,
6
6
  addTransactionToContentMessage,
7
- knownStateFromContent,
8
7
  } from "../coValueContentMessage.js";
9
8
  import {
10
9
  CryptoProvider,
@@ -13,6 +12,7 @@ import {
13
12
  KeySecret,
14
13
  Signature,
15
14
  SignerID,
15
+ SessionMapImpl,
16
16
  } from "../crypto/crypto.js";
17
17
  import {
18
18
  isDeleteSessionID,
@@ -20,17 +20,17 @@ import {
20
20
  SessionID,
21
21
  TransactionID,
22
22
  } from "../ids.js";
23
- import { Stringified } from "../jsonStringify.js";
23
+ import { Stringified, parseJSON } from "../jsonStringify.js";
24
24
  import { JsonObject, JsonValue } from "../jsonValue.js";
25
25
  import { PermissionsDef as RulesetDef } from "../permissions.js";
26
26
  import { NewContentMessage } from "../sync.js";
27
- import { SessionMap } from "./SessionMap.js";
28
27
  import { ControlledAccountOrAgent } from "../coValues/account.js";
29
28
  import {
30
29
  CoValueKnownState,
31
30
  getKnownStateToSend,
32
31
  KnownStateSessions,
33
32
  } from "../knownState.js";
33
+ import { TRANSACTION_CONFIG } from "../config.js";
34
34
 
35
35
  export type CoValueHeader = {
36
36
  type: AnyRawCoValue["type"];
@@ -68,42 +68,197 @@ export type TrustingTransaction = {
68
68
 
69
69
  export type Transaction = PrivateTransaction | TrustingTransaction;
70
70
 
71
+ export type SessionLog = {
72
+ signerID?: SignerID;
73
+ transactions: Transaction[];
74
+ lastSignature: Signature | undefined;
75
+ signatureAfter: { [txIdx: number]: Signature | undefined };
76
+ sessionID: SessionID;
77
+ };
78
+
71
79
  export class VerifiedState {
72
80
  readonly id: RawCoID;
73
81
  readonly crypto: CryptoProvider;
74
82
  readonly header: CoValueHeader;
75
- readonly sessions: SessionMap;
83
+ private readonly impl: SessionMapImpl;
76
84
  public lastAccessed: number | undefined;
77
85
  public branchSourceId?: RawCoID;
78
86
  public branchName?: string;
79
87
  private isDeleted: boolean = false;
80
88
 
89
+ // Cache for SessionLog objects to avoid re-parsing on every access
90
+ private sessionLogCache: Map<SessionID, SessionLog> = new Map();
91
+ private sessionLogCacheValid: Map<SessionID, number> = new Map(); // txCount when cached
92
+
93
+ // Cache for known state to avoid repeated FFI calls between mutations
94
+ private cachedKnownState: CoValueKnownState | undefined;
95
+ private cachedKnownStateWithStreaming: CoValueKnownState | undefined;
96
+
81
97
  constructor(
82
98
  id: RawCoID,
83
99
  crypto: CryptoProvider,
84
100
  header: CoValueHeader,
85
- sessions?: SessionMap,
101
+ streamingKnownState?: KnownStateSessions,
102
+ skipVerify?: boolean,
86
103
  ) {
87
104
  this.id = id;
88
105
  this.crypto = crypto;
89
106
  this.header = header;
90
- this.sessions = sessions ?? new SessionMap(id, crypto);
91
107
  this.branchSourceId = header.meta?.source as RawCoID | undefined;
92
108
  this.branchName = header.meta?.branch as string | undefined;
93
- }
94
109
 
95
- clone(): VerifiedState {
96
- return new VerifiedState(
97
- this.id,
98
- this.crypto,
99
- this.header,
100
- this.sessions.clone(),
110
+ this.impl = crypto.createSessionMap(
111
+ id,
112
+ JSON.stringify(header),
113
+ TRANSACTION_CONFIG.MAX_RECOMMENDED_TX_SIZE,
114
+ skipVerify,
101
115
  );
116
+
117
+ // Set streaming known state if provided
118
+ if (streamingKnownState) {
119
+ this.impl.setStreamingKnownState(JSON.stringify(streamingKnownState));
120
+ }
121
+ }
122
+
123
+ private invalidateCache() {
124
+ this.sessionLogCache.clear();
125
+ this.sessionLogCacheValid.clear();
126
+ this.invalidateKnownStateCache();
127
+ }
128
+
129
+ private invalidateKnownStateCache() {
130
+ this.cachedKnownState = undefined;
131
+ this.cachedKnownStateWithStreaming = undefined;
132
+ }
133
+
134
+ /**
135
+ * Update the session log cache directly when adding transactions.
136
+ * This avoids round-trips to Rust on subsequent reads.
137
+ */
138
+ private updateSessionLogCache(
139
+ sessionID: SessionID,
140
+ signerID: SignerID | undefined,
141
+ newTransactions: Transaction[],
142
+ newSignature: Signature,
143
+ ) {
144
+ const cached = this.sessionLogCache.get(sessionID);
145
+ const currentTxCount = this.impl.getTransactionCount(sessionID);
146
+
147
+ if (cached) {
148
+ // Append to existing cache
149
+ for (const tx of newTransactions) {
150
+ cached.transactions.push(tx);
151
+ }
152
+ cached.lastSignature = newSignature;
153
+ if (signerID) {
154
+ cached.signerID = signerID;
155
+ }
156
+ // Check if we need to update signatureAfter (in-between signature)
157
+ this.updateLastCheckpointSignature(sessionID, cached.signatureAfter);
158
+ this.sessionLogCacheValid.set(sessionID, currentTxCount);
159
+ } else {
160
+ // Create new cache entry
161
+ const signatureAfter: { [txIdx: number]: Signature | undefined } = {};
162
+ this.updateLastCheckpointSignature(sessionID, signatureAfter);
163
+ const sessionLog: SessionLog = {
164
+ signerID,
165
+ transactions: newTransactions.slice(),
166
+ lastSignature: newSignature,
167
+ signatureAfter,
168
+ sessionID,
169
+ };
170
+ this.sessionLogCache.set(sessionID, sessionLog);
171
+ this.sessionLogCacheValid.set(sessionID, currentTxCount);
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Update the signatureAfter map with the latest checkpoint signature.
177
+ * Used when updating cache incrementally.
178
+ */
179
+ private updateLastCheckpointSignature(
180
+ sessionID: SessionID,
181
+ signatureAfter: { [txIdx: number]: Signature | undefined },
182
+ ): void {
183
+ const lastCheckpoint = this.impl.getLastSignatureCheckpoint(sessionID);
184
+ if (
185
+ lastCheckpoint !== undefined &&
186
+ lastCheckpoint !== null &&
187
+ lastCheckpoint >= 0
188
+ ) {
189
+ const sig = this.impl.getSignatureAfter(sessionID, lastCheckpoint);
190
+ if (sig) {
191
+ signatureAfter[lastCheckpoint] = sig as Signature;
192
+ }
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Build the signatureAfter map for a session by iterating through all checkpoints.
198
+ * Used when building a fresh SessionLog from Rust data.
199
+ */
200
+ private buildSignatureAfterMap(sessionID: SessionID): {
201
+ [txIdx: number]: Signature | undefined;
202
+ } {
203
+ const signatureAfter: { [txIdx: number]: Signature | undefined } = {};
204
+ const lastCheckpoint = this.impl.getLastSignatureCheckpoint(sessionID);
205
+ if (
206
+ lastCheckpoint !== undefined &&
207
+ lastCheckpoint !== null &&
208
+ lastCheckpoint >= 0
209
+ ) {
210
+ for (let i = 0; i <= lastCheckpoint; i++) {
211
+ const sig = this.impl.getSignatureAfter(sessionID, i);
212
+ if (sig) {
213
+ signatureAfter[i] = sig as Signature;
214
+ }
215
+ }
216
+ }
217
+ return signatureAfter;
218
+ }
219
+
220
+ private getSessionLog(sessionID: SessionID): SessionLog {
221
+ const currentTxCount = this.impl.getTransactionCount(sessionID);
222
+ const cachedTxCount = this.sessionLogCacheValid.get(sessionID);
223
+
224
+ // Check if cache is valid
225
+ if (cachedTxCount === currentTxCount) {
226
+ const cached = this.sessionLogCache.get(sessionID);
227
+ if (cached) return cached;
228
+ }
229
+
230
+ // Fetch all transactions from Rust
231
+ const transactions: Transaction[] =
232
+ currentTxCount > 0
233
+ ? (this.impl.getSessionTransactions(sessionID, 0) ?? [])
234
+ : [];
235
+
236
+ // Build signatureAfter map
237
+ const signatureAfter = this.buildSignatureAfterMap(sessionID);
238
+
239
+ const lastSignature = this.impl.getLastSignature(sessionID) as
240
+ | Signature
241
+ | undefined;
242
+
243
+ const sessionLog: SessionLog = {
244
+ signerID: undefined, // We don't track this in Rust currently
245
+ transactions,
246
+ lastSignature,
247
+ signatureAfter,
248
+ sessionID,
249
+ };
250
+
251
+ // Cache the result
252
+ this.sessionLogCache.set(sessionID, sessionLog);
253
+ this.sessionLogCacheValid.set(sessionID, currentTxCount);
254
+
255
+ return sessionLog;
102
256
  }
103
257
 
104
258
  markAsDeleted() {
105
259
  this.isDeleted = true;
106
- this.sessions.markAsDeleted();
260
+ this.impl.markAsDeleted();
261
+ this.invalidateCache();
107
262
  }
108
263
 
109
264
  tryAddTransactions(
@@ -113,13 +268,29 @@ export class VerifiedState {
113
268
  newSignature: Signature,
114
269
  skipVerify: boolean = false,
115
270
  ) {
116
- this.sessions.addTransaction(
271
+ if (this.isDeleted && !isDeleteSessionID(sessionID)) {
272
+ throw new Error("Cannot add transactions to a deleted coValue");
273
+ }
274
+
275
+ // Convert transactions to JSON array
276
+ const txJson = JSON.stringify(newTransactions);
277
+
278
+ this.impl.addTransactions(
117
279
  sessionID,
118
280
  signerID,
119
- newTransactions,
281
+ txJson,
120
282
  newSignature,
121
283
  skipVerify,
122
284
  );
285
+
286
+ // Update cache directly instead of invalidating
287
+ this.updateSessionLogCache(
288
+ sessionID,
289
+ signerID,
290
+ newTransactions,
291
+ newSignature,
292
+ );
293
+ this.invalidateKnownStateCache();
123
294
  }
124
295
 
125
296
  makeNewTrustingTransaction(
@@ -128,16 +299,45 @@ export class VerifiedState {
128
299
  changes: JsonValue[],
129
300
  meta: JsonObject | undefined,
130
301
  madeAt: number,
131
- ) {
132
- const result = this.sessions.makeNewTrustingTransaction(
302
+ ): { signature: Signature; transaction: Transaction } {
303
+ if (this.isDeleted) {
304
+ throw new Error(
305
+ "Cannot make new trusting transaction on a deleted coValue",
306
+ );
307
+ }
308
+
309
+ const changesJson = JSON.stringify(changes);
310
+ const metaJson = meta ? JSON.stringify(meta) : undefined;
311
+ const signerSecret = signerAgent.currentSignerSecret();
312
+
313
+ const resultJson = this.impl.makeNewTrustingTransaction(
133
314
  sessionID,
134
- signerAgent,
135
- changes,
136
- meta,
315
+ signerSecret,
316
+ changesJson,
317
+ metaJson,
137
318
  madeAt,
138
319
  );
139
320
 
140
- return result;
321
+ const result = JSON.parse(resultJson) as {
322
+ signature: string;
323
+ transaction: Transaction;
324
+ };
325
+
326
+ const signature = result.signature as Signature;
327
+
328
+ // Update cache directly instead of invalidating
329
+ this.updateSessionLogCache(
330
+ sessionID,
331
+ signerAgent.id as unknown as SignerID,
332
+ [result.transaction],
333
+ signature,
334
+ );
335
+ this.invalidateKnownStateCache();
336
+
337
+ return {
338
+ signature,
339
+ transaction: result.transaction,
340
+ };
141
341
  }
142
342
 
143
343
  makeNewPrivateTransaction(
@@ -148,33 +348,92 @@ export class VerifiedState {
148
348
  keySecret: KeySecret,
149
349
  meta: JsonObject | undefined,
150
350
  madeAt: number,
151
- ) {
152
- const result = this.sessions.makeNewPrivateTransaction(
351
+ ): { signature: Signature; transaction: Transaction } {
352
+ if (this.isDeleted) {
353
+ throw new Error(
354
+ "Cannot make new private transaction on a deleted coValue",
355
+ );
356
+ }
357
+
358
+ const changesJson = JSON.stringify(changes);
359
+ const metaJson = meta ? JSON.stringify(meta) : undefined;
360
+ const signerSecret = signerAgent.currentSignerSecret();
361
+
362
+ const resultJson = this.impl.makeNewPrivateTransaction(
153
363
  sessionID,
154
- signerAgent,
155
- changes,
364
+ signerSecret,
365
+ changesJson,
156
366
  keyID,
157
367
  keySecret,
158
- meta,
368
+ metaJson,
159
369
  madeAt,
160
370
  );
161
371
 
162
- return result;
163
- }
164
-
165
- getLastSignatureCheckpoint(sessionID: SessionID): number {
166
- const sessionLog = this.sessions.get(sessionID);
372
+ const result = JSON.parse(resultJson) as {
373
+ signature: string;
374
+ transaction: Transaction;
375
+ };
167
376
 
168
- if (!sessionLog?.signatureAfter) return -1;
377
+ const signature = result.signature as Signature;
169
378
 
170
- return Object.keys(sessionLog.signatureAfter).reduce(
171
- (max, idx) => Math.max(max, parseInt(idx)),
172
- -1,
379
+ // Update cache directly instead of invalidating
380
+ this.updateSessionLogCache(
381
+ sessionID,
382
+ signerAgent.id as unknown as SignerID,
383
+ [result.transaction],
384
+ signature,
173
385
  );
386
+ this.invalidateKnownStateCache();
387
+
388
+ return {
389
+ signature,
390
+ transaction: result.transaction,
391
+ };
174
392
  }
175
393
 
176
394
  setStreamingKnownState(streamingKnownState: KnownStateSessions) {
177
- this.sessions.setStreamingKnownState(streamingKnownState);
395
+ if (this.isDeleted) {
396
+ return;
397
+ }
398
+ this.impl.setStreamingKnownState(JSON.stringify(streamingKnownState));
399
+ this.cachedKnownStateWithStreaming = undefined;
400
+ }
401
+
402
+ getSession(sessionID: SessionID): SessionLog | undefined {
403
+ const txCount = this.impl.getTransactionCount(sessionID);
404
+ if (txCount === -1) {
405
+ return undefined;
406
+ }
407
+ return this.getSessionLog(sessionID);
408
+ }
409
+
410
+ getTransactionsCount(sessionID: SessionID): number | undefined {
411
+ const txCount = this.impl.getTransactionCount(sessionID);
412
+ if (txCount === -1) {
413
+ return undefined;
414
+ }
415
+ return txCount;
416
+ }
417
+
418
+ get sessionCount(): number {
419
+ return this.impl.getSessionIds().length;
420
+ }
421
+
422
+ getSessions(): Map<SessionID, SessionLog> {
423
+ // Build a Map from all sessions
424
+ const map = new Map<SessionID, SessionLog>();
425
+ const sessionIds = this.impl.getSessionIds() as SessionID[];
426
+ for (const sessionID of sessionIds) {
427
+ map.set(sessionID, this.getSessionLog(sessionID));
428
+ }
429
+ return map;
430
+ }
431
+
432
+ *sessionEntries(): IterableIterator<[SessionID, SessionLog]> {
433
+ const sessionIds = this.impl.getSessionIds() as SessionID[];
434
+ for (const sessionID of sessionIds) {
435
+ yield [sessionID, this.getSessionLog(sessionID)];
436
+ }
178
437
  }
179
438
 
180
439
  newContentSince(
@@ -217,7 +476,7 @@ export class VerifiedState {
217
476
 
218
477
  const sessionSent = knownState?.sessions;
219
478
 
220
- for (const [sessionID, log] of this.sessions.sessions) {
479
+ for (const [sessionID, log] of this.getSessions()) {
221
480
  if (this.isDeleted && !isDeleteSessionID(sessionID)) {
222
481
  continue;
223
482
  }
@@ -329,24 +588,27 @@ export class VerifiedState {
329
588
  return piecesWithContent;
330
589
  }
331
590
 
332
- knownState() {
333
- return this.sessions.knownState;
334
- }
335
-
336
- knownStateWithStreaming() {
337
- return this.sessions.knownStateWithStreaming ?? this.knownState();
338
- }
339
-
340
- immutableKnownState() {
341
- return this.sessions.getImmutableKnownState();
591
+ knownState(): CoValueKnownState {
592
+ if (!this.cachedKnownState) {
593
+ this.cachedKnownState = this.impl.getKnownState() as CoValueKnownState;
594
+ }
595
+ return this.cachedKnownState;
342
596
  }
343
597
 
344
- immutableKnownStateWithStreaming() {
345
- return this.sessions.getImmutableKnownStateWithStreaming();
598
+ knownStateWithStreaming(): CoValueKnownState {
599
+ if (!this.cachedKnownStateWithStreaming) {
600
+ const result = this.impl.getKnownStateWithStreaming();
601
+ if (!result || result === undefined) {
602
+ this.cachedKnownStateWithStreaming = this.knownState();
603
+ } else {
604
+ this.cachedKnownStateWithStreaming = result as CoValueKnownState;
605
+ }
606
+ }
607
+ return this.cachedKnownStateWithStreaming;
346
608
  }
347
609
 
348
610
  isStreaming(): boolean {
349
- return Boolean(this.sessions.knownStateWithStreaming);
611
+ return Boolean(this.impl.getKnownStateWithStreaming());
350
612
  }
351
613
 
352
614
  decryptTransaction(
@@ -354,7 +616,15 @@ export class VerifiedState {
354
616
  txIndex: number,
355
617
  keySecret: KeySecret,
356
618
  ): JsonValue[] | undefined {
357
- return this.sessions.decryptTransaction(sessionID, txIndex, keySecret);
619
+ const decrypted = this.impl.decryptTransaction(
620
+ sessionID,
621
+ txIndex,
622
+ keySecret,
623
+ );
624
+ if (!decrypted) {
625
+ return undefined;
626
+ }
627
+ return parseJSON(decrypted as Stringified<JsonValue[]>);
358
628
  }
359
629
 
360
630
  decryptTransactionMeta(
@@ -362,7 +632,19 @@ export class VerifiedState {
362
632
  txIndex: number,
363
633
  keySecret: KeySecret,
364
634
  ): JsonObject | undefined {
365
- return this.sessions.decryptTransactionMeta(sessionID, txIndex, keySecret);
635
+ const sessionLog = this.getSession(sessionID);
636
+ if (!sessionLog?.transactions[txIndex]?.meta) {
637
+ return undefined;
638
+ }
639
+ const decrypted = this.impl.decryptTransactionMeta(
640
+ sessionID,
641
+ txIndex,
642
+ keySecret,
643
+ );
644
+ if (!decrypted) {
645
+ return undefined;
646
+ }
647
+ return parseJSON(decrypted as Stringified<JsonObject>);
366
648
  }
367
649
  }
368
650