valgen 4.0.1 → 4.2.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/CHANGELOG.md +15 -0
- package/cjs/core/context.js +2 -0
- package/cjs/rules/is-array.js +1 -1
- package/cjs/rules/is-bigint.js +4 -5
- package/cjs/rules/is-boolean.js +1 -1
- package/cjs/rules/is-date.js +63 -21
- package/cjs/rules/is-empty.js +23 -23
- package/cjs/rules/is-integer.js +1 -1
- package/cjs/rules/is-null.js +20 -6
- package/cjs/rules/is-number.js +1 -1
- package/cjs/rules/is-object-id.js +1 -1
- package/cjs/rules/is-object.js +1 -1
- package/cjs/rules/is-record.js +1 -1
- package/cjs/rules/is-string.js +1 -1
- package/cjs/rules/is-tuple.js +1 -1
- package/esm/core/context.js +2 -0
- package/esm/rules/is-array.js +1 -1
- package/esm/rules/is-bigint.js +4 -5
- package/esm/rules/is-boolean.js +1 -1
- package/esm/rules/is-date.js +63 -21
- package/esm/rules/is-empty.js +23 -23
- package/esm/rules/is-integer.js +1 -1
- package/esm/rules/is-null.js +17 -4
- package/esm/rules/is-number.js +1 -1
- package/esm/rules/is-object-id.js +1 -1
- package/esm/rules/is-object.js +1 -1
- package/esm/rules/is-record.js +1 -1
- package/esm/rules/is-string.js +1 -1
- package/esm/rules/is-tuple.js +1 -1
- package/package.json +2 -2
- package/typings/core/types.d.ts +1 -0
- package/typings/rules/is-date.d.ts +3 -2
- package/typings/rules/is-null.d.ts +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
# v4.2.0
|
|
2
|
+
[2023-11-15]
|
|
3
|
+
|
|
4
|
+
### Changes
|
|
5
|
+
|
|
6
|
+
* Removed "format" option and added "precision" option to isDate validator ([`2e332a6`](https://github.com/panates/valgen/commit/2e332a6fb9907e0b50f98a6dbcbbdfb3764af867))
|
|
7
|
+
* Added test for "label" option ([`162f41a`](https://github.com/panates/valgen/commit/162f41ac36762a146718c3efc4784bb33f48c955))
|
|
8
|
+
|
|
9
|
+
# v4.1.0
|
|
10
|
+
[2023-10-31]
|
|
11
|
+
|
|
12
|
+
### Changes
|
|
13
|
+
|
|
14
|
+
* Updated validation messages. ([`066fc4e`](https://github.com/panates/valgen/commit/066fc4e0f9fc7a0c0543572cf543c66084611135))
|
|
15
|
+
|
|
1
16
|
# v4.0.1
|
|
2
17
|
[2023-10-24]
|
|
3
18
|
|
package/cjs/core/context.js
CHANGED
|
@@ -15,6 +15,8 @@ class Context {
|
|
|
15
15
|
this.onFail = options.onFail;
|
|
16
16
|
if (options?.coerce != null)
|
|
17
17
|
this.coerce = options?.coerce;
|
|
18
|
+
if (options?.label != null)
|
|
19
|
+
this.label = options?.label;
|
|
18
20
|
}
|
|
19
21
|
fail(rule, message, value, details) {
|
|
20
22
|
const issue = (0, omit_undefined_js_1.omitUndefined)({
|
package/cjs/rules/is-array.js
CHANGED
|
@@ -12,7 +12,7 @@ function isArray(itemValidator, options) {
|
|
|
12
12
|
if (input != null && context.coerce && !Array.isArray(input))
|
|
13
13
|
input = [input];
|
|
14
14
|
if (!Array.isArray(input)) {
|
|
15
|
-
context.fail(_this, `{{label}}
|
|
15
|
+
context.fail(_this, `{{label}} must be an array`, input);
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
if (!itemValidator)
|
package/cjs/rules/is-bigint.js
CHANGED
|
@@ -9,13 +9,12 @@ const index_js_1 = require("../core/index.js");
|
|
|
9
9
|
*/
|
|
10
10
|
function isBigint(options) {
|
|
11
11
|
return (0, index_js_1.validator)('isBigint', function (input, context, _this) {
|
|
12
|
-
if (input != null && typeof input !== 'bigint' && context.coerce) {
|
|
13
|
-
if (typeof input === 'string' || typeof input === 'number')
|
|
14
|
-
input = BigInt(input);
|
|
15
|
-
}
|
|
16
12
|
if (typeof input === 'bigint')
|
|
17
13
|
return input;
|
|
18
|
-
|
|
14
|
+
if ((typeof input === 'number' && !isNaN(input)) ||
|
|
15
|
+
(typeof input === 'string' && context.coerce))
|
|
16
|
+
return BigInt(input);
|
|
17
|
+
context.fail(_this, `{{label}} must be an integer number`, input);
|
|
19
18
|
}, options);
|
|
20
19
|
}
|
|
21
20
|
exports.isBigint = isBigint;
|
package/cjs/rules/is-boolean.js
CHANGED
|
@@ -24,7 +24,7 @@ function isBoolean(options) {
|
|
|
24
24
|
}
|
|
25
25
|
if (typeof input === 'boolean')
|
|
26
26
|
return input;
|
|
27
|
-
context.fail(_this, `{{label}}
|
|
27
|
+
context.fail(_this, `{{label}} must be a boolean`, input);
|
|
28
28
|
}, options);
|
|
29
29
|
}
|
|
30
30
|
exports.isBoolean = isBoolean;
|
package/cjs/rules/is-date.js
CHANGED
|
@@ -7,31 +7,41 @@ exports.isDateString = exports.isDate = void 0;
|
|
|
7
7
|
const dayjs_1 = __importDefault(require("dayjs"));
|
|
8
8
|
const customParseFormat_1 = __importDefault(require("dayjs/plugin/customParseFormat"));
|
|
9
9
|
const index_js_1 = require("../core/index.js");
|
|
10
|
-
const object_utils_js_1 = require("../helpers/object.utils.js");
|
|
11
10
|
dayjs_1.default.extend(customParseFormat_1.default);
|
|
11
|
+
/* eslint-disable-next-line max-len */ // noinspection RegExpUnnecessaryNonCapturingGroup
|
|
12
|
+
const DATE_PATTERN = /^(\d{4})(?:-(0[0-9]|1[0-2]))?(?:-([0-2][0-9]|3[0-1]))?(?:[T ](([0-1][0-9]|2[0-4]):([0-5][0-9])(?::([0-5][0-9]))?(?:\.(\d{0,3}))?)?((?:[+-](0[0-9]|1[0-2])(?::(\d{2}))?)|Z)?)?$/;
|
|
12
13
|
/**
|
|
13
14
|
* Validates if value is instance of "Date".
|
|
14
15
|
* Converts input value to Date if coerce option is set to 'true'.
|
|
15
16
|
* @validator isDate
|
|
16
17
|
*/
|
|
17
18
|
function isDate(options) {
|
|
19
|
+
const precision = options?.precision;
|
|
18
20
|
return (0, index_js_1.validator)('isDate', function (input, context, _this) {
|
|
19
21
|
if (input != null && !(input instanceof Date) && context.coerce) {
|
|
20
|
-
if (typeof input === 'string') {
|
|
21
|
-
const d = (0, dayjs_1.default)(input
|
|
22
|
+
if (typeof input === 'string' && context.coerce) {
|
|
23
|
+
const d = (0, dayjs_1.default)(input);
|
|
22
24
|
if (d.isValid())
|
|
23
25
|
input = d.toDate();
|
|
24
26
|
}
|
|
25
27
|
else if (typeof input === 'number')
|
|
26
28
|
input = new Date(input);
|
|
27
29
|
}
|
|
28
|
-
if (input && input instanceof Date && !isNaN(input.getTime()))
|
|
30
|
+
if (input && input instanceof Date && !isNaN(input.getTime())) {
|
|
31
|
+
if (precision === 'year') {
|
|
32
|
+
input.setHours(0, 0, 0, 0);
|
|
33
|
+
input.setMonth(0, 1);
|
|
34
|
+
}
|
|
35
|
+
if (precision === 'month') {
|
|
36
|
+
input.setHours(0, 0, 0, 0);
|
|
37
|
+
input.setDate(1);
|
|
38
|
+
}
|
|
39
|
+
if (precision === 'date')
|
|
40
|
+
input.setHours(0, 0, 0, 0);
|
|
29
41
|
return input;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
: ''), input, { format: options?.format });
|
|
34
|
-
}, (0, object_utils_js_1.omitKeys)(options || {}, ['format']));
|
|
42
|
+
}
|
|
43
|
+
context.fail(_this, `{{label}} must be a Date instance or a date string`, input);
|
|
44
|
+
}, options);
|
|
35
45
|
}
|
|
36
46
|
exports.isDate = isDate;
|
|
37
47
|
/**
|
|
@@ -40,23 +50,55 @@ exports.isDate = isDate;
|
|
|
40
50
|
* @validator isDateString
|
|
41
51
|
*/
|
|
42
52
|
function isDateString(options) {
|
|
43
|
-
const
|
|
44
|
-
const
|
|
53
|
+
const precision = options?.precision;
|
|
54
|
+
const trim = options?.trim;
|
|
45
55
|
return (0, index_js_1.validator)('isDateString', function (input, context, _this) {
|
|
46
|
-
if (input
|
|
56
|
+
if (typeof input === 'string') {
|
|
47
57
|
const d = (0, dayjs_1.default)(input);
|
|
48
|
-
if (d.isValid())
|
|
49
|
-
|
|
58
|
+
if (d.isValid()) {
|
|
59
|
+
const m = DATE_PATTERN.exec(input);
|
|
60
|
+
if (m) {
|
|
61
|
+
if (!precision ||
|
|
62
|
+
precision === 'year' ||
|
|
63
|
+
(precision === 'month' && m[2]) ||
|
|
64
|
+
(precision === 'date' && m[2] && m[3]) ||
|
|
65
|
+
(precision === 'time' && m[2] && m[3] && m[4])) {
|
|
66
|
+
if (!context.coerce)
|
|
67
|
+
return input;
|
|
68
|
+
let s = m[1];
|
|
69
|
+
if (m[2])
|
|
70
|
+
s += '-' + m[2];
|
|
71
|
+
else
|
|
72
|
+
return s;
|
|
73
|
+
if (m[3])
|
|
74
|
+
s += '-' + m[3];
|
|
75
|
+
else
|
|
76
|
+
return s;
|
|
77
|
+
if (trim === 'time' || !m[4])
|
|
78
|
+
return s;
|
|
79
|
+
s += 'T' + m[4];
|
|
80
|
+
if (trim === 'timezone')
|
|
81
|
+
return s;
|
|
82
|
+
if (m[9])
|
|
83
|
+
s += '-' + m[9];
|
|
84
|
+
return s;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
50
88
|
}
|
|
51
|
-
else if (
|
|
52
|
-
const d = (0, dayjs_1.default)(input
|
|
89
|
+
else if (input != null) {
|
|
90
|
+
const d = (0, dayjs_1.default)(input);
|
|
53
91
|
if (d.isValid()) {
|
|
54
|
-
if (context.coerce
|
|
55
|
-
return
|
|
56
|
-
|
|
92
|
+
if (!context.coerce)
|
|
93
|
+
return input;
|
|
94
|
+
if (trim === 'timezone')
|
|
95
|
+
return d.millisecond() ? d.format('YYYY-MM-DDTHH:mm:ss.SSS') : d.format('YYYY-MM-DDTHH:mm:ss');
|
|
96
|
+
if (trim === 'time')
|
|
97
|
+
return d.format('YYYY-MM-DD');
|
|
98
|
+
return d.toISOString();
|
|
57
99
|
}
|
|
58
100
|
}
|
|
59
|
-
context.fail(_this, `{{label}} is not a valid date
|
|
60
|
-
},
|
|
101
|
+
context.fail(_this, `{{label}} is not a valid date string`, input, { ...options });
|
|
102
|
+
}, options);
|
|
61
103
|
}
|
|
62
104
|
exports.isDateString = isDateString;
|
package/cjs/rules/is-empty.js
CHANGED
|
@@ -8,29 +8,29 @@ const index_js_1 = require("../core/index.js");
|
|
|
8
8
|
*/
|
|
9
9
|
function isEmpty(options) {
|
|
10
10
|
return (0, index_js_1.validator)('isEmpty', function (input, context, _this) {
|
|
11
|
-
if (input
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
11
|
+
if (input == null)
|
|
12
|
+
return input;
|
|
13
|
+
if (typeof input === 'string') {
|
|
14
|
+
if (!input)
|
|
15
|
+
return input;
|
|
16
|
+
}
|
|
17
|
+
else if (Array.isArray(input)) {
|
|
18
|
+
if (!input.length)
|
|
19
|
+
return input;
|
|
20
|
+
}
|
|
21
|
+
else if (input instanceof Set) {
|
|
22
|
+
if (!input.size)
|
|
23
|
+
return input;
|
|
24
|
+
}
|
|
25
|
+
else if (input instanceof Map) {
|
|
26
|
+
if (!input.size)
|
|
27
|
+
return input;
|
|
28
|
+
}
|
|
29
|
+
else if (typeof input === 'object') {
|
|
30
|
+
if (!Object.keys(input).length)
|
|
31
|
+
return input;
|
|
32
32
|
}
|
|
33
|
-
context.fail(_this, `{{label}}
|
|
33
|
+
context.fail(_this, `{{label}} must be empty`, input);
|
|
34
34
|
}, options);
|
|
35
35
|
}
|
|
36
36
|
exports.isEmpty = isEmpty;
|
|
@@ -62,7 +62,7 @@ function isNotEmpty(options) {
|
|
|
62
62
|
return input;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
-
context.fail(_this, `{{label}}
|
|
65
|
+
context.fail(_this, `{{label}} mustn't be empty`, input);
|
|
66
66
|
}, options);
|
|
67
67
|
}
|
|
68
68
|
exports.isNotEmpty = isNotEmpty;
|
package/cjs/rules/is-integer.js
CHANGED
|
@@ -20,7 +20,7 @@ function isInteger(options) {
|
|
|
20
20
|
}
|
|
21
21
|
if (typeof input === 'number' && !isNaN(input) && Number.isInteger(input))
|
|
22
22
|
return input;
|
|
23
|
-
context.fail(_this, `{{label}}
|
|
23
|
+
context.fail(_this, `{{label}} must be an integer number`, input);
|
|
24
24
|
}, options);
|
|
25
25
|
}
|
|
26
26
|
exports.isInteger = isInteger;
|
package/cjs/rules/is-null.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isUndefined = exports.isDefined = exports.isNull = void 0;
|
|
3
|
+
exports.isUndefined = exports.isDefined = exports.isNullish = exports.isNull = void 0;
|
|
4
4
|
const index_js_1 = require("../core/index.js");
|
|
5
5
|
/**
|
|
6
6
|
* Validates if value is "null".
|
|
@@ -8,14 +8,28 @@ const index_js_1 = require("../core/index.js");
|
|
|
8
8
|
*/
|
|
9
9
|
function isNull(options) {
|
|
10
10
|
return (0, index_js_1.validator)('isNull', function (input, context, _this) {
|
|
11
|
-
if (context.coerce)
|
|
12
|
-
return null;
|
|
13
11
|
if (input === null)
|
|
14
12
|
return input;
|
|
15
|
-
context.
|
|
13
|
+
if (context.coerce)
|
|
14
|
+
return null;
|
|
15
|
+
context.fail(_this, `{{label}} must be null`, input);
|
|
16
16
|
}, options);
|
|
17
17
|
}
|
|
18
18
|
exports.isNull = isNull;
|
|
19
|
+
/**
|
|
20
|
+
* Validates if value is "null" or "undefined".
|
|
21
|
+
* @validator isNull
|
|
22
|
+
*/
|
|
23
|
+
function isNullish(options) {
|
|
24
|
+
return (0, index_js_1.validator)('isNullish', function (input, context, _this) {
|
|
25
|
+
if (input == null)
|
|
26
|
+
return input;
|
|
27
|
+
if (context.coerce)
|
|
28
|
+
return null;
|
|
29
|
+
context.fail(_this, `{{label}} must be null or undefined`, input);
|
|
30
|
+
}, options);
|
|
31
|
+
}
|
|
32
|
+
exports.isNullish = isNullish;
|
|
19
33
|
/**
|
|
20
34
|
* Validates if value is not "undefined" nor "null"
|
|
21
35
|
* @validator isDefined
|
|
@@ -24,7 +38,7 @@ function isDefined(options) {
|
|
|
24
38
|
return (0, index_js_1.validator)('is-defined', function (input, context, _this) {
|
|
25
39
|
if (input !== undefined)
|
|
26
40
|
return input;
|
|
27
|
-
context.fail(_this, `{{label}}
|
|
41
|
+
context.fail(_this, `{{label}} must be defined`, input);
|
|
28
42
|
}, options);
|
|
29
43
|
}
|
|
30
44
|
exports.isDefined = isDefined;
|
|
@@ -38,7 +52,7 @@ function isUndefined(options) {
|
|
|
38
52
|
return undefined;
|
|
39
53
|
if (input === undefined)
|
|
40
54
|
return;
|
|
41
|
-
context.fail(_this, `{{label}} defined`, input);
|
|
55
|
+
context.fail(_this, `{{label}} mustn\'t be defined`, input);
|
|
42
56
|
}, options);
|
|
43
57
|
}
|
|
44
58
|
exports.isUndefined = isUndefined;
|
package/cjs/rules/is-number.js
CHANGED
|
@@ -20,7 +20,7 @@ function isNumber(options) {
|
|
|
20
20
|
}
|
|
21
21
|
if (typeof input === 'number' && !isNaN(input))
|
|
22
22
|
return input;
|
|
23
|
-
context.fail(_this, `{{label}}
|
|
23
|
+
context.fail(_this, `{{label}} must be a number`, input);
|
|
24
24
|
}, options);
|
|
25
25
|
}
|
|
26
26
|
exports.isNumber = isNumber;
|
|
@@ -18,7 +18,7 @@ function isObjectId(options) {
|
|
|
18
18
|
typeof input.toHexString === 'function' &&
|
|
19
19
|
_isObjectIdValue(input.toHexString()))))
|
|
20
20
|
return input;
|
|
21
|
-
context.fail(_this, `{{label}}
|
|
21
|
+
context.fail(_this, `{{label}} must be an ObjectId`, input);
|
|
22
22
|
}, options);
|
|
23
23
|
}
|
|
24
24
|
exports.isObjectId = isObjectId;
|
package/cjs/rules/is-object.js
CHANGED
|
@@ -33,7 +33,7 @@ function isObject(schema, options) {
|
|
|
33
33
|
});
|
|
34
34
|
const _rule = (0, index_js_1.validator)('isObject', function (input, context, _this) {
|
|
35
35
|
if (!(input && typeof input === 'object')) {
|
|
36
|
-
context.fail(_this, `{{label}}
|
|
36
|
+
context.fail(_this, `{{label}} must be an object`, input);
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
const keys = [...Object.keys(input), ...Object.keys(schema)];
|
package/cjs/rules/is-record.js
CHANGED
|
@@ -10,7 +10,7 @@ const index_js_1 = require("../core/index.js");
|
|
|
10
10
|
function isRecord(keyRule, valueRule, options) {
|
|
11
11
|
return (0, index_js_1.validator)('isRecord', function (input, context, _this) {
|
|
12
12
|
if (!(input && typeof input === 'object')) {
|
|
13
|
-
context.fail(_this, `{{label}}
|
|
13
|
+
context.fail(_this, `{{label}} must be an object`, input);
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
16
|
const keyContext = context.extend();
|
package/cjs/rules/is-string.js
CHANGED
package/cjs/rules/is-tuple.js
CHANGED
|
@@ -7,7 +7,7 @@ function isTuple(items, options) {
|
|
|
7
7
|
if (input != null && context.coerce && !Array.isArray(input))
|
|
8
8
|
input = [input];
|
|
9
9
|
if (!Array.isArray(input)) {
|
|
10
|
-
context.fail(_this, `{{label}}
|
|
10
|
+
context.fail(_this, `{{label}} must be a tuple`, input);
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
13
|
const location = context.location || '';
|
package/esm/core/context.js
CHANGED
|
@@ -12,6 +12,8 @@ export class Context {
|
|
|
12
12
|
this.onFail = options.onFail;
|
|
13
13
|
if (options?.coerce != null)
|
|
14
14
|
this.coerce = options?.coerce;
|
|
15
|
+
if (options?.label != null)
|
|
16
|
+
this.label = options?.label;
|
|
15
17
|
}
|
|
16
18
|
fail(rule, message, value, details) {
|
|
17
19
|
const issue = omitUndefined({
|
package/esm/rules/is-array.js
CHANGED
|
@@ -9,7 +9,7 @@ export function isArray(itemValidator, options) {
|
|
|
9
9
|
if (input != null && context.coerce && !Array.isArray(input))
|
|
10
10
|
input = [input];
|
|
11
11
|
if (!Array.isArray(input)) {
|
|
12
|
-
context.fail(_this, `{{label}}
|
|
12
|
+
context.fail(_this, `{{label}} must be an array`, input);
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
15
|
if (!itemValidator)
|
package/esm/rules/is-bigint.js
CHANGED
|
@@ -6,12 +6,11 @@ import { validator } from '../core/index.js';
|
|
|
6
6
|
*/
|
|
7
7
|
export function isBigint(options) {
|
|
8
8
|
return validator('isBigint', function (input, context, _this) {
|
|
9
|
-
if (input != null && typeof input !== 'bigint' && context.coerce) {
|
|
10
|
-
if (typeof input === 'string' || typeof input === 'number')
|
|
11
|
-
input = BigInt(input);
|
|
12
|
-
}
|
|
13
9
|
if (typeof input === 'bigint')
|
|
14
10
|
return input;
|
|
15
|
-
|
|
11
|
+
if ((typeof input === 'number' && !isNaN(input)) ||
|
|
12
|
+
(typeof input === 'string' && context.coerce))
|
|
13
|
+
return BigInt(input);
|
|
14
|
+
context.fail(_this, `{{label}} must be an integer number`, input);
|
|
16
15
|
}, options);
|
|
17
16
|
}
|
package/esm/rules/is-boolean.js
CHANGED
package/esm/rules/is-date.js
CHANGED
|
@@ -1,31 +1,41 @@
|
|
|
1
1
|
import dayjs from 'dayjs';
|
|
2
2
|
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
|
3
3
|
import { validator } from '../core/index.js';
|
|
4
|
-
import { omitKeys } from '../helpers/object.utils.js';
|
|
5
4
|
dayjs.extend(customParseFormat);
|
|
5
|
+
/* eslint-disable-next-line max-len */ // noinspection RegExpUnnecessaryNonCapturingGroup
|
|
6
|
+
const DATE_PATTERN = /^(\d{4})(?:-(0[0-9]|1[0-2]))?(?:-([0-2][0-9]|3[0-1]))?(?:[T ](([0-1][0-9]|2[0-4]):([0-5][0-9])(?::([0-5][0-9]))?(?:\.(\d{0,3}))?)?((?:[+-](0[0-9]|1[0-2])(?::(\d{2}))?)|Z)?)?$/;
|
|
6
7
|
/**
|
|
7
8
|
* Validates if value is instance of "Date".
|
|
8
9
|
* Converts input value to Date if coerce option is set to 'true'.
|
|
9
10
|
* @validator isDate
|
|
10
11
|
*/
|
|
11
12
|
export function isDate(options) {
|
|
13
|
+
const precision = options?.precision;
|
|
12
14
|
return validator('isDate', function (input, context, _this) {
|
|
13
15
|
if (input != null && !(input instanceof Date) && context.coerce) {
|
|
14
|
-
if (typeof input === 'string') {
|
|
15
|
-
const d = dayjs(input
|
|
16
|
+
if (typeof input === 'string' && context.coerce) {
|
|
17
|
+
const d = dayjs(input);
|
|
16
18
|
if (d.isValid())
|
|
17
19
|
input = d.toDate();
|
|
18
20
|
}
|
|
19
21
|
else if (typeof input === 'number')
|
|
20
22
|
input = new Date(input);
|
|
21
23
|
}
|
|
22
|
-
if (input && input instanceof Date && !isNaN(input.getTime()))
|
|
24
|
+
if (input && input instanceof Date && !isNaN(input.getTime())) {
|
|
25
|
+
if (precision === 'year') {
|
|
26
|
+
input.setHours(0, 0, 0, 0);
|
|
27
|
+
input.setMonth(0, 1);
|
|
28
|
+
}
|
|
29
|
+
if (precision === 'month') {
|
|
30
|
+
input.setHours(0, 0, 0, 0);
|
|
31
|
+
input.setDate(1);
|
|
32
|
+
}
|
|
33
|
+
if (precision === 'date')
|
|
34
|
+
input.setHours(0, 0, 0, 0);
|
|
23
35
|
return input;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
: ''), input, { format: options?.format });
|
|
28
|
-
}, omitKeys(options || {}, ['format']));
|
|
36
|
+
}
|
|
37
|
+
context.fail(_this, `{{label}} must be a Date instance or a date string`, input);
|
|
38
|
+
}, options);
|
|
29
39
|
}
|
|
30
40
|
/**
|
|
31
41
|
* Validates if value is DFS (date formatted string).
|
|
@@ -33,22 +43,54 @@ export function isDate(options) {
|
|
|
33
43
|
* @validator isDateString
|
|
34
44
|
*/
|
|
35
45
|
export function isDateString(options) {
|
|
36
|
-
const
|
|
37
|
-
const
|
|
46
|
+
const precision = options?.precision;
|
|
47
|
+
const trim = options?.trim;
|
|
38
48
|
return validator('isDateString', function (input, context, _this) {
|
|
39
|
-
if (input
|
|
49
|
+
if (typeof input === 'string') {
|
|
40
50
|
const d = dayjs(input);
|
|
41
|
-
if (d.isValid())
|
|
42
|
-
|
|
51
|
+
if (d.isValid()) {
|
|
52
|
+
const m = DATE_PATTERN.exec(input);
|
|
53
|
+
if (m) {
|
|
54
|
+
if (!precision ||
|
|
55
|
+
precision === 'year' ||
|
|
56
|
+
(precision === 'month' && m[2]) ||
|
|
57
|
+
(precision === 'date' && m[2] && m[3]) ||
|
|
58
|
+
(precision === 'time' && m[2] && m[3] && m[4])) {
|
|
59
|
+
if (!context.coerce)
|
|
60
|
+
return input;
|
|
61
|
+
let s = m[1];
|
|
62
|
+
if (m[2])
|
|
63
|
+
s += '-' + m[2];
|
|
64
|
+
else
|
|
65
|
+
return s;
|
|
66
|
+
if (m[3])
|
|
67
|
+
s += '-' + m[3];
|
|
68
|
+
else
|
|
69
|
+
return s;
|
|
70
|
+
if (trim === 'time' || !m[4])
|
|
71
|
+
return s;
|
|
72
|
+
s += 'T' + m[4];
|
|
73
|
+
if (trim === 'timezone')
|
|
74
|
+
return s;
|
|
75
|
+
if (m[9])
|
|
76
|
+
s += '-' + m[9];
|
|
77
|
+
return s;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
43
81
|
}
|
|
44
|
-
else if (
|
|
45
|
-
const d = dayjs(input
|
|
82
|
+
else if (input != null) {
|
|
83
|
+
const d = dayjs(input);
|
|
46
84
|
if (d.isValid()) {
|
|
47
|
-
if (context.coerce
|
|
48
|
-
return
|
|
49
|
-
|
|
85
|
+
if (!context.coerce)
|
|
86
|
+
return input;
|
|
87
|
+
if (trim === 'timezone')
|
|
88
|
+
return d.millisecond() ? d.format('YYYY-MM-DDTHH:mm:ss.SSS') : d.format('YYYY-MM-DDTHH:mm:ss');
|
|
89
|
+
if (trim === 'time')
|
|
90
|
+
return d.format('YYYY-MM-DD');
|
|
91
|
+
return d.toISOString();
|
|
50
92
|
}
|
|
51
93
|
}
|
|
52
|
-
context.fail(_this, `{{label}} is not a valid date
|
|
53
|
-
},
|
|
94
|
+
context.fail(_this, `{{label}} is not a valid date string`, input, { ...options });
|
|
95
|
+
}, options);
|
|
54
96
|
}
|
package/esm/rules/is-empty.js
CHANGED
|
@@ -5,29 +5,29 @@ import { validator } from '../core/index.js';
|
|
|
5
5
|
*/
|
|
6
6
|
export function isEmpty(options) {
|
|
7
7
|
return validator('isEmpty', function (input, context, _this) {
|
|
8
|
-
if (input
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
8
|
+
if (input == null)
|
|
9
|
+
return input;
|
|
10
|
+
if (typeof input === 'string') {
|
|
11
|
+
if (!input)
|
|
12
|
+
return input;
|
|
13
|
+
}
|
|
14
|
+
else if (Array.isArray(input)) {
|
|
15
|
+
if (!input.length)
|
|
16
|
+
return input;
|
|
17
|
+
}
|
|
18
|
+
else if (input instanceof Set) {
|
|
19
|
+
if (!input.size)
|
|
20
|
+
return input;
|
|
21
|
+
}
|
|
22
|
+
else if (input instanceof Map) {
|
|
23
|
+
if (!input.size)
|
|
24
|
+
return input;
|
|
25
|
+
}
|
|
26
|
+
else if (typeof input === 'object') {
|
|
27
|
+
if (!Object.keys(input).length)
|
|
28
|
+
return input;
|
|
29
29
|
}
|
|
30
|
-
context.fail(_this, `{{label}}
|
|
30
|
+
context.fail(_this, `{{label}} must be empty`, input);
|
|
31
31
|
}, options);
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
@@ -58,6 +58,6 @@ export function isNotEmpty(options) {
|
|
|
58
58
|
return input;
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
-
context.fail(_this, `{{label}}
|
|
61
|
+
context.fail(_this, `{{label}} mustn't be empty`, input);
|
|
62
62
|
}, options);
|
|
63
63
|
}
|
package/esm/rules/is-integer.js
CHANGED
|
@@ -17,6 +17,6 @@ export function isInteger(options) {
|
|
|
17
17
|
}
|
|
18
18
|
if (typeof input === 'number' && !isNaN(input) && Number.isInteger(input))
|
|
19
19
|
return input;
|
|
20
|
-
context.fail(_this, `{{label}}
|
|
20
|
+
context.fail(_this, `{{label}} must be an integer number`, input);
|
|
21
21
|
}, options);
|
|
22
22
|
}
|
package/esm/rules/is-null.js
CHANGED
|
@@ -5,11 +5,24 @@ import { validator } from '../core/index.js';
|
|
|
5
5
|
*/
|
|
6
6
|
export function isNull(options) {
|
|
7
7
|
return validator('isNull', function (input, context, _this) {
|
|
8
|
+
if (input === null)
|
|
9
|
+
return input;
|
|
8
10
|
if (context.coerce)
|
|
9
11
|
return null;
|
|
10
|
-
|
|
12
|
+
context.fail(_this, `{{label}} must be null`, input);
|
|
13
|
+
}, options);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Validates if value is "null" or "undefined".
|
|
17
|
+
* @validator isNull
|
|
18
|
+
*/
|
|
19
|
+
export function isNullish(options) {
|
|
20
|
+
return validator('isNullish', function (input, context, _this) {
|
|
21
|
+
if (input == null)
|
|
11
22
|
return input;
|
|
12
|
-
context.
|
|
23
|
+
if (context.coerce)
|
|
24
|
+
return null;
|
|
25
|
+
context.fail(_this, `{{label}} must be null or undefined`, input);
|
|
13
26
|
}, options);
|
|
14
27
|
}
|
|
15
28
|
/**
|
|
@@ -20,7 +33,7 @@ export function isDefined(options) {
|
|
|
20
33
|
return validator('is-defined', function (input, context, _this) {
|
|
21
34
|
if (input !== undefined)
|
|
22
35
|
return input;
|
|
23
|
-
context.fail(_this, `{{label}}
|
|
36
|
+
context.fail(_this, `{{label}} must be defined`, input);
|
|
24
37
|
}, options);
|
|
25
38
|
}
|
|
26
39
|
/**
|
|
@@ -33,6 +46,6 @@ export function isUndefined(options) {
|
|
|
33
46
|
return undefined;
|
|
34
47
|
if (input === undefined)
|
|
35
48
|
return;
|
|
36
|
-
context.fail(_this, `{{label}} defined`, input);
|
|
49
|
+
context.fail(_this, `{{label}} mustn\'t be defined`, input);
|
|
37
50
|
}, options);
|
|
38
51
|
}
|
package/esm/rules/is-number.js
CHANGED
|
@@ -12,7 +12,7 @@ export function isObjectId(options) {
|
|
|
12
12
|
typeof input.toHexString === 'function' &&
|
|
13
13
|
_isObjectIdValue(input.toHexString()))))
|
|
14
14
|
return input;
|
|
15
|
-
context.fail(_this, `{{label}}
|
|
15
|
+
context.fail(_this, `{{label}} must be an ObjectId`, input);
|
|
16
16
|
}, options);
|
|
17
17
|
}
|
|
18
18
|
function _isObjectIdValue(input) {
|
package/esm/rules/is-object.js
CHANGED
|
@@ -30,7 +30,7 @@ export function isObject(schema, options) {
|
|
|
30
30
|
});
|
|
31
31
|
const _rule = validator('isObject', function (input, context, _this) {
|
|
32
32
|
if (!(input && typeof input === 'object')) {
|
|
33
|
-
context.fail(_this, `{{label}}
|
|
33
|
+
context.fail(_this, `{{label}} must be an object`, input);
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
36
|
const keys = [...Object.keys(input), ...Object.keys(schema)];
|
package/esm/rules/is-record.js
CHANGED
|
@@ -7,7 +7,7 @@ import { validator, } from '../core/index.js';
|
|
|
7
7
|
export function isRecord(keyRule, valueRule, options) {
|
|
8
8
|
return validator('isRecord', function (input, context, _this) {
|
|
9
9
|
if (!(input && typeof input === 'object')) {
|
|
10
|
-
context.fail(_this, `{{label}}
|
|
10
|
+
context.fail(_this, `{{label}} must be an object`, input);
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
13
|
const keyContext = context.extend();
|
package/esm/rules/is-string.js
CHANGED
|
@@ -18,7 +18,7 @@ export function isString(options) {
|
|
|
18
18
|
}
|
|
19
19
|
if (typeof input === 'string')
|
|
20
20
|
return input;
|
|
21
|
-
context.fail(_this, `{{label}}
|
|
21
|
+
context.fail(_this, `{{label}} must be a string`, input);
|
|
22
22
|
}, options);
|
|
23
23
|
}
|
|
24
24
|
export function stringReplace(searchValue, replacer) {
|
package/esm/rules/is-tuple.js
CHANGED
|
@@ -4,7 +4,7 @@ export function isTuple(items, options) {
|
|
|
4
4
|
if (input != null && context.coerce && !Array.isArray(input))
|
|
5
5
|
input = [input];
|
|
6
6
|
if (!Array.isArray(input)) {
|
|
7
|
-
context.fail(_this, `{{label}}
|
|
7
|
+
context.fail(_this, `{{label}} must be a tuple`, input);
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
10
|
const location = context.location || '';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "valgen",
|
|
3
3
|
"description": "Fast runtime type validator, converter and io (encoding/decoding) library",
|
|
4
|
-
"version": "4.0
|
|
4
|
+
"version": "4.2.0",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Eray Hanoglu <e.hanoglu@panates.com>"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"url": "https://github.com/panates/valgen.git"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@types/validator": "^13.11.
|
|
15
|
+
"@types/validator": "^13.11.6",
|
|
16
16
|
"dayjs": "^2.0.0-alpha.4",
|
|
17
17
|
"ts-gems": "^2.5.0",
|
|
18
18
|
"validator": "^13.11.0"
|
package/typings/core/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ValidationOptions } from '../core/index.js';
|
|
2
2
|
export interface IsDateOptions extends ValidationOptions {
|
|
3
|
-
|
|
3
|
+
precision?: 'year' | 'month' | 'date' | 'time';
|
|
4
4
|
}
|
|
5
5
|
/**
|
|
6
6
|
* Validates if value is instance of "Date".
|
|
@@ -9,7 +9,8 @@ export interface IsDateOptions extends ValidationOptions {
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function isDate(options?: IsDateOptions): import("../core/validator.js").Validator<Date, string | number | Date, import("../core/types.js").ExecutionOptions>;
|
|
11
11
|
export interface IsDateStringOptions extends ValidationOptions {
|
|
12
|
-
|
|
12
|
+
precision?: 'year' | 'month' | 'date' | 'time';
|
|
13
|
+
trim?: 'time' | 'timezone';
|
|
13
14
|
}
|
|
14
15
|
/**
|
|
15
16
|
* Validates if value is DFS (date formatted string).
|
|
@@ -4,6 +4,11 @@ import { ValidationOptions } from '../core/index.js';
|
|
|
4
4
|
* @validator isNull
|
|
5
5
|
*/
|
|
6
6
|
export declare function isNull(options?: ValidationOptions): import("../core/validator.js").Validator<null, unknown, import("../core/types.js").ExecutionOptions>;
|
|
7
|
+
/**
|
|
8
|
+
* Validates if value is "null" or "undefined".
|
|
9
|
+
* @validator isNull
|
|
10
|
+
*/
|
|
11
|
+
export declare function isNullish(options?: ValidationOptions): import("../core/validator.js").Validator<null, unknown, import("../core/types.js").ExecutionOptions>;
|
|
7
12
|
/**
|
|
8
13
|
* Validates if value is not "undefined" nor "null"
|
|
9
14
|
* @validator isDefined
|