@sanity/validation 3.14.3 → 6.12.0-next.112
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/LICENSE +1 -1
- package/README.md +52 -0
- package/lib/_internal.d.ts +96 -0
- package/lib/_internal.js +39 -0
- package/lib/_internal.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -1306
- package/lib/validateDocument-6pLTIHIn.d.ts +277 -0
- package/lib/validateDocument-Cq33kUmN.js +1127 -0
- package/lib/validateDocument-Cq33kUmN.js.map +1 -0
- package/package.json +53 -45
- package/lib/dts/src/index.d.ts +0 -50
- package/lib/index.cjs.mjs +0 -9
- package/lib/index.esm.js +0 -1286
- package/lib/index.esm.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/src/Rule.ts +0 -424
- package/src/ValidationError.ts +0 -32
- package/src/index.ts +0 -9
- package/src/inferFromSchema.ts +0 -19
- package/src/inferFromSchemaType.ts +0 -50
- package/src/util/convertToValidationMarker.ts +0 -84
- package/src/util/deepEquals.ts +0 -77
- package/src/util/escapeRegex.ts +0 -5
- package/src/util/normalizeValidationRules.test.ts +0 -170
- package/src/util/normalizeValidationRules.ts +0 -118
- package/src/util/pathToString.ts +0 -21
- package/src/util/requestIdleCallback.ts +0 -31
- package/src/util/typeString.test.ts +0 -27
- package/src/util/typeString.ts +0 -23
- package/src/validateDocument.test.ts +0 -703
- package/src/validateDocument.ts +0 -240
- package/src/validators/arrayValidator.ts +0 -100
- package/src/validators/booleanValidator.ts +0 -16
- package/src/validators/dateValidator.ts +0 -113
- package/src/validators/genericValidator.ts +0 -117
- package/src/validators/numberValidator.ts +0 -66
- package/src/validators/objectValidator.ts +0 -64
- package/src/validators/slugValidator.ts +0 -117
- package/src/validators/stringValidator.ts +0 -120
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import {Validators, isReference} from '@sanity/types'
|
|
2
|
-
import genericValidator from './genericValidator'
|
|
3
|
-
|
|
4
|
-
const metaKeys = ['_key', '_type', '_weak']
|
|
5
|
-
|
|
6
|
-
const objectValidators: Validators = {
|
|
7
|
-
...genericValidator,
|
|
8
|
-
|
|
9
|
-
presence: (expected, value, message) => {
|
|
10
|
-
if (expected !== 'required') {
|
|
11
|
-
return true
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const keys = value && Object.keys(value).filter((key) => !metaKeys.includes(key))
|
|
15
|
-
|
|
16
|
-
if (value === undefined || (keys && keys.length === 0)) {
|
|
17
|
-
return message || 'Required'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return true
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
reference: async (_unused, value: unknown, message, context) => {
|
|
24
|
-
if (!value) {
|
|
25
|
-
return true
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (!isReference(value)) {
|
|
29
|
-
return message || 'Must be a reference to a document'
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const {type, getDocumentExists} = context
|
|
33
|
-
|
|
34
|
-
if (!type) {
|
|
35
|
-
throw new Error(`\`type\` was not provided in validation context`)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if ('weak' in type && type.weak) {
|
|
39
|
-
return true
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (!getDocumentExists) {
|
|
43
|
-
throw new Error(`\`getDocumentExists\` was not provided in validation context`)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const exists = await getDocumentExists({id: value._ref})
|
|
47
|
-
if (!exists) {
|
|
48
|
-
return 'This reference must be published'
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return true
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
assetRequired: (flag, value, message) => {
|
|
55
|
-
if (!value || !value.asset || !value.asset._ref) {
|
|
56
|
-
const assetType = flag.assetType || 'Asset'
|
|
57
|
-
return message || `${assetType} required`
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return true
|
|
61
|
-
},
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export default objectValidators
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
SlugIsUniqueValidator,
|
|
3
|
-
Path,
|
|
4
|
-
CustomValidator,
|
|
5
|
-
isKeyedObject,
|
|
6
|
-
SlugValidationContext,
|
|
7
|
-
SlugParent,
|
|
8
|
-
SlugSchemaType,
|
|
9
|
-
} from '@sanity/types'
|
|
10
|
-
import {memoize} from 'lodash'
|
|
11
|
-
// import getClient from '../getClient'
|
|
12
|
-
|
|
13
|
-
const memoizedWarnOnArraySlug = memoize(warnOnArraySlug)
|
|
14
|
-
|
|
15
|
-
function getDocumentIds(id: string) {
|
|
16
|
-
const isDraft = id.indexOf('drafts.') === 0
|
|
17
|
-
return {
|
|
18
|
-
published: isDraft ? id.slice('drafts.'.length) : id,
|
|
19
|
-
draft: isDraft ? id : `drafts.${id}`,
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function serializePath(path: Path): string {
|
|
24
|
-
return path.reduce<string>((target, part, i) => {
|
|
25
|
-
const isIndex = typeof part === 'number'
|
|
26
|
-
const isKey = isKeyedObject(part)
|
|
27
|
-
const separator = i === 0 ? '' : '.'
|
|
28
|
-
const add = isIndex || isKey ? '[]' : `${separator}${part}`
|
|
29
|
-
return `${target}${add}`
|
|
30
|
-
}, '')
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const defaultIsUnique: SlugIsUniqueValidator = (slug, context) => {
|
|
34
|
-
const {getClient, document, path, type} = context
|
|
35
|
-
const schemaOptions = type?.options as {disableArrayWarning?: boolean} | undefined
|
|
36
|
-
|
|
37
|
-
if (!document) {
|
|
38
|
-
throw new Error(`\`document\` was not provided in validation context.`)
|
|
39
|
-
}
|
|
40
|
-
if (!path) {
|
|
41
|
-
throw new Error(`\`path\` was not provided in validation context.`)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const disableArrayWarning = schemaOptions?.disableArrayWarning || false
|
|
45
|
-
const {published, draft} = getDocumentIds(document._id)
|
|
46
|
-
const docType = document._type
|
|
47
|
-
const atPath = serializePath(path.concat('current'))
|
|
48
|
-
|
|
49
|
-
if (!disableArrayWarning && atPath.includes('[]')) {
|
|
50
|
-
memoizedWarnOnArraySlug(serializePath(path))
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const constraints = [
|
|
54
|
-
'_type == $docType',
|
|
55
|
-
`!(_id in [$draft, $published])`,
|
|
56
|
-
`${atPath} == $slug`,
|
|
57
|
-
].join(' && ')
|
|
58
|
-
|
|
59
|
-
return getClient({apiVersion: '2022-09-09'}).fetch<boolean>(
|
|
60
|
-
`!defined(*[${constraints}][0]._id)`,
|
|
61
|
-
{
|
|
62
|
-
docType,
|
|
63
|
-
draft,
|
|
64
|
-
published,
|
|
65
|
-
slug,
|
|
66
|
-
},
|
|
67
|
-
{tag: 'validation.slug-is-unique'}
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function warnOnArraySlug(serializedPath: string) {
|
|
72
|
-
/* eslint-disable no-console */
|
|
73
|
-
console.warn(
|
|
74
|
-
[
|
|
75
|
-
`Slug field at path ${serializedPath} is within an array and cannot be automatically checked for uniqueness`,
|
|
76
|
-
`If you need to check for uniqueness, provide your own "isUnique" method`,
|
|
77
|
-
`To disable this message, set \`disableArrayWarning: true\` on the slug \`options\` field`,
|
|
78
|
-
].join('\n')
|
|
79
|
-
)
|
|
80
|
-
/* eslint-enable no-console */
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Validates slugs values by querying for uniqueness from the client.
|
|
85
|
-
*
|
|
86
|
-
* This is a custom rule implementation (e.g. `Rule.custom(slugValidator)`)
|
|
87
|
-
* that's populated in `inferFromSchemaType` when the type name is `slug`
|
|
88
|
-
*/
|
|
89
|
-
export const slugValidator: CustomValidator = async (value, context) => {
|
|
90
|
-
if (!value) {
|
|
91
|
-
return true
|
|
92
|
-
}
|
|
93
|
-
if (typeof value !== 'object') {
|
|
94
|
-
return 'Slug must be an object'
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const slugValue = (value as {current?: string}).current
|
|
98
|
-
if (!slugValue) {
|
|
99
|
-
return 'Slug must have a value'
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const options = context?.type?.options as {isUnique?: SlugIsUniqueValidator} | undefined
|
|
103
|
-
const isUnique = options?.isUnique || defaultIsUnique
|
|
104
|
-
|
|
105
|
-
const slugContext: SlugValidationContext = {
|
|
106
|
-
...context,
|
|
107
|
-
parent: context.parent as SlugParent,
|
|
108
|
-
type: context.type as SlugSchemaType,
|
|
109
|
-
defaultIsUnique,
|
|
110
|
-
}
|
|
111
|
-
const wasUnique = await isUnique(slugValue, slugContext)
|
|
112
|
-
if (wasUnique) {
|
|
113
|
-
return true
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return 'Slug is already in use'
|
|
117
|
-
}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import {Validators} from '@sanity/types'
|
|
2
|
-
import genericValidator from './genericValidator'
|
|
3
|
-
|
|
4
|
-
const DUMMY_ORIGIN = 'http://sanity'
|
|
5
|
-
const emailRegex =
|
|
6
|
-
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
|
7
|
-
const isRelativeUrl = (url: string) => /^\.*\//.test(url)
|
|
8
|
-
|
|
9
|
-
const stringValidators: Validators = {
|
|
10
|
-
...genericValidator,
|
|
11
|
-
|
|
12
|
-
min: (minLength, value, message) => {
|
|
13
|
-
if (!value || value.length >= minLength) {
|
|
14
|
-
return true
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return message || `Must be at least ${minLength} characters long`
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
max: (maxLength, value, message) => {
|
|
21
|
-
if (!value || value.length <= maxLength) {
|
|
22
|
-
return true
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return message || `Must be at most ${maxLength} characters long`
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
length: (wantedLength, value, message) => {
|
|
29
|
-
const strValue = value || ''
|
|
30
|
-
if (strValue.length === wantedLength) {
|
|
31
|
-
return true
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return message || `Must be exactly ${wantedLength} characters long`
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
uri: (constraints, value, message) => {
|
|
38
|
-
const strValue = value || ''
|
|
39
|
-
const {options} = constraints
|
|
40
|
-
const {allowCredentials, relativeOnly} = options
|
|
41
|
-
const allowRelative = options.allowRelative || relativeOnly
|
|
42
|
-
|
|
43
|
-
let url
|
|
44
|
-
try {
|
|
45
|
-
// WARNING: Safari checks for a given `base` param by looking at the length of arguments passed
|
|
46
|
-
// to new URL(str, base), and will fail if invoked with new URL(strValue, undefined)
|
|
47
|
-
url = allowRelative ? new URL(strValue, DUMMY_ORIGIN) : new URL(strValue)
|
|
48
|
-
} catch (err) {
|
|
49
|
-
return message || 'Not a valid URL'
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (relativeOnly && url.origin !== DUMMY_ORIGIN) {
|
|
53
|
-
return message || 'Only relative URLs are allowed'
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (!allowRelative && url.origin === DUMMY_ORIGIN && isRelativeUrl(strValue)) {
|
|
57
|
-
return message || 'Relative URLs are not allowed'
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (!allowCredentials && (url.username || url.password)) {
|
|
61
|
-
return message || `Username/password not allowed`
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const urlScheme = url.protocol.replace(/:$/, '')
|
|
65
|
-
const matchesAllowedScheme = options.scheme.some((scheme) => scheme.test(urlScheme))
|
|
66
|
-
if (!matchesAllowedScheme) {
|
|
67
|
-
return message || 'Does not match allowed protocols/schemes'
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return true
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
stringCasing: (casing, value, message) => {
|
|
74
|
-
const strValue = value || ''
|
|
75
|
-
if (casing === 'uppercase' && strValue !== strValue.toLocaleUpperCase()) {
|
|
76
|
-
return message || `Must be all uppercase letters`
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (casing === 'lowercase' && strValue !== strValue.toLocaleLowerCase()) {
|
|
80
|
-
return message || `Must be all lowercase letters`
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return true
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
presence: (flag, value, message) => {
|
|
87
|
-
if (flag === 'required' && !value) {
|
|
88
|
-
return message || 'Required'
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return true
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
regex: (options, value, message) => {
|
|
95
|
-
const {pattern, name, invert} = options
|
|
96
|
-
const regName = name || `"${pattern.toString()}"`
|
|
97
|
-
const strValue = value || ''
|
|
98
|
-
const matches = pattern.test(strValue)
|
|
99
|
-
if ((!invert && !matches) || (invert && matches)) {
|
|
100
|
-
const defaultMessage = invert
|
|
101
|
-
? `Should not match ${regName}-pattern`
|
|
102
|
-
: `Does not match ${regName}-pattern`
|
|
103
|
-
|
|
104
|
-
return message || defaultMessage
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return true
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
email: (_unused, value, message) => {
|
|
111
|
-
const strValue = `${value || ''}`.trim()
|
|
112
|
-
if (!strValue || emailRegex.test(strValue)) {
|
|
113
|
-
return true
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return message || 'Must be a valid email address'
|
|
117
|
-
},
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export default stringValidators
|