cojson 0.2.2 → 0.3.0-alpha.0
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.
- package/.eslintrc.cjs +1 -0
- package/dist/account.d.ts +8 -8
- package/dist/account.js +2 -2
- package/dist/account.js.map +1 -1
- package/dist/coValue.d.ts +22 -27
- package/dist/coValue.js +21 -0
- package/dist/coValue.js.map +1 -1
- package/dist/coValueCore.d.ts +7 -7
- package/dist/coValueCore.js +11 -14
- package/dist/coValueCore.js.map +1 -1
- package/dist/coValues/coList.d.ts +107 -42
- package/dist/coValues/coList.js +163 -72
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.d.ts +109 -50
- package/dist/coValues/coMap.js +161 -109
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.d.ts +78 -33
- package/dist/coValues/coStream.js +134 -53
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/crypto.d.ts +8 -3
- package/dist/crypto.js +6 -6
- package/dist/crypto.js.map +1 -1
- package/dist/group.d.ts +59 -23
- package/dist/group.js +83 -25
- package/dist/group.js.map +1 -1
- package/dist/index.d.ts +14 -11
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/{node.d.ts → localNode.d.ts} +23 -11
- package/dist/{node.js → localNode.js} +80 -42
- package/dist/localNode.js.map +1 -0
- package/dist/media.d.ts +1 -2
- package/dist/permissions.js +6 -3
- package/dist/permissions.js.map +1 -1
- package/dist/queriedCoValues/queriedCoList.d.ts +66 -0
- package/dist/queriedCoValues/queriedCoList.js +120 -0
- package/dist/queriedCoValues/queriedCoList.js.map +1 -0
- package/dist/queriedCoValues/queriedCoMap.d.ts +47 -0
- package/dist/queriedCoValues/queriedCoMap.js +83 -0
- package/dist/queriedCoValues/queriedCoMap.js.map +1 -0
- package/dist/queriedCoValues/queriedCoStream.d.ts +40 -0
- package/dist/queriedCoValues/queriedCoStream.js +72 -0
- package/dist/queriedCoValues/queriedCoStream.js.map +1 -0
- package/dist/queries.d.ts +31 -0
- package/dist/queries.js +77 -0
- package/dist/queries.js.map +1 -0
- package/dist/sync.d.ts +1 -1
- package/dist/sync.js +1 -1
- package/dist/sync.js.map +1 -1
- package/dist/{testUtils.d.ts → tests/testUtils.d.ts} +9 -9
- package/dist/{testUtils.js → tests/testUtils.js} +9 -7
- package/dist/tests/testUtils.js.map +1 -0
- package/package.json +2 -2
- package/src/account.ts +6 -6
- package/src/coValue.ts +65 -34
- package/src/coValueCore.ts +18 -22
- package/src/coValues/coList.ts +272 -122
- package/src/coValues/coMap.ts +349 -152
- package/src/coValues/coStream.ts +258 -94
- package/src/crypto.ts +37 -24
- package/src/group.ts +112 -46
- package/src/index.ts +42 -30
- package/src/{node.ts → localNode.ts} +117 -66
- package/src/media.ts +1 -2
- package/src/permissions.ts +15 -18
- package/src/queriedCoValues/queriedCoList.ts +248 -0
- package/src/queriedCoValues/queriedCoMap.ts +180 -0
- package/src/queriedCoValues/queriedCoStream.ts +125 -0
- package/src/queries.ts +142 -0
- package/src/sync.ts +2 -2
- package/src/{account.test.ts → tests/account.test.ts} +6 -9
- package/src/{coValue.test.ts → tests/coValue.test.ts} +120 -114
- package/src/{coValueCore.test.ts → tests/coValueCore.test.ts} +7 -7
- package/src/{crypto.test.ts → tests/crypto.test.ts} +19 -21
- package/src/{group.test.ts → tests/group.test.ts} +2 -2
- package/src/{permissions.test.ts → tests/permissions.test.ts} +260 -247
- package/src/tests/queries.test.ts +318 -0
- package/src/{sync.test.ts → tests/sync.test.ts} +39 -39
- package/src/{testUtils.ts → tests/testUtils.ts} +10 -8
- package/dist/coValues/static.d.ts +0 -14
- package/dist/coValues/static.js +0 -20
- package/dist/coValues/static.js.map +0 -1
- package/dist/node.js.map +0 -1
- package/dist/testUtils.js.map +0 -1
- package/src/coValues/static.ts +0 -31
package/src/coValues/coStream.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { JsonObject, JsonValue } from "../jsonValue.js";
|
|
2
|
-
import {
|
|
2
|
+
import { CoValue, CoID, isCoValue } from "../coValue.js";
|
|
3
3
|
import { CoValueCore, accountOrAgentIDfromSessionID } from "../coValueCore.js";
|
|
4
4
|
import { Group } from "../group.js";
|
|
5
|
-
import { SessionID } from "../ids.js";
|
|
5
|
+
import { AgentID, SessionID, TransactionID } from "../ids.js";
|
|
6
6
|
import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
|
|
7
|
-
import { AccountID } from "../
|
|
8
|
-
import { isAccountID } from "../account.js";
|
|
7
|
+
import { AccountID } from "../account.js";
|
|
9
8
|
import { parseJSON } from "../jsonStringify.js";
|
|
10
9
|
|
|
11
|
-
export type
|
|
10
|
+
export type BinaryStreamInfo = {
|
|
12
11
|
mimeType: string;
|
|
13
12
|
fileName?: string;
|
|
14
13
|
totalSizeBytes?: number;
|
|
@@ -16,7 +15,7 @@ export type BinaryChunkInfo = {
|
|
|
16
15
|
|
|
17
16
|
export type BinaryStreamStart = {
|
|
18
17
|
type: "start";
|
|
19
|
-
} &
|
|
18
|
+
} & BinaryStreamInfo;
|
|
20
19
|
|
|
21
20
|
export type BinaryStreamChunk = {
|
|
22
21
|
type: "chunk";
|
|
@@ -34,20 +33,27 @@ export type BinaryStreamItem =
|
|
|
34
33
|
| BinaryStreamChunk
|
|
35
34
|
| BinaryStreamEnd;
|
|
36
35
|
|
|
37
|
-
export
|
|
38
|
-
|
|
36
|
+
export type CoStreamItem<Item extends JsonValue | CoValue> = {
|
|
37
|
+
value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
|
|
38
|
+
tx: TransactionID;
|
|
39
|
+
madeAt: number;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export class CoStreamView<
|
|
43
|
+
Item extends JsonValue | CoValue,
|
|
39
44
|
Meta extends JsonObject | null = null
|
|
40
|
-
> implements
|
|
45
|
+
> implements CoValue
|
|
41
46
|
{
|
|
42
|
-
id: CoID<
|
|
47
|
+
id: CoID<this>;
|
|
43
48
|
type = "costream" as const;
|
|
44
49
|
core: CoValueCore;
|
|
45
50
|
items: {
|
|
46
|
-
[key: SessionID]:
|
|
51
|
+
[key: SessionID]: CoStreamItem<Item>[];
|
|
47
52
|
};
|
|
53
|
+
readonly _item!: Item;
|
|
48
54
|
|
|
49
55
|
constructor(core: CoValueCore) {
|
|
50
|
-
this.id = core.id as CoID<
|
|
56
|
+
this.id = core.id as CoID<this>;
|
|
51
57
|
this.core = core;
|
|
52
58
|
this.items = {};
|
|
53
59
|
this.fillFromCoValue();
|
|
@@ -61,6 +67,11 @@ export class CoStream<
|
|
|
61
67
|
return this.core.getGroup();
|
|
62
68
|
}
|
|
63
69
|
|
|
70
|
+
/** Not yet implemented */
|
|
71
|
+
atTime(_time: number): this {
|
|
72
|
+
throw new Error("Not yet implemented");
|
|
73
|
+
}
|
|
74
|
+
|
|
64
75
|
/** @internal */
|
|
65
76
|
protected fillFromCoValue() {
|
|
66
77
|
this.items = {};
|
|
@@ -71,18 +82,22 @@ export class CoStream<
|
|
|
71
82
|
changes,
|
|
72
83
|
} of this.core.getValidSortedTransactions()) {
|
|
73
84
|
for (const changeUntyped of parseJSON(changes)) {
|
|
74
|
-
const change = changeUntyped as
|
|
85
|
+
const change = changeUntyped as Item extends CoValue
|
|
86
|
+
? CoID<Item>
|
|
87
|
+
: Exclude<Item, CoValue>;
|
|
75
88
|
let entries = this.items[txID.sessionID];
|
|
76
89
|
if (!entries) {
|
|
77
90
|
entries = [];
|
|
78
91
|
this.items[txID.sessionID] = entries;
|
|
79
92
|
}
|
|
80
|
-
entries.push({
|
|
93
|
+
entries.push({ value: change, madeAt, tx: txID });
|
|
81
94
|
}
|
|
82
95
|
}
|
|
83
96
|
}
|
|
84
97
|
|
|
85
|
-
getSingleStream():
|
|
98
|
+
getSingleStream():
|
|
99
|
+
| (Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>)[]
|
|
100
|
+
| undefined {
|
|
86
101
|
if (Object.keys(this.items).length === 0) {
|
|
87
102
|
return undefined;
|
|
88
103
|
} else if (Object.keys(this.items).length !== 1) {
|
|
@@ -91,86 +106,202 @@ export class CoStream<
|
|
|
91
106
|
);
|
|
92
107
|
}
|
|
93
108
|
|
|
94
|
-
return Object.values(this.items)[0]?.map(item => item.
|
|
109
|
+
return Object.values(this.items)[0]?.map((item) => item.value);
|
|
95
110
|
}
|
|
96
111
|
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
sessions(): SessionID[] {
|
|
113
|
+
return Object.keys(this.items) as SessionID[];
|
|
114
|
+
}
|
|
99
115
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
116
|
+
accounts(): Set<AccountID | AgentID> {
|
|
117
|
+
return new Set(this.sessions().map(accountOrAgentIDfromSessionID));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
nthItemIn(
|
|
121
|
+
sessionID: SessionID,
|
|
122
|
+
n: number
|
|
123
|
+
):
|
|
124
|
+
| {
|
|
125
|
+
by: AccountID | AgentID;
|
|
126
|
+
tx: TransactionID;
|
|
127
|
+
at: Date;
|
|
128
|
+
value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
|
|
129
|
+
}
|
|
130
|
+
| undefined {
|
|
131
|
+
const items = this.items[sessionID];
|
|
132
|
+
if (!items) return;
|
|
133
|
+
|
|
134
|
+
const item = items[n];
|
|
135
|
+
if (!item) return;
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
by: accountOrAgentIDfromSessionID(sessionID),
|
|
139
|
+
tx: item.tx,
|
|
140
|
+
at: new Date(item.madeAt),
|
|
141
|
+
value: item.value,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
110
144
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
145
|
+
lastItemIn(sessionID: SessionID):
|
|
146
|
+
| {
|
|
147
|
+
by: AccountID | AgentID;
|
|
148
|
+
tx: TransactionID;
|
|
149
|
+
at: Date;
|
|
150
|
+
value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
|
|
151
|
+
}
|
|
152
|
+
| undefined {
|
|
153
|
+
const items = this.items[sessionID];
|
|
154
|
+
if (!items) return;
|
|
155
|
+
return this.nthItemIn(sessionID, items.length - 1);
|
|
114
156
|
}
|
|
115
157
|
|
|
116
|
-
|
|
117
|
-
|
|
158
|
+
*itemsIn(sessionID: SessionID) {
|
|
159
|
+
const items = this.items[sessionID];
|
|
160
|
+
if (!items) return;
|
|
161
|
+
for (const item of items) {
|
|
162
|
+
yield {
|
|
163
|
+
by: accountOrAgentIDfromSessionID(sessionID),
|
|
164
|
+
tx: item.tx,
|
|
165
|
+
at: new Date(item.madeAt),
|
|
166
|
+
value: item.value,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
118
170
|
|
|
119
|
-
|
|
171
|
+
lastItemBy(account: AccountID | AgentID):
|
|
172
|
+
| {
|
|
173
|
+
by: AccountID | AgentID;
|
|
174
|
+
tx: TransactionID;
|
|
175
|
+
at: Date;
|
|
176
|
+
value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
|
|
177
|
+
}
|
|
178
|
+
| undefined {
|
|
179
|
+
let latestItem:
|
|
180
|
+
| {
|
|
181
|
+
by: AccountID | AgentID;
|
|
182
|
+
tx: TransactionID;
|
|
183
|
+
at: Date;
|
|
184
|
+
value: Item extends CoValue
|
|
185
|
+
? CoID<Item>
|
|
186
|
+
: Exclude<Item, CoValue>;
|
|
187
|
+
}
|
|
188
|
+
| undefined;
|
|
189
|
+
|
|
190
|
+
for (const sessionID of Object.keys(this.items)) {
|
|
120
191
|
if (sessionID.startsWith(account)) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
192
|
+
const item = this.lastItemIn(sessionID as SessionID);
|
|
193
|
+
if (!item) continue;
|
|
194
|
+
if (!latestItem || item.at > latestItem.at) {
|
|
195
|
+
latestItem = {
|
|
196
|
+
by: item.by,
|
|
197
|
+
tx: item.tx,
|
|
198
|
+
at: item.at,
|
|
199
|
+
value: item.value,
|
|
200
|
+
};
|
|
126
201
|
}
|
|
127
202
|
}
|
|
128
203
|
}
|
|
129
204
|
|
|
130
|
-
return
|
|
205
|
+
return latestItem;
|
|
131
206
|
}
|
|
132
207
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
208
|
+
*itemsBy(account: AccountID | AgentID) {
|
|
209
|
+
// TODO: this can be made more lazy without a huge collect and sort
|
|
210
|
+
const items = [
|
|
211
|
+
...Object.keys(this.items).flatMap((sessionID) =>
|
|
212
|
+
sessionID.startsWith(account)
|
|
213
|
+
? [...this.itemsIn(sessionID as SessionID)].map((item) => ({
|
|
214
|
+
in: sessionID as SessionID,
|
|
215
|
+
...item,
|
|
216
|
+
}))
|
|
217
|
+
: []
|
|
218
|
+
),
|
|
219
|
+
];
|
|
220
|
+
|
|
221
|
+
items.sort((a, b) => a.at.getTime() - b.at.getTime());
|
|
222
|
+
|
|
223
|
+
for (const item of items) {
|
|
224
|
+
yield item;
|
|
225
|
+
}
|
|
137
226
|
}
|
|
138
227
|
|
|
139
228
|
toJSON(): {
|
|
140
|
-
[key: SessionID]:
|
|
229
|
+
[key: SessionID]: (Item extends CoValue
|
|
230
|
+
? CoID<Item>
|
|
231
|
+
: Exclude<Item, CoValue>)[];
|
|
141
232
|
} {
|
|
142
|
-
return Object.fromEntries(
|
|
143
|
-
[sessionID, items
|
|
144
|
-
|
|
233
|
+
return Object.fromEntries(
|
|
234
|
+
Object.entries(this.items).map(([sessionID, items]) => [
|
|
235
|
+
sessionID,
|
|
236
|
+
items.map((item) => item.value),
|
|
237
|
+
])
|
|
238
|
+
);
|
|
145
239
|
}
|
|
146
240
|
|
|
147
|
-
subscribe(listener: (
|
|
241
|
+
subscribe(listener: (coStream: this) => void): () => void {
|
|
148
242
|
return this.core.subscribe((content) => {
|
|
149
|
-
listener(content as
|
|
243
|
+
listener(content as this);
|
|
150
244
|
});
|
|
151
245
|
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export class CoStream<
|
|
249
|
+
Item extends JsonValue | CoValue,
|
|
250
|
+
Meta extends JsonObject | null = null
|
|
251
|
+
>
|
|
252
|
+
extends CoStreamView<Item, Meta>
|
|
253
|
+
implements CoValue
|
|
254
|
+
{
|
|
255
|
+
push(
|
|
256
|
+
item: Item extends CoValue ? Item | CoID<Item> : Item,
|
|
257
|
+
privacy: "private" | "trusting" = "private"
|
|
258
|
+
): this {
|
|
259
|
+
this.core.makeTransaction([isCoValue(item) ? item.id : item], privacy);
|
|
260
|
+
return new CoStream(this.core) as this;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
mutate(mutator: (mutable: MutableCoStream<Item, Meta>) => void): this {
|
|
264
|
+
const mutable = new MutableCoStream<Item, Meta>(this.core);
|
|
265
|
+
mutator(mutable);
|
|
266
|
+
return new CoStream(this.core) as this;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** @deprecated Use `mutate` instead. */
|
|
270
|
+
edit(mutator: (mutable: MutableCoStream<Item, Meta>) => void): this {
|
|
271
|
+
return this.mutate(mutator);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
152
274
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
275
|
+
export class MutableCoStream<
|
|
276
|
+
Item extends JsonValue | CoValue,
|
|
277
|
+
Meta extends JsonObject | null = null
|
|
278
|
+
>
|
|
279
|
+
extends CoStreamView<Item, Meta>
|
|
280
|
+
implements CoValue
|
|
281
|
+
{
|
|
282
|
+
push(
|
|
283
|
+
item: Item extends CoValue ? Item | CoID<Item> : Item,
|
|
284
|
+
privacy: "private" | "trusting" = "private"
|
|
285
|
+
) {
|
|
286
|
+
this.core.makeTransaction([isCoValue(item) ? item.id : item], privacy);
|
|
287
|
+
this.fillFromCoValue();
|
|
159
288
|
}
|
|
160
289
|
}
|
|
161
290
|
|
|
162
291
|
const binary_U_prefixLength = 8; // "binary_U".length;
|
|
163
292
|
|
|
164
|
-
export class
|
|
293
|
+
export class BinaryCoStreamView<
|
|
165
294
|
Meta extends BinaryCoStreamMeta = { type: "binary" }
|
|
166
295
|
>
|
|
167
|
-
extends
|
|
168
|
-
implements
|
|
296
|
+
extends CoStreamView<BinaryStreamItem, Meta>
|
|
297
|
+
implements CoValue
|
|
169
298
|
{
|
|
170
|
-
id!: CoID<
|
|
299
|
+
id!: CoID<this>;
|
|
171
300
|
|
|
172
|
-
getBinaryChunks(
|
|
173
|
-
|
|
301
|
+
getBinaryChunks(
|
|
302
|
+
allowUnfinished?: boolean
|
|
303
|
+
):
|
|
304
|
+
| (BinaryStreamInfo & { chunks: Uint8Array[]; finished: boolean })
|
|
174
305
|
| undefined {
|
|
175
306
|
// const before = performance.now();
|
|
176
307
|
const items = this.getSingleStream();
|
|
@@ -225,56 +356,89 @@ export class BinaryCoStream<
|
|
|
225
356
|
finished,
|
|
226
357
|
};
|
|
227
358
|
}
|
|
228
|
-
|
|
229
|
-
edit(
|
|
230
|
-
changer: (editable: WriteableBinaryCoStream<Meta>) => void
|
|
231
|
-
): BinaryCoStream<Meta> {
|
|
232
|
-
const editable = new WriteableBinaryCoStream<Meta>(this.core);
|
|
233
|
-
changer(editable);
|
|
234
|
-
return new BinaryCoStream(this.core);
|
|
235
|
-
}
|
|
236
359
|
}
|
|
237
360
|
|
|
238
|
-
export class
|
|
239
|
-
|
|
240
|
-
Meta extends JsonObject | null = null
|
|
361
|
+
export class BinaryCoStream<
|
|
362
|
+
Meta extends BinaryCoStreamMeta = { type: "binary" }
|
|
241
363
|
>
|
|
242
|
-
extends
|
|
243
|
-
implements
|
|
364
|
+
extends BinaryCoStreamView<Meta>
|
|
365
|
+
implements CoValue
|
|
244
366
|
{
|
|
245
367
|
/** @internal */
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
368
|
+
push(
|
|
369
|
+
item: BinaryStreamItem,
|
|
370
|
+
privacy: "private" | "trusting" = "private"
|
|
371
|
+
): this {
|
|
372
|
+
this.core.makeTransaction([item], privacy);
|
|
373
|
+
return new BinaryCoStream(this.core) as this;
|
|
250
374
|
}
|
|
251
375
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
376
|
+
startBinaryStream(
|
|
377
|
+
settings: BinaryStreamInfo,
|
|
378
|
+
privacy: "private" | "trusting" = "private"
|
|
379
|
+
): this {
|
|
380
|
+
return this.push(
|
|
381
|
+
{
|
|
382
|
+
type: "start",
|
|
383
|
+
...settings,
|
|
384
|
+
} satisfies BinaryStreamStart,
|
|
385
|
+
privacy
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
pushBinaryStreamChunk(
|
|
390
|
+
chunk: Uint8Array,
|
|
391
|
+
privacy: "private" | "trusting" = "private"
|
|
392
|
+
): this {
|
|
393
|
+
// const before = performance.now();
|
|
394
|
+
return this.push(
|
|
395
|
+
{
|
|
396
|
+
type: "chunk",
|
|
397
|
+
chunk: `binary_U${bytesToBase64url(chunk)}`,
|
|
398
|
+
} satisfies BinaryStreamChunk,
|
|
399
|
+
privacy
|
|
400
|
+
);
|
|
401
|
+
// const after = performance.now();
|
|
402
|
+
// console.log(
|
|
403
|
+
// "pushBinaryStreamChunk bandwidth in MB/s",
|
|
404
|
+
// (1000 * chunk.length) / (after - before) / (1024 * 1024)
|
|
405
|
+
// );
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
endBinaryStream(privacy: "private" | "trusting" = "private"): this {
|
|
409
|
+
return this.push(
|
|
410
|
+
{
|
|
411
|
+
type: "end",
|
|
412
|
+
} satisfies BinaryStreamEnd,
|
|
413
|
+
privacy
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
mutate(mutator: (mutable: MutableBinaryCoStream<Meta>) => void): this {
|
|
418
|
+
const mutable = new MutableBinaryCoStream<Meta>(this.core);
|
|
419
|
+
mutator(mutable);
|
|
420
|
+
return new BinaryCoStream(this.core) as this;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/** @deprecated Use `mutate` instead. */
|
|
424
|
+
edit(mutator: (mutable: MutableBinaryCoStream<Meta>) => void): this {
|
|
425
|
+
return this.mutate(mutator);
|
|
255
426
|
}
|
|
256
427
|
}
|
|
257
428
|
|
|
258
|
-
export class
|
|
429
|
+
export class MutableBinaryCoStream<
|
|
259
430
|
Meta extends BinaryCoStreamMeta = { type: "binary" }
|
|
260
431
|
>
|
|
261
|
-
extends
|
|
262
|
-
implements
|
|
432
|
+
extends BinaryCoStreamView<Meta>
|
|
433
|
+
implements CoValue
|
|
263
434
|
{
|
|
264
|
-
/** @internal */
|
|
265
|
-
edit(
|
|
266
|
-
_changer: (editable: WriteableBinaryCoStream<Meta>) => void
|
|
267
|
-
): BinaryCoStream<Meta> {
|
|
268
|
-
throw new Error("Already editing.");
|
|
269
|
-
}
|
|
270
|
-
|
|
271
435
|
/** @internal */
|
|
272
436
|
push(item: BinaryStreamItem, privacy: "private" | "trusting" = "private") {
|
|
273
|
-
|
|
437
|
+
MutableCoStream.prototype.push.call(this, item, privacy);
|
|
274
438
|
}
|
|
275
439
|
|
|
276
440
|
startBinaryStream(
|
|
277
|
-
settings:
|
|
441
|
+
settings: BinaryStreamInfo,
|
|
278
442
|
privacy: "private" | "trusting" = "private"
|
|
279
443
|
) {
|
|
280
444
|
this.push(
|
package/src/crypto.ts
CHANGED
|
@@ -6,33 +6,39 @@ import { randomBytes } from "@noble/ciphers/webcrypto/utils";
|
|
|
6
6
|
import { AgentID, RawCoID, TransactionID } from "./ids.js";
|
|
7
7
|
import { base64URLtoBytes, bytesToBase64url } from "./base64url.js";
|
|
8
8
|
|
|
9
|
-
import { createBLAKE3 } from
|
|
9
|
+
import { createBLAKE3 } from "hash-wasm";
|
|
10
10
|
import { Stringified, parseJSON, stableStringify } from "./jsonStringify.js";
|
|
11
11
|
|
|
12
12
|
let blake3Instance: Awaited<ReturnType<typeof createBLAKE3>>;
|
|
13
13
|
let blake3HashOnce: (data: Uint8Array) => Uint8Array;
|
|
14
|
-
let blake3HashOnceWithContext: (
|
|
15
|
-
|
|
14
|
+
let blake3HashOnceWithContext: (
|
|
15
|
+
data: Uint8Array,
|
|
16
|
+
{ context }: { context: Uint8Array }
|
|
17
|
+
) => Uint8Array;
|
|
18
|
+
let blake3incrementalUpdateSLOW_WITH_DEVTOOLS: (
|
|
19
|
+
state: Uint8Array,
|
|
20
|
+
data: Uint8Array
|
|
21
|
+
) => Uint8Array;
|
|
16
22
|
let blake3digestForState: (state: Uint8Array) => Uint8Array;
|
|
17
23
|
|
|
18
24
|
export const cryptoReady = new Promise<void>((resolve) => {
|
|
19
|
-
createBLAKE3().then(bl3 => {
|
|
25
|
+
createBLAKE3().then((bl3) => {
|
|
20
26
|
blake3Instance = bl3;
|
|
21
27
|
blake3HashOnce = (data) => {
|
|
22
|
-
return bl3.init().update(data).digest(
|
|
23
|
-
}
|
|
24
|
-
blake3HashOnceWithContext = (data, {context}) => {
|
|
25
|
-
return bl3.init().update(context).update(data).digest(
|
|
26
|
-
}
|
|
28
|
+
return bl3.init().update(data).digest("binary");
|
|
29
|
+
};
|
|
30
|
+
blake3HashOnceWithContext = (data, { context }) => {
|
|
31
|
+
return bl3.init().update(context).update(data).digest("binary");
|
|
32
|
+
};
|
|
27
33
|
blake3incrementalUpdateSLOW_WITH_DEVTOOLS = (state, data) => {
|
|
28
34
|
bl3.load(state).update(data);
|
|
29
35
|
return bl3.save();
|
|
30
|
-
}
|
|
36
|
+
};
|
|
31
37
|
blake3digestForState = (state) => {
|
|
32
|
-
return bl3.load(state).digest(
|
|
33
|
-
}
|
|
38
|
+
return bl3.load(state).digest("binary");
|
|
39
|
+
};
|
|
34
40
|
resolve();
|
|
35
|
-
})
|
|
41
|
+
});
|
|
36
42
|
});
|
|
37
43
|
|
|
38
44
|
export type SignerSecret = `signerSecret_z${string}`;
|
|
@@ -149,12 +155,17 @@ export function getAgentSealerSecret(agentSecret: AgentSecret): SealerSecret {
|
|
|
149
155
|
return agentSecret.split("/")[0] as SealerSecret;
|
|
150
156
|
}
|
|
151
157
|
|
|
152
|
-
export function seal<T extends JsonValue>(
|
|
153
|
-
message
|
|
154
|
-
from
|
|
155
|
-
to
|
|
156
|
-
nOnceMaterial
|
|
157
|
-
|
|
158
|
+
export function seal<T extends JsonValue>({
|
|
159
|
+
message,
|
|
160
|
+
from,
|
|
161
|
+
to,
|
|
162
|
+
nOnceMaterial,
|
|
163
|
+
}: {
|
|
164
|
+
message: T;
|
|
165
|
+
from: SealerSecret;
|
|
166
|
+
to: SealerID;
|
|
167
|
+
nOnceMaterial: { in: RawCoID; tx: TransactionID };
|
|
168
|
+
}): Sealed<T> {
|
|
158
169
|
const nOnce = blake3HashOnce(
|
|
159
170
|
textEncoder.encode(stableStringify(nOnceMaterial))
|
|
160
171
|
).slice(0, 24);
|
|
@@ -220,9 +231,12 @@ export class StreamingHash {
|
|
|
220
231
|
}
|
|
221
232
|
|
|
222
233
|
update(value: JsonValue) {
|
|
223
|
-
const encoded = textEncoder.encode(stableStringify(value))
|
|
234
|
+
const encoded = textEncoder.encode(stableStringify(value));
|
|
224
235
|
// const before = performance.now();
|
|
225
|
-
this.state = blake3incrementalUpdateSLOW_WITH_DEVTOOLS(
|
|
236
|
+
this.state = blake3incrementalUpdateSLOW_WITH_DEVTOOLS(
|
|
237
|
+
this.state,
|
|
238
|
+
encoded
|
|
239
|
+
);
|
|
226
240
|
// const after = performance.now();
|
|
227
241
|
// console.log(`Hashing throughput in MB/s`, 1000 * (encoded.length / (after - before)) / (1024 * 1024));
|
|
228
242
|
}
|
|
@@ -333,8 +347,7 @@ function decryptRaw<T extends JsonValue, N extends JsonValue>(
|
|
|
333
347
|
);
|
|
334
348
|
const plaintext = xsalsa20(keySecretBytes, nOnce, ciphertext);
|
|
335
349
|
|
|
336
|
-
|
|
337
|
-
|
|
350
|
+
return textDecoder.decode(plaintext) as Stringified<T>;
|
|
338
351
|
}
|
|
339
352
|
|
|
340
353
|
function decrypt<T extends JsonValue, N extends JsonValue>(
|
|
@@ -345,7 +358,7 @@ function decrypt<T extends JsonValue, N extends JsonValue>(
|
|
|
345
358
|
try {
|
|
346
359
|
return parseJSON(decryptRaw(encrypted, keySecret, nOnceMaterial));
|
|
347
360
|
} catch (e) {
|
|
348
|
-
console.error("Decryption error", e)
|
|
361
|
+
console.error("Decryption error", e);
|
|
349
362
|
return undefined;
|
|
350
363
|
}
|
|
351
364
|
}
|