@hy_ong/zod-kit 0.0.4 → 0.0.6

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.
Files changed (59) hide show
  1. package/.claude/settings.local.json +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +465 -97
  4. package/debug.js +21 -0
  5. package/debug.ts +16 -0
  6. package/dist/index.cjs +3127 -146
  7. package/dist/index.d.cts +3021 -25
  8. package/dist/index.d.ts +3021 -25
  9. package/dist/index.js +3081 -144
  10. package/eslint.config.mts +8 -0
  11. package/package.json +10 -9
  12. package/src/config.ts +1 -1
  13. package/src/i18n/locales/en.json +161 -25
  14. package/src/i18n/locales/zh-TW.json +165 -26
  15. package/src/index.ts +17 -7
  16. package/src/validators/common/boolean.ts +191 -0
  17. package/src/validators/common/date.ts +299 -0
  18. package/src/validators/common/datetime.ts +673 -0
  19. package/src/validators/common/email.ts +313 -0
  20. package/src/validators/common/file.ts +384 -0
  21. package/src/validators/common/id.ts +471 -0
  22. package/src/validators/common/number.ts +319 -0
  23. package/src/validators/common/password.ts +386 -0
  24. package/src/validators/common/text.ts +271 -0
  25. package/src/validators/common/time.ts +600 -0
  26. package/src/validators/common/url.ts +347 -0
  27. package/src/validators/taiwan/business-id.ts +262 -0
  28. package/src/validators/taiwan/fax.ts +327 -0
  29. package/src/validators/taiwan/mobile.ts +242 -0
  30. package/src/validators/taiwan/national-id.ts +425 -0
  31. package/src/validators/taiwan/postal-code.ts +1049 -0
  32. package/src/validators/taiwan/tel.ts +330 -0
  33. package/tests/common/boolean.test.ts +340 -92
  34. package/tests/common/date.test.ts +458 -0
  35. package/tests/common/datetime.test.ts +693 -0
  36. package/tests/common/email.test.ts +232 -60
  37. package/tests/common/file.test.ts +479 -0
  38. package/tests/common/id.test.ts +535 -0
  39. package/tests/common/number.test.ts +230 -60
  40. package/tests/common/password.test.ts +271 -44
  41. package/tests/common/text.test.ts +210 -13
  42. package/tests/common/time.test.ts +528 -0
  43. package/tests/common/url.test.ts +492 -67
  44. package/tests/taiwan/business-id.test.ts +240 -0
  45. package/tests/taiwan/fax.test.ts +463 -0
  46. package/tests/taiwan/mobile.test.ts +373 -0
  47. package/tests/taiwan/national-id.test.ts +435 -0
  48. package/tests/taiwan/postal-code.test.ts +705 -0
  49. package/tests/taiwan/tel.test.ts +467 -0
  50. package/eslint.config.mjs +0 -10
  51. package/src/common/boolean.ts +0 -36
  52. package/src/common/date.ts +0 -43
  53. package/src/common/email.ts +0 -44
  54. package/src/common/integer.ts +0 -46
  55. package/src/common/number.ts +0 -37
  56. package/src/common/password.ts +0 -33
  57. package/src/common/text.ts +0 -34
  58. package/src/common/url.ts +0 -37
  59. package/tests/common/integer.test.ts +0 -90
package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,24 +17,66 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
21
31
  var index_exports = {};
22
32
  __export(index_exports, {
33
+ DATETIME_PATTERNS: () => DATETIME_PATTERNS,
34
+ ID_PATTERNS: () => ID_PATTERNS,
35
+ TIME_PATTERNS: () => TIME_PATTERNS,
36
+ VALID_3_DIGIT_PREFIXES: () => VALID_3_DIGIT_PREFIXES,
23
37
  boolean: () => boolean,
38
+ businessId: () => businessId,
39
+ date: () => date,
40
+ datetime: () => datetime,
41
+ detectIdType: () => detectIdType,
24
42
  email: () => email,
43
+ fax: () => fax,
44
+ file: () => file,
25
45
  getLocale: () => getLocale,
26
- integer: () => integer,
46
+ id: () => id,
47
+ mobile: () => mobile,
48
+ nationalId: () => nationalId,
49
+ normalizeDateTimeValue: () => normalizeDateTimeValue,
50
+ normalizeTime: () => normalizeTime,
27
51
  number: () => number,
52
+ parseDateTimeValue: () => parseDateTimeValue,
53
+ parseTimeToMinutes: () => parseTimeToMinutes,
28
54
  password: () => password,
55
+ postalCode: () => postalCode,
29
56
  setLocale: () => setLocale,
57
+ tel: () => tel,
30
58
  text: () => text,
31
- url: () => url
59
+ time: () => time,
60
+ url: () => url,
61
+ validate3DigitPostalCode: () => validate3DigitPostalCode,
62
+ validate5DigitPostalCode: () => validate5DigitPostalCode,
63
+ validate6DigitPostalCode: () => validate6DigitPostalCode,
64
+ validateCitizenId: () => validateCitizenId,
65
+ validateDateTimeFormat: () => validateDateTimeFormat,
66
+ validateIdType: () => validateIdType,
67
+ validateNewResidentId: () => validateNewResidentId,
68
+ validateOldResidentId: () => validateOldResidentId,
69
+ validateTaiwanBusinessId: () => validateTaiwanBusinessId,
70
+ validateTaiwanFax: () => validateTaiwanFax,
71
+ validateTaiwanMobile: () => validateTaiwanMobile,
72
+ validateTaiwanNationalId: () => validateTaiwanNationalId,
73
+ validateTaiwanPostalCode: () => validateTaiwanPostalCode,
74
+ validateTaiwanTel: () => validateTaiwanTel,
75
+ validateTimeFormat: () => validateTimeFormat
32
76
  });
33
77
  module.exports = __toCommonJS(index_exports);
34
78
 
35
- // src/common/boolean.ts
79
+ // src/validators/common/boolean.ts
36
80
  var import_zod = require("zod");
37
81
 
38
82
  // src/i18n/locales/zh-TW.json
@@ -40,25 +84,40 @@ var zh_TW_default = {
40
84
  common: {
41
85
  boolean: {
42
86
  required: "\u5FC5\u586B",
43
- shouldBe: {
44
- true: "\u5FC5\u9808\u70BA\u662F",
45
- false: "\u5FC5\u9808\u70BA\u5426"
46
- }
87
+ shouldBeTrue: "\u5FC5\u9808\u70BA\u662F",
88
+ shouldBeFalse: "\u5FC5\u9808\u70BA\u5426",
89
+ invalid: "\u5FC5\u9808\u70BA\u5E03\u6797\u503C"
47
90
  },
48
91
  email: {
49
92
  required: "\u5FC5\u586B",
50
- min: "\u9577\u5EA6\u81F3\u5C11 ${min} \u5B57\u5143",
51
- max: "\u9577\u5EA6\u6700\u591A ${max} \u5B57\u5143",
93
+ invalid: "\u96FB\u5B50\u90F5\u4EF6\u683C\u5F0F\u932F\u8AA4",
94
+ minLength: "\u9577\u5EA6\u81F3\u5C11 ${minLength} \u5B57\u5143",
95
+ maxLength: "\u9577\u5EA6\u6700\u591A ${maxLength} \u5B57\u5143",
52
96
  includes: "\u5FC5\u9808\u5305\u542B\u300C${includes}\u300D",
53
- invalid: "\u683C\u5F0F\u932F\u8AA4",
54
- domain: "\u5FC5\u9808\u70BA @${domain} \u7DB2\u57DF"
97
+ domain: "\u5FC5\u9808\u70BA ${domain} \u7DB2\u57DF",
98
+ domainBlacklist: "\u4E0D\u5141\u8A31\u4F7F\u7528 ${domain} \u7DB2\u57DF",
99
+ businessOnly: "\u50C5\u5141\u8A31\u4F01\u696D\u90F5\u7BB1\u5730\u5740",
100
+ noDisposable: "\u4E0D\u5141\u8A31\u4F7F\u7528\u81E8\u6642\u90F5\u7BB1\u5730\u5740"
55
101
  },
56
102
  url: {
57
103
  required: "\u5FC5\u586B",
104
+ invalid: "\u7121\u6548\u7684 URL \u683C\u5F0F",
58
105
  min: "\u9577\u5EA6\u81F3\u5C11 ${min} \u5B57\u5143",
59
106
  max: "\u9577\u5EA6\u6700\u591A ${max} \u5B57\u5143",
60
107
  includes: "\u5FC5\u9808\u5305\u542B\u300C${includes}\u300D",
61
- invalid: "\u683C\u5F0F\u932F\u8AA4"
108
+ excludes: "\u4E0D\u5F97\u5305\u542B\u300C${excludes}\u300D",
109
+ protocol: "\u5354\u8B70\u5FC5\u9808\u70BA\uFF1A${protocols}",
110
+ domain: "\u7DB2\u57DF\u5FC5\u9808\u70BA\uFF1A${domains}",
111
+ domainBlacklist: "\u4E0D\u5141\u8A31\u4F7F\u7528\u7DB2\u57DF ${domain}",
112
+ port: "\u9023\u63A5\u57E0\u5FC5\u9808\u70BA\uFF1A${ports}",
113
+ pathStartsWith: "\u8DEF\u5F91\u5FC5\u9808\u4EE5\u300C${path}\u300D\u958B\u982D",
114
+ pathEndsWith: "\u8DEF\u5F91\u5FC5\u9808\u4EE5\u300C${path}\u300D\u7D50\u5C3E",
115
+ hasQuery: "URL \u5FC5\u9808\u5305\u542B\u67E5\u8A62\u53C3\u6578",
116
+ noQuery: "URL \u4E0D\u5F97\u5305\u542B\u67E5\u8A62\u53C3\u6578",
117
+ hasFragment: "URL \u5FC5\u9808\u5305\u542B\u9328\u9EDE",
118
+ noFragment: "URL \u4E0D\u5F97\u5305\u542B\u9328\u9EDE",
119
+ localhost: "\u4E0D\u5141\u8A31\u4F7F\u7528\u672C\u6A5F URL",
120
+ noLocalhost: "\u4E0D\u5141\u8A31\u4F7F\u7528\u672C\u6A5F URL"
62
121
  },
63
122
  password: {
64
123
  required: "\u5FC5\u586B",
@@ -67,37 +126,161 @@ var zh_TW_default = {
67
126
  uppercase: "\u5FC5\u9808\u5305\u542B\u81F3\u5C11\u4E00\u500B\u5927\u5BEB\u5B57\u6BCD",
68
127
  lowercase: "\u5FC5\u9808\u5305\u542B\u81F3\u5C11\u4E00\u500B\u5C0F\u5BEB\u5B57\u6BCD",
69
128
  digits: "\u5FC5\u9808\u5305\u542B\u81F3\u5C11\u4E00\u500B\u6578\u5B57",
70
- special: "\u5FC5\u9808\u5305\u542B\u81F3\u5C11\u4E00\u500B\u7279\u6B8A\u7B26\u865F"
129
+ special: "\u5FC5\u9808\u5305\u542B\u81F3\u5C11\u4E00\u500B\u7279\u6B8A\u7B26\u865F",
130
+ noRepeating: "\u4E0D\u53EF\u5305\u542B\u91CD\u8907\u5B57\u5143",
131
+ noSequential: "\u4E0D\u53EF\u5305\u542B\u9023\u7E8C\u5B57\u5143",
132
+ noCommonWords: "\u4E0D\u53EF\u5305\u542B\u5E38\u898B\u5BC6\u78BC\u6216\u6A21\u5F0F",
133
+ minStrength: "\u5BC6\u78BC\u5F37\u5EA6\u5FC5\u9808\u81F3\u5C11\u70BA ${minStrength}",
134
+ excludes: "\u4E0D\u5F97\u5305\u542B\u300C${excludes}\u300D",
135
+ includes: "\u5FC5\u9808\u5305\u542B\u300C${includes}\u300D",
136
+ invalid: "\u5BC6\u78BC\u683C\u5F0F\u932F\u8AA4"
71
137
  },
72
138
  number: {
73
139
  required: "\u5FC5\u586B",
74
- min: "\u6700\u5C0F\u503C ${min}",
75
- max: "\u6700\u5927\u503C ${max}"
76
- },
77
- id: {
78
- required: "\u8ACB\u9078\u64C7",
79
- invalid: "\u7121\u6548"
80
- },
81
- integer: {
82
- required: "\u5FC5\u586B",
140
+ invalid: "\u5FC5\u9808\u70BA\u6709\u6548\u6578\u5B57",
141
+ integer: "\u5FC5\u9808\u70BA\u6574\u6578",
142
+ float: "\u5FC5\u9808\u70BA\u5C0F\u6578",
83
143
  min: "\u6700\u5C0F\u503C ${min}",
84
144
  max: "\u6700\u5927\u503C ${max}",
85
- integer: "\u5FC5\u9808\u70BA\u6574\u6578"
145
+ positive: "\u5FC5\u9808\u70BA\u6B63\u6578",
146
+ negative: "\u5FC5\u9808\u70BA\u8CA0\u6578",
147
+ nonNegative: "\u4E0D\u53EF\u70BA\u8CA0\u6578",
148
+ nonPositive: "\u4E0D\u53EF\u70BA\u6B63\u6578",
149
+ multipleOf: "\u5FC5\u9808\u70BA ${multipleOf} \u7684\u500D\u6578",
150
+ finite: "\u5FC5\u9808\u70BA\u6709\u9650\u6578\u5B57",
151
+ precision: "\u5C0F\u6578\u4F4D\u6578\u4E0D\u53EF\u8D85\u904E ${precision} \u4F4D"
86
152
  },
87
- float: {
153
+ id: {
88
154
  required: "\u5FC5\u586B",
89
- float: "\u5FC5\u9808\u70BA\u6D6E\u9EDE\u6578",
90
- min: "\u6700\u5C0F\u503C ${min}",
91
- max: "\u6700\u5927\u503C ${max}"
155
+ invalid: "\u7121\u6548\u7684 ID \u683C\u5F0F",
156
+ minLength: "\u9577\u5EA6\u81F3\u5C11 ${minLength} \u5B57\u5143",
157
+ maxLength: "\u9577\u5EA6\u6700\u591A ${maxLength} \u5B57\u5143",
158
+ numeric: "\u5FC5\u9808\u70BA\u6578\u5B57 ID",
159
+ uuid: "\u5FC5\u9808\u70BA\u6709\u6548\u7684 UUID",
160
+ objectId: "\u5FC5\u9808\u70BA\u6709\u6548\u7684 MongoDB ObjectId",
161
+ nanoid: "\u5FC5\u9808\u70BA\u6709\u6548\u7684 Nano ID",
162
+ snowflake: "\u5FC5\u9808\u70BA\u6709\u6548\u7684 Snowflake ID",
163
+ cuid: "\u5FC5\u9808\u70BA\u6709\u6548\u7684 CUID",
164
+ ulid: "\u5FC5\u9808\u70BA\u6709\u6548\u7684 ULID",
165
+ shortid: "\u5FC5\u9808\u70BA\u6709\u6548\u7684 Short ID",
166
+ customFormat: "\u7121\u6548\u7684 ID \u683C\u5F0F",
167
+ includes: "\u5FC5\u9808\u5305\u542B\u300C${includes}\u300D",
168
+ excludes: "\u4E0D\u5F97\u5305\u542B\u300C${excludes}\u300D",
169
+ startsWith: "\u5FC5\u9808\u4EE5\u300C${startsWith}\u300D\u958B\u982D",
170
+ endsWith: "\u5FC5\u9808\u4EE5\u300C${endsWith}\u300D\u7D50\u5C3E"
92
171
  },
93
172
  text: {
94
173
  required: "\u5FC5\u586B",
95
- min: "\u9577\u5EA6\u81F3\u5C11 ${min} \u5B57\u5143",
96
- max: "\u9577\u5EA6\u6700\u591A ${max} \u5B57\u5143",
174
+ notEmpty: "\u4E0D\u53EF\u70BA\u7A7A\u767D\u6216\u50C5\u542B\u7A7A\u683C",
175
+ minLength: "\u9577\u5EA6\u81F3\u5C11 ${minLength} \u5B57\u5143",
176
+ maxLength: "\u9577\u5EA6\u6700\u591A ${maxLength} \u5B57\u5143",
97
177
  startsWith: "\u5FC5\u9808\u4EE5\u300C${startsWith}\u300D\u958B\u982D",
98
178
  endsWith: "\u5FC5\u9808\u4EE5\u300C${endsWith}\u300D\u7D50\u5C3E",
99
179
  includes: "\u5FC5\u9808\u5305\u542B\u300C${includes}\u300D",
180
+ excludes: "\u4E0D\u5F97\u5305\u542B\u300C${excludes}\u300D",
100
181
  invalid: "\u683C\u5F0F\u932F\u8AA4"
182
+ },
183
+ date: {
184
+ required: "\u5FC5\u586B",
185
+ invalid: "\u7121\u6548\u65E5\u671F",
186
+ format: "\u5FC5\u9808\u70BA ${format} \u683C\u5F0F",
187
+ min: "\u65E5\u671F\u4E0D\u5F97\u65E9\u65BC ${min}",
188
+ max: "\u65E5\u671F\u4E0D\u5F97\u665A\u65BC ${max}",
189
+ includes: "\u5FC5\u9808\u5305\u542B\u300C${includes}\u300D",
190
+ excludes: "\u4E0D\u5F97\u5305\u542B\u300C${excludes}\u300D",
191
+ past: "\u5FC5\u9808\u70BA\u904E\u53BB\u7684\u65E5\u671F",
192
+ future: "\u5FC5\u9808\u70BA\u672A\u4F86\u7684\u65E5\u671F",
193
+ today: "\u5FC5\u9808\u70BA\u4ECA\u5929",
194
+ notToday: "\u4E0D\u5F97\u70BA\u4ECA\u5929",
195
+ weekday: "\u5FC5\u9808\u70BA\u5DE5\u4F5C\u65E5\uFF08\u9031\u4E00\u81F3\u9031\u4E94\uFF09",
196
+ weekend: "\u5FC5\u9808\u70BA\u9031\u672B\uFF08\u9031\u516D\u81F3\u9031\u65E5\uFF09"
197
+ },
198
+ time: {
199
+ required: "\u5FC5\u586B",
200
+ invalid: "\u7121\u6548\u7684\u6642\u9593\u683C\u5F0F",
201
+ format: "\u5FC5\u9808\u70BA ${format} \u683C\u5F0F",
202
+ min: "\u6642\u9593\u4E0D\u5F97\u65E9\u65BC ${min}",
203
+ max: "\u6642\u9593\u4E0D\u5F97\u665A\u65BC ${max}",
204
+ hour: "\u5C0F\u6642\u5FC5\u9808\u4ECB\u65BC ${minHour} \u8207 ${maxHour} \u4E4B\u9593",
205
+ minute: "\u5206\u9418\u5FC5\u9808\u70BA ${minuteStep} \u5206\u9418\u9593\u9694",
206
+ second: "\u79D2\u6578\u5FC5\u9808\u70BA ${secondStep} \u79D2\u9593\u9694",
207
+ includes: "\u5FC5\u9808\u5305\u542B\u300C${includes}\u300D",
208
+ excludes: "\u4E0D\u5F97\u5305\u542B\u300C${excludes}\u300D",
209
+ customRegex: "\u7121\u6548\u7684\u6642\u9593\u683C\u5F0F",
210
+ notInWhitelist: "\u6642\u9593\u4E0D\u5728\u5141\u8A31\u6E05\u55AE\u4E2D"
211
+ },
212
+ datetime: {
213
+ required: "\u5FC5\u586B",
214
+ invalid: "\u7121\u6548\u7684\u65E5\u671F\u6642\u9593\u683C\u5F0F",
215
+ format: "\u5FC5\u9808\u70BA ${format} \u683C\u5F0F",
216
+ min: "\u65E5\u671F\u6642\u9593\u4E0D\u5F97\u65E9\u65BC ${min}",
217
+ max: "\u65E5\u671F\u6642\u9593\u4E0D\u5F97\u665A\u65BC ${max}",
218
+ hour: "\u5C0F\u6642\u5FC5\u9808\u4ECB\u65BC ${minHour} \u8207 ${maxHour} \u4E4B\u9593",
219
+ minute: "\u5206\u9418\u5FC5\u9808\u70BA ${minuteStep} \u5206\u9418\u9593\u9694",
220
+ includes: "\u5FC5\u9808\u5305\u542B\u300C${includes}\u300D",
221
+ excludes: "\u4E0D\u5F97\u5305\u542B\u300C${excludes}\u300D",
222
+ past: "\u5FC5\u9808\u70BA\u904E\u53BB\u7684\u65E5\u671F\u6642\u9593",
223
+ future: "\u5FC5\u9808\u70BA\u672A\u4F86\u7684\u65E5\u671F\u6642\u9593",
224
+ today: "\u5FC5\u9808\u70BA\u4ECA\u5929",
225
+ notToday: "\u4E0D\u5F97\u70BA\u4ECA\u5929",
226
+ weekday: "\u5FC5\u9808\u70BA\u5DE5\u4F5C\u65E5\uFF08\u9031\u4E00\u81F3\u9031\u4E94\uFF09",
227
+ weekend: "\u5FC5\u9808\u70BA\u9031\u672B\uFF08\u9031\u516D\u81F3\u9031\u65E5\uFF09",
228
+ customRegex: "\u7121\u6548\u7684\u65E5\u671F\u6642\u9593\u683C\u5F0F",
229
+ notInWhitelist: "\u65E5\u671F\u6642\u9593\u4E0D\u5728\u5141\u8A31\u6E05\u55AE\u4E2D"
230
+ },
231
+ file: {
232
+ required: "\u5FC5\u586B",
233
+ invalid: "\u7121\u6548\u7684\u6A94\u6848\u683C\u5F0F",
234
+ size: "\u6A94\u6848\u5927\u5C0F\u4E0D\u5F97\u8D85\u904E ${size}",
235
+ minSize: "\u6A94\u6848\u5927\u5C0F\u81F3\u5C11 ${minSize}",
236
+ maxSize: "\u6A94\u6848\u5927\u5C0F\u4E0D\u5F97\u8D85\u904E ${maxSize}",
237
+ type: "\u6A94\u6848\u985E\u578B\u5FC5\u9808\u70BA\uFF1A${type}",
238
+ extension: "\u526F\u6A94\u540D\u5FC5\u9808\u70BA\uFF1A${extension}",
239
+ extensionBlacklist: "\u4E0D\u5141\u8A31\u4F7F\u7528\u526F\u6A94\u540D ${extension}",
240
+ name: "\u6A94\u6848\u540D\u7A31\u5FC5\u9808\u7B26\u5408\u683C\u5F0F ${pattern}",
241
+ nameBlacklist: "\u6A94\u6848\u540D\u7A31\u4E0D\u5F97\u7B26\u5408\u683C\u5F0F ${pattern}",
242
+ imageOnly: "\u50C5\u5141\u8A31\u5716\u7247\u6A94\u6848",
243
+ documentOnly: "\u50C5\u5141\u8A31\u6587\u4EF6\u6A94\u6848",
244
+ videoOnly: "\u50C5\u5141\u8A31\u5F71\u7247\u6A94\u6848",
245
+ audioOnly: "\u50C5\u5141\u8A31\u97F3\u8A0A\u6A94\u6848",
246
+ archiveOnly: "\u50C5\u5141\u8A31\u58D3\u7E2E\u6A94\u6848"
247
+ }
248
+ },
249
+ taiwan: {
250
+ businessId: {
251
+ required: "\u5FC5\u586B",
252
+ invalid: "\u7121\u6548\u7684\u7D71\u4E00\u7DE8\u865F"
253
+ },
254
+ nationalId: {
255
+ required: "\u5FC5\u586B",
256
+ invalid: "\u7121\u6548\u7684\u8EAB\u5206\u8B49\u5B57\u865F"
257
+ },
258
+ mobile: {
259
+ required: "\u5FC5\u586B",
260
+ invalid: "\u7121\u6548\u7684\u624B\u6A5F\u865F\u78BC\u683C\u5F0F",
261
+ notInWhitelist: "\u4E0D\u5728\u5141\u8A31\u7684\u624B\u6A5F\u865F\u78BC\u6E05\u55AE\u4E2D"
262
+ },
263
+ tel: {
264
+ required: "\u5FC5\u586B",
265
+ invalid: "\u7121\u6548\u7684\u5E02\u8A71\u865F\u78BC\u683C\u5F0F",
266
+ notInWhitelist: "\u4E0D\u5728\u5141\u8A31\u7684\u5E02\u8A71\u865F\u78BC\u6E05\u55AE\u4E2D"
267
+ },
268
+ fax: {
269
+ required: "\u5FC5\u586B",
270
+ invalid: "\u7121\u6548\u7684\u50B3\u771F\u865F\u78BC\u683C\u5F0F",
271
+ notInWhitelist: "\u4E0D\u5728\u5141\u8A31\u7684\u50B3\u771F\u865F\u78BC\u6E05\u55AE\u4E2D"
272
+ },
273
+ postalCode: {
274
+ required: "\u5FC5\u586B",
275
+ invalid: "\u7121\u6548\u7684\u90F5\u905E\u5340\u865F",
276
+ invalidFormat: "\u90F5\u905E\u5340\u865F\u683C\u5F0F\u932F\u8AA4",
277
+ invalidRange: "\u90F5\u905E\u5340\u865F\u8D85\u51FA\u6709\u6548\u7BC4\u570D",
278
+ legacy5DigitWarning: "5 \u78BC\u90F5\u905E\u5340\u865F\u70BA\u820A\u5F0F\u683C\u5F0F\uFF0C\u5EFA\u8B70\u4F7F\u7528 6 \u78BC\u683C\u5F0F",
279
+ format3Only: "\u50C5\u5141\u8A31 3 \u78BC\u90F5\u905E\u5340\u865F",
280
+ format5Only: "\u50C5\u5141\u8A31 5 \u78BC\u90F5\u905E\u5340\u865F",
281
+ format6Only: "\u50C5\u5141\u8A31 6 \u78BC\u90F5\u905E\u5340\u865F",
282
+ invalidSuffix: "\u7121\u6548\u7684\u90F5\u905E\u5340\u865F\u5F8C\u78BC - 5 \u78BC\u683C\u5F0F\u9808\u70BA 01-99\uFF0C6 \u78BC\u683C\u5F0F\u9808\u70BA 001-999",
283
+ deprecated5Digit: "5 \u78BC\u90F5\u905E\u5340\u865F\u5DF2\u68C4\u7528\u4E14\u4E0D\u518D\u652F\u63F4"
101
284
  }
102
285
  }
103
286
  };
@@ -107,25 +290,40 @@ var en_default = {
107
290
  common: {
108
291
  boolean: {
109
292
  required: "Required",
110
- shouldBe: {
111
- true: "Must be True",
112
- false: "Must be False"
113
- }
293
+ shouldBeTrue: "Must be True",
294
+ shouldBeFalse: "Must be False",
295
+ invalid: "Must be a boolean value"
114
296
  },
115
297
  email: {
116
298
  required: "Required",
117
- min: "Must be at least ${min} characters",
118
- max: "Must be at most ${max} characters",
299
+ invalid: "Invalid email format",
300
+ minLength: "Must be at least ${minLength} characters",
301
+ maxLength: "Must be at most ${maxLength} characters",
119
302
  includes: "Must include ${includes}",
120
- invalid: "Invalid format",
121
- domain: "Must be under the domain @${domain}"
303
+ domain: "Must be from domain: ${domain}",
304
+ domainBlacklist: "Domain ${domain} is not allowed",
305
+ businessOnly: "Only business email addresses are allowed",
306
+ noDisposable: "Disposable email addresses are not allowed"
122
307
  },
123
308
  url: {
124
309
  required: "Required",
310
+ invalid: "Invalid URL format",
125
311
  min: "Must be at least ${min} characters",
126
312
  max: "Must be at most ${max} characters",
127
313
  includes: "Must include ${includes}",
128
- invalid: "Invalid format"
314
+ excludes: "Must not contain ${excludes}",
315
+ protocol: "Protocol must be one of: ${protocols}",
316
+ domain: "Domain must be one of: ${domains}",
317
+ domainBlacklist: "Domain ${domain} is not allowed",
318
+ port: "Port must be one of: ${ports}",
319
+ pathStartsWith: "Path must start with ${path}",
320
+ pathEndsWith: "Path must end with ${path}",
321
+ hasQuery: "URL must have query parameters",
322
+ noQuery: "URL must not have query parameters",
323
+ hasFragment: "URL must have a fragment",
324
+ noFragment: "URL must not have a fragment",
325
+ localhost: "Localhost URLs are not allowed",
326
+ noLocalhost: "Localhost URLs are not allowed"
129
327
  },
130
328
  password: {
131
329
  required: "Required",
@@ -134,46 +332,167 @@ var en_default = {
134
332
  uppercase: "Must include at least one uppercase letter",
135
333
  lowercase: "Must include at least one lowercase letter",
136
334
  digits: "Must include at least one digit",
137
- special: "Must include at least one special character"
335
+ special: "Must include at least one special character",
336
+ noRepeating: "Must not contain repeating characters",
337
+ noSequential: "Must not contain sequential characters",
338
+ noCommonWords: "Must not contain common words or patterns",
339
+ minStrength: "Password strength must be at least ${minStrength}",
340
+ excludes: "Must not contain ${excludes}",
341
+ includes: "Must include ${includes}",
342
+ invalid: "Invalid password format"
138
343
  },
139
344
  number: {
140
345
  required: "Required",
141
- min: "Must be at least ${min}",
142
- max: "Must be at most ${max}"
143
- },
144
- integer: {
145
- required: "Required",
346
+ invalid: "Must be a valid number",
347
+ integer: "Must be an integer",
348
+ float: "Must be a decimal number",
146
349
  min: "Must be at least ${min}",
147
350
  max: "Must be at most ${max}",
148
- integer: "Must be an integer"
351
+ positive: "Must be positive",
352
+ negative: "Must be negative",
353
+ nonNegative: "Must be non-negative",
354
+ nonPositive: "Must be non-positive",
355
+ multipleOf: "Must be a multiple of ${multipleOf}",
356
+ finite: "Must be a finite number",
357
+ precision: "Must have at most ${precision} decimal places"
149
358
  },
150
- float: {
359
+ id: {
151
360
  required: "Required",
152
- min: "Must be at least ${min}",
153
- max: "Must be at most ${max}",
154
- float: "Must be an float"
361
+ invalid: "Invalid ID format",
362
+ minLength: "Must be at least ${minLength} characters",
363
+ maxLength: "Must be at most ${maxLength} characters",
364
+ numeric: "Must be a numeric ID",
365
+ uuid: "Must be a valid UUID",
366
+ objectId: "Must be a valid MongoDB ObjectId",
367
+ nanoid: "Must be a valid Nano ID",
368
+ snowflake: "Must be a valid Snowflake ID",
369
+ cuid: "Must be a valid CUID",
370
+ ulid: "Must be a valid ULID",
371
+ shortid: "Must be a valid Short ID",
372
+ customFormat: "Invalid ID format",
373
+ includes: "Must include ${includes}",
374
+ excludes: "Must not contain ${excludes}",
375
+ startsWith: "Must start with ${startsWith}",
376
+ endsWith: "Must end with ${endsWith}"
155
377
  },
156
378
  text: {
157
379
  required: "Required",
158
- min: "Must be at least ${min} characters",
159
- max: "Must be at most ${max} characters",
380
+ notEmpty: "Cannot be empty or whitespace only",
381
+ minLength: "Must be at least ${minLength} characters",
382
+ maxLength: "Must be at most ${maxLength} characters",
160
383
  startsWith: "Must start with ${startsWith}",
161
384
  endsWith: "Must end with ${endsWith}",
162
385
  includes: "Must include ${includes}",
386
+ excludes: "Must not contain ${excludes}",
163
387
  invalid: "Invalid format"
164
388
  },
165
389
  date: {
166
390
  required: "Required",
167
- min: "Must be at least ${min} characters",
168
- max: "Must be at most ${max} characters",
391
+ invalid: "Invalid date",
392
+ format: "Must be in ${format} format",
393
+ min: "Date must be on or after ${min}",
394
+ max: "Date must be on or before ${max}",
395
+ includes: "Must include ${includes}",
396
+ excludes: "Must not contain ${excludes}",
397
+ past: "Date must be in the past",
398
+ future: "Date must be in the future",
399
+ today: "Date must be today",
400
+ notToday: "Date must not be today",
401
+ weekday: "Date must be a weekday (Monday-Friday)",
402
+ weekend: "Date must be a weekend (Saturday-Sunday)"
403
+ },
404
+ time: {
405
+ required: "Required",
406
+ invalid: "Invalid time format",
407
+ format: "Must be in ${format} format",
408
+ min: "Time must be after ${min}",
409
+ max: "Time must be before ${max}",
410
+ hour: "Hour must be between ${minHour} and ${maxHour}",
411
+ minute: "Minutes must be in ${minuteStep}-minute intervals",
412
+ second: "Seconds must be in ${secondStep}-second intervals",
169
413
  includes: "Must include ${includes}",
170
- format: "Must be in ${format} format"
414
+ excludes: "Must not contain ${excludes}",
415
+ customRegex: "Invalid time format",
416
+ notInWhitelist: "Time is not in the allowed list"
417
+ },
418
+ datetime: {
419
+ required: "Required",
420
+ invalid: "Invalid datetime format",
421
+ format: "Must be in ${format} format",
422
+ min: "DateTime must be after ${min}",
423
+ max: "DateTime must be before ${max}",
424
+ hour: "Hour must be between ${minHour} and ${maxHour}",
425
+ minute: "Minutes must be in ${minuteStep}-minute intervals",
426
+ includes: "Must include ${includes}",
427
+ excludes: "Must not contain ${excludes}",
428
+ past: "DateTime must be in the past",
429
+ future: "DateTime must be in the future",
430
+ today: "DateTime must be today",
431
+ notToday: "DateTime must not be today",
432
+ weekday: "DateTime must be a weekday (Monday-Friday)",
433
+ weekend: "DateTime must be a weekend (Saturday-Sunday)",
434
+ customRegex: "Invalid datetime format",
435
+ notInWhitelist: "DateTime is not in the allowed list"
436
+ },
437
+ file: {
438
+ required: "Required",
439
+ invalid: "Invalid file format",
440
+ size: "File size must not exceed ${size}",
441
+ minSize: "File size must be at least ${minSize}",
442
+ maxSize: "File size must not exceed ${maxSize}",
443
+ type: "File type must be one of: ${type}",
444
+ extension: "File extension must be one of: ${extension}",
445
+ extensionBlacklist: "File extension ${extension} is not allowed",
446
+ name: "File name must match pattern ${pattern}",
447
+ nameBlacklist: "File name must not match pattern ${pattern}",
448
+ imageOnly: "Only image files are allowed",
449
+ documentOnly: "Only document files are allowed",
450
+ videoOnly: "Only video files are allowed",
451
+ audioOnly: "Only audio files are allowed",
452
+ archiveOnly: "Only archive files are allowed"
453
+ }
454
+ },
455
+ taiwan: {
456
+ businessId: {
457
+ required: "Required",
458
+ invalid: "Invalid Taiwan Business ID"
459
+ },
460
+ nationalId: {
461
+ required: "Required",
462
+ invalid: "Invalid Taiwan National ID"
463
+ },
464
+ mobile: {
465
+ required: "Required",
466
+ invalid: "Invalid Taiwan mobile phone format",
467
+ notInWhitelist: "Not in allowed mobile phone list"
468
+ },
469
+ tel: {
470
+ required: "Required",
471
+ invalid: "Invalid Taiwan telephone format",
472
+ notInWhitelist: "Not in allowed telephone list"
473
+ },
474
+ fax: {
475
+ required: "Required",
476
+ invalid: "Invalid Taiwan fax format",
477
+ notInWhitelist: "Not in allowed fax list"
478
+ },
479
+ postalCode: {
480
+ required: "Required",
481
+ invalid: "Invalid Taiwan postal code",
482
+ invalidFormat: "Invalid postal code format",
483
+ invalidRange: "Postal code is outside valid range",
484
+ legacy5DigitWarning: "5-digit postal codes are legacy format, consider using 6-digit format",
485
+ format3Only: "Only 3-digit postal codes are allowed",
486
+ format5Only: "Only 5-digit postal codes are allowed",
487
+ format6Only: "Only 6-digit postal codes are allowed",
488
+ invalidSuffix: "Invalid postal code suffix - must be 01-99 for 5-digit or 001-999 for 6-digit codes",
489
+ deprecated5Digit: "5-digit postal codes are deprecated and no longer supported"
171
490
  }
172
491
  }
173
492
  };
174
493
 
175
494
  // src/config.ts
176
- var currentLocale = "zh-TW";
495
+ var currentLocale = "en";
177
496
  var setLocale = (locale) => {
178
497
  currentLocale = locale;
179
498
  };
@@ -195,149 +514,2811 @@ function getNestedValue(obj, path) {
195
514
  return typeof result === "string" ? result : void 0;
196
515
  }
197
516
 
198
- // src/common/boolean.ts
517
+ // src/validators/common/boolean.ts
199
518
  function boolean(options) {
200
- const { required = true, defaultValue = null, shouldBe } = options ?? {};
519
+ const {
520
+ required = true,
521
+ defaultValue = null,
522
+ shouldBe,
523
+ truthyValues = [true, "true", 1, "1", "yes", "on"],
524
+ falsyValues = [false, "false", 0, "0", "no", "off"],
525
+ strict = false,
526
+ transform,
527
+ i18n
528
+ } = options ?? {};
529
+ const getMessage = (key, params) => {
530
+ if (i18n) {
531
+ const currentLocale2 = getLocale();
532
+ const customMessages = i18n[currentLocale2];
533
+ if (customMessages && customMessages[key]) {
534
+ const template = customMessages[key];
535
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
536
+ }
537
+ }
538
+ return t(`common.boolean.${key}`, params);
539
+ };
201
540
  let result = import_zod.z.preprocess(
202
541
  (val) => {
203
542
  if (val === "" || val === void 0 || val === null) return defaultValue;
204
- if (val === "true" || val === 1 || val === "1") return true;
205
- if (val === "false" || val === 0 || val === "0") return false;
543
+ if (strict && typeof val !== "boolean" && val !== null) {
544
+ return val;
545
+ }
546
+ if (truthyValues.includes(val)) {
547
+ let processed = true;
548
+ if (transform) processed = transform(processed);
549
+ return processed;
550
+ }
551
+ if (falsyValues.includes(val)) {
552
+ let processed = false;
553
+ if (transform) processed = transform(processed);
554
+ return processed;
555
+ }
206
556
  return val;
207
557
  },
208
558
  import_zod.z.union([import_zod.z.literal(true), import_zod.z.literal(false), import_zod.z.literal(null)])
209
559
  );
210
560
  if (required && defaultValue === null) {
211
- result = result.refine((val) => val !== null, { message: t("common.boolean.required") });
561
+ result = result.refine((val) => val !== null, { message: getMessage("required") });
212
562
  }
213
563
  if (shouldBe === true) {
214
- result = result.refine((val) => val === true, { message: t("common.boolean.shouldBe.true") });
564
+ result = result.refine((val) => val === true, { message: getMessage("shouldBeTrue") });
215
565
  } else if (shouldBe === false) {
216
- result = result.refine((val) => val === false, { message: t("common.boolean.shouldBe.false") });
566
+ result = result.refine((val) => val === false, { message: getMessage("shouldBeFalse") });
567
+ }
568
+ if (strict) {
569
+ result = result.refine(
570
+ (val) => {
571
+ return val === null || typeof val === "boolean";
572
+ },
573
+ { message: getMessage("invalid") }
574
+ );
217
575
  }
218
576
  return result;
219
577
  }
220
578
 
221
- // src/common/email.ts
579
+ // src/validators/common/date.ts
222
580
  var import_zod2 = require("zod");
223
- function email(options) {
224
- const { required = true, domain, min, max, includes } = options ?? {};
225
- const baseSchema = required ? import_zod2.z.preprocess(
226
- (val) => val === "" || val === null || val === void 0 ? null : val,
227
- import_zod2.z.email({
228
- error: (issue) => {
229
- if (issue.code === "invalid_type") return t("common.email.required");
230
- else if (issue.code === "invalid_format") return t("common.email.invalid");
231
- return t("common.email.invalid");
232
- }
233
- })
234
- ) : import_zod2.z.preprocess((val) => val === "" || val === null || val === void 0 ? null : val, import_zod2.z.email({ message: t("common.email.invalid") }).nullable());
235
- 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(
236
- (val) => {
237
- if (val === null || domain === void 0) return true;
238
- return val.split("@")[1]?.toLowerCase() === domain.toLowerCase();
239
- },
240
- { message: t("common.email.domain", { domain }) }
241
- );
581
+ var import_dayjs = __toESM(require("dayjs"), 1);
582
+ var import_customParseFormat = __toESM(require("dayjs/plugin/customParseFormat"), 1);
583
+ var import_isSameOrAfter = __toESM(require("dayjs/plugin/isSameOrAfter"), 1);
584
+ var import_isSameOrBefore = __toESM(require("dayjs/plugin/isSameOrBefore"), 1);
585
+ var import_isToday = __toESM(require("dayjs/plugin/isToday"), 1);
586
+ var import_weekday = __toESM(require("dayjs/plugin/weekday"), 1);
587
+ import_dayjs.default.extend(import_isSameOrAfter.default);
588
+ import_dayjs.default.extend(import_isSameOrBefore.default);
589
+ import_dayjs.default.extend(import_customParseFormat.default);
590
+ import_dayjs.default.extend(import_isToday.default);
591
+ import_dayjs.default.extend(import_weekday.default);
592
+ function date(options) {
593
+ const {
594
+ required = true,
595
+ min,
596
+ max,
597
+ format = "YYYY-MM-DD",
598
+ includes,
599
+ excludes,
600
+ mustBePast,
601
+ mustBeFuture,
602
+ mustBeToday,
603
+ mustNotBeToday,
604
+ weekdaysOnly,
605
+ weekendsOnly,
606
+ transform,
607
+ defaultValue = null,
608
+ i18n
609
+ } = options ?? {};
610
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
611
+ const getMessage = (key, params) => {
612
+ if (i18n) {
613
+ const currentLocale2 = getLocale();
614
+ const customMessages = i18n[currentLocale2];
615
+ if (customMessages && customMessages[key]) {
616
+ const template = customMessages[key];
617
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
618
+ }
619
+ }
620
+ return t(`common.date.${key}`, params);
621
+ };
622
+ const preprocessFn = (val) => {
623
+ if (val === "" || val === null || val === void 0) {
624
+ return actualDefaultValue;
625
+ }
626
+ let processed = String(val).trim();
627
+ if (transform) {
628
+ processed = transform(processed);
629
+ }
630
+ return processed;
631
+ };
632
+ const baseSchema = required ? import_zod2.z.preprocess(preprocessFn, import_zod2.z.string()) : import_zod2.z.preprocess(preprocessFn, import_zod2.z.string().nullable());
633
+ const schema = baseSchema.refine((val) => {
634
+ if (val === null) return true;
635
+ if (required && (val === "" || val === "null" || val === "undefined")) {
636
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
637
+ }
638
+ if (val !== null && !(0, import_dayjs.default)(val, format, true).isValid()) {
639
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("format", { format }), path: [] }]);
640
+ }
641
+ const dateObj = (0, import_dayjs.default)(val, format);
642
+ if (val !== null && min !== void 0 && !dateObj.isSameOrAfter((0, import_dayjs.default)(min, format))) {
643
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
644
+ }
645
+ if (val !== null && max !== void 0 && !dateObj.isSameOrBefore((0, import_dayjs.default)(max, format))) {
646
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
647
+ }
648
+ if (val !== null && includes !== void 0 && !val.includes(includes)) {
649
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
650
+ }
651
+ if (val !== null && excludes !== void 0) {
652
+ const excludeList = Array.isArray(excludes) ? excludes : [excludes];
653
+ for (const exclude of excludeList) {
654
+ if (val.includes(exclude)) {
655
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
656
+ }
657
+ }
658
+ }
659
+ const today = (0, import_dayjs.default)().startOf("day");
660
+ const targetDate = dateObj.startOf("day");
661
+ if (val !== null && mustBePast && !targetDate.isBefore(today)) {
662
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("past"), path: [] }]);
663
+ }
664
+ if (val !== null && mustBeFuture && !targetDate.isAfter(today)) {
665
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("future"), path: [] }]);
666
+ }
667
+ if (val !== null && mustBeToday && !targetDate.isSame(today)) {
668
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("today"), path: [] }]);
669
+ }
670
+ if (val !== null && mustNotBeToday && targetDate.isSame(today)) {
671
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("notToday"), path: [] }]);
672
+ }
673
+ if (val !== null && weekdaysOnly && (dateObj.day() === 0 || dateObj.day() === 6)) {
674
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("weekday"), path: [] }]);
675
+ }
676
+ if (val !== null && weekendsOnly && dateObj.day() !== 0 && dateObj.day() !== 6) {
677
+ throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("weekend"), path: [] }]);
678
+ }
679
+ return true;
680
+ });
242
681
  return schema;
243
682
  }
244
683
 
245
- // src/common/url.ts
684
+ // src/validators/common/datetime.ts
246
685
  var import_zod3 = require("zod");
247
- function url(options) {
248
- const { required = true, min, max, includes } = options ?? {};
249
- const baseSchema = required ? import_zod3.z.preprocess(
250
- (val) => val === "" || val === null || val === void 0 ? null : val,
251
- import_zod3.z.url({
252
- error: (issue) => {
253
- if (issue.code === "invalid_type") return t("common.url.required");
254
- else if (issue.code === "invalid_format") return t("common.url.invalid");
255
- return t("common.url.invalid");
256
- }
257
- })
258
- ) : import_zod3.z.preprocess((val) => val === "" || val === null || val === void 0 ? null : val, import_zod3.z.url({ message: t("common.url.invalid") }).nullable());
259
- 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 }) });
686
+ var import_dayjs2 = __toESM(require("dayjs"), 1);
687
+ var import_customParseFormat2 = __toESM(require("dayjs/plugin/customParseFormat"), 1);
688
+ var import_isSameOrAfter2 = __toESM(require("dayjs/plugin/isSameOrAfter"), 1);
689
+ var import_isSameOrBefore2 = __toESM(require("dayjs/plugin/isSameOrBefore"), 1);
690
+ var import_isToday2 = __toESM(require("dayjs/plugin/isToday"), 1);
691
+ var import_weekday2 = __toESM(require("dayjs/plugin/weekday"), 1);
692
+ var import_timezone = __toESM(require("dayjs/plugin/timezone"), 1);
693
+ var import_utc = __toESM(require("dayjs/plugin/utc"), 1);
694
+ import_dayjs2.default.extend(import_isSameOrAfter2.default);
695
+ import_dayjs2.default.extend(import_isSameOrBefore2.default);
696
+ import_dayjs2.default.extend(import_customParseFormat2.default);
697
+ import_dayjs2.default.extend(import_isToday2.default);
698
+ import_dayjs2.default.extend(import_weekday2.default);
699
+ import_dayjs2.default.extend(import_timezone.default);
700
+ import_dayjs2.default.extend(import_utc.default);
701
+ var DATETIME_PATTERNS = {
702
+ "YYYY-MM-DD HH:mm": /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/,
703
+ "YYYY-MM-DD HH:mm:ss": /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/,
704
+ "YYYY-MM-DD hh:mm A": /^\d{4}-\d{2}-\d{2} \d{1,2}:\d{2} (AM|PM)$/i,
705
+ "YYYY-MM-DD hh:mm:ss A": /^\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2} (AM|PM)$/i,
706
+ "DD/MM/YYYY HH:mm": /^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}$/,
707
+ "DD/MM/YYYY HH:mm:ss": /^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}$/,
708
+ "DD/MM/YYYY hh:mm A": /^\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2} (AM|PM)$/i,
709
+ "MM/DD/YYYY HH:mm": /^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}$/,
710
+ "MM/DD/YYYY hh:mm A": /^\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2} (AM|PM)$/i,
711
+ "YYYY/MM/DD HH:mm": /^\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}$/,
712
+ "DD-MM-YYYY HH:mm": /^\d{1,2}-\d{1,2}-\d{4} \d{2}:\d{2}$/,
713
+ "MM-DD-YYYY HH:mm": /^\d{1,2}-\d{1,2}-\d{4} \d{2}:\d{2}$/,
714
+ ISO: /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z?$/,
715
+ RFC: /^[A-Za-z]{3}, \d{1,2} [A-Za-z]{3} \d{4} \d{2}:\d{2}:\d{2} [A-Z]{3}$/,
716
+ UNIX: /^\d{10}$/
717
+ };
718
+ var validateDateTimeFormat = (value, format) => {
719
+ const pattern = DATETIME_PATTERNS[format];
720
+ if (!pattern.test(value.trim())) {
721
+ return false;
722
+ }
723
+ const parsed = parseDateTimeValue(value, format);
724
+ return parsed !== null;
725
+ };
726
+ var parseDateTimeValue = (value, format, timezone2) => {
727
+ try {
728
+ const cleanValue = value.trim();
729
+ let parsed;
730
+ switch (format) {
731
+ case "ISO":
732
+ parsed = (0, import_dayjs2.default)(cleanValue);
733
+ break;
734
+ case "RFC":
735
+ parsed = (0, import_dayjs2.default)(cleanValue);
736
+ break;
737
+ case "UNIX":
738
+ parsed = import_dayjs2.default.unix(parseInt(cleanValue, 10));
739
+ break;
740
+ default:
741
+ parsed = (0, import_dayjs2.default)(cleanValue, format, true);
742
+ break;
743
+ }
744
+ if (!parsed.isValid()) {
745
+ return null;
746
+ }
747
+ if (timezone2) {
748
+ parsed = parsed.tz(timezone2);
749
+ }
750
+ return parsed;
751
+ } catch {
752
+ return null;
753
+ }
754
+ };
755
+ var normalizeDateTimeValue = (value, format, timezone2) => {
756
+ const parsed = parseDateTimeValue(value, format, timezone2);
757
+ if (!parsed) return null;
758
+ switch (format) {
759
+ case "ISO":
760
+ return parsed.toISOString();
761
+ case "RFC":
762
+ return parsed.format("ddd, DD MMM YYYY HH:mm:ss [GMT]");
763
+ case "UNIX":
764
+ return parsed.unix().toString();
765
+ default:
766
+ return parsed.format(format);
767
+ }
768
+ };
769
+ function datetime(options) {
770
+ const {
771
+ required = true,
772
+ format = "YYYY-MM-DD HH:mm",
773
+ min,
774
+ max,
775
+ minHour,
776
+ maxHour,
777
+ allowedHours,
778
+ minuteStep,
779
+ timezone: timezone2,
780
+ includes,
781
+ excludes,
782
+ regex,
783
+ trimMode = "trim",
784
+ casing = "none",
785
+ mustBePast,
786
+ mustBeFuture,
787
+ mustBeToday,
788
+ mustNotBeToday,
789
+ weekdaysOnly,
790
+ weekendsOnly,
791
+ whitelist,
792
+ whitelistOnly = false,
793
+ transform,
794
+ defaultValue,
795
+ i18n
796
+ } = options ?? {};
797
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
798
+ const getMessage = (key, params) => {
799
+ if (i18n) {
800
+ const currentLocale2 = getLocale();
801
+ const customMessages = i18n[currentLocale2];
802
+ if (customMessages && customMessages[key]) {
803
+ const template = customMessages[key];
804
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
805
+ }
806
+ }
807
+ return t(`common.datetime.${key}`, params);
808
+ };
809
+ const preprocessFn = (val) => {
810
+ if (val === null || val === void 0) {
811
+ return actualDefaultValue;
812
+ }
813
+ let processed = String(val);
814
+ switch (trimMode) {
815
+ case "trim":
816
+ processed = processed.trim();
817
+ break;
818
+ case "trimStart":
819
+ processed = processed.trimStart();
820
+ break;
821
+ case "trimEnd":
822
+ processed = processed.trimEnd();
823
+ break;
824
+ case "none":
825
+ break;
826
+ }
827
+ if (processed === "") {
828
+ if (whitelist && whitelist.includes("")) {
829
+ return "";
830
+ }
831
+ if (!required) {
832
+ return actualDefaultValue;
833
+ }
834
+ return actualDefaultValue;
835
+ }
836
+ switch (casing) {
837
+ case "upper":
838
+ processed = processed.toUpperCase();
839
+ break;
840
+ case "lower":
841
+ processed = processed.toLowerCase();
842
+ break;
843
+ case "none":
844
+ break;
845
+ }
846
+ if (transform) {
847
+ processed = transform(processed);
848
+ }
849
+ return processed;
850
+ };
851
+ const baseSchema = required ? import_zod3.z.preprocess(preprocessFn, import_zod3.z.string()) : import_zod3.z.preprocess(preprocessFn, import_zod3.z.string().nullable());
852
+ const schema = baseSchema.refine((val) => {
853
+ if (val === null) return true;
854
+ if (required && (val === "" || val === "null" || val === "undefined")) {
855
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
856
+ }
857
+ if (val === null) return true;
858
+ if (!required && val === "") return true;
859
+ if (whitelist && whitelist.length > 0) {
860
+ if (whitelist.includes(val)) {
861
+ return true;
862
+ }
863
+ if (whitelistOnly) {
864
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
865
+ }
866
+ }
867
+ if (regex) {
868
+ if (!regex.test(val)) {
869
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("customRegex"), path: [] }]);
870
+ }
871
+ } else {
872
+ if (!validateDateTimeFormat(val, format)) {
873
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("format", { format }), path: [] }]);
874
+ }
875
+ }
876
+ if (includes && !val.includes(includes)) {
877
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
878
+ }
879
+ if (excludes) {
880
+ const excludeList = Array.isArray(excludes) ? excludes : [excludes];
881
+ for (const exclude of excludeList) {
882
+ if (val.includes(exclude)) {
883
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
884
+ }
885
+ }
886
+ }
887
+ if (regex) {
888
+ return true;
889
+ }
890
+ const parsed = parseDateTimeValue(val, format, timezone2);
891
+ if (!parsed) {
892
+ const pattern = DATETIME_PATTERNS[format];
893
+ if (!pattern.test(val.trim())) {
894
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("format", { format }), path: [] }]);
895
+ } else {
896
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
897
+ }
898
+ }
899
+ const hour = parsed.hour();
900
+ if (minHour !== void 0 && hour < minHour) {
901
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("hour", { minHour, maxHour: maxHour ?? 23 }), path: [] }]);
902
+ }
903
+ if (maxHour !== void 0 && hour > maxHour) {
904
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("hour", { minHour: minHour ?? 0, maxHour }), path: [] }]);
905
+ }
906
+ if (allowedHours && allowedHours.length > 0) {
907
+ if (!allowedHours.includes(hour)) {
908
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("hour", { allowedHours: allowedHours.join(", ") }), path: [] }]);
909
+ }
910
+ }
911
+ const minute = parsed.minute();
912
+ if (minuteStep !== void 0 && minute % minuteStep !== 0) {
913
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("minute", { minuteStep }), path: [] }]);
914
+ }
915
+ if (min) {
916
+ const minParsed = typeof min === "string" ? parseDateTimeValue(min, format, timezone2) : (0, import_dayjs2.default)(min);
917
+ if (minParsed && parsed.isBefore(minParsed)) {
918
+ const minFormatted = typeof min === "string" ? min : minParsed.format(format);
919
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("min", { min: minFormatted }), path: [] }]);
920
+ }
921
+ }
922
+ if (max) {
923
+ const maxParsed = typeof max === "string" ? parseDateTimeValue(max, format, timezone2) : (0, import_dayjs2.default)(max);
924
+ if (maxParsed && parsed.isAfter(maxParsed)) {
925
+ const maxFormatted = typeof max === "string" ? max : maxParsed.format(format);
926
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("max", { max: maxFormatted }), path: [] }]);
927
+ }
928
+ }
929
+ const now = timezone2 ? (0, import_dayjs2.default)().tz(timezone2) : (0, import_dayjs2.default)();
930
+ if (mustBePast && !parsed.isBefore(now)) {
931
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("past"), path: [] }]);
932
+ }
933
+ if (mustBeFuture && !parsed.isAfter(now)) {
934
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("future"), path: [] }]);
935
+ }
936
+ if (mustBeToday && !parsed.isSame(now, "day")) {
937
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("today"), path: [] }]);
938
+ }
939
+ if (mustNotBeToday && parsed.isSame(now, "day")) {
940
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("notToday"), path: [] }]);
941
+ }
942
+ const dayOfWeek = parsed.day();
943
+ if (weekdaysOnly && (dayOfWeek === 0 || dayOfWeek === 6)) {
944
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("weekday"), path: [] }]);
945
+ }
946
+ if (weekendsOnly && dayOfWeek !== 0 && dayOfWeek !== 6) {
947
+ throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("weekend"), path: [] }]);
948
+ }
949
+ return true;
950
+ });
260
951
  return schema;
261
952
  }
262
953
 
263
- // src/common/text.ts
954
+ // src/validators/common/email.ts
264
955
  var import_zod4 = require("zod");
265
- function text(options) {
266
- const { required = true, min, max, startsWith, endsWith, includes, regex, defaultValue = null } = options ?? {};
267
- const baseSchema = required ? import_zod4.z.preprocess((val) => val === "" || val === null || val === void 0 ? defaultValue : val, import_zod4.z.coerce.string().trim()) : import_zod4.z.preprocess((val) => val === "" || val === null || val === void 0 ? defaultValue : val, import_zod4.z.coerce.string().trim().nullable());
268
- 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 }) });
956
+ function email(options) {
957
+ const {
958
+ required = true,
959
+ domain,
960
+ domainBlacklist,
961
+ minLength,
962
+ maxLength,
963
+ includes,
964
+ excludes,
965
+ allowSubdomains = true,
966
+ businessOnly = false,
967
+ noDisposable = false,
968
+ lowercase = true,
969
+ transform,
970
+ defaultValue,
971
+ i18n
972
+ } = options ?? {};
973
+ const getMessage = (key, params) => {
974
+ if (i18n) {
975
+ const currentLocale2 = getLocale();
976
+ const customMessages = i18n[currentLocale2];
977
+ if (customMessages && customMessages[key]) {
978
+ const template = customMessages[key];
979
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
980
+ }
981
+ }
982
+ return t(`common.email.${key}`, params);
983
+ };
984
+ const disposableDomains = ["10minutemail.com", "tempmail.org", "guerrillamail.com", "mailinator.com", "yopmail.com", "temp-mail.org", "throwaway.email", "getnada.com", "maildrop.cc"];
985
+ const freeEmailDomains = ["gmail.com", "yahoo.com", "hotmail.com", "outlook.com", "icloud.com", "aol.com", "protonmail.com", "zoho.com"];
986
+ const actualDefaultValue = defaultValue ?? null;
987
+ const baseSchema = import_zod4.z.preprocess(
988
+ (val) => {
989
+ if (val === "" || val === null || val === void 0) {
990
+ return actualDefaultValue;
991
+ }
992
+ let processed = String(val).trim();
993
+ if (lowercase) {
994
+ processed = processed.toLowerCase();
995
+ }
996
+ if (transform) {
997
+ processed = transform(processed);
998
+ }
999
+ return processed;
1000
+ },
1001
+ import_zod4.z.union([import_zod4.z.string().email(), import_zod4.z.null()])
1002
+ );
1003
+ const schema = baseSchema.refine((val) => {
1004
+ if (required && val === null) {
1005
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1006
+ }
1007
+ if (val === null) return true;
1008
+ if (typeof val !== "string") {
1009
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1010
+ }
1011
+ if (minLength !== void 0 && val.length < minLength) {
1012
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("minLength", { minLength }), path: [] }]);
1013
+ }
1014
+ if (maxLength !== void 0 && val.length > maxLength) {
1015
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("maxLength", { maxLength }), path: [] }]);
1016
+ }
1017
+ if (includes !== void 0 && !val.includes(includes)) {
1018
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1019
+ }
1020
+ if (excludes !== void 0) {
1021
+ const excludeList = Array.isArray(excludes) ? excludes : [excludes];
1022
+ for (const exclude of excludeList) {
1023
+ if (val.includes(exclude)) {
1024
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("includes", { includes: exclude }), path: [] }]);
1025
+ }
1026
+ }
1027
+ }
1028
+ const emailDomain = val.split("@")[1]?.toLowerCase();
1029
+ if (!emailDomain) {
1030
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1031
+ }
1032
+ if (businessOnly) {
1033
+ const isFreeProvider = freeEmailDomains.some((freeDomain) => {
1034
+ if (allowSubdomains) {
1035
+ return emailDomain === freeDomain || emailDomain.endsWith("." + freeDomain);
1036
+ }
1037
+ return emailDomain === freeDomain;
1038
+ });
1039
+ if (isFreeProvider) {
1040
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("businessOnly"), path: [] }]);
1041
+ }
1042
+ }
1043
+ if (domainBlacklist && domainBlacklist.length > 0) {
1044
+ const isBlacklisted = domainBlacklist.some((blacklistedDomain) => {
1045
+ const lowerDomain = blacklistedDomain.toLowerCase();
1046
+ if (allowSubdomains) {
1047
+ return emailDomain === lowerDomain || emailDomain.endsWith("." + lowerDomain);
1048
+ }
1049
+ return emailDomain === lowerDomain;
1050
+ });
1051
+ if (isBlacklisted) {
1052
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("domainBlacklist", { domain: emailDomain }), path: [] }]);
1053
+ }
1054
+ }
1055
+ if (domain !== void 0) {
1056
+ const allowedDomains = Array.isArray(domain) ? domain : [domain];
1057
+ const isAllowed = allowedDomains.some((allowedDomain) => {
1058
+ const lowerDomain = allowedDomain.toLowerCase();
1059
+ if (allowSubdomains) {
1060
+ return emailDomain === lowerDomain || emailDomain.endsWith("." + lowerDomain);
1061
+ }
1062
+ return emailDomain === lowerDomain;
1063
+ });
1064
+ if (!isAllowed) {
1065
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("domain", { domain: Array.isArray(domain) ? domain.join(", ") : domain }), path: [] }]);
1066
+ }
1067
+ }
1068
+ if (noDisposable) {
1069
+ const isDisposable = disposableDomains.some((disposableDomain) => {
1070
+ if (allowSubdomains) {
1071
+ return emailDomain === disposableDomain || emailDomain.endsWith("." + disposableDomain);
1072
+ }
1073
+ return emailDomain === disposableDomain;
1074
+ });
1075
+ if (isDisposable) {
1076
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("noDisposable"), path: [] }]);
1077
+ }
1078
+ }
1079
+ return true;
1080
+ });
269
1081
  return schema;
270
1082
  }
271
1083
 
272
- // src/common/number.ts
1084
+ // src/validators/common/file.ts
273
1085
  var import_zod5 = require("zod");
274
- function number(options) {
275
- const { required = true, min, max, defaultValue } = options ?? {};
276
- const schema = import_zod5.z.preprocess(
1086
+ function file(options) {
1087
+ const {
1088
+ required = true,
1089
+ maxSize,
1090
+ minSize,
1091
+ type,
1092
+ typeBlacklist,
1093
+ extension,
1094
+ extensionBlacklist,
1095
+ namePattern,
1096
+ nameBlacklist,
1097
+ imageOnly = false,
1098
+ documentOnly = false,
1099
+ videoOnly = false,
1100
+ audioOnly = false,
1101
+ archiveOnly = false,
1102
+ caseSensitive = false,
1103
+ transform,
1104
+ defaultValue,
1105
+ i18n
1106
+ } = options ?? {};
1107
+ const getMessage = (key, params) => {
1108
+ if (i18n) {
1109
+ const currentLocale2 = getLocale();
1110
+ const customMessages = i18n[currentLocale2];
1111
+ if (customMessages && customMessages[key]) {
1112
+ const template = customMessages[key];
1113
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
1114
+ }
1115
+ }
1116
+ return t(`common.file.${key}`, params);
1117
+ };
1118
+ const imageTypes = ["image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp", "image/svg+xml", "image/bmp", "image/tiff"];
1119
+ const documentTypes = [
1120
+ "application/pdf",
1121
+ "application/msword",
1122
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1123
+ "application/vnd.ms-excel",
1124
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
1125
+ "application/vnd.ms-powerpoint",
1126
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
1127
+ "text/plain",
1128
+ "text/csv"
1129
+ ];
1130
+ const videoTypes = ["video/mp4", "video/mpeg", "video/quicktime", "video/x-msvideo", "video/x-ms-wmv", "video/webm", "video/ogg"];
1131
+ const audioTypes = ["audio/mpeg", "audio/wav", "audio/ogg", "audio/aac", "audio/webm", "audio/mp3", "audio/x-wav"];
1132
+ const archiveTypes = ["application/zip", "application/x-rar-compressed", "application/x-7z-compressed", "application/x-tar", "application/gzip"];
1133
+ const actualDefaultValue = defaultValue ?? null;
1134
+ const baseSchema = import_zod5.z.preprocess(
1135
+ (val) => {
1136
+ if (val === "" || val === null || val === void 0) {
1137
+ return actualDefaultValue;
1138
+ }
1139
+ if (!(val instanceof File)) {
1140
+ return val;
1141
+ }
1142
+ let processed = val;
1143
+ if (transform) {
1144
+ processed = transform(processed);
1145
+ }
1146
+ return processed;
1147
+ },
1148
+ import_zod5.z.union([import_zod5.z.instanceof(File).refine(() => true, { message: getMessage("invalid") }), import_zod5.z.null()])
1149
+ );
1150
+ const schema = baseSchema.refine((val) => required === false || val !== null, {
1151
+ message: getMessage("required")
1152
+ }).refine((val) => val === null || val instanceof File, {
1153
+ message: getMessage("invalid")
1154
+ }).refine((val) => val === null || minSize === void 0 || val.size >= minSize, {
1155
+ message: getMessage("minSize", { minSize: formatFileSize(minSize || 0) })
1156
+ }).refine((val) => val === null || maxSize === void 0 || val.size <= maxSize, {
1157
+ message: getMessage("maxSize", { maxSize: formatFileSize(maxSize || 0) })
1158
+ }).refine((val) => val === null || !imageOnly || imageTypes.includes(val.type), {
1159
+ message: getMessage("imageOnly")
1160
+ }).refine((val) => val === null || !documentOnly || documentTypes.includes(val.type), {
1161
+ message: getMessage("documentOnly")
1162
+ }).refine((val) => val === null || !videoOnly || videoTypes.includes(val.type), {
1163
+ message: getMessage("videoOnly")
1164
+ }).refine((val) => val === null || !audioOnly || audioTypes.includes(val.type), {
1165
+ message: getMessage("audioOnly")
1166
+ }).refine((val) => val === null || !archiveOnly || archiveTypes.includes(val.type), {
1167
+ message: getMessage("archiveOnly")
1168
+ }).refine(
1169
+ (val) => {
1170
+ if (val === null || !typeBlacklist || typeBlacklist.length === 0) return true;
1171
+ return !typeBlacklist.includes(val.type);
1172
+ },
1173
+ {
1174
+ message: getMessage("type", { type: typeBlacklist?.join(", ") || "" })
1175
+ }
1176
+ ).refine(
1177
+ (val) => {
1178
+ if (val === null || type === void 0) return true;
1179
+ const allowedTypes = Array.isArray(type) ? type : [type];
1180
+ return allowedTypes.includes(val.type);
1181
+ },
1182
+ {
1183
+ message: getMessage("type", { type: Array.isArray(type) ? type.join(", ") : type || "" })
1184
+ }
1185
+ ).refine(
1186
+ (val) => {
1187
+ if (val === null || extensionBlacklist === void 0 || extensionBlacklist.length === 0) return true;
1188
+ const fileExtension = getFileExtension(val.name, caseSensitive);
1189
+ const normalizedBlacklist = extensionBlacklist.map((ext) => normalizeExtension(ext, caseSensitive));
1190
+ return !normalizedBlacklist.includes(fileExtension);
1191
+ },
1192
+ {
1193
+ message: getMessage("extensionBlacklist", { extension: extensionBlacklist?.join(", ") || "" })
1194
+ }
1195
+ ).refine(
1196
+ (val) => {
1197
+ if (val === null || extension === void 0) return true;
1198
+ const fileName = val.name;
1199
+ const fileExtension = getFileExtension(fileName, caseSensitive);
1200
+ const allowedExtensions = Array.isArray(extension) ? extension : [extension];
1201
+ const normalizedExtensions = allowedExtensions.map((ext) => normalizeExtension(ext, caseSensitive));
1202
+ return normalizedExtensions.includes(fileExtension);
1203
+ },
1204
+ {
1205
+ message: getMessage("extension", { extension: Array.isArray(extension) ? extension.join(", ") : extension || "" })
1206
+ }
1207
+ ).refine(
1208
+ (val) => {
1209
+ if (val === null || namePattern === void 0) return true;
1210
+ const pattern = typeof namePattern === "string" ? new RegExp(namePattern) : namePattern;
1211
+ return pattern.test(val.name);
1212
+ },
1213
+ {
1214
+ message: getMessage("name", { pattern: namePattern?.toString() || "" })
1215
+ }
1216
+ ).refine(
277
1217
  (val) => {
278
- if (val === "" || val === void 0 || val === null) return defaultValue ?? null;
279
- return typeof val === "string" ? Number(val) : val;
280
- },
281
- import_zod5.z.union([
282
- import_zod5.z.number({
283
- error: (issue) => {
284
- if (issue.code === "invalid_type") return t("common.number.integer");
285
- return t("common.number.required");
1218
+ if (val === null || nameBlacklist === void 0) return true;
1219
+ const blacklistPatterns = Array.isArray(nameBlacklist) ? nameBlacklist : [nameBlacklist];
1220
+ for (const blacklistPattern of blacklistPatterns) {
1221
+ const pattern = typeof blacklistPattern === "string" ? new RegExp(blacklistPattern) : blacklistPattern;
1222
+ if (pattern.test(val.name)) {
1223
+ return false;
286
1224
  }
287
- }),
288
- import_zod5.z.null()
289
- ])
290
- ).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 }) });
1225
+ }
1226
+ return true;
1227
+ },
1228
+ {
1229
+ message: getMessage("nameBlacklist", { pattern: "" })
1230
+ }
1231
+ );
291
1232
  return schema;
292
1233
  }
1234
+ function getFileExtension(fileName, caseSensitive) {
1235
+ const lastDotIndex = fileName.lastIndexOf(".");
1236
+ if (lastDotIndex === -1) return "";
1237
+ const extension = fileName.substring(lastDotIndex);
1238
+ return caseSensitive ? extension : extension.toLowerCase();
1239
+ }
1240
+ function normalizeExtension(extension, caseSensitive) {
1241
+ const normalized = extension.startsWith(".") ? extension : `.${extension}`;
1242
+ return caseSensitive ? normalized : normalized.toLowerCase();
1243
+ }
1244
+ function formatFileSize(bytes) {
1245
+ const units = ["B", "KB", "MB", "GB", "TB"];
1246
+ let size = bytes;
1247
+ let unitIndex = 0;
1248
+ while (size >= 1024 && unitIndex < units.length - 1) {
1249
+ size /= 1024;
1250
+ unitIndex++;
1251
+ }
1252
+ return `${Math.round(size * 100) / 100} ${units[unitIndex]}`;
1253
+ }
293
1254
 
294
- // src/common/password.ts
1255
+ // src/validators/common/id.ts
295
1256
  var import_zod6 = require("zod");
296
- function password(options) {
297
- const { required = true, min, max, uppercase, lowercase, digits, special } = options ?? {};
298
- const baseSchema = required ? import_zod6.z.preprocess((val) => val === "" || val === null || val === void 0 ? null : val, import_zod6.z.coerce.string().trim()) : import_zod6.z.preprocess((val) => val === "" || val === null || val === void 0 ? null : val, import_zod6.z.coerce.string().trim().nullable());
299
- 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") });
1257
+ var ID_PATTERNS = {
1258
+ numeric: /^\d+$/,
1259
+ uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
1260
+ objectId: /^[0-9a-f]{24}$/i,
1261
+ nanoid: /^[A-Za-z0-9_-]{21}$/,
1262
+ snowflake: /^\d{19}$/,
1263
+ cuid: /^c[a-z0-9]{24}$/,
1264
+ ulid: /^[0-9A-HJKMNP-TV-Z]{26}$/,
1265
+ shortid: /^[A-Za-z0-9_-]{7,14}$/
1266
+ };
1267
+ var detectIdType = (value) => {
1268
+ const orderedTypes = [
1269
+ ["uuid", ID_PATTERNS.uuid],
1270
+ ["objectId", ID_PATTERNS.objectId],
1271
+ ["snowflake", ID_PATTERNS.snowflake],
1272
+ ["cuid", ID_PATTERNS.cuid],
1273
+ ["ulid", ID_PATTERNS.ulid],
1274
+ ["nanoid", ID_PATTERNS.nanoid],
1275
+ ["numeric", ID_PATTERNS.numeric],
1276
+ ["shortid", ID_PATTERNS.shortid]
1277
+ // 放最後,因為最通用
1278
+ ];
1279
+ for (const [type, pattern] of orderedTypes) {
1280
+ if (pattern.test(value)) {
1281
+ return type;
1282
+ }
1283
+ }
1284
+ return null;
1285
+ };
1286
+ var validateIdType = (value, type) => {
1287
+ if (type === "auto") {
1288
+ return detectIdType(value) !== null;
1289
+ }
1290
+ const pattern = ID_PATTERNS[type];
1291
+ return pattern ? pattern.test(value) : false;
1292
+ };
1293
+ function id(options) {
1294
+ const {
1295
+ required = true,
1296
+ type = "auto",
1297
+ minLength,
1298
+ maxLength,
1299
+ allowedTypes,
1300
+ customRegex,
1301
+ includes,
1302
+ excludes,
1303
+ startsWith,
1304
+ endsWith,
1305
+ caseSensitive = true,
1306
+ transform,
1307
+ defaultValue,
1308
+ i18n
1309
+ } = options ?? {};
1310
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
1311
+ const getMessage = (key, params) => {
1312
+ if (i18n) {
1313
+ const currentLocale2 = getLocale();
1314
+ const customMessages = i18n[currentLocale2];
1315
+ if (customMessages && customMessages[key]) {
1316
+ const template = customMessages[key];
1317
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
1318
+ }
1319
+ }
1320
+ return t(`common.id.${key}`, params);
1321
+ };
1322
+ const preprocessFn = (val) => {
1323
+ if (val === "" || val === null || val === void 0) {
1324
+ return actualDefaultValue;
1325
+ }
1326
+ let processed = String(val);
1327
+ if (transform) {
1328
+ processed = transform(processed);
1329
+ }
1330
+ return processed;
1331
+ };
1332
+ const baseSchema = required ? import_zod6.z.preprocess(preprocessFn, import_zod6.z.string()) : import_zod6.z.preprocess(preprocessFn, import_zod6.z.string().nullable());
1333
+ const schema = baseSchema.refine((val) => {
1334
+ if (val === null) return true;
1335
+ if (required && (val === "" || val === "null" || val === "undefined")) {
1336
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1337
+ }
1338
+ const comparisonVal = !caseSensitive ? val.toLowerCase() : val;
1339
+ if (val !== null && minLength !== void 0 && val.length < minLength) {
1340
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("minLength", { minLength }), path: [] }]);
1341
+ }
1342
+ if (val !== null && maxLength !== void 0 && val.length > maxLength) {
1343
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("maxLength", { maxLength }), path: [] }]);
1344
+ }
1345
+ const hasContentValidations = customRegex !== void 0 || startsWith !== void 0 || endsWith !== void 0 || includes !== void 0 || excludes !== void 0;
1346
+ if (val !== null && customRegex !== void 0) {
1347
+ if (!customRegex.test(val)) {
1348
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("customFormat"), path: [] }]);
1349
+ }
1350
+ } else if (val !== null && !hasContentValidations) {
1351
+ let isValidId;
1352
+ if (allowedTypes && allowedTypes.length > 0) {
1353
+ isValidId = allowedTypes.some((allowedType) => validateIdType(val, allowedType));
1354
+ if (!isValidId) {
1355
+ const typeNames = allowedTypes.join(", ");
1356
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("invalid") + ` (allowed types: ${typeNames})`, path: [] }]);
1357
+ }
1358
+ } else if (type !== "auto") {
1359
+ isValidId = validateIdType(val, type);
1360
+ if (!isValidId) {
1361
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage(type) || getMessage("invalid"), path: [] }]);
1362
+ }
1363
+ } else {
1364
+ isValidId = detectIdType(val) !== null;
1365
+ if (!isValidId) {
1366
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1367
+ }
1368
+ }
1369
+ } else if (val !== null && hasContentValidations && type !== "auto" && !customRegex) {
1370
+ if (allowedTypes && allowedTypes.length > 0) {
1371
+ const isValidType = allowedTypes.some((allowedType) => validateIdType(val, allowedType));
1372
+ if (!isValidType) {
1373
+ const typeNames = allowedTypes.join(", ");
1374
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("invalid") + ` (allowed types: ${typeNames})`, path: [] }]);
1375
+ }
1376
+ } else {
1377
+ if (!validateIdType(val, type)) {
1378
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage(type) || getMessage("invalid"), path: [] }]);
1379
+ }
1380
+ }
1381
+ }
1382
+ const searchStartsWith = !caseSensitive && startsWith ? startsWith.toLowerCase() : startsWith;
1383
+ const searchEndsWith = !caseSensitive && endsWith ? endsWith.toLowerCase() : endsWith;
1384
+ const searchIncludes = !caseSensitive && includes ? includes.toLowerCase() : includes;
1385
+ if (val !== null && startsWith !== void 0 && !comparisonVal.startsWith(searchStartsWith)) {
1386
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("startsWith", { startsWith }), path: [] }]);
1387
+ }
1388
+ if (val !== null && endsWith !== void 0 && !comparisonVal.endsWith(searchEndsWith)) {
1389
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("endsWith", { endsWith }), path: [] }]);
1390
+ }
1391
+ if (val !== null && includes !== void 0 && !comparisonVal.includes(searchIncludes)) {
1392
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1393
+ }
1394
+ if (val !== null && excludes !== void 0) {
1395
+ const excludeList = Array.isArray(excludes) ? excludes : [excludes];
1396
+ for (const exclude of excludeList) {
1397
+ const searchExclude = !caseSensitive ? exclude.toLowerCase() : exclude;
1398
+ if (comparisonVal.includes(searchExclude)) {
1399
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
1400
+ }
1401
+ }
1402
+ }
1403
+ return true;
1404
+ }).transform((val) => {
1405
+ if (val === null) return val;
1406
+ const shouldPreserveCase = type === "uuid" || type === "objectId";
1407
+ if (!caseSensitive && !shouldPreserveCase) {
1408
+ return val.toLowerCase();
1409
+ }
1410
+ return val;
1411
+ });
300
1412
  return schema;
301
1413
  }
302
1414
 
303
- // src/common/integer.ts
1415
+ // src/validators/common/number.ts
304
1416
  var import_zod7 = require("zod");
305
- function integer(options) {
306
- const { required = true, min, max, defaultValue } = options ?? {};
1417
+ function number(options) {
1418
+ const {
1419
+ required = true,
1420
+ min,
1421
+ max,
1422
+ defaultValue,
1423
+ type = "both",
1424
+ positive,
1425
+ negative,
1426
+ nonNegative,
1427
+ nonPositive,
1428
+ multipleOf,
1429
+ precision,
1430
+ finite = true,
1431
+ transform,
1432
+ parseCommas = false,
1433
+ i18n
1434
+ } = options ?? {};
1435
+ const getMessage = (key, params) => {
1436
+ if (i18n) {
1437
+ const currentLocale2 = getLocale();
1438
+ const customMessages = i18n[currentLocale2];
1439
+ if (customMessages && customMessages[key]) {
1440
+ const template = customMessages[key];
1441
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
1442
+ }
1443
+ }
1444
+ return t(`common.number.${key}`, params);
1445
+ };
1446
+ const actualDefaultValue = defaultValue ?? null;
307
1447
  const schema = import_zod7.z.preprocess(
308
1448
  (val) => {
309
- if (val === "" || val === void 0 || val === null) return defaultValue ?? null;
310
- return typeof val === "string" ? Number(val) : val;
311
- },
312
- import_zod7.z.union([
313
- import_zod7.z.number({
314
- error: (issue) => {
315
- if (issue.code === "invalid_type") return t("common.integer.integer");
316
- return t("common.integer.required");
1449
+ if (val === "" || val === void 0 || val === null) {
1450
+ return actualDefaultValue;
1451
+ }
1452
+ if (typeof val === "string") {
1453
+ let processedVal = val.trim();
1454
+ if (parseCommas) {
1455
+ processedVal = processedVal.replace(/,/g, "");
1456
+ }
1457
+ const parsed = Number(processedVal);
1458
+ if (isNaN(parsed)) {
1459
+ return parsed;
317
1460
  }
318
- }),
319
- import_zod7.z.null()
320
- ])
321
- ).refine((val) => !required || val !== null, {
322
- message: t("common.integer.required")
323
- }).refine((val) => val === null || Number.isInteger(val), {
324
- message: t("common.integer.integer")
325
- }).refine((val) => val === null || min === void 0 || val >= min, {
326
- message: t("common.integer.min", { min })
327
- }).refine((val) => val === null || max === void 0 || val <= max, {
328
- message: t("common.integer.max", { max })
1461
+ if (transform) {
1462
+ return transform(parsed);
1463
+ }
1464
+ return parsed;
1465
+ }
1466
+ if (typeof val === "number") {
1467
+ if (transform && Number.isFinite(val)) {
1468
+ return transform(val);
1469
+ }
1470
+ return val;
1471
+ }
1472
+ return val;
1473
+ },
1474
+ import_zod7.z.union([import_zod7.z.number(), import_zod7.z.null(), import_zod7.z.nan(), import_zod7.z.custom((val) => val === Infinity || val === -Infinity)])
1475
+ ).refine((val) => {
1476
+ if (required && val === null) {
1477
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1478
+ }
1479
+ if (val === null) return true;
1480
+ if (typeof val === "number" && isNaN(val)) {
1481
+ if (type === "integer") {
1482
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("integer"), path: [] }]);
1483
+ } else if (type === "float") {
1484
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("float"), path: [] }]);
1485
+ } else {
1486
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1487
+ }
1488
+ }
1489
+ if (typeof val !== "number") {
1490
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1491
+ }
1492
+ if (finite && !Number.isFinite(val)) {
1493
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("finite"), path: [] }]);
1494
+ }
1495
+ if (type === "integer" && !Number.isInteger(val)) {
1496
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("integer"), path: [] }]);
1497
+ }
1498
+ if (type === "float" && Number.isInteger(val)) {
1499
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("float"), path: [] }]);
1500
+ }
1501
+ if (positive && val <= 0) {
1502
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("positive"), path: [] }]);
1503
+ }
1504
+ if (negative && val >= 0) {
1505
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("negative"), path: [] }]);
1506
+ }
1507
+ if (nonNegative && val < 0) {
1508
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("nonNegative"), path: [] }]);
1509
+ }
1510
+ if (nonPositive && val > 0) {
1511
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("nonPositive"), path: [] }]);
1512
+ }
1513
+ if (min !== void 0 && val < min) {
1514
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
1515
+ }
1516
+ if (max !== void 0 && val > max) {
1517
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
1518
+ }
1519
+ if (multipleOf !== void 0 && val % multipleOf !== 0) {
1520
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("multipleOf", { multipleOf }), path: [] }]);
1521
+ }
1522
+ if (precision !== void 0) {
1523
+ const decimalPlaces = (val.toString().split(".")[1] || "").length;
1524
+ if (decimalPlaces > precision) {
1525
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("precision", { precision }), path: [] }]);
1526
+ }
1527
+ }
1528
+ return true;
1529
+ });
1530
+ return schema;
1531
+ }
1532
+
1533
+ // src/validators/common/password.ts
1534
+ var import_zod8 = require("zod");
1535
+ var COMMON_PASSWORDS = [
1536
+ "password",
1537
+ "123456",
1538
+ "123456789",
1539
+ "12345678",
1540
+ "12345",
1541
+ "1234567",
1542
+ "admin",
1543
+ "qwerty",
1544
+ "abc123",
1545
+ "password123",
1546
+ "letmein",
1547
+ "welcome",
1548
+ "monkey",
1549
+ "dragon",
1550
+ "sunshine",
1551
+ "princess"
1552
+ ];
1553
+ var calculatePasswordStrength = (password2) => {
1554
+ let score = 0;
1555
+ if (password2.length >= 8) score += 1;
1556
+ if (password2.length >= 12) score += 1;
1557
+ if (password2.length >= 16) score += 1;
1558
+ if (/[a-z]/.test(password2)) score += 1;
1559
+ if (/[A-Z]/.test(password2)) score += 1;
1560
+ if (/[0-9]/.test(password2)) score += 1;
1561
+ if (/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password2)) score += 1;
1562
+ if (/(.)\1{2,}/.test(password2)) score -= 1;
1563
+ if (/(?:abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz|012|123|234|345|456|567|678|789)/i.test(password2)) score -= 1;
1564
+ if (score <= 2) return "weak";
1565
+ if (score <= 4) return "medium";
1566
+ if (score <= 6) return "strong";
1567
+ return "very-strong";
1568
+ };
1569
+ function password(options) {
1570
+ const {
1571
+ required = true,
1572
+ min,
1573
+ max,
1574
+ uppercase,
1575
+ lowercase,
1576
+ digits,
1577
+ special,
1578
+ noRepeating,
1579
+ noSequential,
1580
+ noCommonWords,
1581
+ minStrength,
1582
+ excludes,
1583
+ includes,
1584
+ regex,
1585
+ transform,
1586
+ defaultValue,
1587
+ i18n
1588
+ } = options ?? {};
1589
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
1590
+ const getMessage = (key, params) => {
1591
+ if (i18n) {
1592
+ const currentLocale2 = getLocale();
1593
+ const customMessages = i18n[currentLocale2];
1594
+ if (customMessages && customMessages[key]) {
1595
+ const template = customMessages[key];
1596
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
1597
+ }
1598
+ }
1599
+ return t(`common.password.${key}`, params);
1600
+ };
1601
+ const preprocessFn = (val) => {
1602
+ if (val === "" || val === null || val === void 0) {
1603
+ return actualDefaultValue;
1604
+ }
1605
+ let processed = String(val);
1606
+ if (transform) {
1607
+ processed = transform(processed);
1608
+ }
1609
+ return processed;
1610
+ };
1611
+ const baseSchema = required ? import_zod8.z.preprocess(preprocessFn, import_zod8.z.string()) : import_zod8.z.preprocess(preprocessFn, import_zod8.z.string().nullable());
1612
+ const schema = baseSchema.refine((val) => {
1613
+ if (val === null) return true;
1614
+ if (required && (val === "" || val === "null" || val === "undefined")) {
1615
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1616
+ }
1617
+ if (val !== null && min !== void 0 && val.length < min) {
1618
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
1619
+ }
1620
+ if (val !== null && max !== void 0 && val.length > max) {
1621
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
1622
+ }
1623
+ if (val !== null && uppercase && !/[A-Z]/.test(val)) {
1624
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("uppercase"), path: [] }]);
1625
+ }
1626
+ if (val !== null && lowercase && !/[a-z]/.test(val)) {
1627
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("lowercase"), path: [] }]);
1628
+ }
1629
+ if (val !== null && digits && !/[0-9]/.test(val)) {
1630
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("digits"), path: [] }]);
1631
+ }
1632
+ if (val !== null && special && !/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(val)) {
1633
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("special"), path: [] }]);
1634
+ }
1635
+ if (val !== null && noRepeating && /(.)\1{2,}/.test(val)) {
1636
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("noRepeating"), path: [] }]);
1637
+ }
1638
+ if (val !== null && noSequential && /(?:abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz|012|123|234|345|456|567|678|789)/i.test(val)) {
1639
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("noSequential"), path: [] }]);
1640
+ }
1641
+ if (val !== null && noCommonWords && COMMON_PASSWORDS.some((common) => val.toLowerCase().includes(common.toLowerCase()))) {
1642
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("noCommonWords"), path: [] }]);
1643
+ }
1644
+ if (val !== null && minStrength) {
1645
+ const strength = calculatePasswordStrength(val);
1646
+ const strengthLevels = ["weak", "medium", "strong", "very-strong"];
1647
+ const currentLevel = strengthLevels.indexOf(strength);
1648
+ const requiredLevel = strengthLevels.indexOf(minStrength);
1649
+ if (currentLevel < requiredLevel) {
1650
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("minStrength", { minStrength }), path: [] }]);
1651
+ }
1652
+ }
1653
+ if (val !== null && includes !== void 0 && !val.includes(includes)) {
1654
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1655
+ }
1656
+ if (val !== null && excludes !== void 0) {
1657
+ const excludeList = Array.isArray(excludes) ? excludes : [excludes];
1658
+ for (const exclude of excludeList) {
1659
+ if (val.includes(exclude)) {
1660
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
1661
+ }
1662
+ }
1663
+ }
1664
+ if (val !== null && regex !== void 0 && !regex.test(val)) {
1665
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("invalid", { regex }), path: [] }]);
1666
+ }
1667
+ return true;
1668
+ });
1669
+ return schema;
1670
+ }
1671
+
1672
+ // src/validators/common/text.ts
1673
+ var import_zod9 = require("zod");
1674
+ function text(options) {
1675
+ const { required = true, minLength, maxLength, startsWith, endsWith, includes, excludes, regex, trimMode = "trim", casing = "none", transform, notEmpty, defaultValue, i18n } = options ?? {};
1676
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
1677
+ const getMessage = (key, params) => {
1678
+ if (i18n) {
1679
+ const currentLocale2 = getLocale();
1680
+ const customMessages = i18n[currentLocale2];
1681
+ if (customMessages && customMessages[key]) {
1682
+ const template = customMessages[key];
1683
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
1684
+ }
1685
+ }
1686
+ return t(`common.text.${key}`, params);
1687
+ };
1688
+ const applyTrim = (str) => {
1689
+ switch (trimMode) {
1690
+ case "trimStart":
1691
+ return str.trimStart();
1692
+ case "trimEnd":
1693
+ return str.trimEnd();
1694
+ case "none":
1695
+ return str;
1696
+ default:
1697
+ return str.trim();
1698
+ }
1699
+ };
1700
+ const applyCasing = (str) => {
1701
+ switch (casing) {
1702
+ case "upper":
1703
+ return str.toUpperCase();
1704
+ case "lower":
1705
+ return str.toLowerCase();
1706
+ case "title":
1707
+ return str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase());
1708
+ default:
1709
+ return str;
1710
+ }
1711
+ };
1712
+ const preprocessFn = (val) => {
1713
+ if (val === "" || val === null || val === void 0) {
1714
+ return actualDefaultValue;
1715
+ }
1716
+ let processed = String(val);
1717
+ processed = applyTrim(processed);
1718
+ processed = applyCasing(processed);
1719
+ if (transform) {
1720
+ processed = transform(processed);
1721
+ }
1722
+ return processed;
1723
+ };
1724
+ const baseSchema = required ? import_zod9.z.preprocess(preprocessFn, import_zod9.z.string()) : import_zod9.z.preprocess(preprocessFn, import_zod9.z.string().nullable());
1725
+ const schema = baseSchema.refine((val) => {
1726
+ if (val === null) return true;
1727
+ if (required && (val === "" || val === "null" || val === "undefined")) {
1728
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1729
+ }
1730
+ if (notEmpty && val !== null && val.trim() === "") {
1731
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("notEmpty"), path: [] }]);
1732
+ }
1733
+ if (val !== null && minLength !== void 0 && val.length < minLength) {
1734
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("minLength", { minLength }), path: [] }]);
1735
+ }
1736
+ if (val !== null && maxLength !== void 0 && val.length > maxLength) {
1737
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("maxLength", { maxLength }), path: [] }]);
1738
+ }
1739
+ if (val !== null && startsWith !== void 0 && !val.startsWith(startsWith)) {
1740
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("startsWith", { startsWith }), path: [] }]);
1741
+ }
1742
+ if (val !== null && endsWith !== void 0 && !val.endsWith(endsWith)) {
1743
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("endsWith", { endsWith }), path: [] }]);
1744
+ }
1745
+ if (val !== null && includes !== void 0 && !val.includes(includes)) {
1746
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1747
+ }
1748
+ if (val !== null && excludes !== void 0) {
1749
+ const excludeList = Array.isArray(excludes) ? excludes : [excludes];
1750
+ for (const exclude of excludeList) {
1751
+ if (val.includes(exclude)) {
1752
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
1753
+ }
1754
+ }
1755
+ }
1756
+ if (val !== null && regex !== void 0 && !regex.test(val)) {
1757
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("invalid", { regex }), path: [] }]);
1758
+ }
1759
+ return true;
1760
+ });
1761
+ return schema;
1762
+ }
1763
+
1764
+ // src/validators/common/time.ts
1765
+ var import_zod10 = require("zod");
1766
+ var TIME_PATTERNS = {
1767
+ "HH:mm": /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/,
1768
+ "HH:mm:ss": /^([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/,
1769
+ "hh:mm A": /^(0?[1-9]|1[0-2]):[0-5][0-9]\s?(AM|PM)$/i,
1770
+ "hh:mm:ss A": /^(0?[1-9]|1[0-2]):[0-5][0-9]:[0-5][0-9]\s?(AM|PM)$/i,
1771
+ "H:mm": /^([0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/,
1772
+ "h:mm A": /^([1-9]|1[0-2]):[0-5][0-9]\s?(AM|PM)$/i
1773
+ };
1774
+ var parseTimeToMinutes = (timeStr, format) => {
1775
+ const cleanTime = timeStr.trim();
1776
+ try {
1777
+ if (format.includes("A")) {
1778
+ const match = cleanTime.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?\s?(AM|PM)$/i);
1779
+ if (!match) return null;
1780
+ const [, hourStr, minuteStr, , period] = match;
1781
+ let hour = parseInt(hourStr, 10);
1782
+ const minute = parseInt(minuteStr, 10);
1783
+ if (hour < 1 || hour > 12 || minute < 0 || minute > 59) {
1784
+ return null;
1785
+ }
1786
+ if (period.toUpperCase() === "PM" && hour !== 12) {
1787
+ hour += 12;
1788
+ } else if (period.toUpperCase() === "AM" && hour === 12) {
1789
+ hour = 0;
1790
+ }
1791
+ return hour * 60 + minute;
1792
+ } else {
1793
+ const match = cleanTime.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/);
1794
+ if (!match) return null;
1795
+ const [, hourStr, minuteStr] = match;
1796
+ const hour = parseInt(hourStr, 10);
1797
+ const minute = parseInt(minuteStr, 10);
1798
+ if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
1799
+ return null;
1800
+ }
1801
+ return hour * 60 + minute;
1802
+ }
1803
+ } catch {
1804
+ return null;
1805
+ }
1806
+ };
1807
+ var validateTimeFormat = (value, format) => {
1808
+ const pattern = TIME_PATTERNS[format];
1809
+ return pattern.test(value.trim());
1810
+ };
1811
+ var normalizeTime = (timeStr, format) => {
1812
+ const cleanTime = timeStr.trim();
1813
+ if (format.includes("A")) {
1814
+ const match = cleanTime.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?\s?(AM|PM)$/i);
1815
+ if (!match) return null;
1816
+ const [, hourStr, minuteStr, secondStr = "00", period] = match;
1817
+ let hour = parseInt(hourStr, 10);
1818
+ const minute = parseInt(minuteStr, 10);
1819
+ const second = parseInt(secondStr, 10);
1820
+ if (period.toUpperCase() === "PM" && hour !== 12) {
1821
+ hour += 12;
1822
+ } else if (period.toUpperCase() === "AM" && hour === 12) {
1823
+ hour = 0;
1824
+ }
1825
+ 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")}`;
1826
+ }
1827
+ if (format === "H:mm") {
1828
+ const match = cleanTime.match(/^(\d{1,2}):(\d{2})$/);
1829
+ if (!match) return null;
1830
+ const [, hourStr, minuteStr] = match;
1831
+ return `${hourStr.padStart(2, "0")}:${minuteStr}`;
1832
+ }
1833
+ return cleanTime;
1834
+ };
1835
+ function time(options) {
1836
+ const {
1837
+ required = true,
1838
+ format = "HH:mm",
1839
+ min,
1840
+ max,
1841
+ minHour,
1842
+ maxHour,
1843
+ allowedHours,
1844
+ minuteStep,
1845
+ secondStep,
1846
+ includes,
1847
+ excludes,
1848
+ regex,
1849
+ trimMode = "trim",
1850
+ casing = "none",
1851
+ whitelist,
1852
+ whitelistOnly = false,
1853
+ transform,
1854
+ defaultValue,
1855
+ i18n
1856
+ } = options ?? {};
1857
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
1858
+ const getMessage = (key, params) => {
1859
+ if (i18n) {
1860
+ const currentLocale2 = getLocale();
1861
+ const customMessages = i18n[currentLocale2];
1862
+ if (customMessages && customMessages[key]) {
1863
+ const template = customMessages[key];
1864
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
1865
+ }
1866
+ }
1867
+ return t(`common.time.${key}`, params);
1868
+ };
1869
+ const preprocessFn = (val) => {
1870
+ if (val === null || val === void 0) {
1871
+ return actualDefaultValue;
1872
+ }
1873
+ let processed = String(val);
1874
+ switch (trimMode) {
1875
+ case "trim":
1876
+ processed = processed.trim();
1877
+ break;
1878
+ case "trimStart":
1879
+ processed = processed.trimStart();
1880
+ break;
1881
+ case "trimEnd":
1882
+ processed = processed.trimEnd();
1883
+ break;
1884
+ case "none":
1885
+ break;
1886
+ }
1887
+ if (processed === "") {
1888
+ if (whitelist && whitelist.includes("")) {
1889
+ return "";
1890
+ }
1891
+ if (!required) {
1892
+ return actualDefaultValue;
1893
+ }
1894
+ return actualDefaultValue;
1895
+ }
1896
+ switch (casing) {
1897
+ case "upper":
1898
+ processed = processed.toUpperCase();
1899
+ break;
1900
+ case "lower":
1901
+ processed = processed.toLowerCase();
1902
+ break;
1903
+ case "none":
1904
+ break;
1905
+ }
1906
+ if (transform) {
1907
+ processed = transform(processed);
1908
+ }
1909
+ return processed;
1910
+ };
1911
+ const baseSchema = required ? import_zod10.z.preprocess(preprocessFn, import_zod10.z.string()) : import_zod10.z.preprocess(preprocessFn, import_zod10.z.string().nullable());
1912
+ const schema = baseSchema.refine((val) => {
1913
+ if (val === null) return true;
1914
+ if (required && (val === "" || val === "null" || val === "undefined")) {
1915
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1916
+ }
1917
+ if (val === null) return true;
1918
+ if (!required && val === "") return true;
1919
+ if (whitelist && whitelist.length > 0) {
1920
+ if (whitelist.includes(val)) {
1921
+ return true;
1922
+ }
1923
+ if (whitelistOnly) {
1924
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
1925
+ }
1926
+ }
1927
+ if (regex) {
1928
+ if (!regex.test(val)) {
1929
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("customRegex"), path: [] }]);
1930
+ }
1931
+ } else {
1932
+ if (!validateTimeFormat(val, format)) {
1933
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("format", { format }), path: [] }]);
1934
+ }
1935
+ }
1936
+ if (includes && !val.includes(includes)) {
1937
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1938
+ }
1939
+ if (excludes) {
1940
+ const excludeList = Array.isArray(excludes) ? excludes : [excludes];
1941
+ for (const exclude of excludeList) {
1942
+ if (val.includes(exclude)) {
1943
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
1944
+ }
1945
+ }
1946
+ }
1947
+ if (regex) {
1948
+ return true;
1949
+ }
1950
+ const timeMinutes = parseTimeToMinutes(val, format);
1951
+ if (timeMinutes === null) {
1952
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1953
+ }
1954
+ const hour = Math.floor(timeMinutes / 60);
1955
+ if (minHour !== void 0 && hour < minHour) {
1956
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("hour", { minHour, maxHour: maxHour ?? 23 }), path: [] }]);
1957
+ }
1958
+ if (maxHour !== void 0 && hour > maxHour) {
1959
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("hour", { minHour: minHour ?? 0, maxHour }), path: [] }]);
1960
+ }
1961
+ if (allowedHours && allowedHours.length > 0) {
1962
+ if (!allowedHours.includes(hour)) {
1963
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("hour", { allowedHours: allowedHours.join(", ") }), path: [] }]);
1964
+ }
1965
+ }
1966
+ const minute = timeMinutes % 60;
1967
+ if (minuteStep !== void 0 && minute % minuteStep !== 0) {
1968
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("minute", { minuteStep }), path: [] }]);
1969
+ }
1970
+ if (secondStep !== void 0 && format.includes("ss")) {
1971
+ const secondMatch = val.match(/:(\d{2})$/);
1972
+ if (secondMatch) {
1973
+ const seconds = parseInt(secondMatch[1], 10);
1974
+ if (seconds % secondStep !== 0) {
1975
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("second", { secondStep }), path: [] }]);
1976
+ }
1977
+ }
1978
+ }
1979
+ if (min) {
1980
+ const minMinutes = parseTimeToMinutes(min, format);
1981
+ if (minMinutes !== null && timeMinutes < minMinutes) {
1982
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
1983
+ }
1984
+ }
1985
+ if (max) {
1986
+ const maxMinutes = parseTimeToMinutes(max, format);
1987
+ if (maxMinutes !== null && timeMinutes > maxMinutes) {
1988
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
1989
+ }
1990
+ }
1991
+ return true;
1992
+ });
1993
+ return schema;
1994
+ }
1995
+
1996
+ // src/validators/common/url.ts
1997
+ var import_zod11 = require("zod");
1998
+ function url(options) {
1999
+ const {
2000
+ required = true,
2001
+ min,
2002
+ max,
2003
+ includes,
2004
+ excludes,
2005
+ protocols,
2006
+ allowedDomains,
2007
+ blockedDomains,
2008
+ allowedPorts,
2009
+ blockedPorts,
2010
+ pathStartsWith,
2011
+ pathEndsWith,
2012
+ mustHaveQuery,
2013
+ mustNotHaveQuery,
2014
+ mustHaveFragment,
2015
+ mustNotHaveFragment,
2016
+ allowLocalhost = true,
2017
+ blockLocalhost,
2018
+ transform,
2019
+ defaultValue = null,
2020
+ i18n
2021
+ } = options ?? {};
2022
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
2023
+ const getMessage = (key, params) => {
2024
+ if (i18n) {
2025
+ const currentLocale2 = getLocale();
2026
+ const customMessages = i18n[currentLocale2];
2027
+ if (customMessages && customMessages[key]) {
2028
+ const template = customMessages[key];
2029
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
2030
+ }
2031
+ }
2032
+ return t(`common.url.${key}`, params);
2033
+ };
2034
+ const preprocessFn = (val) => {
2035
+ if (val === "" || val === null || val === void 0) {
2036
+ return actualDefaultValue;
2037
+ }
2038
+ let processed = String(val).trim();
2039
+ if (transform) {
2040
+ processed = transform(processed);
2041
+ }
2042
+ return processed;
2043
+ };
2044
+ const baseSchema = required ? import_zod11.z.preprocess(preprocessFn, import_zod11.z.string()) : import_zod11.z.preprocess(preprocessFn, import_zod11.z.string().nullable());
2045
+ const schema = baseSchema.refine((val) => {
2046
+ if (val === null) return true;
2047
+ if (required && (val === "" || val === "null" || val === "undefined")) {
2048
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
2049
+ }
2050
+ let urlObj;
2051
+ try {
2052
+ urlObj = new URL(val);
2053
+ } catch {
2054
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
2055
+ }
2056
+ if (val !== null && min !== void 0 && val.length < min) {
2057
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
2058
+ }
2059
+ if (val !== null && max !== void 0 && val.length > max) {
2060
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
2061
+ }
2062
+ if (val !== null && includes !== void 0 && !val.includes(includes)) {
2063
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
2064
+ }
2065
+ if (val !== null && excludes !== void 0) {
2066
+ const excludeList = Array.isArray(excludes) ? excludes : [excludes];
2067
+ for (const exclude of excludeList) {
2068
+ if (val.includes(exclude)) {
2069
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
2070
+ }
2071
+ }
2072
+ }
2073
+ if (protocols && !protocols.includes(urlObj.protocol.slice(0, -1))) {
2074
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("protocol", { protocols: protocols.join(", ") }), path: [] }]);
2075
+ }
2076
+ const hostname = urlObj.hostname.toLowerCase();
2077
+ if (allowedDomains && !allowedDomains.some((domain) => hostname === domain || hostname.endsWith(`.${domain}`))) {
2078
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("domain", { domains: allowedDomains.join(", ") }), path: [] }]);
2079
+ }
2080
+ if (blockedDomains && blockedDomains.some((domain) => hostname === domain || hostname.endsWith(`.${domain}`))) {
2081
+ const blockedDomain = blockedDomains.find((domain) => hostname === domain || hostname.endsWith(`.${domain}`));
2082
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("domainBlacklist", { domain: blockedDomain }), path: [] }]);
2083
+ }
2084
+ const port = urlObj.port ? parseInt(urlObj.port) : urlObj.protocol === "https:" ? 443 : 80;
2085
+ if (allowedPorts && !allowedPorts.includes(port)) {
2086
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("port", { ports: allowedPorts.join(", ") }), path: [] }]);
2087
+ }
2088
+ if (blockedPorts && blockedPorts.includes(port)) {
2089
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("port", { port }), path: [] }]);
2090
+ }
2091
+ if (pathStartsWith && !urlObj.pathname.startsWith(pathStartsWith)) {
2092
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("pathStartsWith", { path: pathStartsWith }), path: [] }]);
2093
+ }
2094
+ if (pathEndsWith && !urlObj.pathname.endsWith(pathEndsWith)) {
2095
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("pathEndsWith", { path: pathEndsWith }), path: [] }]);
2096
+ }
2097
+ if (mustHaveQuery && !urlObj.search) {
2098
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("hasQuery"), path: [] }]);
2099
+ }
2100
+ if (mustNotHaveQuery && urlObj.search) {
2101
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("noQuery"), path: [] }]);
2102
+ }
2103
+ if (mustHaveFragment && !urlObj.hash) {
2104
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("hasFragment"), path: [] }]);
2105
+ }
2106
+ if (mustNotHaveFragment && urlObj.hash) {
2107
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("noFragment"), path: [] }]);
2108
+ }
2109
+ const isLocalhost = hostname === "localhost" || hostname === "127.0.0.1" || hostname.startsWith("192.168.") || hostname.startsWith("10.") || hostname.match(/^172\.(1[6-9]|2[0-9]|3[0-1])\./);
2110
+ if (blockLocalhost && isLocalhost) {
2111
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("noLocalhost"), path: [] }]);
2112
+ }
2113
+ if (!allowLocalhost && isLocalhost) {
2114
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("localhost"), path: [] }]);
2115
+ }
2116
+ return true;
2117
+ });
2118
+ return schema;
2119
+ }
2120
+
2121
+ // src/validators/taiwan/business-id.ts
2122
+ var import_zod12 = require("zod");
2123
+ var validateTaiwanBusinessId = (value) => {
2124
+ if (!/^\d{8}$/.test(value)) {
2125
+ return false;
2126
+ }
2127
+ const digits = value.split("").map(Number);
2128
+ const coefficients = [1, 2, 1, 2, 1, 2, 4];
2129
+ let sum = 0;
2130
+ for (let i = 0; i < 7; i++) {
2131
+ const product = digits[i] * coefficients[i];
2132
+ sum += Math.floor(product / 10) + product % 10;
2133
+ }
2134
+ sum += digits[7];
2135
+ if (sum % 5 === 0) {
2136
+ return true;
2137
+ }
2138
+ if (sum % 10 === 0) {
2139
+ return true;
2140
+ }
2141
+ if (digits[6] === 7) {
2142
+ let altSum = 0;
2143
+ for (let i = 0; i < 7; i++) {
2144
+ const product = digits[i] * coefficients[i];
2145
+ altSum += Math.floor(product / 10) + product % 10;
2146
+ }
2147
+ altSum += 1 + digits[7];
2148
+ if (altSum % 5 === 0 || altSum % 10 === 0) {
2149
+ return true;
2150
+ }
2151
+ }
2152
+ return false;
2153
+ };
2154
+ function businessId(options) {
2155
+ const {
2156
+ required = true,
2157
+ transform,
2158
+ defaultValue,
2159
+ i18n
2160
+ } = options ?? {};
2161
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
2162
+ const getMessage = (key, params) => {
2163
+ if (i18n) {
2164
+ const currentLocale2 = getLocale();
2165
+ const customMessages = i18n[currentLocale2];
2166
+ if (customMessages && customMessages[key]) {
2167
+ const template = customMessages[key];
2168
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
2169
+ }
2170
+ }
2171
+ return t(`taiwan.businessId.${key}`, params);
2172
+ };
2173
+ const preprocessFn = (val) => {
2174
+ if (val === "" || val === null || val === void 0) {
2175
+ return actualDefaultValue;
2176
+ }
2177
+ let processed = String(val).trim();
2178
+ if (processed === "" && !required) {
2179
+ return null;
2180
+ }
2181
+ if (transform) {
2182
+ processed = transform(processed);
2183
+ }
2184
+ return processed;
2185
+ };
2186
+ const baseSchema = required ? import_zod12.z.preprocess(preprocessFn, import_zod12.z.string()) : import_zod12.z.preprocess(preprocessFn, import_zod12.z.string().nullable());
2187
+ const schema = baseSchema.refine((val) => {
2188
+ if (val === null) return true;
2189
+ if (required && (val === "" || val === "null" || val === "undefined")) {
2190
+ throw new import_zod12.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
2191
+ }
2192
+ if (val === null) return true;
2193
+ if (!required && val === "") return true;
2194
+ if (!validateTaiwanBusinessId(val)) {
2195
+ throw new import_zod12.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
2196
+ }
2197
+ return true;
2198
+ });
2199
+ return schema;
2200
+ }
2201
+
2202
+ // src/validators/taiwan/national-id.ts
2203
+ var import_zod13 = require("zod");
2204
+ var CITY_CODES = {
2205
+ "A": 10,
2206
+ "B": 11,
2207
+ "C": 12,
2208
+ "D": 13,
2209
+ "E": 14,
2210
+ "F": 15,
2211
+ "G": 16,
2212
+ "H": 17,
2213
+ "I": 34,
2214
+ "J": 18,
2215
+ "K": 19,
2216
+ "L": 20,
2217
+ "M": 21,
2218
+ "N": 22,
2219
+ "O": 35,
2220
+ "P": 23,
2221
+ "Q": 24,
2222
+ "R": 25,
2223
+ "S": 26,
2224
+ "T": 27,
2225
+ "U": 28,
2226
+ "V": 29,
2227
+ "W": 32,
2228
+ "X": 30,
2229
+ "Y": 31,
2230
+ "Z": 33
2231
+ };
2232
+ var validateCitizenId = (value) => {
2233
+ if (!/^[A-Z][1-2]\d{8}$/.test(value)) {
2234
+ return false;
2235
+ }
2236
+ const letter = value[0];
2237
+ const digits = value.slice(1).split("").map(Number);
2238
+ const cityCode = CITY_CODES[letter];
2239
+ if (!cityCode) return false;
2240
+ const cityDigits = [Math.floor(cityCode / 10), cityCode % 10];
2241
+ const coefficients = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1];
2242
+ let sum = cityDigits[0] * coefficients[0] + cityDigits[1] * coefficients[1];
2243
+ for (let i = 0; i < 8; i++) {
2244
+ sum += digits[i] * coefficients[i + 2];
2245
+ }
2246
+ const checksum = (10 - sum % 10) % 10;
2247
+ return checksum === digits[8];
2248
+ };
2249
+ var validateOldResidentId = (value) => {
2250
+ if (!/^[A-Z][ABCD]\d{8}$/.test(value)) {
2251
+ return false;
2252
+ }
2253
+ const letter = value[0];
2254
+ const genderCode = value[1];
2255
+ const digits = value.slice(2).split("").map(Number);
2256
+ const cityCode = CITY_CODES[letter];
2257
+ if (!cityCode) return false;
2258
+ const genderValue = genderCode === "A" || genderCode === "C" ? 1 : 0;
2259
+ const cityDigits = [Math.floor(cityCode / 10), cityCode % 10];
2260
+ const coefficients = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1];
2261
+ let sum = cityDigits[0] * coefficients[0] + cityDigits[1] * coefficients[1] + genderValue * coefficients[2];
2262
+ for (let i = 0; i < 7; i++) {
2263
+ sum += digits[i] * coefficients[i + 3];
2264
+ }
2265
+ const checksum = (10 - sum % 10) % 10;
2266
+ return checksum === digits[7];
2267
+ };
2268
+ var validateNewResidentId = (value) => {
2269
+ if (!/^[A-Z][89]\d{8}$/.test(value)) {
2270
+ return false;
2271
+ }
2272
+ const letter = value[0];
2273
+ const digits = value.slice(1).split("").map(Number);
2274
+ const cityCode = CITY_CODES[letter];
2275
+ if (!cityCode) return false;
2276
+ const cityDigits = [Math.floor(cityCode / 10), cityCode % 10];
2277
+ const coefficients = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1];
2278
+ let sum = cityDigits[0] * coefficients[0] + cityDigits[1] * coefficients[1];
2279
+ for (let i = 0; i < 8; i++) {
2280
+ sum += digits[i] * coefficients[i + 2];
2281
+ }
2282
+ const checksum = (10 - sum % 10) % 10;
2283
+ return checksum === digits[8];
2284
+ };
2285
+ var validateTaiwanNationalId = (value, type = "both", allowOldResident = true) => {
2286
+ if (!/^[A-Z].{9}$/.test(value)) {
2287
+ return false;
2288
+ }
2289
+ switch (type) {
2290
+ case "citizen":
2291
+ return validateCitizenId(value);
2292
+ case "resident":
2293
+ return (allowOldResident ? validateOldResidentId(value) : false) || validateNewResidentId(value);
2294
+ case "both":
2295
+ return validateCitizenId(value) || (allowOldResident ? validateOldResidentId(value) : false) || validateNewResidentId(value);
2296
+ default:
2297
+ return false;
2298
+ }
2299
+ };
2300
+ function nationalId(options) {
2301
+ const {
2302
+ required = true,
2303
+ type = "both",
2304
+ allowOldResident = true,
2305
+ transform,
2306
+ defaultValue,
2307
+ i18n
2308
+ } = options ?? {};
2309
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
2310
+ const getMessage = (key, params) => {
2311
+ if (i18n) {
2312
+ const currentLocale2 = getLocale();
2313
+ const customMessages = i18n[currentLocale2];
2314
+ if (customMessages && customMessages[key]) {
2315
+ const template = customMessages[key];
2316
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
2317
+ }
2318
+ }
2319
+ return t(`taiwan.nationalId.${key}`, params);
2320
+ };
2321
+ const preprocessFn = (val) => {
2322
+ if (val === "" || val === null || val === void 0) {
2323
+ return actualDefaultValue;
2324
+ }
2325
+ let processed = String(val).trim().toUpperCase();
2326
+ if (processed === "" && !required) {
2327
+ return null;
2328
+ }
2329
+ if (transform) {
2330
+ processed = transform(processed);
2331
+ }
2332
+ return processed;
2333
+ };
2334
+ const baseSchema = required ? import_zod13.z.preprocess(preprocessFn, import_zod13.z.string()) : import_zod13.z.preprocess(preprocessFn, import_zod13.z.string().nullable());
2335
+ const schema = baseSchema.refine((val) => {
2336
+ if (val === null) return true;
2337
+ if (required && (val === "" || val === "null" || val === "undefined")) {
2338
+ throw new import_zod13.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
2339
+ }
2340
+ if (val === null) return true;
2341
+ if (!required && val === "") return true;
2342
+ if (!validateTaiwanNationalId(val, type, allowOldResident)) {
2343
+ throw new import_zod13.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
2344
+ }
2345
+ return true;
2346
+ });
2347
+ return schema;
2348
+ }
2349
+
2350
+ // src/validators/taiwan/mobile.ts
2351
+ var import_zod14 = require("zod");
2352
+ var validateTaiwanMobile = (value) => {
2353
+ return /^09[0-9]\d{7}$/.test(value);
2354
+ };
2355
+ function mobile(options) {
2356
+ const { required = true, whitelist, transform, defaultValue, i18n } = options ?? {};
2357
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
2358
+ const getMessage = (key, params) => {
2359
+ if (i18n) {
2360
+ const currentLocale2 = getLocale();
2361
+ const customMessages = i18n[currentLocale2];
2362
+ if (customMessages && customMessages[key]) {
2363
+ const template = customMessages[key];
2364
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
2365
+ }
2366
+ }
2367
+ return t(`taiwan.mobile.${key}`, params);
2368
+ };
2369
+ const preprocessFn = (val) => {
2370
+ if (val === null || val === void 0) {
2371
+ return actualDefaultValue;
2372
+ }
2373
+ let processed = String(val).trim();
2374
+ if (processed === "") {
2375
+ if (whitelist && whitelist.includes("")) {
2376
+ return "";
2377
+ }
2378
+ if (!required) {
2379
+ return actualDefaultValue;
2380
+ }
2381
+ return actualDefaultValue;
2382
+ }
2383
+ if (transform) {
2384
+ processed = transform(processed);
2385
+ }
2386
+ return processed;
2387
+ };
2388
+ const baseSchema = required ? import_zod14.z.preprocess(preprocessFn, import_zod14.z.string()) : import_zod14.z.preprocess(preprocessFn, import_zod14.z.string().nullable());
2389
+ const schema = baseSchema.refine((val) => {
2390
+ if (val === null) return true;
2391
+ if (required && (val === "" || val === "null" || val === "undefined")) {
2392
+ throw new import_zod14.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
2393
+ }
2394
+ if (val === null) return true;
2395
+ if (!required && val === "") return true;
2396
+ if (whitelist && whitelist.length > 0) {
2397
+ if (whitelist.includes(val)) {
2398
+ return true;
2399
+ }
2400
+ throw new import_zod14.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
2401
+ }
2402
+ if (!validateTaiwanMobile(val)) {
2403
+ throw new import_zod14.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
2404
+ }
2405
+ return true;
2406
+ });
2407
+ return schema;
2408
+ }
2409
+
2410
+ // src/validators/taiwan/postal-code.ts
2411
+ var import_zod15 = require("zod");
2412
+ var VALID_3_DIGIT_PREFIXES = [
2413
+ // Taipei City (台北市) - 100-116
2414
+ "100",
2415
+ "103",
2416
+ "104",
2417
+ "105",
2418
+ "106",
2419
+ "108",
2420
+ "110",
2421
+ "111",
2422
+ "112",
2423
+ "114",
2424
+ "115",
2425
+ "116",
2426
+ // New Taipei City (新北市) - 200-253
2427
+ "200",
2428
+ "201",
2429
+ "202",
2430
+ "203",
2431
+ "204",
2432
+ "205",
2433
+ "206",
2434
+ "207",
2435
+ "208",
2436
+ "220",
2437
+ "221",
2438
+ "222",
2439
+ "223",
2440
+ "224",
2441
+ "226",
2442
+ "227",
2443
+ "228",
2444
+ "231",
2445
+ "232",
2446
+ "233",
2447
+ "234",
2448
+ "235",
2449
+ "236",
2450
+ "237",
2451
+ "238",
2452
+ "239",
2453
+ "241",
2454
+ "242",
2455
+ "243",
2456
+ "244",
2457
+ "247",
2458
+ "248",
2459
+ "249",
2460
+ "251",
2461
+ "252",
2462
+ "253",
2463
+ // Keelung City (基隆市) - 200-206
2464
+ "200",
2465
+ "201",
2466
+ "202",
2467
+ "203",
2468
+ "204",
2469
+ "205",
2470
+ "206",
2471
+ // Taoyuan City (桃園市) - 300-338
2472
+ "300",
2473
+ "302",
2474
+ "303",
2475
+ "304",
2476
+ "305",
2477
+ "306",
2478
+ "307",
2479
+ "308",
2480
+ "310",
2481
+ "311",
2482
+ "312",
2483
+ "313",
2484
+ "314",
2485
+ "315",
2486
+ "316",
2487
+ "317",
2488
+ "318",
2489
+ "320",
2490
+ "324",
2491
+ "325",
2492
+ "326",
2493
+ "327",
2494
+ "328",
2495
+ "330",
2496
+ "333",
2497
+ "334",
2498
+ "335",
2499
+ "336",
2500
+ "337",
2501
+ "338",
2502
+ // Hsinchu County (新竹縣) - 300-315
2503
+ "300",
2504
+ "302",
2505
+ "303",
2506
+ "304",
2507
+ "305",
2508
+ "306",
2509
+ "307",
2510
+ "308",
2511
+ "310",
2512
+ "311",
2513
+ "312",
2514
+ "313",
2515
+ "314",
2516
+ "315",
2517
+ // Hsinchu City (新竹市) - 300
2518
+ "300",
2519
+ // Miaoli County (苗栗縣) - 350-369
2520
+ "350",
2521
+ "351",
2522
+ "352",
2523
+ "353",
2524
+ "354",
2525
+ "356",
2526
+ "357",
2527
+ "358",
2528
+ "360",
2529
+ "361",
2530
+ "362",
2531
+ "363",
2532
+ "364",
2533
+ "365",
2534
+ "366",
2535
+ "367",
2536
+ "368",
2537
+ "369",
2538
+ // Taichung City (台中市) - 400-439
2539
+ "400",
2540
+ "401",
2541
+ "402",
2542
+ "403",
2543
+ "404",
2544
+ "406",
2545
+ "407",
2546
+ "408",
2547
+ "411",
2548
+ "412",
2549
+ "413",
2550
+ "414",
2551
+ "420",
2552
+ "421",
2553
+ "422",
2554
+ "423",
2555
+ "424",
2556
+ "426",
2557
+ "427",
2558
+ "428",
2559
+ "429",
2560
+ "432",
2561
+ "433",
2562
+ "434",
2563
+ "435",
2564
+ "436",
2565
+ "437",
2566
+ "438",
2567
+ "439",
2568
+ // Changhua County (彰化縣) - 500-530
2569
+ "500",
2570
+ "502",
2571
+ "503",
2572
+ "504",
2573
+ "505",
2574
+ "506",
2575
+ "507",
2576
+ "508",
2577
+ "509",
2578
+ "510",
2579
+ "511",
2580
+ "512",
2581
+ "513",
2582
+ "514",
2583
+ "515",
2584
+ "516",
2585
+ "520",
2586
+ "521",
2587
+ "522",
2588
+ "523",
2589
+ "524",
2590
+ "525",
2591
+ "526",
2592
+ "527",
2593
+ "528",
2594
+ "530",
2595
+ // Nantou County (南投縣) - 540-558
2596
+ "540",
2597
+ "541",
2598
+ "542",
2599
+ "544",
2600
+ "545",
2601
+ "546",
2602
+ "551",
2603
+ "552",
2604
+ "553",
2605
+ "555",
2606
+ "556",
2607
+ "557",
2608
+ "558",
2609
+ // Yunlin County (雲林縣) - 630-655
2610
+ "630",
2611
+ "631",
2612
+ "632",
2613
+ "633",
2614
+ "634",
2615
+ "635",
2616
+ "636",
2617
+ "637",
2618
+ "638",
2619
+ "640",
2620
+ "643",
2621
+ "646",
2622
+ "647",
2623
+ "648",
2624
+ "649",
2625
+ "651",
2626
+ "652",
2627
+ "653",
2628
+ "654",
2629
+ "655",
2630
+ // Chiayi County (嘉義縣) - 600-625
2631
+ "600",
2632
+ "602",
2633
+ "603",
2634
+ "604",
2635
+ "605",
2636
+ "606",
2637
+ "607",
2638
+ "608",
2639
+ "611",
2640
+ "612",
2641
+ "613",
2642
+ "614",
2643
+ "615",
2644
+ "616",
2645
+ "621",
2646
+ "622",
2647
+ "623",
2648
+ "624",
2649
+ "625",
2650
+ // Chiayi City (嘉義市) - 600
2651
+ "600",
2652
+ // Tainan City (台南市) - 700-745
2653
+ "700",
2654
+ "701",
2655
+ "702",
2656
+ "704",
2657
+ "708",
2658
+ "709",
2659
+ "710",
2660
+ "711",
2661
+ "712",
2662
+ "713",
2663
+ "714",
2664
+ "715",
2665
+ "716",
2666
+ "717",
2667
+ "718",
2668
+ "719",
2669
+ "720",
2670
+ "721",
2671
+ "722",
2672
+ "723",
2673
+ "724",
2674
+ "725",
2675
+ "726",
2676
+ "727",
2677
+ "730",
2678
+ "731",
2679
+ "732",
2680
+ "733",
2681
+ "734",
2682
+ "735",
2683
+ "736",
2684
+ "737",
2685
+ "741",
2686
+ "742",
2687
+ "743",
2688
+ "744",
2689
+ "745",
2690
+ // Kaohsiung City (高雄市) - 800-852
2691
+ "800",
2692
+ "801",
2693
+ "802",
2694
+ "803",
2695
+ "804",
2696
+ "805",
2697
+ "806",
2698
+ "807",
2699
+ "811",
2700
+ "812",
2701
+ "813",
2702
+ "814",
2703
+ "815",
2704
+ "820",
2705
+ "821",
2706
+ "822",
2707
+ "823",
2708
+ "824",
2709
+ "825",
2710
+ "826",
2711
+ "827",
2712
+ "828",
2713
+ "829",
2714
+ "830",
2715
+ "831",
2716
+ "832",
2717
+ "833",
2718
+ "840",
2719
+ "842",
2720
+ "843",
2721
+ "844",
2722
+ "845",
2723
+ "846",
2724
+ "847",
2725
+ "848",
2726
+ "849",
2727
+ "851",
2728
+ "852",
2729
+ // Pingtung County (屏東縣) - 900-947
2730
+ "900",
2731
+ "901",
2732
+ "902",
2733
+ "903",
2734
+ "904",
2735
+ "905",
2736
+ "906",
2737
+ "907",
2738
+ "908",
2739
+ "909",
2740
+ "911",
2741
+ "912",
2742
+ "913",
2743
+ "920",
2744
+ "921",
2745
+ "922",
2746
+ "923",
2747
+ "924",
2748
+ "925",
2749
+ "926",
2750
+ "927",
2751
+ "928",
2752
+ "929",
2753
+ "931",
2754
+ "932",
2755
+ "940",
2756
+ "941",
2757
+ "942",
2758
+ "943",
2759
+ "944",
2760
+ "945",
2761
+ "946",
2762
+ "947",
2763
+ // Yilan County (宜蘭縣) - 260-269
2764
+ "260",
2765
+ "261",
2766
+ "262",
2767
+ "263",
2768
+ "264",
2769
+ "265",
2770
+ "266",
2771
+ "267",
2772
+ "268",
2773
+ "269",
2774
+ // Hualien County (花蓮縣) - 970-983
2775
+ "970",
2776
+ "971",
2777
+ "972",
2778
+ "973",
2779
+ "974",
2780
+ "975",
2781
+ "976",
2782
+ "977",
2783
+ "978",
2784
+ "979",
2785
+ "981",
2786
+ "982",
2787
+ "983",
2788
+ // Taitung County (台東縣) - 950-966
2789
+ "950",
2790
+ "951",
2791
+ "952",
2792
+ "953",
2793
+ "954",
2794
+ "955",
2795
+ "956",
2796
+ "957",
2797
+ "958",
2798
+ "959",
2799
+ "961",
2800
+ "962",
2801
+ "963",
2802
+ "964",
2803
+ "965",
2804
+ "966",
2805
+ // Penghu County (澎湖縣) - 880-885
2806
+ "880",
2807
+ "881",
2808
+ "882",
2809
+ "883",
2810
+ "884",
2811
+ "885",
2812
+ // Kinmen County (金門縣) - 890-896
2813
+ "890",
2814
+ "891",
2815
+ "892",
2816
+ "893",
2817
+ "894",
2818
+ "895",
2819
+ "896",
2820
+ // Lienchiang County (連江縣/馬祖) - 209-212
2821
+ "209",
2822
+ "210",
2823
+ "211",
2824
+ "212"
2825
+ ];
2826
+ var POSTAL_CODE_RANGES = {
2827
+ // Major cities with extensive postal networks
2828
+ "100": { range5: [1, 99], range6: [1, 999] },
2829
+ // Taipei City - Zhongzheng
2830
+ "103": { range5: [1, 99], range6: [1, 999] },
2831
+ // Taipei City - Datong
2832
+ "104": { range5: [1, 99], range6: [1, 999] },
2833
+ // Taipei City - Zhongshan
2834
+ "105": { range5: [1, 99], range6: [1, 999] },
2835
+ // Taipei City - Songshan
2836
+ "106": { range5: [1, 99], range6: [1, 999] },
2837
+ // Taipei City - Da'an
2838
+ "108": { range5: [1, 99], range6: [1, 999] },
2839
+ // Taipei City - Wanhua
2840
+ "110": { range5: [1, 99], range6: [1, 999] },
2841
+ // Taipei City - Xinyi
2842
+ "111": { range5: [1, 99], range6: [1, 999] },
2843
+ // Taipei City - Shilin
2844
+ "112": { range5: [1, 99], range6: [1, 999] },
2845
+ // Taipei City - Beitou
2846
+ "114": { range5: [1, 99], range6: [1, 999] },
2847
+ // Taipei City - Neihu
2848
+ "115": { range5: [1, 99], range6: [1, 999] },
2849
+ // Taipei City - Nangang
2850
+ "116": { range5: [1, 99], range6: [1, 999] },
2851
+ // Taipei City - Wenshan
2852
+ // New Taipei City major areas
2853
+ "220": { range5: [1, 99], range6: [1, 999] },
2854
+ // Banqiao
2855
+ "221": { range5: [1, 99], range6: [1, 999] },
2856
+ // Xizhi
2857
+ "222": { range5: [1, 99], range6: [1, 999] },
2858
+ // Shenkeng
2859
+ "223": { range5: [1, 99], range6: [1, 999] },
2860
+ // Shiding
2861
+ "224": { range5: [1, 99], range6: [1, 999] },
2862
+ // Ruifang
2863
+ // Taoyuan City
2864
+ "320": { range5: [1, 99], range6: [1, 999] },
2865
+ // Zhongli
2866
+ "324": { range5: [1, 99], range6: [1, 999] },
2867
+ // Pingzhen
2868
+ "330": { range5: [1, 99], range6: [1, 999] },
2869
+ // Taoyuan
2870
+ // Taichung City
2871
+ "400": { range5: [1, 99], range6: [1, 999] },
2872
+ // Central District
2873
+ "401": { range5: [1, 99], range6: [1, 999] },
2874
+ // East District
2875
+ "402": { range5: [1, 99], range6: [1, 999] },
2876
+ // South District
2877
+ "403": { range5: [1, 99], range6: [1, 999] },
2878
+ // West District
2879
+ "404": { range5: [1, 99], range6: [1, 999] },
2880
+ // North District
2881
+ // Tainan City
2882
+ "700": { range5: [1, 99], range6: [1, 999] },
2883
+ // Central District
2884
+ "701": { range5: [1, 99], range6: [1, 999] },
2885
+ // East District
2886
+ "702": { range5: [1, 99], range6: [1, 999] },
2887
+ // South District
2888
+ // Kaohsiung City
2889
+ "800": { range5: [1, 99], range6: [1, 999] },
2890
+ // Xinxing
2891
+ "801": { range5: [1, 99], range6: [1, 999] },
2892
+ // Qianjin
2893
+ "802": { range5: [1, 99], range6: [1, 999] },
2894
+ // Lingya
2895
+ "803": { range5: [1, 99], range6: [1, 999] },
2896
+ // Yancheng
2897
+ // Smaller areas with more limited ranges
2898
+ "880": { range5: [1, 50], range6: [1, 500] },
2899
+ // Penghu (smaller population)
2900
+ "890": { range5: [1, 30], range6: [1, 300] },
2901
+ // Kinmen (smaller population)
2902
+ "209": { range5: [1, 20], range6: [1, 200] }
2903
+ // Lienchiang/Matsu (smallest population)
2904
+ };
2905
+ var getPostalCodeRanges = (prefix) => {
2906
+ return POSTAL_CODE_RANGES[prefix] || {
2907
+ range5: [1, 99],
2908
+ // Default range for 5-digit
2909
+ range6: [1, 999]
2910
+ // Default range for 6-digit
2911
+ };
2912
+ };
2913
+ var validate3DigitPostalCode = (value, strictValidation = true, allowedPrefixes, blockedPrefixes) => {
2914
+ if (!/^\d{3}$/.test(value)) {
2915
+ return false;
2916
+ }
2917
+ if (blockedPrefixes && blockedPrefixes.includes(value)) {
2918
+ return false;
2919
+ }
2920
+ if (allowedPrefixes) {
2921
+ return allowedPrefixes.includes(value);
2922
+ }
2923
+ if (strictValidation) {
2924
+ return VALID_3_DIGIT_PREFIXES.includes(value);
2925
+ }
2926
+ const num = parseInt(value, 10);
2927
+ return num >= 100 && num <= 999;
2928
+ };
2929
+ var validate5DigitPostalCode = (value, strictValidation = true, strictSuffixValidation = false, allowedPrefixes, blockedPrefixes) => {
2930
+ if (!/^\d{5}$/.test(value)) {
2931
+ return false;
2932
+ }
2933
+ const prefix = value.substring(0, 3);
2934
+ const suffix = value.substring(3, 5);
2935
+ if (!validate3DigitPostalCode(prefix, strictValidation, allowedPrefixes, blockedPrefixes)) {
2936
+ return false;
2937
+ }
2938
+ if (strictSuffixValidation) {
2939
+ const suffixNum = parseInt(suffix, 10);
2940
+ const ranges = getPostalCodeRanges(prefix);
2941
+ if (suffixNum < ranges.range5[0] || suffixNum > ranges.range5[1]) {
2942
+ return false;
2943
+ }
2944
+ }
2945
+ return true;
2946
+ };
2947
+ var validate6DigitPostalCode = (value, strictValidation = true, strictSuffixValidation = false, allowedPrefixes, blockedPrefixes) => {
2948
+ if (!/^\d{6}$/.test(value)) {
2949
+ return false;
2950
+ }
2951
+ const prefix = value.substring(0, 3);
2952
+ const suffix = value.substring(3, 6);
2953
+ if (!validate3DigitPostalCode(prefix, strictValidation, allowedPrefixes, blockedPrefixes)) {
2954
+ return false;
2955
+ }
2956
+ if (strictSuffixValidation) {
2957
+ const suffixNum = parseInt(suffix, 10);
2958
+ const ranges = getPostalCodeRanges(prefix);
2959
+ if (suffixNum < ranges.range6[0] || suffixNum > ranges.range6[1]) {
2960
+ return false;
2961
+ }
2962
+ }
2963
+ return true;
2964
+ };
2965
+ var validateTaiwanPostalCode = (value, format = "3+6", strictValidation = true, strictSuffixValidation = false, allowDashes = true, allowedPrefixes, blockedPrefixes) => {
2966
+ if (!value || typeof value !== "string") {
2967
+ return false;
2968
+ }
2969
+ const cleanValue = allowDashes ? value.replace(/[-\s]/g, "") : value;
2970
+ if (!allowDashes && /[-\s]/.test(value)) {
2971
+ return false;
2972
+ }
2973
+ switch (format) {
2974
+ case "3":
2975
+ return cleanValue.length === 3 && validate3DigitPostalCode(cleanValue, strictValidation, allowedPrefixes, blockedPrefixes);
2976
+ case "5":
2977
+ return cleanValue.length === 5 && validate5DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes);
2978
+ case "6":
2979
+ return cleanValue.length === 6 && validate6DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes);
2980
+ case "3+5":
2981
+ return cleanValue.length === 3 && validate3DigitPostalCode(cleanValue, strictValidation, allowedPrefixes, blockedPrefixes) || cleanValue.length === 5 && validate5DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes);
2982
+ case "3+6":
2983
+ return cleanValue.length === 3 && validate3DigitPostalCode(cleanValue, strictValidation, allowedPrefixes, blockedPrefixes) || cleanValue.length === 6 && validate6DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes);
2984
+ case "5+6":
2985
+ return cleanValue.length === 5 && validate5DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes) || cleanValue.length === 6 && validate6DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes);
2986
+ case "all":
2987
+ return cleanValue.length === 3 && validate3DigitPostalCode(cleanValue, strictValidation, allowedPrefixes, blockedPrefixes) || cleanValue.length === 5 && validate5DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes) || cleanValue.length === 6 && validate6DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes);
2988
+ default:
2989
+ return false;
2990
+ }
2991
+ };
2992
+ function postalCode(options) {
2993
+ const {
2994
+ required = true,
2995
+ format = "3+6",
2996
+ strictValidation = true,
2997
+ allowDashes = true,
2998
+ warn5Digit = true,
2999
+ allowedPrefixes,
3000
+ blockedPrefixes,
3001
+ transform,
3002
+ defaultValue,
3003
+ i18n,
3004
+ strictSuffixValidation = false,
3005
+ deprecate5Digit = false
3006
+ } = options ?? {};
3007
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
3008
+ const getMessage = (key, params) => {
3009
+ if (i18n) {
3010
+ const currentLocale2 = getLocale();
3011
+ const customMessages = i18n[currentLocale2];
3012
+ if (customMessages && customMessages[key]) {
3013
+ const template = customMessages[key];
3014
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
3015
+ }
3016
+ }
3017
+ return t(`taiwan.postalCode.${key}`, params);
3018
+ };
3019
+ const preprocessFn = (val) => {
3020
+ if (val === "" || val === null || val === void 0) {
3021
+ return actualDefaultValue;
3022
+ }
3023
+ let processed = String(val).trim();
3024
+ if (allowDashes) {
3025
+ processed = processed.replace(/[-\s]/g, "");
3026
+ }
3027
+ if (processed === "" && !required) {
3028
+ return null;
3029
+ }
3030
+ if (transform) {
3031
+ processed = transform(processed);
3032
+ }
3033
+ return processed;
3034
+ };
3035
+ const baseSchema = required ? import_zod15.z.preprocess(preprocessFn, import_zod15.z.string()) : import_zod15.z.preprocess(preprocessFn, import_zod15.z.string().nullable());
3036
+ const schema = baseSchema.refine((val) => {
3037
+ if (val === null) return true;
3038
+ if (required && (val === "" || val === "null" || val === "undefined")) {
3039
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
3040
+ }
3041
+ if (val === null) return true;
3042
+ if (!required && val === "") return true;
3043
+ const cleanValue = val.replace(/[-\s]/g, "");
3044
+ if (format === "3" && cleanValue.length !== 3) {
3045
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("format3Only"), path: [] }]);
3046
+ }
3047
+ if (format === "5" && cleanValue.length !== 5) {
3048
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("format5Only"), path: [] }]);
3049
+ }
3050
+ if (format === "6" && cleanValue.length !== 6) {
3051
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("format6Only"), path: [] }]);
3052
+ }
3053
+ if (deprecate5Digit && cleanValue.length === 5) {
3054
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("deprecated5Digit"), path: [] }]);
3055
+ }
3056
+ if (strictSuffixValidation) {
3057
+ if (cleanValue.length === 5) {
3058
+ const prefix = cleanValue.substring(0, 3);
3059
+ const suffix = cleanValue.substring(3, 5);
3060
+ const suffixNum = parseInt(suffix, 10);
3061
+ const ranges = getPostalCodeRanges(prefix);
3062
+ if (suffixNum < ranges.range5[0] || suffixNum > ranges.range5[1]) {
3063
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("invalidSuffix"), path: [] }]);
3064
+ }
3065
+ } else if (cleanValue.length === 6) {
3066
+ const prefix = cleanValue.substring(0, 3);
3067
+ const suffix = cleanValue.substring(3, 6);
3068
+ const suffixNum = parseInt(suffix, 10);
3069
+ const ranges = getPostalCodeRanges(prefix);
3070
+ if (suffixNum < ranges.range6[0] || suffixNum > ranges.range6[1]) {
3071
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("invalidSuffix"), path: [] }]);
3072
+ }
3073
+ }
3074
+ }
3075
+ if (!validateTaiwanPostalCode(val, format, strictValidation, strictSuffixValidation, allowDashes, allowedPrefixes, blockedPrefixes)) {
3076
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
3077
+ }
3078
+ if (warn5Digit && cleanValue.length === 5 && format !== "5" && !deprecate5Digit) {
3079
+ console.warn(getMessage("legacy5DigitWarning"));
3080
+ }
3081
+ return true;
3082
+ });
3083
+ return schema;
3084
+ }
3085
+
3086
+ // src/validators/taiwan/tel.ts
3087
+ var import_zod16 = require("zod");
3088
+ var validateTaiwanTel = (value) => {
3089
+ const cleanValue = value.replace(/[-\s]/g, "");
3090
+ if (!/^0\d{7,10}$/.test(cleanValue)) {
3091
+ return false;
3092
+ }
3093
+ const areaCode4 = cleanValue.substring(0, 4);
3094
+ if (areaCode4 === "0826") {
3095
+ return cleanValue.length === 9 && /^0826[6]\d{4}$/.test(cleanValue);
3096
+ }
3097
+ if (areaCode4 === "0836") {
3098
+ return cleanValue.length === 9 && /^0836[2-9]\d{4}$/.test(cleanValue);
3099
+ }
3100
+ const areaCode3 = cleanValue.substring(0, 3);
3101
+ if (areaCode3 === "037") {
3102
+ return cleanValue.length === 9 && /^037[2-9]\d{5}$/.test(cleanValue);
3103
+ }
3104
+ if (areaCode3 === "049") {
3105
+ return cleanValue.length === 10 && /^049[2-9]\d{6}$/.test(cleanValue);
3106
+ }
3107
+ if (areaCode3 === "082") {
3108
+ return cleanValue.length === 9 && /^082[2-57-9]\d{5}$/.test(cleanValue);
3109
+ }
3110
+ if (areaCode3 === "089") {
3111
+ return cleanValue.length === 9 && /^089[2-9]\d{5}$/.test(cleanValue);
3112
+ }
3113
+ const areaCode2 = cleanValue.substring(0, 2);
3114
+ if (areaCode2 === "02") {
3115
+ return cleanValue.length === 10 && /^02[235-8]\d{7}$/.test(cleanValue);
3116
+ }
3117
+ if (["03", "04", "05", "06"].includes(areaCode2)) {
3118
+ return cleanValue.length === 9;
3119
+ }
3120
+ if (areaCode2 === "07") {
3121
+ return cleanValue.length === 9 && /^07[2-9]\d{6}$/.test(cleanValue);
3122
+ }
3123
+ if (areaCode2 === "08") {
3124
+ return cleanValue.length === 9 && /^08[478]\d{6}$/.test(cleanValue);
3125
+ }
3126
+ return false;
3127
+ };
3128
+ function tel(options) {
3129
+ const { required = true, whitelist, transform, defaultValue, i18n } = options ?? {};
3130
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
3131
+ const getMessage = (key, params) => {
3132
+ if (i18n) {
3133
+ const currentLocale2 = getLocale();
3134
+ const customMessages = i18n[currentLocale2];
3135
+ if (customMessages && customMessages[key]) {
3136
+ const template = customMessages[key];
3137
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
3138
+ }
3139
+ }
3140
+ return t(`taiwan.tel.${key}`, params);
3141
+ };
3142
+ const preprocessFn = (val) => {
3143
+ if (val === null || val === void 0) {
3144
+ return actualDefaultValue;
3145
+ }
3146
+ let processed = String(val).trim();
3147
+ if (processed === "") {
3148
+ if (whitelist && whitelist.includes("")) {
3149
+ return "";
3150
+ }
3151
+ if (!required) {
3152
+ return actualDefaultValue;
3153
+ }
3154
+ return actualDefaultValue;
3155
+ }
3156
+ if (transform) {
3157
+ processed = transform(processed);
3158
+ }
3159
+ return processed;
3160
+ };
3161
+ const baseSchema = required ? import_zod16.z.preprocess(preprocessFn, import_zod16.z.string()) : import_zod16.z.preprocess(preprocessFn, import_zod16.z.string().nullable());
3162
+ const schema = baseSchema.refine((val) => {
3163
+ if (val === null) return true;
3164
+ if (required && (val === "" || val === "null" || val === "undefined")) {
3165
+ throw new import_zod16.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
3166
+ }
3167
+ if (val === null) return true;
3168
+ if (!required && val === "") return true;
3169
+ if (whitelist && whitelist.length > 0) {
3170
+ if (whitelist.includes(val)) {
3171
+ return true;
3172
+ }
3173
+ throw new import_zod16.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
3174
+ }
3175
+ if (!validateTaiwanTel(val)) {
3176
+ throw new import_zod16.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
3177
+ }
3178
+ return true;
3179
+ });
3180
+ return schema;
3181
+ }
3182
+
3183
+ // src/validators/taiwan/fax.ts
3184
+ var import_zod17 = require("zod");
3185
+ var validateTaiwanFax = (value) => {
3186
+ const cleanValue = value.replace(/[-\s]/g, "");
3187
+ if (!/^0\d{7,10}$/.test(cleanValue)) {
3188
+ return false;
3189
+ }
3190
+ const areaCode4 = cleanValue.substring(0, 4);
3191
+ if (areaCode4 === "0826") {
3192
+ return cleanValue.length === 9 && /^0826[6]\d{4}$/.test(cleanValue);
3193
+ }
3194
+ if (areaCode4 === "0836") {
3195
+ return cleanValue.length === 9 && /^0836[2-9]\d{4}$/.test(cleanValue);
3196
+ }
3197
+ const areaCode3 = cleanValue.substring(0, 3);
3198
+ if (areaCode3 === "037") {
3199
+ return cleanValue.length === 9 && /^037[2-9]\d{5}$/.test(cleanValue);
3200
+ }
3201
+ if (areaCode3 === "049") {
3202
+ return cleanValue.length === 10 && /^049[2-9]\d{6}$/.test(cleanValue);
3203
+ }
3204
+ if (areaCode3 === "082") {
3205
+ return cleanValue.length === 9 && /^082[2-57-9]\d{5}$/.test(cleanValue);
3206
+ }
3207
+ if (areaCode3 === "089") {
3208
+ return cleanValue.length === 9 && /^089[2-9]\d{5}$/.test(cleanValue);
3209
+ }
3210
+ const areaCode2 = cleanValue.substring(0, 2);
3211
+ if (areaCode2 === "02") {
3212
+ return cleanValue.length === 10 && /^02[235-8]\d{7}$/.test(cleanValue);
3213
+ }
3214
+ if (["03", "04", "05", "06"].includes(areaCode2)) {
3215
+ return cleanValue.length === 9;
3216
+ }
3217
+ if (areaCode2 === "07") {
3218
+ return cleanValue.length === 9 && /^07[2-9]\d{6}$/.test(cleanValue);
3219
+ }
3220
+ if (areaCode2 === "08") {
3221
+ return cleanValue.length === 9 && /^08[478]\d{6}$/.test(cleanValue);
3222
+ }
3223
+ return false;
3224
+ };
3225
+ function fax(options) {
3226
+ const { required = true, whitelist, transform, defaultValue, i18n } = options ?? {};
3227
+ const actualDefaultValue = defaultValue ?? (required ? "" : null);
3228
+ const getMessage = (key, params) => {
3229
+ if (i18n) {
3230
+ const currentLocale2 = getLocale();
3231
+ const customMessages = i18n[currentLocale2];
3232
+ if (customMessages && customMessages[key]) {
3233
+ const template = customMessages[key];
3234
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
3235
+ }
3236
+ }
3237
+ return t(`taiwan.fax.${key}`, params);
3238
+ };
3239
+ const preprocessFn = (val) => {
3240
+ if (val === null || val === void 0) {
3241
+ return actualDefaultValue;
3242
+ }
3243
+ let processed = String(val).trim();
3244
+ if (processed === "") {
3245
+ if (whitelist && whitelist.includes("")) {
3246
+ return "";
3247
+ }
3248
+ if (!required) {
3249
+ return actualDefaultValue;
3250
+ }
3251
+ return actualDefaultValue;
3252
+ }
3253
+ if (transform) {
3254
+ processed = transform(processed);
3255
+ }
3256
+ return processed;
3257
+ };
3258
+ const baseSchema = required ? import_zod17.z.preprocess(preprocessFn, import_zod17.z.string()) : import_zod17.z.preprocess(preprocessFn, import_zod17.z.string().nullable());
3259
+ const schema = baseSchema.refine((val) => {
3260
+ if (val === null) return true;
3261
+ if (required && (val === "" || val === "null" || val === "undefined")) {
3262
+ throw new import_zod17.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
3263
+ }
3264
+ if (val === null) return true;
3265
+ if (!required && val === "") return true;
3266
+ if (whitelist && whitelist.length > 0) {
3267
+ if (whitelist.includes(val)) {
3268
+ return true;
3269
+ }
3270
+ throw new import_zod17.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
3271
+ }
3272
+ if (!validateTaiwanFax(val)) {
3273
+ throw new import_zod17.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
3274
+ }
3275
+ return true;
329
3276
  });
330
3277
  return schema;
331
3278
  }
332
3279
  // Annotate the CommonJS export names for ESM import in node:
333
3280
  0 && (module.exports = {
3281
+ DATETIME_PATTERNS,
3282
+ ID_PATTERNS,
3283
+ TIME_PATTERNS,
3284
+ VALID_3_DIGIT_PREFIXES,
334
3285
  boolean,
3286
+ businessId,
3287
+ date,
3288
+ datetime,
3289
+ detectIdType,
335
3290
  email,
3291
+ fax,
3292
+ file,
336
3293
  getLocale,
337
- integer,
3294
+ id,
3295
+ mobile,
3296
+ nationalId,
3297
+ normalizeDateTimeValue,
3298
+ normalizeTime,
338
3299
  number,
3300
+ parseDateTimeValue,
3301
+ parseTimeToMinutes,
339
3302
  password,
3303
+ postalCode,
340
3304
  setLocale,
3305
+ tel,
341
3306
  text,
342
- url
3307
+ time,
3308
+ url,
3309
+ validate3DigitPostalCode,
3310
+ validate5DigitPostalCode,
3311
+ validate6DigitPostalCode,
3312
+ validateCitizenId,
3313
+ validateDateTimeFormat,
3314
+ validateIdType,
3315
+ validateNewResidentId,
3316
+ validateOldResidentId,
3317
+ validateTaiwanBusinessId,
3318
+ validateTaiwanFax,
3319
+ validateTaiwanMobile,
3320
+ validateTaiwanNationalId,
3321
+ validateTaiwanPostalCode,
3322
+ validateTaiwanTel,
3323
+ validateTimeFormat
343
3324
  });