jazz-tools 0.7.0-alpha.9 → 0.7.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 +3 -10
- package/.prettierrc.js +9 -0
- package/.turbo/turbo-build.log +14 -15
- package/.turbo/turbo-lint.log +4 -0
- package/.turbo/turbo-test.log +140 -0
- package/CHANGELOG.md +331 -27
- package/LICENSE.txt +1 -1
- package/README.md +10 -2
- package/dist/coValues/account.js +86 -41
- package/dist/coValues/account.js.map +1 -1
- package/dist/coValues/coList.js +75 -48
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.js +167 -44
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.js +192 -35
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coValues/deepLoading.js +60 -0
- package/dist/coValues/deepLoading.js.map +1 -0
- package/dist/coValues/extensions/imageDef.js +10 -7
- package/dist/coValues/extensions/imageDef.js.map +1 -1
- package/dist/coValues/group.js +73 -13
- package/dist/coValues/group.js.map +1 -1
- package/dist/coValues/interfaces.js +58 -35
- package/dist/coValues/interfaces.js.map +1 -1
- package/dist/implementation/devtoolsFormatters.js +114 -0
- package/dist/implementation/devtoolsFormatters.js.map +1 -0
- package/dist/implementation/refs.js +58 -18
- package/dist/implementation/refs.js.map +1 -1
- package/dist/implementation/schema.js +58 -0
- package/dist/implementation/schema.js.map +1 -0
- package/dist/implementation/subscriptionScope.js +19 -1
- package/dist/implementation/subscriptionScope.js.map +1 -1
- package/dist/implementation/symbols.js +5 -0
- package/dist/implementation/symbols.js.map +1 -0
- package/dist/index.js +4 -5
- package/dist/index.js.map +1 -1
- package/dist/internal.js +5 -2
- package/dist/internal.js.map +1 -1
- package/dist/tests/coList.test.js +51 -48
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/coMap.test.js +131 -74
- package/dist/tests/coMap.test.js.map +1 -1
- package/dist/tests/coStream.test.js +56 -41
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/deepLoading.test.js +188 -0
- package/dist/tests/deepLoading.test.js.map +1 -0
- package/dist/tests/groupsAndAccounts.test.js +83 -0
- package/dist/tests/groupsAndAccounts.test.js.map +1 -0
- package/package.json +17 -9
- package/src/coValues/account.ts +186 -128
- package/src/coValues/coList.ts +156 -107
- package/src/coValues/coMap.ts +272 -148
- package/src/coValues/coStream.ts +388 -87
- package/src/coValues/deepLoading.ts +229 -0
- package/src/coValues/extensions/imageDef.ts +17 -13
- package/src/coValues/group.ts +166 -59
- package/src/coValues/interfaces.ts +189 -160
- package/src/implementation/devtoolsFormatters.ts +110 -0
- package/src/implementation/inspect.ts +1 -1
- package/src/implementation/refs.ts +80 -28
- package/src/implementation/schema.ts +141 -0
- package/src/implementation/subscriptionScope.ts +48 -12
- package/src/implementation/symbols.ts +11 -0
- package/src/index.ts +19 -8
- package/src/internal.ts +7 -3
- package/src/tests/coList.test.ts +77 -62
- package/src/tests/coMap.test.ts +201 -114
- package/src/tests/coStream.test.ts +113 -84
- package/src/tests/deepLoading.test.ts +304 -0
- package/src/tests/groupsAndAccounts.test.ts +91 -0
- package/dist/implementation/encoding.js +0 -26
- package/dist/implementation/encoding.js.map +0 -1
- package/src/implementation/encoding.ts +0 -105
package/src/coValues/coStream.ts
CHANGED
@@ -8,16 +8,20 @@ import type {
|
|
8
8
|
RawCoStream,
|
9
9
|
SessionID,
|
10
10
|
} from "cojson";
|
11
|
-
import { cojsonInternals } from "cojson";
|
11
|
+
import { MAX_RECOMMENDED_TX_SIZE, cojsonInternals } from "cojson";
|
12
12
|
import type {
|
13
13
|
CoValue,
|
14
|
-
|
15
|
-
|
16
|
-
EncodingFor,
|
14
|
+
Schema,
|
15
|
+
SchemaFor,
|
17
16
|
Group,
|
18
17
|
ID,
|
19
|
-
|
20
|
-
|
18
|
+
IfCo,
|
19
|
+
UnCo,
|
20
|
+
AccountCtx,
|
21
|
+
CoValueClass,
|
22
|
+
DeeplyLoaded,
|
23
|
+
DepthsIn,
|
24
|
+
UnavailableError,
|
21
25
|
} from "../internal.js";
|
22
26
|
import {
|
23
27
|
ItemsSym,
|
@@ -25,46 +29,56 @@ import {
|
|
25
29
|
CoValueBase,
|
26
30
|
Ref,
|
27
31
|
inspect,
|
28
|
-
|
32
|
+
co,
|
29
33
|
InitValues,
|
30
34
|
SchemaInit,
|
35
|
+
isRefEncoded,
|
36
|
+
loadCoValue,
|
37
|
+
loadCoValueEf,
|
38
|
+
subscribeToCoValue,
|
39
|
+
subscribeToCoValueEf,
|
40
|
+
ensureCoValueLoaded,
|
41
|
+
subscribeToExistingCoValue,
|
31
42
|
} from "../internal.js";
|
32
|
-
import {
|
43
|
+
import { encodeSync, decodeSync } from "@effect/schema/Schema";
|
44
|
+
import { Effect, Stream } from "effect";
|
33
45
|
|
34
|
-
export type CoStreamEntry<Item> = {
|
46
|
+
export type CoStreamEntry<Item> = SingleCoStreamEntry<Item> & {
|
47
|
+
all: IterableIterator<SingleCoStreamEntry<Item>>;
|
48
|
+
};
|
49
|
+
|
50
|
+
export type SingleCoStreamEntry<Item> = {
|
35
51
|
value: NonNullable<Item> extends CoValue ? NonNullable<Item> | null : Item;
|
36
|
-
ref
|
37
|
-
by?: Account;
|
52
|
+
ref: NonNullable<Item> extends CoValue ? Ref<NonNullable<Item>> : never;
|
53
|
+
by?: Account | null;
|
38
54
|
madeAt: Date;
|
39
55
|
tx: CojsonInternalTypes.TransactionID;
|
40
56
|
};
|
41
57
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
{
|
46
|
-
static Of<Item extends ValidItem<Item, "CoStream"> = any>(
|
47
|
-
item: IsVal<Item, Item>
|
48
|
-
): typeof CoStream<Item> {
|
58
|
+
/** @category CoValues */
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
60
|
+
export class CoStream<Item = any> extends CoValueBase implements CoValue {
|
61
|
+
static Of<Item>(item: IfCo<Item, Item>): typeof CoStream<Item> {
|
49
62
|
return class CoStreamOf extends CoStream<Item> {
|
50
|
-
[
|
63
|
+
[co.items] = item;
|
51
64
|
};
|
52
65
|
}
|
53
66
|
|
54
|
-
id
|
55
|
-
_type
|
67
|
+
declare id: ID<this>;
|
68
|
+
declare _type: "CoStream";
|
56
69
|
static {
|
57
70
|
this.prototype._type = "CoStream";
|
58
71
|
}
|
59
|
-
_raw
|
72
|
+
declare _raw: RawCoStream;
|
60
73
|
|
61
74
|
/** @internal This is only a marker type and doesn't exist at runtime */
|
62
75
|
[ItemsSym]!: Item;
|
63
|
-
|
64
|
-
|
65
|
-
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
77
|
+
static _schema: any;
|
78
|
+
get _schema(): {
|
79
|
+
[ItemsSym]: SchemaFor<Item>;
|
66
80
|
} {
|
67
|
-
return (this.constructor as typeof CoStream).
|
81
|
+
return (this.constructor as typeof CoStream)._schema;
|
68
82
|
}
|
69
83
|
|
70
84
|
[key: ID<Account>]: CoStreamEntry<Item>;
|
@@ -76,19 +90,16 @@ export class CoStream<Item extends ValidItem<Item, "CoStream"> = any>
|
|
76
90
|
[key: SessionID]: CoStreamEntry<Item>;
|
77
91
|
};
|
78
92
|
get inCurrentSession(): CoStreamEntry<Item> | undefined {
|
79
|
-
return this.perSession[this._loadedAs.sessionID];
|
93
|
+
return this.perSession[this._loadedAs.sessionID!];
|
80
94
|
}
|
81
95
|
|
82
|
-
|
83
|
-
|
84
|
-
owner: Account | Group;
|
85
|
-
};
|
96
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
97
|
+
[InitValues]?: any;
|
86
98
|
|
87
|
-
constructor(_init: undefined, options: { fromRaw: RawCoStream });
|
88
|
-
constructor(init: Item[], options: { owner: Account | Group });
|
89
99
|
constructor(
|
90
|
-
|
91
|
-
|
100
|
+
options:
|
101
|
+
| { init: Item[]; owner: Account | Group }
|
102
|
+
| { fromRaw: RawCoStream },
|
92
103
|
) {
|
93
104
|
super();
|
94
105
|
|
@@ -102,7 +113,7 @@ export class CoStream<Item extends ValidItem<Item, "CoStream"> = any>
|
|
102
113
|
});
|
103
114
|
} else {
|
104
115
|
this[InitValues] = {
|
105
|
-
init,
|
116
|
+
init: options.init,
|
106
117
|
owner: options.owner,
|
107
118
|
};
|
108
119
|
}
|
@@ -110,6 +121,14 @@ export class CoStream<Item extends ValidItem<Item, "CoStream"> = any>
|
|
110
121
|
return new Proxy(this, CoStreamProxyHandler as ProxyHandler<this>);
|
111
122
|
}
|
112
123
|
|
124
|
+
static create<S extends CoStream>(
|
125
|
+
this: CoValueClass<S>,
|
126
|
+
init: S extends CoStream<infer Item> ? UnCo<Item>[] : never,
|
127
|
+
options: { owner: Account | Group },
|
128
|
+
) {
|
129
|
+
return new this({ init, owner: options.owner });
|
130
|
+
}
|
131
|
+
|
113
132
|
push(...items: Item[]) {
|
114
133
|
for (const item of items) {
|
115
134
|
this.pushItem(item);
|
@@ -117,24 +136,24 @@ export class CoStream<Item extends ValidItem<Item, "CoStream"> = any>
|
|
117
136
|
}
|
118
137
|
|
119
138
|
private pushItem(item: Item) {
|
120
|
-
const itemDescriptor = this.
|
139
|
+
const itemDescriptor = this._schema[ItemsSym] as Schema;
|
121
140
|
|
122
141
|
if (itemDescriptor === "json") {
|
123
142
|
this._raw.push(item as JsonValue);
|
124
143
|
} else if ("encoded" in itemDescriptor) {
|
125
|
-
this._raw.push(
|
126
|
-
} else if (
|
144
|
+
this._raw.push(encodeSync(itemDescriptor.encoded)(item));
|
145
|
+
} else if (isRefEncoded(itemDescriptor)) {
|
127
146
|
this._raw.push((item as unknown as CoValue).id);
|
128
147
|
}
|
129
148
|
}
|
130
149
|
|
131
150
|
toJSON() {
|
132
|
-
const itemDescriptor = this.
|
151
|
+
const itemDescriptor = this._schema[ItemsSym] as Schema;
|
133
152
|
const mapper =
|
134
153
|
itemDescriptor === "json"
|
135
154
|
? (v: unknown) => v
|
136
155
|
: "encoded" in itemDescriptor
|
137
|
-
?
|
156
|
+
? encodeSync(itemDescriptor.encoded)
|
138
157
|
: (v: unknown) => v && (v as CoValue).id;
|
139
158
|
|
140
159
|
return {
|
@@ -144,13 +163,13 @@ export class CoStream<Item extends ValidItem<Item, "CoStream"> = any>
|
|
144
163
|
Object.entries(this).map(([account, entry]) => [
|
145
164
|
account,
|
146
165
|
mapper(entry.value),
|
147
|
-
])
|
166
|
+
]),
|
148
167
|
),
|
149
168
|
in: Object.fromEntries(
|
150
169
|
Object.entries(this.perSession).map(([session, entry]) => [
|
151
170
|
session,
|
152
171
|
mapper(entry.value),
|
153
|
-
])
|
172
|
+
]),
|
154
173
|
),
|
155
174
|
};
|
156
175
|
}
|
@@ -159,12 +178,69 @@ export class CoStream<Item extends ValidItem<Item, "CoStream"> = any>
|
|
159
178
|
return this.toJSON();
|
160
179
|
}
|
161
180
|
|
162
|
-
static
|
181
|
+
static schema<V extends CoStream>(
|
182
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
163
183
|
this: { new (...args: any): V } & typeof CoStream,
|
164
|
-
def: { [ItemsSym]: V["
|
184
|
+
def: { [ItemsSym]: V["_schema"][ItemsSym] },
|
165
185
|
) {
|
166
|
-
this.
|
167
|
-
Object.assign(this.
|
186
|
+
this._schema ||= {};
|
187
|
+
Object.assign(this._schema, def);
|
188
|
+
}
|
189
|
+
|
190
|
+
/** @category Subscription & Loading */
|
191
|
+
static load<S extends CoStream, Depth>(
|
192
|
+
this: CoValueClass<S>,
|
193
|
+
id: ID<S>,
|
194
|
+
as: Account,
|
195
|
+
depth: Depth & DepthsIn<S>,
|
196
|
+
): Promise<DeeplyLoaded<S, Depth> | undefined> {
|
197
|
+
return loadCoValue(this, id, as, depth);
|
198
|
+
}
|
199
|
+
|
200
|
+
/** @category Subscription & Loading */
|
201
|
+
static loadEf<S extends CoStream, Depth>(
|
202
|
+
this: CoValueClass<S>,
|
203
|
+
id: ID<S>,
|
204
|
+
depth: Depth & DepthsIn<S>,
|
205
|
+
): Effect.Effect<DeeplyLoaded<S, Depth>, UnavailableError, AccountCtx> {
|
206
|
+
return loadCoValueEf<S, Depth>(this, id, depth);
|
207
|
+
}
|
208
|
+
|
209
|
+
/** @category Subscription & Loading */
|
210
|
+
static subscribe<S extends CoStream, Depth>(
|
211
|
+
this: CoValueClass<S>,
|
212
|
+
id: ID<S>,
|
213
|
+
as: Account,
|
214
|
+
depth: Depth & DepthsIn<S>,
|
215
|
+
listener: (value: DeeplyLoaded<S, Depth>) => void,
|
216
|
+
): () => void {
|
217
|
+
return subscribeToCoValue<S, Depth>(this, id, as, depth, listener);
|
218
|
+
}
|
219
|
+
|
220
|
+
/** @category Subscription & Loading */
|
221
|
+
static subscribeEf<S extends CoStream, Depth>(
|
222
|
+
this: CoValueClass<S>,
|
223
|
+
id: ID<S>,
|
224
|
+
depth: Depth & DepthsIn<S>,
|
225
|
+
): Stream.Stream<DeeplyLoaded<S, Depth>, UnavailableError, AccountCtx> {
|
226
|
+
return subscribeToCoValueEf<S, Depth>(this, id, depth);
|
227
|
+
}
|
228
|
+
|
229
|
+
/** @category Subscription & Loading */
|
230
|
+
ensureLoaded<S extends CoStream, Depth>(
|
231
|
+
this: S,
|
232
|
+
depth: Depth & DepthsIn<S>,
|
233
|
+
): Promise<DeeplyLoaded<S, Depth> | undefined> {
|
234
|
+
return ensureCoValueLoaded(this, depth);
|
235
|
+
}
|
236
|
+
|
237
|
+
/** @category Subscription & Loading */
|
238
|
+
subscribe<S extends CoStream, Depth>(
|
239
|
+
this: S,
|
240
|
+
depth: Depth & DepthsIn<S>,
|
241
|
+
listener: (value: DeeplyLoaded<S, Depth>) => void,
|
242
|
+
): () => void {
|
243
|
+
return subscribeToExistingCoValue(this, depth, listener);
|
168
244
|
}
|
169
245
|
}
|
170
246
|
|
@@ -176,38 +252,64 @@ function entryFromRawEntry<Item>(
|
|
176
252
|
at: Date;
|
177
253
|
value: JsonValue;
|
178
254
|
},
|
179
|
-
loadedAs: Account
|
255
|
+
loadedAs: Account,
|
180
256
|
accountID: ID<Account> | undefined,
|
181
|
-
itemField:
|
182
|
-
) {
|
257
|
+
itemField: Schema,
|
258
|
+
): Omit<CoStreamEntry<Item>, "all"> {
|
183
259
|
return {
|
184
|
-
get value(): Item
|
260
|
+
get value(): NonNullable<Item> extends CoValue
|
261
|
+
? (CoValue & Item) | null
|
262
|
+
: Item {
|
185
263
|
if (itemField === "json") {
|
186
|
-
return rawEntry.value as Item
|
264
|
+
return rawEntry.value as NonNullable<Item> extends CoValue
|
265
|
+
? (CoValue & Item) | null
|
266
|
+
: Item;
|
187
267
|
} else if ("encoded" in itemField) {
|
188
|
-
return
|
189
|
-
} else if (
|
190
|
-
return this.ref?.accessFrom(
|
268
|
+
return decodeSync(itemField.encoded)(rawEntry.value);
|
269
|
+
} else if (isRefEncoded(itemField)) {
|
270
|
+
return this.ref?.accessFrom(
|
271
|
+
accessFrom,
|
272
|
+
rawEntry.by +
|
273
|
+
rawEntry.tx.sessionID +
|
274
|
+
rawEntry.tx.txIndex +
|
275
|
+
".value",
|
276
|
+
) as NonNullable<Item> extends CoValue
|
277
|
+
? (CoValue & Item) | null
|
278
|
+
: Item;
|
279
|
+
} else {
|
280
|
+
throw new Error("Invalid item field schema");
|
191
281
|
}
|
192
282
|
},
|
193
|
-
get ref()
|
194
|
-
|
283
|
+
get ref(): NonNullable<Item> extends CoValue
|
284
|
+
? Ref<NonNullable<Item>>
|
285
|
+
: never {
|
286
|
+
if (itemField !== "json" && isRefEncoded(itemField)) {
|
195
287
|
const rawId = rawEntry.value;
|
196
288
|
return new Ref(
|
197
289
|
rawId as unknown as ID<CoValue>,
|
198
290
|
loadedAs,
|
199
|
-
itemField
|
200
|
-
)
|
291
|
+
itemField,
|
292
|
+
) as NonNullable<Item> extends CoValue
|
293
|
+
? Ref<NonNullable<Item>>
|
294
|
+
: never;
|
295
|
+
} else {
|
296
|
+
return undefined as never;
|
201
297
|
}
|
202
298
|
},
|
203
299
|
get by() {
|
204
300
|
return (
|
205
301
|
accountID &&
|
206
|
-
new Ref(
|
302
|
+
new Ref<Account>(
|
207
303
|
accountID as unknown as ID<Account>,
|
208
304
|
loadedAs,
|
209
|
-
{ref:
|
210
|
-
)?.accessFrom(
|
305
|
+
{ ref: Account, optional: false },
|
306
|
+
)?.accessFrom(
|
307
|
+
accessFrom,
|
308
|
+
rawEntry.by +
|
309
|
+
rawEntry.tx.sessionID +
|
310
|
+
rawEntry.tx.txIndex +
|
311
|
+
".by",
|
312
|
+
)
|
211
313
|
);
|
212
314
|
},
|
213
315
|
madeAt: rawEntry.at,
|
@@ -242,15 +344,40 @@ export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
|
|
242
344
|
const rawEntry = target._raw.lastItemBy(key as AccountID);
|
243
345
|
|
244
346
|
if (!rawEntry) return;
|
245
|
-
|
347
|
+
const entry = entryFromRawEntry(
|
246
348
|
receiver,
|
247
349
|
rawEntry,
|
248
350
|
target._loadedAs,
|
249
351
|
key as unknown as ID<Account>,
|
250
|
-
target.
|
352
|
+
target._schema[ItemsSym],
|
251
353
|
);
|
354
|
+
|
355
|
+
Object.defineProperty(entry, "all", {
|
356
|
+
get: () => {
|
357
|
+
const allRawEntries = target._raw.itemsBy(key as AccountID);
|
358
|
+
return (function* () {
|
359
|
+
while (true) {
|
360
|
+
const rawEntry = allRawEntries.next();
|
361
|
+
if (rawEntry.done) return;
|
362
|
+
yield entryFromRawEntry(
|
363
|
+
receiver,
|
364
|
+
rawEntry.value,
|
365
|
+
target._loadedAs,
|
366
|
+
key as unknown as ID<Account>,
|
367
|
+
target._schema[ItemsSym],
|
368
|
+
);
|
369
|
+
}
|
370
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
371
|
+
})() satisfies IterableIterator<SingleCoStreamEntry<any>>;
|
372
|
+
},
|
373
|
+
});
|
374
|
+
|
375
|
+
return entry;
|
252
376
|
} else if (key === "perSession") {
|
253
|
-
return new Proxy(
|
377
|
+
return new Proxy(
|
378
|
+
{},
|
379
|
+
CoStreamPerSessionProxyHandler(target, receiver),
|
380
|
+
);
|
254
381
|
} else {
|
255
382
|
return Reflect.get(target, key, receiver);
|
256
383
|
}
|
@@ -261,8 +388,8 @@ export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
|
|
261
388
|
typeof value === "object" &&
|
262
389
|
SchemaInit in value
|
263
390
|
) {
|
264
|
-
(target.constructor as typeof CoStream).
|
265
|
-
(target.constructor as typeof CoStream).
|
391
|
+
(target.constructor as typeof CoStream)._schema ||= {};
|
392
|
+
(target.constructor as typeof CoStream)._schema[ItemsSym] =
|
266
393
|
value[SchemaInit];
|
267
394
|
init(target);
|
268
395
|
return true;
|
@@ -277,8 +404,8 @@ export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
|
|
277
404
|
typeof descriptor.value === "object" &&
|
278
405
|
SchemaInit in descriptor.value
|
279
406
|
) {
|
280
|
-
(target.constructor as typeof CoStream).
|
281
|
-
(target.constructor as typeof CoStream).
|
407
|
+
(target.constructor as typeof CoStream)._schema ||= {};
|
408
|
+
(target.constructor as typeof CoStream)._schema[ItemsSym] =
|
282
409
|
descriptor.value[SchemaInit];
|
283
410
|
init(target);
|
284
411
|
return true;
|
@@ -308,46 +435,85 @@ export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
|
|
308
435
|
},
|
309
436
|
};
|
310
437
|
|
311
|
-
const CoStreamPerSessionProxyHandler
|
312
|
-
|
438
|
+
const CoStreamPerSessionProxyHandler = (
|
439
|
+
innerTarget: CoStream,
|
440
|
+
accessFrom: CoStream,
|
441
|
+
): ProxyHandler<Record<string, never>> => ({
|
442
|
+
get(_target, key, receiver) {
|
313
443
|
if (typeof key === "string" && key.includes("session")) {
|
314
444
|
const sessionID = key as SessionID;
|
315
|
-
const rawEntry =
|
445
|
+
const rawEntry = innerTarget._raw.lastItemIn(sessionID);
|
316
446
|
|
317
447
|
if (!rawEntry) return;
|
318
448
|
const by = cojsonInternals.accountOrAgentIDfromSessionID(sessionID);
|
319
|
-
|
320
|
-
|
449
|
+
|
450
|
+
const entry = entryFromRawEntry(
|
451
|
+
accessFrom,
|
321
452
|
rawEntry,
|
322
|
-
|
453
|
+
innerTarget._loadedAs,
|
323
454
|
cojsonInternals.isAccountID(by)
|
324
455
|
? (by as unknown as ID<Account>)
|
325
456
|
: undefined,
|
326
|
-
|
457
|
+
innerTarget._schema[ItemsSym],
|
327
458
|
);
|
459
|
+
|
460
|
+
Object.defineProperty(entry, "all", {
|
461
|
+
get: () => {
|
462
|
+
const allRawEntries = innerTarget._raw.itemsIn(sessionID);
|
463
|
+
return (function* () {
|
464
|
+
while (true) {
|
465
|
+
const rawEntry = allRawEntries.next();
|
466
|
+
if (rawEntry.done) return;
|
467
|
+
yield entryFromRawEntry(
|
468
|
+
accessFrom,
|
469
|
+
rawEntry.value,
|
470
|
+
innerTarget._loadedAs,
|
471
|
+
cojsonInternals.isAccountID(by)
|
472
|
+
? (by as unknown as ID<Account>)
|
473
|
+
: undefined,
|
474
|
+
innerTarget._schema[ItemsSym],
|
475
|
+
);
|
476
|
+
}
|
477
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
478
|
+
})() satisfies IterableIterator<SingleCoStreamEntry<any>>;
|
479
|
+
},
|
480
|
+
});
|
481
|
+
|
482
|
+
return entry;
|
328
483
|
} else {
|
329
|
-
return Reflect.get(
|
484
|
+
return Reflect.get(innerTarget, key, receiver);
|
330
485
|
}
|
331
486
|
},
|
332
|
-
|
487
|
+
ownKeys() {
|
488
|
+
return innerTarget._raw.sessions();
|
489
|
+
},
|
490
|
+
getOwnPropertyDescriptor(target, key) {
|
491
|
+
if (typeof key === "string" && key.startsWith("co_")) {
|
492
|
+
return {
|
493
|
+
configurable: true,
|
494
|
+
enumerable: true,
|
495
|
+
writable: false,
|
496
|
+
};
|
497
|
+
} else {
|
498
|
+
return Reflect.getOwnPropertyDescriptor(target, key);
|
499
|
+
}
|
500
|
+
},
|
501
|
+
});
|
333
502
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
_type!: "BinaryCoStream";
|
340
|
-
_raw!: RawBinaryCoStream;
|
503
|
+
/** @category CoValues */
|
504
|
+
export class BinaryCoStream extends CoValueBase implements CoValue {
|
505
|
+
declare id: ID<this>;
|
506
|
+
declare _type: "BinaryCoStream";
|
507
|
+
declare _raw: RawBinaryCoStream;
|
341
508
|
|
342
509
|
constructor(
|
343
|
-
init: [] | undefined,
|
344
510
|
options:
|
345
511
|
| {
|
346
512
|
owner: Account | Group;
|
347
513
|
}
|
348
514
|
| {
|
349
515
|
fromRaw: RawBinaryCoStream;
|
350
|
-
}
|
516
|
+
},
|
351
517
|
) {
|
352
518
|
super();
|
353
519
|
|
@@ -365,10 +531,18 @@ export class BinaryCoStream
|
|
365
531
|
value: raw.id,
|
366
532
|
enumerable: false,
|
367
533
|
},
|
534
|
+
_type: { value: "BinaryCoStream", enumerable: false },
|
368
535
|
_raw: { value: raw, enumerable: false },
|
369
536
|
});
|
370
537
|
}
|
371
538
|
|
539
|
+
static create<S extends BinaryCoStream>(
|
540
|
+
this: CoValueClass<S>,
|
541
|
+
options: { owner: Account | Group },
|
542
|
+
) {
|
543
|
+
return new this(options);
|
544
|
+
}
|
545
|
+
|
372
546
|
getChunks(options?: {
|
373
547
|
allowUnfinished?: boolean;
|
374
548
|
}):
|
@@ -389,6 +563,77 @@ export class BinaryCoStream
|
|
389
563
|
this._raw.endBinaryStream();
|
390
564
|
}
|
391
565
|
|
566
|
+
toBlob(options?: { allowUnfinished?: boolean }): Blob | undefined {
|
567
|
+
const chunks = this.getChunks({
|
568
|
+
allowUnfinished: options?.allowUnfinished,
|
569
|
+
});
|
570
|
+
|
571
|
+
if (!chunks) {
|
572
|
+
return undefined;
|
573
|
+
}
|
574
|
+
|
575
|
+
return new Blob(chunks.chunks, { type: chunks.mimeType });
|
576
|
+
}
|
577
|
+
|
578
|
+
static async loadAsBlob(
|
579
|
+
id: ID<BinaryCoStream>,
|
580
|
+
as: Account,
|
581
|
+
options?: {
|
582
|
+
allowUnfinished?: boolean;
|
583
|
+
},
|
584
|
+
): Promise<Blob | undefined> {
|
585
|
+
const stream = await this.load(id, as, []);
|
586
|
+
|
587
|
+
return stream?.toBlob({
|
588
|
+
allowUnfinished: options?.allowUnfinished,
|
589
|
+
});
|
590
|
+
}
|
591
|
+
|
592
|
+
static async createFromBlob(
|
593
|
+
blob: Blob | File,
|
594
|
+
options: {
|
595
|
+
owner: Group | Account;
|
596
|
+
onProgress?: (progress: number) => void;
|
597
|
+
},
|
598
|
+
): Promise<BinaryCoStream> {
|
599
|
+
const stream = this.create({ owner: options.owner });
|
600
|
+
|
601
|
+
const start = Date.now();
|
602
|
+
|
603
|
+
const data = new Uint8Array(await blob.arrayBuffer());
|
604
|
+
stream.start({
|
605
|
+
mimeType: blob.type,
|
606
|
+
totalSizeBytes: blob.size,
|
607
|
+
fileName: blob instanceof File ? blob.name : undefined,
|
608
|
+
});
|
609
|
+
const chunkSize = MAX_RECOMMENDED_TX_SIZE;
|
610
|
+
|
611
|
+
let lastProgressUpdate = Date.now();
|
612
|
+
|
613
|
+
for (let idx = 0; idx < data.length; idx += chunkSize) {
|
614
|
+
stream.push(data.slice(idx, idx + chunkSize));
|
615
|
+
|
616
|
+
if (Date.now() - lastProgressUpdate > 100) {
|
617
|
+
options.onProgress?.(idx / data.length);
|
618
|
+
lastProgressUpdate = Date.now();
|
619
|
+
}
|
620
|
+
|
621
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
622
|
+
}
|
623
|
+
stream.end();
|
624
|
+
const end = Date.now();
|
625
|
+
|
626
|
+
console.debug(
|
627
|
+
"Finished creating binary stream in",
|
628
|
+
(end - start) / 1000,
|
629
|
+
"s - Throughput in MB/s",
|
630
|
+
(1000 * (blob.size / (end - start))) / (1024 * 1024),
|
631
|
+
);
|
632
|
+
options.onProgress?.(1);
|
633
|
+
|
634
|
+
return stream;
|
635
|
+
}
|
636
|
+
|
392
637
|
toJSON() {
|
393
638
|
return {
|
394
639
|
id: this.id,
|
@@ -400,4 +645,60 @@ export class BinaryCoStream
|
|
400
645
|
[inspect]() {
|
401
646
|
return this.toJSON();
|
402
647
|
}
|
648
|
+
|
649
|
+
/** @category Subscription & Loading */
|
650
|
+
static load<B extends BinaryCoStream, Depth>(
|
651
|
+
this: CoValueClass<B>,
|
652
|
+
id: ID<B>,
|
653
|
+
as: Account,
|
654
|
+
depth: Depth & DepthsIn<B>,
|
655
|
+
): Promise<DeeplyLoaded<B, Depth> | undefined> {
|
656
|
+
return loadCoValue(this, id, as, depth);
|
657
|
+
}
|
658
|
+
|
659
|
+
/** @category Subscription & Loading */
|
660
|
+
static loadEf<B extends BinaryCoStream, Depth>(
|
661
|
+
this: CoValueClass<B>,
|
662
|
+
id: ID<B>,
|
663
|
+
depth: Depth & DepthsIn<B>,
|
664
|
+
): Effect.Effect<DeeplyLoaded<B, Depth>, UnavailableError, AccountCtx> {
|
665
|
+
return loadCoValueEf<B, Depth>(this, id, depth);
|
666
|
+
}
|
667
|
+
|
668
|
+
/** @category Subscription & Loading */
|
669
|
+
static subscribe<B extends BinaryCoStream, Depth>(
|
670
|
+
this: CoValueClass<B>,
|
671
|
+
id: ID<B>,
|
672
|
+
as: Account,
|
673
|
+
depth: Depth & DepthsIn<B>,
|
674
|
+
listener: (value: DeeplyLoaded<B, Depth>) => void,
|
675
|
+
): () => void {
|
676
|
+
return subscribeToCoValue<B, Depth>(this, id, as, depth, listener);
|
677
|
+
}
|
678
|
+
|
679
|
+
/** @category Subscription & Loading */
|
680
|
+
static subscribeEf<B extends BinaryCoStream, Depth>(
|
681
|
+
this: CoValueClass<B>,
|
682
|
+
id: ID<B>,
|
683
|
+
depth: Depth & DepthsIn<B>,
|
684
|
+
): Stream.Stream<DeeplyLoaded<B, Depth>, UnavailableError, AccountCtx> {
|
685
|
+
return subscribeToCoValueEf<B, Depth>(this, id, depth);
|
686
|
+
}
|
687
|
+
|
688
|
+
/** @category Subscription & Loading */
|
689
|
+
ensureLoaded<B extends BinaryCoStream, Depth>(
|
690
|
+
this: B,
|
691
|
+
depth: Depth & DepthsIn<B>,
|
692
|
+
): Promise<DeeplyLoaded<B, Depth> | undefined> {
|
693
|
+
return ensureCoValueLoaded(this, depth);
|
694
|
+
}
|
695
|
+
|
696
|
+
/** @category Subscription & Loading */
|
697
|
+
subscribe<B extends BinaryCoStream, Depth>(
|
698
|
+
this: B,
|
699
|
+
depth: Depth & DepthsIn<B>,
|
700
|
+
listener: (value: DeeplyLoaded<B, Depth>) => void,
|
701
|
+
): () => void {
|
702
|
+
return subscribeToExistingCoValue(this, depth, listener);
|
703
|
+
}
|
403
704
|
}
|