@hy_ong/zod-kit 0.0.1 → 0.0.4
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/README.md +2 -2
- package/dist/index.cjs +343 -0
- package/dist/index.d.cts +77 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +308 -0
- package/package.json +17 -5
- package/src/common/boolean.ts +4 -5
- package/src/common/date.ts +5 -6
- package/src/common/email.ts +10 -11
- package/src/common/integer.ts +7 -8
- package/src/common/number.ts +6 -7
- package/src/common/password.ts +8 -9
- package/src/common/text.ts +8 -9
- package/src/common/url.ts +9 -10
- package/src/i18n/locales/en.json +44 -44
- package/src/i18n/locales/zh-TW.json +41 -41
- package/tests/common/boolean.test.ts +20 -20
- package/tests/common/email.test.ts +20 -20
- package/tests/common/integer.test.ts +18 -18
- package/tests/common/number.test.ts +14 -14
- package/tests/common/password.test.ts +23 -23
- package/tests/common/text.test.ts +23 -23
- package/tests/common/url.test.ts +17 -17
package/dist/index.js
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
// src/common/boolean.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
// src/i18n/locales/zh-TW.json
|
|
5
|
+
var zh_TW_default = {
|
|
6
|
+
common: {
|
|
7
|
+
boolean: {
|
|
8
|
+
required: "\u5FC5\u586B",
|
|
9
|
+
shouldBe: {
|
|
10
|
+
true: "\u5FC5\u9808\u70BA\u662F",
|
|
11
|
+
false: "\u5FC5\u9808\u70BA\u5426"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
email: {
|
|
15
|
+
required: "\u5FC5\u586B",
|
|
16
|
+
min: "\u9577\u5EA6\u81F3\u5C11 ${min} \u5B57\u5143",
|
|
17
|
+
max: "\u9577\u5EA6\u6700\u591A ${max} \u5B57\u5143",
|
|
18
|
+
includes: "\u5FC5\u9808\u5305\u542B\u300C${includes}\u300D",
|
|
19
|
+
invalid: "\u683C\u5F0F\u932F\u8AA4",
|
|
20
|
+
domain: "\u5FC5\u9808\u70BA @${domain} \u7DB2\u57DF"
|
|
21
|
+
},
|
|
22
|
+
url: {
|
|
23
|
+
required: "\u5FC5\u586B",
|
|
24
|
+
min: "\u9577\u5EA6\u81F3\u5C11 ${min} \u5B57\u5143",
|
|
25
|
+
max: "\u9577\u5EA6\u6700\u591A ${max} \u5B57\u5143",
|
|
26
|
+
includes: "\u5FC5\u9808\u5305\u542B\u300C${includes}\u300D",
|
|
27
|
+
invalid: "\u683C\u5F0F\u932F\u8AA4"
|
|
28
|
+
},
|
|
29
|
+
password: {
|
|
30
|
+
required: "\u5FC5\u586B",
|
|
31
|
+
min: "\u9577\u5EA6\u81F3\u5C11 ${min} \u5B57\u5143",
|
|
32
|
+
max: "\u9577\u5EA6\u6700\u591A ${max} \u5B57\u5143",
|
|
33
|
+
uppercase: "\u5FC5\u9808\u5305\u542B\u81F3\u5C11\u4E00\u500B\u5927\u5BEB\u5B57\u6BCD",
|
|
34
|
+
lowercase: "\u5FC5\u9808\u5305\u542B\u81F3\u5C11\u4E00\u500B\u5C0F\u5BEB\u5B57\u6BCD",
|
|
35
|
+
digits: "\u5FC5\u9808\u5305\u542B\u81F3\u5C11\u4E00\u500B\u6578\u5B57",
|
|
36
|
+
special: "\u5FC5\u9808\u5305\u542B\u81F3\u5C11\u4E00\u500B\u7279\u6B8A\u7B26\u865F"
|
|
37
|
+
},
|
|
38
|
+
number: {
|
|
39
|
+
required: "\u5FC5\u586B",
|
|
40
|
+
min: "\u6700\u5C0F\u503C ${min}",
|
|
41
|
+
max: "\u6700\u5927\u503C ${max}"
|
|
42
|
+
},
|
|
43
|
+
id: {
|
|
44
|
+
required: "\u8ACB\u9078\u64C7",
|
|
45
|
+
invalid: "\u7121\u6548"
|
|
46
|
+
},
|
|
47
|
+
integer: {
|
|
48
|
+
required: "\u5FC5\u586B",
|
|
49
|
+
min: "\u6700\u5C0F\u503C ${min}",
|
|
50
|
+
max: "\u6700\u5927\u503C ${max}",
|
|
51
|
+
integer: "\u5FC5\u9808\u70BA\u6574\u6578"
|
|
52
|
+
},
|
|
53
|
+
float: {
|
|
54
|
+
required: "\u5FC5\u586B",
|
|
55
|
+
float: "\u5FC5\u9808\u70BA\u6D6E\u9EDE\u6578",
|
|
56
|
+
min: "\u6700\u5C0F\u503C ${min}",
|
|
57
|
+
max: "\u6700\u5927\u503C ${max}"
|
|
58
|
+
},
|
|
59
|
+
text: {
|
|
60
|
+
required: "\u5FC5\u586B",
|
|
61
|
+
min: "\u9577\u5EA6\u81F3\u5C11 ${min} \u5B57\u5143",
|
|
62
|
+
max: "\u9577\u5EA6\u6700\u591A ${max} \u5B57\u5143",
|
|
63
|
+
startsWith: "\u5FC5\u9808\u4EE5\u300C${startsWith}\u300D\u958B\u982D",
|
|
64
|
+
endsWith: "\u5FC5\u9808\u4EE5\u300C${endsWith}\u300D\u7D50\u5C3E",
|
|
65
|
+
includes: "\u5FC5\u9808\u5305\u542B\u300C${includes}\u300D",
|
|
66
|
+
invalid: "\u683C\u5F0F\u932F\u8AA4"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// src/i18n/locales/en.json
|
|
72
|
+
var en_default = {
|
|
73
|
+
common: {
|
|
74
|
+
boolean: {
|
|
75
|
+
required: "Required",
|
|
76
|
+
shouldBe: {
|
|
77
|
+
true: "Must be True",
|
|
78
|
+
false: "Must be False"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
email: {
|
|
82
|
+
required: "Required",
|
|
83
|
+
min: "Must be at least ${min} characters",
|
|
84
|
+
max: "Must be at most ${max} characters",
|
|
85
|
+
includes: "Must include ${includes}",
|
|
86
|
+
invalid: "Invalid format",
|
|
87
|
+
domain: "Must be under the domain @${domain}"
|
|
88
|
+
},
|
|
89
|
+
url: {
|
|
90
|
+
required: "Required",
|
|
91
|
+
min: "Must be at least ${min} characters",
|
|
92
|
+
max: "Must be at most ${max} characters",
|
|
93
|
+
includes: "Must include ${includes}",
|
|
94
|
+
invalid: "Invalid format"
|
|
95
|
+
},
|
|
96
|
+
password: {
|
|
97
|
+
required: "Required",
|
|
98
|
+
min: "Must be at least ${min} characters",
|
|
99
|
+
max: "Must be at most ${max} characters",
|
|
100
|
+
uppercase: "Must include at least one uppercase letter",
|
|
101
|
+
lowercase: "Must include at least one lowercase letter",
|
|
102
|
+
digits: "Must include at least one digit",
|
|
103
|
+
special: "Must include at least one special character"
|
|
104
|
+
},
|
|
105
|
+
number: {
|
|
106
|
+
required: "Required",
|
|
107
|
+
min: "Must be at least ${min}",
|
|
108
|
+
max: "Must be at most ${max}"
|
|
109
|
+
},
|
|
110
|
+
integer: {
|
|
111
|
+
required: "Required",
|
|
112
|
+
min: "Must be at least ${min}",
|
|
113
|
+
max: "Must be at most ${max}",
|
|
114
|
+
integer: "Must be an integer"
|
|
115
|
+
},
|
|
116
|
+
float: {
|
|
117
|
+
required: "Required",
|
|
118
|
+
min: "Must be at least ${min}",
|
|
119
|
+
max: "Must be at most ${max}",
|
|
120
|
+
float: "Must be an float"
|
|
121
|
+
},
|
|
122
|
+
text: {
|
|
123
|
+
required: "Required",
|
|
124
|
+
min: "Must be at least ${min} characters",
|
|
125
|
+
max: "Must be at most ${max} characters",
|
|
126
|
+
startsWith: "Must start with ${startsWith}",
|
|
127
|
+
endsWith: "Must end with ${endsWith}",
|
|
128
|
+
includes: "Must include ${includes}",
|
|
129
|
+
invalid: "Invalid format"
|
|
130
|
+
},
|
|
131
|
+
date: {
|
|
132
|
+
required: "Required",
|
|
133
|
+
min: "Must be at least ${min} characters",
|
|
134
|
+
max: "Must be at most ${max} characters",
|
|
135
|
+
includes: "Must include ${includes}",
|
|
136
|
+
format: "Must be in ${format} format"
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// src/config.ts
|
|
142
|
+
var currentLocale = "zh-TW";
|
|
143
|
+
var setLocale = (locale) => {
|
|
144
|
+
currentLocale = locale;
|
|
145
|
+
};
|
|
146
|
+
var getLocale = () => currentLocale;
|
|
147
|
+
|
|
148
|
+
// src/i18n/index.ts
|
|
149
|
+
var dicts = {
|
|
150
|
+
"zh-TW": zh_TW_default,
|
|
151
|
+
en: en_default
|
|
152
|
+
};
|
|
153
|
+
var t = (key, params = {}) => {
|
|
154
|
+
const locale = getLocale();
|
|
155
|
+
const dict = dicts[locale] || {};
|
|
156
|
+
const template = getNestedValue(dict, key) ?? key;
|
|
157
|
+
return template.replace(/\$\{(\w+)}/g, (_, k) => params[k] ?? "");
|
|
158
|
+
};
|
|
159
|
+
function getNestedValue(obj, path) {
|
|
160
|
+
const result = path.split(".").reduce((acc, part) => acc && typeof acc === "object" ? acc[part] : void 0, obj);
|
|
161
|
+
return typeof result === "string" ? result : void 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/common/boolean.ts
|
|
165
|
+
function boolean(options) {
|
|
166
|
+
const { required = true, defaultValue = null, shouldBe } = options ?? {};
|
|
167
|
+
let result = z.preprocess(
|
|
168
|
+
(val) => {
|
|
169
|
+
if (val === "" || val === void 0 || val === null) return defaultValue;
|
|
170
|
+
if (val === "true" || val === 1 || val === "1") return true;
|
|
171
|
+
if (val === "false" || val === 0 || val === "0") return false;
|
|
172
|
+
return val;
|
|
173
|
+
},
|
|
174
|
+
z.union([z.literal(true), z.literal(false), z.literal(null)])
|
|
175
|
+
);
|
|
176
|
+
if (required && defaultValue === null) {
|
|
177
|
+
result = result.refine((val) => val !== null, { message: t("common.boolean.required") });
|
|
178
|
+
}
|
|
179
|
+
if (shouldBe === true) {
|
|
180
|
+
result = result.refine((val) => val === true, { message: t("common.boolean.shouldBe.true") });
|
|
181
|
+
} else if (shouldBe === false) {
|
|
182
|
+
result = result.refine((val) => val === false, { message: t("common.boolean.shouldBe.false") });
|
|
183
|
+
}
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/common/email.ts
|
|
188
|
+
import { z as z2 } from "zod";
|
|
189
|
+
function email(options) {
|
|
190
|
+
const { required = true, domain, min, max, includes } = options ?? {};
|
|
191
|
+
const baseSchema = required ? z2.preprocess(
|
|
192
|
+
(val) => val === "" || val === null || val === void 0 ? null : val,
|
|
193
|
+
z2.email({
|
|
194
|
+
error: (issue) => {
|
|
195
|
+
if (issue.code === "invalid_type") return t("common.email.required");
|
|
196
|
+
else if (issue.code === "invalid_format") return t("common.email.invalid");
|
|
197
|
+
return t("common.email.invalid");
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
) : z2.preprocess((val) => val === "" || val === null || val === void 0 ? null : val, z2.email({ message: t("common.email.invalid") }).nullable());
|
|
201
|
+
const schema = baseSchema.refine((val) => required ? val !== "" && val !== "null" && val !== "undefined" : true, { message: t("common.text.required") }).refine((val) => val === null || min === void 0 || val.length >= min, { message: t("common.text.min", { min }) }).refine((val) => val === null || max === void 0 || val.length <= max, { message: t("common.text.max", { max }) }).refine((val) => val === null || includes === void 0 || val.includes(includes), { message: t("common.text.includes", { includes }) }).refine(
|
|
202
|
+
(val) => {
|
|
203
|
+
if (val === null || domain === void 0) return true;
|
|
204
|
+
return val.split("@")[1]?.toLowerCase() === domain.toLowerCase();
|
|
205
|
+
},
|
|
206
|
+
{ message: t("common.email.domain", { domain }) }
|
|
207
|
+
);
|
|
208
|
+
return schema;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// src/common/url.ts
|
|
212
|
+
import { z as z3 } from "zod";
|
|
213
|
+
function url(options) {
|
|
214
|
+
const { required = true, min, max, includes } = options ?? {};
|
|
215
|
+
const baseSchema = required ? z3.preprocess(
|
|
216
|
+
(val) => val === "" || val === null || val === void 0 ? null : val,
|
|
217
|
+
z3.url({
|
|
218
|
+
error: (issue) => {
|
|
219
|
+
if (issue.code === "invalid_type") return t("common.url.required");
|
|
220
|
+
else if (issue.code === "invalid_format") return t("common.url.invalid");
|
|
221
|
+
return t("common.url.invalid");
|
|
222
|
+
}
|
|
223
|
+
})
|
|
224
|
+
) : z3.preprocess((val) => val === "" || val === null || val === void 0 ? null : val, z3.url({ message: t("common.url.invalid") }).nullable());
|
|
225
|
+
const schema = baseSchema.refine((val) => required ? val !== "" && val !== "null" && val !== "undefined" : true, { message: t("common.text.required") }).refine((val) => val === null || min === void 0 || val.length >= min, { message: t("common.text.min", { min }) }).refine((val) => val === null || max === void 0 || val.length <= max, { message: t("common.text.max", { max }) }).refine((val) => val === null || includes === void 0 || val.includes(includes), { message: t("common.text.includes", { includes }) });
|
|
226
|
+
return schema;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// src/common/text.ts
|
|
230
|
+
import { z as z4 } from "zod";
|
|
231
|
+
function text(options) {
|
|
232
|
+
const { required = true, min, max, startsWith, endsWith, includes, regex, defaultValue = null } = options ?? {};
|
|
233
|
+
const baseSchema = required ? z4.preprocess((val) => val === "" || val === null || val === void 0 ? defaultValue : val, z4.coerce.string().trim()) : z4.preprocess((val) => val === "" || val === null || val === void 0 ? defaultValue : val, z4.coerce.string().trim().nullable());
|
|
234
|
+
const schema = baseSchema.refine((val) => required ? val !== "" && val !== "null" && val !== "undefined" : true, { message: t("common.text.required") }).refine((val) => val === null || min === void 0 || val.length >= min, { message: t("common.text.min", { min }) }).refine((val) => val === null || max === void 0 || val.length <= max, { message: t("common.text.max", { max }) }).refine((val) => val === null || startsWith === void 0 || val.startsWith(startsWith), { message: t("common.text.startsWith", { startsWith }) }).refine((val) => val === null || endsWith === void 0 || val.endsWith(endsWith), { message: t("common.text.endsWith", { endsWith }) }).refine((val) => val === null || includes === void 0 || val.includes(includes), { message: t("common.text.includes", { includes }) }).refine((val) => val === null || regex === void 0 || regex.test(val), { message: t("common.text.invalid", { regex }) });
|
|
235
|
+
return schema;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/common/number.ts
|
|
239
|
+
import { z as z5 } from "zod";
|
|
240
|
+
function number(options) {
|
|
241
|
+
const { required = true, min, max, defaultValue } = options ?? {};
|
|
242
|
+
const schema = z5.preprocess(
|
|
243
|
+
(val) => {
|
|
244
|
+
if (val === "" || val === void 0 || val === null) return defaultValue ?? null;
|
|
245
|
+
return typeof val === "string" ? Number(val) : val;
|
|
246
|
+
},
|
|
247
|
+
z5.union([
|
|
248
|
+
z5.number({
|
|
249
|
+
error: (issue) => {
|
|
250
|
+
if (issue.code === "invalid_type") return t("common.number.integer");
|
|
251
|
+
return t("common.number.required");
|
|
252
|
+
}
|
|
253
|
+
}),
|
|
254
|
+
z5.null()
|
|
255
|
+
])
|
|
256
|
+
).refine((val) => !required || val !== null, { message: t("common.number.required") }).refine((val) => val === null || min === void 0 || val >= min, { message: t("common.number.min", { min }) }).refine((val) => val === null || max === void 0 || val <= max, { message: t("common.number.max", { max }) });
|
|
257
|
+
return schema;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/common/password.ts
|
|
261
|
+
import { z as z6 } from "zod";
|
|
262
|
+
function password(options) {
|
|
263
|
+
const { required = true, min, max, uppercase, lowercase, digits, special } = options ?? {};
|
|
264
|
+
const baseSchema = required ? z6.preprocess((val) => val === "" || val === null || val === void 0 ? null : val, z6.coerce.string().trim()) : z6.preprocess((val) => val === "" || val === null || val === void 0 ? null : val, z6.coerce.string().trim().nullable());
|
|
265
|
+
const schema = baseSchema.refine((val) => required ? val !== "" && val !== "null" && val !== "undefined" : true, { message: t("common.password.required") }).refine((val) => val === null || min === void 0 || val.length >= min, { message: t("common.password.min", { min }) }).refine((val) => val === null || max === void 0 || val.length <= max, { message: t("common.password.max", { max }) }).refine((val) => val === null || !uppercase || /[A-Z]/.test(val), { message: t("common.password.uppercase") }).refine((val) => val === null || !lowercase || /[a-z]/.test(val), { message: t("common.password.lowercase") }).refine((val) => val === null || !special || /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]+/.test(val), { message: t("common.password.special") }).refine((val) => val === null || !digits || /[0-9]/.test(val), { message: t("common.password.digits") });
|
|
266
|
+
return schema;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/common/integer.ts
|
|
270
|
+
import { z as z7 } from "zod";
|
|
271
|
+
function integer(options) {
|
|
272
|
+
const { required = true, min, max, defaultValue } = options ?? {};
|
|
273
|
+
const schema = z7.preprocess(
|
|
274
|
+
(val) => {
|
|
275
|
+
if (val === "" || val === void 0 || val === null) return defaultValue ?? null;
|
|
276
|
+
return typeof val === "string" ? Number(val) : val;
|
|
277
|
+
},
|
|
278
|
+
z7.union([
|
|
279
|
+
z7.number({
|
|
280
|
+
error: (issue) => {
|
|
281
|
+
if (issue.code === "invalid_type") return t("common.integer.integer");
|
|
282
|
+
return t("common.integer.required");
|
|
283
|
+
}
|
|
284
|
+
}),
|
|
285
|
+
z7.null()
|
|
286
|
+
])
|
|
287
|
+
).refine((val) => !required || val !== null, {
|
|
288
|
+
message: t("common.integer.required")
|
|
289
|
+
}).refine((val) => val === null || Number.isInteger(val), {
|
|
290
|
+
message: t("common.integer.integer")
|
|
291
|
+
}).refine((val) => val === null || min === void 0 || val >= min, {
|
|
292
|
+
message: t("common.integer.min", { min })
|
|
293
|
+
}).refine((val) => val === null || max === void 0 || val <= max, {
|
|
294
|
+
message: t("common.integer.max", { max })
|
|
295
|
+
});
|
|
296
|
+
return schema;
|
|
297
|
+
}
|
|
298
|
+
export {
|
|
299
|
+
boolean,
|
|
300
|
+
email,
|
|
301
|
+
getLocale,
|
|
302
|
+
integer,
|
|
303
|
+
number,
|
|
304
|
+
password,
|
|
305
|
+
setLocale,
|
|
306
|
+
text,
|
|
307
|
+
url
|
|
308
|
+
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hy_ong/zod-kit",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Zod Kit",
|
|
5
5
|
"keywords": [
|
|
6
|
+
"hy_ong",
|
|
6
7
|
"zod",
|
|
7
8
|
"kit",
|
|
8
9
|
"zod-kit"
|
|
@@ -20,22 +21,33 @@
|
|
|
20
21
|
},
|
|
21
22
|
"license": "ISC",
|
|
22
23
|
"author": "Ong Hoe Yuan",
|
|
23
|
-
"type": "
|
|
24
|
-
"main": "dist/index.
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "dist/index.cjs",
|
|
26
|
+
"module": "dist/index.js",
|
|
27
|
+
"types": "dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"import": "./dist/index.js",
|
|
31
|
+
"require": "./dist/index.cjs",
|
|
32
|
+
"types": "./dist/index.d.ts"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
25
35
|
"scripts": {
|
|
26
36
|
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
27
37
|
"test": "vitest"
|
|
28
38
|
},
|
|
29
39
|
"dependencies": {
|
|
30
40
|
"dayjs": "^1.11.13",
|
|
31
|
-
"zod": "^4.0.
|
|
41
|
+
"zod": "^4.0.15"
|
|
32
42
|
},
|
|
33
43
|
"devDependencies": {
|
|
34
44
|
"@eslint/js": "^9.32.0",
|
|
45
|
+
"@types/node": "^22.17.0",
|
|
35
46
|
"eslint": "^9.32.0",
|
|
36
47
|
"prettier": "^3.6.2",
|
|
48
|
+
"tsup": "^8.5.0",
|
|
37
49
|
"typescript": "^5.8.3",
|
|
38
|
-
"typescript-eslint": "^8.
|
|
50
|
+
"typescript-eslint": "^8.39.0",
|
|
39
51
|
"vitest": "^3.2.4"
|
|
40
52
|
}
|
|
41
53
|
}
|
package/src/common/boolean.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { t } from "../i18n"
|
|
|
3
3
|
|
|
4
4
|
export type BooleanOptions<IsRequired extends boolean = true> = {
|
|
5
5
|
required?: IsRequired
|
|
6
|
-
label: string
|
|
7
6
|
defaultValue?: IsRequired extends true ? boolean : boolean | null
|
|
8
7
|
shouldBe?: boolean
|
|
9
8
|
}
|
|
@@ -11,7 +10,7 @@ export type BooleanOptions<IsRequired extends boolean = true> = {
|
|
|
11
10
|
export type BooleanSchema<IsRequired extends boolean> = IsRequired extends true ? ZodBoolean : ZodNullable<ZodBoolean>
|
|
12
11
|
|
|
13
12
|
export function boolean<IsRequired extends boolean = true>(options?: BooleanOptions<IsRequired>): BooleanSchema<IsRequired> {
|
|
14
|
-
const { required = true,
|
|
13
|
+
const { required = true, defaultValue = null, shouldBe } = options ?? {}
|
|
15
14
|
|
|
16
15
|
let result: ZodType = z.preprocess(
|
|
17
16
|
(val) => {
|
|
@@ -24,13 +23,13 @@ export function boolean<IsRequired extends boolean = true>(options?: BooleanOpti
|
|
|
24
23
|
)
|
|
25
24
|
|
|
26
25
|
if (required && defaultValue === null) {
|
|
27
|
-
result = result.refine((val) => val !== null, { message: t("common.boolean.required"
|
|
26
|
+
result = result.refine((val) => val !== null, { message: t("common.boolean.required") })
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
if (shouldBe === true) {
|
|
31
|
-
result = result.refine((val) => val === true, { message: t("common.boolean.shouldBe.true"
|
|
30
|
+
result = result.refine((val) => val === true, { message: t("common.boolean.shouldBe.true") })
|
|
32
31
|
} else if (shouldBe === false) {
|
|
33
|
-
result = result.refine((val) => val === false, { message: t("common.boolean.shouldBe.false"
|
|
32
|
+
result = result.refine((val) => val === false, { message: t("common.boolean.shouldBe.false") })
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
return result as IsRequired extends true ? ZodBoolean : ZodNullable<ZodBoolean>
|
package/src/common/date.ts
CHANGED
|
@@ -11,7 +11,6 @@ dayjs.extend(customParseFormat)
|
|
|
11
11
|
|
|
12
12
|
export type DateOptions<IsRequired extends boolean = true> = {
|
|
13
13
|
required?: IsRequired
|
|
14
|
-
label: string
|
|
15
14
|
min?: number
|
|
16
15
|
max?: number
|
|
17
16
|
format?: string
|
|
@@ -22,7 +21,7 @@ export type DateOptions<IsRequired extends boolean = true> = {
|
|
|
22
21
|
export type DateSchema<IsRequired extends boolean> = IsRequired extends true ? ZodString : ZodNullable<ZodString>
|
|
23
22
|
|
|
24
23
|
export function date<IsRequired extends boolean = true>(options?: DateOptions<IsRequired>): DateSchema<IsRequired> {
|
|
25
|
-
const { required = true,
|
|
24
|
+
const { required = true, min, max, format = "YYYY-MM-DD", includes, defaultValue = null } = options ?? {}
|
|
26
25
|
|
|
27
26
|
const baseSchema = required
|
|
28
27
|
? z.preprocess((val) => (val === "" || val === null || val === undefined ? defaultValue : val), z.coerce.string().trim())
|
|
@@ -34,11 +33,11 @@ export function date<IsRequired extends boolean = true>(options?: DateOptions<Is
|
|
|
34
33
|
if (!val) return !required
|
|
35
34
|
return dayjs(val, format, true).isValid()
|
|
36
35
|
},
|
|
37
|
-
{ message: t("common.date.format", {
|
|
36
|
+
{ message: t("common.date.format", { format }) }
|
|
38
37
|
)
|
|
39
|
-
.refine((val) => val === null || min === undefined || dayjs(val, format).isSameOrAfter(dayjs(min, format)), { message: t("common.date.min", {
|
|
40
|
-
.refine((val) => val === null || max === undefined || dayjs(val, format).isSameOrBefore(dayjs(max, format)), { message: t("common.date.max", {
|
|
41
|
-
.refine((val) => val === null || includes === undefined || val.includes(includes), { message: t("common.date.includes", {
|
|
38
|
+
.refine((val) => val === null || min === undefined || dayjs(val, format).isSameOrAfter(dayjs(min, format)), { message: t("common.date.min", { min }) })
|
|
39
|
+
.refine((val) => val === null || max === undefined || dayjs(val, format).isSameOrBefore(dayjs(max, format)), { message: t("common.date.max", { max }) })
|
|
40
|
+
.refine((val) => val === null || includes === undefined || val.includes(includes), { message: t("common.date.includes", { includes }) })
|
|
42
41
|
|
|
43
42
|
return schema as unknown as DateSchema<IsRequired>
|
|
44
43
|
}
|
package/src/common/email.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { TextSchema } from "./text"
|
|
|
4
4
|
|
|
5
5
|
export type EmailOptions<IsRequired extends boolean = true> = {
|
|
6
6
|
required?: IsRequired
|
|
7
|
-
label: string
|
|
8
7
|
domain?: string
|
|
9
8
|
min?: number
|
|
10
9
|
max?: number
|
|
@@ -14,32 +13,32 @@ export type EmailOptions<IsRequired extends boolean = true> = {
|
|
|
14
13
|
export type EmailSchema<IsRequired extends boolean> = IsRequired extends true ? ZodString : ZodNullable<ZodString>
|
|
15
14
|
|
|
16
15
|
export function email<IsRequired extends boolean = true>(options?: EmailOptions<IsRequired>): EmailSchema<IsRequired> {
|
|
17
|
-
const { required = true,
|
|
16
|
+
const { required = true, domain, min, max, includes } = options ?? {}
|
|
18
17
|
|
|
19
18
|
const baseSchema = required
|
|
20
19
|
? z.preprocess(
|
|
21
20
|
(val) => (val === "" || val === null || val === undefined ? null : val),
|
|
22
21
|
z.email({
|
|
23
22
|
error: (issue) => {
|
|
24
|
-
if (issue.code === "invalid_type") return t("common.email.required"
|
|
25
|
-
else if (issue.code === "invalid_format") return t("common.email.invalid"
|
|
26
|
-
return t("common.email.invalid"
|
|
23
|
+
if (issue.code === "invalid_type") return t("common.email.required")
|
|
24
|
+
else if (issue.code === "invalid_format") return t("common.email.invalid")
|
|
25
|
+
return t("common.email.invalid")
|
|
27
26
|
},
|
|
28
27
|
})
|
|
29
28
|
)
|
|
30
|
-
: z.preprocess((val) => (val === "" || val === null || val === undefined ? null : val), z.email({ message: t("common.email.invalid"
|
|
29
|
+
: z.preprocess((val) => (val === "" || val === null || val === undefined ? null : val), z.email({ message: t("common.email.invalid") }).nullable())
|
|
31
30
|
|
|
32
31
|
const schema = baseSchema
|
|
33
|
-
.refine((val) => (required ? val !== "" && val !== "null" && val !== "undefined" : true), { message: t("common.text.required"
|
|
34
|
-
.refine((val) => val === null || min === undefined || val.length >= min, { message: t("common.text.min", {
|
|
35
|
-
.refine((val) => val === null || max === undefined || val.length <= max, { message: t("common.text.max", {
|
|
36
|
-
.refine((val) => val === null || includes === undefined || val.includes(includes), { message: t("common.text.includes", {
|
|
32
|
+
.refine((val) => (required ? val !== "" && val !== "null" && val !== "undefined" : true), { message: t("common.text.required") })
|
|
33
|
+
.refine((val) => val === null || min === undefined || val.length >= min, { message: t("common.text.min", { min }) })
|
|
34
|
+
.refine((val) => val === null || max === undefined || val.length <= max, { message: t("common.text.max", { max }) })
|
|
35
|
+
.refine((val) => val === null || includes === undefined || val.includes(includes), { message: t("common.text.includes", { includes }) })
|
|
37
36
|
.refine(
|
|
38
37
|
(val) => {
|
|
39
38
|
if (val === null || domain === undefined) return true
|
|
40
39
|
return val.split("@")[1]?.toLowerCase() === domain.toLowerCase()
|
|
41
40
|
},
|
|
42
|
-
{ message: t("common.email.domain", {
|
|
41
|
+
{ message: t("common.email.domain", { domain }) }
|
|
43
42
|
)
|
|
44
43
|
return schema as unknown as TextSchema<IsRequired>
|
|
45
44
|
}
|
package/src/common/integer.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { t } from "../i18n"
|
|
|
3
3
|
|
|
4
4
|
export type IntegerOptions<IsRequired extends boolean = true> = {
|
|
5
5
|
required?: IsRequired
|
|
6
|
-
label: string
|
|
7
6
|
min?: number
|
|
8
7
|
max?: number
|
|
9
8
|
defaultValue?: IsRequired extends true ? number : number | null
|
|
@@ -12,7 +11,7 @@ export type IntegerOptions<IsRequired extends boolean = true> = {
|
|
|
12
11
|
export type IntegerSchema<IsRequired extends boolean> = IsRequired extends true ? ZodNumber : ZodNullable<ZodNumber>
|
|
13
12
|
|
|
14
13
|
export function integer<IsRequired extends boolean = true>(options?: IntegerOptions<IsRequired>): IntegerSchema<IsRequired> {
|
|
15
|
-
const { required = true,
|
|
14
|
+
const { required = true, min, max, defaultValue } = options ?? {}
|
|
16
15
|
|
|
17
16
|
const schema = z
|
|
18
17
|
.preprocess(
|
|
@@ -23,24 +22,24 @@ export function integer<IsRequired extends boolean = true>(options?: IntegerOpti
|
|
|
23
22
|
z.union([
|
|
24
23
|
z.number({
|
|
25
24
|
error: (issue) => {
|
|
26
|
-
if (issue.code === "invalid_type") return t("common.integer.integer"
|
|
27
|
-
return t("common.integer.required"
|
|
25
|
+
if (issue.code === "invalid_type") return t("common.integer.integer")
|
|
26
|
+
return t("common.integer.required")
|
|
28
27
|
},
|
|
29
28
|
}),
|
|
30
29
|
z.null(),
|
|
31
30
|
])
|
|
32
31
|
)
|
|
33
32
|
.refine((val) => !required || val !== null, {
|
|
34
|
-
message: t("common.integer.required"
|
|
33
|
+
message: t("common.integer.required"),
|
|
35
34
|
})
|
|
36
35
|
.refine((val) => val === null || Number.isInteger(val), {
|
|
37
|
-
message: t("common.integer.integer"
|
|
36
|
+
message: t("common.integer.integer"),
|
|
38
37
|
})
|
|
39
38
|
.refine((val) => val === null || min === undefined || val >= min, {
|
|
40
|
-
message: t("common.integer.min", {
|
|
39
|
+
message: t("common.integer.min", { min }),
|
|
41
40
|
})
|
|
42
41
|
.refine((val) => val === null || max === undefined || val <= max, {
|
|
43
|
-
message: t("common.integer.max", {
|
|
42
|
+
message: t("common.integer.max", { max }),
|
|
44
43
|
})
|
|
45
44
|
|
|
46
45
|
return schema as unknown as IntegerSchema<IsRequired>
|
package/src/common/number.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { t } from "../i18n"
|
|
|
3
3
|
|
|
4
4
|
export type NumberOptions<IsRequired extends boolean = true> = {
|
|
5
5
|
required?: IsRequired
|
|
6
|
-
label: string
|
|
7
6
|
min?: number
|
|
8
7
|
max?: number
|
|
9
8
|
defaultValue?: IsRequired extends true ? number : number | null
|
|
@@ -12,7 +11,7 @@ export type NumberOptions<IsRequired extends boolean = true> = {
|
|
|
12
11
|
export type NumberSchema<IsRequired extends boolean> = IsRequired extends true ? ZodNumber : ZodNullable<ZodNumber>
|
|
13
12
|
|
|
14
13
|
export function number<IsRequired extends boolean = true>(options?: NumberOptions<IsRequired>): NumberSchema<IsRequired> {
|
|
15
|
-
const { required = true,
|
|
14
|
+
const { required = true, min, max, defaultValue } = options ?? {}
|
|
16
15
|
|
|
17
16
|
const schema = z
|
|
18
17
|
.preprocess(
|
|
@@ -23,16 +22,16 @@ export function number<IsRequired extends boolean = true>(options?: NumberOption
|
|
|
23
22
|
z.union([
|
|
24
23
|
z.number({
|
|
25
24
|
error: (issue) => {
|
|
26
|
-
if (issue.code === "invalid_type") return t("common.number.integer"
|
|
27
|
-
return t("common.number.required"
|
|
25
|
+
if (issue.code === "invalid_type") return t("common.number.integer")
|
|
26
|
+
return t("common.number.required")
|
|
28
27
|
},
|
|
29
28
|
}),
|
|
30
29
|
z.null(),
|
|
31
30
|
])
|
|
32
31
|
)
|
|
33
|
-
.refine((val) => !required || val !== null, { message: t("common.number.required"
|
|
34
|
-
.refine((val) => val === null || min === undefined || val >= min, { message: t("common.number.min", {
|
|
35
|
-
.refine((val) => val === null || max === undefined || val <= max, { message: t("common.number.max", {
|
|
32
|
+
.refine((val) => !required || val !== null, { message: t("common.number.required") })
|
|
33
|
+
.refine((val) => val === null || min === undefined || val >= min, { message: t("common.number.min", { min }) })
|
|
34
|
+
.refine((val) => val === null || max === undefined || val <= max, { message: t("common.number.max", { max }) })
|
|
36
35
|
|
|
37
36
|
return schema as unknown as NumberSchema<IsRequired>
|
|
38
37
|
}
|
package/src/common/password.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { t } from "../i18n"
|
|
|
3
3
|
|
|
4
4
|
export type PasswordOptions<IsRequired extends boolean = true> = {
|
|
5
5
|
required?: IsRequired
|
|
6
|
-
label: string
|
|
7
6
|
min?: number
|
|
8
7
|
max?: number
|
|
9
8
|
uppercase?: boolean
|
|
@@ -15,20 +14,20 @@ export type PasswordOptions<IsRequired extends boolean = true> = {
|
|
|
15
14
|
export type PasswordSchema<IsRequired extends boolean> = IsRequired extends true ? ZodString : ZodNullable<ZodString>
|
|
16
15
|
|
|
17
16
|
export function password<IsRequired extends boolean = true>(options?: PasswordOptions<IsRequired>): PasswordSchema<IsRequired> {
|
|
18
|
-
const { required = true,
|
|
17
|
+
const { required = true, min, max, uppercase, lowercase, digits, special } = options ?? {}
|
|
19
18
|
|
|
20
19
|
const baseSchema = required
|
|
21
20
|
? z.preprocess((val) => (val === "" || val === null || val === undefined ? null : val), z.coerce.string().trim())
|
|
22
21
|
: z.preprocess((val) => (val === "" || val === null || val === undefined ? null : val), z.coerce.string().trim().nullable())
|
|
23
22
|
|
|
24
23
|
const schema = baseSchema
|
|
25
|
-
.refine((val) => (required ? val !== "" && val !== "null" && val !== "undefined" : true), { message: t("common.password.required"
|
|
26
|
-
.refine((val) => val === null || min === undefined || val.length >= min, { message: t("common.password.min", {
|
|
27
|
-
.refine((val) => val === null || max === undefined || val.length <= max, { message: t("common.password.max", {
|
|
28
|
-
.refine((val) => val === null || !uppercase || /[A-Z]/.test(val), { message: t("common.password.uppercase"
|
|
29
|
-
.refine((val) => val === null || !lowercase || /[a-z]/.test(val), { message: t("common.password.lowercase"
|
|
30
|
-
.refine((val) => val === null || !special || /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]+/.test(val), { message: t("common.password.special"
|
|
31
|
-
.refine((val) => val === null || !digits || /[0-9]/.test(val), { message: t("common.password.digits"
|
|
24
|
+
.refine((val) => (required ? val !== "" && val !== "null" && val !== "undefined" : true), { message: t("common.password.required") })
|
|
25
|
+
.refine((val) => val === null || min === undefined || val.length >= min, { message: t("common.password.min", { min }) })
|
|
26
|
+
.refine((val) => val === null || max === undefined || val.length <= max, { message: t("common.password.max", { max }) })
|
|
27
|
+
.refine((val) => val === null || !uppercase || /[A-Z]/.test(val), { message: t("common.password.uppercase") })
|
|
28
|
+
.refine((val) => val === null || !lowercase || /[a-z]/.test(val), { message: t("common.password.lowercase") })
|
|
29
|
+
.refine((val) => val === null || !special || /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]+/.test(val), { message: t("common.password.special") })
|
|
30
|
+
.refine((val) => val === null || !digits || /[0-9]/.test(val), { message: t("common.password.digits") })
|
|
32
31
|
|
|
33
32
|
return schema as unknown as PasswordSchema<IsRequired>
|
|
34
33
|
}
|
package/src/common/text.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { t } from "../i18n"
|
|
|
3
3
|
|
|
4
4
|
export type TextOptions<IsRequired extends boolean = true> = {
|
|
5
5
|
required?: IsRequired
|
|
6
|
-
label: string
|
|
7
6
|
min?: number
|
|
8
7
|
max?: number
|
|
9
8
|
startsWith?: string
|
|
@@ -16,20 +15,20 @@ export type TextOptions<IsRequired extends boolean = true> = {
|
|
|
16
15
|
export type TextSchema<IsRequired extends boolean> = IsRequired extends true ? ZodString : ZodNullable<ZodString>
|
|
17
16
|
|
|
18
17
|
export function text<IsRequired extends boolean = true>(options?: TextOptions<IsRequired>): TextSchema<IsRequired> {
|
|
19
|
-
const { required = true,
|
|
18
|
+
const { required = true, min, max, startsWith, endsWith, includes, regex, defaultValue = null } = options ?? {}
|
|
20
19
|
|
|
21
20
|
const baseSchema = required
|
|
22
21
|
? z.preprocess((val) => (val === "" || val === null || val === undefined ? defaultValue : val), z.coerce.string().trim())
|
|
23
22
|
: z.preprocess((val) => (val === "" || val === null || val === undefined ? defaultValue : val), z.coerce.string().trim().nullable())
|
|
24
23
|
|
|
25
24
|
const schema = baseSchema
|
|
26
|
-
.refine((val) => (required ? val !== "" && val !== "null" && val !== "undefined" : true), { message: t("common.text.required"
|
|
27
|
-
.refine((val) => val === null || min === undefined || val.length >= min, { message: t("common.text.min", {
|
|
28
|
-
.refine((val) => val === null || max === undefined || val.length <= max, { message: t("common.text.max", {
|
|
29
|
-
.refine((val) => val === null || startsWith === undefined || val.startsWith(startsWith), { message: t("common.text.startsWith", {
|
|
30
|
-
.refine((val) => val === null || endsWith === undefined || val.endsWith(endsWith), { message: t("common.text.endsWith", {
|
|
31
|
-
.refine((val) => val === null || includes === undefined || val.includes(includes), { message: t("common.text.includes", {
|
|
32
|
-
.refine((val) => val === null || regex === undefined || regex.test(val), { message: t("common.text.invalid", {
|
|
25
|
+
.refine((val) => (required ? val !== "" && val !== "null" && val !== "undefined" : true), { message: t("common.text.required") })
|
|
26
|
+
.refine((val) => val === null || min === undefined || val.length >= min, { message: t("common.text.min", { min }) })
|
|
27
|
+
.refine((val) => val === null || max === undefined || val.length <= max, { message: t("common.text.max", { max }) })
|
|
28
|
+
.refine((val) => val === null || startsWith === undefined || val.startsWith(startsWith), { message: t("common.text.startsWith", { startsWith }) })
|
|
29
|
+
.refine((val) => val === null || endsWith === undefined || val.endsWith(endsWith), { message: t("common.text.endsWith", { endsWith }) })
|
|
30
|
+
.refine((val) => val === null || includes === undefined || val.includes(includes), { message: t("common.text.includes", { includes }) })
|
|
31
|
+
.refine((val) => val === null || regex === undefined || regex.test(val), { message: t("common.text.invalid", { regex }) })
|
|
33
32
|
|
|
34
33
|
return schema as unknown as TextSchema<IsRequired>
|
|
35
34
|
}
|