@tinacms/schema-tools 0.0.0-ecea7ac-20241011043815 → 0.0.0-ed6025e-20251201040055
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 +234 -176
- package/dist/index.mjs +234 -176
- package/dist/schema/TinaSchema.d.ts +21 -1
- package/dist/schema/addNamespaceToSchema.d.ts +8 -4
- package/dist/types/index.d.ts +73 -25
- package/dist/util/normalizePath.d.ts +8 -0
- package/dist/validate/fields.d.ts +0 -3
- package/dist/validate/schema.d.ts +101 -39
- package/dist/validate/tinaCloudSchemaConfig.d.ts +37 -0
- package/dist/validate/util.d.ts +3 -0
- package/package.json +8 -9
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,6 +1973,67 @@ class TinaSchema {
|
|
|
1986
1973
|
field.uid = field.uid || false;
|
|
1987
1974
|
});
|
|
1988
1975
|
}
|
|
1976
|
+
findReferencesFromCollection(name2) {
|
|
1977
|
+
const result = {};
|
|
1978
|
+
this.walkFields(({ field, collection: c, path }) => {
|
|
1979
|
+
if (c.name !== name2) {
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
if (field.type === "reference") {
|
|
1983
|
+
field.collections.forEach((name22) => {
|
|
1984
|
+
if (result[name22] === void 0) {
|
|
1985
|
+
result[name22] = [];
|
|
1986
|
+
}
|
|
1987
|
+
result[name22].push(path);
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1990
|
+
});
|
|
1991
|
+
return result;
|
|
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
|
+
}
|
|
1989
2037
|
/**
|
|
1990
2038
|
* This function returns an array of glob matches for a given collection.
|
|
1991
2039
|
*
|
|
@@ -1997,16 +2045,16 @@ class TinaSchema {
|
|
|
1997
2045
|
}) {
|
|
1998
2046
|
var _a, _b;
|
|
1999
2047
|
const collection = typeof collectionOrString === "string" ? this.getCollection(collectionOrString) : collectionOrString;
|
|
2000
|
-
const
|
|
2001
|
-
const pathSuffix =
|
|
2048
|
+
const collectionPath = canonicalPath(collection.path);
|
|
2049
|
+
const pathSuffix = collectionPath ? "/" : "";
|
|
2002
2050
|
const format = collection.format || "md";
|
|
2003
2051
|
const matches = [];
|
|
2004
2052
|
if ((_a = collection == null ? void 0 : collection.match) == null ? void 0 : _a.include) {
|
|
2005
|
-
const match = `${
|
|
2053
|
+
const match = `${collectionPath}${pathSuffix}${collection.match.include}.${format}`;
|
|
2006
2054
|
matches.push(match);
|
|
2007
2055
|
}
|
|
2008
2056
|
if ((_b = collection == null ? void 0 : collection.match) == null ? void 0 : _b.exclude) {
|
|
2009
|
-
const exclude = `!(${
|
|
2057
|
+
const exclude = `!(${collectionPath}${pathSuffix}${collection.match.exclude}.${format})`;
|
|
2010
2058
|
matches.push(exclude);
|
|
2011
2059
|
}
|
|
2012
2060
|
return matches;
|
|
@@ -2199,6 +2247,15 @@ const resolveForm = ({
|
|
|
2199
2247
|
})
|
|
2200
2248
|
};
|
|
2201
2249
|
};
|
|
2250
|
+
const CONTENT_FORMATS = [
|
|
2251
|
+
"mdx",
|
|
2252
|
+
"md",
|
|
2253
|
+
"markdown",
|
|
2254
|
+
"json",
|
|
2255
|
+
"yaml",
|
|
2256
|
+
"yml",
|
|
2257
|
+
"toml"
|
|
2258
|
+
];
|
|
2202
2259
|
const parseZodError = ({ zodError }) => {
|
|
2203
2260
|
var _a, _b, _c, _d;
|
|
2204
2261
|
const errors = zodError.flatten((issue) => {
|
|
@@ -2208,9 +2265,12 @@ const parseZodError = ({ zodError }) => {
|
|
|
2208
2265
|
moreInfo.push(parseZodError({ zodError: unionError }));
|
|
2209
2266
|
});
|
|
2210
2267
|
}
|
|
2211
|
-
const errorMessage =
|
|
2268
|
+
const errorMessage = `${issue == null ? void 0 : issue.message}
|
|
2269
|
+
Additional information:
|
|
2270
|
+
- Error found at path ${issue.path.join(
|
|
2212
2271
|
"."
|
|
2213
|
-
)}
|
|
2272
|
+
)}
|
|
2273
|
+
`;
|
|
2214
2274
|
const errorMessages = [errorMessage, ...moreInfo];
|
|
2215
2275
|
return {
|
|
2216
2276
|
errors: errorMessages
|
|
@@ -2245,6 +2305,9 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2245
2305
|
});
|
|
2246
2306
|
}
|
|
2247
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}]`;
|
|
2248
2311
|
const TypeName = [
|
|
2249
2312
|
"string",
|
|
2250
2313
|
"boolean",
|
|
@@ -2255,10 +2318,11 @@ const TypeName = [
|
|
|
2255
2318
|
"reference",
|
|
2256
2319
|
"rich-text"
|
|
2257
2320
|
];
|
|
2258
|
-
const
|
|
2259
|
-
const
|
|
2260
|
-
|
|
2261
|
-
|
|
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}`;
|
|
2262
2326
|
const Option = z.union(
|
|
2263
2327
|
[
|
|
2264
2328
|
z.string(),
|
|
@@ -2313,7 +2377,8 @@ const ImageField = TinaScalerBase.extend({
|
|
|
2313
2377
|
type: z.literal("image", {
|
|
2314
2378
|
invalid_type_error: typeTypeError,
|
|
2315
2379
|
required_error: typeRequiredError
|
|
2316
|
-
})
|
|
2380
|
+
}),
|
|
2381
|
+
uploadDir: z.function().args(z.any()).returns(z.string()).optional()
|
|
2317
2382
|
});
|
|
2318
2383
|
const DateTimeField = TinaScalerBase.extend({
|
|
2319
2384
|
type: z.literal("datetime", {
|
|
@@ -2344,7 +2409,7 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2344
2409
|
if (dups) {
|
|
2345
2410
|
ctx.addIssue({
|
|
2346
2411
|
code: z.ZodIssueCode.custom,
|
|
2347
|
-
message:
|
|
2412
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2348
2413
|
});
|
|
2349
2414
|
}
|
|
2350
2415
|
});
|
|
@@ -2354,21 +2419,21 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2354
2419
|
invalid_type_error: typeTypeError,
|
|
2355
2420
|
required_error: typeRequiredError
|
|
2356
2421
|
}),
|
|
2357
|
-
fields: z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2422
|
+
fields: z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2358
2423
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2359
2424
|
if (dups) {
|
|
2360
2425
|
ctx.addIssue({
|
|
2361
2426
|
code: z.ZodIssueCode.custom,
|
|
2362
|
-
message:
|
|
2427
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2363
2428
|
});
|
|
2364
2429
|
}
|
|
2365
2430
|
}),
|
|
2366
|
-
templates: z.array(TemplateTemp).min(1).optional().superRefine((val, ctx) => {
|
|
2431
|
+
templates: z.array(TemplateTemp).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2367
2432
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2368
2433
|
if (dups) {
|
|
2369
2434
|
ctx.addIssue({
|
|
2370
2435
|
code: z.ZodIssueCode.custom,
|
|
2371
|
-
message:
|
|
2436
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2372
2437
|
});
|
|
2373
2438
|
}
|
|
2374
2439
|
})
|
|
@@ -2383,7 +2448,7 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2383
2448
|
if (dups) {
|
|
2384
2449
|
ctx.addIssue({
|
|
2385
2450
|
code: z.ZodIssueCode.custom,
|
|
2386
|
-
message:
|
|
2451
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2387
2452
|
});
|
|
2388
2453
|
}
|
|
2389
2454
|
})
|
|
@@ -2403,10 +2468,17 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2403
2468
|
],
|
|
2404
2469
|
{
|
|
2405
2470
|
errorMap: (issue, ctx) => {
|
|
2406
|
-
var _a;
|
|
2471
|
+
var _a, _b;
|
|
2407
2472
|
if (issue.code === "invalid_union_discriminator") {
|
|
2473
|
+
if (!((_a = ctx.data) == null ? void 0 : _a.type)) {
|
|
2474
|
+
return {
|
|
2475
|
+
message: `Missing \`type\` property in field \`${ctx.data.name}\`. Please add a \`type\` property with one of the following:
|
|
2476
|
+
${formattedTypes}`
|
|
2477
|
+
};
|
|
2478
|
+
}
|
|
2408
2479
|
return {
|
|
2409
|
-
message: `Invalid \`type\` property. In the schema is 'type: ${(
|
|
2480
|
+
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:
|
|
2481
|
+
${formattedTypes}`
|
|
2410
2482
|
};
|
|
2411
2483
|
}
|
|
2412
2484
|
return {
|
|
@@ -2416,77 +2488,52 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2416
2488
|
}
|
|
2417
2489
|
).superRefine((val, ctx) => {
|
|
2418
2490
|
if (val.type === "string") {
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
${
|
|
2425
|
-
|
|
2426
|
-
null,
|
|
2427
|
-
2
|
|
2428
|
-
)}
|
|
2429
|
-
`
|
|
2430
|
-
});
|
|
2431
|
-
}
|
|
2432
|
-
if (!val.required) {
|
|
2433
|
-
ctx.addIssue({
|
|
2434
|
-
code: z.ZodIssueCode.custom,
|
|
2435
|
-
message: `Must have { required: true } when using \`isTitle\` Error in value
|
|
2436
|
-
${JSON.stringify(
|
|
2437
|
-
val,
|
|
2438
|
-
null,
|
|
2439
|
-
2
|
|
2440
|
-
)}
|
|
2441
|
-
`
|
|
2442
|
-
});
|
|
2443
|
-
}
|
|
2491
|
+
const stringifiedField = JSON.stringify(val, null, 2);
|
|
2492
|
+
if (val.isTitle && val.list) {
|
|
2493
|
+
ctx.addIssue({
|
|
2494
|
+
code: z.ZodIssueCode.custom,
|
|
2495
|
+
message: `\`list: true\` is not allowed when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2496
|
+
${stringifiedField}`
|
|
2497
|
+
});
|
|
2444
2498
|
}
|
|
2445
|
-
if (val.
|
|
2499
|
+
if (val.isTitle && !val.required) {
|
|
2500
|
+
ctx.addIssue({
|
|
2501
|
+
code: z.ZodIssueCode.custom,
|
|
2502
|
+
message: `Property \`required: true\` is required when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2503
|
+
${stringifiedField}`
|
|
2504
|
+
});
|
|
2505
|
+
}
|
|
2506
|
+
if (val.uid && val.list) {
|
|
2446
2507
|
if (val.list) {
|
|
2447
2508
|
ctx.addIssue({
|
|
2448
2509
|
code: z.ZodIssueCode.custom,
|
|
2449
|
-
message:
|
|
2450
|
-
${
|
|
2451
|
-
val,
|
|
2452
|
-
null,
|
|
2453
|
-
2
|
|
2454
|
-
)}
|
|
2455
|
-
`
|
|
2456
|
-
});
|
|
2457
|
-
}
|
|
2458
|
-
if (!val.required) {
|
|
2459
|
-
ctx.addIssue({
|
|
2460
|
-
code: z.ZodIssueCode.custom,
|
|
2461
|
-
message: `Must have { required: true } when using \`uid\` Error in value
|
|
2462
|
-
${JSON.stringify(
|
|
2463
|
-
val,
|
|
2464
|
-
null,
|
|
2465
|
-
2
|
|
2466
|
-
)}
|
|
2467
|
-
`
|
|
2510
|
+
message: `\`list: true\` is not allowed when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2511
|
+
${stringifiedField}`
|
|
2468
2512
|
});
|
|
2469
2513
|
}
|
|
2470
2514
|
}
|
|
2515
|
+
if (val.uid && !val.required) {
|
|
2516
|
+
ctx.addIssue({
|
|
2517
|
+
code: z.ZodIssueCode.custom,
|
|
2518
|
+
message: `Property \`required: true\` is required when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2519
|
+
${stringifiedField}`
|
|
2520
|
+
});
|
|
2521
|
+
}
|
|
2471
2522
|
}
|
|
2472
2523
|
if (val.type === "object") {
|
|
2473
|
-
|
|
2474
|
-
let isValid = Boolean(val == null ? void 0 : val.templates) || Boolean(val == null ? void 0 : val.fields);
|
|
2475
|
-
if (!isValid) {
|
|
2524
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2476
2525
|
ctx.addIssue({
|
|
2477
2526
|
code: z.ZodIssueCode.custom,
|
|
2478
|
-
message
|
|
2527
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2528
|
+
});
|
|
2529
|
+
return false;
|
|
2530
|
+
}
|
|
2531
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2532
|
+
ctx.addIssue({
|
|
2533
|
+
code: z.ZodIssueCode.custom,
|
|
2534
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2479
2535
|
});
|
|
2480
2536
|
return false;
|
|
2481
|
-
} else {
|
|
2482
|
-
isValid = !((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields));
|
|
2483
|
-
if (!isValid) {
|
|
2484
|
-
ctx.addIssue({
|
|
2485
|
-
code: z.ZodIssueCode.custom,
|
|
2486
|
-
message
|
|
2487
|
-
});
|
|
2488
|
-
}
|
|
2489
|
-
return isValid;
|
|
2490
2537
|
}
|
|
2491
2538
|
}
|
|
2492
2539
|
return true;
|
|
@@ -2513,25 +2560,33 @@ const tinaConfigZod = z$1.object({
|
|
|
2513
2560
|
searchClient: z$1.any().optional(),
|
|
2514
2561
|
indexBatchSize: z$1.number().gte(1).optional(),
|
|
2515
2562
|
maxSearchIndexFieldLength: z$1.number().gte(1).optional()
|
|
2563
|
+
}).optional(),
|
|
2564
|
+
ui: z$1.object({
|
|
2565
|
+
previewUrl: z$1.function().optional(),
|
|
2566
|
+
optOutOfUpdateCheck: z$1.boolean().optional(),
|
|
2567
|
+
regexValidation: z$1.object({
|
|
2568
|
+
folderNameRegex: z$1.string().refine(
|
|
2569
|
+
(val) => {
|
|
2570
|
+
try {
|
|
2571
|
+
new RegExp(val);
|
|
2572
|
+
return true;
|
|
2573
|
+
} catch (error) {
|
|
2574
|
+
return false;
|
|
2575
|
+
}
|
|
2576
|
+
},
|
|
2577
|
+
{ message: "folderNameRegex is not a valid regex pattern" }
|
|
2578
|
+
).optional()
|
|
2579
|
+
}).optional()
|
|
2516
2580
|
}).optional()
|
|
2517
2581
|
});
|
|
2518
2582
|
const validateTinaCloudSchemaConfig = (config) => {
|
|
2519
2583
|
const newConfig = tinaConfigZod.parse(config);
|
|
2520
2584
|
return newConfig;
|
|
2521
2585
|
};
|
|
2522
|
-
const FORMATS = [
|
|
2523
|
-
"json",
|
|
2524
|
-
"md",
|
|
2525
|
-
"markdown",
|
|
2526
|
-
"mdx",
|
|
2527
|
-
"toml",
|
|
2528
|
-
"yaml",
|
|
2529
|
-
"yml"
|
|
2530
|
-
];
|
|
2531
2586
|
const Template = z.object({
|
|
2532
2587
|
label: z.string({
|
|
2533
|
-
invalid_type_error: "label
|
|
2534
|
-
required_error: "label
|
|
2588
|
+
invalid_type_error: "Invalid data type for property `label`. Must be of type `string`",
|
|
2589
|
+
required_error: "Missing `label` property. Property `label` is required."
|
|
2535
2590
|
}),
|
|
2536
2591
|
name,
|
|
2537
2592
|
fields: z.array(TinaFieldZod)
|
|
@@ -2541,7 +2596,7 @@ const Template = z.object({
|
|
|
2541
2596
|
if (dups) {
|
|
2542
2597
|
ctx.addIssue({
|
|
2543
2598
|
code: z.ZodIssueCode.custom,
|
|
2544
|
-
message:
|
|
2599
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2545
2600
|
});
|
|
2546
2601
|
}
|
|
2547
2602
|
});
|
|
@@ -2551,7 +2606,7 @@ const CollectionBaseSchema = z.object({
|
|
|
2551
2606
|
if (val === "relativePath") {
|
|
2552
2607
|
ctx.addIssue({
|
|
2553
2608
|
code: z.ZodIssueCode.custom,
|
|
2554
|
-
message: `name cannot be 'relativePath'
|
|
2609
|
+
message: "Invalid `name` property. `name` cannot be 'relativePath' as it is a reserved field name."
|
|
2555
2610
|
});
|
|
2556
2611
|
}
|
|
2557
2612
|
}),
|
|
@@ -2559,72 +2614,73 @@ const CollectionBaseSchema = z.object({
|
|
|
2559
2614
|
if (val === ".") {
|
|
2560
2615
|
ctx.addIssue({
|
|
2561
2616
|
code: z.ZodIssueCode.custom,
|
|
2562
|
-
message: `path cannot be '.'. Please use '/' or '' instead.
|
|
2617
|
+
message: "Invalid `path` property. `path` cannot be '.'. Please use '/' or '' instead."
|
|
2563
2618
|
});
|
|
2564
2619
|
}
|
|
2565
2620
|
}),
|
|
2566
|
-
format: z.enum(
|
|
2621
|
+
format: z.enum(CONTENT_FORMATS).optional(),
|
|
2567
2622
|
isAuthCollection: z.boolean().optional(),
|
|
2568
2623
|
isDetached: z.boolean().optional()
|
|
2569
2624
|
});
|
|
2570
2625
|
const TinaCloudCollection = CollectionBaseSchema.extend({
|
|
2571
|
-
fields: z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2626
|
+
fields: z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2572
2627
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2573
2628
|
if (dups) {
|
|
2574
2629
|
ctx.addIssue({
|
|
2575
2630
|
code: z.ZodIssueCode.custom,
|
|
2576
|
-
message:
|
|
2631
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2577
2632
|
});
|
|
2578
2633
|
}
|
|
2579
|
-
}).
|
|
2580
|
-
|
|
2581
|
-
(
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
{
|
|
2595
|
-
message: "Fields can only have one use of `uid`"
|
|
2596
|
-
}
|
|
2597
|
-
).refine(
|
|
2598
|
-
// It is valid if it is 0 or 1
|
|
2599
|
-
(val) => {
|
|
2600
|
-
const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
|
|
2601
|
-
return arr.length < 2;
|
|
2602
|
-
},
|
|
2603
|
-
{
|
|
2604
|
-
message: "Fields can only have one use of `password` type"
|
|
2634
|
+
}).superRefine((val, ctx) => {
|
|
2635
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "string" && x.isTitle)) || [];
|
|
2636
|
+
if (arr.length > 1) {
|
|
2637
|
+
ctx.addIssue({
|
|
2638
|
+
code: z.ZodIssueCode.custom,
|
|
2639
|
+
message: `The following fields have the property \`isTitle\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`isTitle\`.`
|
|
2640
|
+
});
|
|
2641
|
+
}
|
|
2642
|
+
}).superRefine((val, ctx) => {
|
|
2643
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
|
|
2644
|
+
if (arr.length > 2) {
|
|
2645
|
+
ctx.addIssue({
|
|
2646
|
+
code: z.ZodIssueCode.custom,
|
|
2647
|
+
message: `The following fields have the property \`uid\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`uid\`.`
|
|
2648
|
+
});
|
|
2605
2649
|
}
|
|
2606
|
-
),
|
|
2607
|
-
|
|
2650
|
+
}).superRefine((val, ctx) => {
|
|
2651
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
|
|
2652
|
+
if (arr.length > 2) {
|
|
2653
|
+
ctx.addIssue({
|
|
2654
|
+
code: z.ZodIssueCode.custom,
|
|
2655
|
+
message: `The following fields have \`type: password\`: [${arr.map((field) => field.name).join(", ")}]. Only one can be of \`type: password\`.`
|
|
2656
|
+
});
|
|
2657
|
+
}
|
|
2658
|
+
}),
|
|
2659
|
+
templates: z.array(Template).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2608
2660
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2609
2661
|
if (dups) {
|
|
2610
2662
|
ctx.addIssue({
|
|
2611
2663
|
code: z.ZodIssueCode.custom,
|
|
2612
|
-
message:
|
|
2664
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2613
2665
|
});
|
|
2614
2666
|
}
|
|
2615
2667
|
})
|
|
2616
|
-
}).
|
|
2617
|
-
(val)
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
}
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2668
|
+
}).superRefine((val, ctx) => {
|
|
2669
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2670
|
+
ctx.addIssue({
|
|
2671
|
+
code: z.ZodIssueCode.custom,
|
|
2672
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2673
|
+
});
|
|
2674
|
+
return false;
|
|
2675
|
+
}
|
|
2676
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2677
|
+
ctx.addIssue({
|
|
2678
|
+
code: z.ZodIssueCode.custom,
|
|
2679
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2680
|
+
});
|
|
2681
|
+
return false;
|
|
2682
|
+
}
|
|
2683
|
+
});
|
|
2628
2684
|
const TinaCloudSchemaZod = z.object({
|
|
2629
2685
|
collections: z.array(TinaCloudCollection),
|
|
2630
2686
|
config: tinaConfigZod.optional()
|
|
@@ -2634,14 +2690,14 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2634
2690
|
if (dups) {
|
|
2635
2691
|
ctx.addIssue({
|
|
2636
2692
|
code: z.ZodIssueCode.custom,
|
|
2637
|
-
message:
|
|
2693
|
+
message: duplicateCollectionErrorMessage(dups),
|
|
2638
2694
|
fatal: true
|
|
2639
2695
|
});
|
|
2640
2696
|
}
|
|
2641
2697
|
if (((_b = val.collections) == null ? void 0 : _b.filter((x) => x.isAuthCollection).length) > 1) {
|
|
2642
2698
|
ctx.addIssue({
|
|
2643
2699
|
code: z.ZodIssueCode.custom,
|
|
2644
|
-
message:
|
|
2700
|
+
message: "Only one collection can be marked as `isAuthCollection`.",
|
|
2645
2701
|
fatal: true
|
|
2646
2702
|
});
|
|
2647
2703
|
}
|
|
@@ -2649,7 +2705,7 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2649
2705
|
if (media && media.tina && media.loadCustomStore) {
|
|
2650
2706
|
ctx.addIssue({
|
|
2651
2707
|
code: z.ZodIssueCode.custom,
|
|
2652
|
-
message: "
|
|
2708
|
+
message: "Cannot have both `loadCustomStore` and `tina`. Must use one or the other.",
|
|
2653
2709
|
fatal: true,
|
|
2654
2710
|
path: ["config", "media"]
|
|
2655
2711
|
});
|
|
@@ -2658,7 +2714,7 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2658
2714
|
if (search && search.tina && search.searchClient) {
|
|
2659
2715
|
ctx.addIssue({
|
|
2660
2716
|
code: z.ZodIssueCode.custom,
|
|
2661
|
-
message: "
|
|
2717
|
+
message: "Cannot have both `searchClient` and `tina`. Must use one or the other.",
|
|
2662
2718
|
fatal: true,
|
|
2663
2719
|
path: ["config", "search"]
|
|
2664
2720
|
});
|
|
@@ -2676,17 +2732,19 @@ const validateSchema = ({ schema }) => {
|
|
|
2676
2732
|
} catch (e) {
|
|
2677
2733
|
if (e instanceof ZodError) {
|
|
2678
2734
|
const errors = parseZodError({ zodError: e });
|
|
2679
|
-
throw new TinaSchemaValidationError(errors.join("
|
|
2735
|
+
throw new TinaSchemaValidationError(errors.join("\n"));
|
|
2680
2736
|
}
|
|
2681
2737
|
throw new Error(e);
|
|
2682
2738
|
}
|
|
2683
2739
|
};
|
|
2684
2740
|
export {
|
|
2741
|
+
CONTENT_FORMATS,
|
|
2685
2742
|
NAMER,
|
|
2686
2743
|
TINA_HOST,
|
|
2687
2744
|
TinaSchema,
|
|
2688
2745
|
TinaSchemaValidationError,
|
|
2689
2746
|
addNamespaceToSchema,
|
|
2747
|
+
canonicalPath,
|
|
2690
2748
|
normalizePath,
|
|
2691
2749
|
parseURL,
|
|
2692
2750
|
resolveField,
|