valgen 4.1.0 → 4.2.1
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/rules/is-date.js +63 -21
- package/esm/rules/is-date.js +63 -21
- package/package.json +2 -2
- package/typings/rules/is-date.d.ts +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
# v4.2.1
|
|
2
|
+
[2023-11-15]
|
|
3
|
+
|
|
4
|
+
### Changes
|
|
5
|
+
|
|
6
|
+
* Fixed generating invalid date string ([`6407ac6`](https://github.com/panates/valgen/commit/6407ac6bd17bf84a8d031efe9b3998d58c5b7f8b))
|
|
7
|
+
|
|
8
|
+
# v4.2.0
|
|
9
|
+
[2023-11-15]
|
|
10
|
+
|
|
11
|
+
### Changes
|
|
12
|
+
|
|
13
|
+
* Removed "format" option and added "precision" option to isDate validator ([`2e332a6`](https://github.com/panates/valgen/commit/2e332a6fb9907e0b50f98a6dbcbbdfb3764af867))
|
|
14
|
+
* Added test for "label" option ([`162f41a`](https://github.com/panates/valgen/commit/162f41ac36762a146718c3efc4784bb33f48c955))
|
|
15
|
+
|
|
1
16
|
# v4.1.0
|
|
2
17
|
[2023-10-31]
|
|
3
18
|
|
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/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/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.1
|
|
4
|
+
"version": "4.2.1",
|
|
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"
|
|
@@ -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).
|