@hy_ong/zod-kit 0.2.0 → 0.2.2
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/.github/workflows/ci.yml +24 -0
- package/CLAUDE.md +64 -22
- package/dist/chunk-2SWEVDFZ.js +134 -0
- package/dist/chunk-32JI34CV.cjs +146 -0
- package/dist/chunk-42C5OHRK.js +71 -0
- package/dist/chunk-46VAH2BJ.js +160 -0
- package/dist/chunk-5JGTDL3Y.js +87 -0
- package/dist/chunk-5LEXCVLX.js +257 -0
- package/dist/chunk-6AAP4LPF.js +2606 -0
- package/dist/chunk-B4EZYZOK.cjs +215 -0
- package/dist/chunk-COYKBWTI.js +161 -0
- package/dist/chunk-DFJZ3NS2.cjs +151 -0
- package/dist/chunk-EDHT4LPO.js +118 -0
- package/dist/chunk-EGHL277K.cjs +165 -0
- package/dist/chunk-ERH4NIMU.cjs +69 -0
- package/dist/chunk-FM3EZ72O.js +165 -0
- package/dist/chunk-GJIRDBZJ.cjs +90 -0
- package/dist/chunk-H2XTEM4M.js +696 -0
- package/dist/chunk-HMSM6FFA.cjs +181 -0
- package/dist/chunk-HTEHINI7.cjs +177 -0
- package/dist/chunk-JOLSGZGN.cjs +696 -0
- package/dist/chunk-JXY7APBU.js +69 -0
- package/dist/chunk-K2UOY6TB.js +136 -0
- package/dist/chunk-KFOHKTFD.js +61 -0
- package/dist/chunk-L4HSIKTU.cjs +135 -0
- package/dist/chunk-LH7ZB4BK.js +124 -0
- package/dist/chunk-LL4ZWLGO.js +90 -0
- package/dist/chunk-M6MTP3NY.cjs +99 -0
- package/dist/chunk-MHJFYYGV.js +215 -0
- package/dist/chunk-MINMXGW3.js +135 -0
- package/dist/chunk-MM7IL2RG.js +181 -0
- package/dist/chunk-OPQJWHXN.cjs +301 -0
- package/dist/chunk-ORFHDJII.cjs +136 -0
- package/dist/chunk-ORVV4MCF.cjs +87 -0
- package/dist/chunk-QICQ6YEY.js +75 -0
- package/dist/chunk-RKUQREMW.js +127 -0
- package/dist/chunk-RO47DKQG.js +146 -0
- package/dist/chunk-RRPXIRTQ.cjs +257 -0
- package/dist/chunk-RYFG2GKM.cjs +118 -0
- package/dist/chunk-STNHTRG7.cjs +124 -0
- package/dist/chunk-TFGS34VD.cjs +71 -0
- package/dist/chunk-TQXDUMML.cjs +61 -0
- package/dist/chunk-UBK3VCVH.cjs +134 -0
- package/dist/chunk-UCOXAZJF.cjs +2606 -0
- package/dist/chunk-UQZKFAFX.js +130 -0
- package/dist/chunk-VB2KV2ZM.cjs +130 -0
- package/dist/chunk-WABKPFPK.js +151 -0
- package/dist/chunk-WDI4QJMQ.js +177 -0
- package/dist/chunk-YDH3L27K.cjs +127 -0
- package/dist/chunk-YIM3D2AD.js +99 -0
- package/dist/chunk-YPSEIDUR.cjs +160 -0
- package/dist/chunk-ZNJLWJX3.cjs +75 -0
- package/dist/chunk-ZTFCJCPO.cjs +161 -0
- package/dist/chunk-ZXUMK2RR.js +301 -0
- package/dist/common/boolean.cjs +7 -0
- package/dist/common/boolean.d.cts +119 -0
- package/dist/common/boolean.d.ts +119 -0
- package/dist/common/boolean.js +7 -0
- package/dist/common/color.cjs +9 -0
- package/dist/common/color.d.cts +26 -0
- package/dist/common/color.d.ts +26 -0
- package/dist/common/color.js +9 -0
- package/dist/common/coordinate.cjs +11 -0
- package/dist/common/coordinate.d.cts +23 -0
- package/dist/common/coordinate.d.ts +23 -0
- package/dist/common/coordinate.js +11 -0
- package/dist/common/credit-card.cjs +11 -0
- package/dist/common/credit-card.d.cts +22 -0
- package/dist/common/credit-card.d.ts +22 -0
- package/dist/common/credit-card.js +11 -0
- package/dist/common/date.cjs +7 -0
- package/dist/common/date.d.cts +174 -0
- package/dist/common/date.d.ts +174 -0
- package/dist/common/date.js +7 -0
- package/dist/common/datetime.cjs +15 -0
- package/dist/common/datetime.d.cts +301 -0
- package/dist/common/datetime.d.ts +301 -0
- package/dist/common/datetime.js +15 -0
- package/dist/common/email.cjs +7 -0
- package/dist/common/email.d.cts +149 -0
- package/dist/common/email.d.ts +149 -0
- package/dist/common/email.js +7 -0
- package/dist/common/file.cjs +7 -0
- package/dist/common/file.d.cts +178 -0
- package/dist/common/file.d.ts +178 -0
- package/dist/common/file.js +7 -0
- package/dist/common/id.cjs +13 -0
- package/dist/common/id.d.cts +288 -0
- package/dist/common/id.d.ts +288 -0
- package/dist/common/id.js +13 -0
- package/dist/common/ip.cjs +11 -0
- package/dist/common/ip.d.cts +25 -0
- package/dist/common/ip.d.ts +25 -0
- package/dist/common/ip.js +11 -0
- package/dist/common/number.cjs +7 -0
- package/dist/common/number.d.cts +167 -0
- package/dist/common/number.d.ts +167 -0
- package/dist/common/number.js +7 -0
- package/dist/common/password.cjs +7 -0
- package/dist/common/password.d.cts +192 -0
- package/dist/common/password.d.ts +192 -0
- package/dist/common/password.js +7 -0
- package/dist/common/text.cjs +7 -0
- package/dist/common/text.d.cts +156 -0
- package/dist/common/text.d.ts +156 -0
- package/dist/common/text.js +7 -0
- package/dist/common/time.cjs +15 -0
- package/dist/common/time.d.cts +268 -0
- package/dist/common/time.d.ts +268 -0
- package/dist/common/time.js +15 -0
- package/dist/common/url.cjs +7 -0
- package/dist/common/url.d.cts +196 -0
- package/dist/common/url.d.ts +196 -0
- package/dist/common/url.js +7 -0
- package/dist/config-CABSSvAp.d.cts +5 -0
- package/dist/config-CABSSvAp.d.ts +5 -0
- package/dist/index.cjs +180 -5255
- package/dist/index.d.cts +28 -3150
- package/dist/index.d.ts +28 -3150
- package/dist/index.js +135 -5131
- package/dist/taiwan/bank-account.cjs +11 -0
- package/dist/taiwan/bank-account.d.cts +22 -0
- package/dist/taiwan/bank-account.d.ts +22 -0
- package/dist/taiwan/bank-account.js +11 -0
- package/dist/taiwan/business-id.cjs +9 -0
- package/dist/taiwan/business-id.d.cts +133 -0
- package/dist/taiwan/business-id.d.ts +133 -0
- package/dist/taiwan/business-id.js +9 -0
- package/dist/taiwan/fax.cjs +9 -0
- package/dist/taiwan/fax.d.cts +157 -0
- package/dist/taiwan/fax.d.ts +157 -0
- package/dist/taiwan/fax.js +9 -0
- package/dist/taiwan/invoice.cjs +9 -0
- package/dist/taiwan/invoice.d.cts +17 -0
- package/dist/taiwan/invoice.d.ts +17 -0
- package/dist/taiwan/invoice.js +9 -0
- package/dist/taiwan/license-plate.cjs +9 -0
- package/dist/taiwan/license-plate.d.cts +19 -0
- package/dist/taiwan/license-plate.d.ts +19 -0
- package/dist/taiwan/license-plate.js +9 -0
- package/dist/taiwan/mobile.cjs +9 -0
- package/dist/taiwan/mobile.d.cts +146 -0
- package/dist/taiwan/mobile.d.ts +146 -0
- package/dist/taiwan/mobile.js +9 -0
- package/dist/taiwan/national-id.cjs +15 -0
- package/dist/taiwan/national-id.d.cts +214 -0
- package/dist/taiwan/national-id.d.ts +214 -0
- package/dist/taiwan/national-id.js +15 -0
- package/dist/taiwan/passport.cjs +9 -0
- package/dist/taiwan/passport.d.cts +19 -0
- package/dist/taiwan/passport.d.ts +19 -0
- package/dist/taiwan/passport.js +9 -0
- package/dist/taiwan/postal-code.cjs +17 -0
- package/dist/taiwan/postal-code.d.cts +237 -0
- package/dist/taiwan/postal-code.d.ts +237 -0
- package/dist/taiwan/postal-code.js +17 -0
- package/dist/taiwan/tel.cjs +9 -0
- package/dist/taiwan/tel.d.cts +162 -0
- package/dist/taiwan/tel.d.ts +162 -0
- package/dist/taiwan/tel.js +9 -0
- package/package.json +132 -6
- package/src/i18n/locales/en-GB.json +51 -0
- package/src/i18n/locales/en-US.json +52 -1
- package/src/i18n/locales/id-ID.json +51 -0
- package/src/i18n/locales/ja-JP.json +51 -0
- package/src/i18n/locales/ko-KR.json +51 -0
- package/src/i18n/locales/ms-MY.json +51 -0
- package/src/i18n/locales/th-TH.json +51 -0
- package/src/i18n/locales/vi-VN.json +51 -0
- package/src/i18n/locales/zh-CN.json +51 -0
- package/src/i18n/locales/zh-TW.json +51 -0
- package/src/index.ts +10 -2
- package/src/validators/common/color.ts +192 -0
- package/src/validators/common/coordinate.ts +159 -0
- package/src/validators/common/credit-card.ts +134 -0
- package/src/validators/common/id.ts +45 -3
- package/src/validators/common/ip.ts +210 -0
- package/src/validators/taiwan/bank-account.ts +176 -0
- package/src/validators/taiwan/invoice.ts +84 -0
- package/src/validators/taiwan/license-plate.ts +110 -0
- package/src/validators/taiwan/passport.ts +103 -0
- package/tests/common/color.test.ts +587 -0
- package/tests/common/coordinate.test.ts +345 -0
- package/tests/common/credit-card.test.ts +378 -0
- package/tests/common/id.test.ts +68 -3
- package/tests/common/ip.test.ts +419 -0
- package/tests/taiwan/bank-account.test.ts +286 -0
- package/tests/taiwan/invoice.test.ts +227 -0
- package/tests/taiwan/license-plate.test.ts +280 -0
- package/tests/taiwan/passport.test.ts +277 -0
- package/tsup.config.ts +36 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getLocale,
|
|
3
|
+
t
|
|
4
|
+
} from "./chunk-6AAP4LPF.js";
|
|
5
|
+
|
|
6
|
+
// src/validators/taiwan/fax.ts
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
var validateTaiwanFax = (value) => {
|
|
9
|
+
const cleanValue = value.replace(/[-\s]/g, "");
|
|
10
|
+
if (!/^0\d{7,10}$/.test(cleanValue)) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
const areaCode4 = cleanValue.substring(0, 4);
|
|
14
|
+
if (areaCode4 === "0836") {
|
|
15
|
+
return cleanValue.length === 9 && /^0836\d{5}$/.test(cleanValue);
|
|
16
|
+
}
|
|
17
|
+
const areaCode3 = cleanValue.substring(0, 3);
|
|
18
|
+
if (areaCode3 === "037") {
|
|
19
|
+
const firstDigit = cleanValue[3];
|
|
20
|
+
if (firstDigit === "0" || firstDigit === "1") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return (cleanValue.length === 9 || cleanValue.length === 10) && /^037[2-9]\d{5,6}$/.test(cleanValue);
|
|
24
|
+
}
|
|
25
|
+
if (areaCode3 === "049") {
|
|
26
|
+
return cleanValue.length === 10 && /^049\d{7}$/.test(cleanValue);
|
|
27
|
+
}
|
|
28
|
+
if (areaCode3 === "082") {
|
|
29
|
+
return cleanValue.length === 9 && /^082\d{6}$/.test(cleanValue);
|
|
30
|
+
}
|
|
31
|
+
if (areaCode3 === "089") {
|
|
32
|
+
return cleanValue.length === 9 && /^089\d{6}$/.test(cleanValue);
|
|
33
|
+
}
|
|
34
|
+
const areaCode2 = cleanValue.substring(0, 2);
|
|
35
|
+
if (areaCode2 === "02") {
|
|
36
|
+
const firstDigit = cleanValue[2];
|
|
37
|
+
if (firstDigit === "0" || firstDigit === "1") {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return cleanValue.length === 10 && /^02[2-9]\d{7}$/.test(cleanValue);
|
|
41
|
+
}
|
|
42
|
+
if (areaCode2 === "03") {
|
|
43
|
+
return (cleanValue.length === 9 || cleanValue.length === 10) && /^03\d{7,8}$/.test(cleanValue);
|
|
44
|
+
}
|
|
45
|
+
if (areaCode2 === "04") {
|
|
46
|
+
return (cleanValue.length === 9 || cleanValue.length === 10) && /^04\d{7,8}$/.test(cleanValue);
|
|
47
|
+
}
|
|
48
|
+
if (areaCode2 === "05") {
|
|
49
|
+
return cleanValue.length === 9 && /^05\d{7}$/.test(cleanValue);
|
|
50
|
+
}
|
|
51
|
+
if (areaCode2 === "06") {
|
|
52
|
+
return cleanValue.length === 9 && /^06\d{7}$/.test(cleanValue);
|
|
53
|
+
}
|
|
54
|
+
if (areaCode2 === "07") {
|
|
55
|
+
const firstDigit = cleanValue[2];
|
|
56
|
+
if (firstDigit === "0" || firstDigit === "1") {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return cleanValue.length === 9 && /^07[2-9]\d{6}$/.test(cleanValue);
|
|
60
|
+
}
|
|
61
|
+
if (areaCode2 === "08") {
|
|
62
|
+
const firstDigit = cleanValue[2];
|
|
63
|
+
if (firstDigit !== "4" && firstDigit !== "7" && firstDigit !== "8") {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return cleanValue.length === 9 && /^08[478]\d{6}$/.test(cleanValue);
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
};
|
|
70
|
+
function twFax(required, options) {
|
|
71
|
+
const { whitelist, transform, defaultValue, i18n } = options ?? {};
|
|
72
|
+
const isRequired = required ?? false;
|
|
73
|
+
const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
|
|
74
|
+
const getMessage = (key, params) => {
|
|
75
|
+
if (i18n) {
|
|
76
|
+
const currentLocale = getLocale();
|
|
77
|
+
const customMessages = i18n[currentLocale];
|
|
78
|
+
if (customMessages && customMessages[key]) {
|
|
79
|
+
const template = customMessages[key];
|
|
80
|
+
return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return t(`taiwan.fax.${key}`, params);
|
|
84
|
+
};
|
|
85
|
+
const preprocessFn = (val) => {
|
|
86
|
+
if (val === null || val === void 0) {
|
|
87
|
+
return actualDefaultValue;
|
|
88
|
+
}
|
|
89
|
+
let processed = String(val).trim();
|
|
90
|
+
if (processed === "") {
|
|
91
|
+
if (whitelist && whitelist.includes("")) {
|
|
92
|
+
return "";
|
|
93
|
+
}
|
|
94
|
+
if (!isRequired) {
|
|
95
|
+
return actualDefaultValue;
|
|
96
|
+
}
|
|
97
|
+
return actualDefaultValue;
|
|
98
|
+
}
|
|
99
|
+
if (transform) {
|
|
100
|
+
processed = transform(processed);
|
|
101
|
+
}
|
|
102
|
+
return processed;
|
|
103
|
+
};
|
|
104
|
+
const baseSchema = isRequired ? z.preprocess(preprocessFn, z.string()) : z.preprocess(preprocessFn, z.string().nullable());
|
|
105
|
+
const schema = baseSchema.superRefine((val, ctx) => {
|
|
106
|
+
if (val === null) return;
|
|
107
|
+
if (isRequired && (val === "" || val === "null" || val === "undefined")) {
|
|
108
|
+
ctx.addIssue({ code: "custom", message: getMessage("required") });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (val === null) return;
|
|
112
|
+
if (!isRequired && val === "") return;
|
|
113
|
+
if (whitelist && whitelist.length > 0 && whitelist.includes(val)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (!validateTaiwanFax(val)) {
|
|
117
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return schema;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export {
|
|
125
|
+
validateTaiwanFax,
|
|
126
|
+
twFax
|
|
127
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getLocale,
|
|
3
|
+
t
|
|
4
|
+
} from "./chunk-6AAP4LPF.js";
|
|
5
|
+
|
|
6
|
+
// src/validators/common/ip.ts
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
function validateIPv4(value) {
|
|
9
|
+
const parts = value.split(".");
|
|
10
|
+
if (parts.length !== 4) return false;
|
|
11
|
+
for (const part of parts) {
|
|
12
|
+
if (part === "") return false;
|
|
13
|
+
if (part.length > 1 && part.startsWith("0")) return false;
|
|
14
|
+
const num = Number(part);
|
|
15
|
+
if (!Number.isInteger(num) || num < 0 || num > 255) return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
function validateIPv6(value) {
|
|
20
|
+
const lastColon = value.lastIndexOf(":");
|
|
21
|
+
if (lastColon !== -1) {
|
|
22
|
+
const afterLastColon = value.substring(lastColon + 1);
|
|
23
|
+
if (afterLastColon.includes(".")) {
|
|
24
|
+
if (!validateIPv4(afterLastColon)) return false;
|
|
25
|
+
const ipv6Prefix = value.substring(0, lastColon);
|
|
26
|
+
return validateIPv6Groups(ipv6Prefix, 6);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return validateIPv6Groups(value, 8);
|
|
30
|
+
}
|
|
31
|
+
function validateIPv6Groups(value, maxGroups) {
|
|
32
|
+
if (value.includes("::")) {
|
|
33
|
+
const doubleColonCount = value.split("::").length - 1;
|
|
34
|
+
if (doubleColonCount > 1) return false;
|
|
35
|
+
const [left, right] = value.split("::");
|
|
36
|
+
const leftGroups = left === "" ? [] : left.split(":");
|
|
37
|
+
const rightGroups = right === "" ? [] : right.split(":");
|
|
38
|
+
if (leftGroups.length + rightGroups.length >= maxGroups) return false;
|
|
39
|
+
for (const group of [...leftGroups, ...rightGroups]) {
|
|
40
|
+
if (!isValidHexGroup(group)) return false;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
const groups = value.split(":");
|
|
45
|
+
if (groups.length !== maxGroups) return false;
|
|
46
|
+
for (const group of groups) {
|
|
47
|
+
if (!isValidHexGroup(group)) return false;
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
function isValidHexGroup(group) {
|
|
52
|
+
if (group.length === 0 || group.length > 4) return false;
|
|
53
|
+
return /^[0-9a-fA-F]{1,4}$/.test(group);
|
|
54
|
+
}
|
|
55
|
+
function ip(required, options) {
|
|
56
|
+
const { version = "any", allowCIDR = false, whitelist, transform, defaultValue, i18n } = options ?? {};
|
|
57
|
+
const isRequired = required ?? false;
|
|
58
|
+
const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
|
|
59
|
+
const getMessage = (key, params) => {
|
|
60
|
+
if (i18n) {
|
|
61
|
+
const currentLocale = getLocale();
|
|
62
|
+
const customMessages = i18n[currentLocale];
|
|
63
|
+
if (customMessages && customMessages[key]) {
|
|
64
|
+
const template = customMessages[key];
|
|
65
|
+
return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return t(`common.ip.${key}`, params);
|
|
69
|
+
};
|
|
70
|
+
const preprocessFn = (val) => {
|
|
71
|
+
if (val === "" || val === null || val === void 0) {
|
|
72
|
+
return actualDefaultValue;
|
|
73
|
+
}
|
|
74
|
+
let processed = String(val).trim();
|
|
75
|
+
if (processed === "" && !required) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
if (transform) {
|
|
79
|
+
processed = transform(processed);
|
|
80
|
+
}
|
|
81
|
+
return processed;
|
|
82
|
+
};
|
|
83
|
+
const baseSchema = isRequired ? z.preprocess(preprocessFn, z.string()) : z.preprocess(preprocessFn, z.string().nullable());
|
|
84
|
+
const schema = baseSchema.superRefine((val, ctx) => {
|
|
85
|
+
if (val === null) return;
|
|
86
|
+
if (isRequired && (val === "" || val === "null" || val === "undefined")) {
|
|
87
|
+
ctx.addIssue({ code: "custom", message: getMessage("required") });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (!isRequired && val === "") return;
|
|
91
|
+
let ipPart = val;
|
|
92
|
+
let cidrPrefix = null;
|
|
93
|
+
const slashIndex = val.indexOf("/");
|
|
94
|
+
if (slashIndex !== -1) {
|
|
95
|
+
if (!allowCIDR) {
|
|
96
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
ipPart = val.substring(0, slashIndex);
|
|
100
|
+
cidrPrefix = val.substring(slashIndex + 1);
|
|
101
|
+
}
|
|
102
|
+
const isV4 = validateIPv4(ipPart);
|
|
103
|
+
const isV6 = validateIPv6(ipPart);
|
|
104
|
+
if (version === "v4") {
|
|
105
|
+
if (!isV4) {
|
|
106
|
+
ctx.addIssue({ code: "custom", message: getMessage("notIPv4") });
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
} else if (version === "v6") {
|
|
110
|
+
if (!isV6) {
|
|
111
|
+
ctx.addIssue({ code: "custom", message: getMessage("notIPv6") });
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
if (!isV4 && !isV6) {
|
|
116
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (cidrPrefix !== null) {
|
|
121
|
+
if (!/^\d+$/.test(cidrPrefix)) {
|
|
122
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const prefixNum = Number(cidrPrefix);
|
|
126
|
+
const maxPrefix = isV4 ? 32 : 128;
|
|
127
|
+
if (prefixNum < 0 || prefixNum > maxPrefix) {
|
|
128
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (whitelist && whitelist.length > 0) {
|
|
133
|
+
if (!whitelist.includes(val)) {
|
|
134
|
+
ctx.addIssue({ code: "custom", message: getMessage("notInWhitelist") });
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
return schema;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export {
|
|
143
|
+
validateIPv4,
|
|
144
|
+
validateIPv6,
|
|
145
|
+
ip
|
|
146
|
+
};
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkUCOXAZJFcjs = require('./chunk-UCOXAZJF.cjs');
|
|
5
|
+
|
|
6
|
+
// src/validators/common/time.ts
|
|
7
|
+
var _zod = require('zod');
|
|
8
|
+
var TIME_PATTERNS = {
|
|
9
|
+
"HH:mm": /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/,
|
|
10
|
+
"HH:mm:ss": /^([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/,
|
|
11
|
+
"hh:mm A": /^(0?[1-9]|1[0-2]):[0-5][0-9]\s?(AM|PM)$/i,
|
|
12
|
+
"hh:mm:ss A": /^(0?[1-9]|1[0-2]):[0-5][0-9]:[0-5][0-9]\s?(AM|PM)$/i,
|
|
13
|
+
"H:mm": /^([0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/,
|
|
14
|
+
"h:mm A": /^([1-9]|1[0-2]):[0-5][0-9]\s?(AM|PM)$/i
|
|
15
|
+
};
|
|
16
|
+
var parseTimeToMinutes = (timeStr, format) => {
|
|
17
|
+
const cleanTime = timeStr.trim();
|
|
18
|
+
try {
|
|
19
|
+
if (format.includes("A")) {
|
|
20
|
+
const match = cleanTime.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?\s?(AM|PM)$/i);
|
|
21
|
+
if (!match) return null;
|
|
22
|
+
const [, hourStr, minuteStr, , period] = match;
|
|
23
|
+
let hour = parseInt(hourStr, 10);
|
|
24
|
+
const minute = parseInt(minuteStr, 10);
|
|
25
|
+
if (hour < 1 || hour > 12 || minute < 0 || minute > 59) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (period.toUpperCase() === "PM" && hour !== 12) {
|
|
29
|
+
hour += 12;
|
|
30
|
+
} else if (period.toUpperCase() === "AM" && hour === 12) {
|
|
31
|
+
hour = 0;
|
|
32
|
+
}
|
|
33
|
+
return hour * 60 + minute;
|
|
34
|
+
} else {
|
|
35
|
+
const match = cleanTime.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/);
|
|
36
|
+
if (!match) return null;
|
|
37
|
+
const [, hourStr, minuteStr] = match;
|
|
38
|
+
const hour = parseInt(hourStr, 10);
|
|
39
|
+
const minute = parseInt(minuteStr, 10);
|
|
40
|
+
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
return hour * 60 + minute;
|
|
44
|
+
}
|
|
45
|
+
} catch (e) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var validateTimeFormat = (value, format) => {
|
|
50
|
+
const pattern = TIME_PATTERNS[format];
|
|
51
|
+
return pattern.test(value.trim());
|
|
52
|
+
};
|
|
53
|
+
var normalizeTime = (timeStr, format) => {
|
|
54
|
+
const cleanTime = timeStr.trim();
|
|
55
|
+
if (format.includes("A")) {
|
|
56
|
+
const match = cleanTime.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?\s?(AM|PM)$/i);
|
|
57
|
+
if (!match) return null;
|
|
58
|
+
const [, hourStr, minuteStr, secondStr = "00", period] = match;
|
|
59
|
+
let hour = parseInt(hourStr, 10);
|
|
60
|
+
const minute = parseInt(minuteStr, 10);
|
|
61
|
+
const second = parseInt(secondStr, 10);
|
|
62
|
+
if (period.toUpperCase() === "PM" && hour !== 12) {
|
|
63
|
+
hour += 12;
|
|
64
|
+
} else if (period.toUpperCase() === "AM" && hour === 12) {
|
|
65
|
+
hour = 0;
|
|
66
|
+
}
|
|
67
|
+
return format.includes("ss") ? `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}:${second.toString().padStart(2, "0")}` : `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}`;
|
|
68
|
+
}
|
|
69
|
+
if (format === "H:mm") {
|
|
70
|
+
const match = cleanTime.match(/^(\d{1,2}):(\d{2})$/);
|
|
71
|
+
if (!match) return null;
|
|
72
|
+
const [, hourStr, minuteStr] = match;
|
|
73
|
+
return `${hourStr.padStart(2, "0")}:${minuteStr}`;
|
|
74
|
+
}
|
|
75
|
+
return cleanTime;
|
|
76
|
+
};
|
|
77
|
+
function time(required, options) {
|
|
78
|
+
const {
|
|
79
|
+
format = "HH:mm",
|
|
80
|
+
min,
|
|
81
|
+
max,
|
|
82
|
+
minHour,
|
|
83
|
+
maxHour,
|
|
84
|
+
allowedHours,
|
|
85
|
+
minuteStep,
|
|
86
|
+
secondStep,
|
|
87
|
+
includes,
|
|
88
|
+
excludes,
|
|
89
|
+
regex,
|
|
90
|
+
trimMode = "trim",
|
|
91
|
+
casing = "none",
|
|
92
|
+
whitelist,
|
|
93
|
+
whitelistOnly = false,
|
|
94
|
+
transform,
|
|
95
|
+
defaultValue,
|
|
96
|
+
i18n
|
|
97
|
+
} = _nullishCoalesce(options, () => ( {}));
|
|
98
|
+
const isRequired = _nullishCoalesce(required, () => ( false));
|
|
99
|
+
const actualDefaultValue = _nullishCoalesce(defaultValue, () => ( (isRequired ? "" : null)));
|
|
100
|
+
const getMessage = (key, params) => {
|
|
101
|
+
if (i18n) {
|
|
102
|
+
const currentLocale = _chunkUCOXAZJFcjs.getLocale.call(void 0, );
|
|
103
|
+
const customMessages = i18n[currentLocale];
|
|
104
|
+
if (customMessages && customMessages[key]) {
|
|
105
|
+
const template = customMessages[key];
|
|
106
|
+
return template.replace(/\$\{(\w+)}/g, (_, k) => _nullishCoalesce(_optionalChain([params, 'optionalAccess', _2 => _2[k]]), () => ( "")));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return _chunkUCOXAZJFcjs.t.call(void 0, `common.time.${key}`, params);
|
|
110
|
+
};
|
|
111
|
+
const preprocessFn = (val) => {
|
|
112
|
+
if (val === null || val === void 0) {
|
|
113
|
+
return actualDefaultValue;
|
|
114
|
+
}
|
|
115
|
+
let processed = String(val);
|
|
116
|
+
switch (trimMode) {
|
|
117
|
+
case "trim":
|
|
118
|
+
processed = processed.trim();
|
|
119
|
+
break;
|
|
120
|
+
case "trimStart":
|
|
121
|
+
processed = processed.trimStart();
|
|
122
|
+
break;
|
|
123
|
+
case "trimEnd":
|
|
124
|
+
processed = processed.trimEnd();
|
|
125
|
+
break;
|
|
126
|
+
case "none":
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
if (processed === "") {
|
|
130
|
+
if (whitelist && whitelist.includes("")) {
|
|
131
|
+
return "";
|
|
132
|
+
}
|
|
133
|
+
if (!isRequired) {
|
|
134
|
+
return actualDefaultValue;
|
|
135
|
+
}
|
|
136
|
+
return actualDefaultValue;
|
|
137
|
+
}
|
|
138
|
+
switch (casing) {
|
|
139
|
+
case "upper":
|
|
140
|
+
processed = processed.toUpperCase();
|
|
141
|
+
break;
|
|
142
|
+
case "lower":
|
|
143
|
+
processed = processed.toLowerCase();
|
|
144
|
+
break;
|
|
145
|
+
case "none":
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
if (transform) {
|
|
149
|
+
processed = transform(processed);
|
|
150
|
+
}
|
|
151
|
+
return processed;
|
|
152
|
+
};
|
|
153
|
+
const baseSchema = isRequired ? _zod.z.preprocess(preprocessFn, _zod.z.string()) : _zod.z.preprocess(preprocessFn, _zod.z.string().nullable());
|
|
154
|
+
const schema = baseSchema.superRefine((val, ctx) => {
|
|
155
|
+
if (val === null) return;
|
|
156
|
+
if (isRequired && (val === "" || val === "null" || val === "undefined")) {
|
|
157
|
+
ctx.addIssue({ code: "custom", message: getMessage("required") });
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (val === null) return;
|
|
161
|
+
if (!isRequired && val === "") return;
|
|
162
|
+
if (whitelist && whitelist.length > 0) {
|
|
163
|
+
if (whitelist.includes(val)) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (whitelistOnly) {
|
|
167
|
+
ctx.addIssue({ code: "custom", message: getMessage("notInWhitelist") });
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (regex) {
|
|
172
|
+
if (!regex.test(val)) {
|
|
173
|
+
ctx.addIssue({ code: "custom", message: getMessage("customRegex") });
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
if (!validateTimeFormat(val, format)) {
|
|
178
|
+
ctx.addIssue({ code: "custom", message: getMessage("format", { format }) });
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (includes && !val.includes(includes)) {
|
|
183
|
+
ctx.addIssue({ code: "custom", message: getMessage("includes", { includes }) });
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (excludes) {
|
|
187
|
+
const excludeList = Array.isArray(excludes) ? excludes : [excludes];
|
|
188
|
+
for (const exclude of excludeList) {
|
|
189
|
+
if (val.includes(exclude)) {
|
|
190
|
+
ctx.addIssue({ code: "custom", message: getMessage("excludes", { excludes: exclude }) });
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (regex) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const timeMinutes = parseTimeToMinutes(val, format);
|
|
199
|
+
if (timeMinutes === null) {
|
|
200
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const hour = Math.floor(timeMinutes / 60);
|
|
204
|
+
if (minHour !== void 0 && hour < minHour) {
|
|
205
|
+
ctx.addIssue({ code: "custom", message: getMessage("hour", { minHour, maxHour: _nullishCoalesce(maxHour, () => ( 23)) }) });
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (maxHour !== void 0 && hour > maxHour) {
|
|
209
|
+
ctx.addIssue({ code: "custom", message: getMessage("hour", { minHour: _nullishCoalesce(minHour, () => ( 0)), maxHour }) });
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (allowedHours && allowedHours.length > 0) {
|
|
213
|
+
if (!allowedHours.includes(hour)) {
|
|
214
|
+
ctx.addIssue({ code: "custom", message: getMessage("hour", { allowedHours: allowedHours.join(", ") }) });
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const minute = timeMinutes % 60;
|
|
219
|
+
if (minuteStep !== void 0 && minute % minuteStep !== 0) {
|
|
220
|
+
ctx.addIssue({ code: "custom", message: getMessage("minute", { minuteStep }) });
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (secondStep !== void 0 && format.includes("ss")) {
|
|
224
|
+
const secondMatch = val.match(/:(\d{2})$/);
|
|
225
|
+
if (secondMatch) {
|
|
226
|
+
const seconds = parseInt(secondMatch[1], 10);
|
|
227
|
+
if (seconds % secondStep !== 0) {
|
|
228
|
+
ctx.addIssue({ code: "custom", message: getMessage("second", { secondStep }) });
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (min) {
|
|
234
|
+
const minMinutes = parseTimeToMinutes(min, format);
|
|
235
|
+
if (minMinutes !== null && timeMinutes < minMinutes) {
|
|
236
|
+
ctx.addIssue({ code: "custom", message: getMessage("min", { min }) });
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (max) {
|
|
241
|
+
const maxMinutes = parseTimeToMinutes(max, format);
|
|
242
|
+
if (maxMinutes !== null && timeMinutes > maxMinutes) {
|
|
243
|
+
ctx.addIssue({ code: "custom", message: getMessage("max", { max }) });
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
return schema;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
exports.TIME_PATTERNS = TIME_PATTERNS; exports.parseTimeToMinutes = parseTimeToMinutes; exports.validateTimeFormat = validateTimeFormat; exports.normalizeTime = normalizeTime; exports.time = time;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkUCOXAZJFcjs = require('./chunk-UCOXAZJF.cjs');
|
|
5
|
+
|
|
6
|
+
// src/validators/common/coordinate.ts
|
|
7
|
+
var _zod = require('zod');
|
|
8
|
+
function validateLatitude(value) {
|
|
9
|
+
return Number.isFinite(value) && value >= -90 && value <= 90;
|
|
10
|
+
}
|
|
11
|
+
function validateLongitude(value) {
|
|
12
|
+
return Number.isFinite(value) && value >= -180 && value <= 180;
|
|
13
|
+
}
|
|
14
|
+
function validatePrecision(value, precision) {
|
|
15
|
+
const decimalPart = value.toString().split(".")[1];
|
|
16
|
+
if (!decimalPart) return true;
|
|
17
|
+
return decimalPart.length <= precision;
|
|
18
|
+
}
|
|
19
|
+
function coordinate(required, options) {
|
|
20
|
+
const { type = "pair", precision, transform, defaultValue, i18n } = _nullishCoalesce(options, () => ( {}));
|
|
21
|
+
const isRequired = _nullishCoalesce(required, () => ( false));
|
|
22
|
+
const actualDefaultValue = _nullishCoalesce(defaultValue, () => ( (isRequired ? "" : null)));
|
|
23
|
+
const getMessage = (key, params) => {
|
|
24
|
+
if (i18n) {
|
|
25
|
+
const currentLocale = _chunkUCOXAZJFcjs.getLocale.call(void 0, );
|
|
26
|
+
const customMessages = i18n[currentLocale];
|
|
27
|
+
if (customMessages && customMessages[key]) {
|
|
28
|
+
const template = customMessages[key];
|
|
29
|
+
return template.replace(/\$\{(\w+)}/g, (_, k) => _nullishCoalesce(_optionalChain([params, 'optionalAccess', _2 => _2[k]]), () => ( "")));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return _chunkUCOXAZJFcjs.t.call(void 0, `common.coordinate.${key}`, params);
|
|
33
|
+
};
|
|
34
|
+
const preprocessFn = (val) => {
|
|
35
|
+
if (val === "" || val === null || val === void 0) {
|
|
36
|
+
return actualDefaultValue;
|
|
37
|
+
}
|
|
38
|
+
let processed = String(val).trim();
|
|
39
|
+
if (processed === "" && !required) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
if (transform) {
|
|
43
|
+
processed = transform(processed);
|
|
44
|
+
}
|
|
45
|
+
return processed;
|
|
46
|
+
};
|
|
47
|
+
const baseSchema = isRequired ? _zod.z.preprocess(preprocessFn, _zod.z.string()) : _zod.z.preprocess(preprocessFn, _zod.z.string().nullable());
|
|
48
|
+
const schema = baseSchema.superRefine((val, ctx) => {
|
|
49
|
+
if (val === null) return;
|
|
50
|
+
if (isRequired && (val === "" || val === "null" || val === "undefined")) {
|
|
51
|
+
ctx.addIssue({ code: "custom", message: getMessage("required") });
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (!isRequired && val === "") return;
|
|
55
|
+
if (type === "pair") {
|
|
56
|
+
const parts = val.split(",");
|
|
57
|
+
if (parts.length !== 2) {
|
|
58
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const lat = Number(parts[0].trim());
|
|
62
|
+
const lng = Number(parts[1].trim());
|
|
63
|
+
if (isNaN(lat) || isNaN(lng)) {
|
|
64
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (!validateLatitude(lat)) {
|
|
68
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalidLatitude") });
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (!validateLongitude(lng)) {
|
|
72
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalidLongitude") });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (precision !== void 0) {
|
|
76
|
+
if (!validatePrecision(lat, precision) || !validatePrecision(lng, precision)) {
|
|
77
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} else if (type === "latitude") {
|
|
82
|
+
const num = Number(val);
|
|
83
|
+
if (isNaN(num)) {
|
|
84
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalidLatitude") });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (!validateLatitude(num)) {
|
|
88
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalidLatitude") });
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (precision !== void 0 && !validatePrecision(num, precision)) {
|
|
92
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
} else if (type === "longitude") {
|
|
96
|
+
const num = Number(val);
|
|
97
|
+
if (isNaN(num)) {
|
|
98
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalidLongitude") });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (!validateLongitude(num)) {
|
|
102
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalidLongitude") });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (precision !== void 0 && !validatePrecision(num, precision)) {
|
|
106
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
return schema;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
exports.validateLatitude = validateLatitude; exports.validateLongitude = validateLongitude; exports.coordinate = coordinate;
|