cojson 0.8.12 → 0.8.16

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 (158) hide show
  1. package/CHANGELOG.md +89 -83
  2. package/dist/native/PeerKnownStates.js +1 -1
  3. package/dist/native/PeerKnownStates.js.map +1 -1
  4. package/dist/native/PeerState.js +1 -1
  5. package/dist/native/PeerState.js.map +1 -1
  6. package/dist/native/PriorityBasedMessageQueue.js +1 -10
  7. package/dist/native/PriorityBasedMessageQueue.js.map +1 -1
  8. package/dist/native/base64url.js.map +1 -1
  9. package/dist/native/base64url.test.js +1 -1
  10. package/dist/native/base64url.test.js.map +1 -1
  11. package/dist/native/coValue.js.map +1 -1
  12. package/dist/native/coValueCore.js +141 -149
  13. package/dist/native/coValueCore.js.map +1 -1
  14. package/dist/native/coValueState.js.map +1 -1
  15. package/dist/native/coValues/account.js +6 -6
  16. package/dist/native/coValues/account.js.map +1 -1
  17. package/dist/native/coValues/coList.js +2 -3
  18. package/dist/native/coValues/coList.js.map +1 -1
  19. package/dist/native/coValues/coMap.js +1 -1
  20. package/dist/native/coValues/coMap.js.map +1 -1
  21. package/dist/native/coValues/coStream.js +3 -5
  22. package/dist/native/coValues/coStream.js.map +1 -1
  23. package/dist/native/coValues/group.js +11 -11
  24. package/dist/native/coValues/group.js.map +1 -1
  25. package/dist/native/coreToCoValue.js +2 -2
  26. package/dist/native/coreToCoValue.js.map +1 -1
  27. package/dist/native/crypto/PureJSCrypto.js +4 -4
  28. package/dist/native/crypto/PureJSCrypto.js.map +1 -1
  29. package/dist/native/crypto/crypto.js.map +1 -1
  30. package/dist/native/exports.js +12 -12
  31. package/dist/native/exports.js.map +1 -1
  32. package/dist/native/ids.js.map +1 -1
  33. package/dist/native/jsonStringify.js.map +1 -1
  34. package/dist/native/localNode.js +5 -7
  35. package/dist/native/localNode.js.map +1 -1
  36. package/dist/native/permissions.js +4 -7
  37. package/dist/native/permissions.js.map +1 -1
  38. package/dist/native/priority.js.map +1 -1
  39. package/dist/native/storage/FileSystem.js.map +1 -1
  40. package/dist/native/storage/chunksAndKnownStates.js +2 -4
  41. package/dist/native/storage/chunksAndKnownStates.js.map +1 -1
  42. package/dist/native/storage/index.js +6 -15
  43. package/dist/native/storage/index.js.map +1 -1
  44. package/dist/native/streamUtils.js.map +1 -1
  45. package/dist/native/sync.js +2 -4
  46. package/dist/native/sync.js.map +1 -1
  47. package/dist/native/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  48. package/dist/native/typeUtils/expectGroup.js.map +1 -1
  49. package/dist/native/typeUtils/isAccountID.js.map +1 -1
  50. package/dist/native/typeUtils/isCoValue.js +1 -1
  51. package/dist/native/typeUtils/isCoValue.js.map +1 -1
  52. package/dist/web/PeerKnownStates.js +1 -1
  53. package/dist/web/PeerKnownStates.js.map +1 -1
  54. package/dist/web/PeerState.js +1 -1
  55. package/dist/web/PeerState.js.map +1 -1
  56. package/dist/web/PriorityBasedMessageQueue.js +1 -10
  57. package/dist/web/PriorityBasedMessageQueue.js.map +1 -1
  58. package/dist/web/base64url.js.map +1 -1
  59. package/dist/web/base64url.test.js +1 -1
  60. package/dist/web/base64url.test.js.map +1 -1
  61. package/dist/web/coValue.js.map +1 -1
  62. package/dist/web/coValueCore.js +141 -149
  63. package/dist/web/coValueCore.js.map +1 -1
  64. package/dist/web/coValueState.js.map +1 -1
  65. package/dist/web/coValues/account.js +6 -6
  66. package/dist/web/coValues/account.js.map +1 -1
  67. package/dist/web/coValues/coList.js +2 -3
  68. package/dist/web/coValues/coList.js.map +1 -1
  69. package/dist/web/coValues/coMap.js +1 -1
  70. package/dist/web/coValues/coMap.js.map +1 -1
  71. package/dist/web/coValues/coStream.js +3 -5
  72. package/dist/web/coValues/coStream.js.map +1 -1
  73. package/dist/web/coValues/group.js +11 -11
  74. package/dist/web/coValues/group.js.map +1 -1
  75. package/dist/web/coreToCoValue.js +2 -2
  76. package/dist/web/coreToCoValue.js.map +1 -1
  77. package/dist/web/crypto/PureJSCrypto.js +4 -4
  78. package/dist/web/crypto/PureJSCrypto.js.map +1 -1
  79. package/dist/web/crypto/WasmCrypto.js +5 -5
  80. package/dist/web/crypto/WasmCrypto.js.map +1 -1
  81. package/dist/web/crypto/crypto.js.map +1 -1
  82. package/dist/web/exports.js +12 -12
  83. package/dist/web/exports.js.map +1 -1
  84. package/dist/web/ids.js.map +1 -1
  85. package/dist/web/jsonStringify.js.map +1 -1
  86. package/dist/web/localNode.js +5 -7
  87. package/dist/web/localNode.js.map +1 -1
  88. package/dist/web/permissions.js +4 -7
  89. package/dist/web/permissions.js.map +1 -1
  90. package/dist/web/priority.js.map +1 -1
  91. package/dist/web/storage/FileSystem.js.map +1 -1
  92. package/dist/web/storage/chunksAndKnownStates.js +2 -4
  93. package/dist/web/storage/chunksAndKnownStates.js.map +1 -1
  94. package/dist/web/storage/index.js +6 -15
  95. package/dist/web/storage/index.js.map +1 -1
  96. package/dist/web/streamUtils.js.map +1 -1
  97. package/dist/web/sync.js +2 -4
  98. package/dist/web/sync.js.map +1 -1
  99. package/dist/web/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  100. package/dist/web/typeUtils/expectGroup.js.map +1 -1
  101. package/dist/web/typeUtils/isAccountID.js.map +1 -1
  102. package/dist/web/typeUtils/isCoValue.js +1 -1
  103. package/dist/web/typeUtils/isCoValue.js.map +1 -1
  104. package/package.json +4 -14
  105. package/src/PeerKnownStates.ts +91 -89
  106. package/src/PeerState.ts +72 -73
  107. package/src/PriorityBasedMessageQueue.ts +42 -49
  108. package/src/base64url.test.ts +24 -24
  109. package/src/base64url.ts +44 -45
  110. package/src/coValue.ts +45 -45
  111. package/src/coValueCore.ts +746 -785
  112. package/src/coValueState.ts +82 -72
  113. package/src/coValues/account.ts +143 -150
  114. package/src/coValues/coList.ts +520 -522
  115. package/src/coValues/coMap.ts +283 -285
  116. package/src/coValues/coStream.ts +320 -324
  117. package/src/coValues/group.ts +306 -305
  118. package/src/coreToCoValue.ts +28 -31
  119. package/src/crypto/PureJSCrypto.ts +188 -194
  120. package/src/crypto/WasmCrypto.ts +236 -254
  121. package/src/crypto/crypto.ts +302 -309
  122. package/src/exports.ts +116 -116
  123. package/src/ids.ts +9 -9
  124. package/src/jsonStringify.ts +46 -46
  125. package/src/jsonValue.ts +24 -10
  126. package/src/localNode.ts +635 -660
  127. package/src/media.ts +3 -3
  128. package/src/permissions.ts +272 -278
  129. package/src/priority.ts +21 -19
  130. package/src/storage/FileSystem.ts +91 -99
  131. package/src/storage/chunksAndKnownStates.ts +110 -115
  132. package/src/storage/index.ts +466 -497
  133. package/src/streamUtils.ts +60 -60
  134. package/src/sync.ts +593 -615
  135. package/src/tests/PeerKnownStates.test.ts +38 -34
  136. package/src/tests/PeerState.test.ts +101 -64
  137. package/src/tests/PriorityBasedMessageQueue.test.ts +91 -91
  138. package/src/tests/account.test.ts +59 -59
  139. package/src/tests/coList.test.ts +65 -65
  140. package/src/tests/coMap.test.ts +137 -137
  141. package/src/tests/coStream.test.ts +254 -257
  142. package/src/tests/coValueCore.test.ts +153 -156
  143. package/src/tests/crypto.test.ts +136 -144
  144. package/src/tests/cryptoImpl.test.ts +205 -197
  145. package/src/tests/group.test.ts +24 -24
  146. package/src/tests/permissions.test.ts +1306 -1371
  147. package/src/tests/priority.test.ts +65 -82
  148. package/src/tests/sync.test.ts +1300 -1291
  149. package/src/tests/testUtils.ts +52 -53
  150. package/src/typeUtils/accountOrAgentIDfromSessionID.ts +4 -4
  151. package/src/typeUtils/expectGroup.ts +9 -9
  152. package/src/typeUtils/isAccountID.ts +1 -1
  153. package/src/typeUtils/isCoValue.ts +9 -9
  154. package/tsconfig.json +4 -6
  155. package/tsconfig.native.json +9 -11
  156. package/tsconfig.web.json +4 -10
  157. package/.eslintrc.cjs +0 -25
  158. package/.prettierrc.js +0 -9
@@ -1,6 +1,6 @@
1
- import { CoValueChunk } from "./index.js";
2
- import { RawCoID } from "../ids.js";
3
1
  import { CryptoProvider, StreamingHash } from "../crypto/crypto.js";
2
+ import { RawCoID } from "../ids.js";
3
+ import { CoValueChunk } from "./index.js";
4
4
 
5
5
  export type BlockFilename = `L${number}-${string}-${string}-H${number}.jsonl`;
6
6
 
@@ -11,123 +11,115 @@ export type WalEntry = { id: RawCoID } & CoValueChunk;
11
11
  export type WalFilename = `wal-${number}.jsonl`;
12
12
 
13
13
  export interface FileSystem<WriteHandle, ReadHandle> {
14
- crypto: CryptoProvider;
15
- createFile(filename: string): Promise<WriteHandle>;
16
- append(handle: WriteHandle, data: Uint8Array): Promise<void>;
17
- close(handle: ReadHandle | WriteHandle): Promise<void>;
18
- closeAndRename(handle: WriteHandle, filename: BlockFilename): Promise<void>;
19
- openToRead(filename: string): Promise<{ handle: ReadHandle; size: number }>;
20
- read(
21
- handle: ReadHandle,
22
- offset: number,
23
- length: number,
24
- ): Promise<Uint8Array>;
25
- listFiles(): Promise<string[]>;
26
- removeFile(filename: BlockFilename | WalFilename): Promise<void>;
14
+ crypto: CryptoProvider;
15
+ createFile(filename: string): Promise<WriteHandle>;
16
+ append(handle: WriteHandle, data: Uint8Array): Promise<void>;
17
+ close(handle: ReadHandle | WriteHandle): Promise<void>;
18
+ closeAndRename(handle: WriteHandle, filename: BlockFilename): Promise<void>;
19
+ openToRead(filename: string): Promise<{ handle: ReadHandle; size: number }>;
20
+ read(handle: ReadHandle, offset: number, length: number): Promise<Uint8Array>;
21
+ listFiles(): Promise<string[]>;
22
+ removeFile(filename: BlockFilename | WalFilename): Promise<void>;
27
23
  }
28
24
 
29
25
  export const textEncoder = new TextEncoder();
30
26
  export const textDecoder = new TextDecoder();
31
27
 
32
28
  export async function readChunk<RH, FS extends FileSystem<unknown, RH>>(
33
- handle: RH,
34
- header: { start: number; length: number },
35
- fs: FS,
29
+ handle: RH,
30
+ header: { start: number; length: number },
31
+ fs: FS,
36
32
  ): Promise<CoValueChunk> {
37
- const chunkBytes = await fs.read(handle, header.start, header.length);
33
+ const chunkBytes = await fs.read(handle, header.start, header.length);
38
34
 
39
- const chunk = JSON.parse(textDecoder.decode(chunkBytes));
40
- return chunk;
35
+ const chunk = JSON.parse(textDecoder.decode(chunkBytes));
36
+ return chunk;
41
37
  }
42
38
 
43
39
  export async function readHeader<RH, FS extends FileSystem<unknown, RH>>(
44
- filename: string,
45
- handle: RH,
46
- size: number,
47
- fs: FS,
40
+ filename: string,
41
+ handle: RH,
42
+ size: number,
43
+ fs: FS,
48
44
  ): Promise<BlockHeader> {
49
- const headerLength = Number(filename.match(/-H(\d+)\.jsonl$/)![1]!);
45
+ const headerLength = Number(filename.match(/-H(\d+)\.jsonl$/)![1]!);
50
46
 
51
- const headerBytes = await fs.read(
52
- handle,
53
- size - headerLength,
54
- headerLength,
55
- );
47
+ const headerBytes = await fs.read(handle, size - headerLength, headerLength);
56
48
 
57
- const header = JSON.parse(textDecoder.decode(headerBytes));
58
- return header;
49
+ const header = JSON.parse(textDecoder.decode(headerBytes));
50
+ return header;
59
51
  }
60
52
 
61
53
  export async function writeBlock<WH, RH, FS extends FileSystem<WH, RH>>(
62
- chunks: Map<RawCoID, CoValueChunk>,
63
- level: number,
64
- blockNumber: number,
65
- fs: FS,
54
+ chunks: Map<RawCoID, CoValueChunk>,
55
+ level: number,
56
+ blockNumber: number,
57
+ fs: FS,
66
58
  ): Promise<BlockFilename> {
67
- if (chunks.size === 0) {
68
- throw new Error("No chunks to write");
69
- }
70
-
71
- const blockHeader: BlockHeader = [];
72
-
73
- let offset = 0;
74
-
75
- const file = await fs.createFile(
76
- "wipBlock" + Math.random().toString(36).substring(7) + ".tmp.jsonl",
77
- );
78
- const hash = new StreamingHash(fs.crypto);
79
-
80
- const chunksSortedById = Array.from(chunks).sort(([id1], [id2]) =>
81
- id1.localeCompare(id2),
82
- );
83
-
84
- for (const [id, chunk] of chunksSortedById) {
85
- const encodedBytes = hash.update(chunk);
86
- const encodedBytesWithNewline = new Uint8Array(encodedBytes.length + 1);
87
- encodedBytesWithNewline.set(encodedBytes);
88
- encodedBytesWithNewline[encodedBytes.length] = 10;
89
- await fs.append(file, encodedBytesWithNewline);
90
- const length = encodedBytesWithNewline.length;
91
- blockHeader.push({ id, start: offset, length });
92
- offset += length;
93
- }
94
-
95
- const headerBytes = textEncoder.encode(JSON.stringify(blockHeader));
96
- await fs.append(file, headerBytes);
97
-
98
- // console.log(
99
- // "full file",
100
- // yield* $(
101
- // fs.read(file as unknown as RH, 0, offset + headerBytes.length),
102
- // ),
103
- // );
104
-
105
- const filename: BlockFilename = `L${level}-${(blockNumber + "").padStart(
106
- 3,
107
- "0",
108
- )}-${hash.digest().replace("hash_", "").slice(0, 15)}-H${
109
- headerBytes.length
110
- }.jsonl`;
111
- // console.log("renaming to" + filename);
112
- await fs.closeAndRename(file, filename);
113
-
114
- return filename;
115
-
116
- // console.log("Wrote block", filename, blockHeader);
117
- // console.log("IDs in block", blockHeader.map(e => e.id));
59
+ if (chunks.size === 0) {
60
+ throw new Error("No chunks to write");
61
+ }
62
+
63
+ const blockHeader: BlockHeader = [];
64
+
65
+ let offset = 0;
66
+
67
+ const file = await fs.createFile(
68
+ "wipBlock" + Math.random().toString(36).substring(7) + ".tmp.jsonl",
69
+ );
70
+ const hash = new StreamingHash(fs.crypto);
71
+
72
+ const chunksSortedById = Array.from(chunks).sort(([id1], [id2]) =>
73
+ id1.localeCompare(id2),
74
+ );
75
+
76
+ for (const [id, chunk] of chunksSortedById) {
77
+ const encodedBytes = hash.update(chunk);
78
+ const encodedBytesWithNewline = new Uint8Array(encodedBytes.length + 1);
79
+ encodedBytesWithNewline.set(encodedBytes);
80
+ encodedBytesWithNewline[encodedBytes.length] = 10;
81
+ await fs.append(file, encodedBytesWithNewline);
82
+ const length = encodedBytesWithNewline.length;
83
+ blockHeader.push({ id, start: offset, length });
84
+ offset += length;
85
+ }
86
+
87
+ const headerBytes = textEncoder.encode(JSON.stringify(blockHeader));
88
+ await fs.append(file, headerBytes);
89
+
90
+ // console.log(
91
+ // "full file",
92
+ // yield* $(
93
+ // fs.read(file as unknown as RH, 0, offset + headerBytes.length),
94
+ // ),
95
+ // );
96
+
97
+ const filename: BlockFilename = `L${level}-${(blockNumber + "").padStart(
98
+ 3,
99
+ "0",
100
+ )}-${hash.digest().replace("hash_", "").slice(0, 15)}-H${
101
+ headerBytes.length
102
+ }.jsonl`;
103
+ // console.log("renaming to" + filename);
104
+ await fs.closeAndRename(file, filename);
105
+
106
+ return filename;
107
+
108
+ // console.log("Wrote block", filename, blockHeader);
109
+ // console.log("IDs in block", blockHeader.map(e => e.id));
118
110
  }
119
111
 
120
112
  export async function writeToWal<WH, RH, FS extends FileSystem<WH, RH>>(
121
- handle: WH,
122
- fs: FS,
123
- id: RawCoID,
124
- chunk: CoValueChunk,
113
+ handle: WH,
114
+ fs: FS,
115
+ id: RawCoID,
116
+ chunk: CoValueChunk,
125
117
  ) {
126
- const walEntry: WalEntry = {
127
- id,
128
- ...chunk,
129
- };
130
- const bytes = textEncoder.encode(JSON.stringify(walEntry) + "\n");
131
- console.log("writing to WAL", handle, id, bytes.length);
132
- return fs.append(handle, bytes);
118
+ const walEntry: WalEntry = {
119
+ id,
120
+ ...chunk,
121
+ };
122
+ const bytes = textEncoder.encode(JSON.stringify(walEntry) + "\n");
123
+ console.log("writing to WAL", handle, id, bytes.length);
124
+ return fs.append(handle, bytes);
133
125
  }
@@ -1,142 +1,137 @@
1
- import { RawCoID, SessionID } from "../ids.js";
2
1
  import { MAX_RECOMMENDED_TX_SIZE } from "../coValueCore.js";
2
+ import { RawCoID, SessionID } from "../ids.js";
3
3
  import { getPriorityFromHeader } from "../priority.js";
4
4
  import { CoValueKnownState, NewContentMessage } from "../sync.js";
5
5
  import { CoValueChunk } from "./index.js";
6
6
 
7
7
  export function contentSinceChunk(
8
- id: RawCoID,
9
- chunk: CoValueChunk,
10
- known?: CoValueKnownState,
8
+ id: RawCoID,
9
+ chunk: CoValueChunk,
10
+ known?: CoValueKnownState,
11
11
  ): NewContentMessage[] {
12
- const newContentPieces: NewContentMessage[] = [];
13
-
14
- newContentPieces.push({
15
- id: id,
16
- action: "content",
17
- header: known?.header ? undefined : chunk.header,
18
- new: {},
19
- priority: getPriorityFromHeader(chunk.header),
20
- });
21
-
22
- for (const [sessionID, sessionsEntry] of Object.entries(
23
- chunk.sessionEntries,
24
- )) {
25
- for (const entry of sessionsEntry) {
26
- const knownStart = known?.sessions[sessionID as SessionID] || 0;
27
-
28
- if (entry.after + entry.transactions.length <= knownStart) {
29
- continue;
30
- }
31
-
32
- const actuallyNewTransactions = entry.transactions.slice(
33
- Math.max(0, knownStart - entry.after),
34
- );
35
-
36
- const newAfter =
37
- entry.after +
38
- (actuallyNewTransactions.length - entry.transactions.length);
39
-
40
- let newContentEntry =
41
- newContentPieces[0]?.new[sessionID as SessionID];
42
-
43
- if (!newContentEntry) {
44
- newContentEntry = {
45
- after: newAfter,
46
- lastSignature: entry.lastSignature,
47
- newTransactions: actuallyNewTransactions,
48
- };
49
- newContentPieces[0]!.new[sessionID as SessionID] =
50
- newContentEntry;
51
- } else {
52
- newContentEntry.newTransactions.push(
53
- ...actuallyNewTransactions,
54
- );
55
- newContentEntry.lastSignature = entry.lastSignature;
56
- }
57
- }
12
+ const newContentPieces: NewContentMessage[] = [];
13
+
14
+ newContentPieces.push({
15
+ id: id,
16
+ action: "content",
17
+ header: known?.header ? undefined : chunk.header,
18
+ new: {},
19
+ priority: getPriorityFromHeader(chunk.header),
20
+ });
21
+
22
+ for (const [sessionID, sessionsEntry] of Object.entries(
23
+ chunk.sessionEntries,
24
+ )) {
25
+ for (const entry of sessionsEntry) {
26
+ const knownStart = known?.sessions[sessionID as SessionID] || 0;
27
+
28
+ if (entry.after + entry.transactions.length <= knownStart) {
29
+ continue;
30
+ }
31
+
32
+ const actuallyNewTransactions = entry.transactions.slice(
33
+ Math.max(0, knownStart - entry.after),
34
+ );
35
+
36
+ const newAfter =
37
+ entry.after +
38
+ (actuallyNewTransactions.length - entry.transactions.length);
39
+
40
+ let newContentEntry = newContentPieces[0]?.new[sessionID as SessionID];
41
+
42
+ if (!newContentEntry) {
43
+ newContentEntry = {
44
+ after: newAfter,
45
+ lastSignature: entry.lastSignature,
46
+ newTransactions: actuallyNewTransactions,
47
+ };
48
+ newContentPieces[0]!.new[sessionID as SessionID] = newContentEntry;
49
+ } else {
50
+ newContentEntry.newTransactions.push(...actuallyNewTransactions);
51
+ newContentEntry.lastSignature = entry.lastSignature;
52
+ }
58
53
  }
54
+ }
59
55
 
60
- return newContentPieces;
56
+ return newContentPieces;
61
57
  }
62
58
 
63
59
  export function chunkToKnownState(id: RawCoID, chunk: CoValueChunk) {
64
- const ourKnown: CoValueKnownState = {
65
- id,
66
- header: !!chunk.header,
67
- sessions: {},
68
- };
69
-
70
- for (const [sessionID, sessionEntries] of Object.entries(
71
- chunk.sessionEntries,
72
- )) {
73
- for (const entry of sessionEntries) {
74
- ourKnown.sessions[sessionID as SessionID] =
75
- entry.after + entry.transactions.length;
76
- }
60
+ const ourKnown: CoValueKnownState = {
61
+ id,
62
+ header: !!chunk.header,
63
+ sessions: {},
64
+ };
65
+
66
+ for (const [sessionID, sessionEntries] of Object.entries(
67
+ chunk.sessionEntries,
68
+ )) {
69
+ for (const entry of sessionEntries) {
70
+ ourKnown.sessions[sessionID as SessionID] =
71
+ entry.after + entry.transactions.length;
77
72
  }
78
- return ourKnown;
73
+ }
74
+ return ourKnown;
79
75
  }
80
76
 
81
77
  export function mergeChunks(
82
- chunkA: CoValueChunk,
83
- chunkB: CoValueChunk,
78
+ chunkA: CoValueChunk,
79
+ chunkB: CoValueChunk,
84
80
  ): "nonContigous" | CoValueChunk {
85
- const header = chunkA.header || chunkB.header;
81
+ const header = chunkA.header || chunkB.header;
86
82
 
87
- const newSessions = { ...chunkA.sessionEntries };
88
- for (const sessionID in chunkB.sessionEntries) {
89
- // figure out if we can merge the chunks
90
- const sessionEntriesA = chunkA.sessionEntries[sessionID];
91
- const sessionEntriesB = chunkB.sessionEntries[sessionID]!;
83
+ const newSessions = { ...chunkA.sessionEntries };
84
+ for (const sessionID in chunkB.sessionEntries) {
85
+ // figure out if we can merge the chunks
86
+ const sessionEntriesA = chunkA.sessionEntries[sessionID];
87
+ const sessionEntriesB = chunkB.sessionEntries[sessionID]!;
92
88
 
93
- if (!sessionEntriesA) {
94
- newSessions[sessionID] = sessionEntriesB;
95
- continue;
96
- }
97
-
98
- const lastEntryOfA = sessionEntriesA[sessionEntriesA.length - 1]!;
99
- const firstEntryOfB = sessionEntriesB[0]!;
89
+ if (!sessionEntriesA) {
90
+ newSessions[sessionID] = sessionEntriesB;
91
+ continue;
92
+ }
100
93
 
94
+ const lastEntryOfA = sessionEntriesA[sessionEntriesA.length - 1]!;
95
+ const firstEntryOfB = sessionEntriesB[0]!;
96
+
97
+ if (
98
+ lastEntryOfA.after + lastEntryOfA.transactions.length ===
99
+ firstEntryOfB.after
100
+ ) {
101
+ const newEntries = [];
102
+ let bytesSinceLastSignature = 0;
103
+ for (const entry of sessionEntriesA.concat(sessionEntriesB)) {
104
+ const entryByteLength = entry.transactions.reduce(
105
+ (sum, tx) =>
106
+ sum +
107
+ (tx.privacy === "private"
108
+ ? tx.encryptedChanges.length
109
+ : tx.changes.length),
110
+ 0,
111
+ );
101
112
  if (
102
- lastEntryOfA.after + lastEntryOfA.transactions.length ===
103
- firstEntryOfB.after
113
+ newEntries.length === 0 ||
114
+ bytesSinceLastSignature + entryByteLength > MAX_RECOMMENDED_TX_SIZE
104
115
  ) {
105
- const newEntries = [];
106
- let bytesSinceLastSignature = 0;
107
- for (const entry of sessionEntriesA.concat(sessionEntriesB)) {
108
- const entryByteLength = entry.transactions.reduce(
109
- (sum, tx) =>
110
- sum +
111
- (tx.privacy === "private"
112
- ? tx.encryptedChanges.length
113
- : tx.changes.length),
114
- 0,
115
- );
116
- if (
117
- newEntries.length === 0 ||
118
- bytesSinceLastSignature + entryByteLength >
119
- MAX_RECOMMENDED_TX_SIZE
120
- ) {
121
- newEntries.push({
122
- after: entry.after,
123
- lastSignature: entry.lastSignature,
124
- transactions: entry.transactions,
125
- });
126
- bytesSinceLastSignature = 0;
127
- } else {
128
- const lastNewEntry = newEntries[newEntries.length - 1]!;
129
- lastNewEntry.transactions.push(...entry.transactions);
130
- lastNewEntry.lastSignature = entry.lastSignature;
131
-
132
- bytesSinceLastSignature += entry.transactions.length;
133
- }
134
- }
135
- newSessions[sessionID] = newEntries;
116
+ newEntries.push({
117
+ after: entry.after,
118
+ lastSignature: entry.lastSignature,
119
+ transactions: entry.transactions,
120
+ });
121
+ bytesSinceLastSignature = 0;
136
122
  } else {
137
- return "nonContigous" as const;
123
+ const lastNewEntry = newEntries[newEntries.length - 1]!;
124
+ lastNewEntry.transactions.push(...entry.transactions);
125
+ lastNewEntry.lastSignature = entry.lastSignature;
126
+
127
+ bytesSinceLastSignature += entry.transactions.length;
138
128
  }
129
+ }
130
+ newSessions[sessionID] = newEntries;
131
+ } else {
132
+ return "nonContigous" as const;
139
133
  }
134
+ }
140
135
 
141
- return { header, sessionEntries: newSessions };
136
+ return { header, sessionEntries: newSessions };
142
137
  }