@tinacms/schema-tools 0.0.0-d69e892-20241003042309 → 0.0.0-d9672bc-20250218033222
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 +174 -176
- package/dist/index.mjs +174 -176
- package/dist/schema/TinaSchema.d.ts +8 -6
- package/dist/schema/addNamespaceToSchema.d.ts +8 -4
- package/dist/types/index.d.ts +9 -2
- 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.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,29 +1945,8 @@
|
|
|
1961
1945
|
}
|
|
1962
1946
|
}
|
|
1963
1947
|
};
|
|
1964
|
-
this.walkFields = (cb) => {
|
|
1965
|
-
const walk = (collectionOrObject, collection, path) => {
|
|
1966
|
-
if (collectionOrObject.templates) {
|
|
1967
|
-
collectionOrObject.templates.forEach((template) => {
|
|
1968
|
-
template.fields.forEach((field) => {
|
|
1969
|
-
cb({ field, collection, path: [...path, template.name] });
|
|
1970
|
-
});
|
|
1971
|
-
});
|
|
1972
|
-
}
|
|
1973
|
-
if (collectionOrObject.fields) {
|
|
1974
|
-
collectionOrObject.fields.forEach((field) => {
|
|
1975
|
-
cb({ field, collection, path: [...path, field.name] });
|
|
1976
|
-
if (field.type === "rich-text" || field.type === "object") {
|
|
1977
|
-
walk(field, collection, [...path, field.name]);
|
|
1978
|
-
}
|
|
1979
|
-
});
|
|
1980
|
-
}
|
|
1981
|
-
};
|
|
1982
|
-
const collections = this.getCollections();
|
|
1983
|
-
collections.forEach((collection) => walk(collection, collection, []));
|
|
1984
|
-
};
|
|
1985
1948
|
this.schema = config;
|
|
1986
|
-
this.walkFields(({ field, collection
|
|
1949
|
+
this.walkFields(({ field, collection }) => {
|
|
1987
1950
|
if (!("searchable" in field)) {
|
|
1988
1951
|
if (field.type === "image") {
|
|
1989
1952
|
field.searchable = false;
|
|
@@ -2004,6 +1967,51 @@
|
|
|
2004
1967
|
field.uid = field.uid || false;
|
|
2005
1968
|
});
|
|
2006
1969
|
}
|
|
1970
|
+
findReferencesFromCollection(name2) {
|
|
1971
|
+
const result = {};
|
|
1972
|
+
this.walkFields(({ field, collection: c, path }) => {
|
|
1973
|
+
if (c.name !== name2) {
|
|
1974
|
+
return;
|
|
1975
|
+
}
|
|
1976
|
+
if (field.type === "reference") {
|
|
1977
|
+
field.collections.forEach((name22) => {
|
|
1978
|
+
if (result[name22] === void 0) {
|
|
1979
|
+
result[name22] = [];
|
|
1980
|
+
}
|
|
1981
|
+
result[name22].push(path);
|
|
1982
|
+
});
|
|
1983
|
+
}
|
|
1984
|
+
});
|
|
1985
|
+
return result;
|
|
1986
|
+
}
|
|
1987
|
+
walkFields(cb) {
|
|
1988
|
+
const walk = (collectionOrObject, collection, path = "$") => {
|
|
1989
|
+
if (collectionOrObject.templates) {
|
|
1990
|
+
collectionOrObject.templates.forEach((template) => {
|
|
1991
|
+
const templatePath = `${path}.${template.name}`;
|
|
1992
|
+
template.fields.forEach((field) => {
|
|
1993
|
+
const fieldPath = field.list ? `${templatePath}[*].${field.name}` : `${templatePath}.${field.name}`;
|
|
1994
|
+
cb({ field, collection, path: fieldPath });
|
|
1995
|
+
if (field.type === "object") {
|
|
1996
|
+
walk(field, collection, fieldPath);
|
|
1997
|
+
}
|
|
1998
|
+
});
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
2001
|
+
if (collectionOrObject.fields) {
|
|
2002
|
+
collectionOrObject.fields.forEach((field) => {
|
|
2003
|
+
const fieldPath = field.list ? `${path}.${field.name}[*]` : `${path}.${field.name}`;
|
|
2004
|
+
cb({ field, collection, path: fieldPath });
|
|
2005
|
+
if (field.type === "object" && field.fields) {
|
|
2006
|
+
walk(field, collection, fieldPath);
|
|
2007
|
+
}
|
|
2008
|
+
});
|
|
2009
|
+
}
|
|
2010
|
+
};
|
|
2011
|
+
this.getCollections().forEach((collection) => {
|
|
2012
|
+
walk(collection, collection);
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
2007
2015
|
/**
|
|
2008
2016
|
* This function returns an array of glob matches for a given collection.
|
|
2009
2017
|
*
|
|
@@ -2226,9 +2234,12 @@
|
|
|
2226
2234
|
moreInfo.push(parseZodError({ zodError: unionError }));
|
|
2227
2235
|
});
|
|
2228
2236
|
}
|
|
2229
|
-
const errorMessage =
|
|
2237
|
+
const errorMessage = `${issue == null ? void 0 : issue.message}
|
|
2238
|
+
Additional information:
|
|
2239
|
+
- Error found at path ${issue.path.join(
|
|
2230
2240
|
"."
|
|
2231
|
-
)}
|
|
2241
|
+
)}
|
|
2242
|
+
`;
|
|
2232
2243
|
const errorMessages = [errorMessage, ...moreInfo];
|
|
2233
2244
|
return {
|
|
2234
2245
|
errors: errorMessages
|
|
@@ -2263,6 +2274,9 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2263
2274
|
});
|
|
2264
2275
|
}
|
|
2265
2276
|
});
|
|
2277
|
+
const duplicateFieldErrorMessage = (fields) => `Fields must have unique names. Found duplicate field names: [${fields}]`;
|
|
2278
|
+
const duplicateTemplateErrorMessage = (templates) => `Templates must have unique names. Found duplicate template names: [${templates}]`;
|
|
2279
|
+
const duplicateCollectionErrorMessage = (collection) => `Collections must have unique names. Found duplicate collection names: [${collection}]`;
|
|
2266
2280
|
const TypeName = [
|
|
2267
2281
|
"string",
|
|
2268
2282
|
"boolean",
|
|
@@ -2273,10 +2287,11 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2273
2287
|
"reference",
|
|
2274
2288
|
"rich-text"
|
|
2275
2289
|
];
|
|
2276
|
-
const
|
|
2277
|
-
const
|
|
2278
|
-
|
|
2279
|
-
|
|
2290
|
+
const formattedTypes = ` - ${TypeName.join("\n - ")}`;
|
|
2291
|
+
const typeTypeError = `Invalid \`type\` property. \`type\` expected to be one of the following values:
|
|
2292
|
+
${formattedTypes}`;
|
|
2293
|
+
const typeRequiredError = `Missing \`type\` property. Please add a \`type\` property with one of the following:
|
|
2294
|
+
${formattedTypes}`;
|
|
2280
2295
|
const Option = z.z.union(
|
|
2281
2296
|
[
|
|
2282
2297
|
z.z.string(),
|
|
@@ -2362,7 +2377,7 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2362
2377
|
if (dups) {
|
|
2363
2378
|
ctx.addIssue({
|
|
2364
2379
|
code: z.z.ZodIssueCode.custom,
|
|
2365
|
-
message:
|
|
2380
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2366
2381
|
});
|
|
2367
2382
|
}
|
|
2368
2383
|
});
|
|
@@ -2372,21 +2387,21 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2372
2387
|
invalid_type_error: typeTypeError,
|
|
2373
2388
|
required_error: typeRequiredError
|
|
2374
2389
|
}),
|
|
2375
|
-
fields: z.z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2390
|
+
fields: z.z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2376
2391
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2377
2392
|
if (dups) {
|
|
2378
2393
|
ctx.addIssue({
|
|
2379
2394
|
code: z.z.ZodIssueCode.custom,
|
|
2380
|
-
message:
|
|
2395
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2381
2396
|
});
|
|
2382
2397
|
}
|
|
2383
2398
|
}),
|
|
2384
|
-
templates: z.z.array(TemplateTemp).min(1).optional().superRefine((val, ctx) => {
|
|
2399
|
+
templates: z.z.array(TemplateTemp).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2385
2400
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2386
2401
|
if (dups) {
|
|
2387
2402
|
ctx.addIssue({
|
|
2388
2403
|
code: z.z.ZodIssueCode.custom,
|
|
2389
|
-
message:
|
|
2404
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2390
2405
|
});
|
|
2391
2406
|
}
|
|
2392
2407
|
})
|
|
@@ -2401,7 +2416,7 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2401
2416
|
if (dups) {
|
|
2402
2417
|
ctx.addIssue({
|
|
2403
2418
|
code: z.z.ZodIssueCode.custom,
|
|
2404
|
-
message:
|
|
2419
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2405
2420
|
});
|
|
2406
2421
|
}
|
|
2407
2422
|
})
|
|
@@ -2421,10 +2436,17 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2421
2436
|
],
|
|
2422
2437
|
{
|
|
2423
2438
|
errorMap: (issue, ctx) => {
|
|
2424
|
-
var _a;
|
|
2439
|
+
var _a, _b;
|
|
2425
2440
|
if (issue.code === "invalid_union_discriminator") {
|
|
2441
|
+
if (!((_a = ctx.data) == null ? void 0 : _a.type)) {
|
|
2442
|
+
return {
|
|
2443
|
+
message: `Missing \`type\` property in field \`${ctx.data.name}\`. Please add a \`type\` property with one of the following:
|
|
2444
|
+
${formattedTypes}`
|
|
2445
|
+
};
|
|
2446
|
+
}
|
|
2426
2447
|
return {
|
|
2427
|
-
message: `Invalid \`type\` property. In the schema is 'type: ${(
|
|
2448
|
+
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:
|
|
2449
|
+
${formattedTypes}`
|
|
2428
2450
|
};
|
|
2429
2451
|
}
|
|
2430
2452
|
return {
|
|
@@ -2434,77 +2456,52 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2434
2456
|
}
|
|
2435
2457
|
).superRefine((val, ctx) => {
|
|
2436
2458
|
if (val.type === "string") {
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
${
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
ctx.addIssue({
|
|
2452
|
-
code: z.z.ZodIssueCode.custom,
|
|
2453
|
-
message: `Must have { required: true } when using \`isTitle\` Error in value
|
|
2454
|
-
${JSON.stringify(
|
|
2455
|
-
val,
|
|
2456
|
-
null,
|
|
2457
|
-
2
|
|
2458
|
-
)}
|
|
2459
|
-
`
|
|
2460
|
-
});
|
|
2461
|
-
}
|
|
2459
|
+
const stringifiedField = JSON.stringify(val, null, 2);
|
|
2460
|
+
if (val.isTitle && val.list) {
|
|
2461
|
+
ctx.addIssue({
|
|
2462
|
+
code: z.z.ZodIssueCode.custom,
|
|
2463
|
+
message: `\`list: true\` is not allowed when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2464
|
+
${stringifiedField}`
|
|
2465
|
+
});
|
|
2466
|
+
}
|
|
2467
|
+
if (val.isTitle && !val.required) {
|
|
2468
|
+
ctx.addIssue({
|
|
2469
|
+
code: z.z.ZodIssueCode.custom,
|
|
2470
|
+
message: `Property \`required: true\` is required when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2471
|
+
${stringifiedField}`
|
|
2472
|
+
});
|
|
2462
2473
|
}
|
|
2463
|
-
if (val.uid) {
|
|
2474
|
+
if (val.uid && val.list) {
|
|
2464
2475
|
if (val.list) {
|
|
2465
2476
|
ctx.addIssue({
|
|
2466
2477
|
code: z.z.ZodIssueCode.custom,
|
|
2467
|
-
message:
|
|
2468
|
-
${
|
|
2469
|
-
val,
|
|
2470
|
-
null,
|
|
2471
|
-
2
|
|
2472
|
-
)}
|
|
2473
|
-
`
|
|
2474
|
-
});
|
|
2475
|
-
}
|
|
2476
|
-
if (!val.required) {
|
|
2477
|
-
ctx.addIssue({
|
|
2478
|
-
code: z.z.ZodIssueCode.custom,
|
|
2479
|
-
message: `Must have { required: true } when using \`uid\` Error in value
|
|
2480
|
-
${JSON.stringify(
|
|
2481
|
-
val,
|
|
2482
|
-
null,
|
|
2483
|
-
2
|
|
2484
|
-
)}
|
|
2485
|
-
`
|
|
2478
|
+
message: `\`list: true\` is not allowed when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2479
|
+
${stringifiedField}`
|
|
2486
2480
|
});
|
|
2487
2481
|
}
|
|
2488
2482
|
}
|
|
2483
|
+
if (val.uid && !val.required) {
|
|
2484
|
+
ctx.addIssue({
|
|
2485
|
+
code: z.z.ZodIssueCode.custom,
|
|
2486
|
+
message: `Property \`required: true\` is required when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2487
|
+
${stringifiedField}`
|
|
2488
|
+
});
|
|
2489
|
+
}
|
|
2489
2490
|
}
|
|
2490
2491
|
if (val.type === "object") {
|
|
2491
|
-
|
|
2492
|
-
let isValid = Boolean(val == null ? void 0 : val.templates) || Boolean(val == null ? void 0 : val.fields);
|
|
2493
|
-
if (!isValid) {
|
|
2492
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2494
2493
|
ctx.addIssue({
|
|
2495
2494
|
code: z.z.ZodIssueCode.custom,
|
|
2496
|
-
message
|
|
2495
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2496
|
+
});
|
|
2497
|
+
return false;
|
|
2498
|
+
}
|
|
2499
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2500
|
+
ctx.addIssue({
|
|
2501
|
+
code: z.z.ZodIssueCode.custom,
|
|
2502
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2497
2503
|
});
|
|
2498
2504
|
return false;
|
|
2499
|
-
} else {
|
|
2500
|
-
isValid = !((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields));
|
|
2501
|
-
if (!isValid) {
|
|
2502
|
-
ctx.addIssue({
|
|
2503
|
-
code: z.z.ZodIssueCode.custom,
|
|
2504
|
-
message
|
|
2505
|
-
});
|
|
2506
|
-
}
|
|
2507
|
-
return isValid;
|
|
2508
2505
|
}
|
|
2509
2506
|
}
|
|
2510
2507
|
return true;
|
|
@@ -2548,8 +2545,8 @@ ${JSON.stringify(
|
|
|
2548
2545
|
];
|
|
2549
2546
|
const Template = z.z.object({
|
|
2550
2547
|
label: z.z.string({
|
|
2551
|
-
invalid_type_error: "label
|
|
2552
|
-
required_error: "label
|
|
2548
|
+
invalid_type_error: "Invalid data type for property `label`. Must be of type `string`",
|
|
2549
|
+
required_error: "Missing `label` property. Property `label` is required."
|
|
2553
2550
|
}),
|
|
2554
2551
|
name,
|
|
2555
2552
|
fields: z.z.array(TinaFieldZod)
|
|
@@ -2559,7 +2556,7 @@ ${JSON.stringify(
|
|
|
2559
2556
|
if (dups) {
|
|
2560
2557
|
ctx.addIssue({
|
|
2561
2558
|
code: z.z.ZodIssueCode.custom,
|
|
2562
|
-
message:
|
|
2559
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2563
2560
|
});
|
|
2564
2561
|
}
|
|
2565
2562
|
});
|
|
@@ -2569,7 +2566,7 @@ ${JSON.stringify(
|
|
|
2569
2566
|
if (val === "relativePath") {
|
|
2570
2567
|
ctx.addIssue({
|
|
2571
2568
|
code: z.z.ZodIssueCode.custom,
|
|
2572
|
-
message: `name cannot be 'relativePath'
|
|
2569
|
+
message: "Invalid `name` property. `name` cannot be 'relativePath' as it is a reserved field name."
|
|
2573
2570
|
});
|
|
2574
2571
|
}
|
|
2575
2572
|
}),
|
|
@@ -2577,7 +2574,7 @@ ${JSON.stringify(
|
|
|
2577
2574
|
if (val === ".") {
|
|
2578
2575
|
ctx.addIssue({
|
|
2579
2576
|
code: z.z.ZodIssueCode.custom,
|
|
2580
|
-
message: `path cannot be '.'. Please use '/' or '' instead.
|
|
2577
|
+
message: "Invalid `path` property. `path` cannot be '.'. Please use '/' or '' instead."
|
|
2581
2578
|
});
|
|
2582
2579
|
}
|
|
2583
2580
|
}),
|
|
@@ -2586,63 +2583,64 @@ ${JSON.stringify(
|
|
|
2586
2583
|
isDetached: z.z.boolean().optional()
|
|
2587
2584
|
});
|
|
2588
2585
|
const TinaCloudCollection = CollectionBaseSchema.extend({
|
|
2589
|
-
fields: z.z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2586
|
+
fields: z.z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2590
2587
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2591
2588
|
if (dups) {
|
|
2592
2589
|
ctx.addIssue({
|
|
2593
2590
|
code: z.z.ZodIssueCode.custom,
|
|
2594
|
-
message:
|
|
2591
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2595
2592
|
});
|
|
2596
2593
|
}
|
|
2597
|
-
}).
|
|
2598
|
-
|
|
2599
|
-
(
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
message: "Fields can only have one use of `isTitle`"
|
|
2605
|
-
}
|
|
2606
|
-
).refine(
|
|
2607
|
-
// It is valid if it is 0 or 1
|
|
2608
|
-
(val) => {
|
|
2609
|
-
const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
|
|
2610
|
-
return arr.length < 2;
|
|
2611
|
-
},
|
|
2612
|
-
{
|
|
2613
|
-
message: "Fields can only have one use of `uid`"
|
|
2614
|
-
}
|
|
2615
|
-
).refine(
|
|
2616
|
-
// It is valid if it is 0 or 1
|
|
2617
|
-
(val) => {
|
|
2618
|
-
const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
|
|
2619
|
-
return arr.length < 2;
|
|
2620
|
-
},
|
|
2621
|
-
{
|
|
2622
|
-
message: "Fields can only have one use of `password` type"
|
|
2594
|
+
}).superRefine((val, ctx) => {
|
|
2595
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "string" && x.isTitle)) || [];
|
|
2596
|
+
if (arr.length > 1) {
|
|
2597
|
+
ctx.addIssue({
|
|
2598
|
+
code: z.z.ZodIssueCode.custom,
|
|
2599
|
+
message: `The following fields have the property \`isTitle\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`isTitle\`.`
|
|
2600
|
+
});
|
|
2623
2601
|
}
|
|
2624
|
-
),
|
|
2625
|
-
|
|
2602
|
+
}).superRefine((val, ctx) => {
|
|
2603
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
|
|
2604
|
+
if (arr.length > 2) {
|
|
2605
|
+
ctx.addIssue({
|
|
2606
|
+
code: z.z.ZodIssueCode.custom,
|
|
2607
|
+
message: `The following fields have the property \`uid\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`uid\`.`
|
|
2608
|
+
});
|
|
2609
|
+
}
|
|
2610
|
+
}).superRefine((val, ctx) => {
|
|
2611
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
|
|
2612
|
+
if (arr.length > 2) {
|
|
2613
|
+
ctx.addIssue({
|
|
2614
|
+
code: z.z.ZodIssueCode.custom,
|
|
2615
|
+
message: `The following fields have \`type: password\`: [${arr.map((field) => field.name).join(", ")}]. Only one can be of \`type: password\`.`
|
|
2616
|
+
});
|
|
2617
|
+
}
|
|
2618
|
+
}),
|
|
2619
|
+
templates: z.z.array(Template).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2626
2620
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2627
2621
|
if (dups) {
|
|
2628
2622
|
ctx.addIssue({
|
|
2629
2623
|
code: z.z.ZodIssueCode.custom,
|
|
2630
|
-
message:
|
|
2624
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2631
2625
|
});
|
|
2632
2626
|
}
|
|
2633
2627
|
})
|
|
2634
|
-
}).
|
|
2635
|
-
(val)
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
}
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2628
|
+
}).superRefine((val, ctx) => {
|
|
2629
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2630
|
+
ctx.addIssue({
|
|
2631
|
+
code: z.z.ZodIssueCode.custom,
|
|
2632
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2633
|
+
});
|
|
2634
|
+
return false;
|
|
2635
|
+
}
|
|
2636
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2637
|
+
ctx.addIssue({
|
|
2638
|
+
code: z.z.ZodIssueCode.custom,
|
|
2639
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2640
|
+
});
|
|
2641
|
+
return false;
|
|
2642
|
+
}
|
|
2643
|
+
});
|
|
2646
2644
|
const TinaCloudSchemaZod = z.z.object({
|
|
2647
2645
|
collections: z.z.array(TinaCloudCollection),
|
|
2648
2646
|
config: tinaConfigZod.optional()
|
|
@@ -2652,14 +2650,14 @@ ${JSON.stringify(
|
|
|
2652
2650
|
if (dups) {
|
|
2653
2651
|
ctx.addIssue({
|
|
2654
2652
|
code: z.z.ZodIssueCode.custom,
|
|
2655
|
-
message:
|
|
2653
|
+
message: duplicateCollectionErrorMessage(dups),
|
|
2656
2654
|
fatal: true
|
|
2657
2655
|
});
|
|
2658
2656
|
}
|
|
2659
2657
|
if (((_b = val.collections) == null ? void 0 : _b.filter((x) => x.isAuthCollection).length) > 1) {
|
|
2660
2658
|
ctx.addIssue({
|
|
2661
2659
|
code: z.z.ZodIssueCode.custom,
|
|
2662
|
-
message:
|
|
2660
|
+
message: "Only one collection can be marked as `isAuthCollection`.",
|
|
2663
2661
|
fatal: true
|
|
2664
2662
|
});
|
|
2665
2663
|
}
|
|
@@ -2667,7 +2665,7 @@ ${JSON.stringify(
|
|
|
2667
2665
|
if (media && media.tina && media.loadCustomStore) {
|
|
2668
2666
|
ctx.addIssue({
|
|
2669
2667
|
code: z.z.ZodIssueCode.custom,
|
|
2670
|
-
message: "
|
|
2668
|
+
message: "Cannot have both `loadCustomStore` and `tina`. Must use one or the other.",
|
|
2671
2669
|
fatal: true,
|
|
2672
2670
|
path: ["config", "media"]
|
|
2673
2671
|
});
|
|
@@ -2676,7 +2674,7 @@ ${JSON.stringify(
|
|
|
2676
2674
|
if (search && search.tina && search.searchClient) {
|
|
2677
2675
|
ctx.addIssue({
|
|
2678
2676
|
code: z.z.ZodIssueCode.custom,
|
|
2679
|
-
message: "
|
|
2677
|
+
message: "Cannot have both `searchClient` and `tina`. Must use one or the other.",
|
|
2680
2678
|
fatal: true,
|
|
2681
2679
|
path: ["config", "search"]
|
|
2682
2680
|
});
|
|
@@ -2694,7 +2692,7 @@ ${JSON.stringify(
|
|
|
2694
2692
|
} catch (e) {
|
|
2695
2693
|
if (e instanceof z.ZodError) {
|
|
2696
2694
|
const errors = parseZodError({ zodError: e });
|
|
2697
|
-
throw new TinaSchemaValidationError(errors.join("
|
|
2695
|
+
throw new TinaSchemaValidationError(errors.join("\n"));
|
|
2698
2696
|
}
|
|
2699
2697
|
throw new Error(e);
|
|
2700
2698
|
}
|
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,29 +1927,8 @@ class TinaSchema {
|
|
|
1943
1927
|
}
|
|
1944
1928
|
}
|
|
1945
1929
|
};
|
|
1946
|
-
this.walkFields = (cb) => {
|
|
1947
|
-
const walk = (collectionOrObject, collection, path) => {
|
|
1948
|
-
if (collectionOrObject.templates) {
|
|
1949
|
-
collectionOrObject.templates.forEach((template) => {
|
|
1950
|
-
template.fields.forEach((field) => {
|
|
1951
|
-
cb({ field, collection, path: [...path, template.name] });
|
|
1952
|
-
});
|
|
1953
|
-
});
|
|
1954
|
-
}
|
|
1955
|
-
if (collectionOrObject.fields) {
|
|
1956
|
-
collectionOrObject.fields.forEach((field) => {
|
|
1957
|
-
cb({ field, collection, path: [...path, field.name] });
|
|
1958
|
-
if (field.type === "rich-text" || field.type === "object") {
|
|
1959
|
-
walk(field, collection, [...path, field.name]);
|
|
1960
|
-
}
|
|
1961
|
-
});
|
|
1962
|
-
}
|
|
1963
|
-
};
|
|
1964
|
-
const collections = this.getCollections();
|
|
1965
|
-
collections.forEach((collection) => walk(collection, collection, []));
|
|
1966
|
-
};
|
|
1967
1930
|
this.schema = config;
|
|
1968
|
-
this.walkFields(({ field, collection
|
|
1931
|
+
this.walkFields(({ field, collection }) => {
|
|
1969
1932
|
if (!("searchable" in field)) {
|
|
1970
1933
|
if (field.type === "image") {
|
|
1971
1934
|
field.searchable = false;
|
|
@@ -1986,6 +1949,51 @@ class TinaSchema {
|
|
|
1986
1949
|
field.uid = field.uid || false;
|
|
1987
1950
|
});
|
|
1988
1951
|
}
|
|
1952
|
+
findReferencesFromCollection(name2) {
|
|
1953
|
+
const result = {};
|
|
1954
|
+
this.walkFields(({ field, collection: c, path }) => {
|
|
1955
|
+
if (c.name !== name2) {
|
|
1956
|
+
return;
|
|
1957
|
+
}
|
|
1958
|
+
if (field.type === "reference") {
|
|
1959
|
+
field.collections.forEach((name22) => {
|
|
1960
|
+
if (result[name22] === void 0) {
|
|
1961
|
+
result[name22] = [];
|
|
1962
|
+
}
|
|
1963
|
+
result[name22].push(path);
|
|
1964
|
+
});
|
|
1965
|
+
}
|
|
1966
|
+
});
|
|
1967
|
+
return result;
|
|
1968
|
+
}
|
|
1969
|
+
walkFields(cb) {
|
|
1970
|
+
const walk = (collectionOrObject, collection, path = "$") => {
|
|
1971
|
+
if (collectionOrObject.templates) {
|
|
1972
|
+
collectionOrObject.templates.forEach((template) => {
|
|
1973
|
+
const templatePath = `${path}.${template.name}`;
|
|
1974
|
+
template.fields.forEach((field) => {
|
|
1975
|
+
const fieldPath = field.list ? `${templatePath}[*].${field.name}` : `${templatePath}.${field.name}`;
|
|
1976
|
+
cb({ field, collection, path: fieldPath });
|
|
1977
|
+
if (field.type === "object") {
|
|
1978
|
+
walk(field, collection, fieldPath);
|
|
1979
|
+
}
|
|
1980
|
+
});
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1983
|
+
if (collectionOrObject.fields) {
|
|
1984
|
+
collectionOrObject.fields.forEach((field) => {
|
|
1985
|
+
const fieldPath = field.list ? `${path}.${field.name}[*]` : `${path}.${field.name}`;
|
|
1986
|
+
cb({ field, collection, path: fieldPath });
|
|
1987
|
+
if (field.type === "object" && field.fields) {
|
|
1988
|
+
walk(field, collection, fieldPath);
|
|
1989
|
+
}
|
|
1990
|
+
});
|
|
1991
|
+
}
|
|
1992
|
+
};
|
|
1993
|
+
this.getCollections().forEach((collection) => {
|
|
1994
|
+
walk(collection, collection);
|
|
1995
|
+
});
|
|
1996
|
+
}
|
|
1989
1997
|
/**
|
|
1990
1998
|
* This function returns an array of glob matches for a given collection.
|
|
1991
1999
|
*
|
|
@@ -2208,9 +2216,12 @@ const parseZodError = ({ zodError }) => {
|
|
|
2208
2216
|
moreInfo.push(parseZodError({ zodError: unionError }));
|
|
2209
2217
|
});
|
|
2210
2218
|
}
|
|
2211
|
-
const errorMessage =
|
|
2219
|
+
const errorMessage = `${issue == null ? void 0 : issue.message}
|
|
2220
|
+
Additional information:
|
|
2221
|
+
- Error found at path ${issue.path.join(
|
|
2212
2222
|
"."
|
|
2213
|
-
)}
|
|
2223
|
+
)}
|
|
2224
|
+
`;
|
|
2214
2225
|
const errorMessages = [errorMessage, ...moreInfo];
|
|
2215
2226
|
return {
|
|
2216
2227
|
errors: errorMessages
|
|
@@ -2245,6 +2256,9 @@ If you need to use this value in your content you can use the \`nameOverride\` p
|
|
|
2245
2256
|
});
|
|
2246
2257
|
}
|
|
2247
2258
|
});
|
|
2259
|
+
const duplicateFieldErrorMessage = (fields) => `Fields must have unique names. Found duplicate field names: [${fields}]`;
|
|
2260
|
+
const duplicateTemplateErrorMessage = (templates) => `Templates must have unique names. Found duplicate template names: [${templates}]`;
|
|
2261
|
+
const duplicateCollectionErrorMessage = (collection) => `Collections must have unique names. Found duplicate collection names: [${collection}]`;
|
|
2248
2262
|
const TypeName = [
|
|
2249
2263
|
"string",
|
|
2250
2264
|
"boolean",
|
|
@@ -2255,10 +2269,11 @@ const TypeName = [
|
|
|
2255
2269
|
"reference",
|
|
2256
2270
|
"rich-text"
|
|
2257
2271
|
];
|
|
2258
|
-
const
|
|
2259
|
-
const
|
|
2260
|
-
|
|
2261
|
-
|
|
2272
|
+
const formattedTypes = ` - ${TypeName.join("\n - ")}`;
|
|
2273
|
+
const typeTypeError = `Invalid \`type\` property. \`type\` expected to be one of the following values:
|
|
2274
|
+
${formattedTypes}`;
|
|
2275
|
+
const typeRequiredError = `Missing \`type\` property. Please add a \`type\` property with one of the following:
|
|
2276
|
+
${formattedTypes}`;
|
|
2262
2277
|
const Option = z.union(
|
|
2263
2278
|
[
|
|
2264
2279
|
z.string(),
|
|
@@ -2344,7 +2359,7 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2344
2359
|
if (dups) {
|
|
2345
2360
|
ctx.addIssue({
|
|
2346
2361
|
code: z.ZodIssueCode.custom,
|
|
2347
|
-
message:
|
|
2362
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2348
2363
|
});
|
|
2349
2364
|
}
|
|
2350
2365
|
});
|
|
@@ -2354,21 +2369,21 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2354
2369
|
invalid_type_error: typeTypeError,
|
|
2355
2370
|
required_error: typeRequiredError
|
|
2356
2371
|
}),
|
|
2357
|
-
fields: z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2372
|
+
fields: z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2358
2373
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2359
2374
|
if (dups) {
|
|
2360
2375
|
ctx.addIssue({
|
|
2361
2376
|
code: z.ZodIssueCode.custom,
|
|
2362
|
-
message:
|
|
2377
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2363
2378
|
});
|
|
2364
2379
|
}
|
|
2365
2380
|
}),
|
|
2366
|
-
templates: z.array(TemplateTemp).min(1).optional().superRefine((val, ctx) => {
|
|
2381
|
+
templates: z.array(TemplateTemp).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2367
2382
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2368
2383
|
if (dups) {
|
|
2369
2384
|
ctx.addIssue({
|
|
2370
2385
|
code: z.ZodIssueCode.custom,
|
|
2371
|
-
message:
|
|
2386
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2372
2387
|
});
|
|
2373
2388
|
}
|
|
2374
2389
|
})
|
|
@@ -2383,7 +2398,7 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2383
2398
|
if (dups) {
|
|
2384
2399
|
ctx.addIssue({
|
|
2385
2400
|
code: z.ZodIssueCode.custom,
|
|
2386
|
-
message:
|
|
2401
|
+
message: duplicateTemplateErrorMessage(dups)
|
|
2387
2402
|
});
|
|
2388
2403
|
}
|
|
2389
2404
|
})
|
|
@@ -2403,10 +2418,17 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2403
2418
|
],
|
|
2404
2419
|
{
|
|
2405
2420
|
errorMap: (issue, ctx) => {
|
|
2406
|
-
var _a;
|
|
2421
|
+
var _a, _b;
|
|
2407
2422
|
if (issue.code === "invalid_union_discriminator") {
|
|
2423
|
+
if (!((_a = ctx.data) == null ? void 0 : _a.type)) {
|
|
2424
|
+
return {
|
|
2425
|
+
message: `Missing \`type\` property in field \`${ctx.data.name}\`. Please add a \`type\` property with one of the following:
|
|
2426
|
+
${formattedTypes}`
|
|
2427
|
+
};
|
|
2428
|
+
}
|
|
2408
2429
|
return {
|
|
2409
|
-
message: `Invalid \`type\` property. In the schema is 'type: ${(
|
|
2430
|
+
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:
|
|
2431
|
+
${formattedTypes}`
|
|
2410
2432
|
};
|
|
2411
2433
|
}
|
|
2412
2434
|
return {
|
|
@@ -2416,77 +2438,52 @@ const TinaFieldZod = z.lazy(() => {
|
|
|
2416
2438
|
}
|
|
2417
2439
|
).superRefine((val, ctx) => {
|
|
2418
2440
|
if (val.type === "string") {
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
${
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
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
|
-
}
|
|
2441
|
+
const stringifiedField = JSON.stringify(val, null, 2);
|
|
2442
|
+
if (val.isTitle && val.list) {
|
|
2443
|
+
ctx.addIssue({
|
|
2444
|
+
code: z.ZodIssueCode.custom,
|
|
2445
|
+
message: `\`list: true\` is not allowed when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2446
|
+
${stringifiedField}`
|
|
2447
|
+
});
|
|
2448
|
+
}
|
|
2449
|
+
if (val.isTitle && !val.required) {
|
|
2450
|
+
ctx.addIssue({
|
|
2451
|
+
code: z.ZodIssueCode.custom,
|
|
2452
|
+
message: `Property \`required: true\` is required when using \`isTitle\` for fields of \`type: string\`. Error found in field:
|
|
2453
|
+
${stringifiedField}`
|
|
2454
|
+
});
|
|
2444
2455
|
}
|
|
2445
|
-
if (val.uid) {
|
|
2456
|
+
if (val.uid && val.list) {
|
|
2446
2457
|
if (val.list) {
|
|
2447
2458
|
ctx.addIssue({
|
|
2448
2459
|
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
|
-
`
|
|
2460
|
+
message: `\`list: true\` is not allowed when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2461
|
+
${stringifiedField}`
|
|
2468
2462
|
});
|
|
2469
2463
|
}
|
|
2470
2464
|
}
|
|
2465
|
+
if (val.uid && !val.required) {
|
|
2466
|
+
ctx.addIssue({
|
|
2467
|
+
code: z.ZodIssueCode.custom,
|
|
2468
|
+
message: `Property \`required: true\` is required when using \`uid\` for fields of \`type: string\`. Error found in field:
|
|
2469
|
+
${stringifiedField}`
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
2471
2472
|
}
|
|
2472
2473
|
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) {
|
|
2474
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2476
2475
|
ctx.addIssue({
|
|
2477
2476
|
code: z.ZodIssueCode.custom,
|
|
2478
|
-
message
|
|
2477
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2478
|
+
});
|
|
2479
|
+
return false;
|
|
2480
|
+
}
|
|
2481
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2482
|
+
ctx.addIssue({
|
|
2483
|
+
code: z.ZodIssueCode.custom,
|
|
2484
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2479
2485
|
});
|
|
2480
2486
|
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
2487
|
}
|
|
2491
2488
|
}
|
|
2492
2489
|
return true;
|
|
@@ -2530,8 +2527,8 @@ const FORMATS = [
|
|
|
2530
2527
|
];
|
|
2531
2528
|
const Template = z.object({
|
|
2532
2529
|
label: z.string({
|
|
2533
|
-
invalid_type_error: "label
|
|
2534
|
-
required_error: "label
|
|
2530
|
+
invalid_type_error: "Invalid data type for property `label`. Must be of type `string`",
|
|
2531
|
+
required_error: "Missing `label` property. Property `label` is required."
|
|
2535
2532
|
}),
|
|
2536
2533
|
name,
|
|
2537
2534
|
fields: z.array(TinaFieldZod)
|
|
@@ -2541,7 +2538,7 @@ const Template = z.object({
|
|
|
2541
2538
|
if (dups) {
|
|
2542
2539
|
ctx.addIssue({
|
|
2543
2540
|
code: z.ZodIssueCode.custom,
|
|
2544
|
-
message:
|
|
2541
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2545
2542
|
});
|
|
2546
2543
|
}
|
|
2547
2544
|
});
|
|
@@ -2551,7 +2548,7 @@ const CollectionBaseSchema = z.object({
|
|
|
2551
2548
|
if (val === "relativePath") {
|
|
2552
2549
|
ctx.addIssue({
|
|
2553
2550
|
code: z.ZodIssueCode.custom,
|
|
2554
|
-
message: `name cannot be 'relativePath'
|
|
2551
|
+
message: "Invalid `name` property. `name` cannot be 'relativePath' as it is a reserved field name."
|
|
2555
2552
|
});
|
|
2556
2553
|
}
|
|
2557
2554
|
}),
|
|
@@ -2559,7 +2556,7 @@ const CollectionBaseSchema = z.object({
|
|
|
2559
2556
|
if (val === ".") {
|
|
2560
2557
|
ctx.addIssue({
|
|
2561
2558
|
code: z.ZodIssueCode.custom,
|
|
2562
|
-
message: `path cannot be '.'. Please use '/' or '' instead.
|
|
2559
|
+
message: "Invalid `path` property. `path` cannot be '.'. Please use '/' or '' instead."
|
|
2563
2560
|
});
|
|
2564
2561
|
}
|
|
2565
2562
|
}),
|
|
@@ -2568,63 +2565,64 @@ const CollectionBaseSchema = z.object({
|
|
|
2568
2565
|
isDetached: z.boolean().optional()
|
|
2569
2566
|
});
|
|
2570
2567
|
const TinaCloudCollection = CollectionBaseSchema.extend({
|
|
2571
|
-
fields: z.array(TinaFieldZod).min(1).optional().superRefine((val, ctx) => {
|
|
2568
|
+
fields: z.array(TinaFieldZod).min(1, "Property `fields` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2572
2569
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2573
2570
|
if (dups) {
|
|
2574
2571
|
ctx.addIssue({
|
|
2575
2572
|
code: z.ZodIssueCode.custom,
|
|
2576
|
-
message:
|
|
2573
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2577
2574
|
});
|
|
2578
2575
|
}
|
|
2579
|
-
}).
|
|
2580
|
-
|
|
2581
|
-
(
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
message: "Fields can only have one use of `isTitle`"
|
|
2587
|
-
}
|
|
2588
|
-
).refine(
|
|
2589
|
-
// It is valid if it is 0 or 1
|
|
2590
|
-
(val) => {
|
|
2591
|
-
const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
|
|
2592
|
-
return arr.length < 2;
|
|
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"
|
|
2576
|
+
}).superRefine((val, ctx) => {
|
|
2577
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "string" && x.isTitle)) || [];
|
|
2578
|
+
if (arr.length > 1) {
|
|
2579
|
+
ctx.addIssue({
|
|
2580
|
+
code: z.ZodIssueCode.custom,
|
|
2581
|
+
message: `The following fields have the property \`isTitle\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`isTitle\`.`
|
|
2582
|
+
});
|
|
2605
2583
|
}
|
|
2606
|
-
),
|
|
2607
|
-
|
|
2584
|
+
}).superRefine((val, ctx) => {
|
|
2585
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.uid)) || [];
|
|
2586
|
+
if (arr.length > 2) {
|
|
2587
|
+
ctx.addIssue({
|
|
2588
|
+
code: z.ZodIssueCode.custom,
|
|
2589
|
+
message: `The following fields have the property \`uid\`: [${arr.map((field) => field.name).join(", ")}]. Only one can contain the property \`uid\`.`
|
|
2590
|
+
});
|
|
2591
|
+
}
|
|
2592
|
+
}).superRefine((val, ctx) => {
|
|
2593
|
+
const arr = (val == null ? void 0 : val.filter((x) => x.type === "password")) || [];
|
|
2594
|
+
if (arr.length > 2) {
|
|
2595
|
+
ctx.addIssue({
|
|
2596
|
+
code: z.ZodIssueCode.custom,
|
|
2597
|
+
message: `The following fields have \`type: password\`: [${arr.map((field) => field.name).join(", ")}]. Only one can be of \`type: password\`.`
|
|
2598
|
+
});
|
|
2599
|
+
}
|
|
2600
|
+
}),
|
|
2601
|
+
templates: z.array(Template).min(1, "Property `templates` cannot be empty.").optional().superRefine((val, ctx) => {
|
|
2608
2602
|
const dups = findDuplicates(val == null ? void 0 : val.map((x) => x.name));
|
|
2609
2603
|
if (dups) {
|
|
2610
2604
|
ctx.addIssue({
|
|
2611
2605
|
code: z.ZodIssueCode.custom,
|
|
2612
|
-
message:
|
|
2606
|
+
message: duplicateFieldErrorMessage(dups)
|
|
2613
2607
|
});
|
|
2614
2608
|
}
|
|
2615
2609
|
})
|
|
2616
|
-
}).
|
|
2617
|
-
(val)
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
}
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2610
|
+
}).superRefine((val, ctx) => {
|
|
2611
|
+
if (!(val == null ? void 0 : val.templates) && !(val == null ? void 0 : val.fields)) {
|
|
2612
|
+
ctx.addIssue({
|
|
2613
|
+
code: z.ZodIssueCode.custom,
|
|
2614
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property."
|
|
2615
|
+
});
|
|
2616
|
+
return false;
|
|
2617
|
+
}
|
|
2618
|
+
if ((val == null ? void 0 : val.templates) && (val == null ? void 0 : val.fields)) {
|
|
2619
|
+
ctx.addIssue({
|
|
2620
|
+
code: z.ZodIssueCode.custom,
|
|
2621
|
+
message: "Fields of `type: object` must have either `templates` or `fields` property, not both."
|
|
2622
|
+
});
|
|
2623
|
+
return false;
|
|
2624
|
+
}
|
|
2625
|
+
});
|
|
2628
2626
|
const TinaCloudSchemaZod = z.object({
|
|
2629
2627
|
collections: z.array(TinaCloudCollection),
|
|
2630
2628
|
config: tinaConfigZod.optional()
|
|
@@ -2634,14 +2632,14 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2634
2632
|
if (dups) {
|
|
2635
2633
|
ctx.addIssue({
|
|
2636
2634
|
code: z.ZodIssueCode.custom,
|
|
2637
|
-
message:
|
|
2635
|
+
message: duplicateCollectionErrorMessage(dups),
|
|
2638
2636
|
fatal: true
|
|
2639
2637
|
});
|
|
2640
2638
|
}
|
|
2641
2639
|
if (((_b = val.collections) == null ? void 0 : _b.filter((x) => x.isAuthCollection).length) > 1) {
|
|
2642
2640
|
ctx.addIssue({
|
|
2643
2641
|
code: z.ZodIssueCode.custom,
|
|
2644
|
-
message:
|
|
2642
|
+
message: "Only one collection can be marked as `isAuthCollection`.",
|
|
2645
2643
|
fatal: true
|
|
2646
2644
|
});
|
|
2647
2645
|
}
|
|
@@ -2649,7 +2647,7 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2649
2647
|
if (media && media.tina && media.loadCustomStore) {
|
|
2650
2648
|
ctx.addIssue({
|
|
2651
2649
|
code: z.ZodIssueCode.custom,
|
|
2652
|
-
message: "
|
|
2650
|
+
message: "Cannot have both `loadCustomStore` and `tina`. Must use one or the other.",
|
|
2653
2651
|
fatal: true,
|
|
2654
2652
|
path: ["config", "media"]
|
|
2655
2653
|
});
|
|
@@ -2658,7 +2656,7 @@ const TinaCloudSchemaZod = z.object({
|
|
|
2658
2656
|
if (search && search.tina && search.searchClient) {
|
|
2659
2657
|
ctx.addIssue({
|
|
2660
2658
|
code: z.ZodIssueCode.custom,
|
|
2661
|
-
message: "
|
|
2659
|
+
message: "Cannot have both `searchClient` and `tina`. Must use one or the other.",
|
|
2662
2660
|
fatal: true,
|
|
2663
2661
|
path: ["config", "search"]
|
|
2664
2662
|
});
|
|
@@ -2676,7 +2674,7 @@ const validateSchema = ({ schema }) => {
|
|
|
2676
2674
|
} catch (e) {
|
|
2677
2675
|
if (e instanceof ZodError) {
|
|
2678
2676
|
const errors = parseZodError({ zodError: e });
|
|
2679
|
-
throw new TinaSchemaValidationError(errors.join("
|
|
2677
|
+
throw new TinaSchemaValidationError(errors.join("\n"));
|
|
2680
2678
|
}
|
|
2681
2679
|
throw new Error(e);
|
|
2682
2680
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Schema, Collection, Template, Collectable, CollectionTemplateable
|
|
1
|
+
import type { Schema, Collection, Template, Collectable, CollectionTemplateable } from '../types/index';
|
|
2
2
|
type Version = {
|
|
3
3
|
fullVersion: string;
|
|
4
4
|
major: string;
|
|
@@ -28,6 +28,7 @@ export declare class TinaSchema {
|
|
|
28
28
|
} & Schema);
|
|
29
29
|
getIsTitleFieldName: (collection: string) => string;
|
|
30
30
|
getCollectionsByName: (collectionNames: string[]) => Collection<true>[];
|
|
31
|
+
findReferencesFromCollection(name: string): Record<string, string[]>;
|
|
31
32
|
getCollection: (collectionName: string) => Collection<true>;
|
|
32
33
|
getCollections: () => Collection<true>[];
|
|
33
34
|
getCollectionByFullPath: (filepath: string) => Collection<true>;
|
|
@@ -59,11 +60,12 @@ export declare class TinaSchema {
|
|
|
59
60
|
*
|
|
60
61
|
*/
|
|
61
62
|
getTemplatesForCollectable: (collection: Collectable) => CollectionTemplateable;
|
|
62
|
-
walkFields
|
|
63
|
-
field:
|
|
64
|
-
collection:
|
|
65
|
-
path: string
|
|
66
|
-
|
|
63
|
+
walkFields(cb: (args: {
|
|
64
|
+
field: any;
|
|
65
|
+
collection: any;
|
|
66
|
+
path: string;
|
|
67
|
+
isListItem?: boolean;
|
|
68
|
+
}) => void): void;
|
|
67
69
|
/**
|
|
68
70
|
* This function returns an array of glob matches for a given collection.
|
|
69
71
|
*
|
|
@@ -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
|
@@ -185,7 +185,7 @@ export type ReferenceField = (FieldGeneric<string, undefined, ReferenceFieldOpti
|
|
|
185
185
|
export type PasswordField = (FieldGeneric<string, undefined> | FieldGeneric<string, false>) & BaseField & {
|
|
186
186
|
type: 'password';
|
|
187
187
|
};
|
|
188
|
-
type
|
|
188
|
+
type ToolbarOverrideType = 'heading' | 'link' | 'image' | 'quote' | 'ul' | 'ol' | 'code' | 'codeBlock' | 'bold' | 'italic' | 'raw' | 'embed' | 'mermaid' | 'table';
|
|
189
189
|
type RichTextAst = {
|
|
190
190
|
type: 'root';
|
|
191
191
|
children: Record<string, unknown>[];
|
|
@@ -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
|
-
|
|
201
|
+
/**@deprecated use overrides.toolbar */
|
|
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`).
|
|
@@ -630,6 +636,7 @@ type Document = {
|
|
|
630
636
|
relativePath: string;
|
|
631
637
|
filename: string;
|
|
632
638
|
extension: string;
|
|
639
|
+
hasReferences?: boolean;
|
|
633
640
|
};
|
|
634
641
|
};
|
|
635
642
|
export interface UICollection<Form = any, CMS = any, TinaForm = any> {
|
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-d9672bc-20250218033222",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"exports": {
|
|
@@ -23,16 +23,16 @@
|
|
|
23
23
|
]
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@types/jest": "^29.5.
|
|
26
|
+
"@types/jest": "^29.5.14",
|
|
27
27
|
"@types/micromatch": "^4.0.9",
|
|
28
|
-
"@types/react": "^18.3.
|
|
28
|
+
"@types/react": "^18.3.12",
|
|
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.6.
|
|
33
|
+
"typescript": "^5.6.3",
|
|
34
34
|
"yup": "^0.32.11",
|
|
35
|
-
"@tinacms/scripts": "1.
|
|
35
|
+
"@tinacms/scripts": "1.3.1"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"react": ">=16.14.0",
|