jazz-tools 0.16.0 → 0.16.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.
Files changed (59) hide show
  1. package/.turbo/turbo-build.log +31 -31
  2. package/CHANGELOG.md +9 -0
  3. package/dist/{chunk-MLCNE3TL.js → chunk-CL3ROOZM.js} +7 -3
  4. package/dist/chunk-CL3ROOZM.js.map +1 -0
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/testing.js +1 -1
  8. package/dist/tools/coValues/coMap.d.ts +4 -6
  9. package/dist/tools/coValues/coMap.d.ts.map +1 -1
  10. package/dist/tools/coValues/request.d.ts +2 -2
  11. package/dist/tools/coValues/request.d.ts.map +1 -1
  12. package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts +1 -1
  13. package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts.map +1 -1
  14. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +3 -2
  15. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
  16. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +3 -2
  17. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
  18. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +13 -24
  19. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
  20. package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts +3 -2
  21. package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts.map +1 -1
  22. package/dist/tools/implementation/zodSchema/typeConverters/CoFieldInit.d.ts +10 -0
  23. package/dist/tools/implementation/zodSchema/typeConverters/CoFieldInit.d.ts.map +1 -0
  24. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts +2 -2
  25. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts.map +1 -1
  26. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts +2 -2
  27. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts.map +1 -1
  28. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.d.ts +2 -2
  29. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.d.ts.map +1 -1
  30. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.d.ts +2 -2
  31. package/dist/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.d.ts.map +1 -1
  32. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  33. package/dist/tools/implementation/zodSchema/zodSchema.d.ts +2 -2
  34. package/dist/tools/implementation/zodSchema/zodSchema.d.ts.map +1 -1
  35. package/dist/tools/lib/utilityTypes.d.ts +8 -0
  36. package/dist/tools/lib/utilityTypes.d.ts.map +1 -1
  37. package/package.json +4 -4
  38. package/src/tools/coValues/coMap.ts +4 -7
  39. package/src/tools/coValues/request.ts +2 -2
  40. package/src/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.ts +18 -2
  41. package/src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +2 -2
  42. package/src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts +2 -2
  43. package/src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts +21 -42
  44. package/src/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.ts +2 -2
  45. package/src/tools/implementation/zodSchema/typeConverters/CoFieldInit.ts +13 -0
  46. package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.ts +4 -5
  47. package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.ts +5 -5
  48. package/src/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchema.ts +53 -52
  49. package/src/tools/implementation/zodSchema/typeConverters/InstanceOrPrimitiveOfSchemaCoValuesNullable.ts +56 -54
  50. package/src/tools/implementation/zodSchema/zodCo.ts +2 -2
  51. package/src/tools/implementation/zodSchema/zodSchema.ts +2 -2
  52. package/src/tools/lib/utilityTypes.ts +9 -0
  53. package/src/tools/tests/coFeed.test.ts +8 -6
  54. package/src/tools/tests/coList.test.ts +10 -0
  55. package/src/tools/tests/coMap.record.test.ts +9 -0
  56. package/src/tools/tests/coMap.test-d.ts +29 -1
  57. package/src/tools/tests/coMap.test.ts +69 -2
  58. package/src/tools/tests/zod.test.ts +38 -0
  59. package/dist/chunk-MLCNE3TL.js.map +0 -1
@@ -41,12 +41,11 @@ export type InstanceOrPrimitiveOfSchema<
41
41
  -readonly [key in keyof Shape]: InstanceOrPrimitiveOfSchema<
42
42
  Shape[key]
43
43
  >;
44
- } & (unknown extends CatchAll
45
- ? {}
46
- : {
47
- // @ts-expect-error
44
+ } & (CatchAll extends AnyZodOrCoValueSchema
45
+ ? {
48
46
  [key: string]: InstanceOrPrimitiveOfSchema<CatchAll>;
49
- }) &
47
+ }
48
+ : {}) &
50
49
  CoMap
51
50
  : S extends CoreCoListSchema<infer T>
52
51
  ? CoList<InstanceOrPrimitiveOfSchema<T>>
@@ -66,56 +65,58 @@ export type InstanceOrPrimitiveOfSchema<
66
65
  : S extends z.core.$ZodType
67
66
  ? S extends z.core.$ZodOptional<infer Inner extends z.core.$ZodType>
68
67
  ? InstanceOrPrimitiveOfSchema<Inner> | undefined
69
- : S extends z.ZodJSONSchema
70
- ? JsonValue
71
- : S extends z.core.$ZodUnion<infer Members extends z.core.$ZodType[]>
72
- ? InstanceOrPrimitiveOfSchema<Members[number]>
73
- : // primitives below here - we manually traverse to ensure we only allow what we can handle
74
- S extends z.core.$ZodObject<infer Shape>
75
- ? {
76
- -readonly [key in keyof Shape]: InstanceOrPrimitiveOfSchema<
77
- Shape[key]
78
- >;
79
- }
80
- : S extends z.core.$ZodArray<infer Item extends z.core.$ZodType>
81
- ? InstanceOrPrimitiveOfSchema<Item>[]
82
- : S extends z.core.$ZodTuple<
83
- infer Items extends readonly z.core.$ZodType[]
84
- >
85
- ? {
86
- [key in keyof Items]: InstanceOrPrimitiveOfSchema<
87
- Items[key]
88
- >;
89
- }
90
- : S extends z.core.$ZodString
91
- ? string
92
- : S extends z.core.$ZodNumber
93
- ? number
94
- : S extends z.core.$ZodBoolean
95
- ? boolean
96
- : S extends z.core.$ZodLiteral<infer Literal>
97
- ? Literal
98
- : S extends z.core.$ZodDate
99
- ? Date
100
- : S extends z.core.$ZodEnum<infer Enum>
101
- ? Enum[keyof Enum]
102
- : S extends z.core.$ZodTemplateLiteral<
103
- infer pattern
104
- >
105
- ? pattern
106
- : S extends z.core.$ZodReadonly<
107
- infer Inner extends z.core.$ZodType
68
+ : S extends z.core.$ZodNullable<infer Inner extends z.core.$ZodType>
69
+ ? InstanceOrPrimitiveOfSchema<Inner> | null
70
+ : S extends z.ZodJSONSchema
71
+ ? JsonValue
72
+ : S extends z.core.$ZodUnion<infer Members extends z.core.$ZodType[]>
73
+ ? InstanceOrPrimitiveOfSchema<Members[number]>
74
+ : // primitives below here - we manually traverse to ensure we only allow what we can handle
75
+ S extends z.core.$ZodObject<infer Shape>
76
+ ? {
77
+ -readonly [key in keyof Shape]: InstanceOrPrimitiveOfSchema<
78
+ Shape[key]
79
+ >;
80
+ }
81
+ : S extends z.core.$ZodArray<infer Item extends z.core.$ZodType>
82
+ ? InstanceOrPrimitiveOfSchema<Item>[]
83
+ : S extends z.core.$ZodTuple<
84
+ infer Items extends readonly z.core.$ZodType[]
85
+ >
86
+ ? {
87
+ [key in keyof Items]: InstanceOrPrimitiveOfSchema<
88
+ Items[key]
89
+ >;
90
+ }
91
+ : S extends z.core.$ZodString
92
+ ? string
93
+ : S extends z.core.$ZodNumber
94
+ ? number
95
+ : S extends z.core.$ZodBoolean
96
+ ? boolean
97
+ : S extends z.core.$ZodLiteral<infer Literal>
98
+ ? Literal
99
+ : S extends z.core.$ZodDate
100
+ ? Date
101
+ : S extends z.core.$ZodEnum<infer Enum>
102
+ ? Enum[keyof Enum]
103
+ : S extends z.core.$ZodTemplateLiteral<
104
+ infer pattern
108
105
  >
109
- ? InstanceOrPrimitiveOfSchema<Inner>
110
- : S extends z.core.$ZodDefault<
111
- infer Default extends z.core.$ZodType
106
+ ? pattern
107
+ : S extends z.core.$ZodReadonly<
108
+ infer Inner extends z.core.$ZodType
112
109
  >
113
- ? InstanceOrPrimitiveOfSchema<Default>
114
- : S extends z.core.$ZodCatch<
115
- infer Catch extends z.core.$ZodType
110
+ ? InstanceOrPrimitiveOfSchema<Inner>
111
+ : S extends z.core.$ZodDefault<
112
+ infer Default extends z.core.$ZodType
116
113
  >
117
- ? InstanceOrPrimitiveOfSchema<Catch>
118
- : never
114
+ ? InstanceOrPrimitiveOfSchema<Default>
115
+ : S extends z.core.$ZodCatch<
116
+ infer Catch extends z.core.$ZodType
117
+ >
118
+ ? InstanceOrPrimitiveOfSchema<Catch>
119
+ : never
119
120
  : S extends CoValueClass
120
121
  ? InstanceType<S>
121
122
  : never;
@@ -49,13 +49,13 @@ export type InstanceOrPrimitiveOfSchemaCoValuesNullable<
49
49
  -readonly [key in keyof Shape]: InstanceOrPrimitiveOfSchemaCoValuesNullable<
50
50
  Shape[key]
51
51
  >;
52
- } & (unknown extends CatchAll
53
- ? {}
54
- : {
52
+ } & (CatchAll extends AnyZodOrCoValueSchema
53
+ ? {
55
54
  [
56
- key: string // @ts-expect-error
55
+ key: string
57
56
  ]: InstanceOrPrimitiveOfSchemaCoValuesNullable<CatchAll>;
58
- }) &
57
+ }
58
+ : {}) &
59
59
  CoMap)
60
60
  | null
61
61
  : S extends CoreCoListSchema<infer T>
@@ -78,58 +78,60 @@ export type InstanceOrPrimitiveOfSchemaCoValuesNullable<
78
78
  : S extends z.core.$ZodType
79
79
  ? S extends z.core.$ZodOptional<infer Inner extends z.core.$ZodType>
80
80
  ? InstanceOrPrimitiveOfSchemaCoValuesNullable<Inner> | undefined
81
- : S extends z.ZodJSONSchema
82
- ? JsonValue
83
- : S extends z.core.$ZodUnion<
84
- infer Members extends readonly z.core.$ZodType[]
85
- >
86
- ? InstanceOrPrimitiveOfSchemaCoValuesNullable<Members[number]>
87
- : // primitives below here - we manually traverse to ensure we only allow what we can handle
88
- S extends z.core.$ZodObject<infer Shape>
89
- ? {
90
- -readonly [key in keyof Shape]: InstanceOrPrimitiveOfSchema<
91
- Shape[key]
92
- >;
93
- }
94
- : S extends z.core.$ZodArray<infer Item extends z.core.$ZodType>
95
- ? InstanceOrPrimitiveOfSchema<Item>[]
96
- : S extends z.core.$ZodTuple<
97
- infer Items extends z.core.$ZodType[]
98
- >
99
- ? {
100
- [key in keyof Items]: InstanceOrPrimitiveOfSchema<
101
- Items[key]
102
- >;
103
- }
104
- : S extends z.core.$ZodString
105
- ? string
106
- : S extends z.core.$ZodNumber
107
- ? number
108
- : S extends z.core.$ZodBoolean
109
- ? boolean
110
- : S extends z.core.$ZodLiteral<infer Literal>
111
- ? Literal
112
- : S extends z.core.$ZodDate
113
- ? Date
114
- : S extends z.core.$ZodEnum<infer Enum>
115
- ? Enum[keyof Enum]
116
- : S extends z.core.$ZodTemplateLiteral<
117
- infer pattern
118
- >
119
- ? pattern
120
- : S extends z.core.$ZodReadonly<
121
- infer Inner extends z.core.$ZodType
81
+ : S extends z.core.$ZodNullable<infer Inner extends z.core.$ZodType>
82
+ ? InstanceOrPrimitiveOfSchemaCoValuesNullable<Inner> | null
83
+ : S extends z.ZodJSONSchema
84
+ ? JsonValue
85
+ : S extends z.core.$ZodUnion<
86
+ infer Members extends readonly z.core.$ZodType[]
87
+ >
88
+ ? InstanceOrPrimitiveOfSchemaCoValuesNullable<Members[number]>
89
+ : // primitives below here - we manually traverse to ensure we only allow what we can handle
90
+ S extends z.core.$ZodObject<infer Shape>
91
+ ? {
92
+ -readonly [key in keyof Shape]: InstanceOrPrimitiveOfSchema<
93
+ Shape[key]
94
+ >;
95
+ }
96
+ : S extends z.core.$ZodArray<infer Item extends z.core.$ZodType>
97
+ ? InstanceOrPrimitiveOfSchema<Item>[]
98
+ : S extends z.core.$ZodTuple<
99
+ infer Items extends z.core.$ZodType[]
100
+ >
101
+ ? {
102
+ [key in keyof Items]: InstanceOrPrimitiveOfSchema<
103
+ Items[key]
104
+ >;
105
+ }
106
+ : S extends z.core.$ZodString
107
+ ? string
108
+ : S extends z.core.$ZodNumber
109
+ ? number
110
+ : S extends z.core.$ZodBoolean
111
+ ? boolean
112
+ : S extends z.core.$ZodLiteral<infer Literal>
113
+ ? Literal
114
+ : S extends z.core.$ZodDate
115
+ ? Date
116
+ : S extends z.core.$ZodEnum<infer Enum>
117
+ ? Enum[keyof Enum]
118
+ : S extends z.core.$ZodTemplateLiteral<
119
+ infer pattern
122
120
  >
123
- ? InstanceOrPrimitiveOfSchema<Inner>
124
- : S extends z.core.$ZodDefault<
125
- infer Default extends z.core.$ZodType
121
+ ? pattern
122
+ : S extends z.core.$ZodReadonly<
123
+ infer Inner extends z.core.$ZodType
126
124
  >
127
- ? InstanceOrPrimitiveOfSchema<Default>
128
- : S extends z.core.$ZodCatch<
129
- infer Catch extends z.core.$ZodType
125
+ ? InstanceOrPrimitiveOfSchema<Inner>
126
+ : S extends z.core.$ZodDefault<
127
+ infer Default extends z.core.$ZodType
130
128
  >
131
- ? InstanceOrPrimitiveOfSchema<Catch>
132
- : never
129
+ ? InstanceOrPrimitiveOfSchema<Default>
130
+ : S extends z.core.$ZodCatch<
131
+ infer Catch extends z.core.$ZodType
132
+ >
133
+ ? InstanceOrPrimitiveOfSchema<Catch>
134
+ : never
133
135
  : S extends CoValueClass
134
136
  ? InstanceType<S> | null
135
137
  : never;
@@ -108,7 +108,7 @@ export const coListDefiner = <T extends AnyZodOrCoValueSchema>(
108
108
  element: T,
109
109
  ): CoListSchema<T> => {
110
110
  const coreSchema = createCoreCoListSchema(element);
111
- return hydrateCoreCoValueSchema(coreSchema) as unknown as CoListSchema<T>;
111
+ return hydrateCoreCoValueSchema(coreSchema);
112
112
  };
113
113
 
114
114
  export const coProfileDefiner = <
@@ -121,7 +121,7 @@ export const coProfileDefiner = <
121
121
  inbox: z.optional(z.string()),
122
122
  inboxInvite: z.optional(z.string()),
123
123
  });
124
- return coMapDefiner(ehnancedShape) as CoProfileSchema<Shape>;
124
+ return coMapDefiner(ehnancedShape) as unknown as CoProfileSchema<Shape>;
125
125
  };
126
126
 
127
127
  export const coFeedDefiner = <T extends AnyZodOrCoValueSchema>(
@@ -24,8 +24,8 @@ import {
24
24
  import { CoFeedSchema, CoreCoFeedSchema } from "./schemaTypes/CoFeedSchema.js";
25
25
  import { CoListSchema, CoreCoListSchema } from "./schemaTypes/CoListSchema.js";
26
26
  import {
27
- CoMapInitZod,
28
27
  CoMapSchema,
28
+ CoMapSchemaInit,
29
29
  CoreCoMapSchema,
30
30
  } from "./schemaTypes/CoMapSchema.js";
31
31
  import {
@@ -126,5 +126,5 @@ export type ResolveQueryStrict<
126
126
  export type InitFor<T extends CoValueClassOrSchema> = T extends CoreCoMapSchema<
127
127
  infer Shape
128
128
  >
129
- ? Simplify<CoMapInitZod<Shape>>
129
+ ? Simplify<CoMapSchemaInit<Shape>>
130
130
  : never;
@@ -1,3 +1,12 @@
1
+ /**
2
+ * Make any property optional if its type includes `undefined`, preserving the type as-is
3
+ */
4
+ export type PartialOnUndefined<T> = {
5
+ [K in keyof T as undefined extends T[K] ? never : K]: T[K];
6
+ } & {
7
+ [K in keyof T as undefined extends T[K] ? K : never]?: T[K];
8
+ };
9
+
1
10
  /**
2
11
  * Useful to flatten the type output to improve type hints shown in editors.
3
12
  * And also to transform an interface into a type to aide with assignability.
@@ -13,15 +13,9 @@ import {
13
13
  FileStream,
14
14
  Group,
15
15
  co,
16
- cojsonInternals,
17
16
  isControlledAccount,
18
17
  z,
19
18
  } from "../index.js";
20
- import {
21
- Loaded,
22
- createJazzContextFromExistingCredentials,
23
- randomSessionProvider,
24
- } from "../internal.js";
25
19
  import { createJazzTestAccount, setupJazzTestSync } from "../testing.js";
26
20
  import { setupTwoNodes } from "./utils.js";
27
21
 
@@ -58,6 +52,14 @@ describe("Simple CoFeed operations", async () => {
58
52
  expect(stream.perSession[me.sessionID]?.value).toEqual("milk");
59
53
  });
60
54
 
55
+ test("Construction with nullable values", () => {
56
+ const NullableTestStream = co.feed(z.string().nullable());
57
+ const stream = NullableTestStream.create(["milk", null], { owner: me });
58
+
59
+ expect(stream.perAccount[me.id]?.value).toEqual(null);
60
+ expect(stream.perSession[me.sessionID]?.value).toEqual(null);
61
+ });
62
+
61
63
  test("Construction with an Account", () => {
62
64
  const stream = TestStream.create(["milk"], me);
63
65
 
@@ -52,6 +52,16 @@ describe("Simple CoList operations", async () => {
52
52
  expect(list[2]).toBe("c");
53
53
  });
54
54
 
55
+ test("list with nullable content", () => {
56
+ const List = co.list(z.string().nullable());
57
+ const list = List.create(["a", "b", "c", null]);
58
+ expect(list.length).toBe(4);
59
+ expect(list[0]).toBe("a");
60
+ expect(list[1]).toBe("b");
61
+ expect(list[2]).toBe("c");
62
+ expect(list[3]).toBeNull();
63
+ });
64
+
55
65
  test("Construction with an Account", () => {
56
66
  const list = TestList.create(["milk"], me);
57
67
 
@@ -52,6 +52,15 @@ describe("CoMap.Record", async () => {
52
52
  expect(Object.keys(person)).toEqual(["age"]);
53
53
  });
54
54
 
55
+ test("create a Record with nullable values", () => {
56
+ const Person = co.record(z.string(), z.string().nullable());
57
+ const person = Person.create({ name: "John", age: null });
58
+ person.bio = null;
59
+ expect(person.name).toEqual("John");
60
+ expect(person.age).toEqual(null);
61
+ expect(person.bio).toEqual(null);
62
+ });
63
+
55
64
  test("property existence", () => {
56
65
  const Person = co.record(z.string(), z.string());
57
66
 
@@ -1,7 +1,7 @@
1
1
  import { assert, describe, expectTypeOf, test } from "vitest";
2
2
  import { Group, co, z } from "../exports.js";
3
3
  import { Account } from "../index.js";
4
- import { Loaded } from "../internal.js";
4
+ import { CoMap, Loaded } from "../internal.js";
5
5
 
6
6
  describe("CoMap", async () => {
7
7
  describe("init", () => {
@@ -408,4 +408,32 @@ describe("CoMap resolution", async () => {
408
408
  | null
409
409
  >();
410
410
  });
411
+
412
+ test("loading a map with a nullable field", async () => {
413
+ const Dog = co.map({
414
+ name: z.string(),
415
+ breed: z.string(),
416
+ });
417
+ const Person = co.map({
418
+ name: z.string(),
419
+ age: z.number().nullable(),
420
+ dog: Dog,
421
+ });
422
+
423
+ const person = Person.create({
424
+ name: "John",
425
+ age: 20,
426
+ dog: Dog.create({ name: "Rex", breed: "Labrador" }),
427
+ });
428
+
429
+ const loadedPerson = await Person.load(person.id);
430
+
431
+ expectTypeOf(loadedPerson!).toEqualTypeOf<
432
+ {
433
+ name: string;
434
+ age: number | null;
435
+ dog: Loaded<typeof Dog> | null;
436
+ } & CoMap
437
+ >();
438
+ });
411
439
  });
@@ -143,8 +143,7 @@ describe("CoMap", async () => {
143
143
  const Person = co.map({
144
144
  name: z.string(),
145
145
  age: z.number(),
146
- // TODO: would be nice if this didn't need a type annotation
147
- get friend(): co.Optional<typeof Person> {
146
+ get friend() {
148
147
  return co.optional(Person);
149
148
  },
150
149
  });
@@ -291,6 +290,74 @@ describe("CoMap", async () => {
291
290
  age: 30,
292
291
  });
293
292
  });
293
+
294
+ it("should allow extra properties when catchall is provided", () => {
295
+ const Person = co
296
+ .map({
297
+ name: z.string(),
298
+ age: z.number(),
299
+ })
300
+ .catchall(z.string());
301
+
302
+ const person = Person.create({ name: "John", age: 20 });
303
+ expect(person.name).toEqual("John");
304
+ expect(person.age).toEqual(20);
305
+ expect(person.extra).toBeUndefined();
306
+
307
+ person.name = "Jane";
308
+ person.age = 28;
309
+ person.extra = "extra";
310
+
311
+ expect(person.name).toEqual("Jane");
312
+ expect(person.age).toEqual(28);
313
+ expect(person.extra).toEqual("extra");
314
+ });
315
+
316
+ test("CoMap with reference can be created with a shallowly resolved reference", async () => {
317
+ const Dog = co.map({
318
+ name: z.string(),
319
+ breed: z.string(),
320
+ });
321
+ const Person = co.map({
322
+ name: z.string(),
323
+ age: z.number(),
324
+ pet: Dog,
325
+ get friend() {
326
+ return Person.optional();
327
+ },
328
+ });
329
+
330
+ const group = Group.create();
331
+ group.addMember("everyone", "writer");
332
+
333
+ const pet = Dog.create({ name: "Rex", breed: "Labrador" }, group);
334
+ const personA = Person.create(
335
+ {
336
+ name: "John",
337
+ age: 20,
338
+ pet,
339
+ },
340
+ { owner: group },
341
+ );
342
+
343
+ const userB = await createJazzTestAccount();
344
+ const loadedPersonA = await Person.load(personA.id, {
345
+ resolve: true,
346
+ loadAs: userB,
347
+ });
348
+
349
+ expect(loadedPersonA).not.toBeNull();
350
+ assert(loadedPersonA);
351
+
352
+ const personB = Person.create({
353
+ name: "Jane",
354
+ age: 28,
355
+ pet,
356
+ friend: loadedPersonA,
357
+ });
358
+
359
+ expect(personB.friend?.pet.name).toEqual("Rex");
360
+ });
294
361
  });
295
362
 
296
363
  describe("Mutation", () => {
@@ -60,6 +60,44 @@ describe("co.map and Zod schema compatibility", () => {
60
60
  expect(map.createdAt).toEqual(undefined);
61
61
  });
62
62
 
63
+ it("should not handle nullable date fields", () => {
64
+ const schema = co.map({
65
+ updatedAt: z.date().nullable(),
66
+ });
67
+ expect(() => schema.create({ updatedAt: null })).toThrow(
68
+ "Nullable z.date() is not supported",
69
+ );
70
+ });
71
+
72
+ it("should handle nullable fields", () => {
73
+ const schema = co.map({
74
+ updatedAt: z.string().nullable(),
75
+ });
76
+
77
+ const map = schema.create({
78
+ updatedAt: null,
79
+ });
80
+ expect(map.updatedAt).toBeNull();
81
+
82
+ map.updatedAt = "Test";
83
+ expect(map.updatedAt).toEqual("Test");
84
+ });
85
+
86
+ it("should handle nullish fields", () => {
87
+ const schema = co.map({
88
+ updatedAt: z.string().nullish(),
89
+ });
90
+
91
+ const map = schema.create({});
92
+ expect(map.updatedAt).toBeUndefined();
93
+
94
+ map.updatedAt = null;
95
+ expect(map.updatedAt).toBeNull();
96
+
97
+ map.updatedAt = "Test";
98
+ expect(map.updatedAt).toEqual("Test");
99
+ });
100
+
63
101
  it("should handle literal fields", async () => {
64
102
  const schema = co.map({
65
103
  status: z.literal("active"),