jazz-tools 0.19.0 → 0.19.1
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/.turbo/turbo-build.log +51 -51
- package/CHANGELOG.md +10 -0
- package/dist/{chunk-P3YLNFN4.js → chunk-NCNM6UDZ.js} +61 -22
- package/dist/chunk-NCNM6UDZ.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/testing.js +1 -1
- package/dist/tools/coValues/deepLoading.d.ts +8 -7
- package/dist/tools/coValues/deepLoading.d.ts.map +1 -1
- package/dist/tools/coValues/interfaces.d.ts +3 -3
- package/dist/tools/coValues/interfaces.d.ts.map +1 -1
- package/dist/tools/coValues/schemaUnion.d.ts +6 -9
- package/dist/tools/coValues/schemaUnion.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts +18 -7
- package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/unionUtils.d.ts.map +1 -1
- package/dist/tools/subscribe/SubscriptionScope.d.ts +1 -0
- package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/tools/coValues/coList.ts +1 -1
- package/src/tools/coValues/deepLoading.ts +85 -71
- package/src/tools/coValues/interfaces.ts +3 -3
- package/src/tools/coValues/schemaUnion.ts +19 -14
- package/src/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.ts +69 -9
- package/src/tools/implementation/zodSchema/unionUtils.ts +35 -4
- package/src/tools/subscribe/SubscriptionScope.ts +3 -14
- package/src/tools/tests/coDiscriminatedUnion.test.ts +347 -5
- package/src/tools/tests/deepLoading.test.ts +55 -59
- package/src/tools/tests/schema.resolved.test.ts +70 -1
- package/dist/chunk-P3YLNFN4.js.map +0 -1
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, test, vi } from "vitest";
|
|
2
|
-
import { CoPlainText, Loaded, co, z } from "../exports.js";
|
|
2
|
+
import { CoPlainText, Group, Loaded, co, loadCoValue, z } from "../exports.js";
|
|
3
3
|
import { createJazzTestAccount, setupJazzTestSync } from "../testing.js";
|
|
4
4
|
import { assertLoaded, waitFor } from "./utils.js";
|
|
5
|
+
import type { Account } from "jazz-tools";
|
|
5
6
|
|
|
6
7
|
describe("co.discriminatedUnion", () => {
|
|
8
|
+
let account: Account;
|
|
9
|
+
|
|
7
10
|
beforeEach(async () => {
|
|
8
11
|
await setupJazzTestSync();
|
|
9
12
|
|
|
10
|
-
await createJazzTestAccount({
|
|
13
|
+
account = await createJazzTestAccount({
|
|
11
14
|
isCurrentActiveAccount: true,
|
|
12
15
|
creationProps: { name: "Hermes Puggington" },
|
|
13
16
|
});
|
|
@@ -266,7 +269,7 @@ describe("co.discriminatedUnion", () => {
|
|
|
266
269
|
expect(referenceItem.children[0]?.type).toEqual("note");
|
|
267
270
|
});
|
|
268
271
|
|
|
269
|
-
test("load CoValue instances using the DiscriminatedUnion schema", async () => {
|
|
272
|
+
test("load CoValue instances using the DiscriminatedUnion schema without resolve", async () => {
|
|
270
273
|
const Dog = co.map({
|
|
271
274
|
type: z.literal("dog"),
|
|
272
275
|
});
|
|
@@ -281,7 +284,40 @@ describe("co.discriminatedUnion", () => {
|
|
|
281
284
|
expect(loadedPet.type).toEqual("dog");
|
|
282
285
|
});
|
|
283
286
|
|
|
284
|
-
test("
|
|
287
|
+
test("load CoValue instances using the DiscriminatedUnion schema with deep resolve", async () => {
|
|
288
|
+
const Person = co.map({
|
|
289
|
+
name: z.string(),
|
|
290
|
+
});
|
|
291
|
+
const Dog = co.map({
|
|
292
|
+
type: z.literal("dog"),
|
|
293
|
+
owner: Person,
|
|
294
|
+
});
|
|
295
|
+
const Cat = co.map({
|
|
296
|
+
type: z.literal("cat"),
|
|
297
|
+
owner: Person,
|
|
298
|
+
});
|
|
299
|
+
const Pet = co.discriminatedUnion("type", [Dog, Cat]);
|
|
300
|
+
|
|
301
|
+
const dog = Dog.create({
|
|
302
|
+
type: "dog",
|
|
303
|
+
owner: Person.create({
|
|
304
|
+
name: "John Doe",
|
|
305
|
+
}),
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
const loadedPet = await Pet.load(dog.$jazz.id, {
|
|
309
|
+
resolve: {
|
|
310
|
+
owner: true,
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
assertLoaded(loadedPet);
|
|
315
|
+
|
|
316
|
+
expect(loadedPet?.type).toEqual("dog");
|
|
317
|
+
expect(loadedPet?.owner.name).toEqual("John Doe");
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
test("subscribe to CoValue instances using the DiscriminatedUnion schema without resolve", async () => {
|
|
285
321
|
const Person = co.map({
|
|
286
322
|
name: z.string(),
|
|
287
323
|
});
|
|
@@ -319,7 +355,41 @@ describe("co.discriminatedUnion", () => {
|
|
|
319
355
|
expect(updates[0]?.name).toEqual("Rex");
|
|
320
356
|
});
|
|
321
357
|
|
|
322
|
-
test("
|
|
358
|
+
test("subscribe to CoValue instances using the DiscriminatedUnion schema with deep resolve", async () => {
|
|
359
|
+
const Person = co.map({
|
|
360
|
+
name: z.string(),
|
|
361
|
+
});
|
|
362
|
+
const Dog = co.map({
|
|
363
|
+
type: z.literal("dog"),
|
|
364
|
+
owner: Person,
|
|
365
|
+
});
|
|
366
|
+
const Cat = co.map({
|
|
367
|
+
type: z.literal("cat"),
|
|
368
|
+
owner: Person,
|
|
369
|
+
});
|
|
370
|
+
const Pet = co.discriminatedUnion("type", [Dog, Cat]);
|
|
371
|
+
|
|
372
|
+
const dog = Dog.create({
|
|
373
|
+
type: "dog",
|
|
374
|
+
owner: Person.create({
|
|
375
|
+
name: "John Doe",
|
|
376
|
+
}),
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
const spy = vi.fn();
|
|
380
|
+
Pet.subscribe(dog.$jazz.id, { resolve: { owner: true } }, (pet) => {
|
|
381
|
+
expect(pet.owner.name).toEqual("John Doe");
|
|
382
|
+
spy(pet);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
expect(spy).not.toHaveBeenCalled();
|
|
386
|
+
|
|
387
|
+
await waitFor(() => expect(spy).toHaveBeenCalled());
|
|
388
|
+
|
|
389
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
test("should work when one of the options has a discriminated union field", async () => {
|
|
323
393
|
const Collie = co.map({
|
|
324
394
|
type: z.literal("collie"),
|
|
325
395
|
});
|
|
@@ -371,4 +441,276 @@ describe("co.discriminatedUnion", () => {
|
|
|
371
441
|
assertLoaded(loadedAnimal);
|
|
372
442
|
expect(loadedAnimal.type).toEqual("collie");
|
|
373
443
|
});
|
|
444
|
+
|
|
445
|
+
test("load co.discriminatedUnion with deep resolve using loadCoValue", async () => {
|
|
446
|
+
const Person = co.map({
|
|
447
|
+
name: z.string(),
|
|
448
|
+
});
|
|
449
|
+
const Dog = co.map({
|
|
450
|
+
type: z.literal("dog"),
|
|
451
|
+
owner: Person,
|
|
452
|
+
});
|
|
453
|
+
const Cat = co.map({
|
|
454
|
+
type: z.literal("cat"),
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
const Pet = co.discriminatedUnion("type", [Dog, Cat]);
|
|
458
|
+
|
|
459
|
+
const dog = Dog.create({
|
|
460
|
+
type: "dog",
|
|
461
|
+
owner: Person.create({ name: "John Doe" }),
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
const loadedPet = await loadCoValue(Pet.getCoValueClass(), dog.$jazz.id, {
|
|
465
|
+
resolve: { owner: true },
|
|
466
|
+
loadAs: account,
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
assertLoaded(loadedPet);
|
|
470
|
+
|
|
471
|
+
if (loadedPet.type === "dog") {
|
|
472
|
+
expect(loadedPet.owner.name).toEqual("John Doe");
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
test("load co.discriminatedUnion with non-matching deep resolve", async () => {
|
|
477
|
+
const Person = co.map({
|
|
478
|
+
name: z.string(),
|
|
479
|
+
});
|
|
480
|
+
const Dog = co.map({
|
|
481
|
+
type: z.literal("dog"),
|
|
482
|
+
owner: Person,
|
|
483
|
+
});
|
|
484
|
+
const Cat = co.map({
|
|
485
|
+
type: z.literal("cat"),
|
|
486
|
+
});
|
|
487
|
+
const Pet = co.discriminatedUnion("type", [Dog, Cat]);
|
|
488
|
+
|
|
489
|
+
const cat = Cat.create({
|
|
490
|
+
type: "cat",
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
const loadedPet = await Pet.load(cat.$jazz.id, {
|
|
494
|
+
resolve: { owner: true },
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
assertLoaded(loadedPet);
|
|
498
|
+
|
|
499
|
+
expect(loadedPet.type).toEqual("cat");
|
|
500
|
+
// @ts-expect-error - no owner on Cat
|
|
501
|
+
expect(loadedPet.owner).toBeUndefined();
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
test("load co.discriminatedUnion list with different schemas on deep resolved fields", async () => {
|
|
505
|
+
// Schema without nested CoValues
|
|
506
|
+
const Bird = co.map({
|
|
507
|
+
type: z.literal("bird"),
|
|
508
|
+
species: z.string(),
|
|
509
|
+
});
|
|
510
|
+
const Person = co.map({
|
|
511
|
+
name: z.string(),
|
|
512
|
+
bird: Bird,
|
|
513
|
+
});
|
|
514
|
+
// Schema with a nested CoValue
|
|
515
|
+
const Dog = co.map({
|
|
516
|
+
type: z.literal("dog"),
|
|
517
|
+
friend: Person,
|
|
518
|
+
});
|
|
519
|
+
// Same attribute (friend) with a completely different schema (list)
|
|
520
|
+
const Cat = co.map({
|
|
521
|
+
type: z.literal("cat"),
|
|
522
|
+
get friend() {
|
|
523
|
+
return co.list(Cat);
|
|
524
|
+
},
|
|
525
|
+
});
|
|
526
|
+
const Pet = co.discriminatedUnion("type", [Dog, Cat, Bird]);
|
|
527
|
+
const Pets = co.list(Pet);
|
|
528
|
+
|
|
529
|
+
const bird = Bird.create({
|
|
530
|
+
type: "bird",
|
|
531
|
+
species: "Parrot",
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
const dog = Dog.create({
|
|
535
|
+
type: "dog",
|
|
536
|
+
friend: Person.create({ name: "John Doe", bird }),
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
const cat = Cat.create({
|
|
540
|
+
type: "cat",
|
|
541
|
+
friend: [{ type: "cat", friend: [{ type: "cat", friend: [] }] }],
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
const pets = Pets.create([dog, cat, bird]);
|
|
545
|
+
|
|
546
|
+
const loadedPets = await Pets.load(pets.$jazz.id, {
|
|
547
|
+
resolve: { $each: { friend: { $each: { friend: true }, bird: true } } },
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
assertLoaded(loadedPets);
|
|
551
|
+
|
|
552
|
+
for (const pet of loadedPets) {
|
|
553
|
+
if (pet.type === "dog") {
|
|
554
|
+
expect(pet.friend.name).toEqual("John Doe");
|
|
555
|
+
expect(pet.friend.bird.species).toEqual("Parrot");
|
|
556
|
+
// @ts-expect-error - no species on Person
|
|
557
|
+
expect(pet.friend.species).toBeUndefined();
|
|
558
|
+
} else if (pet.type === "cat") {
|
|
559
|
+
expect(pet.friend[0]?.type).toEqual("cat");
|
|
560
|
+
// @ts-expect-error - no name on Bird
|
|
561
|
+
expect(pet.friend.name).toBeUndefined();
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
test("ensureLoaded on co.discriminatedUnion members", async () => {
|
|
567
|
+
const Person = co.map({
|
|
568
|
+
name: z.string(),
|
|
569
|
+
});
|
|
570
|
+
const Dog = co.map({
|
|
571
|
+
type: z.literal("dog"),
|
|
572
|
+
owner: Person,
|
|
573
|
+
});
|
|
574
|
+
const Cat = co.map({
|
|
575
|
+
type: z.literal("cat"),
|
|
576
|
+
friend: Person,
|
|
577
|
+
});
|
|
578
|
+
const Pet = co.discriminatedUnion("type", [Dog, Cat]);
|
|
579
|
+
|
|
580
|
+
const dog = Dog.create({
|
|
581
|
+
type: "dog",
|
|
582
|
+
owner: Person.create({ name: "John Doe" }),
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
const cat = Cat.create({
|
|
586
|
+
type: "cat",
|
|
587
|
+
friend: Person.create({ name: "Jane Doe" }),
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
const pet = await Pet.load(dog.$jazz.id);
|
|
591
|
+
|
|
592
|
+
assertLoaded(pet);
|
|
593
|
+
|
|
594
|
+
// @ts-expect-error - can't use ensureLoaded before narrowing
|
|
595
|
+
pet.$jazz.ensureLoaded({
|
|
596
|
+
resolve: { owner: true },
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
if (pet.type === "dog") {
|
|
600
|
+
const loadedPet = await pet.$jazz.ensureLoaded({
|
|
601
|
+
resolve: { owner: true },
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
expect(loadedPet.owner.name).toEqual("John Doe");
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
describe("Deep loading mutually exclusive nested CoMaps", async () => {
|
|
609
|
+
const Breed = co.map({
|
|
610
|
+
type: z.enum(["collie", "border-collie"]),
|
|
611
|
+
});
|
|
612
|
+
const Dog = co.map({
|
|
613
|
+
type: z.literal("dog"),
|
|
614
|
+
breed: Breed,
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
const Ocean = co.map({
|
|
618
|
+
name: z.enum(["atlantic", "pacific"]),
|
|
619
|
+
});
|
|
620
|
+
const Shark = co.map({
|
|
621
|
+
type: z.literal("shark"),
|
|
622
|
+
ocean: Ocean,
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
const Animal = co.discriminatedUnion("type", [Dog, Shark]);
|
|
626
|
+
const Species = co.list(Animal);
|
|
627
|
+
|
|
628
|
+
let species: Loaded<typeof Species>;
|
|
629
|
+
|
|
630
|
+
beforeEach(async () => {
|
|
631
|
+
const group = Group.create();
|
|
632
|
+
group.makePublic();
|
|
633
|
+
|
|
634
|
+
species = Species.create(
|
|
635
|
+
[
|
|
636
|
+
{
|
|
637
|
+
type: "dog",
|
|
638
|
+
breed: {
|
|
639
|
+
type: "collie",
|
|
640
|
+
},
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
type: "shark",
|
|
644
|
+
ocean: {
|
|
645
|
+
name: "atlantic",
|
|
646
|
+
},
|
|
647
|
+
},
|
|
648
|
+
],
|
|
649
|
+
group,
|
|
650
|
+
);
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
test("co.discriminatedUnion should load with deeply resolved mutually exclusive nested CoMaps", async () => {
|
|
654
|
+
const loadedSpecies = await Species.load(species.$jazz.id, {
|
|
655
|
+
resolve: {
|
|
656
|
+
$each: {
|
|
657
|
+
breed: true,
|
|
658
|
+
ocean: true,
|
|
659
|
+
},
|
|
660
|
+
},
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
assertLoaded(loadedSpecies);
|
|
664
|
+
|
|
665
|
+
// @ts-expect-error - type needs to be narrowed
|
|
666
|
+
expect(loadedSpecies[0]?.breed.type).toEqual("collie");
|
|
667
|
+
// @ts-expect-error - type needs to be narrowed
|
|
668
|
+
expect(loadedSpecies[1]?.ocean.name).toEqual("atlantic");
|
|
669
|
+
|
|
670
|
+
for (const animal of loadedSpecies) {
|
|
671
|
+
if (animal.type === "dog") {
|
|
672
|
+
expect(animal.breed.type).toBeDefined();
|
|
673
|
+
// @ts-expect-error - no ocean property on Dog
|
|
674
|
+
expect(animal.ocean).toBeUndefined();
|
|
675
|
+
} else if (animal.type === "shark") {
|
|
676
|
+
expect(animal.ocean.name).toBeDefined();
|
|
677
|
+
// @ts-expect-error - no breed property on Shark
|
|
678
|
+
expect(animal.breed).toBeUndefined();
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
test("co.discriminatedUnion should load with deeply resolved nested CoMaps with another account as owner", async () => {
|
|
684
|
+
const alice = await createJazzTestAccount({
|
|
685
|
+
creationProps: { name: "Alice" },
|
|
686
|
+
isCurrentActiveAccount: false,
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
const loadedSpecies = await Species.load(species.$jazz.id, {
|
|
690
|
+
loadAs: alice,
|
|
691
|
+
resolve: {
|
|
692
|
+
$each: {
|
|
693
|
+
breed: true,
|
|
694
|
+
ocean: true,
|
|
695
|
+
},
|
|
696
|
+
},
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
console.log(loadedSpecies.$isLoaded);
|
|
700
|
+
|
|
701
|
+
assertLoaded(loadedSpecies);
|
|
702
|
+
|
|
703
|
+
for (const animal of loadedSpecies) {
|
|
704
|
+
if (animal.type === "dog") {
|
|
705
|
+
expect(animal.breed.type).toBeDefined();
|
|
706
|
+
// @ts-expect-error - no ocean on Dog
|
|
707
|
+
expect(animal.ocean).toBeUndefined();
|
|
708
|
+
} else if (animal.type === "shark") {
|
|
709
|
+
expect(animal.ocean.name).toBeDefined();
|
|
710
|
+
// @ts-expect-error - no breed on Shark
|
|
711
|
+
expect(animal.breed).toBeUndefined();
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
});
|
|
374
716
|
});
|
|
@@ -361,55 +361,49 @@ test("Deep loading a record-like coMap", async () => {
|
|
|
361
361
|
expect(recordLoaded.key2?.list).toBeTruthy();
|
|
362
362
|
});
|
|
363
363
|
|
|
364
|
-
test("The resolve type doesn't accept extra keys", async () => {
|
|
365
|
-
expect.assertions(1);
|
|
366
|
-
|
|
364
|
+
test("The resolve type doesn't accept extra keys, but the load resolves anyway", async () => {
|
|
367
365
|
const me = await CustomAccount.create({
|
|
368
366
|
creationProps: { name: "Hermes Puggington" },
|
|
369
367
|
crypto: Crypto,
|
|
370
368
|
});
|
|
371
369
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
});
|
|
370
|
+
const meLoaded = await me.$jazz.ensureLoaded({
|
|
371
|
+
resolve: {
|
|
372
|
+
// @ts-expect-error
|
|
373
|
+
profile: { stream: true, extraKey: true },
|
|
374
|
+
// @ts-expect-error
|
|
375
|
+
root: { list: true, extraKey: true },
|
|
376
|
+
},
|
|
377
|
+
});
|
|
381
378
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
379
|
+
await me.$jazz.ensureLoaded({
|
|
380
|
+
resolve: {
|
|
381
|
+
// @ts-expect-error
|
|
382
|
+
root: { list: { $each: true, extraKey: true } },
|
|
383
|
+
},
|
|
384
|
+
});
|
|
388
385
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
386
|
+
await me.$jazz.ensureLoaded({
|
|
387
|
+
resolve: {
|
|
388
|
+
root: { list: true },
|
|
389
|
+
// @ts-expect-error
|
|
390
|
+
extraKey: true,
|
|
391
|
+
},
|
|
392
|
+
});
|
|
396
393
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
} catch (e) {
|
|
411
|
-
expect(e).toBeInstanceOf(Error);
|
|
412
|
-
}
|
|
394
|
+
// using assignment to check type compatibility
|
|
395
|
+
const _T:
|
|
396
|
+
| (Loaded<typeof CustomAccount> & {
|
|
397
|
+
profile: Loaded<typeof CustomProfile> & {
|
|
398
|
+
stream: Loaded<typeof TestFeed>;
|
|
399
|
+
extraKey: never;
|
|
400
|
+
};
|
|
401
|
+
root: Loaded<typeof TestMap> & {
|
|
402
|
+
list: Loaded<typeof TestList>;
|
|
403
|
+
extraKey: never;
|
|
404
|
+
};
|
|
405
|
+
})
|
|
406
|
+
| null = meLoaded;
|
|
413
407
|
});
|
|
414
408
|
|
|
415
409
|
test("The resolve type accepts keys from optional fields", async () => {
|
|
@@ -435,7 +429,7 @@ test("The resolve type accepts keys from optional fields", async () => {
|
|
|
435
429
|
expect(pets[0]?.owner?.name).toEqual("Rex");
|
|
436
430
|
});
|
|
437
431
|
|
|
438
|
-
test("The resolve type
|
|
432
|
+
test("The resolve type accepts keys from discriminated unions", async () => {
|
|
439
433
|
const Person = co.map({
|
|
440
434
|
name: z.string(),
|
|
441
435
|
});
|
|
@@ -449,24 +443,25 @@ test("The resolve type doesn't accept keys from discriminated unions", async ()
|
|
|
449
443
|
const Pet = co.discriminatedUnion("type", [Dog, Cat]);
|
|
450
444
|
const Pets = co.list(Pet);
|
|
451
445
|
|
|
452
|
-
const pets =
|
|
446
|
+
const pets = Pets.create([
|
|
453
447
|
Dog.create({ type: "dog", owner: Person.create({ name: "Rex" }) }),
|
|
448
|
+
Cat.create({ type: "cat" }),
|
|
454
449
|
]);
|
|
455
450
|
|
|
456
451
|
await pets.$jazz.ensureLoaded({
|
|
457
|
-
resolve: {
|
|
458
|
-
$each: true,
|
|
459
|
-
},
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
await pets.$jazz.ensureLoaded({
|
|
463
|
-
// @ts-expect-error cannot resolve owner
|
|
464
452
|
resolve: { $each: { owner: true } },
|
|
465
453
|
});
|
|
466
454
|
|
|
467
455
|
expect(pets).toBeTruthy();
|
|
468
|
-
|
|
469
|
-
|
|
456
|
+
|
|
457
|
+
for (const pet of pets) {
|
|
458
|
+
if (pet.type === "dog") {
|
|
459
|
+
expect(pet.owner?.name).toEqual("Rex");
|
|
460
|
+
} else {
|
|
461
|
+
expect("owner" in pet).toEqual(false);
|
|
462
|
+
// @ts-expect-error - this should still not appear in the types
|
|
463
|
+
expect(pet.owner).toBeUndefined();
|
|
464
|
+
}
|
|
470
465
|
}
|
|
471
466
|
});
|
|
472
467
|
|
|
@@ -1110,7 +1105,7 @@ test("throw when calling ensureLoaded on a ref that's required but missing", asy
|
|
|
1110
1105
|
).rejects.toThrow("Failed to deeply load CoValue " + root.$jazz.id);
|
|
1111
1106
|
});
|
|
1112
1107
|
|
|
1113
|
-
test("
|
|
1108
|
+
test("returns the value when calling ensureLoaded on a ref that is not defined in the schema", async () => {
|
|
1114
1109
|
const JazzRoot = co.map({});
|
|
1115
1110
|
|
|
1116
1111
|
const me = await Account.create({
|
|
@@ -1120,12 +1115,13 @@ test("throw when calling ensureLoaded on a ref that is not defined in the schema
|
|
|
1120
1115
|
|
|
1121
1116
|
const root = JazzRoot.create({}, { owner: me });
|
|
1122
1117
|
|
|
1123
|
-
await
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1118
|
+
const loadedRoot = await JazzRoot.load(root.$jazz.id, {
|
|
1119
|
+
// @ts-expect-error missing required ref
|
|
1120
|
+
resolve: { profile: true },
|
|
1121
|
+
loadAs: me,
|
|
1122
|
+
});
|
|
1123
|
+
|
|
1124
|
+
expect(loadedRoot.$jazz.loadingState).toBe(CoValueLoadingState.LOADED);
|
|
1129
1125
|
});
|
|
1130
1126
|
|
|
1131
1127
|
test("should not throw when calling ensureLoaded a record with a deleted ref", async () => {
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
assert,
|
|
3
|
+
beforeAll,
|
|
4
|
+
describe,
|
|
5
|
+
expect,
|
|
6
|
+
expectTypeOf,
|
|
7
|
+
test,
|
|
8
|
+
} from "vitest";
|
|
2
9
|
import {
|
|
3
10
|
Account,
|
|
4
11
|
co,
|
|
@@ -104,6 +111,27 @@ describe("Schema.resolved()", () => {
|
|
|
104
111
|
profile: true,
|
|
105
112
|
});
|
|
106
113
|
});
|
|
114
|
+
|
|
115
|
+
test("to a DiscriminatedUnion schema", () => {
|
|
116
|
+
const Pet = co.discriminatedUnion("type", [
|
|
117
|
+
co.map({
|
|
118
|
+
type: z.literal("dog"),
|
|
119
|
+
name: co.plainText(),
|
|
120
|
+
}),
|
|
121
|
+
co.map({
|
|
122
|
+
type: z.literal("cat"),
|
|
123
|
+
name: co.plainText(),
|
|
124
|
+
}),
|
|
125
|
+
]);
|
|
126
|
+
|
|
127
|
+
const PetWithName = Pet.resolved({
|
|
128
|
+
name: true,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
expect(PetWithName.resolveQuery).toEqual({
|
|
132
|
+
name: true,
|
|
133
|
+
});
|
|
134
|
+
});
|
|
107
135
|
});
|
|
108
136
|
|
|
109
137
|
describe("the schema's resolve query is used when loading CoValues", () => {
|
|
@@ -234,6 +262,47 @@ describe("Schema.resolved()", () => {
|
|
|
234
262
|
expect(loadedAccount.profile.$isLoaded).toBe(true);
|
|
235
263
|
expect(loadedAccount.profile.name).toBe("Hermes Puggington");
|
|
236
264
|
});
|
|
265
|
+
|
|
266
|
+
test("for DiscriminatedUnion", async () => {
|
|
267
|
+
const Person = co.map({
|
|
268
|
+
name: co.plainText(),
|
|
269
|
+
});
|
|
270
|
+
const Dog = co.map({
|
|
271
|
+
type: z.literal("dog"),
|
|
272
|
+
name: co.plainText(),
|
|
273
|
+
owner: Person,
|
|
274
|
+
});
|
|
275
|
+
const Cat = co.map({
|
|
276
|
+
type: z.literal("cat"),
|
|
277
|
+
name: co.plainText(),
|
|
278
|
+
});
|
|
279
|
+
const Pet = co.discriminatedUnion("type", [Dog, Cat]).resolved({
|
|
280
|
+
name: true,
|
|
281
|
+
owner: {
|
|
282
|
+
name: true,
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const dog = Dog.create(
|
|
287
|
+
{
|
|
288
|
+
type: "dog",
|
|
289
|
+
name: "Rex",
|
|
290
|
+
owner: { name: "Lewis" },
|
|
291
|
+
},
|
|
292
|
+
publicGroup,
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
const loadedDiscriminatedUnion = await Pet.load(dog.$jazz.id, {
|
|
296
|
+
loadAs: clientAccount,
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
assertLoaded(loadedDiscriminatedUnion);
|
|
300
|
+
expect(loadedDiscriminatedUnion.name.$isLoaded).toBe(true);
|
|
301
|
+
expect(loadedDiscriminatedUnion.name.toUpperCase()).toBe("REX");
|
|
302
|
+
|
|
303
|
+
assert(loadedDiscriminatedUnion.type === "dog");
|
|
304
|
+
expect(loadedDiscriminatedUnion.owner.name.toUpperCase()).toBe("LEWIS");
|
|
305
|
+
});
|
|
237
306
|
});
|
|
238
307
|
|
|
239
308
|
describe("on subscribe()", () => {
|