@theshelf/validation-driver-zod 0.4.5 → 0.5.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/dist/Zod.js +69 -72
- package/package.json +5 -4
package/dist/Zod.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { ValidationResult,
|
|
2
|
+
import { ValidationResult, MAX_EMAIL_LENGTH, MAX_URL_LENGTH } from '@theshelf/validation';
|
|
3
3
|
// Zod is so type heavy that we've chosen for inferred types to be used.
|
|
4
4
|
// This is a trade-off between readability and verbosity.
|
|
5
5
|
export default class Zod {
|
|
6
|
-
#
|
|
6
|
+
#validators = new Map();
|
|
7
7
|
constructor() {
|
|
8
|
-
this.#
|
|
9
|
-
this.#
|
|
10
|
-
this.#
|
|
11
|
-
this.#
|
|
12
|
-
this.#
|
|
13
|
-
this.#
|
|
14
|
-
this.#
|
|
15
|
-
this.#
|
|
16
|
-
this.#
|
|
17
|
-
this.#
|
|
8
|
+
this.#validators.set('string', (constraints, required) => this.#validateString(constraints, required));
|
|
9
|
+
this.#validators.set('number', (constraints, required) => this.#validateNumber(constraints, required));
|
|
10
|
+
this.#validators.set('boolean', (constraints, required) => this.#validateBoolean(constraints, required));
|
|
11
|
+
this.#validators.set('date', (constraints, required) => this.#validateDate(constraints, required));
|
|
12
|
+
this.#validators.set('datetime', (constraints, required) => this.#validateDateTime(constraints, required));
|
|
13
|
+
this.#validators.set('uuid', (constraints, required) => this.#validateUuid(constraints, required));
|
|
14
|
+
this.#validators.set('email', (constraints, required) => this.#validateEmail(constraints, required));
|
|
15
|
+
this.#validators.set('array', (constraints, required) => this.#validateArray(constraints, required));
|
|
16
|
+
this.#validators.set('url', (constraints, required) => this.#validateUrl(constraints, required));
|
|
17
|
+
this.#validators.set('enum', (constraints, required) => this.#validateEnum(constraints, required));
|
|
18
18
|
}
|
|
19
19
|
get name() { return Zod.name; }
|
|
20
20
|
validate(data, schema) {
|
|
@@ -30,89 +30,86 @@ export default class Zod {
|
|
|
30
30
|
#buildValidator(schema) {
|
|
31
31
|
return Object.entries(schema)
|
|
32
32
|
.reduce((partialSchema, [key, value]) => {
|
|
33
|
-
const
|
|
34
|
-
return partialSchema.extend({ [key]:
|
|
33
|
+
const fieldValidator = this.#getFieldValidator(value);
|
|
34
|
+
return partialSchema.extend({ [key]: fieldValidator });
|
|
35
35
|
}, z.object({})).strict();
|
|
36
36
|
}
|
|
37
|
-
#
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
#getFieldValidator(validation) {
|
|
38
|
+
const required = validation.required === true;
|
|
39
|
+
for (const key of Object.keys(validation)) {
|
|
40
|
+
const type = key.toLowerCase();
|
|
41
|
+
const validator = this.#validators.get(type);
|
|
42
|
+
if (validator === undefined)
|
|
40
43
|
continue;
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
throw new UnknownValidator(key);
|
|
44
|
-
}
|
|
45
|
-
return validator(validation);
|
|
44
|
+
const constraints = validation[key];
|
|
45
|
+
return validator(constraints, required);
|
|
46
46
|
}
|
|
47
47
|
return z.never();
|
|
48
48
|
}
|
|
49
|
-
#validateString(
|
|
49
|
+
#validateString(constraints, required) {
|
|
50
50
|
let validation = z.string();
|
|
51
|
-
if (
|
|
52
|
-
validation = validation.min(
|
|
53
|
-
if (
|
|
54
|
-
validation = validation.max(
|
|
55
|
-
if (
|
|
56
|
-
validation = validation.regex(new RegExp(
|
|
57
|
-
return this.#checkRequired(
|
|
58
|
-
}
|
|
59
|
-
#validateNumber(
|
|
51
|
+
if (constraints.minLength !== undefined)
|
|
52
|
+
validation = validation.min(constraints.minLength);
|
|
53
|
+
if (constraints.maxLength !== undefined)
|
|
54
|
+
validation = validation.max(constraints.maxLength);
|
|
55
|
+
if (constraints.pattern !== undefined)
|
|
56
|
+
validation = validation.regex(new RegExp(constraints.pattern));
|
|
57
|
+
return this.#checkRequired(validation, required);
|
|
58
|
+
}
|
|
59
|
+
#validateNumber(constraints, required) {
|
|
60
60
|
let validation = z.number();
|
|
61
|
-
if (
|
|
62
|
-
validation = validation.min(
|
|
63
|
-
if (
|
|
64
|
-
validation = validation.max(
|
|
65
|
-
return this.#checkRequired(
|
|
61
|
+
if (constraints.minValue !== undefined)
|
|
62
|
+
validation = validation.min(constraints.minValue);
|
|
63
|
+
if (constraints.maxValue !== undefined)
|
|
64
|
+
validation = validation.max(constraints.maxValue);
|
|
65
|
+
return this.#checkRequired(validation, required);
|
|
66
66
|
}
|
|
67
|
-
#validateBoolean(
|
|
67
|
+
#validateBoolean(constraints, required) {
|
|
68
68
|
const validation = z.boolean();
|
|
69
|
-
return this.#checkRequired(
|
|
69
|
+
return this.#checkRequired(validation, required);
|
|
70
70
|
}
|
|
71
|
-
#validateDate(
|
|
71
|
+
#validateDate(constraints, required) {
|
|
72
72
|
const validation = z.iso.date();
|
|
73
|
-
return this.#checkRequired(
|
|
73
|
+
return this.#checkRequired(validation, required);
|
|
74
74
|
}
|
|
75
|
-
#validateDateTime(
|
|
75
|
+
#validateDateTime(constraints, required) {
|
|
76
76
|
const validation = z.iso.datetime();
|
|
77
|
-
return this.#checkRequired(
|
|
77
|
+
return this.#checkRequired(validation, required);
|
|
78
78
|
}
|
|
79
|
-
#validateUuid(
|
|
79
|
+
#validateUuid(constraints, required) {
|
|
80
80
|
const validation = z.uuid();
|
|
81
|
-
return this.#checkRequired(
|
|
81
|
+
return this.#checkRequired(validation, required);
|
|
82
82
|
}
|
|
83
|
-
#validateEmail(
|
|
83
|
+
#validateEmail(constraints, required) {
|
|
84
84
|
const validation = z.email().max(MAX_EMAIL_LENGTH);
|
|
85
|
-
return this.#checkRequired(
|
|
86
|
-
}
|
|
87
|
-
#validateArray(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
#validateUrl(value) {
|
|
85
|
+
return this.#checkRequired(validation, required);
|
|
86
|
+
}
|
|
87
|
+
#validateArray(constraints, required) {
|
|
88
|
+
const itemValidator = this.#getFieldValidator(constraints);
|
|
89
|
+
let validation = z.array(itemValidator);
|
|
90
|
+
if (constraints.minLength !== undefined)
|
|
91
|
+
validation = validation.min(constraints.minLength);
|
|
92
|
+
if (constraints.maxLength !== undefined)
|
|
93
|
+
validation = validation.max(constraints.maxLength);
|
|
94
|
+
return this.#checkRequired(validation, required);
|
|
95
|
+
}
|
|
96
|
+
#validateUrl(constraints, required) {
|
|
98
97
|
let validation = z.url().max(MAX_URL_LENGTH);
|
|
99
|
-
if (
|
|
100
|
-
const escapedProtocols =
|
|
98
|
+
if (constraints.protocols !== undefined) {
|
|
99
|
+
const escapedProtocols = constraints.protocols.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
|
|
101
100
|
const expression = escapedProtocols.join('|');
|
|
102
101
|
validation = validation.regex(new RegExp(`^(${expression}):.*`));
|
|
103
102
|
}
|
|
104
|
-
return this.#checkRequired(
|
|
103
|
+
return this.#checkRequired(validation, required);
|
|
105
104
|
}
|
|
106
|
-
#validateEnum(
|
|
107
|
-
const validation =
|
|
105
|
+
#validateEnum(constraints, required) {
|
|
106
|
+
const validation = constraints.values === undefined
|
|
108
107
|
? z.enum([])
|
|
109
|
-
: z.enum(
|
|
110
|
-
return this.#checkRequired(
|
|
108
|
+
: z.enum(constraints.values);
|
|
109
|
+
return this.#checkRequired(validation, required);
|
|
111
110
|
}
|
|
112
|
-
#checkRequired(
|
|
113
|
-
return
|
|
114
|
-
? validation
|
|
115
|
-
: validation.optional();
|
|
111
|
+
#checkRequired(validation, required) {
|
|
112
|
+
return required ? validation : validation.optional();
|
|
116
113
|
}
|
|
117
114
|
#getMessages(issues, schema) {
|
|
118
115
|
const messages = new Map();
|
|
@@ -136,7 +133,7 @@ export default class Zod {
|
|
|
136
133
|
}
|
|
137
134
|
}
|
|
138
135
|
#getMessageByField(path, schema) {
|
|
139
|
-
const
|
|
140
|
-
return
|
|
136
|
+
const validation = schema[path];
|
|
137
|
+
return validation?.message ?? 'Invalid field';
|
|
141
138
|
}
|
|
142
139
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theshelf/validation-driver-zod",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "git+https://github.com/MaskingTechnology/theshelf.git"
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"test-coverage": "vitest run --coverage",
|
|
15
15
|
"lint": "eslint",
|
|
16
16
|
"review": "npm run build && npm run lint && npm run test",
|
|
17
|
-
"prepublishOnly": "npm run clean && npm run build"
|
|
17
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
18
|
+
"link": "npm link"
|
|
18
19
|
},
|
|
19
20
|
"files": [
|
|
20
21
|
"README.md",
|
|
@@ -23,9 +24,9 @@
|
|
|
23
24
|
"types": "./dist/index.d.ts",
|
|
24
25
|
"exports": "./dist/index.js",
|
|
25
26
|
"dependencies": {
|
|
26
|
-
"zod": "4.4
|
|
27
|
+
"zod": "^4.5.4"
|
|
27
28
|
},
|
|
28
29
|
"peerDependencies": {
|
|
29
|
-
"@theshelf/validation": "^0.
|
|
30
|
+
"@theshelf/validation": "^0.5.0"
|
|
30
31
|
}
|
|
31
32
|
}
|