cojson 0.2.2 → 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/{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/{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/coValues/coMap.ts
CHANGED
|
@@ -1,48 +1,49 @@
|
|
|
1
|
-
import { JsonObject, JsonValue } from
|
|
2
|
-
import { TransactionID } from
|
|
3
|
-
import { CoID,
|
|
4
|
-
import { CoValueCore, accountOrAgentIDfromSessionID } from
|
|
5
|
-
import { AccountID, isAccountID } from
|
|
6
|
-
import { Group } from
|
|
7
|
-
import { parseJSON } from
|
|
8
|
-
|
|
9
|
-
type MapOp<K extends string, V extends JsonValue | undefined> = {
|
|
1
|
+
import { JsonObject, JsonValue } from "../jsonValue.js";
|
|
2
|
+
import { TransactionID } from "../ids.js";
|
|
3
|
+
import { CoID, CoValue, isCoValue } from "../coValue.js";
|
|
4
|
+
import { CoValueCore, accountOrAgentIDfromSessionID } from "../coValueCore.js";
|
|
5
|
+
import { AccountID, isAccountID } from "../account.js";
|
|
6
|
+
import { Group } from "../group.js";
|
|
7
|
+
import { parseJSON } from "../jsonStringify.js";
|
|
8
|
+
|
|
9
|
+
type MapOp<K extends string, V extends JsonValue | CoValue | undefined> = {
|
|
10
10
|
txID: TransactionID;
|
|
11
11
|
madeAt: number;
|
|
12
12
|
changeIdx: number;
|
|
13
13
|
} & MapOpPayload<K, V>;
|
|
14
14
|
// TODO: add after TransactionID[] for conflicts/ordering
|
|
15
15
|
|
|
16
|
-
export type MapOpPayload<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
export type MapOpPayload<
|
|
17
|
+
K extends string,
|
|
18
|
+
V extends JsonValue | CoValue | undefined
|
|
19
|
+
> =
|
|
20
|
+
| {
|
|
21
|
+
op: "set";
|
|
22
|
+
key: K;
|
|
23
|
+
value: V extends CoValue ? CoID<V> : Exclude<V, CoValue>;
|
|
24
|
+
}
|
|
25
|
+
| {
|
|
26
|
+
op: "del";
|
|
27
|
+
key: K;
|
|
28
|
+
};
|
|
29
29
|
|
|
30
30
|
/** A collaborative map with precise shape `M` and optional static metadata `Meta` */
|
|
31
31
|
export class CoMap<
|
|
32
|
-
M extends { [key: string]: JsonValue | undefined
|
|
33
|
-
Meta extends JsonObject | null = null
|
|
34
|
-
> implements
|
|
35
|
-
|
|
32
|
+
M extends { [key: string]: JsonValue | CoValue | undefined },
|
|
33
|
+
Meta extends JsonObject | null = null
|
|
34
|
+
> implements CoValue
|
|
35
|
+
{
|
|
36
|
+
id: CoID<this>;
|
|
36
37
|
type = "comap" as const;
|
|
37
38
|
core: CoValueCore;
|
|
38
39
|
/** @internal */
|
|
39
40
|
ops: {
|
|
40
|
-
[
|
|
41
|
+
[Key in keyof M & string]?: MapOp<Key, M[Key]>[];
|
|
41
42
|
};
|
|
42
43
|
|
|
43
44
|
/** @internal */
|
|
44
45
|
constructor(core: CoValueCore) {
|
|
45
|
-
this.id = core.id as CoID<
|
|
46
|
+
this.id = core.id as CoID<this>;
|
|
46
47
|
this.core = core;
|
|
47
48
|
this.ops = {};
|
|
48
49
|
|
|
@@ -61,11 +62,18 @@ export class CoMap<
|
|
|
61
62
|
protected fillOpsFromCoValue() {
|
|
62
63
|
this.ops = {};
|
|
63
64
|
|
|
64
|
-
for (const {
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
for (const {
|
|
66
|
+
txID,
|
|
67
|
+
changes,
|
|
68
|
+
madeAt,
|
|
69
|
+
} of this.core.getValidSortedTransactions()) {
|
|
70
|
+
for (const [changeIdx, changeUntyped] of parseJSON(
|
|
71
|
+
changes
|
|
67
72
|
).entries()) {
|
|
68
|
-
const change = changeUntyped as MapOpPayload<
|
|
73
|
+
const change = changeUntyped as MapOpPayload<
|
|
74
|
+
keyof M & string,
|
|
75
|
+
M[keyof M & string]
|
|
76
|
+
>;
|
|
69
77
|
let entries = this.ops[change.key];
|
|
70
78
|
if (!entries) {
|
|
71
79
|
entries = [];
|
|
@@ -75,18 +83,25 @@ export class CoMap<
|
|
|
75
83
|
txID,
|
|
76
84
|
madeAt,
|
|
77
85
|
changeIdx,
|
|
78
|
-
...(change as MapOpPayload<
|
|
86
|
+
...(change as MapOpPayload<
|
|
87
|
+
keyof M & string,
|
|
88
|
+
M[keyof M & string]
|
|
89
|
+
>),
|
|
79
90
|
});
|
|
80
91
|
}
|
|
81
92
|
}
|
|
82
93
|
}
|
|
83
94
|
|
|
84
|
-
keys():
|
|
85
|
-
return Object.keys(this.ops) as
|
|
95
|
+
keys(): (keyof M & string)[] {
|
|
96
|
+
return Object.keys(this.ops) as (keyof M & string)[];
|
|
86
97
|
}
|
|
87
98
|
|
|
88
99
|
/** Returns the current value for the given key. */
|
|
89
|
-
get<K extends
|
|
100
|
+
get<K extends keyof M & string>(
|
|
101
|
+
key: K
|
|
102
|
+
):
|
|
103
|
+
| (M[K] extends CoValue ? CoID<M[K]> : Exclude<M[K], CoValue>)
|
|
104
|
+
| undefined {
|
|
90
105
|
const ops = this.ops[key];
|
|
91
106
|
if (!ops) {
|
|
92
107
|
return undefined;
|
|
@@ -101,7 +116,12 @@ export class CoMap<
|
|
|
101
116
|
}
|
|
102
117
|
}
|
|
103
118
|
|
|
104
|
-
getAtTime<K extends
|
|
119
|
+
getAtTime<K extends keyof M & string>(
|
|
120
|
+
key: K,
|
|
121
|
+
time: number
|
|
122
|
+
):
|
|
123
|
+
| (M[K] extends CoValue ? CoID<M[K]> : Exclude<M[K], CoValue>)
|
|
124
|
+
| undefined {
|
|
105
125
|
const ops = this.ops[key];
|
|
106
126
|
if (!ops) {
|
|
107
127
|
return undefined;
|
|
@@ -121,8 +141,8 @@ export class CoMap<
|
|
|
121
141
|
}
|
|
122
142
|
|
|
123
143
|
/** Returns the accountID of the last account to modify the value for the given key. */
|
|
124
|
-
whoEdited<K extends
|
|
125
|
-
const tx
|
|
144
|
+
whoEdited<K extends keyof M & string>(key: K): AccountID | undefined {
|
|
145
|
+
const tx = this.getLastTxID(key);
|
|
126
146
|
if (!tx) {
|
|
127
147
|
return undefined;
|
|
128
148
|
}
|
|
@@ -134,7 +154,7 @@ export class CoMap<
|
|
|
134
154
|
}
|
|
135
155
|
}
|
|
136
156
|
|
|
137
|
-
getLastTxID<K extends
|
|
157
|
+
getLastTxID<K extends keyof M & string>(key: K): TransactionID | undefined {
|
|
138
158
|
const ops = this.ops[key];
|
|
139
159
|
if (!ops) {
|
|
140
160
|
return undefined;
|
|
@@ -145,7 +165,15 @@ export class CoMap<
|
|
|
145
165
|
return lastEntry.txID;
|
|
146
166
|
}
|
|
147
167
|
|
|
148
|
-
getLastEntry<K extends
|
|
168
|
+
getLastEntry<K extends keyof M & string>(
|
|
169
|
+
key: K
|
|
170
|
+
):
|
|
171
|
+
| {
|
|
172
|
+
at: number;
|
|
173
|
+
txID: TransactionID;
|
|
174
|
+
value: M[K] extends CoValue ? CoID<M[K]> : Exclude<M[K], CoValue>;
|
|
175
|
+
}
|
|
176
|
+
| undefined {
|
|
149
177
|
const ops = this.ops[key];
|
|
150
178
|
if (!ops) {
|
|
151
179
|
return undefined;
|
|
@@ -156,21 +184,43 @@ export class CoMap<
|
|
|
156
184
|
if (lastEntry.op === "del") {
|
|
157
185
|
return undefined;
|
|
158
186
|
} else {
|
|
159
|
-
return {
|
|
187
|
+
return {
|
|
188
|
+
at: lastEntry.madeAt,
|
|
189
|
+
txID: lastEntry.txID,
|
|
190
|
+
value: lastEntry.value,
|
|
191
|
+
};
|
|
160
192
|
}
|
|
161
193
|
}
|
|
162
194
|
|
|
163
|
-
getHistory<K extends
|
|
195
|
+
getHistory<K extends keyof M & string>(
|
|
196
|
+
key: K
|
|
197
|
+
): {
|
|
198
|
+
at: number;
|
|
199
|
+
txID: TransactionID;
|
|
200
|
+
value:
|
|
201
|
+
| (M[K] extends CoValue ? CoID<M[K]> : Exclude<M[K], CoValue>)
|
|
202
|
+
| undefined;
|
|
203
|
+
}[] {
|
|
164
204
|
const ops = this.ops[key];
|
|
165
205
|
if (!ops) {
|
|
166
206
|
return [];
|
|
167
207
|
}
|
|
168
208
|
|
|
169
|
-
const history: {
|
|
209
|
+
const history: {
|
|
210
|
+
at: number;
|
|
211
|
+
txID: TransactionID;
|
|
212
|
+
value:
|
|
213
|
+
| (M[K] extends CoValue ? CoID<M[K]> : Exclude<M[K], CoValue>)
|
|
214
|
+
| undefined;
|
|
215
|
+
}[] = [];
|
|
170
216
|
|
|
171
217
|
for (const op of ops) {
|
|
172
218
|
if (op.op === "del") {
|
|
173
|
-
history.push({
|
|
219
|
+
history.push({
|
|
220
|
+
at: op.madeAt,
|
|
221
|
+
txID: op.txID,
|
|
222
|
+
value: undefined,
|
|
223
|
+
});
|
|
174
224
|
} else {
|
|
175
225
|
history.push({ at: op.madeAt, txID: op.txID, value: op.value });
|
|
176
226
|
}
|
|
@@ -192,25 +242,28 @@ export class CoMap<
|
|
|
192
242
|
return json;
|
|
193
243
|
}
|
|
194
244
|
|
|
195
|
-
subscribe(listener: (coMap:
|
|
245
|
+
subscribe(listener: (coMap: this) => void): () => void {
|
|
196
246
|
return this.core.subscribe((content) => {
|
|
197
|
-
listener(content as
|
|
247
|
+
listener(content as this);
|
|
198
248
|
});
|
|
199
249
|
}
|
|
200
250
|
|
|
201
|
-
edit(changer: (editable: WriteableCoMap<M, Meta>) => void):
|
|
251
|
+
edit(changer: (editable: WriteableCoMap<M, Meta>) => void): this {
|
|
202
252
|
const editable = new WriteableCoMap<M, Meta>(this.core);
|
|
203
253
|
changer(editable);
|
|
204
|
-
return new CoMap(this.core);
|
|
254
|
+
return new CoMap(this.core) as this;
|
|
205
255
|
}
|
|
206
256
|
}
|
|
207
257
|
|
|
208
258
|
export class WriteableCoMap<
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
>
|
|
259
|
+
M extends { [key: string]: JsonValue | CoValue | undefined },
|
|
260
|
+
Meta extends JsonObject | null = null
|
|
261
|
+
>
|
|
262
|
+
extends CoMap<M, Meta>
|
|
263
|
+
implements CoValue
|
|
264
|
+
{
|
|
212
265
|
/** @internal */
|
|
213
|
-
edit(_changer: (editable: WriteableCoMap<M, Meta>) => void):
|
|
266
|
+
edit(_changer: (editable: WriteableCoMap<M, Meta>) => void): this {
|
|
214
267
|
throw new Error("Already editing.");
|
|
215
268
|
}
|
|
216
269
|
|
|
@@ -219,14 +272,21 @@ export class WriteableCoMap<
|
|
|
219
272
|
* If `privacy` is `"private"` **(default)**, both `key` and `value` are encrypted in the transaction, only readable by other members of the group this `CoMap` belongs to. Not even sync servers can see the content in plaintext.
|
|
220
273
|
*
|
|
221
274
|
* If `privacy` is `"trusting"`, both `key` and `value` are stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers. */
|
|
222
|
-
set<K extends
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
275
|
+
set<K extends keyof M & string>(
|
|
276
|
+
key: K,
|
|
277
|
+
value: M[K] extends CoValue ? M[K] | CoID<M[K]> : M[K],
|
|
278
|
+
privacy: "private" | "trusting" = "private"
|
|
279
|
+
): void {
|
|
280
|
+
this.core.makeTransaction(
|
|
281
|
+
[
|
|
282
|
+
{
|
|
283
|
+
op: "set",
|
|
284
|
+
key,
|
|
285
|
+
value: isCoValue(value) ? value.id : value,
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
privacy
|
|
289
|
+
);
|
|
230
290
|
|
|
231
291
|
this.fillOpsFromCoValue();
|
|
232
292
|
}
|
|
@@ -236,13 +296,19 @@ export class WriteableCoMap<
|
|
|
236
296
|
* If `privacy` is `"private"` **(default)**, `key` is encrypted in the transaction, only readable by other members of the group this `CoMap` belongs to. Not even sync servers can see the content in plaintext.
|
|
237
297
|
*
|
|
238
298
|
* If `privacy` is `"trusting"`, `key` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers. */
|
|
239
|
-
delete(
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
299
|
+
delete(
|
|
300
|
+
key: keyof M & string,
|
|
301
|
+
privacy: "private" | "trusting" = "private"
|
|
302
|
+
): void {
|
|
303
|
+
this.core.makeTransaction(
|
|
304
|
+
[
|
|
305
|
+
{
|
|
306
|
+
op: "del",
|
|
307
|
+
key,
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
privacy
|
|
311
|
+
);
|
|
246
312
|
|
|
247
313
|
this.fillOpsFromCoValue();
|
|
248
314
|
}
|
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
5
|
import { SessionID } from "../ids.js";
|
|
6
6
|
import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
|
|
7
|
-
import { AccountID } from "../
|
|
8
|
-
import { isAccountID } from "../account.js";
|
|
7
|
+
import { AccountID, isAccountID } 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,25 @@ export type BinaryStreamItem =
|
|
|
34
33
|
| BinaryStreamChunk
|
|
35
34
|
| BinaryStreamEnd;
|
|
36
35
|
|
|
36
|
+
export type CoStreamItem<T extends JsonValue | CoValue> = {
|
|
37
|
+
item: T extends CoValue ? CoID<T> : Exclude<T, CoValue>;
|
|
38
|
+
madeAt: number;
|
|
39
|
+
};
|
|
40
|
+
|
|
37
41
|
export class CoStream<
|
|
38
|
-
T extends JsonValue,
|
|
42
|
+
T extends JsonValue | CoValue,
|
|
39
43
|
Meta extends JsonObject | null = null
|
|
40
|
-
> implements
|
|
44
|
+
> implements CoValue
|
|
41
45
|
{
|
|
42
|
-
id: CoID<
|
|
46
|
+
id: CoID<this>;
|
|
43
47
|
type = "costream" as const;
|
|
44
48
|
core: CoValueCore;
|
|
45
49
|
items: {
|
|
46
|
-
[key: SessionID]:
|
|
50
|
+
[key: SessionID]: CoStreamItem<T>[];
|
|
47
51
|
};
|
|
48
52
|
|
|
49
53
|
constructor(core: CoValueCore) {
|
|
50
|
-
this.id = core.id as CoID<
|
|
54
|
+
this.id = core.id as CoID<this>;
|
|
51
55
|
this.core = core;
|
|
52
56
|
this.items = {};
|
|
53
57
|
this.fillFromCoValue();
|
|
@@ -71,18 +75,22 @@ export class CoStream<
|
|
|
71
75
|
changes,
|
|
72
76
|
} of this.core.getValidSortedTransactions()) {
|
|
73
77
|
for (const changeUntyped of parseJSON(changes)) {
|
|
74
|
-
const change = changeUntyped as T
|
|
78
|
+
const change = changeUntyped as T extends CoValue
|
|
79
|
+
? CoID<T>
|
|
80
|
+
: Exclude<T, CoValue>;
|
|
75
81
|
let entries = this.items[txID.sessionID];
|
|
76
82
|
if (!entries) {
|
|
77
83
|
entries = [];
|
|
78
84
|
this.items[txID.sessionID] = entries;
|
|
79
85
|
}
|
|
80
|
-
entries.push({item: change, madeAt});
|
|
86
|
+
entries.push({ item: change, madeAt });
|
|
81
87
|
}
|
|
82
88
|
}
|
|
83
89
|
}
|
|
84
90
|
|
|
85
|
-
getSingleStream():
|
|
91
|
+
getSingleStream():
|
|
92
|
+
| (T extends CoValue ? CoID<T> : Exclude<T, CoValue>)[]
|
|
93
|
+
| undefined {
|
|
86
94
|
if (Object.keys(this.items).length === 0) {
|
|
87
95
|
return undefined;
|
|
88
96
|
} else if (Object.keys(this.items).length !== 1) {
|
|
@@ -91,36 +99,54 @@ export class CoStream<
|
|
|
91
99
|
);
|
|
92
100
|
}
|
|
93
101
|
|
|
94
|
-
return Object.values(this.items)[0]?.map(item => item.item);
|
|
102
|
+
return Object.values(this.items)[0]?.map((item) => item.item);
|
|
95
103
|
}
|
|
96
104
|
|
|
97
|
-
getLastItemsPerAccount(): {
|
|
98
|
-
|
|
105
|
+
getLastItemsPerAccount(): {
|
|
106
|
+
[account: AccountID]:
|
|
107
|
+
| (T extends CoValue ? CoID<T> : Exclude<T, CoValue>)
|
|
108
|
+
| undefined;
|
|
109
|
+
} {
|
|
110
|
+
const result: { [account: AccountID]: CoStreamItem<T> | undefined } =
|
|
111
|
+
{};
|
|
99
112
|
|
|
100
113
|
for (const [sessionID, items] of Object.entries(this.items)) {
|
|
101
|
-
const account = accountOrAgentIDfromSessionID(
|
|
114
|
+
const account = accountOrAgentIDfromSessionID(
|
|
115
|
+
sessionID as SessionID
|
|
116
|
+
);
|
|
102
117
|
if (!isAccountID(account)) continue;
|
|
103
118
|
if (items.length > 0) {
|
|
104
119
|
const lastItemOfSession = items[items.length - 1]!;
|
|
105
|
-
if (
|
|
120
|
+
if (
|
|
121
|
+
!result[account] ||
|
|
122
|
+
lastItemOfSession.madeAt > result[account]!.madeAt
|
|
123
|
+
) {
|
|
106
124
|
result[account] = lastItemOfSession;
|
|
107
125
|
}
|
|
108
126
|
}
|
|
109
127
|
}
|
|
110
128
|
|
|
111
|
-
return Object.fromEntries(
|
|
112
|
-
[account, item
|
|
113
|
-
|
|
129
|
+
return Object.fromEntries(
|
|
130
|
+
Object.entries(result).map(([account, item]) => [
|
|
131
|
+
account,
|
|
132
|
+
item?.item,
|
|
133
|
+
])
|
|
134
|
+
);
|
|
114
135
|
}
|
|
115
136
|
|
|
116
|
-
getLastItemFrom(
|
|
117
|
-
|
|
137
|
+
getLastItemFrom(
|
|
138
|
+
account: AccountID
|
|
139
|
+
): (T extends CoValue ? CoID<T> : Exclude<T, CoValue>) | undefined {
|
|
140
|
+
let lastItem: CoStreamItem<T> | undefined;
|
|
118
141
|
|
|
119
142
|
for (const [sessionID, items] of Object.entries(this.items)) {
|
|
120
143
|
if (sessionID.startsWith(account)) {
|
|
121
144
|
if (items.length > 0) {
|
|
122
145
|
const lastItemOfSession = items[items.length - 1]!;
|
|
123
|
-
if (
|
|
146
|
+
if (
|
|
147
|
+
!lastItem ||
|
|
148
|
+
lastItemOfSession.madeAt > lastItem.madeAt
|
|
149
|
+
) {
|
|
124
150
|
lastItem = lastItemOfSession;
|
|
125
151
|
}
|
|
126
152
|
}
|
|
@@ -130,32 +156,35 @@ export class CoStream<
|
|
|
130
156
|
return lastItem?.item;
|
|
131
157
|
}
|
|
132
158
|
|
|
133
|
-
getLastItemFromMe():
|
|
159
|
+
getLastItemFromMe():
|
|
160
|
+
| (T extends CoValue ? CoID<T> : Exclude<T, CoValue>)
|
|
161
|
+
| undefined {
|
|
134
162
|
const myAccountID = this.core.node.account.id;
|
|
135
163
|
if (!isAccountID(myAccountID)) return undefined;
|
|
136
164
|
return this.getLastItemFrom(myAccountID);
|
|
137
165
|
}
|
|
138
166
|
|
|
139
167
|
toJSON(): {
|
|
140
|
-
[key: SessionID]: T[];
|
|
168
|
+
[key: SessionID]: (T extends CoValue ? CoID<T> : Exclude<T, CoValue>)[];
|
|
141
169
|
} {
|
|
142
|
-
return Object.fromEntries(
|
|
143
|
-
[sessionID, items
|
|
144
|
-
|
|
170
|
+
return Object.fromEntries(
|
|
171
|
+
Object.entries(this.items).map(([sessionID, items]) => [
|
|
172
|
+
sessionID,
|
|
173
|
+
items.map((item) => item.item),
|
|
174
|
+
])
|
|
175
|
+
);
|
|
145
176
|
}
|
|
146
177
|
|
|
147
|
-
subscribe(listener: (
|
|
178
|
+
subscribe(listener: (coStream: this) => void): () => void {
|
|
148
179
|
return this.core.subscribe((content) => {
|
|
149
|
-
listener(content as
|
|
180
|
+
listener(content as this);
|
|
150
181
|
});
|
|
151
182
|
}
|
|
152
183
|
|
|
153
|
-
edit(
|
|
154
|
-
changer: (editable: WriteableCoStream<T, Meta>) => void
|
|
155
|
-
): CoStream<T, Meta> {
|
|
184
|
+
edit(changer: (editable: WriteableCoStream<T, Meta>) => void): this {
|
|
156
185
|
const editable = new WriteableCoStream<T, Meta>(this.core);
|
|
157
186
|
changer(editable);
|
|
158
|
-
return new CoStream(this.core);
|
|
187
|
+
return new CoStream(this.core) as this;
|
|
159
188
|
}
|
|
160
189
|
}
|
|
161
190
|
|
|
@@ -165,12 +194,14 @@ export class BinaryCoStream<
|
|
|
165
194
|
Meta extends BinaryCoStreamMeta = { type: "binary" }
|
|
166
195
|
>
|
|
167
196
|
extends CoStream<BinaryStreamItem, Meta>
|
|
168
|
-
implements
|
|
197
|
+
implements CoValue
|
|
169
198
|
{
|
|
170
|
-
id!: CoID<
|
|
199
|
+
id!: CoID<this>;
|
|
171
200
|
|
|
172
|
-
getBinaryChunks(
|
|
173
|
-
|
|
201
|
+
getBinaryChunks(
|
|
202
|
+
allowUnfinished?: boolean
|
|
203
|
+
):
|
|
204
|
+
| (BinaryStreamInfo & { chunks: Uint8Array[]; finished: boolean })
|
|
174
205
|
| undefined {
|
|
175
206
|
// const before = performance.now();
|
|
176
207
|
const items = this.getSingleStream();
|
|
@@ -226,31 +257,33 @@ export class BinaryCoStream<
|
|
|
226
257
|
};
|
|
227
258
|
}
|
|
228
259
|
|
|
229
|
-
edit(
|
|
230
|
-
changer: (editable: WriteableBinaryCoStream<Meta>) => void
|
|
231
|
-
): BinaryCoStream<Meta> {
|
|
260
|
+
edit(changer: (editable: WriteableBinaryCoStream<Meta>) => void): this {
|
|
232
261
|
const editable = new WriteableBinaryCoStream<Meta>(this.core);
|
|
233
262
|
changer(editable);
|
|
234
|
-
return new BinaryCoStream(this.core);
|
|
263
|
+
return new BinaryCoStream(this.core) as this;
|
|
235
264
|
}
|
|
236
265
|
}
|
|
237
266
|
|
|
238
267
|
export class WriteableCoStream<
|
|
239
|
-
T extends JsonValue,
|
|
268
|
+
T extends JsonValue | CoValue,
|
|
240
269
|
Meta extends JsonObject | null = null
|
|
241
270
|
>
|
|
242
271
|
extends CoStream<T, Meta>
|
|
243
|
-
implements
|
|
272
|
+
implements CoValue
|
|
244
273
|
{
|
|
245
274
|
/** @internal */
|
|
246
|
-
edit(
|
|
247
|
-
_changer: (editable: WriteableCoStream<T, Meta>) => void
|
|
248
|
-
): CoStream<T, Meta> {
|
|
275
|
+
edit(_changer: (editable: WriteableCoStream<T, Meta>) => void): this {
|
|
249
276
|
throw new Error("Already editing.");
|
|
250
277
|
}
|
|
251
278
|
|
|
252
|
-
push(
|
|
253
|
-
|
|
279
|
+
push(
|
|
280
|
+
item: T extends CoValue ? T | CoID<T> : T,
|
|
281
|
+
privacy: "private" | "trusting" = "private"
|
|
282
|
+
) {
|
|
283
|
+
this.core.makeTransaction(
|
|
284
|
+
[isCoValue(item) ? item.id : item],
|
|
285
|
+
privacy
|
|
286
|
+
);
|
|
254
287
|
this.fillFromCoValue();
|
|
255
288
|
}
|
|
256
289
|
}
|
|
@@ -259,12 +292,10 @@ export class WriteableBinaryCoStream<
|
|
|
259
292
|
Meta extends BinaryCoStreamMeta = { type: "binary" }
|
|
260
293
|
>
|
|
261
294
|
extends BinaryCoStream<Meta>
|
|
262
|
-
implements
|
|
295
|
+
implements CoValue
|
|
263
296
|
{
|
|
264
297
|
/** @internal */
|
|
265
|
-
edit(
|
|
266
|
-
_changer: (editable: WriteableBinaryCoStream<Meta>) => void
|
|
267
|
-
): BinaryCoStream<Meta> {
|
|
298
|
+
edit(_changer: (editable: WriteableBinaryCoStream<Meta>) => void): this {
|
|
268
299
|
throw new Error("Already editing.");
|
|
269
300
|
}
|
|
270
301
|
|
|
@@ -274,7 +305,7 @@ export class WriteableBinaryCoStream<
|
|
|
274
305
|
}
|
|
275
306
|
|
|
276
307
|
startBinaryStream(
|
|
277
|
-
settings:
|
|
308
|
+
settings: BinaryStreamInfo,
|
|
278
309
|
privacy: "private" | "trusting" = "private"
|
|
279
310
|
) {
|
|
280
311
|
this.push(
|
package/src/coValues/static.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { JsonObject } from '../jsonValue.js';
|
|
2
|
-
import { CoID,
|
|
2
|
+
import { CoID, CoValue } from '../coValue.js';
|
|
3
3
|
import { CoValueCore } from '../coValueCore.js';
|
|
4
4
|
import { Group } from '../index.js';
|
|
5
5
|
|
|
6
|
-
export class Static<T extends JsonObject> implements
|
|
7
|
-
id: CoID<
|
|
6
|
+
export class Static<T extends JsonObject> implements CoValue{
|
|
7
|
+
id: CoID<this>;
|
|
8
8
|
type = "static" as const;
|
|
9
9
|
core: CoValueCore;
|
|
10
10
|
|
|
11
11
|
constructor(core: CoValueCore) {
|
|
12
|
-
this.id = core.id as CoID<
|
|
12
|
+
this.id = core.id as CoID<this>;
|
|
13
13
|
this.core = core;
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -25,7 +25,7 @@ export class Static<T extends JsonObject> implements ReadableCoValue{
|
|
|
25
25
|
throw new Error("Method not implemented.");
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
subscribe(_listener: (
|
|
28
|
+
subscribe(_listener: (st: this) => void): () => void {
|
|
29
29
|
throw new Error("Method not implemented.");
|
|
30
30
|
}
|
|
31
31
|
}
|