@tinacms/schema-tools 0.0.0-c72bb45-20241118014035 → 0.0.0-c965b5f-20250426163441
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.d.ts +1 -6
- package/dist/index.js +183 -162
- package/dist/index.mjs +183 -162
- package/dist/schema/TinaSchema.d.ts +21 -5
- package/dist/schema/addNamespaceToSchema.d.ts +8 -4
- package/dist/types/index.d.ts +10 -3
- package/dist/validate/fields.d.ts +0 -3
- package/dist/validate/schema.d.ts +0 -3
- package/dist/validate/util.d.ts +3 -0
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -20,42 +20,26 @@
|
|
|
20
20
|
}
|
|
21
21
|
const yup__namespace = /* @__PURE__ */ _interopNamespaceDefault(yup);
|
|
22
22
|
function addNamespaceToSchema(maybeNode, namespace = []) {
|
|
23
|
-
if (typeof maybeNode
|
|
23
|
+
if (typeof maybeNode !== "object" || maybeNode === null) {
|
|
24
24
|
return maybeNode;
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const keys = Object.keys(maybeNode);
|
|
34
|
-
Object.values(maybeNode).map((m, index) => {
|
|
35
|
-
const key = keys[index];
|
|
36
|
-
if (Array.isArray(m)) {
|
|
37
|
-
newNode[key] = m.map((element) => {
|
|
38
|
-
if (!element) {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
if (!element.hasOwnProperty("name")) {
|
|
42
|
-
return element;
|
|
26
|
+
const newNode = { ...maybeNode, namespace: [...namespace] };
|
|
27
|
+
Object.entries(maybeNode).forEach(([key, value]) => {
|
|
28
|
+
if (Array.isArray(value)) {
|
|
29
|
+
newNode[key] = value.map((element) => {
|
|
30
|
+
if (element && typeof element === "object" && "name" in element) {
|
|
31
|
+
const valueName = element.name || element.value;
|
|
32
|
+
return addNamespaceToSchema(element, [...namespace, valueName]);
|
|
43
33
|
}
|
|
44
|
-
|
|
45
|
-
return addNamespaceToSchema(element, [...namespace, value]);
|
|
34
|
+
return element;
|
|
46
35
|
});
|
|
36
|
+
} else if (value && typeof value === "object" && "name" in value) {
|
|
37
|
+
newNode[key] = addNamespaceToSchema(value, [...namespace, value.name]);
|
|
47
38
|
} else {
|
|
48
|
-
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (!m.hasOwnProperty("name")) {
|
|
52
|
-
newNode[key] = m;
|
|
53
|
-
} else {
|
|
54
|
-
newNode[key] = addNamespaceToSchema(m, [...namespace, m.name]);
|
|
55
|
-
}
|
|
39
|
+
newNode[key] = value;
|
|
56
40
|
}
|
|
57
41
|
});
|
|
58
|
-
return
|
|
42
|
+
return newNode;
|
|
59
43
|
}
|
|
60
44
|
function getDefaultExportFromCjs(x) {
|
|
61
45
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
@@ -1961,7 +1945,7 @@
|
|
|
1961
1945
|
}
|
|
1962
1946
|
}
|
|
1963
1947
|
};
|
|
1964
|
-
this.
|
|
1948
|
+
this.legacyWalkFields = (cb) => {
|
|
1965
1949
|
const walk = (collectionOrObject, collection, path) => {
|
|
1966
1950
|
if (collectionOrObject.templates) {
|
|
1967
1951
|
collectionOrObject.templates.forEach((template) => {
|
|
@@ -1983,7 +1967,7 @@
|
|
|
1983
1967
|
collections.forEach((collection) => walk(collection, collection, []));
|
|
1984
1968
|
};
|
|
1985
1969
|
this.schema = config;
|
|
1986
|
-
this.
|
|
1970
|
+
this.legacyWalkFields(({ field, collection }) => {
|
|
1987
1971
|
if (!("searchable" in field)) {
|
|
1988
1972
|
if (field.type === "image") {
|
|
1989
1973
|
field.searchable = false;
|
|
@@ -2004,20 +1988,67 @@
|
|
|
2004
1988
|
field.uid = field.uid || false;
|
|
2005
1989
|
});
|
|
2006
1990
|
}
|
|
2007
|
-
|
|
1991
|
+
findReferencesFromCollection(name2) {
|
|
2008
1992
|
const result = {};
|
|
2009
1993
|
this.walkFields(({ field, collection: c, path }) => {
|
|
1994
|
+
if (c.name !== name2) {
|
|
1995
|
+
return;
|
|
1996
|
+
}
|
|
2010
1997
|
if (field.type === "reference") {
|
|
2011
|
-
|
|
2012
|
-
if (result[
|
|
2013
|
-
result[
|
|
1998
|
+
field.collections.forEach((name22) => {
|
|
1999
|
+
if (result[name22] === void 0) {
|
|
2000
|
+
result[name22] = [];
|
|
2014
2001
|
}
|
|
2015
|
-
result[
|
|
2016
|
-
}
|
|
2002
|
+
result[name22].push(path);
|
|
2003
|
+
});
|
|
2017
2004
|
}
|
|
2018
2005
|
});
|
|
2019
2006
|
return result;
|
|
2020
2007
|
}
|
|
2008
|
+
/**
|
|
2009
|
+
* Walk all fields in tina schema
|
|
2010
|
+
*
|
|
2011
|
+
* @param cb callback function invoked for each field
|
|
2012
|
+
*/
|
|
2013
|
+
walkFields(cb) {
|
|
2014
|
+
const walk = (collectionOrObject, collection, path = "$") => {
|
|
2015
|
+
if (collectionOrObject.templates) {
|
|
2016
|
+
collectionOrObject.templates.forEach((template) => {
|
|
2017
|
+
const templatePath = `${path}.${template.name}`;
|
|
2018
|
+
template.fields.forEach((field) => {
|
|
2019
|
+
const fieldPath = field.list ? `${templatePath}[*].${field.name}` : `${templatePath}.${field.name}`;
|
|
2020
|
+
cb({ field, collection, path: fieldPath });
|
|
2021
|
+
if (field.type === "object") {
|
|
2022
|
+
walk(field, collection, fieldPath);
|
|
2023
|
+
}
|
|
2024
|
+
});
|
|
2025
|
+
});
|
|
2026
|
+
}
|
|
2027
|
+
if (collectionOrObject.fields) {
|
|
2028
|
+
collectionOrObject.fields.forEach((field) => {
|
|
2029
|
+
const fieldPath = field.list ? `${path}.${field.name}[*]` : `${path}.${field.name}`;
|
|
2030
|
+
cb({ field, collection, path: fieldPath });
|
|
2031
|
+
if (field.type === "object" && field.fields) {
|
|
2032
|
+
walk(field, collection, fieldPath);
|
|
2033
|
+
} else if (field.templates) {
|
|
2034
|
+
field.templates.forEach((template) => {
|
|
2035
|
+
const templatePath = `${fieldPath}.${template.name}`;
|
|
2036
|
+
template.fields.forEach((field2) => {
|
|
2037
|
+
const fieldPath2 = field2.list ? `${templatePath}[*].${field2.name}` : `${templatePath}.${field2.name}`;
|
|
2038
|
+
cb({ field: field2, collection, path: fieldPath2 });
|
|
2039
|
+
if (field2.type === "object") {
|
|
2040
|
+
walk(field2, collection, fieldPath2);
|
|
2041
|
+
}
|
|
2042
|
+
});
|
|
2043
|
+
});
|
|
2044
|
+
}
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
2047
|
+
};
|
|
2048
|
+
this.getCollections().forEach((collection) => {
|
|
2049
|
+
walk(collection, collection);
|
|
2050
|
+
});
|
|
2051
|
+
}
|
|
2021
2052
|
/**
|
|
2022
2053
|
* This function returns an array of glob matches for a given collection.
|
|
2023
2054
|
*
|
|
@@ -2240,9 +2271,12 @@
|
|
|
2240
2271
|
moreInfo.push(parseZodError({ zodError: unionError }));
|
|
2241
2272
|
});
|
|
2242
2273
|
}
|
|
2243
|
-
const errorMessage =
|
|
2274
|
+
const errorMessage = `${issue == null ? void 0 : issue.message}
|
|
2275
|
+
Additional information:
|
|
2276
|
+
- Error found at path ${issue.path.join(
|
|
2244
2277
|
"."
|
|
2245
|
-
)}
|
|
2278
|
+
)}
|
|
2279
|
+
`;
|
|
2246
2280
|
const errorMessages = [errorMessage, ...moreInfo];
|
|
2247
2281
|
return {
|
|
2248
2282
|
errors: errorMessages
|
|
@@ -2277,6 +2311,9 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2277
2311
|
});
|
|
2278
2312
|
}
|
|
2279
2313
|
});
|
|
2314
|
+
const duplicateFieldErrorMessage = (fields) => `Fields must have unique names. Found duplicate field names: [${fields}]`;
|
|
2315
|
+
const duplicateTemplateErrorMessage = (templates) => `Templates must have unique names. Found duplicate template names: [${templates}]`;
|
|
2316
|
+
const duplicateCollectionErrorMessage = (collection) => `Collections must have unique names. Found duplicate collection names: [${collection}]`;
|
|
2280
2317
|
const TypeName = [
|
|
2281
2318
|
"string",
|
|
2282
2319
|
"boolean",
|
|
@@ -2287,10 +2324,11 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2287
2324
|
"reference",
|
|
2288
2325
|
"rich-text"
|
|
2289
2326
|
];
|
|
2290
|
-
const
|
|
2291
|
-
const
|
|
2292
|
-
|
|
2293
|
-
|
|
2327
|
+
const formattedTypes = ` - ${TypeName.join("\n - ")}`;
|
|
2328
|
+
const typeTypeError = `Invalid \`type\` property. \`type\` expected to be one of the following values:
|
|
2329
|
+
${formattedTypes}`;
|
|
2330
|
+
const typeRequiredError = `Missing \`type\` property. Please add a \`type\` property with one of the following:
|
|
2331
|
+
${formattedTypes}`;
|
|
2294
2332
|
const Option = z.z.union(
|
|
2295
2333
|
[
|
|
2296
2334
|
z.z.string(),
|
|
@@ -2376,7 +2414,7 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2376
2414
|
if (dups) {
|
|
2377
2415
|
ctx.addIssue({
|
|
2378
2416
|
code: z.z.ZodIssueCode.custom,
|
|
2379
|
-
message:
|
|
2417
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2380
2418
|
});
|
|
2381
2419
|
}
|
|
2382
2420
|
});
|
|
@@ -2386,21 +2424,21 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2386
2424
|
invalid_type_error: typeTypeError,
|
|
2387
2425
|
required_error: typeRequiredError
|
|
2388
2426
|
}),
|
|
2389
|
-
fields: z.z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2427
|
+
fields: z.z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2390
2428
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2391
2429
|
if (dups) {
|
|
2392
2430
|
ctx.addIssue({
|
|
2393
2431
|
code: z.z.ZodIssueCode.custom,
|
|
2394
|
-
message:
|
|
2432
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2395
2433
|
});
|
|
2396
2434
|
}
|
|
2397
2435
|
}),
|
|
2398
|
-
templates: z.z.array(TemplateTemp).min(1).optional().superRefine((val, ctx) => {
|
|
2436
|
+
templates: z.z.array(TemplateTemp).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2399
2437
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2400
2438
|
if (dups) {
|
|
2401
2439
|
ctx.addIssue({
|
|
2402
2440
|
code: z.z.ZodIssueCode.custom,
|
|
2403
|
-
message:
|
|
2441
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2404
2442
|
});
|
|
2405
2443
|
}
|
|
2406
2444
|
})
|
|
@@ -2415,7 +2453,7 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2415
2453
|
if (dups) {
|
|
2416
2454
|
ctx.addIssue({
|
|
2417
2455
|
code: z.z.ZodIssueCode.custom,
|
|
2418
|
-
message:
|
|
2456
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2419
2457
|
});
|
|
2420
2458
|
}
|
|
2421
2459
|
})
|
|
@@ -2435,10 +2473,17 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2435
2473
|
],
|
|
2436
2474
|
{
|
|
2437
2475
|
errorMap: (issue, ctx) => {
|
|
2438
|
-
var _a;
|
|
2476
|
+
var _a, _b;
|
|
2439
2477
|
if (issue.code === "invalid_union_discriminator") {
|
|
2478
|
+
if (!((_a = ctx.data) == null ? void 0 : _a.type)) {
|
|
2479
|
+
return {
|
|
2480
|
+
message: `Missing \`type\` property in field \`${ctx.data.name}\`. Please add a \`type\` property with one of the following:
|
|
2481
|
+
${formattedTypes}`
|
|
2482
|
+
};
|
|
2483
|
+
}
|
|
2440
2484
|
return {
|
|
2441
|
-
message: `Invalid \`type\` property. In the schema is 'type: ${(
|
|
2485
|
+
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:
|
|
2486
|
+
${formattedTypes}`
|
|
2442
2487
|
};
|
|
2443
2488
|
}
|
|
2444
2489
|
return {
|
|
@@ -2448,77 +2493,52 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2448
2493
|
}
|
|
2449
2494
|
).superRefine((val, ctx) => {
|
|
2450
2495
|
if (val.type === "string") {
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
${
|
|
2457
|
-
|
|
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
|
-
}
|
|
2496
|
+
const stringifiedField = JSON.stringify(val, null, 2);
|
|
2497
|
+
if (val.isTitle && val.list) {
|
|
2498
|
+
ctx.addIssue({
|
|
2499
|
+
code: z.z.ZodIssueCode.custom,
|
|
2500
|
+
message: `\`list: true\` is not allowed when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2501
|
+
${stringifiedField}`
|
|
2502
|
+
});
|
|
2476
2503
|
}
|
|
2477
|
-
if (val.
|
|
2504
|
+
if (val.isTitle && !val.required) {
|
|
2505
|
+
ctx.addIssue({
|
|
2506
|
+
code: z.z.ZodIssueCode.custom,
|
|
2507
|
+
message: `Property \`required: true\` is required when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2508
|
+
${stringifiedField}`
|
|
2509
|
+
});
|
|
2510
|
+
}
|
|
2511
|
+
if (val.uid && val.list) {
|
|
2478
2512
|
if (val.list) {
|
|
2479
2513
|
ctx.addIssue({
|
|
2480
2514
|
code: z.z.ZodIssueCode.custom,
|
|
2481
|
-
message:
|
|
2482
|
-
${
|
|
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
|
-
`
|
|
2515
|
+
message: `\`list: true\` is not allowed when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2516
|
+
${stringifiedField}`
|
|
2500
2517
|
});
|
|
2501
2518
|
}
|
|
2502
2519
|
}
|
|
2520
|
+
if (val.uid && !val.required) {
|
|
2521
|
+
ctx.addIssue({
|
|
2522
|
+
code: z.z.ZodIssueCode.custom,
|
|
2523
|
+
message: `Property \`required: true\` is required when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2524
|
+
${stringifiedField}`
|
|
2525
|
+
});
|
|
2526
|
+
}
|
|
2503
2527
|
}
|
|
2504
2528
|
if (val.type === "object") {
|
|
2505
|
-
|
|
2506
|
-
let isValid = Boolean(val == null ? void 0 : val.templates) || Boolean(val == null ? void 0 : val.fields);
|
|
2507
|
-
if (!isValid) {
|
|
2529
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2508
2530
|
ctx.addIssue({
|
|
2509
2531
|
code: z.z.ZodIssueCode.custom,
|
|
2510
|
-
message
|
|
2532
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2533
|
+
});
|
|
2534
|
+
return false;
|
|
2535
|
+
}
|
|
2536
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2537
|
+
ctx.addIssue({
|
|
2538
|
+
code: z.z.ZodIssueCode.custom,
|
|
2539
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2511
2540
|
});
|
|
2512
2541
|
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
2542
|
}
|
|
2523
2543
|
}
|
|
2524
2544
|
return true;
|
|
@@ -2562,8 +2582,8 @@ ${JSON.stringify(
|
|
|
2562
2582
|
];
|
|
2563
2583
|
const Template = z.z.object({
|
|
2564
2584
|
label: z.z.string({
|
|
2565
|
-
invalid_type_error: "label
|
|
2566
|
-
required_error: "label
|
|
2585
|
+
invalid_type_error: "Invalid data type for property `label`. Must be of type `string`",
|
|
2586
|
+
required_error: "Missing `label` property. Property `label` is required."
|
|
2567
2587
|
}),
|
|
2568
2588
|
name,
|
|
2569
2589
|
fields: z.z.array(TinaFieldZod)
|
|
@@ -2573,7 +2593,7 @@ ${JSON.stringify(
|
|
|
2573
2593
|
if (dups) {
|
|
2574
2594
|
ctx.addIssue({
|
|
2575
2595
|
code: z.z.ZodIssueCode.custom,
|
|
2576
|
-
message:
|
|
2596
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2577
2597
|
});
|
|
2578
2598
|
}
|
|
2579
2599
|
});
|
|
@@ -2583,7 +2603,7 @@ ${JSON.stringify(
|
|
|
2583
2603
|
if (val === "relativePath") {
|
|
2584
2604
|
ctx.addIssue({
|
|
2585
2605
|
code: z.z.ZodIssueCode.custom,
|
|
2586
|
-
message: `name cannot be 'relativePath'
|
|
2606
|
+
message: "Invalid `name` property. `name` cannot be 'relativePath' as it is a reserved field name."
|
|
2587
2607
|
});
|
|
2588
2608
|
}
|
|
2589
2609
|
}),
|
|
@@ -2591,7 +2611,7 @@ ${JSON.stringify(
|
|
|
2591
2611
|
if (val === ".") {
|
|
2592
2612
|
ctx.addIssue({
|
|
2593
2613
|
code: z.z.ZodIssueCode.custom,
|
|
2594
|
-
message: `path cannot be '.'. Please use '/' or '' instead.
|
|
2614
|
+
message: "Invalid `path` property. `path` cannot be '.'. Please use '/' or '' instead."
|
|
2595
2615
|
});
|
|
2596
2616
|
}
|
|
2597
2617
|
}),
|
|
@@ -2600,63 +2620,64 @@ ${JSON.stringify(
|
|
|
2600
2620
|
isDetached: z.z.boolean().optional()
|
|
2601
2621
|
});
|
|
2602
2622
|
const TinaCloudCollection = CollectionBaseSchema.extend({
|
|
2603
|
-
fields: z.z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2623
|
+
fields: z.z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2604
2624
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2605
2625
|
if (dups) {
|
|
2606
2626
|
ctx.addIssue({
|
|
2607
2627
|
code: z.z.ZodIssueCode.custom,
|
|
2608
|
-
message:
|
|
2628
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2609
2629
|
});
|
|
2610
2630
|
}
|
|
2611
|
-
}).
|
|
2612
|
-
|
|
2613
|
-
(
|
|
2614
|
-
|
|
2615
|
-
|
|
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"
|
|
2631
|
+
}).superRefine((val, ctx) => {
|
|
2632
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "string" && x.isTitle)) || [];
|
|
2633
|
+
if (arr.length > 1) {
|
|
2634
|
+
ctx.addIssue({
|
|
2635
|
+
code: z.z.ZodIssueCode.custom,
|
|
2636
|
+
message: `The following fields have the property \`isTitle\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`isTitle\`.`
|
|
2637
|
+
});
|
|
2637
2638
|
}
|
|
2638
|
-
),
|
|
2639
|
-
|
|
2639
|
+
}).superRefine((val, ctx) => {
|
|
2640
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
|
|
2641
|
+
if (arr.length > 2) {
|
|
2642
|
+
ctx.addIssue({
|
|
2643
|
+
code: z.z.ZodIssueCode.custom,
|
|
2644
|
+
message: `The following fields have the property \`uid\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`uid\`.`
|
|
2645
|
+
});
|
|
2646
|
+
}
|
|
2647
|
+
}).superRefine((val, ctx) => {
|
|
2648
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
|
|
2649
|
+
if (arr.length > 2) {
|
|
2650
|
+
ctx.addIssue({
|
|
2651
|
+
code: z.z.ZodIssueCode.custom,
|
|
2652
|
+
message: `The following fields have \`type: password\`: [${arr.map((field) => field.name).join(", ")}]. Only one can be of \`type: password\`.`
|
|
2653
|
+
});
|
|
2654
|
+
}
|
|
2655
|
+
}),
|
|
2656
|
+
templates: z.z.array(Template).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2640
2657
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2641
2658
|
if (dups) {
|
|
2642
2659
|
ctx.addIssue({
|
|
2643
2660
|
code: z.z.ZodIssueCode.custom,
|
|
2644
|
-
message:
|
|
2661
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2645
2662
|
});
|
|
2646
2663
|
}
|
|
2647
2664
|
})
|
|
2648
|
-
}).
|
|
2649
|
-
(val)
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
}
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2665
|
+
}).superRefine((val, ctx) => {
|
|
2666
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2667
|
+
ctx.addIssue({
|
|
2668
|
+
code: z.z.ZodIssueCode.custom,
|
|
2669
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2670
|
+
});
|
|
2671
|
+
return false;
|
|
2672
|
+
}
|
|
2673
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2674
|
+
ctx.addIssue({
|
|
2675
|
+
code: z.z.ZodIssueCode.custom,
|
|
2676
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2677
|
+
});
|
|
2678
|
+
return false;
|
|
2679
|
+
}
|
|
2680
|
+
});
|
|
2660
2681
|
const TinaCloudSchemaZod = z.z.object({
|
|
2661
2682
|
collections: z.z.array(TinaCloudCollection),
|
|
2662
2683
|
config: tinaConfigZod.optional()
|
|
@@ -2666,14 +2687,14 @@ ${JSON.stringify(
|
|
|
2666
2687
|
if (dups) {
|
|
2667
2688
|
ctx.addIssue({
|
|
2668
2689
|
code: z.z.ZodIssueCode.custom,
|
|
2669
|
-
message:
|
|
2690
|
+
message: duplicateCollectionErrorMessage(dups),
|
|
2670
2691
|
fatal: true
|
|
2671
2692
|
});
|
|
2672
2693
|
}
|
|
2673
2694
|
if (((_b = val.collections) == null ? void 0 : _b.filter((x) => x.isAuthCollection).length) > 1) {
|
|
2674
2695
|
ctx.addIssue({
|
|
2675
2696
|
code: z.z.ZodIssueCode.custom,
|
|
2676
|
-
message:
|
|
2697
|
+
message: "Only one collection can be marked as `isAuthCollection`.",
|
|
2677
2698
|
fatal: true
|
|
2678
2699
|
});
|
|
2679
2700
|
}
|
|
@@ -2681,7 +2702,7 @@ ${JSON.stringify(
|
|
|
2681
2702
|
if (media && media.tina && media.loadCustomStore) {
|
|
2682
2703
|
ctx.addIssue({
|
|
2683
2704
|
code: z.z.ZodIssueCode.custom,
|
|
2684
|
-
message: "
|
|
2705
|
+
message: "Cannot have both `loadCustomStore` and `tina`. Must use one or the other.",
|
|
2685
2706
|
fatal: true,
|
|
2686
2707
|
path: ["config", "media"]
|
|
2687
2708
|
});
|
|
@@ -2690,7 +2711,7 @@ ${JSON.stringify(
|
|
|
2690
2711
|
if (search && search.tina && search.searchClient) {
|
|
2691
2712
|
ctx.addIssue({
|
|
2692
2713
|
code: z.z.ZodIssueCode.custom,
|
|
2693
|
-
message: "
|
|
2714
|
+
message: "Cannot have both `searchClient` and `tina`. Must use one or the other.",
|
|
2694
2715
|
fatal: true,
|
|
2695
2716
|
path: ["config", "search"]
|
|
2696
2717
|
});
|
|
@@ -2708,7 +2729,7 @@ ${JSON.stringify(
|
|
|
2708
2729
|
} catch (e) {
|
|
2709
2730
|
if (e instanceof z.ZodError) {
|
|
2710
2731
|
const errors = parseZodError({ zodError: e });
|
|
2711
|
-
throw new TinaSchemaValidationError(errors.join("
|
|
2732
|
+
throw new TinaSchemaValidationError(errors.join("\n"));
|
|
2712
2733
|
}
|
|
2713
2734
|
throw new Error(e);
|
|
2714
2735
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -2,42 +2,26 @@ import * as yup from "yup";
|
|
|
2
2
|
import UrlPattern from "url-pattern";
|
|
3
3
|
import z$1, { z, ZodError } from "zod";
|
|
4
4
|
function addNamespaceToSchema(maybeNode, namespace = []) {
|
|
5
|
-
if (typeof maybeNode
|
|
5
|
+
if (typeof maybeNode !== "object" || maybeNode === null) {
|
|
6
6
|
return maybeNode;
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const keys = Object.keys(maybeNode);
|
|
16
|
-
Object.values(maybeNode).map((m, index) => {
|
|
17
|
-
const key = keys[index];
|
|
18
|
-
if (Array.isArray(m)) {
|
|
19
|
-
newNode[key] = m.map((element) => {
|
|
20
|
-
if (!element) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
if (!element.hasOwnProperty("name")) {
|
|
24
|
-
return element;
|
|
8
|
+
const newNode = { ...maybeNode, namespace: [...namespace] };
|
|
9
|
+
Object.entries(maybeNode).forEach(([key, value]) => {
|
|
10
|
+
if (Array.isArray(value)) {
|
|
11
|
+
newNode[key] = value.map((element) => {
|
|
12
|
+
if (element && typeof element === "object" && "name" in element) {
|
|
13
|
+
const valueName = element.name || element.value;
|
|
14
|
+
return addNamespaceToSchema(element, [...namespace, valueName]);
|
|
25
15
|
}
|
|
26
|
-
|
|
27
|
-
return addNamespaceToSchema(element, [...namespace, value]);
|
|
16
|
+
return element;
|
|
28
17
|
});
|
|
18
|
+
} else if (value && typeof value === "object" && "name" in value) {
|
|
19
|
+
newNode[key] = addNamespaceToSchema(value, [...namespace, value.name]);
|
|
29
20
|
} else {
|
|
30
|
-
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
if (!m.hasOwnProperty("name")) {
|
|
34
|
-
newNode[key] = m;
|
|
35
|
-
} else {
|
|
36
|
-
newNode[key] = addNamespaceToSchema(m, [...namespace, m.name]);
|
|
37
|
-
}
|
|
21
|
+
newNode[key] = value;
|
|
38
22
|
}
|
|
39
23
|
});
|
|
40
|
-
return
|
|
24
|
+
return newNode;
|
|
41
25
|
}
|
|
42
26
|
function getDefaultExportFromCjs(x) {
|
|
43
27
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
@@ -1943,7 +1927,7 @@ class TinaSchema {
|
|
|
1943
1927
|
}
|
|
1944
1928
|
}
|
|
1945
1929
|
};
|
|
1946
|
-
this.
|
|
1930
|
+
this.legacyWalkFields = (cb) => {
|
|
1947
1931
|
const walk = (collectionOrObject, collection, path) => {
|
|
1948
1932
|
if (collectionOrObject.templates) {
|
|
1949
1933
|
collectionOrObject.templates.forEach((template) => {
|
|
@@ -1965,7 +1949,7 @@ class TinaSchema {
|
|
|
1965
1949
|
collections.forEach((collection) => walk(collection, collection, []));
|
|
1966
1950
|
};
|
|
1967
1951
|
this.schema = config;
|
|
1968
|
-
this.
|
|
1952
|
+
this.legacyWalkFields(({ field, collection }) => {
|
|
1969
1953
|
if (!("searchable" in field)) {
|
|
1970
1954
|
if (field.type === "image") {
|
|
1971
1955
|
field.searchable = false;
|
|
@@ -1986,20 +1970,67 @@ class TinaSchema {
|
|
|
1986
1970
|
field.uid = field.uid || false;
|
|
1987
1971
|
});
|
|
1988
1972
|
}
|
|
1989
|
-
|
|
1973
|
+
findReferencesFromCollection(name2) {
|
|
1990
1974
|
const result = {};
|
|
1991
1975
|
this.walkFields(({ field, collection: c, path }) => {
|
|
1976
|
+
if (c.name !== name2) {
|
|
1977
|
+
return;
|
|
1978
|
+
}
|
|
1992
1979
|
if (field.type === "reference") {
|
|
1993
|
-
|
|
1994
|
-
if (result[
|
|
1995
|
-
result[
|
|
1980
|
+
field.collections.forEach((name22) => {
|
|
1981
|
+
if (result[name22] === void 0) {
|
|
1982
|
+
result[name22] = [];
|
|
1996
1983
|
}
|
|
1997
|
-
result[
|
|
1998
|
-
}
|
|
1984
|
+
result[name22].push(path);
|
|
1985
|
+
});
|
|
1999
1986
|
}
|
|
2000
1987
|
});
|
|
2001
1988
|
return result;
|
|
2002
1989
|
}
|
|
1990
|
+
/**
|
|
1991
|
+
* Walk all fields in tina schema
|
|
1992
|
+
*
|
|
1993
|
+
* @param cb callback function invoked for each field
|
|
1994
|
+
*/
|
|
1995
|
+
walkFields(cb) {
|
|
1996
|
+
const walk = (collectionOrObject, collection, path = "$") => {
|
|
1997
|
+
if (collectionOrObject.templates) {
|
|
1998
|
+
collectionOrObject.templates.forEach((template) => {
|
|
1999
|
+
const templatePath = `${path}.${template.name}`;
|
|
2000
|
+
template.fields.forEach((field) => {
|
|
2001
|
+
const fieldPath = field.list ? `${templatePath}[*].${field.name}` : `${templatePath}.${field.name}`;
|
|
2002
|
+
cb({ field, collection, path: fieldPath });
|
|
2003
|
+
if (field.type === "object") {
|
|
2004
|
+
walk(field, collection, fieldPath);
|
|
2005
|
+
}
|
|
2006
|
+
});
|
|
2007
|
+
});
|
|
2008
|
+
}
|
|
2009
|
+
if (collectionOrObject.fields) {
|
|
2010
|
+
collectionOrObject.fields.forEach((field) => {
|
|
2011
|
+
const fieldPath = field.list ? `${path}.${field.name}[*]` : `${path}.${field.name}`;
|
|
2012
|
+
cb({ field, collection, path: fieldPath });
|
|
2013
|
+
if (field.type === "object" && field.fields) {
|
|
2014
|
+
walk(field, collection, fieldPath);
|
|
2015
|
+
} else if (field.templates) {
|
|
2016
|
+
field.templates.forEach((template) => {
|
|
2017
|
+
const templatePath = `${fieldPath}.${template.name}`;
|
|
2018
|
+
template.fields.forEach((field2) => {
|
|
2019
|
+
const fieldPath2 = field2.list ? `${templatePath}[*].${field2.name}` : `${templatePath}.${field2.name}`;
|
|
2020
|
+
cb({ field: field2, collection, path: fieldPath2 });
|
|
2021
|
+
if (field2.type === "object") {
|
|
2022
|
+
walk(field2, collection, fieldPath2);
|
|
2023
|
+
}
|
|
2024
|
+
});
|
|
2025
|
+
});
|
|
2026
|
+
}
|
|
2027
|
+
});
|
|
2028
|
+
}
|
|
2029
|
+
};
|
|
2030
|
+
this.getCollections().forEach((collection) => {
|
|
2031
|
+
walk(collection, collection);
|
|
2032
|
+
});
|
|
2033
|
+
}
|
|
2003
2034
|
/**
|
|
2004
2035
|
* This function returns an array of glob matches for a given collection.
|
|
2005
2036
|
*
|
|
@@ -2222,9 +2253,12 @@ const parseZodError = ({ zodError }) => {
|
|
|
2222
2253
|
moreInfo.push(parseZodError({ zodError: unionError }));
|
|
2223
2254
|
});
|
|
2224
2255
|
}
|
|
2225
|
-
const errorMessage =
|
|
2256
|
+
const errorMessage = `${issue == null ? void 0 : issue.message}
|
|
2257
|
+
Additional information:
|
|
2258
|
+
- Error found at path ${issue.path.join(
|
|
2226
2259
|
"."
|
|
2227
|
-
)}
|
|
2260
|
+
)}
|
|
2261
|
+
`;
|
|
2228
2262
|
const errorMessages = [errorMessage, ...moreInfo];
|
|
2229
2263
|
return {
|
|
2230
2264
|
errors: errorMessages
|
|
@@ -2259,6 +2293,9 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2259
2293
|
});
|
|
2260
2294
|
}
|
|
2261
2295
|
});
|
|
2296
|
+
const duplicateFieldErrorMessage = (fields) => `Fields must have unique names. Found duplicate field names: [${fields}]`;
|
|
2297
|
+
const duplicateTemplateErrorMessage = (templates) => `Templates must have unique names. Found duplicate template names: [${templates}]`;
|
|
2298
|
+
const duplicateCollectionErrorMessage = (collection) => `Collections must have unique names. Found duplicate collection names: [${collection}]`;
|
|
2262
2299
|
const TypeName = [
|
|
2263
2300
|
"string",
|
|
2264
2301
|
"boolean",
|
|
@@ -2269,10 +2306,11 @@ const TypeName = [
|
|
|
2269
2306
|
"reference",
|
|
2270
2307
|
"rich-text"
|
|
2271
2308
|
];
|
|
2272
|
-
const
|
|
2273
|
-
const
|
|
2274
|
-
|
|
2275
|
-
|
|
2309
|
+
const formattedTypes = ` - ${TypeName.join("\n - ")}`;
|
|
2310
|
+
const typeTypeError = `Invalid \`type\` property. \`type\` expected to be one of the following values:
|
|
2311
|
+
${formattedTypes}`;
|
|
2312
|
+
const typeRequiredError = `Missing \`type\` property. Please add a \`type\` property with one of the following:
|
|
2313
|
+
${formattedTypes}`;
|
|
2276
2314
|
const Option = z.union(
|
|
2277
2315
|
[
|
|
2278
2316
|
z.string(),
|
|
@@ -2358,7 +2396,7 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2358
2396
|
if (dups) {
|
|
2359
2397
|
ctx.addIssue({
|
|
2360
2398
|
code: z.ZodIssueCode.custom,
|
|
2361
|
-
message:
|
|
2399
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2362
2400
|
});
|
|
2363
2401
|
}
|
|
2364
2402
|
});
|
|
@@ -2368,21 +2406,21 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2368
2406
|
invalid_type_error: typeTypeError,
|
|
2369
2407
|
required_error: typeRequiredError
|
|
2370
2408
|
}),
|
|
2371
|
-
fields: z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2409
|
+
fields: z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2372
2410
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2373
2411
|
if (dups) {
|
|
2374
2412
|
ctx.addIssue({
|
|
2375
2413
|
code: z.ZodIssueCode.custom,
|
|
2376
|
-
message:
|
|
2414
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2377
2415
|
});
|
|
2378
2416
|
}
|
|
2379
2417
|
}),
|
|
2380
|
-
templates: z.array(TemplateTemp).min(1).optional().superRefine((val, ctx) => {
|
|
2418
|
+
templates: z.array(TemplateTemp).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2381
2419
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2382
2420
|
if (dups) {
|
|
2383
2421
|
ctx.addIssue({
|
|
2384
2422
|
code: z.ZodIssueCode.custom,
|
|
2385
|
-
message:
|
|
2423
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2386
2424
|
});
|
|
2387
2425
|
}
|
|
2388
2426
|
})
|
|
@@ -2397,7 +2435,7 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2397
2435
|
if (dups) {
|
|
2398
2436
|
ctx.addIssue({
|
|
2399
2437
|
code: z.ZodIssueCode.custom,
|
|
2400
|
-
message:
|
|
2438
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2401
2439
|
});
|
|
2402
2440
|
}
|
|
2403
2441
|
})
|
|
@@ -2417,10 +2455,17 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2417
2455
|
],
|
|
2418
2456
|
{
|
|
2419
2457
|
errorMap: (issue, ctx) => {
|
|
2420
|
-
var _a;
|
|
2458
|
+
var _a, _b;
|
|
2421
2459
|
if (issue.code === "invalid_union_discriminator") {
|
|
2460
|
+
if (!((_a = ctx.data) == null ? void 0 : _a.type)) {
|
|
2461
|
+
return {
|
|
2462
|
+
message: `Missing \`type\` property in field \`${ctx.data.name}\`. Please add a \`type\` property with one of the following:
|
|
2463
|
+
${formattedTypes}`
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2422
2466
|
return {
|
|
2423
|
-
message: `Invalid \`type\` property. In the schema is 'type: ${(
|
|
2467
|
+
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:
|
|
2468
|
+
${formattedTypes}`
|
|
2424
2469
|
};
|
|
2425
2470
|
}
|
|
2426
2471
|
return {
|
|
@@ -2430,77 +2475,52 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2430
2475
|
}
|
|
2431
2476
|
).superRefine((val, ctx) => {
|
|
2432
2477
|
if (val.type === "string") {
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
${
|
|
2439
|
-
|
|
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
|
-
}
|
|
2478
|
+
const stringifiedField = JSON.stringify(val, null, 2);
|
|
2479
|
+
if (val.isTitle && val.list) {
|
|
2480
|
+
ctx.addIssue({
|
|
2481
|
+
code: z.ZodIssueCode.custom,
|
|
2482
|
+
message: `\`list: true\` is not allowed when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2483
|
+
${stringifiedField}`
|
|
2484
|
+
});
|
|
2458
2485
|
}
|
|
2459
|
-
if (val.
|
|
2486
|
+
if (val.isTitle && !val.required) {
|
|
2487
|
+
ctx.addIssue({
|
|
2488
|
+
code: z.ZodIssueCode.custom,
|
|
2489
|
+
message: `Property \`required: true\` is required when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2490
|
+
${stringifiedField}`
|
|
2491
|
+
});
|
|
2492
|
+
}
|
|
2493
|
+
if (val.uid && val.list) {
|
|
2460
2494
|
if (val.list) {
|
|
2461
2495
|
ctx.addIssue({
|
|
2462
2496
|
code: z.ZodIssueCode.custom,
|
|
2463
|
-
message:
|
|
2464
|
-
${
|
|
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
|
-
`
|
|
2497
|
+
message: `\`list: true\` is not allowed when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2498
|
+
${stringifiedField}`
|
|
2482
2499
|
});
|
|
2483
2500
|
}
|
|
2484
2501
|
}
|
|
2502
|
+
if (val.uid && !val.required) {
|
|
2503
|
+
ctx.addIssue({
|
|
2504
|
+
code: z.ZodIssueCode.custom,
|
|
2505
|
+
message: `Property \`required: true\` is required when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2506
|
+
${stringifiedField}`
|
|
2507
|
+
});
|
|
2508
|
+
}
|
|
2485
2509
|
}
|
|
2486
2510
|
if (val.type === "object") {
|
|
2487
|
-
|
|
2488
|
-
let isValid = Boolean(val == null ? void 0 : val.templates) || Boolean(val == null ? void 0 : val.fields);
|
|
2489
|
-
if (!isValid) {
|
|
2511
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2490
2512
|
ctx.addIssue({
|
|
2491
2513
|
code: z.ZodIssueCode.custom,
|
|
2492
|
-
message
|
|
2514
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2515
|
+
});
|
|
2516
|
+
return false;
|
|
2517
|
+
}
|
|
2518
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2519
|
+
ctx.addIssue({
|
|
2520
|
+
code: z.ZodIssueCode.custom,
|
|
2521
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2493
2522
|
});
|
|
2494
2523
|
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
2524
|
}
|
|
2505
2525
|
}
|
|
2506
2526
|
return true;
|
|
@@ -2544,8 +2564,8 @@ const FORMATS = [
|
|
|
2544
2564
|
];
|
|
2545
2565
|
const Template = z.object({
|
|
2546
2566
|
label: z.string({
|
|
2547
|
-
invalid_type_error: "label
|
|
2548
|
-
required_error: "label
|
|
2567
|
+
invalid_type_error: "Invalid data type for property `label`. Must be of type `string`",
|
|
2568
|
+
required_error: "Missing `label` property. Property `label` is required."
|
|
2549
2569
|
}),
|
|
2550
2570
|
name,
|
|
2551
2571
|
fields: z.array(TinaFieldZod)
|
|
@@ -2555,7 +2575,7 @@ const Template = z.object({
|
|
|
2555
2575
|
if (dups) {
|
|
2556
2576
|
ctx.addIssue({
|
|
2557
2577
|
code: z.ZodIssueCode.custom,
|
|
2558
|
-
message:
|
|
2578
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2559
2579
|
});
|
|
2560
2580
|
}
|
|
2561
2581
|
});
|
|
@@ -2565,7 +2585,7 @@ const CollectionBaseSchema = z.object({
|
|
|
2565
2585
|
if (val === "relativePath") {
|
|
2566
2586
|
ctx.addIssue({
|
|
2567
2587
|
code: z.ZodIssueCode.custom,
|
|
2568
|
-
message: `name cannot be 'relativePath'
|
|
2588
|
+
message: "Invalid `name` property. `name` cannot be 'relativePath' as it is a reserved field name."
|
|
2569
2589
|
});
|
|
2570
2590
|
}
|
|
2571
2591
|
}),
|
|
@@ -2573,7 +2593,7 @@ const CollectionBaseSchema = z.object({
|
|
|
2573
2593
|
if (val === ".") {
|
|
2574
2594
|
ctx.addIssue({
|
|
2575
2595
|
code: z.ZodIssueCode.custom,
|
|
2576
|
-
message: `path cannot be '.'. Please use '/' or '' instead.
|
|
2596
|
+
message: "Invalid `path` property. `path` cannot be '.'. Please use '/' or '' instead."
|
|
2577
2597
|
});
|
|
2578
2598
|
}
|
|
2579
2599
|
}),
|
|
@@ -2582,63 +2602,64 @@ const CollectionBaseSchema = z.object({
|
|
|
2582
2602
|
isDetached: z.boolean().optional()
|
|
2583
2603
|
});
|
|
2584
2604
|
const TinaCloudCollection = CollectionBaseSchema.extend({
|
|
2585
|
-
fields: z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2605
|
+
fields: z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2586
2606
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2587
2607
|
if (dups) {
|
|
2588
2608
|
ctx.addIssue({
|
|
2589
2609
|
code: z.ZodIssueCode.custom,
|
|
2590
|
-
message:
|
|
2610
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2591
2611
|
});
|
|
2592
2612
|
}
|
|
2593
|
-
}).
|
|
2594
|
-
|
|
2595
|
-
(
|
|
2596
|
-
|
|
2597
|
-
|
|
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"
|
|
2613
|
+
}).superRefine((val, ctx) => {
|
|
2614
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "string" && x.isTitle)) || [];
|
|
2615
|
+
if (arr.length > 1) {
|
|
2616
|
+
ctx.addIssue({
|
|
2617
|
+
code: z.ZodIssueCode.custom,
|
|
2618
|
+
message: `The following fields have the property \`isTitle\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`isTitle\`.`
|
|
2619
|
+
});
|
|
2619
2620
|
}
|
|
2620
|
-
),
|
|
2621
|
-
|
|
2621
|
+
}).superRefine((val, ctx) => {
|
|
2622
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
|
|
2623
|
+
if (arr.length > 2) {
|
|
2624
|
+
ctx.addIssue({
|
|
2625
|
+
code: z.ZodIssueCode.custom,
|
|
2626
|
+
message: `The following fields have the property \`uid\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`uid\`.`
|
|
2627
|
+
});
|
|
2628
|
+
}
|
|
2629
|
+
}).superRefine((val, ctx) => {
|
|
2630
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
|
|
2631
|
+
if (arr.length > 2) {
|
|
2632
|
+
ctx.addIssue({
|
|
2633
|
+
code: z.ZodIssueCode.custom,
|
|
2634
|
+
message: `The following fields have \`type: password\`: [${arr.map((field) => field.name).join(", ")}]. Only one can be of \`type: password\`.`
|
|
2635
|
+
});
|
|
2636
|
+
}
|
|
2637
|
+
}),
|
|
2638
|
+
templates: z.array(Template).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2622
2639
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2623
2640
|
if (dups) {
|
|
2624
2641
|
ctx.addIssue({
|
|
2625
2642
|
code: z.ZodIssueCode.custom,
|
|
2626
|
-
message:
|
|
2643
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2627
2644
|
});
|
|
2628
2645
|
}
|
|
2629
2646
|
})
|
|
2630
|
-
}).
|
|
2631
|
-
(val)
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
}
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2647
|
+
}).superRefine((val, ctx) => {
|
|
2648
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2649
|
+
ctx.addIssue({
|
|
2650
|
+
code: z.ZodIssueCode.custom,
|
|
2651
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2652
|
+
});
|
|
2653
|
+
return false;
|
|
2654
|
+
}
|
|
2655
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2656
|
+
ctx.addIssue({
|
|
2657
|
+
code: z.ZodIssueCode.custom,
|
|
2658
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2659
|
+
});
|
|
2660
|
+
return false;
|
|
2661
|
+
}
|
|
2662
|
+
});
|
|
2642
2663
|
const TinaCloudSchemaZod = z.object({
|
|
2643
2664
|
collections: z.array(TinaCloudCollection),
|
|
2644
2665
|
config: tinaConfigZod.optional()
|
|
@@ -2648,14 +2669,14 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2648
2669
|
if (dups) {
|
|
2649
2670
|
ctx.addIssue({
|
|
2650
2671
|
code: z.ZodIssueCode.custom,
|
|
2651
|
-
message:
|
|
2672
|
+
message: duplicateCollectionErrorMessage(dups),
|
|
2652
2673
|
fatal: true
|
|
2653
2674
|
});
|
|
2654
2675
|
}
|
|
2655
2676
|
if (((_b = val.collections) == null ? void 0 : _b.filter((x) => x.isAuthCollection).length) > 1) {
|
|
2656
2677
|
ctx.addIssue({
|
|
2657
2678
|
code: z.ZodIssueCode.custom,
|
|
2658
|
-
message:
|
|
2679
|
+
message: "Only one collection can be marked as `isAuthCollection`.",
|
|
2659
2680
|
fatal: true
|
|
2660
2681
|
});
|
|
2661
2682
|
}
|
|
@@ -2663,7 +2684,7 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2663
2684
|
if (media && media.tina && media.loadCustomStore) {
|
|
2664
2685
|
ctx.addIssue({
|
|
2665
2686
|
code: z.ZodIssueCode.custom,
|
|
2666
|
-
message: "
|
|
2687
|
+
message: "Cannot have both `loadCustomStore` and `tina`. Must use one or the other.",
|
|
2667
2688
|
fatal: true,
|
|
2668
2689
|
path: ["config", "media"]
|
|
2669
2690
|
});
|
|
@@ -2672,7 +2693,7 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2672
2693
|
if (search && search.tina && search.searchClient) {
|
|
2673
2694
|
ctx.addIssue({
|
|
2674
2695
|
code: z.ZodIssueCode.custom,
|
|
2675
|
-
message: "
|
|
2696
|
+
message: "Cannot have both `searchClient` and `tina`. Must use one or the other.",
|
|
2676
2697
|
fatal: true,
|
|
2677
2698
|
path: ["config", "search"]
|
|
2678
2699
|
});
|
|
@@ -2690,7 +2711,7 @@ const validateSchema = ({ schema }) => {
|
|
|
2690
2711
|
} catch (e) {
|
|
2691
2712
|
if (e instanceof ZodError) {
|
|
2692
2713
|
const errors = parseZodError({ zodError: e });
|
|
2693
|
-
throw new TinaSchemaValidationError(errors.join("
|
|
2714
|
+
throw new TinaSchemaValidationError(errors.join("\n"));
|
|
2694
2715
|
}
|
|
2695
2716
|
throw new Error(e);
|
|
2696
2717
|
}
|
|
@@ -28,10 +28,7 @@ export declare class TinaSchema {
|
|
|
28
28
|
} & Schema);
|
|
29
29
|
getIsTitleFieldName: (collection: string) => string;
|
|
30
30
|
getCollectionsByName: (collectionNames: string[]) => Collection<true>[];
|
|
31
|
-
|
|
32
|
-
path: string[];
|
|
33
|
-
field: TinaField;
|
|
34
|
-
}[]>;
|
|
31
|
+
findReferencesFromCollection(name: string): Record<string, string[]>;
|
|
35
32
|
getCollection: (collectionName: string) => Collection<true>;
|
|
36
33
|
getCollections: () => Collection<true>[];
|
|
37
34
|
getCollectionByFullPath: (filepath: string) => Collection<true>;
|
|
@@ -63,7 +60,26 @@ export declare class TinaSchema {
|
|
|
63
60
|
*
|
|
64
61
|
*/
|
|
65
62
|
getTemplatesForCollectable: (collection: Collectable) => CollectionTemplateable;
|
|
66
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Walk all fields in tina schema
|
|
65
|
+
*
|
|
66
|
+
* @param cb callback function invoked for each field
|
|
67
|
+
*/
|
|
68
|
+
walkFields(cb: (args: {
|
|
69
|
+
field: any;
|
|
70
|
+
collection: any;
|
|
71
|
+
path: string;
|
|
72
|
+
isListItem?: boolean;
|
|
73
|
+
}) => void): void;
|
|
74
|
+
/**
|
|
75
|
+
* Walk all fields in Tina Schema
|
|
76
|
+
*
|
|
77
|
+
* This is a legacy version to preserve backwards compatibility for the tina generated schema. It does not
|
|
78
|
+
* traverse fields in object lists in rich-text templates.
|
|
79
|
+
*
|
|
80
|
+
* @param cb callback function invoked for each field
|
|
81
|
+
*/
|
|
82
|
+
legacyWalkFields: (cb: (args: {
|
|
67
83
|
field: TinaField;
|
|
68
84
|
collection: Collection;
|
|
69
85
|
path: string[];
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
type Node = {
|
|
2
|
+
name?: string;
|
|
3
|
+
value?: string;
|
|
4
|
+
namespace?: string[];
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
};
|
|
7
|
+
export declare function addNamespaceToSchema<T extends Node | string>(maybeNode: T, namespace?: string[]): T;
|
|
8
|
+
export {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -198,8 +198,14 @@ export type RichTextField<WithNamespace extends boolean = false> = (FieldGeneric
|
|
|
198
198
|
* will be stored as frontmatter
|
|
199
199
|
*/
|
|
200
200
|
isBody?: boolean;
|
|
201
|
+
/**@deprecated use overrides.toolbar */
|
|
201
202
|
toolbarOverride?: ToolbarOverrideType[];
|
|
202
203
|
templates?: RichTextTemplate<WithNamespace>[];
|
|
204
|
+
overrides?: {
|
|
205
|
+
toolbar?: ToolbarOverrideType[];
|
|
206
|
+
/**Default set to true */
|
|
207
|
+
showFloatingToolbar?: boolean;
|
|
208
|
+
};
|
|
203
209
|
/**
|
|
204
210
|
* By default, Tina parses markdown with MDX, this is a more strict parser
|
|
205
211
|
* that allows you to use structured content inside markdown (via `templates`).
|
|
@@ -357,6 +363,7 @@ interface AuthHooks {
|
|
|
357
363
|
type AuthOptions = AuthHooks & AuthProvider;
|
|
358
364
|
export interface Config<CMSCallback = undefined, FormifyCallback = undefined, DocumentCreatorCallback = undefined, Store = undefined, SearchClient = undefined> {
|
|
359
365
|
contentApiUrlOverride?: string;
|
|
366
|
+
oauth2?: boolean;
|
|
360
367
|
authProvider?: AuthProvider;
|
|
361
368
|
admin?: {
|
|
362
369
|
/**
|
|
@@ -394,7 +401,7 @@ export interface Config<CMSCallback = undefined, FormifyCallback = undefined, Do
|
|
|
394
401
|
token?: string | null;
|
|
395
402
|
ui?: {
|
|
396
403
|
/**
|
|
397
|
-
* When using
|
|
404
|
+
* When using TinaCloud's branching feature, provide the URL for your given branch
|
|
398
405
|
*
|
|
399
406
|
* Eg. If you're deplying to Vercel, and your repo name is 'my-app',
|
|
400
407
|
* Vercel's preview URL would be based on the branch:
|
|
@@ -521,7 +528,7 @@ export interface Config<CMSCallback = undefined, FormifyCallback = undefined, Do
|
|
|
521
528
|
} | {
|
|
522
529
|
searchClient?: never;
|
|
523
530
|
/**
|
|
524
|
-
* Use the
|
|
531
|
+
* Use the TinaCloud search index
|
|
525
532
|
*/
|
|
526
533
|
tina: {
|
|
527
534
|
/**
|
|
@@ -548,7 +555,7 @@ export interface Config<CMSCallback = undefined, FormifyCallback = undefined, Do
|
|
|
548
555
|
maxSearchIndexFieldLength?: number;
|
|
549
556
|
};
|
|
550
557
|
/**
|
|
551
|
-
* Used to override the default
|
|
558
|
+
* Used to override the default TinaCloud API URL
|
|
552
559
|
*
|
|
553
560
|
* [mostly for internal use only]
|
|
554
561
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tinacms/schema-tools",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-c965b5f-20250426163441",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"exports": {
|
|
@@ -25,14 +25,14 @@
|
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/jest": "^29.5.14",
|
|
27
27
|
"@types/micromatch": "^4.0.9",
|
|
28
|
-
"@types/react": "^18.3.
|
|
28
|
+
"@types/react": "^18.3.18",
|
|
29
29
|
"@types/yup": "^0.29.14",
|
|
30
30
|
"jest": "^29.7.0",
|
|
31
31
|
"react": "^18.3.1",
|
|
32
32
|
"ts-jest": "^29.2.5",
|
|
33
|
-
"typescript": "^5.
|
|
33
|
+
"typescript": "^5.7.3",
|
|
34
34
|
"yup": "^0.32.11",
|
|
35
|
-
"@tinacms/scripts": "
|
|
35
|
+
"@tinacms/scripts": "1.3.4"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"react": ">=16.14.0",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"picomatch-browser": "2.2.6",
|
|
50
50
|
"url-pattern": "^1.0.3",
|
|
51
|
-
"zod": "^3.
|
|
51
|
+
"zod": "^3.24.2"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "tinacms-scripts build",
|