@tinacms/schema-tools 1.6.8 → 1.6.9

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/dist/index.js CHANGED
@@ -2240,9 +2240,12 @@
2240
2240
  moreInfo.push(parseZodError({ zodError: unionError }));
2241
2241
  });
2242
2242
  }
2243
- const errorMessage = `Error ${issue == null ? void 0 : issue.message} at path ${issue.path.join(
2243
+ const errorMessage = `${issue == null ? void 0 : issue.message}
2244
+ Additional information:
2245
+ - Error found at path ${issue.path.join(
2244
2246
  "."
2245
- )}`;
2247
+ )}
2248
+ `;
2246
2249
  const errorMessages = [errorMessage, ...moreInfo];
2247
2250
  return {
2248
2251
  errors: errorMessages
@@ -2277,6 +2280,9 @@ If you need to use this value in your content you can use the \`nameOverride\` p
2277
2280
  });
2278
2281
  }
2279
2282
  });
2283
+ const duplicateFieldErrorMessage = (fields) => `Fields must have unique names. Found duplicate field names: [${fields}]`;
2284
+ const duplicateTemplateErrorMessage = (templates) => `Templates must have unique names. Found duplicate template names: [${templates}]`;
2285
+ const duplicateCollectionErrorMessage = (collection) => `Collections must have unique names. Found duplicate collection names: [${collection}]`;
2280
2286
  const TypeName = [
2281
2287
  "string",
2282
2288
  "boolean",
@@ -2287,10 +2293,11 @@ If you need to use this value in your content you can use the \`nameOverride\` p
2287
2293
  "reference",
2288
2294
  "rich-text"
2289
2295
  ];
2290
- const typeTypeError = `type must be one of ${TypeName.join(", ")}`;
2291
- const typeRequiredError = `type is required and must be one of ${TypeName.join(
2292
- ", "
2293
- )}`;
2296
+ const formattedTypes = ` - ${TypeName.join("\n - ")}`;
2297
+ const typeTypeError = `Invalid \`type\` property. \`type\` expected to be one of the following values:
2298
+ ${formattedTypes}`;
2299
+ const typeRequiredError = `Missing \`type\` property. Please add a \`type\` property with one of the following:
2300
+ ${formattedTypes}`;
2294
2301
  const Option = z.z.union(
2295
2302
  [
2296
2303
  z.z.string(),
@@ -2376,7 +2383,7 @@ If you need to use this value in your content you can use the \`nameOverride\` p
2376
2383
  if (dups) {
2377
2384
  ctx.addIssue({
2378
2385
  code: z.z.ZodIssueCode.custom,
2379
- message: `Fields must have a unique name, duplicate field names: ${dups}`
2386
+ message: duplicateFieldErrorMessage(dups)
2380
2387
  });
2381
2388
  }
2382
2389
  });
@@ -2386,21 +2393,21 @@ If you need to use this value in your content you can use the \`nameOverride\` p
2386
2393
  invalid_type_error: typeTypeError,
2387
2394
  required_error: typeRequiredError
2388
2395
  }),
2389
- fields: z.z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
2396
+ fields: z.z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
2390
2397
  const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
2391
2398
  if (dups) {
2392
2399
  ctx.addIssue({
2393
2400
  code: z.z.ZodIssueCode.custom,
2394
- message: `Fields must have a unique name, duplicate field names: ${dups}`
2401
+ message: duplicateFieldErrorMessage(dups)
2395
2402
  });
2396
2403
  }
2397
2404
  }),
2398
- templates: z.z.array(TemplateTemp).min(1).optional().superRefine((val, ctx) => {
2405
+ templates: z.z.array(TemplateTemp).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
2399
2406
  const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
2400
2407
  if (dups) {
2401
2408
  ctx.addIssue({
2402
2409
  code: z.z.ZodIssueCode.custom,
2403
- message: `Templates must have a unique name, duplicate template names: ${dups}`
2410
+ message: duplicateTemplateErrorMessage(dups)
2404
2411
  });
2405
2412
  }
2406
2413
  })
@@ -2415,7 +2422,7 @@ If you need to use this value in your content you can use the \`nameOverride\` p
2415
2422
  if (dups) {
2416
2423
  ctx.addIssue({
2417
2424
  code: z.z.ZodIssueCode.custom,
2418
- message: `Templates must have a unique name, duplicate template names: ${dups}`
2425
+ message: duplicateTemplateErrorMessage(dups)
2419
2426
  });
2420
2427
  }
2421
2428
  })
@@ -2435,10 +2442,17 @@ If you need to use this value in your content you can use the \`nameOverride\` p
2435
2442
  ],
2436
2443
  {
2437
2444
  errorMap: (issue, ctx) => {
2438
- var _a;
2445
+ var _a, _b;
2439
2446
  if (issue.code === "invalid_union_discriminator") {
2447
+ if (!((_a = ctx.data) == null ? void 0 : _a.type)) {
2448
+ return {
2449
+ message: `Missing \`type\` property in field \`${ctx.data.name}\`. Please add a \`type\` property with one of the following:
2450
+ ${formattedTypes}`
2451
+ };
2452
+ }
2440
2453
  return {
2441
- message: `Invalid \`type\` property. In the schema is 'type: ${(_a = ctx.data) == null ? void 0 : _a.type}' and expected one of ${TypeName.join(", ")}`
2454
+ message: `Invalid \`type\` property in field \`${ctx.data.name}\`. In the schema is 'type: ${(_b = ctx.data) == null ? void 0 : _b.type}' but expected one of the following:
2455
+ ${formattedTypes}`
2442
2456
  };
2443
2457
  }
2444
2458
  return {
@@ -2448,77 +2462,52 @@ If you need to use this value in your content you can use the \`nameOverride\` p
2448
2462
  }
2449
2463
  ).superRefine((val, ctx) => {
2450
2464
  if (val.type === "string") {
2451
- if (val.isTitle) {
2452
- if (val.list) {
2453
- ctx.addIssue({
2454
- code: z.z.ZodIssueCode.custom,
2455
- message: `Can not have \`list: true\` when using \`isTitle\`. Error in value
2456
- ${JSON.stringify(
2457
- val,
2458
- null,
2459
- 2
2460
- )}
2461
- `
2462
- });
2463
- }
2464
- if (!val.required) {
2465
- ctx.addIssue({
2466
- code: z.z.ZodIssueCode.custom,
2467
- message: `Must have { required: true } when using \`isTitle\` Error in value
2468
- ${JSON.stringify(
2469
- val,
2470
- null,
2471
- 2
2472
- )}
2473
- `
2474
- });
2475
- }
2465
+ const stringifiedField = JSON.stringify(val, null, 2);
2466
+ if (val.isTitle && val.list) {
2467
+ ctx.addIssue({
2468
+ code: z.z.ZodIssueCode.custom,
2469
+ message: `\`list: true\` is not allowed when using \`isTitle\` for fields of \`type: string\`. Error found in field:
2470
+ ${stringifiedField}`
2471
+ });
2472
+ }
2473
+ if (val.isTitle && !val.required) {
2474
+ ctx.addIssue({
2475
+ code: z.z.ZodIssueCode.custom,
2476
+ message: `Property \`required: true\` is required when using \`isTitle\` for fields of \`type: string\`. Error found in field:
2477
+ ${stringifiedField}`
2478
+ });
2476
2479
  }
2477
- if (val.uid) {
2480
+ if (val.uid && val.list) {
2478
2481
  if (val.list) {
2479
2482
  ctx.addIssue({
2480
2483
  code: z.z.ZodIssueCode.custom,
2481
- message: `Can not have \`list: true\` when using \`uid\`. Error in value
2482
- ${JSON.stringify(
2483
- val,
2484
- null,
2485
- 2
2486
- )}
2487
- `
2488
- });
2489
- }
2490
- if (!val.required) {
2491
- ctx.addIssue({
2492
- code: z.z.ZodIssueCode.custom,
2493
- message: `Must have { required: true } when using \`uid\` Error in value
2494
- ${JSON.stringify(
2495
- val,
2496
- null,
2497
- 2
2498
- )}
2499
- `
2484
+ message: `\`list: true\` is not allowed when using \`uid\` for fields of \`type: string\`. Error found in field:
2485
+ ${stringifiedField}`
2500
2486
  });
2501
2487
  }
2502
2488
  }
2489
+ if (val.uid && !val.required) {
2490
+ ctx.addIssue({
2491
+ code: z.z.ZodIssueCode.custom,
2492
+ message: `Property \`required: true\` is required when using \`uid\` for fields of \`type: string\`. Error found in field:
2493
+ ${stringifiedField}`
2494
+ });
2495
+ }
2503
2496
  }
2504
2497
  if (val.type === "object") {
2505
- const message = "Must provide one of templates or fields in your collection";
2506
- let isValid = Boolean(val == null ? void 0 : val.templates) || Boolean(val == null ? void 0 : val.fields);
2507
- if (!isValid) {
2498
+ if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
2508
2499
  ctx.addIssue({
2509
2500
  code: z.z.ZodIssueCode.custom,
2510
- message
2501
+ message: "Fields of `type: object` must have either `templates` or `fields` property."
2502
+ });
2503
+ return false;
2504
+ }
2505
+ if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
2506
+ ctx.addIssue({
2507
+ code: z.z.ZodIssueCode.custom,
2508
+ message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
2511
2509
  });
2512
2510
  return false;
2513
- } else {
2514
- isValid = !((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields));
2515
- if (!isValid) {
2516
- ctx.addIssue({
2517
- code: z.z.ZodIssueCode.custom,
2518
- message
2519
- });
2520
- }
2521
- return isValid;
2522
2511
  }
2523
2512
  }
2524
2513
  return true;
@@ -2562,8 +2551,8 @@ ${JSON.stringify(
2562
2551
  ];
2563
2552
  const Template = z.z.object({
2564
2553
  label: z.z.string({
2565
- invalid_type_error: "label must be a string",
2566
- required_error: "label was not provided but is required"
2554
+ invalid_type_error: "Invalid data type for property `label`. Must be of type `string`",
2555
+ required_error: "Missing `label` property. Property `label` is required."
2567
2556
  }),
2568
2557
  name,
2569
2558
  fields: z.z.array(TinaFieldZod)
@@ -2573,7 +2562,7 @@ ${JSON.stringify(
2573
2562
  if (dups) {
2574
2563
  ctx.addIssue({
2575
2564
  code: z.z.ZodIssueCode.custom,
2576
- message: `Fields must have a unique name, duplicate field names: ${dups}`
2565
+ message: duplicateFieldErrorMessage(dups)
2577
2566
  });
2578
2567
  }
2579
2568
  });
@@ -2583,7 +2572,7 @@ ${JSON.stringify(
2583
2572
  if (val === "relativePath") {
2584
2573
  ctx.addIssue({
2585
2574
  code: z.z.ZodIssueCode.custom,
2586
- message: `name cannot be 'relativePath'. 'relativePath' is a reserved field name.`
2575
+ message: "Invalid `name` property. `name` cannot be 'relativePath' as it is a reserved field name."
2587
2576
  });
2588
2577
  }
2589
2578
  }),
@@ -2591,7 +2580,7 @@ ${JSON.stringify(
2591
2580
  if (val === ".") {
2592
2581
  ctx.addIssue({
2593
2582
  code: z.z.ZodIssueCode.custom,
2594
- message: `path cannot be '.'. Please use '/' or '' instead. `
2583
+ message: "Invalid `path` property. `path` cannot be '.'. Please use '/' or '' instead."
2595
2584
  });
2596
2585
  }
2597
2586
  }),
@@ -2600,63 +2589,64 @@ ${JSON.stringify(
2600
2589
  isDetached: z.z.boolean().optional()
2601
2590
  });
2602
2591
  const TinaCloudCollection = CollectionBaseSchema.extend({
2603
- fields: z.z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
2592
+ fields: z.z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
2604
2593
  const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
2605
2594
  if (dups) {
2606
2595
  ctx.addIssue({
2607
2596
  code: z.z.ZodIssueCode.custom,
2608
- message: `Fields must have a unique name, duplicate field names: ${dups}`
2597
+ message: duplicateFieldErrorMessage(dups)
2609
2598
  });
2610
2599
  }
2611
- }).refine(
2612
- // It is valid if it is 0 or 1
2613
- (val) => {
2614
- const arr = (val == null ? void 0 : val.filter((x) => x.type === "string" && x.isTitle)) || [];
2615
- return arr.length < 2;
2616
- },
2617
- {
2618
- message: "Fields can only have one use of `isTitle`"
2619
- }
2620
- ).refine(
2621
- // It is valid if it is 0 or 1
2622
- (val) => {
2623
- const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
2624
- return arr.length < 2;
2625
- },
2626
- {
2627
- message: "Fields can only have one use of `uid`"
2628
- }
2629
- ).refine(
2630
- // It is valid if it is 0 or 1
2631
- (val) => {
2632
- const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
2633
- return arr.length < 2;
2634
- },
2635
- {
2636
- message: "Fields can only have one use of `password` type"
2600
+ }).superRefine((val, ctx) => {
2601
+ const arr = (val == null ? void 0 : val.filter((x) => x.type === "string" && x.isTitle)) || [];
2602
+ if (arr.length > 1) {
2603
+ ctx.addIssue({
2604
+ code: z.z.ZodIssueCode.custom,
2605
+ message: `The following fields have the property \`isTitle\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`isTitle\`.`
2606
+ });
2607
+ }
2608
+ }).superRefine((val, ctx) => {
2609
+ const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
2610
+ if (arr.length > 2) {
2611
+ ctx.addIssue({
2612
+ code: z.z.ZodIssueCode.custom,
2613
+ message: `The following fields have the property \`uid\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`uid\`.`
2614
+ });
2615
+ }
2616
+ }).superRefine((val, ctx) => {
2617
+ const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
2618
+ if (arr.length > 2) {
2619
+ ctx.addIssue({
2620
+ code: z.z.ZodIssueCode.custom,
2621
+ message: `The following fields have \`type: password\`: [${arr.map((field) => field.name).join(", ")}]. Only one can be of \`type: password\`.`
2622
+ });
2637
2623
  }
2638
- ),
2639
- templates: z.z.array(Template).min(1).optional().superRefine((val, ctx) => {
2624
+ }),
2625
+ templates: z.z.array(Template).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
2640
2626
  const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
2641
2627
  if (dups) {
2642
2628
  ctx.addIssue({
2643
2629
  code: z.z.ZodIssueCode.custom,
2644
- message: `Templates must have a unique name, duplicate template names: ${dups}`
2630
+ message: duplicateFieldErrorMessage(dups)
2645
2631
  });
2646
2632
  }
2647
2633
  })
2648
- }).refine(
2649
- (val) => {
2650
- let isValid = Boolean(val == null ? void 0 : val.templates) || Boolean(val == null ? void 0 : val.fields);
2651
- if (!isValid) {
2652
- return false;
2653
- } else {
2654
- isValid = !((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields));
2655
- return isValid;
2656
- }
2657
- },
2658
- { message: "Must provide one of templates or fields in your collection" }
2659
- );
2634
+ }).superRefine((val, ctx) => {
2635
+ if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
2636
+ ctx.addIssue({
2637
+ code: z.z.ZodIssueCode.custom,
2638
+ message: "Fields of `type: object` must have either `templates` or `fields` property."
2639
+ });
2640
+ return false;
2641
+ }
2642
+ if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
2643
+ ctx.addIssue({
2644
+ code: z.z.ZodIssueCode.custom,
2645
+ message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
2646
+ });
2647
+ return false;
2648
+ }
2649
+ });
2660
2650
  const TinaCloudSchemaZod = z.z.object({
2661
2651
  collections: z.z.array(TinaCloudCollection),
2662
2652
  config: tinaConfigZod.optional()
@@ -2666,14 +2656,14 @@ ${JSON.stringify(
2666
2656
  if (dups) {
2667
2657
  ctx.addIssue({
2668
2658
  code: z.z.ZodIssueCode.custom,
2669
- message: `${dups} are duplicate names in your collections. Collection names must be unique.`,
2659
+ message: duplicateCollectionErrorMessage(dups),
2670
2660
  fatal: true
2671
2661
  });
2672
2662
  }
2673
2663
  if (((_b = val.collections) == null ? void 0 : _b.filter((x) => x.isAuthCollection).length) > 1) {
2674
2664
  ctx.addIssue({
2675
2665
  code: z.z.ZodIssueCode.custom,
2676
- message: `Only one collection can be marked as isAuthCollection`,
2666
+ message: "Only one collection can be marked as `isAuthCollection`.",
2677
2667
  fatal: true
2678
2668
  });
2679
2669
  }
@@ -2681,7 +2671,7 @@ ${JSON.stringify(
2681
2671
  if (media && media.tina && media.loadCustomStore) {
2682
2672
  ctx.addIssue({
2683
2673
  code: z.z.ZodIssueCode.custom,
2684
- message: "can not have both loadCustomStore and tina. Must use one or the other",
2674
+ message: "Cannot have both `loadCustomStore` and `tina`. Must use one or the other.",
2685
2675
  fatal: true,
2686
2676
  path: ["config", "media"]
2687
2677
  });
@@ -2690,7 +2680,7 @@ ${JSON.stringify(
2690
2680
  if (search && search.tina && search.searchClient) {
2691
2681
  ctx.addIssue({
2692
2682
  code: z.z.ZodIssueCode.custom,
2693
- message: "can not have both searchClient and tina. Must use one or the other",
2683
+ message: "Cannot have both `searchClient` and `tina`. Must use one or the other.",
2694
2684
  fatal: true,
2695
2685
  path: ["config", "search"]
2696
2686
  });
@@ -2708,7 +2698,7 @@ ${JSON.stringify(
2708
2698
  } catch (e) {
2709
2699
  if (e instanceof z.ZodError) {
2710
2700
  const errors = parseZodError({ zodError: e });
2711
- throw new TinaSchemaValidationError(errors.join(", \n"));
2701
+ throw new TinaSchemaValidationError(errors.join("\n"));
2712
2702
  }
2713
2703
  throw new Error(e);
2714
2704
  }
package/dist/index.mjs CHANGED
@@ -2222,9 +2222,12 @@ const parseZodError = ({ zodError }) => {
2222
2222
  moreInfo.push(parseZodError({ zodError: unionError }));
2223
2223
  });
2224
2224
  }
2225
- const errorMessage = `Error ${issue == null ? void 0 : issue.message} at path ${issue.path.join(
2225
+ const errorMessage = `${issue == null ? void 0 : issue.message}
2226
+ Additional information:
2227
+ - Error found at path ${issue.path.join(
2226
2228
  "."
2227
- )}`;
2229
+ )}
2230
+ `;
2228
2231
  const errorMessages = [errorMessage, ...moreInfo];
2229
2232
  return {
2230
2233
  errors: errorMessages
@@ -2259,6 +2262,9 @@ If you need to use this value in your content you can use the \`nameOverride\` p
2259
2262
  });
2260
2263
  }
2261
2264
  });
2265
+ const duplicateFieldErrorMessage = (fields) => `Fields must have unique names. Found duplicate field names: [${fields}]`;
2266
+ const duplicateTemplateErrorMessage = (templates) => `Templates must have unique names. Found duplicate template names: [${templates}]`;
2267
+ const duplicateCollectionErrorMessage = (collection) => `Collections must have unique names. Found duplicate collection names: [${collection}]`;
2262
2268
  const TypeName = [
2263
2269
  "string",
2264
2270
  "boolean",
@@ -2269,10 +2275,11 @@ const TypeName = [
2269
2275
  "reference",
2270
2276
  "rich-text"
2271
2277
  ];
2272
- const typeTypeError = `type must be one of ${TypeName.join(", ")}`;
2273
- const typeRequiredError = `type is required and must be one of ${TypeName.join(
2274
- ", "
2275
- )}`;
2278
+ const formattedTypes = ` - ${TypeName.join("\n - ")}`;
2279
+ const typeTypeError = `Invalid \`type\` property. \`type\` expected to be one of the following values:
2280
+ ${formattedTypes}`;
2281
+ const typeRequiredError = `Missing \`type\` property. Please add a \`type\` property with one of the following:
2282
+ ${formattedTypes}`;
2276
2283
  const Option = z.union(
2277
2284
  [
2278
2285
  z.string(),
@@ -2358,7 +2365,7 @@ const TinaFieldZod = z.lazy(() => {
2358
2365
  if (dups) {
2359
2366
  ctx.addIssue({
2360
2367
  code: z.ZodIssueCode.custom,
2361
- message: `Fields must have a unique name, duplicate field names: ${dups}`
2368
+ message: duplicateFieldErrorMessage(dups)
2362
2369
  });
2363
2370
  }
2364
2371
  });
@@ -2368,21 +2375,21 @@ const TinaFieldZod = z.lazy(() => {
2368
2375
  invalid_type_error: typeTypeError,
2369
2376
  required_error: typeRequiredError
2370
2377
  }),
2371
- fields: z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
2378
+ fields: z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
2372
2379
  const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
2373
2380
  if (dups) {
2374
2381
  ctx.addIssue({
2375
2382
  code: z.ZodIssueCode.custom,
2376
- message: `Fields must have a unique name, duplicate field names: ${dups}`
2383
+ message: duplicateFieldErrorMessage(dups)
2377
2384
  });
2378
2385
  }
2379
2386
  }),
2380
- templates: z.array(TemplateTemp).min(1).optional().superRefine((val, ctx) => {
2387
+ templates: z.array(TemplateTemp).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
2381
2388
  const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
2382
2389
  if (dups) {
2383
2390
  ctx.addIssue({
2384
2391
  code: z.ZodIssueCode.custom,
2385
- message: `Templates must have a unique name, duplicate template names: ${dups}`
2392
+ message: duplicateTemplateErrorMessage(dups)
2386
2393
  });
2387
2394
  }
2388
2395
  })
@@ -2397,7 +2404,7 @@ const TinaFieldZod = z.lazy(() => {
2397
2404
  if (dups) {
2398
2405
  ctx.addIssue({
2399
2406
  code: z.ZodIssueCode.custom,
2400
- message: `Templates must have a unique name, duplicate template names: ${dups}`
2407
+ message: duplicateTemplateErrorMessage(dups)
2401
2408
  });
2402
2409
  }
2403
2410
  })
@@ -2417,10 +2424,17 @@ const TinaFieldZod = z.lazy(() => {
2417
2424
  ],
2418
2425
  {
2419
2426
  errorMap: (issue, ctx) => {
2420
- var _a;
2427
+ var _a, _b;
2421
2428
  if (issue.code === "invalid_union_discriminator") {
2429
+ if (!((_a = ctx.data) == null ? void 0 : _a.type)) {
2430
+ return {
2431
+ message: `Missing \`type\` property in field \`${ctx.data.name}\`. Please add a \`type\` property with one of the following:
2432
+ ${formattedTypes}`
2433
+ };
2434
+ }
2422
2435
  return {
2423
- message: `Invalid \`type\` property. In the schema is 'type: ${(_a = ctx.data) == null ? void 0 : _a.type}' and expected one of ${TypeName.join(", ")}`
2436
+ message: `Invalid \`type\` property in field \`${ctx.data.name}\`. In the schema is 'type: ${(_b = ctx.data) == null ? void 0 : _b.type}' but expected one of the following:
2437
+ ${formattedTypes}`
2424
2438
  };
2425
2439
  }
2426
2440
  return {
@@ -2430,77 +2444,52 @@ const TinaFieldZod = z.lazy(() => {
2430
2444
  }
2431
2445
  ).superRefine((val, ctx) => {
2432
2446
  if (val.type === "string") {
2433
- if (val.isTitle) {
2434
- if (val.list) {
2435
- ctx.addIssue({
2436
- code: z.ZodIssueCode.custom,
2437
- message: `Can not have \`list: true\` when using \`isTitle\`. Error in value
2438
- ${JSON.stringify(
2439
- val,
2440
- null,
2441
- 2
2442
- )}
2443
- `
2444
- });
2445
- }
2446
- if (!val.required) {
2447
- ctx.addIssue({
2448
- code: z.ZodIssueCode.custom,
2449
- message: `Must have { required: true } when using \`isTitle\` Error in value
2450
- ${JSON.stringify(
2451
- val,
2452
- null,
2453
- 2
2454
- )}
2455
- `
2456
- });
2457
- }
2447
+ const stringifiedField = JSON.stringify(val, null, 2);
2448
+ if (val.isTitle && val.list) {
2449
+ ctx.addIssue({
2450
+ code: z.ZodIssueCode.custom,
2451
+ message: `\`list: true\` is not allowed when using \`isTitle\` for fields of \`type: string\`. Error found in field:
2452
+ ${stringifiedField}`
2453
+ });
2454
+ }
2455
+ if (val.isTitle && !val.required) {
2456
+ ctx.addIssue({
2457
+ code: z.ZodIssueCode.custom,
2458
+ message: `Property \`required: true\` is required when using \`isTitle\` for fields of \`type: string\`. Error found in field:
2459
+ ${stringifiedField}`
2460
+ });
2458
2461
  }
2459
- if (val.uid) {
2462
+ if (val.uid && val.list) {
2460
2463
  if (val.list) {
2461
2464
  ctx.addIssue({
2462
2465
  code: z.ZodIssueCode.custom,
2463
- message: `Can not have \`list: true\` when using \`uid\`. Error in value
2464
- ${JSON.stringify(
2465
- val,
2466
- null,
2467
- 2
2468
- )}
2469
- `
2470
- });
2471
- }
2472
- if (!val.required) {
2473
- ctx.addIssue({
2474
- code: z.ZodIssueCode.custom,
2475
- message: `Must have { required: true } when using \`uid\` Error in value
2476
- ${JSON.stringify(
2477
- val,
2478
- null,
2479
- 2
2480
- )}
2481
- `
2466
+ message: `\`list: true\` is not allowed when using \`uid\` for fields of \`type: string\`. Error found in field:
2467
+ ${stringifiedField}`
2482
2468
  });
2483
2469
  }
2484
2470
  }
2471
+ if (val.uid && !val.required) {
2472
+ ctx.addIssue({
2473
+ code: z.ZodIssueCode.custom,
2474
+ message: `Property \`required: true\` is required when using \`uid\` for fields of \`type: string\`. Error found in field:
2475
+ ${stringifiedField}`
2476
+ });
2477
+ }
2485
2478
  }
2486
2479
  if (val.type === "object") {
2487
- const message = "Must provide one of templates or fields in your collection";
2488
- let isValid = Boolean(val == null ? void 0 : val.templates) || Boolean(val == null ? void 0 : val.fields);
2489
- if (!isValid) {
2480
+ if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
2490
2481
  ctx.addIssue({
2491
2482
  code: z.ZodIssueCode.custom,
2492
- message
2483
+ message: "Fields of `type: object` must have either `templates` or `fields` property."
2484
+ });
2485
+ return false;
2486
+ }
2487
+ if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
2488
+ ctx.addIssue({
2489
+ code: z.ZodIssueCode.custom,
2490
+ message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
2493
2491
  });
2494
2492
  return false;
2495
- } else {
2496
- isValid = !((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields));
2497
- if (!isValid) {
2498
- ctx.addIssue({
2499
- code: z.ZodIssueCode.custom,
2500
- message
2501
- });
2502
- }
2503
- return isValid;
2504
2493
  }
2505
2494
  }
2506
2495
  return true;
@@ -2544,8 +2533,8 @@ const FORMATS = [
2544
2533
  ];
2545
2534
  const Template = z.object({
2546
2535
  label: z.string({
2547
- invalid_type_error: "label must be a string",
2548
- required_error: "label was not provided but is required"
2536
+ invalid_type_error: "Invalid data type for property `label`. Must be of type `string`",
2537
+ required_error: "Missing `label` property. Property `label` is required."
2549
2538
  }),
2550
2539
  name,
2551
2540
  fields: z.array(TinaFieldZod)
@@ -2555,7 +2544,7 @@ const Template = z.object({
2555
2544
  if (dups) {
2556
2545
  ctx.addIssue({
2557
2546
  code: z.ZodIssueCode.custom,
2558
- message: `Fields must have a unique name, duplicate field names: ${dups}`
2547
+ message: duplicateFieldErrorMessage(dups)
2559
2548
  });
2560
2549
  }
2561
2550
  });
@@ -2565,7 +2554,7 @@ const CollectionBaseSchema = z.object({
2565
2554
  if (val === "relativePath") {
2566
2555
  ctx.addIssue({
2567
2556
  code: z.ZodIssueCode.custom,
2568
- message: `name cannot be 'relativePath'. 'relativePath' is a reserved field name.`
2557
+ message: "Invalid `name` property. `name` cannot be 'relativePath' as it is a reserved field name."
2569
2558
  });
2570
2559
  }
2571
2560
  }),
@@ -2573,7 +2562,7 @@ const CollectionBaseSchema = z.object({
2573
2562
  if (val === ".") {
2574
2563
  ctx.addIssue({
2575
2564
  code: z.ZodIssueCode.custom,
2576
- message: `path cannot be '.'. Please use '/' or '' instead. `
2565
+ message: "Invalid `path` property. `path` cannot be '.'. Please use '/' or '' instead."
2577
2566
  });
2578
2567
  }
2579
2568
  }),
@@ -2582,63 +2571,64 @@ const CollectionBaseSchema = z.object({
2582
2571
  isDetached: z.boolean().optional()
2583
2572
  });
2584
2573
  const TinaCloudCollection = CollectionBaseSchema.extend({
2585
- fields: z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
2574
+ fields: z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
2586
2575
  const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
2587
2576
  if (dups) {
2588
2577
  ctx.addIssue({
2589
2578
  code: z.ZodIssueCode.custom,
2590
- message: `Fields must have a unique name, duplicate field names: ${dups}`
2579
+ message: duplicateFieldErrorMessage(dups)
2591
2580
  });
2592
2581
  }
2593
- }).refine(
2594
- // It is valid if it is 0 or 1
2595
- (val) => {
2596
- const arr = (val == null ? void 0 : val.filter((x) => x.type === "string" && x.isTitle)) || [];
2597
- return arr.length < 2;
2598
- },
2599
- {
2600
- message: "Fields can only have one use of `isTitle`"
2601
- }
2602
- ).refine(
2603
- // It is valid if it is 0 or 1
2604
- (val) => {
2605
- const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
2606
- return arr.length < 2;
2607
- },
2608
- {
2609
- message: "Fields can only have one use of `uid`"
2610
- }
2611
- ).refine(
2612
- // It is valid if it is 0 or 1
2613
- (val) => {
2614
- const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
2615
- return arr.length < 2;
2616
- },
2617
- {
2618
- message: "Fields can only have one use of `password` type"
2582
+ }).superRefine((val, ctx) => {
2583
+ const arr = (val == null ? void 0 : val.filter((x) => x.type === "string" && x.isTitle)) || [];
2584
+ if (arr.length > 1) {
2585
+ ctx.addIssue({
2586
+ code: z.ZodIssueCode.custom,
2587
+ message: `The following fields have the property \`isTitle\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`isTitle\`.`
2588
+ });
2589
+ }
2590
+ }).superRefine((val, ctx) => {
2591
+ const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
2592
+ if (arr.length > 2) {
2593
+ ctx.addIssue({
2594
+ code: z.ZodIssueCode.custom,
2595
+ message: `The following fields have the property \`uid\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`uid\`.`
2596
+ });
2597
+ }
2598
+ }).superRefine((val, ctx) => {
2599
+ const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
2600
+ if (arr.length > 2) {
2601
+ ctx.addIssue({
2602
+ code: z.ZodIssueCode.custom,
2603
+ message: `The following fields have \`type: password\`: [${arr.map((field) => field.name).join(", ")}]. Only one can be of \`type: password\`.`
2604
+ });
2619
2605
  }
2620
- ),
2621
- templates: z.array(Template).min(1).optional().superRefine((val, ctx) => {
2606
+ }),
2607
+ templates: z.array(Template).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
2622
2608
  const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
2623
2609
  if (dups) {
2624
2610
  ctx.addIssue({
2625
2611
  code: z.ZodIssueCode.custom,
2626
- message: `Templates must have a unique name, duplicate template names: ${dups}`
2612
+ message: duplicateFieldErrorMessage(dups)
2627
2613
  });
2628
2614
  }
2629
2615
  })
2630
- }).refine(
2631
- (val) => {
2632
- let isValid = Boolean(val == null ? void 0 : val.templates) || Boolean(val == null ? void 0 : val.fields);
2633
- if (!isValid) {
2634
- return false;
2635
- } else {
2636
- isValid = !((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields));
2637
- return isValid;
2638
- }
2639
- },
2640
- { message: "Must provide one of templates or fields in your collection" }
2641
- );
2616
+ }).superRefine((val, ctx) => {
2617
+ if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
2618
+ ctx.addIssue({
2619
+ code: z.ZodIssueCode.custom,
2620
+ message: "Fields of `type: object` must have either `templates` or `fields` property."
2621
+ });
2622
+ return false;
2623
+ }
2624
+ if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
2625
+ ctx.addIssue({
2626
+ code: z.ZodIssueCode.custom,
2627
+ message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
2628
+ });
2629
+ return false;
2630
+ }
2631
+ });
2642
2632
  const TinaCloudSchemaZod = z.object({
2643
2633
  collections: z.array(TinaCloudCollection),
2644
2634
  config: tinaConfigZod.optional()
@@ -2648,14 +2638,14 @@ const TinaCloudSchemaZod = z.object({
2648
2638
  if (dups) {
2649
2639
  ctx.addIssue({
2650
2640
  code: z.ZodIssueCode.custom,
2651
- message: `${dups} are duplicate names in your collections. Collection names must be unique.`,
2641
+ message: duplicateCollectionErrorMessage(dups),
2652
2642
  fatal: true
2653
2643
  });
2654
2644
  }
2655
2645
  if (((_b = val.collections) == null ? void 0 : _b.filter((x) => x.isAuthCollection).length) > 1) {
2656
2646
  ctx.addIssue({
2657
2647
  code: z.ZodIssueCode.custom,
2658
- message: `Only one collection can be marked as isAuthCollection`,
2648
+ message: "Only one collection can be marked as `isAuthCollection`.",
2659
2649
  fatal: true
2660
2650
  });
2661
2651
  }
@@ -2663,7 +2653,7 @@ const TinaCloudSchemaZod = z.object({
2663
2653
  if (media && media.tina && media.loadCustomStore) {
2664
2654
  ctx.addIssue({
2665
2655
  code: z.ZodIssueCode.custom,
2666
- message: "can not have both loadCustomStore and tina. Must use one or the other",
2656
+ message: "Cannot have both `loadCustomStore` and `tina`. Must use one or the other.",
2667
2657
  fatal: true,
2668
2658
  path: ["config", "media"]
2669
2659
  });
@@ -2672,7 +2662,7 @@ const TinaCloudSchemaZod = z.object({
2672
2662
  if (search && search.tina && search.searchClient) {
2673
2663
  ctx.addIssue({
2674
2664
  code: z.ZodIssueCode.custom,
2675
- message: "can not have both searchClient and tina. Must use one or the other",
2665
+ message: "Cannot have both `searchClient` and `tina`. Must use one or the other.",
2676
2666
  fatal: true,
2677
2667
  path: ["config", "search"]
2678
2668
  });
@@ -2690,7 +2680,7 @@ const validateSchema = ({ schema }) => {
2690
2680
  } catch (e) {
2691
2681
  if (e instanceof ZodError) {
2692
2682
  const errors = parseZodError({ zodError: e });
2693
- throw new TinaSchemaValidationError(errors.join(", \n"));
2683
+ throw new TinaSchemaValidationError(errors.join("\n"));
2694
2684
  }
2695
2685
  throw new Error(e);
2696
2686
  }
@@ -1,6 +1,3 @@
1
- /**
2
-
3
- */
4
1
  import { z } from 'zod';
5
2
  import type { TinaField as TinaFieldType } from '../types/index';
6
3
  export declare const TinaFieldZod: z.ZodType<TinaFieldType>;
@@ -1,6 +1,3 @@
1
- /**
2
-
3
- */
4
1
  import { z } from 'zod';
5
2
  export declare const CollectionBaseSchema: z.ZodObject<{
6
3
  label: z.ZodOptional<z.ZodString>;
@@ -0,0 +1,3 @@
1
+ export declare const duplicateFieldErrorMessage: (fields: string) => string;
2
+ export declare const duplicateTemplateErrorMessage: (templates: string) => string;
3
+ export declare const duplicateCollectionErrorMessage: (collection: string) => string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinacms/schema-tools",
3
- "version": "1.6.8",
3
+ "version": "1.6.9",
4
4
  "main": "dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "exports": {