@tinacms/schema-tools 0.0.0-d524599-20241115065930 → 0.0.0-d689189-20250526233934
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 +207 -181
- package/dist/index.mjs +207 -181
- package/dist/schema/TinaSchema.d.ts +21 -5
- package/dist/schema/addNamespaceToSchema.d.ts +8 -4
- package/dist/types/index.d.ts +14 -5
- package/dist/util/normalizePath.d.ts +8 -0
- package/dist/validate/fields.d.ts +0 -3
- package/dist/validate/schema.d.ts +36 -39
- package/dist/validate/util.d.ts +3 -0
- package/package.json +5 -5
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;
|
|
@@ -1662,6 +1646,9 @@ const parseURL = (url) => {
|
|
|
1662
1646
|
};
|
|
1663
1647
|
};
|
|
1664
1648
|
const normalizePath = (filepath) => filepath.replace(/\\/g, "/");
|
|
1649
|
+
const canonicalPath = (filepath) => {
|
|
1650
|
+
return normalizePath(filepath).split("/").filter((name2) => name2 !== "").join("/");
|
|
1651
|
+
};
|
|
1665
1652
|
class TinaSchema {
|
|
1666
1653
|
/**
|
|
1667
1654
|
* Create a schema class from a user defined schema object
|
|
@@ -1711,21 +1698,21 @@ class TinaSchema {
|
|
|
1711
1698
|
};
|
|
1712
1699
|
this.getCollectionByFullPath = (filepath) => {
|
|
1713
1700
|
const fileExtension = filepath.split(".").pop();
|
|
1714
|
-
const
|
|
1701
|
+
const canonicalFilepath = canonicalPath(filepath);
|
|
1715
1702
|
const possibleCollections = this.getCollections().filter((collection) => {
|
|
1716
1703
|
var _a, _b;
|
|
1717
|
-
if (!
|
|
1704
|
+
if (!canonicalFilepath.endsWith(`.gitkeep.${collection.format || "md"}`) && fileExtension !== (collection.format || "md")) {
|
|
1718
1705
|
return false;
|
|
1719
1706
|
}
|
|
1720
1707
|
if (((_a = collection == null ? void 0 : collection.match) == null ? void 0 : _a.include) || ((_b = collection == null ? void 0 : collection.match) == null ? void 0 : _b.exclude)) {
|
|
1721
1708
|
const matches = this.getMatches({ collection });
|
|
1722
|
-
const match = picomatch$1.isMatch(
|
|
1709
|
+
const match = picomatch$1.isMatch(canonicalFilepath, matches);
|
|
1723
1710
|
if (!match) {
|
|
1724
1711
|
return false;
|
|
1725
1712
|
}
|
|
1726
1713
|
}
|
|
1727
|
-
const
|
|
1728
|
-
return
|
|
1714
|
+
const collectionPath = canonicalPath(collection.path);
|
|
1715
|
+
return collectionPath === "" || canonicalFilepath.startsWith(`${collectionPath}/`);
|
|
1729
1716
|
});
|
|
1730
1717
|
if (possibleCollections.length === 0) {
|
|
1731
1718
|
throw new Error(`Unable to find collection for file at ${filepath}`);
|
|
@@ -1943,7 +1930,7 @@ class TinaSchema {
|
|
|
1943
1930
|
}
|
|
1944
1931
|
}
|
|
1945
1932
|
};
|
|
1946
|
-
this.
|
|
1933
|
+
this.legacyWalkFields = (cb) => {
|
|
1947
1934
|
const walk = (collectionOrObject, collection, path) => {
|
|
1948
1935
|
if (collectionOrObject.templates) {
|
|
1949
1936
|
collectionOrObject.templates.forEach((template) => {
|
|
@@ -1965,7 +1952,7 @@ class TinaSchema {
|
|
|
1965
1952
|
collections.forEach((collection) => walk(collection, collection, []));
|
|
1966
1953
|
};
|
|
1967
1954
|
this.schema = config;
|
|
1968
|
-
this.
|
|
1955
|
+
this.legacyWalkFields(({ field, collection }) => {
|
|
1969
1956
|
if (!("searchable" in field)) {
|
|
1970
1957
|
if (field.type === "image") {
|
|
1971
1958
|
field.searchable = false;
|
|
@@ -1986,20 +1973,67 @@ class TinaSchema {
|
|
|
1986
1973
|
field.uid = field.uid || false;
|
|
1987
1974
|
});
|
|
1988
1975
|
}
|
|
1989
|
-
|
|
1976
|
+
findReferencesFromCollection(name2) {
|
|
1990
1977
|
const result = {};
|
|
1991
1978
|
this.walkFields(({ field, collection: c, path }) => {
|
|
1979
|
+
if (c.name !== name2) {
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1992
1982
|
if (field.type === "reference") {
|
|
1993
|
-
|
|
1994
|
-
if (result[
|
|
1995
|
-
result[
|
|
1983
|
+
field.collections.forEach((name22) => {
|
|
1984
|
+
if (result[name22] === void 0) {
|
|
1985
|
+
result[name22] = [];
|
|
1996
1986
|
}
|
|
1997
|
-
result[
|
|
1998
|
-
}
|
|
1987
|
+
result[name22].push(path);
|
|
1988
|
+
});
|
|
1999
1989
|
}
|
|
2000
1990
|
});
|
|
2001
1991
|
return result;
|
|
2002
1992
|
}
|
|
1993
|
+
/**
|
|
1994
|
+
* Walk all fields in tina schema
|
|
1995
|
+
*
|
|
1996
|
+
* @param cb callback function invoked for each field
|
|
1997
|
+
*/
|
|
1998
|
+
walkFields(cb) {
|
|
1999
|
+
const walk = (collectionOrObject, collection, path = "$") => {
|
|
2000
|
+
if (collectionOrObject.templates) {
|
|
2001
|
+
collectionOrObject.templates.forEach((template) => {
|
|
2002
|
+
const templatePath = `${path}.${template.name}`;
|
|
2003
|
+
template.fields.forEach((field) => {
|
|
2004
|
+
const fieldPath = field.list ? `${templatePath}[*].${field.name}` : `${templatePath}.${field.name}`;
|
|
2005
|
+
cb({ field, collection, path: fieldPath });
|
|
2006
|
+
if (field.type === "object") {
|
|
2007
|
+
walk(field, collection, fieldPath);
|
|
2008
|
+
}
|
|
2009
|
+
});
|
|
2010
|
+
});
|
|
2011
|
+
}
|
|
2012
|
+
if (collectionOrObject.fields) {
|
|
2013
|
+
collectionOrObject.fields.forEach((field) => {
|
|
2014
|
+
const fieldPath = field.list ? `${path}.${field.name}[*]` : `${path}.${field.name}`;
|
|
2015
|
+
cb({ field, collection, path: fieldPath });
|
|
2016
|
+
if (field.type === "object" && field.fields) {
|
|
2017
|
+
walk(field, collection, fieldPath);
|
|
2018
|
+
} else if (field.templates) {
|
|
2019
|
+
field.templates.forEach((template) => {
|
|
2020
|
+
const templatePath = `${fieldPath}.${template.name}`;
|
|
2021
|
+
template.fields.forEach((field2) => {
|
|
2022
|
+
const fieldPath2 = field2.list ? `${templatePath}[*].${field2.name}` : `${templatePath}.${field2.name}`;
|
|
2023
|
+
cb({ field: field2, collection, path: fieldPath2 });
|
|
2024
|
+
if (field2.type === "object") {
|
|
2025
|
+
walk(field2, collection, fieldPath2);
|
|
2026
|
+
}
|
|
2027
|
+
});
|
|
2028
|
+
});
|
|
2029
|
+
}
|
|
2030
|
+
});
|
|
2031
|
+
}
|
|
2032
|
+
};
|
|
2033
|
+
this.getCollections().forEach((collection) => {
|
|
2034
|
+
walk(collection, collection);
|
|
2035
|
+
});
|
|
2036
|
+
}
|
|
2003
2037
|
/**
|
|
2004
2038
|
* This function returns an array of glob matches for a given collection.
|
|
2005
2039
|
*
|
|
@@ -2011,16 +2045,16 @@ class TinaSchema {
|
|
|
2011
2045
|
}) {
|
|
2012
2046
|
var _a, _b;
|
|
2013
2047
|
const collection = typeof collectionOrString === "string" ? this.getCollection(collectionOrString) : collectionOrString;
|
|
2014
|
-
const
|
|
2015
|
-
const pathSuffix =
|
|
2048
|
+
const collectionPath = canonicalPath(collection.path);
|
|
2049
|
+
const pathSuffix = collectionPath ? "/" : "";
|
|
2016
2050
|
const format = collection.format || "md";
|
|
2017
2051
|
const matches = [];
|
|
2018
2052
|
if ((_a = collection == null ? void 0 : collection.match) == null ? void 0 : _a.include) {
|
|
2019
|
-
const match = `${
|
|
2053
|
+
const match = `${collectionPath}${pathSuffix}${collection.match.include}.${format}`;
|
|
2020
2054
|
matches.push(match);
|
|
2021
2055
|
}
|
|
2022
2056
|
if ((_b = collection == null ? void 0 : collection.match) == null ? void 0 : _b.exclude) {
|
|
2023
|
-
const exclude = `!(${
|
|
2057
|
+
const exclude = `!(${collectionPath}${pathSuffix}${collection.match.exclude}.${format})`;
|
|
2024
2058
|
matches.push(exclude);
|
|
2025
2059
|
}
|
|
2026
2060
|
return matches;
|
|
@@ -2213,6 +2247,15 @@ const resolveForm = ({
|
|
|
2213
2247
|
})
|
|
2214
2248
|
};
|
|
2215
2249
|
};
|
|
2250
|
+
const CONTENT_FORMATS = [
|
|
2251
|
+
"mdx",
|
|
2252
|
+
"md",
|
|
2253
|
+
"markdown",
|
|
2254
|
+
"json",
|
|
2255
|
+
"yaml",
|
|
2256
|
+
"yml",
|
|
2257
|
+
"toml"
|
|
2258
|
+
];
|
|
2216
2259
|
const parseZodError = ({ zodError }) => {
|
|
2217
2260
|
var _a, _b, _c, _d;
|
|
2218
2261
|
const errors = zodError.flatten((issue) => {
|
|
@@ -2222,9 +2265,12 @@ const parseZodError = ({ zodError }) => {
|
|
|
2222
2265
|
moreInfo.push(parseZodError({ zodError: unionError }));
|
|
2223
2266
|
});
|
|
2224
2267
|
}
|
|
2225
|
-
const errorMessage =
|
|
2268
|
+
const errorMessage = `${issue == null ? void 0 : issue.message}
|
|
2269
|
+
Additional information:
|
|
2270
|
+
- Error found at path ${issue.path.join(
|
|
2226
2271
|
"."
|
|
2227
|
-
)}
|
|
2272
|
+
)}
|
|
2273
|
+
`;
|
|
2228
2274
|
const errorMessages = [errorMessage, ...moreInfo];
|
|
2229
2275
|
return {
|
|
2230
2276
|
errors: errorMessages
|
|
@@ -2259,6 +2305,9 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2259
2305
|
});
|
|
2260
2306
|
}
|
|
2261
2307
|
});
|
|
2308
|
+
const duplicateFieldErrorMessage = (fields) => `Fields must have unique names. Found duplicate field names: [${fields}]`;
|
|
2309
|
+
const duplicateTemplateErrorMessage = (templates) => `Templates must have unique names. Found duplicate template names: [${templates}]`;
|
|
2310
|
+
const duplicateCollectionErrorMessage = (collection) => `Collections must have unique names. Found duplicate collection names: [${collection}]`;
|
|
2262
2311
|
const TypeName = [
|
|
2263
2312
|
"string",
|
|
2264
2313
|
"boolean",
|
|
@@ -2269,10 +2318,11 @@ const TypeName = [
|
|
|
2269
2318
|
"reference",
|
|
2270
2319
|
"rich-text"
|
|
2271
2320
|
];
|
|
2272
|
-
const
|
|
2273
|
-
const
|
|
2274
|
-
|
|
2275
|
-
|
|
2321
|
+
const formattedTypes = ` - ${TypeName.join("\n - ")}`;
|
|
2322
|
+
const typeTypeError = `Invalid \`type\` property. \`type\` expected to be one of the following values:
|
|
2323
|
+
${formattedTypes}`;
|
|
2324
|
+
const typeRequiredError = `Missing \`type\` property. Please add a \`type\` property with one of the following:
|
|
2325
|
+
${formattedTypes}`;
|
|
2276
2326
|
const Option = z.union(
|
|
2277
2327
|
[
|
|
2278
2328
|
z.string(),
|
|
@@ -2358,7 +2408,7 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2358
2408
|
if (dups) {
|
|
2359
2409
|
ctx.addIssue({
|
|
2360
2410
|
code: z.ZodIssueCode.custom,
|
|
2361
|
-
message:
|
|
2411
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2362
2412
|
});
|
|
2363
2413
|
}
|
|
2364
2414
|
});
|
|
@@ -2368,21 +2418,21 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2368
2418
|
invalid_type_error: typeTypeError,
|
|
2369
2419
|
required_error: typeRequiredError
|
|
2370
2420
|
}),
|
|
2371
|
-
fields: z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2421
|
+
fields: z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2372
2422
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2373
2423
|
if (dups) {
|
|
2374
2424
|
ctx.addIssue({
|
|
2375
2425
|
code: z.ZodIssueCode.custom,
|
|
2376
|
-
message:
|
|
2426
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2377
2427
|
});
|
|
2378
2428
|
}
|
|
2379
2429
|
}),
|
|
2380
|
-
templates: z.array(TemplateTemp).min(1).optional().superRefine((val, ctx) => {
|
|
2430
|
+
templates: z.array(TemplateTemp).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2381
2431
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2382
2432
|
if (dups) {
|
|
2383
2433
|
ctx.addIssue({
|
|
2384
2434
|
code: z.ZodIssueCode.custom,
|
|
2385
|
-
message:
|
|
2435
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2386
2436
|
});
|
|
2387
2437
|
}
|
|
2388
2438
|
})
|
|
@@ -2397,7 +2447,7 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2397
2447
|
if (dups) {
|
|
2398
2448
|
ctx.addIssue({
|
|
2399
2449
|
code: z.ZodIssueCode.custom,
|
|
2400
|
-
message:
|
|
2450
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2401
2451
|
});
|
|
2402
2452
|
}
|
|
2403
2453
|
})
|
|
@@ -2417,10 +2467,17 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2417
2467
|
],
|
|
2418
2468
|
{
|
|
2419
2469
|
errorMap: (issue, ctx) => {
|
|
2420
|
-
var _a;
|
|
2470
|
+
var _a, _b;
|
|
2421
2471
|
if (issue.code === "invalid_union_discriminator") {
|
|
2472
|
+
if (!((_a = ctx.data) == null ? void 0 : _a.type)) {
|
|
2473
|
+
return {
|
|
2474
|
+
message: `Missing \`type\` property in field \`${ctx.data.name}\`. Please add a \`type\` property with one of the following:
|
|
2475
|
+
${formattedTypes}`
|
|
2476
|
+
};
|
|
2477
|
+
}
|
|
2422
2478
|
return {
|
|
2423
|
-
message: `Invalid \`type\` property. In the schema is 'type: ${(
|
|
2479
|
+
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:
|
|
2480
|
+
${formattedTypes}`
|
|
2424
2481
|
};
|
|
2425
2482
|
}
|
|
2426
2483
|
return {
|
|
@@ -2430,77 +2487,52 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2430
2487
|
}
|
|
2431
2488
|
).superRefine((val, ctx) => {
|
|
2432
2489
|
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
|
-
}
|
|
2490
|
+
const stringifiedField = JSON.stringify(val, null, 2);
|
|
2491
|
+
if (val.isTitle && val.list) {
|
|
2492
|
+
ctx.addIssue({
|
|
2493
|
+
code: z.ZodIssueCode.custom,
|
|
2494
|
+
message: `\`list: true\` is not allowed when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2495
|
+
${stringifiedField}`
|
|
2496
|
+
});
|
|
2458
2497
|
}
|
|
2459
|
-
if (val.
|
|
2498
|
+
if (val.isTitle && !val.required) {
|
|
2499
|
+
ctx.addIssue({
|
|
2500
|
+
code: z.ZodIssueCode.custom,
|
|
2501
|
+
message: `Property \`required: true\` is required when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2502
|
+
${stringifiedField}`
|
|
2503
|
+
});
|
|
2504
|
+
}
|
|
2505
|
+
if (val.uid && val.list) {
|
|
2460
2506
|
if (val.list) {
|
|
2461
2507
|
ctx.addIssue({
|
|
2462
2508
|
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
|
-
`
|
|
2509
|
+
message: `\`list: true\` is not allowed when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2510
|
+
${stringifiedField}`
|
|
2482
2511
|
});
|
|
2483
2512
|
}
|
|
2484
2513
|
}
|
|
2514
|
+
if (val.uid && !val.required) {
|
|
2515
|
+
ctx.addIssue({
|
|
2516
|
+
code: z.ZodIssueCode.custom,
|
|
2517
|
+
message: `Property \`required: true\` is required when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2518
|
+
${stringifiedField}`
|
|
2519
|
+
});
|
|
2520
|
+
}
|
|
2485
2521
|
}
|
|
2486
2522
|
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) {
|
|
2523
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2490
2524
|
ctx.addIssue({
|
|
2491
2525
|
code: z.ZodIssueCode.custom,
|
|
2492
|
-
message
|
|
2526
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2527
|
+
});
|
|
2528
|
+
return false;
|
|
2529
|
+
}
|
|
2530
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2531
|
+
ctx.addIssue({
|
|
2532
|
+
code: z.ZodIssueCode.custom,
|
|
2533
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2493
2534
|
});
|
|
2494
2535
|
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
2536
|
}
|
|
2505
2537
|
}
|
|
2506
2538
|
return true;
|
|
@@ -2533,19 +2565,10 @@ const validateTinaCloudSchemaConfig = (config) => {
|
|
|
2533
2565
|
const newConfig = tinaConfigZod.parse(config);
|
|
2534
2566
|
return newConfig;
|
|
2535
2567
|
};
|
|
2536
|
-
const FORMATS = [
|
|
2537
|
-
"json",
|
|
2538
|
-
"md",
|
|
2539
|
-
"markdown",
|
|
2540
|
-
"mdx",
|
|
2541
|
-
"toml",
|
|
2542
|
-
"yaml",
|
|
2543
|
-
"yml"
|
|
2544
|
-
];
|
|
2545
2568
|
const Template = z.object({
|
|
2546
2569
|
label: z.string({
|
|
2547
|
-
invalid_type_error: "label
|
|
2548
|
-
required_error: "label
|
|
2570
|
+
invalid_type_error: "Invalid data type for property `label`. Must be of type `string`",
|
|
2571
|
+
required_error: "Missing `label` property. Property `label` is required."
|
|
2549
2572
|
}),
|
|
2550
2573
|
name,
|
|
2551
2574
|
fields: z.array(TinaFieldZod)
|
|
@@ -2555,7 +2578,7 @@ const Template = z.object({
|
|
|
2555
2578
|
if (dups) {
|
|
2556
2579
|
ctx.addIssue({
|
|
2557
2580
|
code: z.ZodIssueCode.custom,
|
|
2558
|
-
message:
|
|
2581
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2559
2582
|
});
|
|
2560
2583
|
}
|
|
2561
2584
|
});
|
|
@@ -2565,7 +2588,7 @@ const CollectionBaseSchema = z.object({
|
|
|
2565
2588
|
if (val === "relativePath") {
|
|
2566
2589
|
ctx.addIssue({
|
|
2567
2590
|
code: z.ZodIssueCode.custom,
|
|
2568
|
-
message: `name cannot be 'relativePath'
|
|
2591
|
+
message: "Invalid `name` property. `name` cannot be 'relativePath' as it is a reserved field name."
|
|
2569
2592
|
});
|
|
2570
2593
|
}
|
|
2571
2594
|
}),
|
|
@@ -2573,72 +2596,73 @@ const CollectionBaseSchema = z.object({
|
|
|
2573
2596
|
if (val === ".") {
|
|
2574
2597
|
ctx.addIssue({
|
|
2575
2598
|
code: z.ZodIssueCode.custom,
|
|
2576
|
-
message: `path cannot be '.'. Please use '/' or '' instead.
|
|
2599
|
+
message: "Invalid `path` property. `path` cannot be '.'. Please use '/' or '' instead."
|
|
2577
2600
|
});
|
|
2578
2601
|
}
|
|
2579
2602
|
}),
|
|
2580
|
-
format: z.enum(
|
|
2603
|
+
format: z.enum(CONTENT_FORMATS).optional(),
|
|
2581
2604
|
isAuthCollection: z.boolean().optional(),
|
|
2582
2605
|
isDetached: z.boolean().optional()
|
|
2583
2606
|
});
|
|
2584
2607
|
const TinaCloudCollection = CollectionBaseSchema.extend({
|
|
2585
|
-
fields: z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2608
|
+
fields: z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2586
2609
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2587
2610
|
if (dups) {
|
|
2588
2611
|
ctx.addIssue({
|
|
2589
2612
|
code: z.ZodIssueCode.custom,
|
|
2590
|
-
message:
|
|
2613
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2591
2614
|
});
|
|
2592
2615
|
}
|
|
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"
|
|
2616
|
+
}).superRefine((val, ctx) => {
|
|
2617
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "string" && x.isTitle)) || [];
|
|
2618
|
+
if (arr.length > 1) {
|
|
2619
|
+
ctx.addIssue({
|
|
2620
|
+
code: z.ZodIssueCode.custom,
|
|
2621
|
+
message: `The following fields have the property \`isTitle\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`isTitle\`.`
|
|
2622
|
+
});
|
|
2619
2623
|
}
|
|
2620
|
-
),
|
|
2621
|
-
|
|
2624
|
+
}).superRefine((val, ctx) => {
|
|
2625
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
|
|
2626
|
+
if (arr.length > 2) {
|
|
2627
|
+
ctx.addIssue({
|
|
2628
|
+
code: z.ZodIssueCode.custom,
|
|
2629
|
+
message: `The following fields have the property \`uid\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`uid\`.`
|
|
2630
|
+
});
|
|
2631
|
+
}
|
|
2632
|
+
}).superRefine((val, ctx) => {
|
|
2633
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
|
|
2634
|
+
if (arr.length > 2) {
|
|
2635
|
+
ctx.addIssue({
|
|
2636
|
+
code: z.ZodIssueCode.custom,
|
|
2637
|
+
message: `The following fields have \`type: password\`: [${arr.map((field) => field.name).join(", ")}]. Only one can be of \`type: password\`.`
|
|
2638
|
+
});
|
|
2639
|
+
}
|
|
2640
|
+
}),
|
|
2641
|
+
templates: z.array(Template).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2622
2642
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2623
2643
|
if (dups) {
|
|
2624
2644
|
ctx.addIssue({
|
|
2625
2645
|
code: z.ZodIssueCode.custom,
|
|
2626
|
-
message:
|
|
2646
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2627
2647
|
});
|
|
2628
2648
|
}
|
|
2629
2649
|
})
|
|
2630
|
-
}).
|
|
2631
|
-
(val)
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
}
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2650
|
+
}).superRefine((val, ctx) => {
|
|
2651
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2652
|
+
ctx.addIssue({
|
|
2653
|
+
code: z.ZodIssueCode.custom,
|
|
2654
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2655
|
+
});
|
|
2656
|
+
return false;
|
|
2657
|
+
}
|
|
2658
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2659
|
+
ctx.addIssue({
|
|
2660
|
+
code: z.ZodIssueCode.custom,
|
|
2661
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2662
|
+
});
|
|
2663
|
+
return false;
|
|
2664
|
+
}
|
|
2665
|
+
});
|
|
2642
2666
|
const TinaCloudSchemaZod = z.object({
|
|
2643
2667
|
collections: z.array(TinaCloudCollection),
|
|
2644
2668
|
config: tinaConfigZod.optional()
|
|
@@ -2648,14 +2672,14 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2648
2672
|
if (dups) {
|
|
2649
2673
|
ctx.addIssue({
|
|
2650
2674
|
code: z.ZodIssueCode.custom,
|
|
2651
|
-
message:
|
|
2675
|
+
message: duplicateCollectionErrorMessage(dups),
|
|
2652
2676
|
fatal: true
|
|
2653
2677
|
});
|
|
2654
2678
|
}
|
|
2655
2679
|
if (((_b = val.collections) == null ? void 0 : _b.filter((x) => x.isAuthCollection).length) > 1) {
|
|
2656
2680
|
ctx.addIssue({
|
|
2657
2681
|
code: z.ZodIssueCode.custom,
|
|
2658
|
-
message:
|
|
2682
|
+
message: "Only one collection can be marked as `isAuthCollection`.",
|
|
2659
2683
|
fatal: true
|
|
2660
2684
|
});
|
|
2661
2685
|
}
|
|
@@ -2663,7 +2687,7 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2663
2687
|
if (media && media.tina && media.loadCustomStore) {
|
|
2664
2688
|
ctx.addIssue({
|
|
2665
2689
|
code: z.ZodIssueCode.custom,
|
|
2666
|
-
message: "
|
|
2690
|
+
message: "Cannot have both `loadCustomStore` and `tina`. Must use one or the other.",
|
|
2667
2691
|
fatal: true,
|
|
2668
2692
|
path: ["config", "media"]
|
|
2669
2693
|
});
|
|
@@ -2672,7 +2696,7 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2672
2696
|
if (search && search.tina && search.searchClient) {
|
|
2673
2697
|
ctx.addIssue({
|
|
2674
2698
|
code: z.ZodIssueCode.custom,
|
|
2675
|
-
message: "
|
|
2699
|
+
message: "Cannot have both `searchClient` and `tina`. Must use one or the other.",
|
|
2676
2700
|
fatal: true,
|
|
2677
2701
|
path: ["config", "search"]
|
|
2678
2702
|
});
|
|
@@ -2690,17 +2714,19 @@ const validateSchema = ({ schema }) => {
|
|
|
2690
2714
|
} catch (e) {
|
|
2691
2715
|
if (e instanceof ZodError) {
|
|
2692
2716
|
const errors = parseZodError({ zodError: e });
|
|
2693
|
-
throw new TinaSchemaValidationError(errors.join("
|
|
2717
|
+
throw new TinaSchemaValidationError(errors.join("\n"));
|
|
2694
2718
|
}
|
|
2695
2719
|
throw new Error(e);
|
|
2696
2720
|
}
|
|
2697
2721
|
};
|
|
2698
2722
|
export {
|
|
2723
|
+
CONTENT_FORMATS,
|
|
2699
2724
|
NAMER,
|
|
2700
2725
|
TINA_HOST,
|
|
2701
2726
|
TinaSchema,
|
|
2702
2727
|
TinaSchemaValidationError,
|
|
2703
2728
|
addNamespaceToSchema,
|
|
2729
|
+
canonicalPath,
|
|
2704
2730
|
normalizePath,
|
|
2705
2731
|
parseURL,
|
|
2706
2732
|
resolveField,
|