@sanity/validation 3.14.4 → 6.12.0-next.46

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.
Files changed (40) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +29 -0
  3. package/lib/_internal.d.ts +93 -0
  4. package/lib/_internal.js +39 -0
  5. package/lib/_internal.js.map +1 -0
  6. package/lib/index.d.ts +2 -0
  7. package/lib/index.js +2 -1306
  8. package/lib/validateDocument-C77_Oewa.js +843 -0
  9. package/lib/validateDocument-C77_Oewa.js.map +1 -0
  10. package/lib/validateDocument-CBOsd748.d.ts +199 -0
  11. package/package.json +53 -45
  12. package/lib/dts/src/index.d.ts +0 -50
  13. package/lib/index.cjs.mjs +0 -9
  14. package/lib/index.esm.js +0 -1286
  15. package/lib/index.esm.js.map +0 -1
  16. package/lib/index.js.map +0 -1
  17. package/src/Rule.ts +0 -424
  18. package/src/ValidationError.ts +0 -32
  19. package/src/index.ts +0 -9
  20. package/src/inferFromSchema.ts +0 -19
  21. package/src/inferFromSchemaType.ts +0 -50
  22. package/src/util/convertToValidationMarker.ts +0 -84
  23. package/src/util/deepEquals.ts +0 -77
  24. package/src/util/escapeRegex.ts +0 -5
  25. package/src/util/normalizeValidationRules.test.ts +0 -170
  26. package/src/util/normalizeValidationRules.ts +0 -118
  27. package/src/util/pathToString.ts +0 -21
  28. package/src/util/requestIdleCallback.ts +0 -31
  29. package/src/util/typeString.test.ts +0 -27
  30. package/src/util/typeString.ts +0 -23
  31. package/src/validateDocument.test.ts +0 -703
  32. package/src/validateDocument.ts +0 -240
  33. package/src/validators/arrayValidator.ts +0 -100
  34. package/src/validators/booleanValidator.ts +0 -16
  35. package/src/validators/dateValidator.ts +0 -113
  36. package/src/validators/genericValidator.ts +0 -117
  37. package/src/validators/numberValidator.ts +0 -66
  38. package/src/validators/objectValidator.ts +0 -64
  39. package/src/validators/slugValidator.ts +0 -117
  40. package/src/validators/stringValidator.ts +0 -120
@@ -1,170 +0,0 @@
1
- import {NumberSchemaType, SchemaType, StringSchemaType} from '@sanity/types'
2
- import RuleClass from '../Rule'
3
- import normalizeValidationRules from './normalizeValidationRules'
4
-
5
- describe('normalizeValidationRules', () => {
6
- // see `infer.test.ts` for more related tests.
7
- // note the Schema.compile runs this function indirectly via `inferFromSchema`
8
- it('utilizes schema types to infer base rules', () => {
9
- const coolNumberType: NumberSchemaType = {
10
- jsonType: 'number',
11
- name: 'coolNumber',
12
- }
13
-
14
- const rules = normalizeValidationRules(coolNumberType)
15
- expect(rules).toHaveLength(1)
16
- const [rule] = rules
17
-
18
- expect(rule).toBeInstanceOf(RuleClass)
19
- expect(rule._rules).toMatchObject([
20
- {
21
- constraint: 'Number',
22
- flag: 'type',
23
- },
24
- ])
25
- })
26
-
27
- it('follows the type chain to determine the base rule', () => {
28
- const sickDatetime = {
29
- type: {
30
- type: {
31
- jsonType: 'string',
32
- },
33
- name: 'datetime',
34
- },
35
- name: 'sickDatetime',
36
- }
37
-
38
- const rules = normalizeValidationRules(sickDatetime as SchemaType)
39
- expect(rules).toHaveLength(1)
40
- const [rule] = rules
41
-
42
- // type chain is applied from inner to outer so the resulting type should be
43
- // date instead of string
44
- expect(rule._rules).toMatchObject([
45
- {
46
- constraint: 'Date',
47
- flag: 'type',
48
- },
49
- ])
50
- })
51
-
52
- it('converts a validation function to a rule instance', () => {
53
- const coolStringType: StringSchemaType = {
54
- jsonType: 'string',
55
- name: 'coolString',
56
- validation: (rule) => rule.uppercase(),
57
- }
58
-
59
- const rules = normalizeValidationRules(coolStringType)
60
- expect(rules).toHaveLength(1)
61
- const [rule] = rules
62
-
63
- expect(rule).toBeInstanceOf(RuleClass)
64
- expect(rule._rules).toMatchObject([
65
- {
66
- constraint: 'String',
67
- flag: 'type',
68
- },
69
- {
70
- constraint: 'uppercase',
71
- flag: 'stringCasing',
72
- },
73
- ])
74
- })
75
-
76
- it('converts falsy values to an empty array', () => {
77
- expect(normalizeValidationRules(undefined)).toEqual([])
78
- })
79
-
80
- it('converts schema list options with titles to `rule.valid` constraints', () => {
81
- const stringTypeWithOptions: StringSchemaType = {
82
- jsonType: 'string',
83
- name: 'stringTypeWithOptions',
84
- options: {
85
- list: [
86
- {title: 'Blue', value: 'blue'},
87
- {title: 'Red', value: 'red'},
88
- ],
89
- },
90
- }
91
-
92
- const rules = normalizeValidationRules(stringTypeWithOptions)
93
- expect(rules).toHaveLength(1)
94
- const [rule] = rules
95
-
96
- expect(rule).toBeInstanceOf(RuleClass)
97
- expect(rule._rules).toMatchObject([
98
- {
99
- constraint: 'String',
100
- flag: 'type',
101
- },
102
- {
103
- constraint: ['blue', 'red'],
104
- flag: 'valid',
105
- },
106
- ])
107
- })
108
-
109
- it('converts schema list options with strings only to `rule.valid` constraints', () => {
110
- const stringTypeWithOptions: StringSchemaType = {
111
- jsonType: 'string',
112
- name: 'stringTypeWithOptions',
113
- options: {
114
- list: ['blue', 'red'],
115
- },
116
- }
117
-
118
- const rules = normalizeValidationRules(stringTypeWithOptions)
119
- expect(rules).toHaveLength(1)
120
- const [rule] = rules
121
-
122
- expect(rule).toBeInstanceOf(RuleClass)
123
- expect(rule._rules).toMatchObject([
124
- {
125
- constraint: 'String',
126
- flag: 'type',
127
- },
128
- {
129
- constraint: ['blue', 'red'],
130
- flag: 'valid',
131
- },
132
- ])
133
- })
134
-
135
- it('converts arrays of validation', () => {
136
- const coolNumberType: NumberSchemaType = {
137
- jsonType: 'number',
138
- name: 'coolNumber',
139
- validation: [(rule) => rule.greaterThan(3), RuleClass.number().lessThan(5)],
140
- }
141
-
142
- const rules = normalizeValidationRules(coolNumberType)
143
- expect(rules).toHaveLength(2)
144
- const [first, second] = rules
145
-
146
- expect(first).toBeInstanceOf(RuleClass)
147
- expect(first._rules).toMatchObject([
148
- {
149
- constraint: 'Number',
150
- flag: 'type',
151
- },
152
- {
153
- constraint: 3,
154
- flag: 'greaterThan',
155
- },
156
- ])
157
-
158
- expect(second).toBeInstanceOf(RuleClass)
159
- expect(second._rules).toMatchObject([
160
- {
161
- constraint: 'Number',
162
- flag: 'type',
163
- },
164
- {
165
- constraint: 5,
166
- flag: 'lessThan',
167
- },
168
- ])
169
- })
170
- })
@@ -1,118 +0,0 @@
1
- import {SchemaType, Rule, RuleTypeConstraint} from '@sanity/types'
2
- import RuleClass from '../Rule'
3
- import {slugValidator} from '../validators/slugValidator'
4
-
5
- const ruleConstraintTypes: {[P in Lowercase<RuleTypeConstraint>]: true} = {
6
- array: true,
7
- boolean: true,
8
- date: true,
9
- number: true,
10
- object: true,
11
- string: true,
12
- }
13
-
14
- const isRuleConstraint = (typeString: string): typeString is Lowercase<RuleTypeConstraint> =>
15
- typeString in ruleConstraintTypes
16
-
17
- function getTypeChain(type: SchemaType | undefined, visited: Set<SchemaType>): SchemaType[] {
18
- if (!type) return []
19
- if (visited.has(type)) return []
20
-
21
- visited.add(type)
22
-
23
- const next = type.type ? getTypeChain(type.type, visited) : []
24
- return [...next, type]
25
- }
26
-
27
- function baseRuleReducer(inputRule: Rule, type: SchemaType) {
28
- let baseRule = inputRule
29
-
30
- if (isRuleConstraint(type.jsonType)) {
31
- baseRule = baseRule.type(type.jsonType)
32
- }
33
-
34
- const typeOptionsList =
35
- // if type.options is truthy
36
- type?.options &&
37
- // and type.options is an object (non-null from the previous)
38
- typeof type.options === 'object' &&
39
- // and if `list` is in options
40
- 'list' in type.options &&
41
- // then finally access the list
42
- type.options.list
43
-
44
- if (Array.isArray(typeOptionsList)) {
45
- baseRule = baseRule.valid(
46
- typeOptionsList.map((option) => extractValueFromListOption(option, type))
47
- )
48
- }
49
-
50
- if (type.name === 'datetime') return baseRule.type('Date')
51
- if (type.name === 'date') return baseRule.type('Date')
52
- if (type.name === 'url') return baseRule.uri()
53
- if (type.name === 'slug') return baseRule.custom(slugValidator)
54
- if (type.name === 'reference') return baseRule.reference()
55
- if (type.name === 'email') return baseRule.email()
56
- return baseRule
57
- }
58
-
59
- function hasValueField(typeDef: SchemaType | undefined): boolean {
60
- if (!typeDef) return false
61
- if (!('fields' in typeDef) && typeDef.type) return hasValueField(typeDef.type)
62
- if (!('fields' in typeDef)) return false
63
- if (!Array.isArray(typeDef.fields)) return false
64
- return typeDef.fields.some((field) => field.name === 'value')
65
- }
66
-
67
- function extractValueFromListOption(option: unknown, typeDef: SchemaType): unknown {
68
- // If you define a `list` option with object items, where the item has a `value` field,
69
- // we don't want to treat that as the value but rather the surrounding object
70
- // This differs from the case where you have a title/value pair setup for a string/number, for instance
71
- if (typeDef.jsonType === 'object' && hasValueField(typeDef)) return option
72
-
73
- return (option as Record<string, unknown>).value === undefined
74
- ? option
75
- : (option as Record<string, unknown>).value
76
- }
77
-
78
- /**
79
- * Takes in `SchemaValidationValue` and returns an array of `Rule` instances.
80
- */
81
- export default function normalizeValidationRules(typeDef: SchemaType | undefined): Rule[] {
82
- if (!typeDef) {
83
- return []
84
- }
85
-
86
- const validation = typeDef.validation
87
-
88
- if (Array.isArray(validation)) {
89
- return validation.flatMap((i) =>
90
- normalizeValidationRules({
91
- ...typeDef,
92
- validation: i,
93
- })
94
- )
95
- }
96
-
97
- if (validation instanceof RuleClass) {
98
- return [validation]
99
- }
100
-
101
- const baseRule =
102
- // using an object + Object.values to de-dupe the type chain by type name
103
- Object.values(
104
- getTypeChain(typeDef, new Set()).reduce<Record<string, SchemaType>>((acc, type) => {
105
- acc[type.name] = type
106
- return acc
107
- }, {})
108
- ).reduce(baseRuleReducer, new RuleClass(typeDef))
109
-
110
- if (!validation) {
111
- return [baseRule]
112
- }
113
-
114
- return normalizeValidationRules({
115
- ...typeDef,
116
- validation: validation(baseRule),
117
- })
118
- }
@@ -1,21 +0,0 @@
1
- import {Path, isKeyedObject} from '@sanity/types'
2
-
3
- export default function pathToString(path: Path | undefined = []): string {
4
- return path.reduce<string>((target, segment, i) => {
5
- const segmentType = typeof segment
6
- if (segmentType === 'number') {
7
- return `${target}[${segment}]`
8
- }
9
-
10
- if (segmentType === 'string') {
11
- const separator = i === 0 ? '' : '.'
12
- return `${target}${separator}${segment}`
13
- }
14
-
15
- if (isKeyedObject(segment)) {
16
- return `${target}[_key=="${segment._key}"]`
17
- }
18
-
19
- throw new Error(`Unsupported path segment "${segment}"`)
20
- }, '')
21
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * Simple requestIdleCallback polyfill
3
- * Can be removed when all browsers support requestIdleCallback: https://caniuse.com/requestidlecallback
4
- * @param callback -
5
- * @param options -
6
- */
7
- const requestIdleCallbackShim: typeof window.requestIdleCallback = function requestIdleCallbackShim(
8
- callback,
9
- options?
10
- ): number {
11
- const start = Date.now()
12
- return window.setTimeout(() => {
13
- callback({
14
- didTimeout: false,
15
- timeRemaining() {
16
- return Math.max(0, Date.now() - start)
17
- },
18
- })
19
- }, 0)
20
- }
21
-
22
- const cancelIdleCallbackShim: typeof window.cancelIdleCallback = function cancelIdleCallbackShim(
23
- handle: number
24
- ): void {
25
- return window.clearTimeout(handle)
26
- }
27
-
28
- const win = typeof window === 'undefined' ? undefined : window
29
-
30
- export const requestIdleCallback = win?.requestIdleCallback || requestIdleCallbackShim
31
- export const cancelIdleCallback = win?.cancelIdleCallback || cancelIdleCallbackShim
@@ -1,27 +0,0 @@
1
- import typeString from './typeString'
2
-
3
- describe('typeString', () => {
4
- it('returns the a type string of built in types', () => {
5
- expect(typeString({})).toBe('Object')
6
- expect(
7
- typeString(function () {
8
- // intentionally blank
9
- })
10
- ).toBe('Function')
11
- expect(typeString(['hey'])).toBe('Array')
12
- expect(typeString('some string')).toBe('String')
13
- expect(typeString(false)).toBe('Boolean')
14
- expect(typeString(5)).toBe('Number')
15
- expect(typeString(new Date())).toBe('Date')
16
- })
17
-
18
- it('returns a type string string using the constructor', () => {
19
- class ExampleClass {}
20
- expect(typeString(new ExampleClass())).toBe('ExampleClass')
21
- })
22
-
23
- it('returns a type string for null or undefined', () => {
24
- expect(typeString(null)).toBe('null')
25
- expect(typeString(undefined)).toBe('undefined')
26
- })
27
- })
@@ -1,23 +0,0 @@
1
- // this file was adapted from a previous dependency `type-of-is`
2
- // https://github.com/stephenhandley/type-of-is/blob/7138a7e79f5af7c286bf8123f60843a91aaebf38/index.js
3
- const _toString = {}.toString
4
-
5
- const builtIns = [Object, Function, Array, String, Boolean, Number, Date, RegExp, Error]
6
-
7
- function isBuiltIn(_constructor: unknown) {
8
- for (let i = 0; i < builtIns.length; i++) {
9
- if (builtIns[i] === _constructor) return true
10
- }
11
- return false
12
- }
13
-
14
- export default function typeString(obj: unknown): string {
15
- // [object Blah] -> Blah
16
- const stringType = _toString.call(obj).slice(8, -1)
17
- if (obj === null || obj === undefined) return stringType.toLowerCase()
18
-
19
- // eslint-disable-next-line @typescript-eslint/ban-types
20
- const constructorType = (obj as object).constructor
21
- if (constructorType && !isBuiltIn(constructorType)) return constructorType.name
22
- return stringType
23
- }