jazz-tools 0.18.19 → 0.18.20
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 +47 -47
- package/CHANGELOG.md +16 -0
- package/dist/browser/index.js +2 -2
- package/dist/browser/index.js.map +1 -1
- package/dist/{chunk-RN3Y24WX.js → chunk-TVHI2UMO.js} +48 -1
- package/dist/chunk-TVHI2UMO.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/react-core/hooks.d.ts.map +1 -1
- package/dist/react-core/index.js +2 -2
- package/dist/react-core/index.js.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/tools/coValues/coList.d.ts.map +1 -1
- package/dist/tools/coValues/coPlainText.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts +1 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.d.ts +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodReExport.d.ts +1 -1
- package/dist/tools/implementation/zodSchema/zodReExport.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/browser/auth/PasskeyAuth.ts +2 -2
- package/src/react-core/hooks.ts +3 -2
- package/src/react-core/tests/useInboxSender.test.ts +37 -3
- package/src/tools/coValues/coList.ts +11 -0
- package/src/tools/coValues/coPlainText.ts +9 -0
- package/src/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.ts +47 -2
- package/src/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.ts +9 -4
- package/src/tools/implementation/zodSchema/zodReExport.ts +1 -0
- package/src/tools/tests/coList.test.ts +34 -0
- package/src/tools/tests/coPlainText.test.ts +25 -1
- package/src/tools/tests/zod.test.ts +131 -0
- package/dist/chunk-RN3Y24WX.js.map +0 -1
- package/jazz-tools-0.18.6.tgz +0 -0
@@ -680,6 +680,40 @@ describe("CoList applyDiff operations", async () => {
|
|
680
680
|
list.$jazz.applyDiff(["e", "c", "new", "y", "x"]);
|
681
681
|
expect(list.$jazz.raw.asArray()).toEqual(["e", "c", "new", "y", "x"]);
|
682
682
|
});
|
683
|
+
|
684
|
+
test("applyDiff should emit a single update", () => {
|
685
|
+
const TestMap = co.map({
|
686
|
+
type: z.string(),
|
687
|
+
});
|
688
|
+
|
689
|
+
const TestList = co.list(TestMap);
|
690
|
+
|
691
|
+
const bread = TestMap.create({ type: "bread" }, me);
|
692
|
+
const butter = TestMap.create({ type: "butter" }, me);
|
693
|
+
const onion = TestMap.create({ type: "onion" }, me);
|
694
|
+
|
695
|
+
const list = TestList.create([bread, butter, onion], me);
|
696
|
+
|
697
|
+
const updateFn = vi.fn();
|
698
|
+
|
699
|
+
const unsubscribe = TestList.subscribe(
|
700
|
+
list.$jazz.id,
|
701
|
+
{
|
702
|
+
resolve: {
|
703
|
+
$each: true,
|
704
|
+
},
|
705
|
+
},
|
706
|
+
updateFn,
|
707
|
+
);
|
708
|
+
|
709
|
+
updateFn.mockClear();
|
710
|
+
|
711
|
+
list.$jazz.applyDiff([bread]);
|
712
|
+
|
713
|
+
expect(updateFn).toHaveBeenCalledTimes(1);
|
714
|
+
|
715
|
+
unsubscribe();
|
716
|
+
});
|
683
717
|
});
|
684
718
|
|
685
719
|
describe("CoList resolution", async () => {
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { WasmCrypto } from "cojson/crypto/WasmCrypto";
|
2
2
|
import { Channel } from "queueueue";
|
3
|
-
import { describe, expect, test } from "vitest";
|
3
|
+
import { describe, expect, test, vi } from "vitest";
|
4
4
|
import {
|
5
5
|
Account,
|
6
6
|
cojsonInternals,
|
@@ -94,6 +94,30 @@ describe("CoPlainText", () => {
|
|
94
94
|
text.$jazz.applyDiff(`😊👋 안녕!`);
|
95
95
|
expect(text.toString()).toEqual(`😊👋 안녕!`);
|
96
96
|
});
|
97
|
+
|
98
|
+
test("applyDiff should emit a single update", () => {
|
99
|
+
const Text = co.plainText();
|
100
|
+
|
101
|
+
const text = Text.create(`😊`, { owner: me });
|
102
|
+
|
103
|
+
const updateFn = vi.fn();
|
104
|
+
|
105
|
+
const unsubscribe = Text.subscribe(
|
106
|
+
text.$jazz.id,
|
107
|
+
{
|
108
|
+
loadAs: me,
|
109
|
+
},
|
110
|
+
updateFn,
|
111
|
+
);
|
112
|
+
|
113
|
+
updateFn.mockClear();
|
114
|
+
|
115
|
+
text.$jazz.applyDiff(`😊👋 안녕!`);
|
116
|
+
|
117
|
+
expect(updateFn).toHaveBeenCalledTimes(1);
|
118
|
+
|
119
|
+
unsubscribe();
|
120
|
+
});
|
97
121
|
});
|
98
122
|
|
99
123
|
describe("Properties", () => {
|
@@ -511,6 +511,137 @@ describe("co.map and Zod schema compatibility", () => {
|
|
511
511
|
expect(map.readonly).toEqual({ name: "John" });
|
512
512
|
});
|
513
513
|
});
|
514
|
+
|
515
|
+
describe("Codec types", () => {
|
516
|
+
class DateRange {
|
517
|
+
constructor(
|
518
|
+
public start: Date,
|
519
|
+
public end: Date,
|
520
|
+
) {}
|
521
|
+
|
522
|
+
isDateInRange(date: Date) {
|
523
|
+
return date >= this.start && date <= this.end;
|
524
|
+
}
|
525
|
+
}
|
526
|
+
|
527
|
+
const dateRangeCodec = z.codec(
|
528
|
+
z.tuple([z.string(), z.string()]),
|
529
|
+
z.z.instanceof(DateRange),
|
530
|
+
{
|
531
|
+
encode: (value) =>
|
532
|
+
[value.start.toISOString(), value.end.toISOString()] as [
|
533
|
+
string,
|
534
|
+
string,
|
535
|
+
],
|
536
|
+
decode: ([start, end]) => {
|
537
|
+
return new DateRange(new Date(start), new Date(end));
|
538
|
+
},
|
539
|
+
},
|
540
|
+
);
|
541
|
+
|
542
|
+
it("should handle codec field", async () => {
|
543
|
+
const schema = co.map({
|
544
|
+
range: dateRangeCodec,
|
545
|
+
});
|
546
|
+
|
547
|
+
const map = schema.create({
|
548
|
+
range: new DateRange(new Date("2025-01-01"), new Date("2025-01-31")),
|
549
|
+
});
|
550
|
+
|
551
|
+
expect(map.range.isDateInRange(new Date("2025-01-15"))).toEqual(true);
|
552
|
+
});
|
553
|
+
|
554
|
+
it("should handle codec field with RegExp", async () => {
|
555
|
+
const schema = co.map({
|
556
|
+
regexp: z.codec(z.string(), z.z.instanceof(RegExp), {
|
557
|
+
encode: (value) => value.toString(),
|
558
|
+
decode: (value) => {
|
559
|
+
const [, pattern, flags] = value.match(/^\/(.*)\/([a-z]*)$/i)!;
|
560
|
+
if (!pattern) throw new Error("Invalid RegExp string");
|
561
|
+
return new RegExp(pattern, flags);
|
562
|
+
},
|
563
|
+
}),
|
564
|
+
});
|
565
|
+
|
566
|
+
const map = schema.create({
|
567
|
+
regexp: /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/,
|
568
|
+
});
|
569
|
+
|
570
|
+
expect(map.regexp.test("2001-01-31")).toEqual(true);
|
571
|
+
});
|
572
|
+
|
573
|
+
it("should handle optional codec field", async () => {
|
574
|
+
const schema = co.map({
|
575
|
+
range: dateRangeCodec.optional(),
|
576
|
+
});
|
577
|
+
const map = schema.create({});
|
578
|
+
|
579
|
+
expect(map.range).toBeUndefined();
|
580
|
+
expect(map.$jazz.has("range")).toEqual(false);
|
581
|
+
});
|
582
|
+
|
583
|
+
it("should handle nullable codec field", async () => {
|
584
|
+
const schema = co.map({
|
585
|
+
range: dateRangeCodec.nullable(),
|
586
|
+
});
|
587
|
+
const map = schema.create({ range: null });
|
588
|
+
|
589
|
+
expect(map.range).toBeNull();
|
590
|
+
|
591
|
+
map.$jazz.set(
|
592
|
+
"range",
|
593
|
+
new DateRange(new Date("2025-01-01"), new Date("2025-01-31")),
|
594
|
+
);
|
595
|
+
expect(map.range?.isDateInRange(new Date("2025-01-15"))).toEqual(true);
|
596
|
+
});
|
597
|
+
|
598
|
+
it("should handle nullish codec field", async () => {
|
599
|
+
const schema = co.map({
|
600
|
+
range: dateRangeCodec.nullish(),
|
601
|
+
});
|
602
|
+
|
603
|
+
const map = schema.create({});
|
604
|
+
expect(map.range).toBeUndefined();
|
605
|
+
expect(map.$jazz.has("range")).toEqual(false);
|
606
|
+
|
607
|
+
map.$jazz.set("range", undefined);
|
608
|
+
expect(map.range).toBeUndefined();
|
609
|
+
expect(map.$jazz.has("range")).toEqual(true);
|
610
|
+
|
611
|
+
map.$jazz.set("range", null);
|
612
|
+
expect(map.range).toBeNull();
|
613
|
+
|
614
|
+
map.$jazz.set(
|
615
|
+
"range",
|
616
|
+
new DateRange(new Date("2025-01-01"), new Date("2025-01-31")),
|
617
|
+
);
|
618
|
+
expect(map.range?.isDateInRange(new Date("2025-01-15"))).toEqual(true);
|
619
|
+
});
|
620
|
+
|
621
|
+
it("should not handle codec field with unsupported inner field", async () => {
|
622
|
+
const schema = co.map({
|
623
|
+
record: z.codec(
|
624
|
+
z.z.map(z.string(), z.string()),
|
625
|
+
z.z.record(z.string(), z.string()),
|
626
|
+
{
|
627
|
+
encode: (value) => new Map(Object.entries(value)),
|
628
|
+
decode: (value) => Object.fromEntries(value.entries()),
|
629
|
+
},
|
630
|
+
),
|
631
|
+
});
|
632
|
+
|
633
|
+
expect(() =>
|
634
|
+
schema.create({
|
635
|
+
record: {
|
636
|
+
key1: "value1",
|
637
|
+
key2: "value2",
|
638
|
+
},
|
639
|
+
}),
|
640
|
+
).toThrow(
|
641
|
+
"z.codec() is only supported if the input schema is already supported. Unsupported zod type: map",
|
642
|
+
);
|
643
|
+
});
|
644
|
+
});
|
514
645
|
});
|
515
646
|
|
516
647
|
describe("z.object() and CoValue schema compatibility", () => {
|