jazz-tools 0.14.17 → 0.14.18

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.
@@ -299,4 +299,109 @@ describe("CoMap.Record", async () => {
299
299
  );
300
300
  });
301
301
  });
302
+
303
+ // Covers https://github.com/garden-co/jazz/issues/2385
304
+ test("create a Record with a discriminated union containing a co.map that uses withHelpers", () => {
305
+ const Base = co.map({
306
+ type: z.literal("base"),
307
+ name: z.string(),
308
+ });
309
+
310
+ const IssueRepro = co.map({
311
+ type: z.literal("repro"),
312
+ catchall: co.map({}).withHelpers((self) => self),
313
+ name: z.string(),
314
+ });
315
+
316
+ const PersonRecord = co.record(
317
+ z.string(),
318
+ z.discriminatedUnion("type", [Base, IssueRepro]),
319
+ );
320
+
321
+ const person = IssueRepro.create({
322
+ type: "repro",
323
+ catchall: IssueRepro.def.shape.catchall.create({}),
324
+ name: "John",
325
+ });
326
+
327
+ const record = PersonRecord.create({
328
+ john: person,
329
+ });
330
+
331
+ if (record.john?.type === "repro") {
332
+ expect(record.john.catchall).toEqual({});
333
+ expect(record.john.name).toEqual("John");
334
+ expect(record.john.type).toEqual("repro");
335
+ }
336
+ });
337
+
338
+ // Covers https://github.com/garden-co/jazz/issues/2385
339
+ test("create a Record with a discriminated union containing a co.map that uses catchall", () => {
340
+ const Base = co.map({
341
+ type: z.literal("base"),
342
+ name: z.string(),
343
+ });
344
+
345
+ const IssueRepro = co.map({
346
+ type: z.literal("repro"),
347
+ catchall: co.map({}).catchall(z.string()),
348
+ name: z.string(),
349
+ });
350
+
351
+ const PersonRecord = co.record(
352
+ z.string(),
353
+ z.discriminatedUnion("type", [Base, IssueRepro]),
354
+ );
355
+
356
+ const person = IssueRepro.create({
357
+ type: "repro",
358
+ catchall: IssueRepro.def.shape.catchall.create({}),
359
+ name: "John",
360
+ });
361
+
362
+ const record = PersonRecord.create({
363
+ john: person,
364
+ });
365
+
366
+ if (record.john?.type === "repro") {
367
+ expect(record.john.catchall).toEqual({});
368
+ expect(record.john.name).toEqual("John");
369
+ expect(record.john.type).toEqual("repro");
370
+ }
371
+ });
372
+
373
+ // Covers https://github.com/garden-co/jazz/issues/2385
374
+ test("create a Record with a discriminated union containing a co.image", () => {
375
+ const Base = co.map({
376
+ type: z.literal("base"),
377
+ name: z.string(),
378
+ });
379
+
380
+ const IssueRepro = co.map({
381
+ type: z.literal("repro"),
382
+ image: co.image().optional(),
383
+ name: z.string(),
384
+ });
385
+
386
+ const PersonRecord = co.record(
387
+ z.string(),
388
+ z.discriminatedUnion("type", [Base, IssueRepro]),
389
+ );
390
+
391
+ const person = IssueRepro.create({
392
+ type: "repro",
393
+ image: undefined,
394
+ name: "John",
395
+ });
396
+
397
+ const record = PersonRecord.create({
398
+ john: person,
399
+ });
400
+
401
+ if (record.john?.type === "repro") {
402
+ expect(record.john.image).toEqual(undefined);
403
+ expect(record.john.name).toEqual("John");
404
+ expect(record.john.type).toEqual("repro");
405
+ }
406
+ });
302
407
  });
@@ -110,29 +110,6 @@ describe("CoMap", async () => {
110
110
  expect(emptyMap.color).toEqual(undefined);
111
111
  });
112
112
 
113
- test("setting date as undefined should throw", () => {
114
- const Person = co.map({
115
- color: z.string(),
116
- _height: z.number(),
117
- birthday: z.date(),
118
- name: z.string(),
119
- // nullable: z.optional.encoded<string | undefined>({
120
- // encode: (value: string | undefined) => value || null,
121
- // decode: (value: unknown) => (value as string) || undefined,
122
- // });
123
- optionalDate: z.date().optional(),
124
- });
125
-
126
- expect(() =>
127
- Person.create({
128
- color: "red",
129
- _height: 10,
130
- name: "John",
131
- birthday: undefined!,
132
- }),
133
- ).toThrow();
134
- });
135
-
136
113
  test("CoMap with reference", () => {
137
114
  const Dog = co.map({
138
115
  name: z.string(),
@@ -1223,4 +1200,159 @@ describe("Creating and finding unique CoMaps", async () => {
1223
1200
  const foundAlice = Person.findUnique({ name: "Alice" }, group.id);
1224
1201
  expect(foundAlice).toEqual(alice.id);
1225
1202
  });
1203
+
1204
+ test("complex discriminated union", () => {
1205
+ const StringTag = co.map({
1206
+ type: z.literal("string"),
1207
+ stringValue: z.string(),
1208
+ });
1209
+
1210
+ const DateTag = co.map({
1211
+ type: z.literal("date"),
1212
+ dateValue: z.date(),
1213
+ repeat: z.optional(
1214
+ z.literal("daily").or(z.literal("weekly")).or(z.literal("monthly")),
1215
+ ),
1216
+ });
1217
+
1218
+ const StringAttributeValue = co.map({
1219
+ type: z.literal(["somethingElse", "string"]),
1220
+ stringValue: z.string(),
1221
+ });
1222
+
1223
+ const NumberAttributeValue = co.map({
1224
+ type: z.literal("number"),
1225
+ numberValue: z.number(),
1226
+ });
1227
+
1228
+ const DateAttributeValue = co.map({
1229
+ type: z.literal("date"),
1230
+ dateValue: z.date(),
1231
+ });
1232
+
1233
+ const AttributeValue = z.discriminatedUnion("type", [
1234
+ StringAttributeValue,
1235
+ NumberAttributeValue,
1236
+ DateAttributeValue,
1237
+ ]);
1238
+
1239
+ const AttributeTagKey = co.map({
1240
+ key: z.string(),
1241
+ });
1242
+
1243
+ const AttributeTag = co.map({
1244
+ type: z.literal("attribute"),
1245
+ key: AttributeTagKey, // this is a covalue so that it can be referenced uniquely by other tags
1246
+ attributeValue: AttributeValue,
1247
+ });
1248
+
1249
+ const Tag = z.discriminatedUnion("type", [
1250
+ AttributeTag,
1251
+ StringTag,
1252
+ DateTag,
1253
+ ]);
1254
+
1255
+ const Wrapper = co.map({
1256
+ tag: Tag,
1257
+ });
1258
+
1259
+ const wrapper = Wrapper.create({
1260
+ tag: AttributeTag.create({
1261
+ type: "attribute",
1262
+ key: AttributeTagKey.create({ key: "name" }),
1263
+ attributeValue: StringAttributeValue.create({
1264
+ type: "string",
1265
+ stringValue: "Alice",
1266
+ }),
1267
+ }),
1268
+ });
1269
+
1270
+ if (wrapper.tag.type === "attribute") {
1271
+ expect(wrapper.tag.key.key).toEqual("name");
1272
+ if (wrapper.tag.attributeValue.type === "string") {
1273
+ expect(wrapper.tag.attributeValue.stringValue).toEqual("Alice");
1274
+ }
1275
+ }
1276
+ });
1277
+
1278
+ test("complex discriminated union with numeric discriminator value", () => {
1279
+ const HttpError = co.map({
1280
+ code: z.number(),
1281
+ message: z.string(),
1282
+ });
1283
+
1284
+ const ClientError = co.map({
1285
+ type: z.literal(400),
1286
+ error: HttpError,
1287
+ });
1288
+
1289
+ const ServerError = co.map({
1290
+ type: z.literal(500),
1291
+ error: HttpError,
1292
+ });
1293
+
1294
+ const NetworkError = co.map({
1295
+ type: z.literal(0),
1296
+ error: HttpError,
1297
+ });
1298
+
1299
+ const ErrorResponse = z.discriminatedUnion("type", [
1300
+ ClientError,
1301
+ ServerError,
1302
+ NetworkError,
1303
+ ]);
1304
+
1305
+ const ErrorWrapper = co.map({
1306
+ response: ErrorResponse,
1307
+ });
1308
+
1309
+ const wrapper = ErrorWrapper.create({
1310
+ response: ClientError.create({
1311
+ type: 400,
1312
+ error: HttpError.create({
1313
+ code: 400,
1314
+ message: "Bad Request",
1315
+ }),
1316
+ }),
1317
+ });
1318
+
1319
+ if (wrapper.response.type === 400) {
1320
+ expect(wrapper.response.error.code).toEqual(400);
1321
+ expect(wrapper.response.error.message).toEqual("Bad Request");
1322
+ }
1323
+
1324
+ const serverErrorWrapper = ErrorWrapper.create({
1325
+ response: ServerError.create({
1326
+ type: 500,
1327
+ error: HttpError.create({
1328
+ code: 500,
1329
+ message: "Internal Server Error",
1330
+ }),
1331
+ }),
1332
+ });
1333
+
1334
+ if (serverErrorWrapper.response.type === 500) {
1335
+ expect(serverErrorWrapper.response.error.code).toEqual(500);
1336
+ expect(serverErrorWrapper.response.error.message).toEqual(
1337
+ "Internal Server Error",
1338
+ );
1339
+ }
1340
+
1341
+ const networkErrorWrapper = ErrorWrapper.create({
1342
+ response: NetworkError.create({
1343
+ type: 0,
1344
+ error: HttpError.create({
1345
+ code: 0,
1346
+ message: "Network Error",
1347
+ }),
1348
+ }),
1349
+ });
1350
+
1351
+ if (networkErrorWrapper.response.type === 0) {
1352
+ expect(networkErrorWrapper.response.error.code).toEqual(0);
1353
+ expect(networkErrorWrapper.response.error.message).toEqual(
1354
+ "Network Error",
1355
+ );
1356
+ }
1357
+ });
1226
1358
  });
@@ -43,6 +43,15 @@ describe("co.map and Zod schema compatibility", () => {
43
43
  expect(map.createdAt).toEqual(date);
44
44
  });
45
45
 
46
+ it("should handle optional date fields", async () => {
47
+ const schema = co.map({
48
+ createdAt: z.date().optional(),
49
+ });
50
+ const account = await createJazzTestAccount();
51
+ const map = schema.create({ createdAt: undefined }, account);
52
+ expect(map.createdAt).toEqual(undefined);
53
+ });
54
+
46
55
  it("should handle literal fields", async () => {
47
56
  const schema = co.map({
48
57
  status: z.literal("active"),