@sanity/agent-schema 0.2.0 → 0.3.0
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/_chunks-es/{navigateToField.js → walkTree.js} +40 -2
- package/dist/_chunks-es/walkTree.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/validation/index.d.ts +32 -1
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +150 -8
- package/dist/validation/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/_chunks-es/navigateToField.js.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { a as ValidateValueFn, c as ValidationErrorCode, h as ManifestSchemaType, i as PatchOperations, l as ValidationResult, n as InsertOperation, o as ValidationContext, r as LocalizationConfig, s as ValidationError, t as FieldSchemaLookupResult } from "../_chunks-dts/types.js";
|
|
2
|
+
import { SanityClient } from "@sanity/client";
|
|
2
3
|
/**
|
|
3
4
|
* Validate an array value and its items.
|
|
4
5
|
*/
|
|
@@ -9,6 +10,11 @@ declare function validateArray(value: unknown, fieldSchema: ManifestSchemaType,
|
|
|
9
10
|
* against the existing document state.
|
|
10
11
|
*/
|
|
11
12
|
declare function validateUniqueItems(newItems: unknown[], existingArray: unknown[], pathPrefix: string, errors: ValidationError[]): void;
|
|
13
|
+
/**
|
|
14
|
+
* Return paths of fields with custom validators on the document type.
|
|
15
|
+
* Document-level custom validators are reported at `(document)`.
|
|
16
|
+
*/
|
|
17
|
+
declare function detectCustomValidators(documentType: string, schema: ManifestSchemaType[]): string[];
|
|
12
18
|
interface PathResolutionResult {
|
|
13
19
|
/** The resolved field schema, or null if not found */
|
|
14
20
|
schema: ManifestSchemaType | null;
|
|
@@ -212,6 +218,15 @@ declare function validateSchemaRules(value: unknown, fieldSchema: ManifestSchema
|
|
|
212
218
|
* Checks structure and optionally validates existence via client.
|
|
213
219
|
*/
|
|
214
220
|
declare function validateReference(value: unknown, fieldSchema: ManifestSchemaType, path: string, errors: ValidationError[], context: ValidationContext): Promise<void>;
|
|
221
|
+
declare function validateRequiredFields(document: Record<string, unknown>, documentType: string, schema: ManifestSchemaType[]): ValidationError[];
|
|
222
|
+
/**
|
|
223
|
+
* Check whether the slug values on a draft collide with any other document in
|
|
224
|
+
* the dataset (excluding the draft and its published twin).
|
|
225
|
+
*/
|
|
226
|
+
declare function validateSlugCollisions(document: Record<string, unknown>, documentType: string, schema: ManifestSchemaType[], client: SanityClient, ids: {
|
|
227
|
+
publishedId: string;
|
|
228
|
+
draftId: string;
|
|
229
|
+
}): Promise<ValidationError[]>;
|
|
215
230
|
/**
|
|
216
231
|
* Validate a slug value.
|
|
217
232
|
*/
|
|
@@ -282,5 +297,21 @@ declare function formatValidationErrors(errors: ValidationError[]): string;
|
|
|
282
297
|
* This is the core recursive validator that dispatches to type-specific validators.
|
|
283
298
|
*/
|
|
284
299
|
declare function validateValue(value: unknown, fieldSchema: ManifestSchemaType, path: string, errors: ValidationError[], context: ValidationContext, schema: ManifestSchemaType[], warnings?: ValidationError[]): Promise<void>;
|
|
285
|
-
|
|
300
|
+
type ValidateForPublishInput = {
|
|
301
|
+
document: Record<string, unknown>;
|
|
302
|
+
documentType: string;
|
|
303
|
+
schema: ManifestSchemaType[];
|
|
304
|
+
client: SanityClient;
|
|
305
|
+
publishedId: string;
|
|
306
|
+
draftId: string;
|
|
307
|
+
};
|
|
308
|
+
declare function validateForPublish({
|
|
309
|
+
document,
|
|
310
|
+
documentType,
|
|
311
|
+
schema,
|
|
312
|
+
client,
|
|
313
|
+
publishedId,
|
|
314
|
+
draftId
|
|
315
|
+
}: ValidateForPublishInput): Promise<ValidationResult>;
|
|
316
|
+
export { type FieldSchemaLookupResult, type InsertOperation, type LocalizationConfig, type PatchOperations, type ValidateValueFn, type ValidationContext, type ValidationError, type ValidationErrorCode, type ValidationResult, createError, detectCustomValidators, formatValidationErrors, formatValue, getActualJsType, getExpectedJsType, getFieldSchemaAtPath, getUniquenessKey, getValidImageMetadataFields, getValueAtPath, isInternationalizedArrayField, isV5InternationalizedArray, resolveFieldSchemaAtPath, validateArray, validateBlock, validateDocumentLanguageField, validateFieldLevelLanguageField, validateFieldLevelLanguageKey, validateFile, validateForPublish, validateGeopoint, validateImage, validateImageMetadata, validateImagePath, validateInternationalizedArrayItems, validateInternationalizedArraySet, validateNoExtraProperties, validateObject, validatePrimitive, validateReference, validateRequiredFields, validateSchemaRules, validateSlug, validateSlugCollisions, validateUniqueItems, validateValue };
|
|
286
317
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/validation/array.validator.ts","../../src/validation/document-path-resolver.ts","../../src/validation/language.validator.ts","../../src/validation/object.validator.ts","../../src/validation/path-validation.ts","../../src/validation/portable-text.validator.ts","../../src/validation/primitive.validator.ts","../../src/validation/reference.validator.ts","../../src/validation/special-types.validator.ts","../../src/validation/utils.ts","../../src/validation/validate-value.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/validation/array.validator.ts","../../src/validation/customValidators.ts","../../src/validation/document-path-resolver.ts","../../src/validation/language.validator.ts","../../src/validation/object.validator.ts","../../src/validation/path-validation.ts","../../src/validation/portable-text.validator.ts","../../src/validation/primitive.validator.ts","../../src/validation/reference.validator.ts","../../src/validation/requiredFields.ts","../../src/validation/slugCollisions.ts","../../src/validation/special-types.validator.ts","../../src/validation/utils.ts","../../src/validation/validate-value.ts","../../src/validation/validateForPublish.ts"],"mappings":"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"}
|
package/dist/validation/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isPrimitiveType, resolveFieldSchema, BUILT_IN_TYPE_FIELDS, resolveFieldSchemaAllUnions } from "../_chunks-es/
|
|
1
|
+
import { isPrimitiveType, walkSchemaTree, resolveFieldSchema, BUILT_IN_TYPE_FIELDS, resolveFieldSchemaAllUnions, joinSchemaPath } from "../_chunks-es/walkTree.js";
|
|
2
2
|
function createError(path, code, message, received, expected, fix) {
|
|
3
3
|
return { path, code, message, received, expected, fix };
|
|
4
4
|
}
|
|
@@ -152,10 +152,10 @@ async function validateArray(value, fieldSchema, path, schema, errors, context,
|
|
|
152
152
|
(t) => !t.name && isPrimitiveType(t.type)
|
|
153
153
|
), seenKeys = /* @__PURE__ */ new Set();
|
|
154
154
|
for (let i = 0; i < value.length; i++) {
|
|
155
|
-
const item = value[i],
|
|
155
|
+
const item = value[i], itemPath2 = `${path}[${i}]`, errorCountBefore = errors.length, itemObj = item, itemType = itemObj?._type, itemKey = itemObj?._key;
|
|
156
156
|
!isPrimitiveArray && typeof item == "object" && item !== null && (itemKey === void 0 ? errors.push(
|
|
157
157
|
createError(
|
|
158
|
-
|
|
158
|
+
itemPath2,
|
|
159
159
|
"ARRAY_ITEM_INVALID",
|
|
160
160
|
'Object array item missing "_key" property',
|
|
161
161
|
formatValue(item),
|
|
@@ -164,7 +164,7 @@ async function validateArray(value, fieldSchema, path, schema, errors, context,
|
|
|
164
164
|
)
|
|
165
165
|
) : typeof itemKey == "string" && itemKey !== "" && (seenKeys.has(itemKey) ? errors.push(
|
|
166
166
|
createError(
|
|
167
|
-
`${
|
|
167
|
+
`${itemPath2}._key`,
|
|
168
168
|
"ARRAY_ITEM_INVALID",
|
|
169
169
|
`duplicate _key "${itemKey}" in array`,
|
|
170
170
|
itemKey,
|
|
@@ -200,7 +200,7 @@ async function validateArray(value, fieldSchema, path, schema, errors, context,
|
|
|
200
200
|
if (!isPrimitiveArray && (typeof item == "string" || typeof item == "number" || typeof item == "boolean" || item === null)) {
|
|
201
201
|
errors.push(
|
|
202
202
|
createError(
|
|
203
|
-
|
|
203
|
+
itemPath2,
|
|
204
204
|
"TYPE_MISMATCH",
|
|
205
205
|
"Expected object but found primitive in array",
|
|
206
206
|
formatValue(item),
|
|
@@ -213,7 +213,7 @@ async function validateArray(value, fieldSchema, path, schema, errors, context,
|
|
|
213
213
|
const namedTypes = itemTypes.filter((t) => t.name);
|
|
214
214
|
namedTypes.length > 0 && itemType ? errors.push(
|
|
215
215
|
createError(
|
|
216
|
-
|
|
216
|
+
itemPath2,
|
|
217
217
|
"ARRAY_ITEM_INVALID",
|
|
218
218
|
`Wrong _type "${itemType}" for array item`,
|
|
219
219
|
formatValue(item),
|
|
@@ -222,7 +222,7 @@ async function validateArray(value, fieldSchema, path, schema, errors, context,
|
|
|
222
222
|
)
|
|
223
223
|
) : errors.push(
|
|
224
224
|
createError(
|
|
225
|
-
|
|
225
|
+
itemPath2,
|
|
226
226
|
"ARRAY_ITEM_INVALID",
|
|
227
227
|
itemType ? `Unknown array item type: ${itemType}` : "Invalid array item",
|
|
228
228
|
formatValue(item),
|
|
@@ -232,7 +232,7 @@ async function validateArray(value, fieldSchema, path, schema, errors, context,
|
|
|
232
232
|
), tagItemErrors(errors, errorCountBefore, i, path);
|
|
233
233
|
continue;
|
|
234
234
|
}
|
|
235
|
-
await validateValue2(item, matchingSchema,
|
|
235
|
+
await validateValue2(item, matchingSchema, itemPath2, errors, context, schema), tagItemErrors(errors, errorCountBefore, i, path);
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
function tagItemErrors(errors, startIndex, itemIndex, arrayPath) {
|
|
@@ -267,6 +267,17 @@ function validateUniqueItems(newItems, existingArray, pathPrefix, errors) {
|
|
|
267
267
|
), newKeys.add(uniquenessKey);
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
|
+
const isRequiredRule = (rule) => rule.type === "required" || rule.flag === "presence" && rule.constraint === "required", isCustomRule = (rule) => rule.type === "custom" || rule.flag === "custom", matchesAnyRule = (field, predicate, errorLevelOnly) => (field.validation ?? []).some(
|
|
271
|
+
(group) => (!errorLevelOnly || (group.level ?? "error") === "error") && (group.rules ?? []).some((rule) => predicate(rule))
|
|
272
|
+
), hasRequiredValidator = (field) => matchesAnyRule(field, isRequiredRule, !0), hasCustomValidator = (field) => matchesAnyRule(field, isCustomRule, !1);
|
|
273
|
+
function detectCustomValidators(documentType, schema) {
|
|
274
|
+
const typeSchema = schema.find((s) => s.name === documentType);
|
|
275
|
+
if (!typeSchema) return [];
|
|
276
|
+
const paths = [];
|
|
277
|
+
return hasCustomValidator(typeSchema) && paths.push("(document)"), walkSchemaTree(documentType, schema, (field, path) => {
|
|
278
|
+
hasCustomValidator(field) && paths.push(path);
|
|
279
|
+
}), paths;
|
|
280
|
+
}
|
|
270
281
|
function pathHasArraySelectors(path) {
|
|
271
282
|
return /\[(_key==|[0-9])/.test(path);
|
|
272
283
|
}
|
|
@@ -1533,6 +1544,95 @@ async function validateReference(value, fieldSchema, path, errors, context) {
|
|
|
1533
1544
|
} catch {
|
|
1534
1545
|
}
|
|
1535
1546
|
}
|
|
1547
|
+
const isPlainObject$1 = (value) => typeof value == "object" && value !== null && !Array.isArray(value), isMissing = (value) => value == null ? !0 : typeof value == "string" || Array.isArray(value) ? value.length === 0 : !1, missingRequiredError = (path, field) => createError(
|
|
1548
|
+
path,
|
|
1549
|
+
"REQUIRED_FIELD_MISSING",
|
|
1550
|
+
`Required field "${field.name}" is missing`,
|
|
1551
|
+
formatValue(void 0),
|
|
1552
|
+
`${field.title ?? field.name} (${field.type})`,
|
|
1553
|
+
`Set a value for "${field.name}" before publishing`
|
|
1554
|
+
), itemPath = (parent, item, index) => {
|
|
1555
|
+
const key = item._key;
|
|
1556
|
+
return typeof key == "string" ? `${parent}[_key=="${key}"]` : `${parent}[${index}]`;
|
|
1557
|
+
}, resolveItemFields = (itemSchema, schema) => itemSchema.fields?.length ? itemSchema.fields : !itemSchema.type || isPrimitiveType(itemSchema.type) ? void 0 : schema.find((s) => s.name === itemSchema.type)?.fields;
|
|
1558
|
+
function walkArray(field, value, path, schema, errors) {
|
|
1559
|
+
if (field.of?.length)
|
|
1560
|
+
for (let index = 0; index < value.length; index++) {
|
|
1561
|
+
const item = value[index];
|
|
1562
|
+
if (!isPlainObject$1(item)) continue;
|
|
1563
|
+
const matched = field.of.find((member) => member.type === item._type) ?? field.of[0], itemFields = resolveItemFields(matched, schema);
|
|
1564
|
+
itemFields?.length && walkFields(itemFields, item, itemPath(path, item, index), schema, errors);
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
function walkFields(fields, value, path, schema, errors) {
|
|
1568
|
+
const obj = isPlainObject$1(value) ? value : {};
|
|
1569
|
+
for (const field of fields) {
|
|
1570
|
+
const fieldValue = obj[field.name], fieldPath = joinSchemaPath(path, field.name);
|
|
1571
|
+
if (hasRequiredValidator(field) && isMissing(fieldValue)) {
|
|
1572
|
+
errors.push(missingRequiredError(fieldPath, field));
|
|
1573
|
+
continue;
|
|
1574
|
+
}
|
|
1575
|
+
if (isMissing(fieldValue)) continue;
|
|
1576
|
+
if (Array.isArray(fieldValue)) {
|
|
1577
|
+
walkArray(field, fieldValue, fieldPath, schema, errors);
|
|
1578
|
+
continue;
|
|
1579
|
+
}
|
|
1580
|
+
if (field.fields?.length) {
|
|
1581
|
+
walkFields(field.fields, fieldValue, fieldPath, schema, errors);
|
|
1582
|
+
continue;
|
|
1583
|
+
}
|
|
1584
|
+
if (!field.type || isPrimitiveType(field.type)) continue;
|
|
1585
|
+
const referenced = schema.find((s) => s.name === field.type);
|
|
1586
|
+
referenced?.fields?.length && walkFields(referenced.fields, fieldValue, fieldPath, schema, errors);
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
function validateRequiredFields(document, documentType, schema) {
|
|
1590
|
+
const typeSchema = schema.find((s) => s.name === documentType);
|
|
1591
|
+
if (!typeSchema?.fields?.length) return [];
|
|
1592
|
+
const errors = [];
|
|
1593
|
+
return walkFields(typeSchema.fields, document, "", schema, errors), errors;
|
|
1594
|
+
}
|
|
1595
|
+
const isPlainObject = (value) => typeof value == "object" && value !== null && !Array.isArray(value), isSlugType = (field, schema) => field.type === "slug" ? !0 : schema.find((s) => s.name === field.type)?.type === "slug", hasCustomIsUnique = (field) => {
|
|
1596
|
+
const isUnique = field.options?.isUnique;
|
|
1597
|
+
return isPlainObject(isUnique) && isUnique.__type === "function";
|
|
1598
|
+
}, readSlugCurrent = (value) => {
|
|
1599
|
+
if (!isPlainObject(value)) return;
|
|
1600
|
+
const current = value.current;
|
|
1601
|
+
return typeof current == "string" && current.length > 0 ? current : void 0;
|
|
1602
|
+
};
|
|
1603
|
+
function collectSlugFields(document, documentType, schema) {
|
|
1604
|
+
const typeSchema = schema.find((s) => s.name === documentType);
|
|
1605
|
+
if (!typeSchema?.fields?.length) return [];
|
|
1606
|
+
const out = [];
|
|
1607
|
+
for (const field of typeSchema.fields) {
|
|
1608
|
+
if (!isSlugType(field, schema)) continue;
|
|
1609
|
+
const current = readSlugCurrent(document[field.name]);
|
|
1610
|
+
current !== void 0 && out.push({ path: field.name, field, current });
|
|
1611
|
+
}
|
|
1612
|
+
return out;
|
|
1613
|
+
}
|
|
1614
|
+
const collisionError = (path, current, conflictingId) => createError(
|
|
1615
|
+
`${path}.current`,
|
|
1616
|
+
"INVALID_FORMAT",
|
|
1617
|
+
`Slug "${current}" is already in use by another document`,
|
|
1618
|
+
formatValue(current),
|
|
1619
|
+
"A slug not used by any other document",
|
|
1620
|
+
`Choose a different slug for "${path}". The conflicting document is "${conflictingId}".`
|
|
1621
|
+
);
|
|
1622
|
+
async function validateSlugCollisions(document, documentType, schema, client, ids) {
|
|
1623
|
+
const slugs = collectSlugFields(document, documentType, schema);
|
|
1624
|
+
return slugs.length === 0 ? [] : (await Promise.all(
|
|
1625
|
+
slugs.map(async ({ path, field, current }) => {
|
|
1626
|
+
if (hasCustomIsUnique(field)) return;
|
|
1627
|
+
const query = `*[!(_id in [$publishedId, $draftId]) && ${path}.current == $slug][0]._id`, conflictingId = await client.fetch(query, {
|
|
1628
|
+
publishedId: ids.publishedId,
|
|
1629
|
+
draftId: ids.draftId,
|
|
1630
|
+
slug: current
|
|
1631
|
+
});
|
|
1632
|
+
return conflictingId ? collisionError(path, current, conflictingId) : void 0;
|
|
1633
|
+
})
|
|
1634
|
+
)).filter((e) => e !== void 0);
|
|
1635
|
+
}
|
|
1536
1636
|
function validateSlug(value, path, errors) {
|
|
1537
1637
|
if (typeof value != "object" || value === null) {
|
|
1538
1638
|
errors.push(
|
|
@@ -1882,8 +1982,47 @@ async function validateValue(value, fieldSchema, path, errors, context, schema,
|
|
|
1882
1982
|
}
|
|
1883
1983
|
}
|
|
1884
1984
|
}
|
|
1985
|
+
async function validateForPublish({
|
|
1986
|
+
document,
|
|
1987
|
+
documentType,
|
|
1988
|
+
schema,
|
|
1989
|
+
client,
|
|
1990
|
+
publishedId,
|
|
1991
|
+
draftId
|
|
1992
|
+
}) {
|
|
1993
|
+
const typeSchema = schema.find((s) => s.name === documentType);
|
|
1994
|
+
if (!typeSchema)
|
|
1995
|
+
return {
|
|
1996
|
+
valid: !1,
|
|
1997
|
+
errors: [
|
|
1998
|
+
createError(
|
|
1999
|
+
"_type",
|
|
2000
|
+
"FIELD_NOT_IN_SCHEMA",
|
|
2001
|
+
`Document type "${documentType}" not found in schema`,
|
|
2002
|
+
documentType,
|
|
2003
|
+
"Valid document type",
|
|
2004
|
+
"Check the schema for valid document type names"
|
|
2005
|
+
)
|
|
2006
|
+
],
|
|
2007
|
+
warnings: []
|
|
2008
|
+
};
|
|
2009
|
+
const structuralErrors = [], [, slugs] = await Promise.all([
|
|
2010
|
+
validateObject(
|
|
2011
|
+
document,
|
|
2012
|
+
typeSchema,
|
|
2013
|
+
"",
|
|
2014
|
+
schema,
|
|
2015
|
+
structuralErrors,
|
|
2016
|
+
{ documentType, client },
|
|
2017
|
+
validateValue
|
|
2018
|
+
),
|
|
2019
|
+
validateSlugCollisions(document, documentType, schema, client, { publishedId, draftId })
|
|
2020
|
+
]), required = validateRequiredFields(document, documentType, schema), errors = [...structuralErrors, ...required, ...slugs];
|
|
2021
|
+
return { valid: errors.length === 0, errors, warnings: [] };
|
|
2022
|
+
}
|
|
1885
2023
|
export {
|
|
1886
2024
|
createError,
|
|
2025
|
+
detectCustomValidators,
|
|
1887
2026
|
formatValidationErrors,
|
|
1888
2027
|
formatValue,
|
|
1889
2028
|
getActualJsType,
|
|
@@ -1901,6 +2040,7 @@ export {
|
|
|
1901
2040
|
validateFieldLevelLanguageField,
|
|
1902
2041
|
validateFieldLevelLanguageKey,
|
|
1903
2042
|
validateFile,
|
|
2043
|
+
validateForPublish,
|
|
1904
2044
|
validateGeopoint,
|
|
1905
2045
|
validateImage,
|
|
1906
2046
|
validateImageMetadata,
|
|
@@ -1911,8 +2051,10 @@ export {
|
|
|
1911
2051
|
validateObject,
|
|
1912
2052
|
validatePrimitive,
|
|
1913
2053
|
validateReference,
|
|
2054
|
+
validateRequiredFields,
|
|
1914
2055
|
validateSchemaRules,
|
|
1915
2056
|
validateSlug,
|
|
2057
|
+
validateSlugCollisions,
|
|
1916
2058
|
validateUniqueItems,
|
|
1917
2059
|
validateValue
|
|
1918
2060
|
};
|