cojson 0.2.1 → 0.2.3
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 +7 -7
- package/dist/account.js +2 -2
- package/dist/account.js.map +1 -1
- package/dist/coValue.d.ts +26 -23
- package/dist/coValue.js +14 -0
- package/dist/coValue.js.map +1 -1
- package/dist/coValueCore.d.ts +6 -6
- package/dist/coValueCore.js.map +1 -1
- package/dist/coValues/coList.d.ts +22 -22
- package/dist/coValues/coList.js +3 -2
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.d.ts +29 -35
- package/dist/coValues/coMap.js +17 -8
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.d.ts +28 -27
- package/dist/coValues/coStream.js +15 -6
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coValues/static.d.ts +4 -4
- package/dist/coValues/static.js.map +1 -1
- package/dist/group.d.ts +8 -6
- package/dist/group.js +20 -4
- package/dist/group.js.map +1 -1
- package/dist/index.d.ts +7 -6
- package/dist/index.js.map +1 -1
- package/dist/media.d.ts +1 -2
- package/dist/node.d.ts +7 -3
- package/dist/node.js +37 -7
- package/dist/node.js.map +1 -1
- package/dist/queries.d.ts +114 -0
- package/dist/queries.js +260 -0
- package/dist/queries.js.map +1 -0
- package/dist/sync.js +3 -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} +7 -5
- package/dist/tests/testUtils.js.map +1 -0
- package/package.json +2 -2
- package/src/account.ts +5 -5
- package/src/coValue.ts +54 -28
- package/src/coValueCore.ts +6 -6
- package/src/coValues/coList.ts +73 -37
- package/src/coValues/coMap.ts +134 -68
- package/src/coValues/coStream.ts +86 -55
- package/src/coValues/static.ts +5 -5
- package/src/group.ts +50 -11
- package/src/index.ts +10 -8
- package/src/media.ts +1 -2
- package/src/node.ts +70 -19
- package/src/queries.ts +519 -0
- package/src/sync.ts +10 -2
- package/src/{account.test.ts → tests/account.test.ts} +4 -4
- package/src/{coValue.test.ts → tests/coValue.test.ts} +5 -5
- package/src/{coValueCore.test.ts → tests/coValueCore.test.ts} +7 -7
- package/src/{crypto.test.ts → tests/crypto.test.ts} +3 -3
- package/src/{group.test.ts → tests/group.test.ts} +2 -2
- package/src/{permissions.test.ts → tests/permissions.test.ts} +5 -5
- package/src/tests/queries.test.ts +301 -0
- package/src/{sync.test.ts → tests/sync.test.ts} +10 -10
- package/src/{testUtils.ts → tests/testUtils.ts} +8 -6
- package/dist/testUtils.js.map +0 -1
package/src/group.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CoID,
|
|
1
|
+
import { CoID, CoValue, AnyCoValue } from "./coValue.js";
|
|
2
2
|
import { CoMap } from "./coValues/coMap.js";
|
|
3
3
|
import { JsonObject, JsonValue } from "./jsonValue.js";
|
|
4
4
|
import {
|
|
@@ -21,7 +21,11 @@ import { AccountID, GeneralizedControlledAccount, Profile } from "./account.js";
|
|
|
21
21
|
import { Role } from "./permissions.js";
|
|
22
22
|
import { base58 } from "@scure/base";
|
|
23
23
|
import { CoList } from "./coValues/coList.js";
|
|
24
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
BinaryCoStream,
|
|
26
|
+
BinaryCoStreamMeta,
|
|
27
|
+
CoStream,
|
|
28
|
+
} from "./coValues/coStream.js";
|
|
25
29
|
|
|
26
30
|
export type GroupContent = {
|
|
27
31
|
profile: CoID<Profile> | null;
|
|
@@ -35,7 +39,7 @@ export type GroupContent = {
|
|
|
35
39
|
};
|
|
36
40
|
|
|
37
41
|
export function expectGroupContent(
|
|
38
|
-
content:
|
|
42
|
+
content: CoValue
|
|
39
43
|
): CoMap<GroupContent, JsonObject | null> {
|
|
40
44
|
if (content.type !== "comap") {
|
|
41
45
|
throw new Error("Expected map");
|
|
@@ -238,10 +242,22 @@ export class Group {
|
|
|
238
242
|
|
|
239
243
|
/** Creates a new `CoMap` within this group, with the specified specialized
|
|
240
244
|
* `CoMap` type `M` and optional static metadata. */
|
|
241
|
-
createMap<
|
|
245
|
+
createMap<
|
|
246
|
+
M extends CoMap<
|
|
247
|
+
{ [key: string]: JsonValue | AnyCoValue | undefined },
|
|
248
|
+
JsonObject | null
|
|
249
|
+
>
|
|
250
|
+
>(
|
|
251
|
+
init?: M extends CoMap<infer M, infer _Meta>
|
|
252
|
+
? {
|
|
253
|
+
[K in keyof M]: M[K] extends AnyCoValue
|
|
254
|
+
? M[K] | CoID<M[K]>
|
|
255
|
+
: M[K];
|
|
256
|
+
}
|
|
257
|
+
: never,
|
|
242
258
|
meta?: M["meta"]
|
|
243
259
|
): M {
|
|
244
|
-
|
|
260
|
+
let map = this.node
|
|
245
261
|
.createCoValue({
|
|
246
262
|
type: "comap",
|
|
247
263
|
ruleset: {
|
|
@@ -252,14 +268,27 @@ export class Group {
|
|
|
252
268
|
...createdNowUnique(),
|
|
253
269
|
})
|
|
254
270
|
.getCurrentContent() as M;
|
|
271
|
+
|
|
272
|
+
if (init) {
|
|
273
|
+
map = map.edit((editable) => {
|
|
274
|
+
for (const [key, value] of Object.entries(init)) {
|
|
275
|
+
editable.set(key, value);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return map;
|
|
255
281
|
}
|
|
256
282
|
|
|
257
283
|
/** Creates a new `CoList` within this group, with the specified specialized
|
|
258
284
|
* `CoList` type `L` and optional static metadata. */
|
|
259
|
-
createList<L extends CoList<JsonValue, JsonObject | null>>(
|
|
285
|
+
createList<L extends CoList<JsonValue | CoValue, JsonObject | null>>(
|
|
286
|
+
init?: L extends CoList<infer I, infer _Meta>
|
|
287
|
+
? (I extends CoValue ? CoID<I> | I : I)[]
|
|
288
|
+
: never,
|
|
260
289
|
meta?: L["meta"]
|
|
261
290
|
): L {
|
|
262
|
-
|
|
291
|
+
let list = this.node
|
|
263
292
|
.createCoValue({
|
|
264
293
|
type: "colist",
|
|
265
294
|
ruleset: {
|
|
@@ -270,9 +299,19 @@ export class Group {
|
|
|
270
299
|
...createdNowUnique(),
|
|
271
300
|
})
|
|
272
301
|
.getCurrentContent() as L;
|
|
302
|
+
|
|
303
|
+
if (init) {
|
|
304
|
+
list = list.edit((editable) => {
|
|
305
|
+
for (const item of init) {
|
|
306
|
+
editable.push(item);
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return list;
|
|
273
312
|
}
|
|
274
313
|
|
|
275
|
-
createStream<C extends CoStream<JsonValue, JsonObject | null>>(
|
|
314
|
+
createStream<C extends CoStream<JsonValue | CoValue, JsonObject | null>>(
|
|
276
315
|
meta?: C["meta"]
|
|
277
316
|
): C {
|
|
278
317
|
return this.node
|
|
@@ -288,9 +327,9 @@ export class Group {
|
|
|
288
327
|
.getCurrentContent() as C;
|
|
289
328
|
}
|
|
290
329
|
|
|
291
|
-
createBinaryStream<
|
|
292
|
-
C
|
|
293
|
-
|
|
330
|
+
createBinaryStream<C extends BinaryCoStream<BinaryCoStreamMeta>>(
|
|
331
|
+
meta: C["meta"] = { type: "binary" }
|
|
332
|
+
): C {
|
|
294
333
|
return this.node
|
|
295
334
|
.createCoValue({
|
|
296
335
|
type: "costream",
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CoValueCore, newRandomSessionID, MAX_RECOMMENDED_TX_SIZE } from "./coValueCore.js";
|
|
2
2
|
import { LocalNode } from "./node.js";
|
|
3
|
-
import type { CoValue
|
|
3
|
+
import type { CoValue } from "./coValue.js";
|
|
4
4
|
import { CoMap, WriteableCoMap } from "./coValues/coMap.js";
|
|
5
5
|
import { CoList, WriteableCoList } from "./coValues/coList.js";
|
|
6
6
|
import {
|
|
@@ -28,16 +28,17 @@ import { base64URLtoBytes, bytesToBase64url } from "./base64url.js";
|
|
|
28
28
|
import { parseJSON } from "./jsonStringify.js";
|
|
29
29
|
|
|
30
30
|
import type { SessionID, AgentID } from "./ids.js";
|
|
31
|
-
import type { CoID,
|
|
32
|
-
import type {
|
|
31
|
+
import type { CoID, AnyCoValue } from "./coValue.js";
|
|
32
|
+
import type { Queried } from "./queries.js";
|
|
33
|
+
import type { BinaryStreamInfo, BinaryCoStreamMeta } from "./coValues/coStream.js";
|
|
33
34
|
import type { JsonValue } from "./jsonValue.js";
|
|
34
35
|
import type { SyncMessage, Peer } from "./sync.js";
|
|
35
36
|
import type { AgentSecret } from "./crypto.js";
|
|
36
|
-
import type { AccountID, Profile } from "./account.js";
|
|
37
|
+
import type { AccountID, Account, Profile } from "./account.js";
|
|
37
38
|
import type { InviteSecret } from "./group.js";
|
|
38
39
|
import type * as Media from "./media.js";
|
|
39
40
|
|
|
40
|
-
type Value = JsonValue |
|
|
41
|
+
type Value = JsonValue | AnyCoValue;
|
|
41
42
|
|
|
42
43
|
/** @hidden */
|
|
43
44
|
export const cojsonInternals = {
|
|
@@ -81,14 +82,15 @@ export type {
|
|
|
81
82
|
Value,
|
|
82
83
|
JsonValue,
|
|
83
84
|
CoValue,
|
|
84
|
-
|
|
85
|
-
CoValueImpl,
|
|
85
|
+
AnyCoValue,
|
|
86
86
|
CoID,
|
|
87
|
+
Queried,
|
|
87
88
|
AccountID,
|
|
89
|
+
Account,
|
|
88
90
|
Profile,
|
|
89
91
|
SessionID,
|
|
90
92
|
Peer,
|
|
91
|
-
|
|
93
|
+
BinaryStreamInfo,
|
|
92
94
|
BinaryCoStreamMeta,
|
|
93
95
|
AgentID,
|
|
94
96
|
AgentSecret,
|
package/src/media.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { CoMap } from './coValues/coMap.js'
|
|
2
|
-
import { CoID } from './coValue.js'
|
|
3
2
|
import { BinaryCoStream } from './coValues/coStream.js'
|
|
4
3
|
|
|
5
4
|
export type ImageDefinition = CoMap<{
|
|
6
5
|
originalSize: [number, number];
|
|
7
6
|
placeholderDataURL?: string;
|
|
8
|
-
[res: `${number}x${number}`]:
|
|
7
|
+
[res: `${number}x${number}`]: BinaryCoStream;
|
|
9
8
|
}>;
|
package/src/node.ts
CHANGED
|
@@ -9,7 +9,11 @@ import {
|
|
|
9
9
|
newRandomKeySecret,
|
|
10
10
|
seal,
|
|
11
11
|
} from "./crypto.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
CoValueCore,
|
|
14
|
+
CoValueHeader,
|
|
15
|
+
newRandomSessionID,
|
|
16
|
+
} from "./coValueCore.js";
|
|
13
17
|
import {
|
|
14
18
|
InviteSecret,
|
|
15
19
|
Group,
|
|
@@ -19,9 +23,10 @@ import {
|
|
|
19
23
|
} from "./group.js";
|
|
20
24
|
import { Peer, SyncManager } from "./sync.js";
|
|
21
25
|
import { AgentID, RawCoID, SessionID, isAgentID } from "./ids.js";
|
|
22
|
-
import { CoID
|
|
26
|
+
import { CoID } from "./coValue.js";
|
|
27
|
+
import { Queried, query } from "./queries.js";
|
|
23
28
|
import {
|
|
24
|
-
|
|
29
|
+
AccountGroup,
|
|
25
30
|
AccountMeta,
|
|
26
31
|
accountHeaderForInitialAgentSecret,
|
|
27
32
|
GeneralizedControlledAccount,
|
|
@@ -30,9 +35,10 @@ import {
|
|
|
30
35
|
AccountID,
|
|
31
36
|
Profile,
|
|
32
37
|
AccountContent,
|
|
33
|
-
|
|
38
|
+
Account,
|
|
34
39
|
} from "./account.js";
|
|
35
40
|
import { CoMap } from "./coValues/coMap.js";
|
|
41
|
+
import { CoValue } from "./index.js";
|
|
36
42
|
|
|
37
43
|
/** A `LocalNode` represents a local view of a set of loaded `CoValue`s, from the perspective of a particular account (or primitive cryptographic agent).
|
|
38
44
|
|
|
@@ -152,16 +158,45 @@ export class LocalNode {
|
|
|
152
158
|
* promise once a first version has been loaded. See `coValue.subscribe()` and `node.useTelepathicData()`
|
|
153
159
|
* for listening to subsequent updates to the CoValue.
|
|
154
160
|
*/
|
|
155
|
-
async load<T extends
|
|
161
|
+
async load<T extends CoValue>(id: CoID<T>): Promise<T> {
|
|
156
162
|
return (await this.loadCoValue(id)).getCurrentContent() as T;
|
|
157
163
|
}
|
|
158
164
|
|
|
165
|
+
subscribe<T extends CoValue>(id: CoID<T>, callback: (update: T) => void): () => void {
|
|
166
|
+
let stopped = false;
|
|
167
|
+
let unsubscribe!: () => void;
|
|
168
|
+
|
|
169
|
+
console.log("Subscribing to " + id);
|
|
170
|
+
|
|
171
|
+
this.load(id).then((coValue) => {
|
|
172
|
+
if (stopped) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
unsubscribe = coValue.subscribe(callback);
|
|
176
|
+
}).catch((e) => {
|
|
177
|
+
console.error("Error subscribing to ", id, e);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
return () => {
|
|
181
|
+
console.log("Unsubscribing from " + id);
|
|
182
|
+
stopped = true;
|
|
183
|
+
unsubscribe?.();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
query<T extends CoValue>(
|
|
188
|
+
id: CoID<T>,
|
|
189
|
+
callback: (update: Queried<T> | undefined) => void
|
|
190
|
+
): () => void {
|
|
191
|
+
return query(id, this, callback);
|
|
192
|
+
}
|
|
193
|
+
|
|
159
194
|
/**
|
|
160
195
|
* Loads a profile associated with an account. `Profile` is at least a `CoMap<{string: name}>`,
|
|
161
196
|
* but might contain other, app-specific properties.
|
|
162
197
|
*/
|
|
163
198
|
async loadProfile(id: AccountID): Promise<Profile> {
|
|
164
|
-
const account = await this.load<
|
|
199
|
+
const account = await this.load<Account>(id);
|
|
165
200
|
const profileID = account.get("profile");
|
|
166
201
|
|
|
167
202
|
if (!profileID) {
|
|
@@ -172,7 +207,7 @@ export class LocalNode {
|
|
|
172
207
|
).getCurrentContent() as Profile;
|
|
173
208
|
}
|
|
174
209
|
|
|
175
|
-
async acceptInvite<T extends
|
|
210
|
+
async acceptInvite<T extends CoValue>(
|
|
176
211
|
groupOrOwnedValueID: CoID<T>,
|
|
177
212
|
inviteSecret: InviteSecret
|
|
178
213
|
): Promise<void> {
|
|
@@ -204,10 +239,7 @@ export class LocalNode {
|
|
|
204
239
|
}
|
|
205
240
|
});
|
|
206
241
|
setTimeout(
|
|
207
|
-
() =>
|
|
208
|
-
reject(
|
|
209
|
-
new Error("Couldn't find invite before timeout")
|
|
210
|
-
),
|
|
242
|
+
() => reject(new Error("Couldn't find invite before timeout")),
|
|
211
243
|
2000
|
|
212
244
|
);
|
|
213
245
|
});
|
|
@@ -224,7 +256,9 @@ export class LocalNode {
|
|
|
224
256
|
(existingRole === "writer" && inviteRole === "reader") ||
|
|
225
257
|
(existingRole === "reader" && inviteRole === "readerInvite")
|
|
226
258
|
) {
|
|
227
|
-
console.debug(
|
|
259
|
+
console.debug(
|
|
260
|
+
"Not accepting invite that would replace or downgrade role"
|
|
261
|
+
);
|
|
228
262
|
return;
|
|
229
263
|
}
|
|
230
264
|
|
|
@@ -242,7 +276,8 @@ export class LocalNode {
|
|
|
242
276
|
: "reader"
|
|
243
277
|
);
|
|
244
278
|
|
|
245
|
-
group.underlyingMap.core._sessions =
|
|
279
|
+
group.underlyingMap.core._sessions =
|
|
280
|
+
groupAsInvite.underlyingMap.core.sessions;
|
|
246
281
|
group.underlyingMap.core._cachedContent = undefined;
|
|
247
282
|
|
|
248
283
|
for (const groupListener of group.underlyingMap.core.listeners) {
|
|
@@ -332,11 +367,11 @@ export class LocalNode {
|
|
|
332
367
|
account.node
|
|
333
368
|
);
|
|
334
369
|
|
|
335
|
-
|
|
370
|
+
let profile = accountAsGroup.createMap<Profile>(undefined, {
|
|
336
371
|
type: "profile",
|
|
337
372
|
});
|
|
338
373
|
|
|
339
|
-
profile.edit((editable) => {
|
|
374
|
+
profile = profile.edit((editable) => {
|
|
340
375
|
editable.set("name", name, "trusting");
|
|
341
376
|
});
|
|
342
377
|
|
|
@@ -346,14 +381,26 @@ export class LocalNode {
|
|
|
346
381
|
|
|
347
382
|
const accountOnThisNode = this.expectCoValueLoaded(account.id);
|
|
348
383
|
|
|
349
|
-
accountOnThisNode._sessions = {
|
|
384
|
+
accountOnThisNode._sessions = {
|
|
385
|
+
...accountAsGroup.underlyingMap.core.sessions,
|
|
386
|
+
};
|
|
350
387
|
accountOnThisNode._cachedContent = undefined;
|
|
351
388
|
|
|
389
|
+
const profileOnThisNode = this.createCoValue(profile.core.header);
|
|
390
|
+
|
|
391
|
+
profileOnThisNode._sessions = {
|
|
392
|
+
...profile.core.sessions,
|
|
393
|
+
};
|
|
394
|
+
profileOnThisNode._cachedContent = undefined;
|
|
395
|
+
|
|
352
396
|
return controlledAccount;
|
|
353
397
|
}
|
|
354
398
|
|
|
355
399
|
/** @internal */
|
|
356
|
-
resolveAccountAgent(
|
|
400
|
+
resolveAccountAgent(
|
|
401
|
+
id: AccountID | AgentID,
|
|
402
|
+
expectation?: string
|
|
403
|
+
): AgentID {
|
|
357
404
|
if (isAgentID(id)) {
|
|
358
405
|
return id;
|
|
359
406
|
}
|
|
@@ -374,7 +421,7 @@ export class LocalNode {
|
|
|
374
421
|
);
|
|
375
422
|
}
|
|
376
423
|
|
|
377
|
-
return new
|
|
424
|
+
return new AccountGroup(
|
|
378
425
|
coValue.getCurrentContent() as CoMap<GroupContent, AccountMeta>,
|
|
379
426
|
this
|
|
380
427
|
).getCurrentAgentID();
|
|
@@ -443,7 +490,11 @@ export class LocalNode {
|
|
|
443
490
|
continue;
|
|
444
491
|
}
|
|
445
492
|
|
|
446
|
-
const newCoValue = new CoValueCore(
|
|
493
|
+
const newCoValue = new CoValueCore(
|
|
494
|
+
entry.coValue.header,
|
|
495
|
+
newNode,
|
|
496
|
+
{ ...entry.coValue.sessions }
|
|
497
|
+
);
|
|
447
498
|
|
|
448
499
|
newNode.coValues[coValueID as RawCoID] = {
|
|
449
500
|
state: "loaded",
|