cojson 0.8.12 → 0.8.17

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 (164) hide show
  1. package/CHANGELOG.md +95 -83
  2. package/dist/native/PeerKnownStates.js +6 -1
  3. package/dist/native/PeerKnownStates.js.map +1 -1
  4. package/dist/native/PeerState.js +4 -3
  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/SyncStateSubscriptionManager.js +70 -0
  9. package/dist/native/SyncStateSubscriptionManager.js.map +1 -0
  10. package/dist/native/base64url.js.map +1 -1
  11. package/dist/native/base64url.test.js +1 -1
  12. package/dist/native/base64url.test.js.map +1 -1
  13. package/dist/native/coValue.js.map +1 -1
  14. package/dist/native/coValueCore.js +141 -149
  15. package/dist/native/coValueCore.js.map +1 -1
  16. package/dist/native/coValueState.js.map +1 -1
  17. package/dist/native/coValues/account.js +6 -6
  18. package/dist/native/coValues/account.js.map +1 -1
  19. package/dist/native/coValues/coList.js +2 -3
  20. package/dist/native/coValues/coList.js.map +1 -1
  21. package/dist/native/coValues/coMap.js +1 -1
  22. package/dist/native/coValues/coMap.js.map +1 -1
  23. package/dist/native/coValues/coStream.js +3 -5
  24. package/dist/native/coValues/coStream.js.map +1 -1
  25. package/dist/native/coValues/group.js +11 -11
  26. package/dist/native/coValues/group.js.map +1 -1
  27. package/dist/native/coreToCoValue.js +2 -2
  28. package/dist/native/coreToCoValue.js.map +1 -1
  29. package/dist/native/crypto/PureJSCrypto.js +4 -4
  30. package/dist/native/crypto/PureJSCrypto.js.map +1 -1
  31. package/dist/native/crypto/crypto.js.map +1 -1
  32. package/dist/native/exports.js +12 -12
  33. package/dist/native/exports.js.map +1 -1
  34. package/dist/native/ids.js.map +1 -1
  35. package/dist/native/jsonStringify.js.map +1 -1
  36. package/dist/native/localNode.js +5 -7
  37. package/dist/native/localNode.js.map +1 -1
  38. package/dist/native/permissions.js +4 -7
  39. package/dist/native/permissions.js.map +1 -1
  40. package/dist/native/priority.js.map +1 -1
  41. package/dist/native/storage/FileSystem.js.map +1 -1
  42. package/dist/native/storage/chunksAndKnownStates.js +2 -4
  43. package/dist/native/storage/chunksAndKnownStates.js.map +1 -1
  44. package/dist/native/storage/index.js +6 -15
  45. package/dist/native/storage/index.js.map +1 -1
  46. package/dist/native/streamUtils.js.map +1 -1
  47. package/dist/native/sync.js +57 -7
  48. package/dist/native/sync.js.map +1 -1
  49. package/dist/native/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  50. package/dist/native/typeUtils/expectGroup.js.map +1 -1
  51. package/dist/native/typeUtils/isAccountID.js.map +1 -1
  52. package/dist/native/typeUtils/isCoValue.js +1 -1
  53. package/dist/native/typeUtils/isCoValue.js.map +1 -1
  54. package/dist/web/PeerKnownStates.js +6 -1
  55. package/dist/web/PeerKnownStates.js.map +1 -1
  56. package/dist/web/PeerState.js +4 -3
  57. package/dist/web/PeerState.js.map +1 -1
  58. package/dist/web/PriorityBasedMessageQueue.js +1 -10
  59. package/dist/web/PriorityBasedMessageQueue.js.map +1 -1
  60. package/dist/web/SyncStateSubscriptionManager.js +70 -0
  61. package/dist/web/SyncStateSubscriptionManager.js.map +1 -0
  62. package/dist/web/base64url.js.map +1 -1
  63. package/dist/web/base64url.test.js +1 -1
  64. package/dist/web/base64url.test.js.map +1 -1
  65. package/dist/web/coValue.js.map +1 -1
  66. package/dist/web/coValueCore.js +141 -149
  67. package/dist/web/coValueCore.js.map +1 -1
  68. package/dist/web/coValueState.js.map +1 -1
  69. package/dist/web/coValues/account.js +6 -6
  70. package/dist/web/coValues/account.js.map +1 -1
  71. package/dist/web/coValues/coList.js +2 -3
  72. package/dist/web/coValues/coList.js.map +1 -1
  73. package/dist/web/coValues/coMap.js +1 -1
  74. package/dist/web/coValues/coMap.js.map +1 -1
  75. package/dist/web/coValues/coStream.js +3 -5
  76. package/dist/web/coValues/coStream.js.map +1 -1
  77. package/dist/web/coValues/group.js +11 -11
  78. package/dist/web/coValues/group.js.map +1 -1
  79. package/dist/web/coreToCoValue.js +2 -2
  80. package/dist/web/coreToCoValue.js.map +1 -1
  81. package/dist/web/crypto/PureJSCrypto.js +4 -4
  82. package/dist/web/crypto/PureJSCrypto.js.map +1 -1
  83. package/dist/web/crypto/WasmCrypto.js +5 -5
  84. package/dist/web/crypto/WasmCrypto.js.map +1 -1
  85. package/dist/web/crypto/crypto.js.map +1 -1
  86. package/dist/web/exports.js +12 -12
  87. package/dist/web/exports.js.map +1 -1
  88. package/dist/web/ids.js.map +1 -1
  89. package/dist/web/jsonStringify.js.map +1 -1
  90. package/dist/web/localNode.js +5 -7
  91. package/dist/web/localNode.js.map +1 -1
  92. package/dist/web/permissions.js +4 -7
  93. package/dist/web/permissions.js.map +1 -1
  94. package/dist/web/priority.js.map +1 -1
  95. package/dist/web/storage/FileSystem.js.map +1 -1
  96. package/dist/web/storage/chunksAndKnownStates.js +2 -4
  97. package/dist/web/storage/chunksAndKnownStates.js.map +1 -1
  98. package/dist/web/storage/index.js +6 -15
  99. package/dist/web/storage/index.js.map +1 -1
  100. package/dist/web/streamUtils.js.map +1 -1
  101. package/dist/web/sync.js +57 -7
  102. package/dist/web/sync.js.map +1 -1
  103. package/dist/web/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
  104. package/dist/web/typeUtils/expectGroup.js.map +1 -1
  105. package/dist/web/typeUtils/isAccountID.js.map +1 -1
  106. package/dist/web/typeUtils/isCoValue.js +1 -1
  107. package/dist/web/typeUtils/isCoValue.js.map +1 -1
  108. package/package.json +4 -14
  109. package/src/PeerKnownStates.ts +98 -90
  110. package/src/PeerState.ts +92 -73
  111. package/src/PriorityBasedMessageQueue.ts +42 -49
  112. package/src/SyncStateSubscriptionManager.ts +124 -0
  113. package/src/base64url.test.ts +24 -24
  114. package/src/base64url.ts +44 -45
  115. package/src/coValue.ts +45 -45
  116. package/src/coValueCore.ts +746 -785
  117. package/src/coValueState.ts +82 -72
  118. package/src/coValues/account.ts +143 -150
  119. package/src/coValues/coList.ts +520 -522
  120. package/src/coValues/coMap.ts +283 -285
  121. package/src/coValues/coStream.ts +320 -324
  122. package/src/coValues/group.ts +306 -305
  123. package/src/coreToCoValue.ts +28 -31
  124. package/src/crypto/PureJSCrypto.ts +188 -194
  125. package/src/crypto/WasmCrypto.ts +236 -254
  126. package/src/crypto/crypto.ts +302 -309
  127. package/src/exports.ts +116 -116
  128. package/src/ids.ts +9 -9
  129. package/src/jsonStringify.ts +46 -46
  130. package/src/jsonValue.ts +24 -10
  131. package/src/localNode.ts +635 -660
  132. package/src/media.ts +3 -3
  133. package/src/permissions.ts +272 -278
  134. package/src/priority.ts +21 -19
  135. package/src/storage/FileSystem.ts +91 -99
  136. package/src/storage/chunksAndKnownStates.ts +110 -115
  137. package/src/storage/index.ts +466 -497
  138. package/src/streamUtils.ts +60 -60
  139. package/src/sync.ts +656 -608
  140. package/src/tests/PeerKnownStates.test.ts +38 -34
  141. package/src/tests/PeerState.test.ts +101 -64
  142. package/src/tests/PriorityBasedMessageQueue.test.ts +91 -91
  143. package/src/tests/SyncStateSubscriptionManager.test.ts +232 -0
  144. package/src/tests/account.test.ts +59 -59
  145. package/src/tests/coList.test.ts +65 -65
  146. package/src/tests/coMap.test.ts +137 -137
  147. package/src/tests/coStream.test.ts +254 -257
  148. package/src/tests/coValueCore.test.ts +153 -156
  149. package/src/tests/crypto.test.ts +136 -144
  150. package/src/tests/cryptoImpl.test.ts +205 -197
  151. package/src/tests/group.test.ts +24 -24
  152. package/src/tests/permissions.test.ts +1306 -1371
  153. package/src/tests/priority.test.ts +65 -82
  154. package/src/tests/sync.test.ts +1573 -1263
  155. package/src/tests/testUtils.ts +85 -53
  156. package/src/typeUtils/accountOrAgentIDfromSessionID.ts +4 -4
  157. package/src/typeUtils/expectGroup.ts +9 -9
  158. package/src/typeUtils/isAccountID.ts +1 -1
  159. package/src/typeUtils/isCoValue.ts +9 -9
  160. package/tsconfig.json +4 -6
  161. package/tsconfig.native.json +9 -11
  162. package/tsconfig.web.json +4 -10
  163. package/.eslintrc.cjs +0 -25
  164. 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
  }