jazz-tools 0.7.0-alpha.26 → 0.7.0-alpha.28
Sign up to get free protection for your applications and to get access to all the features.
- package/.turbo/turbo-build.log +39 -36
- package/CHANGELOG.md +17 -0
- package/dist/coValues/account.js +15 -8
- package/dist/coValues/account.js.map +1 -1
- package/dist/coValues/coList.js +3 -2
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coStream.js +38 -19
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coValues/group.js +26 -1
- package/dist/coValues/group.js.map +1 -1
- package/dist/implementation/schema.js +5 -3
- package/dist/implementation/schema.js.map +1 -1
- package/dist/implementation/symbols.js +5 -0
- package/dist/implementation/symbols.js.map +1 -0
- package/dist/internal.js +1 -0
- package/dist/internal.js.map +1 -1
- package/dist/tests/coList.test.js +15 -15
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/coMap.test.js +15 -16
- package/dist/tests/coMap.test.js.map +1 -1
- package/dist/tests/coStream.test.js +4 -4
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/groupsAndAccounts.test.js +70 -0
- package/dist/tests/groupsAndAccounts.test.js.map +1 -0
- package/package.json +2 -2
- package/src/coValues/account.ts +21 -10
- package/src/coValues/coList.ts +5 -8
- package/src/coValues/coStream.ts +48 -30
- package/src/coValues/group.ts +62 -16
- package/src/implementation/schema.ts +5 -9
- package/src/implementation/symbols.ts +12 -0
- package/src/internal.ts +1 -0
- package/src/tests/coList.test.ts +15 -15
- package/src/tests/coMap.test.ts +24 -19
- package/src/tests/coStream.test.ts +4 -4
- package/src/tests/groupsAndAccounts.test.ts +77 -0
package/src/coValues/coStream.ts
CHANGED
@@ -275,22 +275,24 @@ export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
|
|
275
275
|
get: () => {
|
276
276
|
const allRawEntries = target._raw.itemsBy(key as AccountID);
|
277
277
|
return (function* () {
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
278
|
+
while (true) {
|
279
|
+
const rawEntry = allRawEntries.next();
|
280
|
+
if (rawEntry.done) return;
|
281
|
+
yield entryFromRawEntry(
|
282
|
+
receiver,
|
283
|
+
rawEntry.value,
|
284
|
+
target._loadedAs,
|
285
|
+
key as unknown as ID<Account>,
|
286
|
+
target._schema[ItemsSym]
|
287
|
+
);
|
288
|
+
}
|
287
289
|
})() satisfies IterableIterator<SingleCoStreamEntry<any>>;
|
288
290
|
},
|
289
291
|
});
|
290
292
|
|
291
293
|
return entry;
|
292
294
|
} else if (key === "perSession") {
|
293
|
-
return new Proxy(
|
295
|
+
return new Proxy({}, CoStreamPerSessionProxyHandler(target, receiver));
|
294
296
|
} else {
|
295
297
|
return Reflect.get(target, key, receiver);
|
296
298
|
}
|
@@ -348,50 +350,66 @@ export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
|
|
348
350
|
},
|
349
351
|
};
|
350
352
|
|
351
|
-
const CoStreamPerSessionProxyHandler: ProxyHandler<
|
352
|
-
get(
|
353
|
+
const CoStreamPerSessionProxyHandler = (innerTarget: CoStream, accessFrom: CoStream): ProxyHandler<Record<string, never>> => ({
|
354
|
+
get(_target, key, receiver) {
|
353
355
|
if (typeof key === "string" && key.includes("session")) {
|
354
356
|
const sessionID = key as SessionID;
|
355
|
-
const rawEntry =
|
357
|
+
const rawEntry = innerTarget._raw.lastItemIn(sessionID);
|
356
358
|
|
357
359
|
if (!rawEntry) return;
|
358
360
|
const by = cojsonInternals.accountOrAgentIDfromSessionID(sessionID);
|
359
361
|
|
360
362
|
const entry = entryFromRawEntry(
|
361
|
-
|
363
|
+
accessFrom,
|
362
364
|
rawEntry,
|
363
|
-
|
365
|
+
innerTarget._loadedAs,
|
364
366
|
cojsonInternals.isAccountID(by)
|
365
367
|
? (by as unknown as ID<Account>)
|
366
368
|
: undefined,
|
367
|
-
|
369
|
+
innerTarget._schema[ItemsSym]
|
368
370
|
);
|
369
371
|
|
370
372
|
Object.defineProperty(entry, "all", {
|
371
373
|
get: () => {
|
372
|
-
const allRawEntries =
|
374
|
+
const allRawEntries = innerTarget._raw.itemsIn(sessionID);
|
373
375
|
return (function* () {
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
376
|
+
while (true) {
|
377
|
+
const rawEntry = allRawEntries.next();
|
378
|
+
if (rawEntry.done) return;
|
379
|
+
yield entryFromRawEntry(
|
380
|
+
accessFrom,
|
381
|
+
rawEntry.value,
|
382
|
+
innerTarget._loadedAs,
|
383
|
+
cojsonInternals.isAccountID(by)
|
384
|
+
? (by as unknown as ID<Account>)
|
385
|
+
: undefined,
|
386
|
+
innerTarget._schema[ItemsSym]
|
387
|
+
);
|
388
|
+
}
|
385
389
|
})() satisfies IterableIterator<SingleCoStreamEntry<any>>;
|
386
390
|
},
|
387
391
|
});
|
388
392
|
|
389
393
|
return entry;
|
390
394
|
} else {
|
391
|
-
return Reflect.get(
|
395
|
+
return Reflect.get(innerTarget, key, receiver);
|
392
396
|
}
|
393
397
|
},
|
394
|
-
|
398
|
+
ownKeys() {
|
399
|
+
return innerTarget._raw.sessions();
|
400
|
+
},
|
401
|
+
getOwnPropertyDescriptor(target, key) {
|
402
|
+
if (typeof key === "string" && key.startsWith("co_")) {
|
403
|
+
return {
|
404
|
+
configurable: true,
|
405
|
+
enumerable: true,
|
406
|
+
writable: false,
|
407
|
+
};
|
408
|
+
} else {
|
409
|
+
return Reflect.getOwnPropertyDescriptor(target, key);
|
410
|
+
}
|
411
|
+
},
|
412
|
+
});
|
395
413
|
|
396
414
|
export class BinaryCoStream
|
397
415
|
extends CoValueBase
|
package/src/coValues/group.ts
CHANGED
@@ -1,5 +1,11 @@
|
|
1
|
-
import type { Everyone, RawGroup, Role } from "cojson";
|
2
|
-
import type {
|
1
|
+
import type { AccountID, Everyone, RawGroup, Role } from "cojson";
|
2
|
+
import type {
|
3
|
+
CoValue,
|
4
|
+
ID,
|
5
|
+
JsonEncoded,
|
6
|
+
RefEncoded,
|
7
|
+
Schema,
|
8
|
+
} from "../internal.js";
|
3
9
|
import {
|
4
10
|
Account,
|
5
11
|
CoMap,
|
@@ -8,16 +14,32 @@ import {
|
|
8
14
|
co,
|
9
15
|
isControlledAccount,
|
10
16
|
AccountAndGroupProxyHandler,
|
17
|
+
MembersSym,
|
11
18
|
} from "../internal.js";
|
12
19
|
|
13
20
|
export class Profile extends CoMap<{ name: co<string> }> {
|
14
21
|
name = co.string;
|
15
22
|
}
|
16
23
|
|
24
|
+
type GroupSchema<Def extends Group> = {
|
25
|
+
profile: NonNullable<Def["profile"]> extends CoValue
|
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
|
+
|
17
34
|
export class Group<
|
18
|
-
Def extends {
|
35
|
+
Def extends {
|
19
36
|
profile: Profile | null;
|
20
37
|
root: CoMap | null;
|
38
|
+
[MembersSym]: Account | null;
|
39
|
+
} = {
|
40
|
+
profile: Profile | null;
|
41
|
+
root: CoMap | null;
|
42
|
+
[MembersSym]: Account | null;
|
21
43
|
},
|
22
44
|
>
|
23
45
|
extends CoValueBase
|
@@ -31,31 +53,23 @@ export class Group<
|
|
31
53
|
declare _raw: RawGroup;
|
32
54
|
|
33
55
|
static _schema: any;
|
34
|
-
get _schema(): {
|
35
|
-
profile: Def["profile"] extends CoValue
|
36
|
-
? RefEncoded<Def["profile"]>
|
37
|
-
: JsonEncoded;
|
38
|
-
root: Def["root"] extends CoValue
|
39
|
-
? RefEncoded<Def["root"]>
|
40
|
-
: JsonEncoded;
|
41
|
-
} {
|
56
|
+
get _schema(): GroupSchema<this> {
|
42
57
|
return (this.constructor as typeof Group)._schema;
|
43
58
|
}
|
44
59
|
static {
|
45
60
|
this._schema = {
|
46
61
|
profile: "json" satisfies Schema,
|
47
62
|
root: "json" satisfies Schema,
|
63
|
+
[MembersSym]: () => Account satisfies Schema,
|
48
64
|
} as any;
|
49
65
|
Object.defineProperty(this.prototype, "_schema", {
|
50
66
|
get: () => this._schema,
|
51
67
|
});
|
52
68
|
}
|
53
69
|
|
54
|
-
profile
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
root!: Def["root"] extends CoMap ? Def["root"] | null : undefined;
|
70
|
+
declare profile: Def["profile"] | null;
|
71
|
+
declare root: Def["root"] | null;
|
72
|
+
declare [MembersSym]: Def[MembersSym] | null;
|
59
73
|
|
60
74
|
get _refs(): {
|
61
75
|
profile: Def["profile"] extends Profile ? Ref<Def["profile"]> : never;
|
@@ -136,4 +150,36 @@ export class Group<
|
|
136
150
|
addMember(member: Everyone | Account, role: Role) {
|
137
151
|
this._raw.addMember(member === "everyone" ? member : member._raw, role);
|
138
152
|
}
|
153
|
+
|
154
|
+
get members() {
|
155
|
+
return this._raw
|
156
|
+
.keys()
|
157
|
+
.filter((key) => {
|
158
|
+
return key === "everyone" || key.startsWith("co_");
|
159
|
+
})
|
160
|
+
.map((id) => {
|
161
|
+
const role = this._raw.get(id as Everyone | AccountID);
|
162
|
+
const accountID =
|
163
|
+
id === "everyone"
|
164
|
+
? undefined
|
165
|
+
: (id as unknown as ID<Account>);
|
166
|
+
const ref =
|
167
|
+
accountID &&
|
168
|
+
new Ref<NonNullable<this[MembersSym]>>(
|
169
|
+
accountID,
|
170
|
+
this._loadedAs,
|
171
|
+
this._schema[MembersSym]
|
172
|
+
);
|
173
|
+
const accessRef = () => ref?.accessFrom(this);
|
174
|
+
|
175
|
+
return {
|
176
|
+
id: id as unknown as Everyone | ID<this[MembersSym]>,
|
177
|
+
role,
|
178
|
+
ref,
|
179
|
+
get account() {
|
180
|
+
return accessRef();
|
181
|
+
},
|
182
|
+
};
|
183
|
+
});
|
184
|
+
}
|
139
185
|
}
|
@@ -10,15 +10,6 @@ export type IfCo<C, R> = C extends infer _A | infer B
|
|
10
10
|
: never
|
11
11
|
: never;
|
12
12
|
|
13
|
-
export const SchemaInit = Symbol.for("SchemaInit");
|
14
|
-
export type SchemaInit = typeof SchemaInit;
|
15
|
-
|
16
|
-
export const InitValues = Symbol.for("InitValues");
|
17
|
-
export type InitValues = typeof InitValues;
|
18
|
-
|
19
|
-
export const ItemsSym = Symbol.for("items");
|
20
|
-
export type ItemsSym = typeof ItemsSym;
|
21
|
-
|
22
13
|
export const co = {
|
23
14
|
string: {
|
24
15
|
[SchemaInit]: "json" satisfies Schema,
|
@@ -29,6 +20,9 @@ export const co = {
|
|
29
20
|
boolean: {
|
30
21
|
[SchemaInit]: "json" satisfies Schema,
|
31
22
|
} as unknown as co<boolean>,
|
23
|
+
null: {
|
24
|
+
[SchemaInit]: "json" satisfies Schema,
|
25
|
+
} as unknown as co<null>,
|
32
26
|
literal: <T extends string | number | boolean>(_lit: T): co<T> => {
|
33
27
|
return { [SchemaInit]: "json" satisfies Schema } as any;
|
34
28
|
},
|
@@ -44,6 +38,7 @@ export const co = {
|
|
44
38
|
return { [SchemaInit]: arg satisfies Schema } as any;
|
45
39
|
},
|
46
40
|
items: ItemsSym as ItemsSym,
|
41
|
+
members: MembersSym as MembersSym,
|
47
42
|
};
|
48
43
|
|
49
44
|
export type JsonEncoded = "json";
|
@@ -89,6 +84,7 @@ export type EffectSchemaWithInputAndOutput<A, I = A> = EffectSchema<
|
|
89
84
|
export type Encoder<V> = EffectSchemaWithInputAndOutput<V, JsonValue>;
|
90
85
|
|
91
86
|
import { Date } from "@effect/schema/Schema";
|
87
|
+
import { SchemaInit, ItemsSym, MembersSym } from "./symbols.js";
|
92
88
|
|
93
89
|
export const Encoders = {
|
94
90
|
Date,
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
export const SchemaInit = Symbol.for("SchemaInit");
|
3
|
+
export type SchemaInit = typeof SchemaInit;
|
4
|
+
|
5
|
+
export const InitValues = Symbol.for("InitValues");
|
6
|
+
export type InitValues = typeof InitValues;
|
7
|
+
|
8
|
+
export const ItemsSym = Symbol.for("items");
|
9
|
+
export type ItemsSym = typeof ItemsSym;
|
10
|
+
|
11
|
+
export const MembersSym = Symbol.for("members");
|
12
|
+
export type MembersSym = typeof MembersSym;
|
package/src/internal.ts
CHANGED
package/src/tests/coList.test.ts
CHANGED
@@ -17,7 +17,7 @@ beforeEach(async () => {
|
|
17
17
|
|
18
18
|
describe("Simple CoList operations", async () => {
|
19
19
|
const me = await Account.create({
|
20
|
-
name: "Hermes Puggington",
|
20
|
+
creationProps: { name: "Hermes Puggington" },
|
21
21
|
});
|
22
22
|
|
23
23
|
class TestList extends CoList.Of(co.string) {}
|
@@ -97,19 +97,19 @@ describe("Simple CoList operations", async () => {
|
|
97
97
|
expect(list._raw.asArray()).toEqual(["butter", "onion"]);
|
98
98
|
});
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
100
|
+
test("splice", () => {
|
101
|
+
const list = new TestList(["bread", "butter", "onion"], {
|
102
|
+
owner: me,
|
103
|
+
});
|
104
|
+
list.splice(1, 1, "salt", "pepper");
|
105
|
+
expect(list.length).toBe(4);
|
106
|
+
expect(list._raw.asArray()).toEqual([
|
107
|
+
"bread",
|
108
|
+
"salt",
|
109
|
+
"pepper",
|
110
|
+
"onion",
|
111
|
+
]);
|
112
|
+
});
|
113
113
|
});
|
114
114
|
});
|
115
115
|
|
@@ -126,7 +126,7 @@ describe("CoList resolution", async () => {
|
|
126
126
|
|
127
127
|
const initNodeAndList = async () => {
|
128
128
|
const me = await Account.create({
|
129
|
-
name: "Hermes Puggington",
|
129
|
+
creationProps: { name: "Hermes Puggington" },
|
130
130
|
});
|
131
131
|
|
132
132
|
const list = new TestList(
|
package/src/tests/coMap.test.ts
CHANGED
@@ -17,7 +17,7 @@ beforeEach(async () => {
|
|
17
17
|
|
18
18
|
describe("Simple CoMap operations", async () => {
|
19
19
|
const me = await Account.create({
|
20
|
-
name: "Hermes Puggington",
|
20
|
+
creationProps: { name: "Hermes Puggington" },
|
21
21
|
});
|
22
22
|
|
23
23
|
class TestMap extends CoMap<TestMap> {
|
@@ -50,11 +50,7 @@ describe("Simple CoMap operations", async () => {
|
|
50
50
|
expect(map._height).toEqual(10);
|
51
51
|
expect(map.birthday).toEqual(birthday);
|
52
52
|
expect(map._raw.get("birthday")).toEqual(birthday.toISOString());
|
53
|
-
expect(Object.keys(map)).toEqual([
|
54
|
-
"color",
|
55
|
-
"_height",
|
56
|
-
"birthday",
|
57
|
-
]);
|
53
|
+
expect(Object.keys(map)).toEqual(["color", "_height", "birthday"]);
|
58
54
|
});
|
59
55
|
|
60
56
|
describe("Mutation", () => {
|
@@ -202,7 +198,7 @@ describe("CoMap resolution", async () => {
|
|
202
198
|
|
203
199
|
const initNodeAndMap = async () => {
|
204
200
|
const me = await Account.create({
|
205
|
-
name: "Hermes Puggington",
|
201
|
+
creationProps: { name: "Hermes Puggington" },
|
206
202
|
});
|
207
203
|
|
208
204
|
const map = new TestMap(
|
@@ -394,7 +390,7 @@ describe("CoMap resolution", async () => {
|
|
394
390
|
|
395
391
|
test("Construction with optional", async () => {
|
396
392
|
const me = await Account.create({
|
397
|
-
name: "Hermes Puggington",
|
393
|
+
creationProps: { name: "Hermes Puggington" },
|
398
394
|
});
|
399
395
|
|
400
396
|
const mapWithout = new TestMapWithOptionalRef(
|
@@ -437,7 +433,7 @@ describe("CoMap resolution", async () => {
|
|
437
433
|
|
438
434
|
test("Construction with index signature", async () => {
|
439
435
|
const me = await Account.create({
|
440
|
-
name: "Hermes Puggington",
|
436
|
+
creationProps: { name: "Hermes Puggington" },
|
441
437
|
});
|
442
438
|
|
443
439
|
const record = new TestRecord(
|
@@ -454,18 +450,18 @@ describe("CoMap resolution", async () => {
|
|
454
450
|
expect(record._raw.get("other")).toEqual(3);
|
455
451
|
expect(Object.keys(record)).toEqual(["height", "other"]);
|
456
452
|
expect(record.toJSON()).toMatchObject({
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
453
|
+
_type: "CoMap",
|
454
|
+
height: 5,
|
455
|
+
id: expect.any(String),
|
456
|
+
other: 3,
|
457
|
+
});
|
462
458
|
});
|
463
459
|
|
464
460
|
class TestRecord2 extends CoMap.Record(co.number) {}
|
465
461
|
|
466
462
|
test("Construction with index signature (shorthand)", async () => {
|
467
463
|
const me = await Account.create({
|
468
|
-
name: "Hermes Puggington",
|
464
|
+
creationProps: { name: "Hermes Puggington" },
|
469
465
|
});
|
470
466
|
|
471
467
|
const record = new TestRecord2(
|
@@ -487,13 +483,19 @@ describe("CoMap resolution", async () => {
|
|
487
483
|
|
488
484
|
test("Construction with index signature ref", async () => {
|
489
485
|
const me = await Account.create({
|
490
|
-
name: "Hermes Puggington",
|
486
|
+
creationProps: { name: "Hermes Puggington" },
|
491
487
|
});
|
492
488
|
|
493
489
|
const record = new TestRecordRef(
|
494
490
|
{
|
495
|
-
firstNested: new TwiceNestedMap(
|
496
|
-
|
491
|
+
firstNested: new TwiceNestedMap(
|
492
|
+
{ taste: "sour" },
|
493
|
+
{ owner: me }
|
494
|
+
),
|
495
|
+
secondNested: new TwiceNestedMap(
|
496
|
+
{ taste: "sweet" },
|
497
|
+
{ owner: me }
|
498
|
+
),
|
497
499
|
},
|
498
500
|
{ owner: me }
|
499
501
|
);
|
@@ -503,6 +505,9 @@ describe("CoMap resolution", async () => {
|
|
503
505
|
expect(record.secondNested?.taste).toEqual("sweet");
|
504
506
|
expect(record.secondNested?.id).toBeDefined();
|
505
507
|
expect(Object.keys(record)).toEqual(["firstNested", "secondNested"]);
|
506
|
-
expect(Object.keys(record._refs)).toEqual([
|
508
|
+
expect(Object.keys(record._refs)).toEqual([
|
509
|
+
"firstNested",
|
510
|
+
"secondNested",
|
511
|
+
]);
|
507
512
|
});
|
508
513
|
});
|
@@ -18,7 +18,7 @@ beforeEach(async () => {
|
|
18
18
|
|
19
19
|
describe("Simple CoStream operations", async () => {
|
20
20
|
const me = await Account.create({
|
21
|
-
name: "Hermes Puggington",
|
21
|
+
creationProps: { name: "Hermes Puggington" },
|
22
22
|
});
|
23
23
|
|
24
24
|
class TestStream extends CoStream.Of(co.string) {}
|
@@ -56,7 +56,7 @@ describe("CoStream resolution", async () => {
|
|
56
56
|
|
57
57
|
const initNodeAndStream = async () => {
|
58
58
|
const me = await Account.create({
|
59
|
-
name: "Hermes Puggington",
|
59
|
+
creationProps: { name: "Hermes Puggington" },
|
60
60
|
});
|
61
61
|
|
62
62
|
const stream = new TestStream(
|
@@ -257,7 +257,7 @@ describe("CoStream resolution", async () => {
|
|
257
257
|
|
258
258
|
describe("Simple BinaryCoStream operations", async () => {
|
259
259
|
const me = await Account.create({
|
260
|
-
name: "Hermes Puggington",
|
260
|
+
creationProps: { name: "Hermes Puggington" },
|
261
261
|
});
|
262
262
|
|
263
263
|
const stream = new BinaryCoStream(undefined, { owner: me });
|
@@ -285,7 +285,7 @@ describe("Simple BinaryCoStream operations", async () => {
|
|
285
285
|
describe("BinaryCoStream loading & Subscription", async () => {
|
286
286
|
const initNodeAndStream = async () => {
|
287
287
|
const me = await Account.create({
|
288
|
-
name: "Hermes Puggington",
|
288
|
+
creationProps: { name: "Hermes Puggington" },
|
289
289
|
});
|
290
290
|
|
291
291
|
const stream = new BinaryCoStream(undefined, { owner: me });
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import { expect, describe, test, beforeEach } from "vitest";
|
2
|
+
|
3
|
+
import { webcrypto } from "node:crypto";
|
4
|
+
import { Account, jazzReady, CoMap, co, Group } from "..";
|
5
|
+
|
6
|
+
if (!("crypto" in globalThis)) {
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
8
|
+
(globalThis as any).crypto = webcrypto;
|
9
|
+
}
|
10
|
+
|
11
|
+
beforeEach(async () => {
|
12
|
+
await jazzReady;
|
13
|
+
});
|
14
|
+
|
15
|
+
describe("Custom accounts and groups", async () => {
|
16
|
+
class CustomProfile extends CoMap<CustomProfile> {
|
17
|
+
name = co.string;
|
18
|
+
color = co.string;
|
19
|
+
}
|
20
|
+
|
21
|
+
class CustomAccount extends Account<CustomAccount> {
|
22
|
+
profile = co.ref(CustomProfile);
|
23
|
+
root = co.ref(CoMap);
|
24
|
+
|
25
|
+
migrate(creationProps?: { name: string }) {
|
26
|
+
if (creationProps) {
|
27
|
+
const profileGroup = new Group({ owner: this });
|
28
|
+
profileGroup.addMember("everyone", "reader");
|
29
|
+
this.profile = new CustomProfile(
|
30
|
+
{ name: creationProps.name, color: "blue" },
|
31
|
+
{ owner: this }
|
32
|
+
);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
class CustomGroup extends Group<CustomGroup> {
|
38
|
+
profile = co.null;
|
39
|
+
root = co.null;
|
40
|
+
[co.members] = co.ref(CustomAccount);
|
41
|
+
}
|
42
|
+
|
43
|
+
type T = CustomGroup[typeof co.members];
|
44
|
+
|
45
|
+
test("Custom account and group", async () => {
|
46
|
+
const me = await CustomAccount.create({
|
47
|
+
creationProps: { name: "Hermes Puggington" },
|
48
|
+
});
|
49
|
+
|
50
|
+
expect(me.profile).toBeDefined();
|
51
|
+
expect(me.profile?.name).toBe("Hermes Puggington");
|
52
|
+
expect(me.profile?.color).toBe("blue");
|
53
|
+
|
54
|
+
const group = new CustomGroup({ owner: me });
|
55
|
+
group.addMember("everyone", "reader");
|
56
|
+
|
57
|
+
expect(group.members).toMatchObject([
|
58
|
+
{ id: me.id, role: "admin" },
|
59
|
+
{ id: "everyone", role: "reader" },
|
60
|
+
]);
|
61
|
+
|
62
|
+
await new Promise<void>((resolve) => {
|
63
|
+
group.subscribe((update) => {
|
64
|
+
const myProfile = update.members.find((member) => {
|
65
|
+
return member.id === me.id && member.account?.profile;
|
66
|
+
});
|
67
|
+
if (myProfile) {
|
68
|
+
expect(myProfile.account?.profile?.name).toBe(
|
69
|
+
"Hermes Puggington"
|
70
|
+
);
|
71
|
+
expect(myProfile.account?.profile?.color).toBe("blue");
|
72
|
+
resolve();
|
73
|
+
}
|
74
|
+
});
|
75
|
+
});
|
76
|
+
});
|
77
|
+
});
|