jazz-tools 0.7.0-alpha.30 → 0.7.0-alpha.32
Sign up to get free protection for your applications and to get access to all the features.
- package/.turbo/turbo-build.log +55 -57
- package/CHANGELOG.md +13 -0
- package/dist/cli/index.js +46 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/coValues/account.js +9 -6
- package/dist/coValues/account.js.map +1 -1
- package/dist/coValues/coList.js +10 -7
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.js +57 -3
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.js +55 -4
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coValues/extensions/imageDef.js +1 -0
- package/dist/coValues/extensions/imageDef.js.map +1 -1
- package/dist/coValues/group.js +8 -2
- package/dist/coValues/group.js.map +1 -1
- package/dist/coValues/interfaces.js +10 -1
- package/dist/coValues/interfaces.js.map +1 -1
- package/dist/implementation/schema.js +3 -1
- package/dist/implementation/schema.js.map +1 -1
- package/dist/implementation/subscriptionScope.js.map +1 -1
- package/dist/tests/coList.test.js +13 -13
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/coMap.test.js +22 -22
- package/dist/tests/coMap.test.js.map +1 -1
- package/dist/tests/coStream.test.js +9 -9
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/groupsAndAccounts.test.js +6 -4
- package/dist/tests/groupsAndAccounts.test.js.map +1 -1
- package/package.json +14 -8
- package/src/cli/index.ts +69 -0
- package/src/coValues/account.ts +29 -42
- package/src/coValues/coList.ts +24 -17
- package/src/coValues/coMap.ts +73 -20
- package/src/coValues/coStream.ts +110 -18
- package/src/coValues/extensions/imageDef.ts +2 -1
- package/src/coValues/group.ts +34 -48
- package/src/coValues/interfaces.ts +30 -20
- package/src/implementation/schema.ts +5 -1
- package/src/implementation/subscriptionScope.ts +2 -2
- package/src/tests/coList.test.ts +16 -16
- package/src/tests/coMap.test.ts +35 -35
- package/src/tests/coStream.test.ts +11 -11
- package/src/tests/groupsAndAccounts.test.ts +13 -9
package/src/coValues/coList.ts
CHANGED
@@ -8,9 +8,10 @@ import type {
|
|
8
8
|
SchemaFor,
|
9
9
|
ID,
|
10
10
|
RefEncoded,
|
11
|
-
|
11
|
+
ClassOf,
|
12
12
|
UnavailableError,
|
13
13
|
IfCo,
|
14
|
+
UnCo,
|
14
15
|
} from "../internal.js";
|
15
16
|
import {
|
16
17
|
Account,
|
@@ -27,11 +28,13 @@ import {
|
|
27
28
|
} from "../internal.js";
|
28
29
|
import { encodeSync, decodeSync } from "@effect/schema/Schema";
|
29
30
|
|
31
|
+
/** @category CoValues */
|
30
32
|
export class CoList<Item = any>
|
31
33
|
extends Array<Item>
|
32
34
|
implements CoValue<"CoList", RawCoList>
|
33
35
|
{
|
34
36
|
static Of<Item>(item: IfCo<Item, Item>): typeof CoList<Item> {
|
37
|
+
// TODO: cache superclass for item class
|
35
38
|
return class CoListOf extends CoList<Item> {
|
36
39
|
[co.items] = item;
|
37
40
|
};
|
@@ -64,6 +67,7 @@ export class CoList<Item = any>
|
|
64
67
|
: Group.fromRaw(this._raw.group);
|
65
68
|
}
|
66
69
|
|
70
|
+
/** @category Content */
|
67
71
|
get _refs(): {
|
68
72
|
[idx: number]: NonNullable<Item> extends CoValue
|
69
73
|
? Ref<NonNullable<Item>>
|
@@ -107,21 +111,16 @@ export class CoList<Item = any>
|
|
107
111
|
return Array;
|
108
112
|
}
|
109
113
|
|
110
|
-
constructor(_init: undefined, options: { fromRaw: RawCoList });
|
111
|
-
constructor(init: Item[], options: { owner: Account | Group });
|
112
114
|
constructor(
|
113
|
-
|
114
|
-
|
115
|
+
options:
|
116
|
+
| { init: Item[]; owner: Account | Group }
|
117
|
+
| { fromRaw: RawCoList }
|
115
118
|
) {
|
116
119
|
super();
|
117
120
|
|
118
|
-
if (
|
119
|
-
throw new Error("Must provide options");
|
120
|
-
}
|
121
|
-
|
122
|
-
if (init && "owner" in options) {
|
121
|
+
if ("owner" in options) {
|
123
122
|
this[InitValues] = {
|
124
|
-
init,
|
123
|
+
init: options.init,
|
125
124
|
owner: options.owner,
|
126
125
|
};
|
127
126
|
} else if ("fromRaw" in options) {
|
@@ -137,6 +136,14 @@ export class CoList<Item = any>
|
|
137
136
|
return new Proxy(this, CoListProxyHandler as ProxyHandler<this>);
|
138
137
|
}
|
139
138
|
|
139
|
+
static create<L extends CoList>(
|
140
|
+
this: ClassOf<L>,
|
141
|
+
items: UnCo<L[number]>[],
|
142
|
+
options: {owner: Account | Group}
|
143
|
+
) {
|
144
|
+
return new this({ init: items, owner: options.owner });
|
145
|
+
}
|
146
|
+
|
140
147
|
push(...items: Item[]): number;
|
141
148
|
/** @private For exact type compatibility with Array superclass */
|
142
149
|
push(...items: Item[]): number;
|
@@ -235,29 +242,29 @@ export class CoList<Item = any>
|
|
235
242
|
}
|
236
243
|
|
237
244
|
static fromRaw<V extends CoList>(
|
238
|
-
this:
|
245
|
+
this: ClassOf<V> & typeof CoList,
|
239
246
|
raw: RawCoList
|
240
247
|
) {
|
241
|
-
return new this(
|
248
|
+
return new this({ fromRaw: raw });
|
242
249
|
}
|
243
250
|
|
244
251
|
static loadEf = CoValueBase.loadEf as unknown as <V extends CoValue>(
|
245
|
-
this:
|
252
|
+
this: ClassOf<V>,
|
246
253
|
id: ID<V>
|
247
254
|
) => Effect.Effect<V, UnavailableError, AccountCtx>;
|
248
255
|
static load = CoValueBase.load as unknown as <V extends CoValue>(
|
249
|
-
this:
|
256
|
+
this: ClassOf<V>,
|
250
257
|
id: ID<V>,
|
251
258
|
options: { as: Account | Group }
|
252
259
|
) => Promise<V | undefined>;
|
253
260
|
static subscribeEf = CoValueBase.subscribeEf as unknown as <
|
254
261
|
V extends CoValue,
|
255
262
|
>(
|
256
|
-
this:
|
263
|
+
this: ClassOf<V>,
|
257
264
|
id: ID<V>
|
258
265
|
) => Stream.Stream<V, UnavailableError, AccountCtx>;
|
259
266
|
static subscribe = CoValueBase.subscribe as unknown as <V extends CoValue>(
|
260
|
-
this:
|
267
|
+
this: ClassOf<V>,
|
261
268
|
id: ID<V>,
|
262
269
|
options: { as: Account | Group },
|
263
270
|
onUpdate: (value: V) => void
|
package/src/coValues/coMap.ts
CHANGED
@@ -9,6 +9,7 @@ import type {
|
|
9
9
|
RefEncoded,
|
10
10
|
IfCo,
|
11
11
|
RefIfCoValue,
|
12
|
+
ClassOf,
|
12
13
|
} from "../internal.js";
|
13
14
|
import {
|
14
15
|
Account,
|
@@ -23,11 +24,6 @@ import {
|
|
23
24
|
isRefEncoded,
|
24
25
|
} from "../internal.js";
|
25
26
|
|
26
|
-
type DefaultFields = {
|
27
|
-
[key: string]: any;
|
28
|
-
[ItemsSym]?: any;
|
29
|
-
};
|
30
|
-
|
31
27
|
type CoMapEdit<V> = {
|
32
28
|
value?: V;
|
33
29
|
ref?: RefIfCoValue<V>;
|
@@ -40,24 +36,72 @@ type InitValuesFor<C extends CoMap> = {
|
|
40
36
|
owner: Account | Group;
|
41
37
|
};
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
/**
|
40
|
+
* CoMaps are collaborative versions of plain objects, mapping string-like keys to values.
|
41
|
+
*
|
42
|
+
* @categoryDescription Declaration
|
43
|
+
* Declare your own CoMap schemas by subclassing `CoMap` and assigning field schemas with `co`.
|
44
|
+
*
|
45
|
+
* ```ts
|
46
|
+
* import { co, CoMap } from "jazz-tools";
|
47
|
+
*
|
48
|
+
* class Person extends CoMap {
|
49
|
+
* name = co.string;
|
50
|
+
* age = co.number;
|
51
|
+
* pet = co.ref(Animal);
|
52
|
+
* }
|
53
|
+
* ```
|
54
|
+
*
|
55
|
+
* @categoryDescription Content
|
56
|
+
* You can access properties you declare on a `CoMap` (using `co`) as if they were normal properties on a plain object, using dot notation, `Object.keys()`, etc.
|
57
|
+
*
|
58
|
+
* ```ts
|
59
|
+
* person.name;
|
60
|
+
* person["age"];
|
61
|
+
* person.age = 42;
|
62
|
+
* person.pet?.name;
|
63
|
+
* Object.keys(person);
|
64
|
+
* // => ["name", "age", "pet"]
|
65
|
+
* ```
|
66
|
+
*
|
67
|
+
* @category CoValues
|
68
|
+
* */
|
69
|
+
export class CoMap extends CoValueBase implements CoValue<"CoMap", RawCoMap> {
|
70
|
+
/**
|
71
|
+
* The ID of this `CoMap`
|
72
|
+
* @category Content */
|
47
73
|
declare id: ID<this>;
|
74
|
+
/** @category Type Helpers */
|
48
75
|
declare _type: "CoMap";
|
49
76
|
static {
|
50
77
|
this.prototype._type = "CoMap";
|
51
78
|
}
|
79
|
+
/** @category Internals */
|
52
80
|
declare _raw: RawCoMap;
|
53
81
|
|
82
|
+
/** @internal */
|
54
83
|
static _schema: any;
|
84
|
+
/** @internal */
|
55
85
|
get _schema() {
|
56
86
|
return (this.constructor as typeof CoMap)._schema as {
|
57
87
|
[key: string]: Schema;
|
58
88
|
} & { [ItemsSym]?: Schema };
|
59
89
|
}
|
60
90
|
|
91
|
+
/**
|
92
|
+
* If property `prop` is a `co.ref(...)`, you can use `coMaps._refs.prop` to access
|
93
|
+
* the `Ref` instead of the potentially loaded/null value.
|
94
|
+
* This allows you to always get the ID or load the value manually.
|
95
|
+
*
|
96
|
+
* @example
|
97
|
+
* ```ts
|
98
|
+
* person._refs.pet.id; // => ID<Animal>
|
99
|
+
* person._refs.pet.value;
|
100
|
+
* // => Animal | undefined
|
101
|
+
* const pet = await person._refs.pet.load();
|
102
|
+
* ```
|
103
|
+
*
|
104
|
+
* @category Content */
|
61
105
|
get _refs(): {
|
62
106
|
[Key in CoKeys<this>]: IfCo<this[Key], RefIfCoValue<this[Key]>>;
|
63
107
|
} {
|
@@ -80,6 +124,7 @@ export class CoMap<Fields extends object = DefaultFields>
|
|
80
124
|
) as any;
|
81
125
|
}
|
82
126
|
|
127
|
+
/** @category Collaboration */
|
83
128
|
get _edits() {
|
84
129
|
return new Proxy(this, {
|
85
130
|
get(target, key) {
|
@@ -124,26 +169,23 @@ export class CoMap<Fields extends object = DefaultFields>
|
|
124
169
|
};
|
125
170
|
}
|
126
171
|
|
172
|
+
/** @internal */
|
127
173
|
get _loadedAs() {
|
128
174
|
return Account.fromNode(this._raw.core.node);
|
129
175
|
}
|
130
176
|
|
177
|
+
/** @internal */
|
131
178
|
[InitValues]?: any;
|
132
179
|
|
133
|
-
|
180
|
+
/** @internal */
|
134
181
|
constructor(
|
135
|
-
init:
|
136
|
-
options: { owner: Account | Group }
|
137
|
-
);
|
138
|
-
constructor(
|
139
|
-
init: Simplify<CoMapInit<Fields>> | undefined,
|
140
|
-
options: { owner: Account | Group } | { fromRaw: RawCoMap }
|
182
|
+
options: { fromRaw: RawCoMap } | { init: any; owner: Account | Group }
|
141
183
|
) {
|
142
184
|
super();
|
143
185
|
|
144
|
-
if (
|
186
|
+
if ("owner" in options) {
|
145
187
|
this[InitValues] = {
|
146
|
-
init,
|
188
|
+
init: options.init,
|
147
189
|
owner: options.owner,
|
148
190
|
} as InitValuesFor<this>;
|
149
191
|
} else if ("fromRaw" in options) {
|
@@ -161,6 +203,15 @@ export class CoMap<Fields extends object = DefaultFields>
|
|
161
203
|
return new Proxy(this, CoMapProxyHandler as ProxyHandler<this>);
|
162
204
|
}
|
163
205
|
|
206
|
+
/** @category Creation */
|
207
|
+
static create<M extends CoMap>(
|
208
|
+
this: ClassOf<M>,
|
209
|
+
init: Simplify<CoMapInit<M>>,
|
210
|
+
options: { owner: Account | Group }
|
211
|
+
) {
|
212
|
+
return new this({ init, owner: options.owner });
|
213
|
+
}
|
214
|
+
|
164
215
|
toJSON() {
|
165
216
|
const jsonedFields = this._raw.keys().map((key) => {
|
166
217
|
const tKey = key as CoKeys<this>;
|
@@ -188,6 +239,7 @@ export class CoMap<Fields extends object = DefaultFields>
|
|
188
239
|
return this.toJSON();
|
189
240
|
}
|
190
241
|
|
242
|
+
/** @internal */
|
191
243
|
rawFromInit<Fields extends object = Record<string, any>>(
|
192
244
|
init: Simplify<CoMapInit<Fields>> | undefined,
|
193
245
|
owner: Account | Group
|
@@ -222,9 +274,10 @@ export class CoMap<Fields extends object = DefaultFields>
|
|
222
274
|
return rawOwner.createMap(rawInit);
|
223
275
|
}
|
224
276
|
|
277
|
+
/** @category Declaration */
|
225
278
|
static Record<Value>(value: IfCo<Value, Value>) {
|
226
279
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
227
|
-
class RecordLikeCoMap extends CoMap
|
280
|
+
class RecordLikeCoMap extends CoMap {
|
228
281
|
[ItemsSym] = value;
|
229
282
|
}
|
230
283
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
@@ -236,7 +289,7 @@ export class CoMap<Fields extends object = DefaultFields>
|
|
236
289
|
|
237
290
|
export type CoKeys<Fields extends object> = Exclude<
|
238
291
|
keyof Fields & string,
|
239
|
-
keyof CoMap
|
292
|
+
keyof CoMap
|
240
293
|
>;
|
241
294
|
|
242
295
|
export type CoMapInit<Fields extends object> = {
|
package/src/coValues/coStream.ts
CHANGED
@@ -8,7 +8,7 @@ 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
14
|
Schema,
|
@@ -17,6 +17,8 @@ import type {
|
|
17
17
|
ID,
|
18
18
|
Me,
|
19
19
|
IfCo,
|
20
|
+
ClassOf,
|
21
|
+
UnCo,
|
20
22
|
} from "../internal.js";
|
21
23
|
import {
|
22
24
|
ItemsSym,
|
@@ -43,13 +45,12 @@ export type SingleCoStreamEntry<Item> = {
|
|
43
45
|
tx: CojsonInternalTypes.TransactionID;
|
44
46
|
};
|
45
47
|
|
48
|
+
/** @category CoValues */
|
46
49
|
export class CoStream<Item = any>
|
47
50
|
extends CoValueBase
|
48
51
|
implements CoValue<"CoStream", RawCoStream>
|
49
52
|
{
|
50
|
-
static Of<Item>(
|
51
|
-
item: IfCo<Item, Item>
|
52
|
-
): typeof CoStream<Item> {
|
53
|
+
static Of<Item>(item: IfCo<Item, Item>): typeof CoStream<Item> {
|
53
54
|
return class CoStreamOf extends CoStream<Item> {
|
54
55
|
[co.items] = item;
|
55
56
|
};
|
@@ -85,11 +86,10 @@ export class CoStream<Item = any>
|
|
85
86
|
|
86
87
|
[InitValues]?: any;
|
87
88
|
|
88
|
-
constructor(_init: undefined, options: { fromRaw: RawCoStream });
|
89
|
-
constructor(init: Item[], options: { owner: Account | Group });
|
90
89
|
constructor(
|
91
|
-
|
92
|
-
|
90
|
+
options:
|
91
|
+
| { init: Item[]; owner: Account | Group }
|
92
|
+
| { fromRaw: RawCoStream }
|
93
93
|
) {
|
94
94
|
super();
|
95
95
|
|
@@ -103,7 +103,7 @@ export class CoStream<Item = any>
|
|
103
103
|
});
|
104
104
|
} else {
|
105
105
|
this[InitValues] = {
|
106
|
-
init,
|
106
|
+
init: options.init,
|
107
107
|
owner: options.owner,
|
108
108
|
};
|
109
109
|
}
|
@@ -111,6 +111,14 @@ export class CoStream<Item = any>
|
|
111
111
|
return new Proxy(this, CoStreamProxyHandler as ProxyHandler<this>);
|
112
112
|
}
|
113
113
|
|
114
|
+
static create<S extends CoStream>(
|
115
|
+
this: ClassOf<S>,
|
116
|
+
init: S extends CoStream<infer Item> ? UnCo<Item>[] : never,
|
117
|
+
options: { owner: Account | Group }
|
118
|
+
) {
|
119
|
+
return new this({ init, owner: options.owner });
|
120
|
+
}
|
121
|
+
|
114
122
|
push(...items: Item[]) {
|
115
123
|
for (const item of items) {
|
116
124
|
this.pushItem(item);
|
@@ -123,9 +131,7 @@ export class CoStream<Item = any>
|
|
123
131
|
if (itemDescriptor === "json") {
|
124
132
|
this._raw.push(item as JsonValue);
|
125
133
|
} else if ("encoded" in itemDescriptor) {
|
126
|
-
this._raw.push(
|
127
|
-
encodeSync(itemDescriptor.encoded)(item)
|
128
|
-
);
|
134
|
+
this._raw.push(encodeSync(itemDescriptor.encoded)(item));
|
129
135
|
} else if (isRefEncoded(itemDescriptor)) {
|
130
136
|
this._raw.push((item as unknown as CoValue).id);
|
131
137
|
}
|
@@ -192,9 +198,7 @@ function entryFromRawEntry<Item>(
|
|
192
198
|
? (CoValue & Item) | null
|
193
199
|
: Item;
|
194
200
|
} else if ("encoded" in itemField) {
|
195
|
-
return decodeSync(itemField.encoded)(
|
196
|
-
rawEntry.value
|
197
|
-
);
|
201
|
+
return decodeSync(itemField.encoded)(rawEntry.value);
|
198
202
|
} else if (isRefEncoded(itemField)) {
|
199
203
|
return this.ref?.accessFrom(
|
200
204
|
accessFrom
|
@@ -292,7 +296,10 @@ export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
|
|
292
296
|
|
293
297
|
return entry;
|
294
298
|
} else if (key === "perSession") {
|
295
|
-
return new Proxy(
|
299
|
+
return new Proxy(
|
300
|
+
{},
|
301
|
+
CoStreamPerSessionProxyHandler(target, receiver)
|
302
|
+
);
|
296
303
|
} else {
|
297
304
|
return Reflect.get(target, key, receiver);
|
298
305
|
}
|
@@ -350,7 +357,10 @@ export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
|
|
350
357
|
},
|
351
358
|
};
|
352
359
|
|
353
|
-
const CoStreamPerSessionProxyHandler = (
|
360
|
+
const CoStreamPerSessionProxyHandler = (
|
361
|
+
innerTarget: CoStream,
|
362
|
+
accessFrom: CoStream
|
363
|
+
): ProxyHandler<Record<string, never>> => ({
|
354
364
|
get(_target, key, receiver) {
|
355
365
|
if (typeof key === "string" && key.includes("session")) {
|
356
366
|
const sessionID = key as SessionID;
|
@@ -411,6 +421,7 @@ const CoStreamPerSessionProxyHandler = (innerTarget: CoStream, accessFrom: CoStr
|
|
411
421
|
},
|
412
422
|
});
|
413
423
|
|
424
|
+
/** @category CoValues */
|
414
425
|
export class BinaryCoStream
|
415
426
|
extends CoValueBase
|
416
427
|
implements CoValue<"BinaryCoStream", RawBinaryCoStream>
|
@@ -420,7 +431,6 @@ export class BinaryCoStream
|
|
420
431
|
declare _raw: RawBinaryCoStream;
|
421
432
|
|
422
433
|
constructor(
|
423
|
-
_init: [] | undefined,
|
424
434
|
options:
|
425
435
|
| {
|
426
436
|
owner: Account | Group;
|
@@ -449,6 +459,13 @@ export class BinaryCoStream
|
|
449
459
|
});
|
450
460
|
}
|
451
461
|
|
462
|
+
static create<S extends BinaryCoStream>(
|
463
|
+
this: ClassOf<S>,
|
464
|
+
options: { owner: Account | Group }
|
465
|
+
) {
|
466
|
+
return new this(options);
|
467
|
+
}
|
468
|
+
|
452
469
|
getChunks(options?: {
|
453
470
|
allowUnfinished?: boolean;
|
454
471
|
}):
|
@@ -469,6 +486,81 @@ export class BinaryCoStream
|
|
469
486
|
this._raw.endBinaryStream();
|
470
487
|
}
|
471
488
|
|
489
|
+
toBlob(options?: { allowUnfinished?: boolean }): Blob | undefined {
|
490
|
+
const chunks = this.getChunks({
|
491
|
+
allowUnfinished: options?.allowUnfinished,
|
492
|
+
});
|
493
|
+
|
494
|
+
if (!chunks) {
|
495
|
+
return undefined;
|
496
|
+
}
|
497
|
+
|
498
|
+
return new Blob(chunks.chunks, { type: chunks.mimeType });
|
499
|
+
}
|
500
|
+
|
501
|
+
static async loadAsBlob(
|
502
|
+
id: ID<BinaryCoStream>,
|
503
|
+
options: {
|
504
|
+
as: Account & Me;
|
505
|
+
allowUnfinished?: boolean;
|
506
|
+
onProgress?: (progress: number) => void;
|
507
|
+
}
|
508
|
+
): Promise<Blob | undefined> {
|
509
|
+
const stream = await this.load(id, {
|
510
|
+
as: options.as,
|
511
|
+
onProgress: options.onProgress,
|
512
|
+
});
|
513
|
+
|
514
|
+
return stream?.toBlob({
|
515
|
+
allowUnfinished: options.allowUnfinished,
|
516
|
+
});
|
517
|
+
}
|
518
|
+
|
519
|
+
static async createFromBlob(
|
520
|
+
blob: Blob | File,
|
521
|
+
options: {
|
522
|
+
owner: Group | Account;
|
523
|
+
onProgress?: (progress: number) => void;
|
524
|
+
}
|
525
|
+
): Promise<BinaryCoStream> {
|
526
|
+
const stream = this.create({ owner: options.owner });
|
527
|
+
|
528
|
+
const start = Date.now();
|
529
|
+
|
530
|
+
const data = new Uint8Array(await blob.arrayBuffer());
|
531
|
+
stream.start({
|
532
|
+
mimeType: blob.type,
|
533
|
+
totalSizeBytes: blob.size,
|
534
|
+
fileName: blob instanceof File ? blob.name : undefined,
|
535
|
+
});
|
536
|
+
const chunkSize = MAX_RECOMMENDED_TX_SIZE;
|
537
|
+
|
538
|
+
let lastProgressUpdate = Date.now();
|
539
|
+
|
540
|
+
for (let idx = 0; idx < data.length; idx += chunkSize) {
|
541
|
+
stream.push(data.slice(idx, idx + chunkSize));
|
542
|
+
|
543
|
+
if (Date.now() - lastProgressUpdate > 100) {
|
544
|
+
options.onProgress?.(idx / data.length);
|
545
|
+
lastProgressUpdate = Date.now();
|
546
|
+
}
|
547
|
+
|
548
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
549
|
+
}
|
550
|
+
stream.end();
|
551
|
+
const end = Date.now();
|
552
|
+
|
553
|
+
console.debug(
|
554
|
+
"Finished creating binary stream in",
|
555
|
+
(end - start) / 1000,
|
556
|
+
"s - Throughput in MB/s",
|
557
|
+
(1000 * (blob.size / (end - start))) / (1024 * 1024)
|
558
|
+
);
|
559
|
+
options.onProgress?.(1);
|
560
|
+
|
561
|
+
return stream;
|
562
|
+
}
|
563
|
+
|
472
564
|
toJSON() {
|
473
565
|
return {
|
474
566
|
id: this.id,
|
@@ -5,7 +5,8 @@ import {
|
|
5
5
|
subscriptionsScopes,
|
6
6
|
} from "../../internal.js";
|
7
7
|
|
8
|
-
|
8
|
+
/** @category Media */
|
9
|
+
export class ImageDefinition extends CoMap {
|
9
10
|
originalSize = co.json<[number, number]>();
|
10
11
|
placeholderDataURL? = co.string;
|
11
12
|
|
package/src/coValues/group.ts
CHANGED
@@ -2,9 +2,9 @@ import type { AccountID, Everyone, RawGroup, Role } from "cojson";
|
|
2
2
|
import type {
|
3
3
|
CoValue,
|
4
4
|
ID,
|
5
|
-
JsonEncoded,
|
6
5
|
RefEncoded,
|
7
6
|
Schema,
|
7
|
+
ClassOf,
|
8
8
|
} from "../internal.js";
|
9
9
|
import {
|
10
10
|
Account,
|
@@ -17,34 +17,13 @@ import {
|
|
17
17
|
MembersSym,
|
18
18
|
} from "../internal.js";
|
19
19
|
|
20
|
-
|
20
|
+
/** @category Identity & Permissions */
|
21
|
+
export class Profile extends CoMap {
|
21
22
|
name = co.string;
|
22
23
|
}
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
? RefEncoded<NonNullable<Def["profile"]>>
|
27
|
-
: JsonEncoded;
|
28
|
-
root: NonNullable<Def["root"]> extends CoValue
|
29
|
-
? RefEncoded<NonNullable<Def["root"]>>
|
30
|
-
: JsonEncoded;
|
31
|
-
[MembersSym]: RefEncoded<NonNullable<Def[MembersSym]>>;
|
32
|
-
};
|
33
|
-
|
34
|
-
export class Group<
|
35
|
-
Def extends {
|
36
|
-
profile: Profile | null;
|
37
|
-
root: CoMap | null;
|
38
|
-
[MembersSym]: Account | null;
|
39
|
-
} = {
|
40
|
-
profile: Profile | null;
|
41
|
-
root: CoMap | null;
|
42
|
-
[MembersSym]: Account | null;
|
43
|
-
},
|
44
|
-
>
|
45
|
-
extends CoValueBase
|
46
|
-
implements CoValue<"Group", RawGroup>
|
47
|
-
{
|
25
|
+
/** @category Identity & Permissions */
|
26
|
+
export class Group extends CoValueBase implements CoValue<"Group", RawGroup> {
|
48
27
|
declare id: ID<this>;
|
49
28
|
declare _type: "Group";
|
50
29
|
static {
|
@@ -53,7 +32,11 @@ export class Group<
|
|
53
32
|
declare _raw: RawGroup;
|
54
33
|
|
55
34
|
static _schema: any;
|
56
|
-
get _schema():
|
35
|
+
get _schema(): {
|
36
|
+
profile: Schema;
|
37
|
+
root: Schema;
|
38
|
+
[MembersSym]: RefEncoded<Account>;
|
39
|
+
} {
|
57
40
|
return (this.constructor as typeof Group)._schema;
|
58
41
|
}
|
59
42
|
static {
|
@@ -67,19 +50,16 @@ export class Group<
|
|
67
50
|
});
|
68
51
|
}
|
69
52
|
|
70
|
-
declare profile:
|
71
|
-
declare root:
|
72
|
-
declare [MembersSym]:
|
53
|
+
declare profile: Profile | null;
|
54
|
+
declare root: CoMap | null;
|
55
|
+
declare [MembersSym]: Account | null;
|
73
56
|
|
74
|
-
get _refs()
|
75
|
-
profile: Def["profile"] extends Profile ? Ref<Def["profile"]> : never;
|
76
|
-
root: Def["root"] extends CoMap ? Ref<Def["root"]> : never;
|
77
|
-
} {
|
57
|
+
get _refs() {
|
78
58
|
const profileID = this._raw.get("profile") as unknown as
|
79
|
-
| ID<NonNullable<
|
59
|
+
| ID<NonNullable<this["profile"]>>
|
80
60
|
| undefined;
|
81
61
|
const rootID = this._raw.get("root") as unknown as
|
82
|
-
| ID<NonNullable<
|
62
|
+
| ID<NonNullable<this["root"]>>
|
83
63
|
| undefined;
|
84
64
|
return {
|
85
65
|
profile:
|
@@ -88,33 +68,32 @@ export class Group<
|
|
88
68
|
profileID,
|
89
69
|
this._loadedAs,
|
90
70
|
this._schema.profile as RefEncoded<
|
91
|
-
NonNullable<
|
71
|
+
NonNullable<this["profile"]>
|
92
72
|
>
|
93
|
-
) as any
|
73
|
+
) as any as this["profile"] extends Profile
|
74
|
+
? Ref<this["profile"]>
|
75
|
+
: never),
|
94
76
|
root:
|
95
77
|
rootID &&
|
96
78
|
(new Ref(
|
97
79
|
rootID,
|
98
80
|
this._loadedAs,
|
99
|
-
this._schema.root as RefEncoded<NonNullable<
|
100
|
-
) as any
|
81
|
+
this._schema.root as RefEncoded<NonNullable<this["root"]>>
|
82
|
+
) as any as this["root"] extends CoMap
|
83
|
+
? Ref<this["root"]>
|
84
|
+
: never),
|
101
85
|
};
|
102
86
|
}
|
103
87
|
|
104
|
-
|
105
|
-
constructor(
|
106
|
-
constructor(init: undefined, options: { owner: Account | Group });
|
107
|
-
constructor(
|
108
|
-
init: undefined | { owner: Account | Group },
|
109
|
-
options?: { fromRaw: RawGroup } | { owner: Account | Group }
|
110
|
-
) {
|
88
|
+
/** @deprecated Don't use constructor directly, use .create */
|
89
|
+
constructor(options: { fromRaw: RawGroup } | { owner: Account | Group }) {
|
111
90
|
super();
|
112
91
|
let raw: RawGroup;
|
113
92
|
|
114
93
|
if (options && "fromRaw" in options) {
|
115
94
|
raw = options.fromRaw;
|
116
95
|
} else {
|
117
|
-
const initOwner = options
|
96
|
+
const initOwner = options.owner;
|
118
97
|
if (!initOwner) throw new Error("No owner provided");
|
119
98
|
if (
|
120
99
|
initOwner instanceof Account &&
|
@@ -143,6 +122,13 @@ export class Group<
|
|
143
122
|
);
|
144
123
|
}
|
145
124
|
|
125
|
+
static create<G extends Group>(
|
126
|
+
this: ClassOf<G>,
|
127
|
+
options: { owner: Account }
|
128
|
+
) {
|
129
|
+
return new this(options);
|
130
|
+
}
|
131
|
+
|
146
132
|
myRole(): Role | undefined {
|
147
133
|
return this._raw.myRole();
|
148
134
|
}
|