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,397 +1,393 @@
1
+ import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
2
+ import { CoID, RawCoValue } from "../coValue.js";
3
+ import { CoValueCore } from "../coValueCore.js";
4
+ import { AgentID, SessionID, TransactionID } from "../ids.js";
1
5
  import { JsonObject, JsonValue } from "../jsonValue.js";
2
- import { RawCoValue, CoID } from "../coValue.js";
6
+ import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
3
7
  import { isAccountID } from "../typeUtils/isAccountID.js";
4
8
  import { isCoValue } from "../typeUtils/isCoValue.js";
5
- import { CoValueCore } from "../coValueCore.js";
6
- import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
7
- import { RawGroup } from "./group.js";
8
- import { AgentID, SessionID, TransactionID } from "../ids.js";
9
- import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
10
9
  import { RawAccountID } from "./account.js";
10
+ import { RawGroup } from "./group.js";
11
11
 
12
12
  export type BinaryStreamInfo = {
13
- mimeType: string;
14
- fileName?: string;
15
- totalSizeBytes?: number;
13
+ mimeType: string;
14
+ fileName?: string;
15
+ totalSizeBytes?: number;
16
16
  };
17
17
 
18
18
  export type BinaryStreamStart = {
19
- type: "start";
19
+ type: "start";
20
20
  } & BinaryStreamInfo;
21
21
 
22
22
  export type BinaryStreamChunk = {
23
- type: "chunk";
24
- chunk: `binary_U${string}`;
23
+ type: "chunk";
24
+ chunk: `binary_U${string}`;
25
25
  };
26
26
 
27
27
  export type BinaryStreamEnd = {
28
- type: "end";
28
+ type: "end";
29
29
  };
30
30
 
31
31
  export type BinaryCoStreamMeta = JsonObject & { type: "binary" };
32
32
 
33
33
  export type BinaryStreamItem =
34
- | BinaryStreamStart
35
- | BinaryStreamChunk
36
- | BinaryStreamEnd;
34
+ | BinaryStreamStart
35
+ | BinaryStreamChunk
36
+ | BinaryStreamEnd;
37
37
 
38
38
  export type CoStreamItem<Item extends JsonValue> = {
39
- value: Item;
40
- tx: TransactionID;
41
- madeAt: number;
39
+ value: Item;
40
+ tx: TransactionID;
41
+ madeAt: number;
42
42
  };
43
43
 
44
44
  export class RawCoStreamView<
45
- Item extends JsonValue = JsonValue,
46
- Meta extends JsonObject | null = JsonObject | null,
45
+ Item extends JsonValue = JsonValue,
46
+ Meta extends JsonObject | null = JsonObject | null,
47
47
  > implements RawCoValue
48
48
  {
49
- id: CoID<this>;
50
- type = "costream" as const;
51
- core: CoValueCore;
52
- items: {
53
- [key: SessionID]: CoStreamItem<Item>[];
54
- };
55
- readonly _item!: Item;
56
-
57
- constructor(core: CoValueCore) {
58
- this.id = core.id as CoID<this>;
59
- this.core = core;
60
- this.items = {};
61
- this.fillFromCoValue();
62
- }
63
-
64
- get headerMeta(): Meta {
65
- return this.core.header.meta as Meta;
66
- }
67
-
68
- get group(): RawGroup {
69
- return this.core.getGroup();
70
- }
71
-
72
- /** Not yet implemented */
73
- atTime(_time: number): this {
74
- throw new Error("Not yet implemented");
75
- }
76
-
77
- /** @internal */
78
- protected fillFromCoValue() {
79
- this.items = {};
80
-
81
- for (const {
82
- txID,
83
- madeAt,
84
- changes,
85
- } of this.core.getValidSortedTransactions()) {
86
- for (const changeUntyped of changes) {
87
- const change = changeUntyped as Item;
88
- let entries = this.items[txID.sessionID];
89
- if (!entries) {
90
- entries = [];
91
- this.items[txID.sessionID] = entries;
92
- }
93
- entries.push({ value: change, madeAt, tx: txID });
94
- }
49
+ id: CoID<this>;
50
+ type = "costream" as const;
51
+ core: CoValueCore;
52
+ items: {
53
+ [key: SessionID]: CoStreamItem<Item>[];
54
+ };
55
+ readonly _item!: Item;
56
+
57
+ constructor(core: CoValueCore) {
58
+ this.id = core.id as CoID<this>;
59
+ this.core = core;
60
+ this.items = {};
61
+ this.fillFromCoValue();
62
+ }
63
+
64
+ get headerMeta(): Meta {
65
+ return this.core.header.meta as Meta;
66
+ }
67
+
68
+ get group(): RawGroup {
69
+ return this.core.getGroup();
70
+ }
71
+
72
+ /** Not yet implemented */
73
+ atTime(_time: number): this {
74
+ throw new Error("Not yet implemented");
75
+ }
76
+
77
+ /** @internal */
78
+ protected fillFromCoValue() {
79
+ this.items = {};
80
+
81
+ for (const {
82
+ txID,
83
+ madeAt,
84
+ changes,
85
+ } of this.core.getValidSortedTransactions()) {
86
+ for (const changeUntyped of changes) {
87
+ const change = changeUntyped as Item;
88
+ let entries = this.items[txID.sessionID];
89
+ if (!entries) {
90
+ entries = [];
91
+ this.items[txID.sessionID] = entries;
95
92
  }
93
+ entries.push({ value: change, madeAt, tx: txID });
94
+ }
96
95
  }
96
+ }
97
97
 
98
- getSingleStream(): Item[] | undefined {
99
- const streams = Object.values(this.items);
100
- const firstStream = streams[0];
101
-
102
- if (!firstStream) {
103
- return undefined;
104
- }
98
+ getSingleStream(): Item[] | undefined {
99
+ const streams = Object.values(this.items);
100
+ const firstStream = streams[0];
105
101
 
106
- if (streams.length > 1) {
107
- throw new Error(
108
- "CoStream.getSingleStream() can only be called when there is exactly one stream",
109
- );
110
- }
111
-
112
- return firstStream.map((item) => item.value);
102
+ if (!firstStream) {
103
+ return undefined;
113
104
  }
114
105
 
115
- sessions(): SessionID[] {
116
- return Object.keys(this.items) as SessionID[];
106
+ if (streams.length > 1) {
107
+ throw new Error(
108
+ "CoStream.getSingleStream() can only be called when there is exactly one stream",
109
+ );
117
110
  }
118
111
 
119
- accounts(): Set<RawAccountID> {
120
- return new Set(
121
- this.sessions()
122
- .map(accountOrAgentIDfromSessionID)
123
- .filter(isAccountID),
124
- );
112
+ return firstStream.map((item) => item.value);
113
+ }
114
+
115
+ sessions(): SessionID[] {
116
+ return Object.keys(this.items) as SessionID[];
117
+ }
118
+
119
+ accounts(): Set<RawAccountID> {
120
+ return new Set(
121
+ this.sessions().map(accountOrAgentIDfromSessionID).filter(isAccountID),
122
+ );
123
+ }
124
+
125
+ nthItemIn(
126
+ sessionID: SessionID,
127
+ n: number,
128
+ ):
129
+ | {
130
+ by: RawAccountID | AgentID;
131
+ tx: TransactionID;
132
+ at: Date;
133
+ value: Item;
134
+ }
135
+ | undefined {
136
+ const items = this.items[sessionID];
137
+ if (!items) return;
138
+
139
+ const item = items[n];
140
+ if (!item) return;
141
+
142
+ return {
143
+ by: accountOrAgentIDfromSessionID(sessionID),
144
+ tx: item.tx,
145
+ at: new Date(item.madeAt),
146
+ value: item.value,
147
+ };
148
+ }
149
+
150
+ lastItemIn(sessionID: SessionID):
151
+ | {
152
+ by: RawAccountID | AgentID;
153
+ tx: TransactionID;
154
+ at: Date;
155
+ value: Item;
156
+ }
157
+ | undefined {
158
+ const items = this.items[sessionID];
159
+ if (!items) return;
160
+ return this.nthItemIn(sessionID, items.length - 1);
161
+ }
162
+
163
+ *itemsIn(sessionID: SessionID) {
164
+ const items = this.items[sessionID];
165
+ if (!items) return;
166
+ for (const item of items) {
167
+ yield {
168
+ by: accountOrAgentIDfromSessionID(sessionID),
169
+ tx: item.tx,
170
+ at: new Date(item.madeAt),
171
+ value: item.value as Item,
172
+ };
125
173
  }
126
-
127
- nthItemIn(
128
- sessionID: SessionID,
129
- n: number,
130
- ):
131
- | {
132
- by: RawAccountID | AgentID;
133
- tx: TransactionID;
134
- at: Date;
135
- value: Item;
136
- }
137
- | undefined {
138
- const items = this.items[sessionID];
139
- if (!items) return;
140
-
141
- const item = items[n];
142
- if (!item) return;
143
-
144
- return {
145
- by: accountOrAgentIDfromSessionID(sessionID),
174
+ }
175
+
176
+ lastItemBy(account: RawAccountID | AgentID):
177
+ | {
178
+ by: RawAccountID | AgentID;
179
+ tx: TransactionID;
180
+ at: Date;
181
+ value: Item;
182
+ }
183
+ | undefined {
184
+ let latestItem:
185
+ | {
186
+ by: RawAccountID | AgentID;
187
+ tx: TransactionID;
188
+ at: Date;
189
+ value: Item;
190
+ }
191
+ | undefined;
192
+
193
+ for (const sessionID of Object.keys(this.items)) {
194
+ if (sessionID.startsWith(account)) {
195
+ const item = this.lastItemIn(sessionID as SessionID);
196
+ if (!item) continue;
197
+ if (!latestItem || item.at > latestItem.at) {
198
+ latestItem = {
199
+ by: item.by,
146
200
  tx: item.tx,
147
- at: new Date(item.madeAt),
201
+ at: item.at,
148
202
  value: item.value,
149
- };
150
- }
151
-
152
- lastItemIn(sessionID: SessionID):
153
- | {
154
- by: RawAccountID | AgentID;
155
- tx: TransactionID;
156
- at: Date;
157
- value: Item;
158
- }
159
- | undefined {
160
- const items = this.items[sessionID];
161
- if (!items) return;
162
- return this.nthItemIn(sessionID, items.length - 1);
163
- }
164
-
165
- *itemsIn(sessionID: SessionID) {
166
- const items = this.items[sessionID];
167
- if (!items) return;
168
- for (const item of items) {
169
- yield {
170
- by: accountOrAgentIDfromSessionID(sessionID),
171
- tx: item.tx,
172
- at: new Date(item.madeAt),
173
- value: item.value as Item,
174
- };
175
- }
176
- }
177
-
178
- lastItemBy(account: RawAccountID | AgentID):
179
- | {
180
- by: RawAccountID | AgentID;
181
- tx: TransactionID;
182
- at: Date;
183
- value: Item;
184
- }
185
- | undefined {
186
- let latestItem:
187
- | {
188
- by: RawAccountID | AgentID;
189
- tx: TransactionID;
190
- at: Date;
191
- value: Item;
192
- }
193
- | undefined;
194
-
195
- for (const sessionID of Object.keys(this.items)) {
196
- if (sessionID.startsWith(account)) {
197
- const item = this.lastItemIn(sessionID as SessionID);
198
- if (!item) continue;
199
- if (!latestItem || item.at > latestItem.at) {
200
- latestItem = {
201
- by: item.by,
202
- tx: item.tx,
203
- at: item.at,
204
- value: item.value,
205
- };
206
- }
207
- }
203
+ };
208
204
  }
209
-
210
- return latestItem;
205
+ }
211
206
  }
212
207
 
213
- *itemsBy(account: RawAccountID | AgentID) {
214
- // TODO: this can be made more lazy without a huge collect and sort
215
- const items = [
216
- ...Object.keys(this.items).flatMap((sessionID) =>
217
- sessionID.startsWith(account)
218
- ? [...this.itemsIn(sessionID as SessionID)].map((item) => ({
219
- in: sessionID as SessionID,
220
- ...item,
221
- }))
222
- : [],
223
- ),
224
- ];
225
-
226
- items.sort((a, b) => a.at.getTime() - b.at.getTime());
227
-
228
- for (const item of items) {
229
- yield item;
230
- }
231
- }
232
-
233
- toJSON(): {
234
- [key: SessionID]: Item[];
235
- } {
236
- return Object.fromEntries(
237
- Object.entries(this.items).map(([sessionID, items]) => [
238
- sessionID,
239
- items.map((item) => item.value),
240
- ]),
241
- );
242
- }
243
-
244
- subscribe(listener: (coStream: this) => void): () => void {
245
- return this.core.subscribe((content) => {
246
- listener(content as this);
247
- });
208
+ return latestItem;
209
+ }
210
+
211
+ *itemsBy(account: RawAccountID | AgentID) {
212
+ // TODO: this can be made more lazy without a huge collect and sort
213
+ const items = [
214
+ ...Object.keys(this.items).flatMap((sessionID) =>
215
+ sessionID.startsWith(account)
216
+ ? [...this.itemsIn(sessionID as SessionID)].map((item) => ({
217
+ in: sessionID as SessionID,
218
+ ...item,
219
+ }))
220
+ : [],
221
+ ),
222
+ ];
223
+
224
+ items.sort((a, b) => a.at.getTime() - b.at.getTime());
225
+
226
+ for (const item of items) {
227
+ yield item;
248
228
  }
229
+ }
230
+
231
+ toJSON(): {
232
+ [key: SessionID]: Item[];
233
+ } {
234
+ return Object.fromEntries(
235
+ Object.entries(this.items).map(([sessionID, items]) => [
236
+ sessionID,
237
+ items.map((item) => item.value),
238
+ ]),
239
+ );
240
+ }
241
+
242
+ subscribe(listener: (coStream: this) => void): () => void {
243
+ return this.core.subscribe((content) => {
244
+ listener(content as this);
245
+ });
246
+ }
249
247
  }
250
248
 
251
249
  export class RawCoStream<
252
- Item extends JsonValue = JsonValue,
253
- Meta extends JsonObject | null = JsonObject | null,
254
- >
255
- extends RawCoStreamView<Item, Meta>
256
- implements RawCoValue
250
+ Item extends JsonValue = JsonValue,
251
+ Meta extends JsonObject | null = JsonObject | null,
252
+ >
253
+ extends RawCoStreamView<Item, Meta>
254
+ implements RawCoValue
257
255
  {
258
- push(item: Item, privacy: "private" | "trusting" = "private"): void {
259
- this.core.makeTransaction([isCoValue(item) ? item.id : item], privacy);
260
- this.fillFromCoValue();
261
- }
256
+ push(item: Item, privacy: "private" | "trusting" = "private"): void {
257
+ this.core.makeTransaction([isCoValue(item) ? item.id : item], privacy);
258
+ this.fillFromCoValue();
259
+ }
262
260
  }
263
261
 
264
262
  const binary_U_prefixLength = 8; // "binary_U".length;
265
263
 
266
264
  export class RawBinaryCoStreamView<
267
- Meta extends BinaryCoStreamMeta = { type: "binary" },
268
- >
269
- extends RawCoStreamView<BinaryStreamItem, Meta>
270
- implements RawCoValue
265
+ Meta extends BinaryCoStreamMeta = { type: "binary" },
266
+ >
267
+ extends RawCoStreamView<BinaryStreamItem, Meta>
268
+ implements RawCoValue
271
269
  {
272
- isBinaryStreamEnded() {
273
- const items = this.getSingleStream();
274
-
275
- if (!items || items.length === 0) {
276
- return false;
277
- }
278
-
279
- const lastItem = items[items.length - 1];
270
+ isBinaryStreamEnded() {
271
+ const items = this.getSingleStream();
280
272
 
281
- return lastItem?.type === "end";
273
+ if (!items || items.length === 0) {
274
+ return false;
282
275
  }
283
276
 
284
- getBinaryChunks(
285
- allowUnfinished?: boolean,
286
- ):
287
- | (BinaryStreamInfo & { chunks: Uint8Array[]; finished: boolean })
288
- | undefined {
289
- const items = this.getSingleStream();
277
+ const lastItem = items[items.length - 1];
290
278
 
291
- // No active streams
292
- if (!items) return;
279
+ return lastItem?.type === "end";
280
+ }
293
281
 
294
- const start = items[0];
282
+ getBinaryChunks(
283
+ allowUnfinished?: boolean,
284
+ ):
285
+ | (BinaryStreamInfo & { chunks: Uint8Array[]; finished: boolean })
286
+ | undefined {
287
+ const items = this.getSingleStream();
295
288
 
296
- if (start?.type !== "start") {
297
- console.error("Invalid binary stream start", start);
298
- return;
299
- }
289
+ // No active streams
290
+ if (!items) return;
291
+
292
+ const start = items[0];
300
293
 
301
- const end = items[items.length - 1];
294
+ if (start?.type !== "start") {
295
+ console.error("Invalid binary stream start", start);
296
+ return;
297
+ }
302
298
 
303
- if (end?.type !== "end" && !allowUnfinished) return;
299
+ const end = items[items.length - 1];
304
300
 
305
- const chunks: Uint8Array[] = [];
301
+ if (end?.type !== "end" && !allowUnfinished) return;
306
302
 
307
- let finished = false;
303
+ const chunks: Uint8Array[] = [];
308
304
 
309
- for (const item of items.slice(1)) {
310
- if (item.type === "end") {
311
- finished = true;
312
- break;
313
- }
305
+ let finished = false;
314
306
 
315
- if (item.type !== "chunk") {
316
- console.error("Invalid binary stream chunk", item);
317
- return undefined;
318
- }
307
+ for (const item of items.slice(1)) {
308
+ if (item.type === "end") {
309
+ finished = true;
310
+ break;
311
+ }
319
312
 
320
- const chunk = base64URLtoBytes(
321
- item.chunk.slice(binary_U_prefixLength),
322
- );
323
- chunks.push(chunk);
324
- }
313
+ if (item.type !== "chunk") {
314
+ console.error("Invalid binary stream chunk", item);
315
+ return undefined;
316
+ }
325
317
 
326
- return {
327
- mimeType: start.mimeType,
328
- fileName: start.fileName,
329
- totalSizeBytes: start.totalSizeBytes,
330
- chunks,
331
- finished,
332
- };
318
+ const chunk = base64URLtoBytes(item.chunk.slice(binary_U_prefixLength));
319
+ chunks.push(chunk);
333
320
  }
321
+
322
+ return {
323
+ mimeType: start.mimeType,
324
+ fileName: start.fileName,
325
+ totalSizeBytes: start.totalSizeBytes,
326
+ chunks,
327
+ finished,
328
+ };
329
+ }
334
330
  }
335
331
 
336
332
  export class RawBinaryCoStream<
337
- Meta extends BinaryCoStreamMeta = { type: "binary" },
338
- >
339
- extends RawBinaryCoStreamView<Meta>
340
- implements RawCoValue
333
+ Meta extends BinaryCoStreamMeta = { type: "binary" },
334
+ >
335
+ extends RawBinaryCoStreamView<Meta>
336
+ implements RawCoValue
341
337
  {
342
- /** @internal */
343
- push(
344
- item: BinaryStreamItem,
345
- privacy: "private" | "trusting" = "private",
346
- updateView: boolean = true,
347
- ): void {
348
- this.core.makeTransaction([item], privacy);
349
- if (updateView) {
350
- this.fillFromCoValue();
351
- }
352
- }
353
-
354
- startBinaryStream(
355
- settings: BinaryStreamInfo,
356
- privacy: "private" | "trusting" = "private",
357
- ): void {
358
- this.push(
359
- {
360
- type: "start",
361
- ...settings,
362
- } satisfies BinaryStreamStart,
363
- privacy,
364
- false,
365
- );
366
- }
367
-
368
- pushBinaryStreamChunk(
369
- chunk: Uint8Array,
370
- privacy: "private" | "trusting" = "private",
371
- ): void {
372
- // const before = performance.now();
373
- this.push(
374
- {
375
- type: "chunk",
376
- chunk: `binary_U${bytesToBase64url(chunk)}`,
377
- } satisfies BinaryStreamChunk,
378
- privacy,
379
- false,
380
- );
381
- // const after = performance.now();
382
- // console.log(
383
- // "pushBinaryStreamChunk bandwidth in MB/s",
384
- // (1000 * chunk.length) / (after - before) / (1024 * 1024)
385
- // );
386
- }
387
-
388
- endBinaryStream(privacy: "private" | "trusting" = "private") {
389
- this.push(
390
- {
391
- type: "end",
392
- } satisfies BinaryStreamEnd,
393
- privacy,
394
- true,
395
- );
338
+ /** @internal */
339
+ push(
340
+ item: BinaryStreamItem,
341
+ privacy: "private" | "trusting" = "private",
342
+ updateView: boolean = true,
343
+ ): void {
344
+ this.core.makeTransaction([item], privacy);
345
+ if (updateView) {
346
+ this.fillFromCoValue();
396
347
  }
348
+ }
349
+
350
+ startBinaryStream(
351
+ settings: BinaryStreamInfo,
352
+ privacy: "private" | "trusting" = "private",
353
+ ): void {
354
+ this.push(
355
+ {
356
+ type: "start",
357
+ ...settings,
358
+ } satisfies BinaryStreamStart,
359
+ privacy,
360
+ false,
361
+ );
362
+ }
363
+
364
+ pushBinaryStreamChunk(
365
+ chunk: Uint8Array,
366
+ privacy: "private" | "trusting" = "private",
367
+ ): void {
368
+ // const before = performance.now();
369
+ this.push(
370
+ {
371
+ type: "chunk",
372
+ chunk: `binary_U${bytesToBase64url(chunk)}`,
373
+ } satisfies BinaryStreamChunk,
374
+ privacy,
375
+ false,
376
+ );
377
+ // const after = performance.now();
378
+ // console.log(
379
+ // "pushBinaryStreamChunk bandwidth in MB/s",
380
+ // (1000 * chunk.length) / (after - before) / (1024 * 1024)
381
+ // );
382
+ }
383
+
384
+ endBinaryStream(privacy: "private" | "trusting" = "private") {
385
+ this.push(
386
+ {
387
+ type: "end",
388
+ } satisfies BinaryStreamEnd,
389
+ privacy,
390
+ true,
391
+ );
392
+ }
397
393
  }