@sanity/validation 2.30.1-purple-unicorn.964 → 3.0.0-dev-preview.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/lib/dts/src/Rule.js +317 -312
- package/lib/dts/src/ValidationError.js +16 -16
- package/lib/dts/src/index.js +7 -7
- package/lib/dts/src/inferFromSchema.js +11 -11
- package/lib/dts/src/inferFromSchemaType.js +24 -24
- package/lib/dts/src/util/convertToValidationMarker.js +44 -53
- package/lib/dts/src/util/deepEquals.js +50 -49
- package/lib/dts/src/util/escapeRegex.js +4 -4
- package/lib/dts/src/util/normalizeValidationRules.js +87 -78
- package/lib/dts/src/util/normalizeValidationRules.test.d.ts +2 -2
- package/lib/dts/src/util/normalizeValidationRules.test.js +149 -149
- package/lib/dts/src/util/pathToString.js +16 -16
- package/lib/dts/src/util/typeString.js +17 -14
- package/lib/dts/src/util/typeString.test.d.ts +2 -2
- package/lib/dts/src/util/typeString.test.js +23 -24
- package/lib/dts/src/validateDocument.js +132 -157
- package/lib/dts/src/validateDocument.test.d.ts +2 -2
- package/lib/dts/src/validateDocument.test.js +664 -678
- package/lib/dts/src/validators/arrayValidator.js +75 -75
- package/lib/dts/src/validators/booleanValidator.js +11 -11
- package/lib/dts/src/validators/dateValidator.js +74 -68
- package/lib/dts/src/validators/genericValidator.js +89 -87
- package/lib/dts/src/validators/numberValidator.js +46 -48
- package/lib/dts/src/validators/objectValidator.js +47 -47
- package/lib/dts/src/validators/slugValidator.js +68 -74
- package/lib/dts/src/validators/stringValidator.js +93 -93
- package/lib/dts/test/array.test.d.ts +2 -2
- package/lib/dts/test/array.test.js +54 -78
- package/lib/dts/test/children.test.d.ts +2 -2
- package/lib/dts/test/children.test.js +69 -87
- package/lib/dts/test/createSchema.d.ts +6 -3
- package/lib/dts/test/createSchema.js +17 -17
- package/lib/dts/test/generics.test.d.ts +2 -2
- package/lib/dts/test/generics.test.js +59 -59
- package/lib/dts/test/infer.test.d.ts +2 -2
- package/lib/dts/test/infer.test.js +236 -285
- package/lib/dts/test/mocks/mockSanityClient.d.ts +4 -5
- package/lib/dts/test/mocks/mockSanityClient.d.ts.map +1 -1
- package/lib/dts/test/mocks/mockSanityClient.js +6 -6
- package/lib/dts/test/nullExport.d.ts +3 -3
- package/lib/dts/test/nullExport.js +2 -2
- package/lib/dts/test/numbers.test.d.ts +2 -2
- package/lib/dts/test/numbers.test.js +56 -62
- package/lib/dts/test/strings.test.d.ts +2 -2
- package/lib/dts/test/strings.test.js +99 -150
- package/lib/dts/tsconfig.lib.tsbuildinfo +1 -1
- package/lib/dts/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
import deepEquals from '../util/deepEquals'
|
|
2
|
-
import ValidationErrorClass from '../ValidationError'
|
|
3
|
-
import genericValidator from './genericValidator'
|
|
1
|
+
import deepEquals from '../util/deepEquals';
|
|
2
|
+
import ValidationErrorClass from '../ValidationError';
|
|
3
|
+
import genericValidator from './genericValidator';
|
|
4
4
|
const arrayValidators = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
return message || `Must have at least ${minLength} items`
|
|
11
|
-
},
|
|
12
|
-
max: (maxLength, value, message) => {
|
|
13
|
-
if (!value || value.length <= maxLength) {
|
|
14
|
-
return true
|
|
15
|
-
}
|
|
16
|
-
return message || `Must have at most ${maxLength} items`
|
|
17
|
-
},
|
|
18
|
-
length: (wantedLength, value, message) => {
|
|
19
|
-
if (!value || value.length === wantedLength) {
|
|
20
|
-
return true
|
|
21
|
-
}
|
|
22
|
-
return message || `Must have exactly ${wantedLength} items`
|
|
23
|
-
},
|
|
24
|
-
presence: (flag, value, message) => {
|
|
25
|
-
if (flag === 'required' && !value) {
|
|
26
|
-
return message || 'Required'
|
|
27
|
-
}
|
|
28
|
-
return true
|
|
29
|
-
},
|
|
30
|
-
valid: (allowedValues, values, message) => {
|
|
31
|
-
const valueType = typeof values
|
|
32
|
-
if (valueType === 'undefined') {
|
|
33
|
-
return true
|
|
34
|
-
}
|
|
35
|
-
const paths = []
|
|
36
|
-
for (let i = 0; i < values.length; i++) {
|
|
37
|
-
const value = values[i]
|
|
38
|
-
if (allowedValues.some((expected) => deepEquals(expected, value))) {
|
|
39
|
-
continue
|
|
40
|
-
}
|
|
41
|
-
const pathSegment = value && value._key ? {_key: value._key} : i
|
|
42
|
-
paths.push([pathSegment])
|
|
43
|
-
}
|
|
44
|
-
return paths.length === 0
|
|
45
|
-
? true
|
|
46
|
-
: new ValidationErrorClass(message || 'Value did not match any allowed values', {paths})
|
|
47
|
-
},
|
|
48
|
-
unique: (_unused, value, message) => {
|
|
49
|
-
const dupeIndices = []
|
|
50
|
-
if (!value) {
|
|
51
|
-
return true
|
|
52
|
-
}
|
|
53
|
-
for (let x = 0; x < value.length; x++) {
|
|
54
|
-
for (let y = x + 1; y < value.length; y++) {
|
|
55
|
-
const itemA = value[x]
|
|
56
|
-
const itemB = value[y]
|
|
57
|
-
if (!deepEquals(itemA, itemB)) {
|
|
58
|
-
continue
|
|
5
|
+
...genericValidator,
|
|
6
|
+
min: (minLength, value, message) => {
|
|
7
|
+
if (!value || value.length >= minLength) {
|
|
8
|
+
return true;
|
|
59
9
|
}
|
|
60
|
-
|
|
61
|
-
|
|
10
|
+
return message || `Must have at least ${minLength} items`;
|
|
11
|
+
},
|
|
12
|
+
max: (maxLength, value, message) => {
|
|
13
|
+
if (!value || value.length <= maxLength) {
|
|
14
|
+
return true;
|
|
62
15
|
}
|
|
63
|
-
|
|
64
|
-
|
|
16
|
+
return message || `Must have at most ${maxLength} items`;
|
|
17
|
+
},
|
|
18
|
+
length: (wantedLength, value, message) => {
|
|
19
|
+
if (!value || value.length === wantedLength) {
|
|
20
|
+
return true;
|
|
65
21
|
}
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
22
|
+
return message || `Must have exactly ${wantedLength} items`;
|
|
23
|
+
},
|
|
24
|
+
presence: (flag, value, message) => {
|
|
25
|
+
if (flag === 'required' && !value) {
|
|
26
|
+
return message || 'Required';
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
},
|
|
30
|
+
valid: (allowedValues, values, message) => {
|
|
31
|
+
const valueType = typeof values;
|
|
32
|
+
if (valueType === 'undefined') {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
const paths = [];
|
|
36
|
+
for (let i = 0; i < values.length; i++) {
|
|
37
|
+
const value = values[i];
|
|
38
|
+
if (allowedValues.some((expected) => deepEquals(expected, value))) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const pathSegment = value && value._key ? { _key: value._key } : i;
|
|
42
|
+
paths.push([pathSegment]);
|
|
43
|
+
}
|
|
44
|
+
return paths.length === 0
|
|
45
|
+
? true
|
|
46
|
+
: new ValidationErrorClass(message || 'Value did not match any allowed values', { paths });
|
|
47
|
+
},
|
|
48
|
+
unique: (_unused, value, message) => {
|
|
49
|
+
const dupeIndices = [];
|
|
50
|
+
if (!value) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
for (let x = 0; x < value.length; x++) {
|
|
54
|
+
for (let y = x + 1; y < value.length; y++) {
|
|
55
|
+
const itemA = value[x];
|
|
56
|
+
const itemB = value[y];
|
|
57
|
+
if (!deepEquals(itemA, itemB)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (dupeIndices.indexOf(x) === -1) {
|
|
61
|
+
dupeIndices.push(x);
|
|
62
|
+
}
|
|
63
|
+
if (dupeIndices.indexOf(y) === -1) {
|
|
64
|
+
dupeIndices.push(y);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const paths = dupeIndices.map((idx) => {
|
|
69
|
+
const item = value[idx];
|
|
70
|
+
const pathSegment = item && item._key ? { _key: item._key } : idx;
|
|
71
|
+
return [pathSegment];
|
|
72
|
+
});
|
|
73
|
+
return dupeIndices.length > 0
|
|
74
|
+
? new ValidationErrorClass(message || `Can't be a duplicate`, { paths })
|
|
75
|
+
: true;
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
export default arrayValidators;
|
|
79
|
+
//# sourceMappingURL=arrayValidator.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import genericValidator from './genericValidator'
|
|
1
|
+
import genericValidator from './genericValidator';
|
|
2
2
|
const booleanValidators = {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export default booleanValidators
|
|
12
|
-
//# sourceMappingURL=booleanValidator.js.map
|
|
3
|
+
...genericValidator,
|
|
4
|
+
presence: (flag, value, message) => {
|
|
5
|
+
if (flag === 'required' && typeof value !== 'boolean') {
|
|
6
|
+
return message || 'Required';
|
|
7
|
+
}
|
|
8
|
+
return true;
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
export default booleanValidators;
|
|
12
|
+
//# sourceMappingURL=booleanValidator.js.map
|
|
@@ -1,77 +1,83 @@
|
|
|
1
|
-
import formatDate from 'date-fns/format'
|
|
2
|
-
import genericValidator from './genericValidator'
|
|
1
|
+
import formatDate from 'date-fns/format';
|
|
2
|
+
import genericValidator from './genericValidator';
|
|
3
3
|
export function isRecord(obj) {
|
|
4
|
-
|
|
4
|
+
return typeof obj === 'object' && obj !== null && !Array.isArray(obj);
|
|
5
5
|
}
|
|
6
|
-
const isoDate =
|
|
7
|
-
/^(?:[-+]\d{2})?(?:\d{4}(?!\d{2}\b))(?:(-?)(?:(?:0[1-9]|1[0-2])(?:\1(?:[12]\d|0[1-9]|3[01]))?|W(?:[0-4]\d|5[0-2])(?:-?[1-7])?|(?:00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[1-6])))(?![T]$|[T][\d]+Z$)(?:[T\s](?:(?:(?:[01]\d|2[0-3])(?:(:?)[0-5]\d)?|24:?00)(?:[.,]\d+(?!:))?)(?:\2[0-5]\d(?:[.,]\d+)?)?(?:[Z]|(?:[+-])(?:[01]\d|2[0-3])(?::?[0-5]\d)?)?)?)?$/
|
|
6
|
+
const isoDate = /^(?:[-+]\d{2})?(?:\d{4}(?!\d{2}\b))(?:(-?)(?:(?:0[1-9]|1[0-2])(?:\1(?:[12]\d|0[1-9]|3[01]))?|W(?:[0-4]\d|5[0-2])(?:-?[1-7])?|(?:00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[1-6])))(?![T]$|[T][\d]+Z$)(?:[T\s](?:(?:(?:[01]\d|2[0-3])(?:(:?)[0-5]\d)?|24:?00)(?:[.,]\d+(?!:))?)(?:\2[0-5]\d(?:[.,]\d+)?)?(?:[Z]|(?:[+-])(?:[01]\d|2[0-3])(?::?[0-5]\d)?)?)?)?$/;
|
|
8
7
|
const getFormattedDate = (type = '', value, options) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
if (type === 'date') {
|
|
14
|
-
// If the type is date only
|
|
15
|
-
return formatDate(new Date(value), format)
|
|
16
|
-
}
|
|
17
|
-
// If the type is datetime
|
|
18
|
-
if (options && options.timeFormat) {
|
|
19
|
-
format += ` ${options.timeFormat}`
|
|
20
|
-
} else {
|
|
21
|
-
format += ' HH:mm'
|
|
22
|
-
}
|
|
23
|
-
return formatDate(new Date(value), format)
|
|
24
|
-
}
|
|
25
|
-
function parseDate(date, throwOnError = false) {
|
|
26
|
-
if (!date) return null
|
|
27
|
-
if (date === 'now') return new Date()
|
|
28
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
-
const parsed = new Date(date)
|
|
30
|
-
const isInvalid = isNaN(parsed.getTime())
|
|
31
|
-
if (isInvalid && throwOnError) {
|
|
32
|
-
throw new Error(`Unable to parse "${date}" to a date`)
|
|
33
|
-
}
|
|
34
|
-
return isInvalid ? null : parsed
|
|
35
|
-
}
|
|
36
|
-
const dateValidators = {
|
|
37
|
-
...genericValidator,
|
|
38
|
-
type: (_unused, value, message) => {
|
|
39
|
-
const strVal = `${value}`
|
|
40
|
-
if (!strVal || isoDate.test(value)) {
|
|
41
|
-
return true
|
|
8
|
+
let format = 'yyyy-MM-dd';
|
|
9
|
+
if (options && options.dateFormat) {
|
|
10
|
+
format = options.dateFormat;
|
|
42
11
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const dateVal = parseDate(value)
|
|
47
|
-
if (!dateVal) {
|
|
48
|
-
return true // `type()` should catch parse errors
|
|
12
|
+
if (type === 'date') {
|
|
13
|
+
// If the type is date only
|
|
14
|
+
return formatDate(new Date(value), format);
|
|
49
15
|
}
|
|
50
|
-
|
|
51
|
-
|
|
16
|
+
// If the type is datetime
|
|
17
|
+
if (options && options.timeFormat) {
|
|
18
|
+
format += ` ${options.timeFormat}`;
|
|
52
19
|
}
|
|
53
|
-
|
|
54
|
-
|
|
20
|
+
else {
|
|
21
|
+
format += ' HH:mm';
|
|
55
22
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (!context.type) {
|
|
69
|
-
throw new Error(`\`type\` was not provided in validation context.`)
|
|
23
|
+
return formatDate(new Date(value), format);
|
|
24
|
+
};
|
|
25
|
+
function parseDate(date, throwOnError = false) {
|
|
26
|
+
if (!date)
|
|
27
|
+
return null;
|
|
28
|
+
if (date === 'now')
|
|
29
|
+
return new Date();
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
const parsed = new Date(date);
|
|
32
|
+
const isInvalid = isNaN(parsed.getTime());
|
|
33
|
+
if (isInvalid && throwOnError) {
|
|
34
|
+
throw new Error(`Unable to parse "${date}" to a date`);
|
|
70
35
|
}
|
|
71
|
-
|
|
72
|
-
const date = getFormattedDate(context.type.name, maxDate, dateTimeOptions)
|
|
73
|
-
return message || `Must be at or before ${date}`
|
|
74
|
-
},
|
|
36
|
+
return isInvalid ? null : parsed;
|
|
75
37
|
}
|
|
76
|
-
|
|
77
|
-
|
|
38
|
+
const dateValidators = {
|
|
39
|
+
...genericValidator,
|
|
40
|
+
type: (_unused, value, message) => {
|
|
41
|
+
const strVal = `${value}`;
|
|
42
|
+
if (!strVal || isoDate.test(value)) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return message || 'Must be a valid ISO-8601 formatted date string';
|
|
46
|
+
},
|
|
47
|
+
min: (minDate, value, message, context) => {
|
|
48
|
+
const dateVal = parseDate(value);
|
|
49
|
+
if (!dateVal) {
|
|
50
|
+
return true; // `type()` should catch parse errors
|
|
51
|
+
}
|
|
52
|
+
if (!value || dateVal >= parseDate(minDate, true)) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (!context.type) {
|
|
56
|
+
throw new Error(`\`type\` was not provided in validation context.`);
|
|
57
|
+
}
|
|
58
|
+
const dateTimeOptions = isRecord(context.type.options)
|
|
59
|
+
? context.type.options
|
|
60
|
+
: {};
|
|
61
|
+
const date = getFormattedDate(context.type.name, minDate, dateTimeOptions);
|
|
62
|
+
return message || `Must be at or after ${date}`;
|
|
63
|
+
},
|
|
64
|
+
max: (maxDate, value, message, context) => {
|
|
65
|
+
const dateVal = parseDate(value);
|
|
66
|
+
if (!dateVal) {
|
|
67
|
+
return true; // `type()` should catch parse errors
|
|
68
|
+
}
|
|
69
|
+
if (!value || dateVal <= parseDate(maxDate, true)) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
if (!context.type) {
|
|
73
|
+
throw new Error(`\`type\` was not provided in validation context.`);
|
|
74
|
+
}
|
|
75
|
+
const dateTimeOptions = isRecord(context.type.options)
|
|
76
|
+
? context.type.options
|
|
77
|
+
: {};
|
|
78
|
+
const date = getFormattedDate(context.type.name, maxDate, dateTimeOptions);
|
|
79
|
+
return message || `Must be at or before ${date}`;
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
export default dateValidators;
|
|
83
|
+
//# sourceMappingURL=dateValidator.js.map
|
|
@@ -1,91 +1,93 @@
|
|
|
1
|
-
import typeString from '../util/typeString'
|
|
2
|
-
import deepEquals from '../util/deepEquals'
|
|
3
|
-
import pathToString from '../util/pathToString'
|
|
4
|
-
import ValidationErrorClass from '../ValidationError'
|
|
5
|
-
const SLOW_VALIDATOR_TIMEOUT = 5000
|
|
1
|
+
import typeString from '../util/typeString';
|
|
2
|
+
import deepEquals from '../util/deepEquals';
|
|
3
|
+
import pathToString from '../util/pathToString';
|
|
4
|
+
import ValidationErrorClass from '../ValidationError';
|
|
5
|
+
const SLOW_VALIDATOR_TIMEOUT = 5000;
|
|
6
6
|
const formatValidationErrors = (options) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} else if (options.results.length === 1) {
|
|
11
|
-
message = options.results[0]?.item.message
|
|
12
|
-
} else {
|
|
13
|
-
message = `[${options.results
|
|
14
|
-
.map((err) => err.item.message)
|
|
15
|
-
.join(` - ${options.operation} - `)}]`
|
|
16
|
-
}
|
|
17
|
-
return new ValidationErrorClass(message, {
|
|
18
|
-
children: options.results.length > 1 ? options.results : undefined,
|
|
19
|
-
operation: options.operation,
|
|
20
|
-
})
|
|
21
|
-
}
|
|
22
|
-
const genericValidators = {
|
|
23
|
-
type: (expected, value, message) => {
|
|
24
|
-
const actualType = typeString(value)
|
|
25
|
-
if (actualType !== expected && actualType !== 'undefined') {
|
|
26
|
-
return message || `Expected type "${expected}", got "${actualType}"`
|
|
27
|
-
}
|
|
28
|
-
return true
|
|
29
|
-
},
|
|
30
|
-
presence: (expected, value, message) => {
|
|
31
|
-
if (value === undefined && expected === 'required') {
|
|
32
|
-
return message || 'Value is required'
|
|
7
|
+
let message;
|
|
8
|
+
if (options.message) {
|
|
9
|
+
message = options.message;
|
|
33
10
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
all: async (children, value, message, context) => {
|
|
37
|
-
const resolved = await Promise.all(children.map((child) => child.validate(value, context)))
|
|
38
|
-
const results = resolved.flat()
|
|
39
|
-
if (!results.length) return true
|
|
40
|
-
return formatValidationErrors({
|
|
41
|
-
message,
|
|
42
|
-
results,
|
|
43
|
-
operation: 'AND',
|
|
44
|
-
})
|
|
45
|
-
},
|
|
46
|
-
either: async (children, value, message, context) => {
|
|
47
|
-
const resolved = await Promise.all(children.map((child) => child.validate(value, context)))
|
|
48
|
-
const results = resolved.flat()
|
|
49
|
-
// Read: There is at least one rule that matched
|
|
50
|
-
if (results.length < children.length) return true
|
|
51
|
-
return formatValidationErrors({
|
|
52
|
-
message,
|
|
53
|
-
results,
|
|
54
|
-
operation: 'OR',
|
|
55
|
-
})
|
|
56
|
-
},
|
|
57
|
-
valid: (allowedValues, actual, message) => {
|
|
58
|
-
const valueType = typeof actual
|
|
59
|
-
if (valueType === 'undefined') {
|
|
60
|
-
return true
|
|
11
|
+
else if (options.results.length === 1) {
|
|
12
|
+
message = options.results[0]?.item.message;
|
|
61
13
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
: 'Value did not match any allowed values'
|
|
67
|
-
return allowedValues.some((expected) => deepEquals(expected, actual))
|
|
68
|
-
? true
|
|
69
|
-
: message || defaultMessage
|
|
70
|
-
},
|
|
71
|
-
custom: async (fn, value, message, context) => {
|
|
72
|
-
const slowTimer = setTimeout(() => {
|
|
73
|
-
// eslint-disable-next-line no-console
|
|
74
|
-
console.warn(
|
|
75
|
-
`Custom validator at ${pathToString(
|
|
76
|
-
context.path
|
|
77
|
-
)} has taken more than ${SLOW_VALIDATOR_TIMEOUT}ms to respond`
|
|
78
|
-
)
|
|
79
|
-
}, SLOW_VALIDATOR_TIMEOUT)
|
|
80
|
-
let result
|
|
81
|
-
try {
|
|
82
|
-
result = await fn(value, context)
|
|
83
|
-
} finally {
|
|
84
|
-
clearTimeout(slowTimer)
|
|
14
|
+
else {
|
|
15
|
+
message = `[${options.results
|
|
16
|
+
.map((err) => err.item.message)
|
|
17
|
+
.join(` - ${options.operation} - `)}]`;
|
|
85
18
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
19
|
+
return new ValidationErrorClass(message, {
|
|
20
|
+
children: options.results.length > 1 ? options.results : undefined,
|
|
21
|
+
operation: options.operation,
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
const genericValidators = {
|
|
25
|
+
type: (expected, value, message) => {
|
|
26
|
+
const actualType = typeString(value);
|
|
27
|
+
if (actualType !== expected && actualType !== 'undefined') {
|
|
28
|
+
return message || `Expected type "${expected}", got "${actualType}"`;
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
},
|
|
32
|
+
presence: (expected, value, message) => {
|
|
33
|
+
if (value === undefined && expected === 'required') {
|
|
34
|
+
return message || 'Value is required';
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
},
|
|
38
|
+
all: async (children, value, message, context) => {
|
|
39
|
+
const resolved = await Promise.all(children.map((child) => child.validate(value, context)));
|
|
40
|
+
const results = resolved.flat();
|
|
41
|
+
if (!results.length)
|
|
42
|
+
return true;
|
|
43
|
+
return formatValidationErrors({
|
|
44
|
+
message,
|
|
45
|
+
results,
|
|
46
|
+
operation: 'AND',
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
either: async (children, value, message, context) => {
|
|
50
|
+
const resolved = await Promise.all(children.map((child) => child.validate(value, context)));
|
|
51
|
+
const results = resolved.flat();
|
|
52
|
+
// Read: There is at least one rule that matched
|
|
53
|
+
if (results.length < children.length)
|
|
54
|
+
return true;
|
|
55
|
+
return formatValidationErrors({
|
|
56
|
+
message,
|
|
57
|
+
results,
|
|
58
|
+
operation: 'OR',
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
valid: (allowedValues, actual, message) => {
|
|
62
|
+
const valueType = typeof actual;
|
|
63
|
+
if (valueType === 'undefined') {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
const value = (valueType === 'number' || valueType === 'string') && `${actual}`;
|
|
67
|
+
const strValue = value && value.length > 30 ? `${value.slice(0, 30)}…` : value;
|
|
68
|
+
const defaultMessage = value
|
|
69
|
+
? `Value "${strValue}" did not match any allowed values`
|
|
70
|
+
: 'Value did not match any allowed values';
|
|
71
|
+
return allowedValues.some((expected) => deepEquals(expected, actual))
|
|
72
|
+
? true
|
|
73
|
+
: message || defaultMessage;
|
|
74
|
+
},
|
|
75
|
+
custom: async (fn, value, message, context) => {
|
|
76
|
+
const slowTimer = setTimeout(() => {
|
|
77
|
+
// eslint-disable-next-line no-console
|
|
78
|
+
console.warn(`Custom validator at ${pathToString(context.path)} has taken more than ${SLOW_VALIDATOR_TIMEOUT}ms to respond`);
|
|
79
|
+
}, SLOW_VALIDATOR_TIMEOUT);
|
|
80
|
+
let result;
|
|
81
|
+
try {
|
|
82
|
+
result = await fn(value, context);
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
clearTimeout(slowTimer);
|
|
86
|
+
}
|
|
87
|
+
if (typeof result === 'string')
|
|
88
|
+
return message || result;
|
|
89
|
+
return result;
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
export default genericValidators;
|
|
93
|
+
//# sourceMappingURL=genericValidator.js.map
|
|
@@ -1,49 +1,47 @@
|
|
|
1
|
-
import genericValidator from './genericValidator'
|
|
2
|
-
const precisionRx = /(?:\.(\d+))?(?:[eE]([+-]?\d+))
|
|
1
|
+
import genericValidator from './genericValidator';
|
|
2
|
+
const precisionRx = /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/;
|
|
3
3
|
const numberValidators = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
export default numberValidators
|
|
49
|
-
//# sourceMappingURL=numberValidator.js.map
|
|
4
|
+
...genericValidator,
|
|
5
|
+
integer: (_unused, value, message) => {
|
|
6
|
+
if (!Number.isInteger(value)) {
|
|
7
|
+
return message || 'Must be an integer';
|
|
8
|
+
}
|
|
9
|
+
return true;
|
|
10
|
+
},
|
|
11
|
+
precision: (limit, value, message) => {
|
|
12
|
+
if (value === undefined)
|
|
13
|
+
return true;
|
|
14
|
+
const places = value.toString().match(precisionRx);
|
|
15
|
+
const decimals = Math.max((places[1] ? places[1].length : 0) - (places[2] ? parseInt(places[2], 10) : 0), 0);
|
|
16
|
+
if (decimals > limit) {
|
|
17
|
+
return message || `Max precision is ${limit}`;
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
},
|
|
21
|
+
min: (minNum, value, message) => {
|
|
22
|
+
if (value >= minNum) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
return message || `Must be greater than or equal ${minNum}`;
|
|
26
|
+
},
|
|
27
|
+
max: (maxNum, value, message) => {
|
|
28
|
+
if (value <= maxNum) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return message || `Must be less than or equal ${maxNum}`;
|
|
32
|
+
},
|
|
33
|
+
greaterThan: (num, value, message) => {
|
|
34
|
+
if (value > num) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
return message || `Must be greater than ${num}`;
|
|
38
|
+
},
|
|
39
|
+
lessThan: (maxNum, value, message) => {
|
|
40
|
+
if (value < maxNum) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return message || `Must be less than ${maxNum}`;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
export default numberValidators;
|
|
47
|
+
//# sourceMappingURL=numberValidator.js.map
|