cojson 0.7.35-unique.2 → 0.7.35
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/.turbo/turbo-test.log +321 -253
- package/CHANGELOG.md +3 -2
- package/dist/PeerState.js +58 -0
- package/dist/PeerState.js.map +1 -0
- package/dist/PriorityBasedMessageQueue.js +51 -0
- package/dist/PriorityBasedMessageQueue.js.map +1 -0
- package/dist/base64url.js.map +1 -1
- package/dist/coValue.js.map +1 -1
- package/dist/coValueCore.js +3 -0
- package/dist/coValueCore.js.map +1 -1
- package/dist/coValues/account.js +2 -2
- package/dist/coValues/account.js.map +1 -1
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.js +14 -15
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coValues/group.js +8 -8
- package/dist/coValues/group.js.map +1 -1
- package/dist/coreToCoValue.js.map +1 -1
- package/dist/crypto/PureJSCrypto.js.map +1 -1
- package/dist/crypto/WasmCrypto.js.map +1 -1
- package/dist/crypto/crypto.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/jsonStringify.js.map +1 -1
- package/dist/localNode.js +2 -2
- package/dist/localNode.js.map +1 -1
- package/dist/permissions.js.map +1 -1
- package/dist/priority.js +31 -0
- package/dist/priority.js.map +1 -0
- package/dist/storage/FileSystem.js.map +1 -1
- package/dist/storage/chunksAndKnownStates.js +2 -0
- package/dist/storage/chunksAndKnownStates.js.map +1 -1
- package/dist/storage/index.js.map +1 -1
- package/dist/streamUtils.js.map +1 -1
- package/dist/sync.js +7 -18
- package/dist/sync.js.map +1 -1
- package/dist/tests/PeerState.test.js +80 -0
- package/dist/tests/PeerState.test.js.map +1 -0
- package/dist/tests/PriorityBasedMessageQueue.test.js +97 -0
- package/dist/tests/PriorityBasedMessageQueue.test.js.map +1 -0
- package/dist/tests/coMap.test.js.map +1 -1
- package/dist/tests/coStream.test.js +34 -1
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/permissions.test.js.map +1 -1
- package/dist/tests/priority.test.js +61 -0
- package/dist/tests/priority.test.js.map +1 -0
- package/dist/tests/sync.test.js +323 -12
- package/dist/tests/sync.test.js.map +1 -1
- package/dist/tests/testUtils.js.map +1 -1
- package/dist/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
- package/dist/typeUtils/expectGroup.js.map +1 -1
- package/dist/typeUtils/isAccountID.js.map +1 -1
- package/package.json +3 -3
- package/src/PeerState.ts +74 -0
- package/src/PriorityBasedMessageQueue.ts +77 -0
- package/src/coValueCore.ts +10 -7
- package/src/coValues/account.ts +5 -5
- package/src/coValues/coList.ts +4 -4
- package/src/coValues/coMap.ts +3 -3
- package/src/coValues/coStream.ts +29 -26
- package/src/coValues/group.ts +11 -15
- package/src/ids.ts +2 -2
- package/src/index.ts +5 -5
- package/src/localNode.ts +11 -12
- package/src/permissions.ts +5 -5
- package/src/priority.ts +39 -0
- package/src/storage/chunksAndKnownStates.ts +2 -0
- package/src/sync.ts +19 -34
- package/src/tests/PeerState.test.ts +92 -0
- package/src/tests/PriorityBasedMessageQueue.test.ts +111 -0
- package/src/tests/coStream.test.ts +58 -1
- package/src/tests/priority.test.ts +75 -0
- package/src/tests/sync.test.ts +487 -25
- package/src/typeUtils/accountOrAgentIDfromSessionID.ts +3 -3
- package/src/typeUtils/isAccountID.ts +2 -2
package/src/coValues/coStream.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfrom
|
|
|
7
7
|
import { RawGroup } from "./group.js";
|
|
8
8
|
import { AgentID, SessionID, TransactionID } from "../ids.js";
|
|
9
9
|
import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
|
|
10
|
-
import {
|
|
10
|
+
import { AccountID } from "./account.js";
|
|
11
11
|
|
|
12
12
|
export type BinaryStreamInfo = {
|
|
13
13
|
mimeType: string;
|
|
@@ -96,22 +96,27 @@ export class RawCoStreamView<
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
getSingleStream(): Item[] | undefined {
|
|
99
|
-
|
|
99
|
+
const streams = Object.values(this.items);
|
|
100
|
+
const firstStream = streams[0];
|
|
101
|
+
|
|
102
|
+
if (!firstStream) {
|
|
100
103
|
return undefined;
|
|
101
|
-
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (streams.length > 1) {
|
|
102
107
|
throw new Error(
|
|
103
108
|
"CoStream.getSingleStream() can only be called when there is exactly one stream",
|
|
104
109
|
);
|
|
105
110
|
}
|
|
106
111
|
|
|
107
|
-
return
|
|
112
|
+
return firstStream.map((item) => item.value);
|
|
108
113
|
}
|
|
109
114
|
|
|
110
115
|
sessions(): SessionID[] {
|
|
111
116
|
return Object.keys(this.items) as SessionID[];
|
|
112
117
|
}
|
|
113
118
|
|
|
114
|
-
accounts(): Set<
|
|
119
|
+
accounts(): Set<AccountID> {
|
|
115
120
|
return new Set(
|
|
116
121
|
this.sessions()
|
|
117
122
|
.map(accountOrAgentIDfromSessionID)
|
|
@@ -124,7 +129,7 @@ export class RawCoStreamView<
|
|
|
124
129
|
n: number,
|
|
125
130
|
):
|
|
126
131
|
| {
|
|
127
|
-
by:
|
|
132
|
+
by: AccountID | AgentID;
|
|
128
133
|
tx: TransactionID;
|
|
129
134
|
at: Date;
|
|
130
135
|
value: Item;
|
|
@@ -146,7 +151,7 @@ export class RawCoStreamView<
|
|
|
146
151
|
|
|
147
152
|
lastItemIn(sessionID: SessionID):
|
|
148
153
|
| {
|
|
149
|
-
by:
|
|
154
|
+
by: AccountID | AgentID;
|
|
150
155
|
tx: TransactionID;
|
|
151
156
|
at: Date;
|
|
152
157
|
value: Item;
|
|
@@ -170,9 +175,9 @@ export class RawCoStreamView<
|
|
|
170
175
|
}
|
|
171
176
|
}
|
|
172
177
|
|
|
173
|
-
lastItemBy(account:
|
|
178
|
+
lastItemBy(account: AccountID | AgentID):
|
|
174
179
|
| {
|
|
175
|
-
by:
|
|
180
|
+
by: AccountID | AgentID;
|
|
176
181
|
tx: TransactionID;
|
|
177
182
|
at: Date;
|
|
178
183
|
value: Item;
|
|
@@ -180,7 +185,7 @@ export class RawCoStreamView<
|
|
|
180
185
|
| undefined {
|
|
181
186
|
let latestItem:
|
|
182
187
|
| {
|
|
183
|
-
by:
|
|
188
|
+
by: AccountID | AgentID;
|
|
184
189
|
tx: TransactionID;
|
|
185
190
|
at: Date;
|
|
186
191
|
value: Item;
|
|
@@ -205,7 +210,7 @@ export class RawCoStreamView<
|
|
|
205
210
|
return latestItem;
|
|
206
211
|
}
|
|
207
212
|
|
|
208
|
-
*itemsBy(account:
|
|
213
|
+
*itemsBy(account: AccountID | AgentID) {
|
|
209
214
|
// TODO: this can be made more lazy without a huge collect and sort
|
|
210
215
|
const items = [
|
|
211
216
|
...Object.keys(this.items).flatMap((sessionID) =>
|
|
@@ -264,14 +269,26 @@ export class RawBinaryCoStreamView<
|
|
|
264
269
|
extends RawCoStreamView<BinaryStreamItem, Meta>
|
|
265
270
|
implements RawCoValue
|
|
266
271
|
{
|
|
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];
|
|
280
|
+
|
|
281
|
+
return lastItem?.type === "end";
|
|
282
|
+
}
|
|
283
|
+
|
|
267
284
|
getBinaryChunks(
|
|
268
285
|
allowUnfinished?: boolean,
|
|
269
286
|
):
|
|
270
287
|
| (BinaryStreamInfo & { chunks: Uint8Array[]; finished: boolean })
|
|
271
288
|
| undefined {
|
|
272
|
-
// const before = performance.now();
|
|
273
289
|
const items = this.getSingleStream();
|
|
274
290
|
|
|
291
|
+
// No active streams
|
|
275
292
|
if (!items) return;
|
|
276
293
|
|
|
277
294
|
const start = items[0];
|
|
@@ -288,9 +305,6 @@ export class RawBinaryCoStreamView<
|
|
|
288
305
|
const chunks: Uint8Array[] = [];
|
|
289
306
|
|
|
290
307
|
let finished = false;
|
|
291
|
-
// let totalLength = 0;
|
|
292
|
-
|
|
293
|
-
let lastProgressUpdate = Date.now();
|
|
294
308
|
|
|
295
309
|
for (const item of items.slice(1)) {
|
|
296
310
|
if (item.type === "end") {
|
|
@@ -306,20 +320,9 @@ export class RawBinaryCoStreamView<
|
|
|
306
320
|
const chunk = base64URLtoBytes(
|
|
307
321
|
item.chunk.slice(binary_U_prefixLength),
|
|
308
322
|
);
|
|
309
|
-
// totalLength += chunk.length;
|
|
310
323
|
chunks.push(chunk);
|
|
311
|
-
|
|
312
|
-
if (Date.now() - lastProgressUpdate > 100) {
|
|
313
|
-
lastProgressUpdate = Date.now();
|
|
314
|
-
}
|
|
315
324
|
}
|
|
316
325
|
|
|
317
|
-
// const after = performance.now();
|
|
318
|
-
// console.log(
|
|
319
|
-
// "getBinaryChunks bandwidth in MB/s",
|
|
320
|
-
// (1000 * totalLength) / (after - before) / (1024 * 1024)
|
|
321
|
-
// );
|
|
322
|
-
|
|
323
326
|
return {
|
|
324
327
|
mimeType: start.mimeType,
|
|
325
328
|
fileName: start.fileName,
|
package/src/coValues/group.ts
CHANGED
|
@@ -5,10 +5,9 @@ import { JsonObject } from "../jsonValue.js";
|
|
|
5
5
|
import { RawBinaryCoStream, RawCoStream } from "./coStream.js";
|
|
6
6
|
import { Encrypted, KeyID, KeySecret, Sealed } from "../crypto/crypto.js";
|
|
7
7
|
import { AgentID, isAgentID } from "../ids.js";
|
|
8
|
-
import { RawAccount,
|
|
8
|
+
import { RawAccount, AccountID, ControlledAccountOrAgent } from "./account.js";
|
|
9
9
|
import { Role } from "../permissions.js";
|
|
10
10
|
import { base58 } from "@scure/base";
|
|
11
|
-
import { CoValueUniqueness } from "../coValueCore.js";
|
|
12
11
|
|
|
13
12
|
export const EVERYONE = "everyone" as const;
|
|
14
13
|
export type Everyone = "everyone";
|
|
@@ -16,10 +15,10 @@ export type Everyone = "everyone";
|
|
|
16
15
|
export type GroupShape = {
|
|
17
16
|
profile: CoID<RawCoMap> | null;
|
|
18
17
|
root: CoID<RawCoMap> | null;
|
|
19
|
-
[key:
|
|
18
|
+
[key: AccountID | AgentID]: Role;
|
|
20
19
|
[EVERYONE]?: Role;
|
|
21
20
|
readKey?: KeyID;
|
|
22
|
-
[revelationFor: `${KeyID}_for_${
|
|
21
|
+
[revelationFor: `${KeyID}_for_${AccountID | AgentID}`]: Sealed<KeySecret>;
|
|
23
22
|
[revelationFor: `${KeyID}_for_${Everyone}`]: KeySecret;
|
|
24
23
|
[oldKeyForNewKey: `${KeyID}_for_${KeyID}`]: Encrypted<
|
|
25
24
|
KeySecret,
|
|
@@ -56,12 +55,12 @@ export class RawGroup<
|
|
|
56
55
|
*
|
|
57
56
|
* @category 1. Role reading
|
|
58
57
|
*/
|
|
59
|
-
roleOf(accountID:
|
|
58
|
+
roleOf(accountID: AccountID): Role | undefined {
|
|
60
59
|
return this.roleOfInternal(accountID);
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
/** @internal */
|
|
64
|
-
roleOfInternal(accountID:
|
|
63
|
+
roleOfInternal(accountID: AccountID | AgentID): Role | undefined {
|
|
65
64
|
return this.get(accountID);
|
|
66
65
|
}
|
|
67
66
|
|
|
@@ -157,7 +156,7 @@ export class RawGroup<
|
|
|
157
156
|
} else {
|
|
158
157
|
return false;
|
|
159
158
|
}
|
|
160
|
-
}) as (
|
|
159
|
+
}) as (AccountID | AgentID)[];
|
|
161
160
|
|
|
162
161
|
const maybeCurrentReadKey = this.core.getCurrentReadKey();
|
|
163
162
|
|
|
@@ -256,7 +255,6 @@ export class RawGroup<
|
|
|
256
255
|
init?: M["_shape"],
|
|
257
256
|
meta?: M["headerMeta"],
|
|
258
257
|
initPrivacy: "trusting" | "private" = "private",
|
|
259
|
-
uniqueness: CoValueUniqueness = this.core.crypto.createdNowUnique()
|
|
260
258
|
): M {
|
|
261
259
|
const map = this.core.node
|
|
262
260
|
.createCoValue({
|
|
@@ -266,7 +264,7 @@ export class RawGroup<
|
|
|
266
264
|
group: this.id,
|
|
267
265
|
},
|
|
268
266
|
meta: meta || null,
|
|
269
|
-
...
|
|
267
|
+
...this.core.crypto.createdNowUnique(),
|
|
270
268
|
})
|
|
271
269
|
.getCurrentContent() as M;
|
|
272
270
|
|
|
@@ -289,7 +287,6 @@ export class RawGroup<
|
|
|
289
287
|
init?: L["_item"][],
|
|
290
288
|
meta?: L["headerMeta"],
|
|
291
289
|
initPrivacy: "trusting" | "private" = "private",
|
|
292
|
-
uniqueness: CoValueUniqueness = this.core.crypto.createdNowUnique()
|
|
293
290
|
): L {
|
|
294
291
|
const list = this.core.node
|
|
295
292
|
.createCoValue({
|
|
@@ -299,7 +296,7 @@ export class RawGroup<
|
|
|
299
296
|
group: this.id,
|
|
300
297
|
},
|
|
301
298
|
meta: meta || null,
|
|
302
|
-
...
|
|
299
|
+
...this.core.crypto.createdNowUnique(),
|
|
303
300
|
})
|
|
304
301
|
.getCurrentContent() as L;
|
|
305
302
|
|
|
@@ -313,7 +310,7 @@ export class RawGroup<
|
|
|
313
310
|
}
|
|
314
311
|
|
|
315
312
|
/** @category 3. Value creation */
|
|
316
|
-
createStream<C extends RawCoStream>(meta?: C["headerMeta"]
|
|
313
|
+
createStream<C extends RawCoStream>(meta?: C["headerMeta"]): C {
|
|
317
314
|
return this.core.node
|
|
318
315
|
.createCoValue({
|
|
319
316
|
type: "costream",
|
|
@@ -322,7 +319,7 @@ export class RawGroup<
|
|
|
322
319
|
group: this.id,
|
|
323
320
|
},
|
|
324
321
|
meta: meta || null,
|
|
325
|
-
...
|
|
322
|
+
...this.core.crypto.createdNowUnique(),
|
|
326
323
|
})
|
|
327
324
|
.getCurrentContent() as C;
|
|
328
325
|
}
|
|
@@ -330,7 +327,6 @@ export class RawGroup<
|
|
|
330
327
|
/** @category 3. Value creation */
|
|
331
328
|
createBinaryStream<C extends RawBinaryCoStream>(
|
|
332
329
|
meta: C["headerMeta"] = { type: "binary" },
|
|
333
|
-
uniqueness: CoValueUniqueness = this.core.crypto.createdNowUnique()
|
|
334
330
|
): C {
|
|
335
331
|
return this.core.node
|
|
336
332
|
.createCoValue({
|
|
@@ -340,7 +336,7 @@ export class RawGroup<
|
|
|
340
336
|
group: this.id,
|
|
341
337
|
},
|
|
342
338
|
meta: meta,
|
|
343
|
-
...
|
|
339
|
+
...this.core.crypto.createdNowUnique(),
|
|
344
340
|
})
|
|
345
341
|
.getCurrentContent() as C;
|
|
346
342
|
}
|
package/src/ids.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AccountID } from "./coValues/account.js";
|
|
2
2
|
import { base58 } from "@scure/base";
|
|
3
3
|
import { shortHashLength } from "./crypto/crypto.js";
|
|
4
4
|
|
|
@@ -28,4 +28,4 @@ export function isAgentID(id: string): id is AgentID {
|
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
export type SessionID = `${
|
|
31
|
+
export type SessionID = `${AccountID | AgentID}_session_z${string}`;
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CoValueCore,
|
|
3
|
-
type CoValueUniqueness,
|
|
4
3
|
newRandomSessionID,
|
|
5
4
|
MAX_RECOMMENDED_TX_SIZE,
|
|
6
5
|
idforHeader,
|
|
7
6
|
} from "./coValueCore.js";
|
|
8
7
|
import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromSessionID.js";
|
|
9
8
|
import { LocalNode } from "./localNode.js";
|
|
10
|
-
import type
|
|
9
|
+
import { type RawCoValue } from "./coValue.js";
|
|
11
10
|
import { RawCoMap } from "./coValues/coMap.js";
|
|
12
11
|
import { RawCoList } from "./coValues/coList.js";
|
|
13
12
|
import { RawCoStream, RawBinaryCoStream } from "./coValues/coStream.js";
|
|
@@ -51,7 +50,7 @@ import type {
|
|
|
51
50
|
import { DisconnectedError, PingTimeoutError } from "./sync.js";
|
|
52
51
|
import type { AgentSecret } from "./crypto/crypto.js";
|
|
53
52
|
import type {
|
|
54
|
-
|
|
53
|
+
AccountID,
|
|
55
54
|
AccountMeta,
|
|
56
55
|
RawAccountMigration,
|
|
57
56
|
} from "./coValues/account.js";
|
|
@@ -62,6 +61,7 @@ type Value = JsonValue | AnyRawCoValue;
|
|
|
62
61
|
|
|
63
62
|
import { LSMStorage, BlockFilename, WalFilename } from "./storage/index.js";
|
|
64
63
|
import { FileSystem } from "./storage/FileSystem.js";
|
|
64
|
+
import { getPriorityFromHeader } from "./priority.js";
|
|
65
65
|
|
|
66
66
|
/** @hidden */
|
|
67
67
|
export const cojsonInternals = {
|
|
@@ -81,6 +81,7 @@ export const cojsonInternals = {
|
|
|
81
81
|
idforHeader,
|
|
82
82
|
StreamingHash,
|
|
83
83
|
Channel,
|
|
84
|
+
getPriorityFromHeader,
|
|
84
85
|
};
|
|
85
86
|
|
|
86
87
|
export {
|
|
@@ -97,7 +98,7 @@ export {
|
|
|
97
98
|
CoID,
|
|
98
99
|
AnyRawCoValue,
|
|
99
100
|
RawAccount,
|
|
100
|
-
|
|
101
|
+
AccountID,
|
|
101
102
|
AccountMeta,
|
|
102
103
|
RawAccountMigration,
|
|
103
104
|
RawProfile as Profile,
|
|
@@ -131,7 +132,6 @@ export type {
|
|
|
131
132
|
OutgoingSyncQueue,
|
|
132
133
|
DisconnectedError,
|
|
133
134
|
PingTimeoutError,
|
|
134
|
-
CoValueUniqueness
|
|
135
135
|
};
|
|
136
136
|
|
|
137
137
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
package/src/localNode.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { AgentSecret, CryptoProvider } from "./crypto/crypto.js";
|
|
|
2
2
|
import {
|
|
3
3
|
CoValueCore,
|
|
4
4
|
CoValueHeader,
|
|
5
|
-
CoValueUniqueness,
|
|
6
5
|
newRandomSessionID,
|
|
7
6
|
} from "./coValueCore.js";
|
|
8
7
|
import {
|
|
@@ -20,7 +19,7 @@ import {
|
|
|
20
19
|
ControlledAccountOrAgent,
|
|
21
20
|
RawControlledAccount,
|
|
22
21
|
ControlledAgent,
|
|
23
|
-
|
|
22
|
+
AccountID,
|
|
24
23
|
RawProfile,
|
|
25
24
|
RawAccountMigration,
|
|
26
25
|
InvalidAccountAgentIDError,
|
|
@@ -82,7 +81,7 @@ export class LocalNode {
|
|
|
82
81
|
initialAgentSecret?: AgentSecret;
|
|
83
82
|
}): Promise<{
|
|
84
83
|
node: LocalNode;
|
|
85
|
-
accountID:
|
|
84
|
+
accountID: AccountID;
|
|
86
85
|
accountSecret: AgentSecret;
|
|
87
86
|
sessionID: SessionID;
|
|
88
87
|
}> {
|
|
@@ -174,7 +173,7 @@ export class LocalNode {
|
|
|
174
173
|
crypto,
|
|
175
174
|
migration,
|
|
176
175
|
}: {
|
|
177
|
-
accountID:
|
|
176
|
+
accountID: AccountID;
|
|
178
177
|
accountSecret: AgentSecret;
|
|
179
178
|
sessionID: SessionID | undefined;
|
|
180
179
|
peersToLoadFrom: Peer[];
|
|
@@ -471,7 +470,7 @@ export class LocalNode {
|
|
|
471
470
|
}
|
|
472
471
|
|
|
473
472
|
/** @internal */
|
|
474
|
-
expectProfileLoaded(id:
|
|
473
|
+
expectProfileLoaded(id: AccountID, expectation?: string): RawProfile {
|
|
475
474
|
const account = this.expectCoValueLoaded(id, expectation);
|
|
476
475
|
const profileID = expectGroup(account.getCurrentContent()).get(
|
|
477
476
|
"profile",
|
|
@@ -534,7 +533,7 @@ export class LocalNode {
|
|
|
534
533
|
|
|
535
534
|
/** @internal */
|
|
536
535
|
resolveAccountAgent(
|
|
537
|
-
id:
|
|
536
|
+
id: AccountID | AgentID,
|
|
538
537
|
expectation?: string,
|
|
539
538
|
): Result<AgentID, ResolveAccountAgentError> {
|
|
540
539
|
if (isAgentID(id)) {
|
|
@@ -561,7 +560,7 @@ export class LocalNode {
|
|
|
561
560
|
}
|
|
562
561
|
|
|
563
562
|
resolveAccountAgentAsync(
|
|
564
|
-
id:
|
|
563
|
+
id: AccountID | AgentID,
|
|
565
564
|
expectation?: string,
|
|
566
565
|
): ResultAsync<AgentID, ResolveAccountAgentError> {
|
|
567
566
|
if (isAgentID(id)) {
|
|
@@ -607,12 +606,12 @@ export class LocalNode {
|
|
|
607
606
|
/**
|
|
608
607
|
* @deprecated use Account.createGroup() instead
|
|
609
608
|
*/
|
|
610
|
-
createGroup(
|
|
609
|
+
createGroup(): RawGroup {
|
|
611
610
|
const groupCoValue = this.createCoValue({
|
|
612
611
|
type: "comap",
|
|
613
612
|
ruleset: { type: "group", initialAdmin: this.account.id },
|
|
614
613
|
meta: null,
|
|
615
|
-
...
|
|
614
|
+
...this.crypto.createdNowUnique(),
|
|
616
615
|
});
|
|
617
616
|
|
|
618
617
|
const group = expectGroup(groupCoValue.getCurrentContent());
|
|
@@ -732,19 +731,19 @@ export type LoadCoValueCoreError = {
|
|
|
732
731
|
type: "ErrorLoadingCoValueCore";
|
|
733
732
|
error: unknown;
|
|
734
733
|
expectation?: string;
|
|
735
|
-
id:
|
|
734
|
+
id: AccountID;
|
|
736
735
|
};
|
|
737
736
|
|
|
738
737
|
export type AccountUnavailableFromAllPeersError = {
|
|
739
738
|
type: "AccountUnavailableFromAllPeers";
|
|
740
739
|
expectation?: string;
|
|
741
|
-
id:
|
|
740
|
+
id: AccountID;
|
|
742
741
|
};
|
|
743
742
|
|
|
744
743
|
export type UnexpectedlyNotAccountError = {
|
|
745
744
|
type: "UnexpectedlyNotAccount";
|
|
746
745
|
expectation?: string;
|
|
747
|
-
id:
|
|
746
|
+
id: AccountID;
|
|
748
747
|
};
|
|
749
748
|
|
|
750
749
|
export type ResolveAccountAgentError =
|
package/src/permissions.ts
CHANGED
|
@@ -5,13 +5,13 @@ import { KeyID } from "./crypto/crypto.js";
|
|
|
5
5
|
import { CoValueCore, Transaction } from "./coValueCore.js";
|
|
6
6
|
import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromSessionID.js";
|
|
7
7
|
import { AgentID, RawCoID, SessionID, TransactionID } from "./ids.js";
|
|
8
|
-
import { RawAccount,
|
|
8
|
+
import { RawAccount, AccountID, RawProfile } from "./coValues/account.js";
|
|
9
9
|
import { parseJSON } from "./jsonStringify.js";
|
|
10
10
|
import { EVERYONE, Everyone } from "./coValues/group.js";
|
|
11
11
|
import { expectGroup } from "./typeUtils/expectGroup.js";
|
|
12
12
|
|
|
13
13
|
export type PermissionsDef =
|
|
14
|
-
| { type: "group"; initialAdmin:
|
|
14
|
+
| { type: "group"; initialAdmin: AccountID | AgentID }
|
|
15
15
|
| { type: "ownedByGroup"; group: RawCoID }
|
|
16
16
|
| { type: "unsafeAllowAll" };
|
|
17
17
|
|
|
@@ -53,7 +53,7 @@ export function determineValidTransactions(
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
const memberState: {
|
|
56
|
-
[agent:
|
|
56
|
+
[agent: AccountID | AgentID]: Role;
|
|
57
57
|
[EVERYONE]?: Role;
|
|
58
58
|
} = {};
|
|
59
59
|
|
|
@@ -99,7 +99,7 @@ export function determineValidTransactions(
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
const change = changes[0] as
|
|
102
|
-
| MapOpPayload<
|
|
102
|
+
| MapOpPayload<AccountID | AgentID | Everyone, Role>
|
|
103
103
|
| MapOpPayload<"readKey", JsonValue>
|
|
104
104
|
| MapOpPayload<"profile", CoID<RawProfile>>;
|
|
105
105
|
if (changes.length !== 1) {
|
|
@@ -303,7 +303,7 @@ export function isKeyForKeyField(co: string): co is `${KeyID}_for_${KeyID}` {
|
|
|
303
303
|
|
|
304
304
|
export function isKeyForAccountField(
|
|
305
305
|
co: string,
|
|
306
|
-
): co is `${KeyID}_for_${
|
|
306
|
+
): co is `${KeyID}_for_${AccountID | AgentID}` {
|
|
307
307
|
return (
|
|
308
308
|
(co.startsWith("key_") &&
|
|
309
309
|
(co.includes("_for_sealer") || co.includes("_for_co"))) ||
|
package/src/priority.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type CoValueHeader } from "./coValueCore.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The priority of a `CoValue` determines how much priority is given
|
|
5
|
+
* to its content messages.
|
|
6
|
+
*
|
|
7
|
+
* The priority value is handled as weight in the weighed round robin algorithm
|
|
8
|
+
* used to determine the order in which messages are sent.
|
|
9
|
+
*
|
|
10
|
+
* Follows the HTTP urgency range and order:
|
|
11
|
+
* - https://www.rfc-editor.org/rfc/rfc9218.html#name-urgency
|
|
12
|
+
*/
|
|
13
|
+
export const CO_VALUE_PRIORITY = {
|
|
14
|
+
HIGH: 0,
|
|
15
|
+
MEDIUM: 3,
|
|
16
|
+
LOW: 6,
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
export type CoValuePriority = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
|
20
|
+
|
|
21
|
+
export function getPriorityFromHeader(header: CoValueHeader | undefined | boolean): CoValuePriority {
|
|
22
|
+
if (typeof header === "boolean" || !header) {
|
|
23
|
+
return CO_VALUE_PRIORITY.MEDIUM;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (header.meta?.type === "account") {
|
|
27
|
+
return CO_VALUE_PRIORITY.HIGH;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (header.ruleset.type === "group") {
|
|
31
|
+
return CO_VALUE_PRIORITY.HIGH;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (header.type === "costream" && header.meta?.type === "binary") {
|
|
35
|
+
return CO_VALUE_PRIORITY.LOW;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return CO_VALUE_PRIORITY.MEDIUM;
|
|
39
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RawCoID, SessionID } from "../ids.js";
|
|
2
2
|
import { MAX_RECOMMENDED_TX_SIZE } from "../index.js";
|
|
3
|
+
import { getPriorityFromHeader } from "../priority.js";
|
|
3
4
|
import { CoValueKnownState, NewContentMessage } from "../sync.js";
|
|
4
5
|
import { CoValueChunk } from "./index.js";
|
|
5
6
|
|
|
@@ -15,6 +16,7 @@ export function contentSinceChunk(
|
|
|
15
16
|
action: "content",
|
|
16
17
|
header: known?.header ? undefined : chunk.header,
|
|
17
18
|
new: {},
|
|
19
|
+
priority: getPriorityFromHeader(chunk.header),
|
|
18
20
|
});
|
|
19
21
|
|
|
20
22
|
for (const [sessionID, sessionsEntry] of Object.entries(
|
package/src/sync.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { CoValueHeader, Transaction } from "./coValueCore.js";
|
|
|
3
3
|
import { CoValueCore } from "./coValueCore.js";
|
|
4
4
|
import { LocalNode, newLoadingState } from "./localNode.js";
|
|
5
5
|
import { RawCoID, SessionID } from "./ids.js";
|
|
6
|
+
import { PeerState } from "./PeerState.js";
|
|
7
|
+
import { CoValuePriority } from "./priority.js";
|
|
6
8
|
|
|
7
9
|
export type CoValueKnownState = {
|
|
8
10
|
id: RawCoID;
|
|
@@ -38,6 +40,7 @@ export type NewContentMessage = {
|
|
|
38
40
|
action: "content";
|
|
39
41
|
id: RawCoID;
|
|
40
42
|
header?: CoValueHeader;
|
|
43
|
+
priority: CoValuePriority;
|
|
41
44
|
new: {
|
|
42
45
|
[sessionID: SessionID]: SessionNewContent;
|
|
43
46
|
};
|
|
@@ -76,17 +79,6 @@ export interface Peer {
|
|
|
76
79
|
crashOnClose: boolean;
|
|
77
80
|
}
|
|
78
81
|
|
|
79
|
-
export interface PeerState {
|
|
80
|
-
id: PeerID;
|
|
81
|
-
optimisticKnownStates: { [id: RawCoID]: CoValueKnownState };
|
|
82
|
-
toldKnownState: Set<RawCoID>;
|
|
83
|
-
incoming: IncomingSyncStream;
|
|
84
|
-
outgoing: OutgoingSyncQueue;
|
|
85
|
-
role: "peer" | "server" | "client";
|
|
86
|
-
priority?: number;
|
|
87
|
-
crashOnClose: boolean;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
82
|
export function combinedKnownStates(
|
|
91
83
|
stateA: CoValueKnownState,
|
|
92
84
|
stateB: CoValueKnownState,
|
|
@@ -141,7 +133,7 @@ export class SyncManager {
|
|
|
141
133
|
|
|
142
134
|
for (const peer of eligiblePeers) {
|
|
143
135
|
// console.log("loading", id, "from", peer.id);
|
|
144
|
-
await peer.
|
|
136
|
+
await peer.pushOutgoingMessage({
|
|
145
137
|
action: "load",
|
|
146
138
|
id: id,
|
|
147
139
|
header: false,
|
|
@@ -227,7 +219,7 @@ export class SyncManager {
|
|
|
227
219
|
id,
|
|
228
220
|
header: false,
|
|
229
221
|
sessions: {},
|
|
230
|
-
}).catch((e) => {
|
|
222
|
+
}).catch((e: unknown) => {
|
|
231
223
|
console.error("Error sending load", e);
|
|
232
224
|
});
|
|
233
225
|
return;
|
|
@@ -244,7 +236,7 @@ export class SyncManager {
|
|
|
244
236
|
this.trySendToPeer(peer, {
|
|
245
237
|
action: "load",
|
|
246
238
|
...coValue.knownState(),
|
|
247
|
-
}).catch((e) => {
|
|
239
|
+
}).catch((e: unknown) => {
|
|
248
240
|
console.error("Error sending load", e);
|
|
249
241
|
});
|
|
250
242
|
}
|
|
@@ -274,7 +266,7 @@ export class SyncManager {
|
|
|
274
266
|
action: "known",
|
|
275
267
|
asDependencyOf,
|
|
276
268
|
...coValue.knownState(),
|
|
277
|
-
}).catch((e) => {
|
|
269
|
+
}).catch((e: unknown) => {
|
|
278
270
|
console.error("Error sending known state", e);
|
|
279
271
|
});
|
|
280
272
|
|
|
@@ -282,7 +274,10 @@ export class SyncManager {
|
|
|
282
274
|
}
|
|
283
275
|
}
|
|
284
276
|
|
|
285
|
-
async sendNewContentIncludingDependencies(
|
|
277
|
+
async sendNewContentIncludingDependencies(
|
|
278
|
+
id: RawCoID,
|
|
279
|
+
peer: PeerState,
|
|
280
|
+
) {
|
|
286
281
|
const coValue = this.local.expectCoValueLoaded(id);
|
|
287
282
|
|
|
288
283
|
await Promise.all(
|
|
@@ -310,9 +305,11 @@ export class SyncManager {
|
|
|
310
305
|
// } header: ${!!piece.header}`,
|
|
311
306
|
// // Object.values(piece.new).map((s) => s.newTransactions)
|
|
312
307
|
// );
|
|
313
|
-
|
|
308
|
+
|
|
309
|
+
this.trySendToPeer(peer, piece).catch((e: unknown) => {
|
|
314
310
|
console.error("Error sending content piece", e);
|
|
315
311
|
});
|
|
312
|
+
|
|
316
313
|
if (performance.now() - lastYield > 10) {
|
|
317
314
|
await new Promise<void>((resolve) => {
|
|
318
315
|
setTimeout(resolve, 0);
|
|
@@ -336,16 +333,7 @@ export class SyncManager {
|
|
|
336
333
|
}
|
|
337
334
|
|
|
338
335
|
addPeer(peer: Peer) {
|
|
339
|
-
const peerState
|
|
340
|
-
id: peer.id,
|
|
341
|
-
optimisticKnownStates: {},
|
|
342
|
-
incoming: peer.incoming,
|
|
343
|
-
outgoing: peer.outgoing,
|
|
344
|
-
toldKnownState: new Set(),
|
|
345
|
-
role: peer.role,
|
|
346
|
-
priority: peer.priority,
|
|
347
|
-
crashOnClose: peer.crashOnClose,
|
|
348
|
-
};
|
|
336
|
+
const peerState = new PeerState(peer);
|
|
349
337
|
this.peers[peer.id] = peerState;
|
|
350
338
|
|
|
351
339
|
if (peer.role === "server") {
|
|
@@ -420,7 +408,7 @@ export class SyncManager {
|
|
|
420
408
|
}
|
|
421
409
|
|
|
422
410
|
trySendToPeer(peer: PeerState, msg: SyncMessage) {
|
|
423
|
-
return peer.
|
|
411
|
+
return peer.pushOutgoingMessage(msg);
|
|
424
412
|
}
|
|
425
413
|
|
|
426
414
|
async handleLoad(msg: LoadMessage, peer: PeerState) {
|
|
@@ -679,7 +667,8 @@ export class SyncManager {
|
|
|
679
667
|
newTransactions.length + " new transactions",
|
|
680
668
|
"after: " + newContentForSession.after,
|
|
681
669
|
"our last known tx idx initially: " + ourKnownTxIdx,
|
|
682
|
-
"our last known tx idx now: " +
|
|
670
|
+
"our last known tx idx now: " +
|
|
671
|
+
coValue.sessionLogs.get(sessionID)?.transactions.length,
|
|
683
672
|
);
|
|
684
673
|
continue;
|
|
685
674
|
}
|
|
@@ -774,11 +763,7 @@ export class SyncManager {
|
|
|
774
763
|
|
|
775
764
|
gracefulShutdown() {
|
|
776
765
|
for (const peer of Object.values(this.peers)) {
|
|
777
|
-
|
|
778
|
-
peer.outgoing.close();
|
|
779
|
-
peer.incoming = (async function* () {
|
|
780
|
-
yield "Disconnected" as const;
|
|
781
|
-
})();
|
|
766
|
+
peer.gracefulShutdown();
|
|
782
767
|
}
|
|
783
768
|
}
|
|
784
769
|
}
|