@hy_ong/zod-kit 0.0.5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/.claude/settings.local.json +9 -1
  2. package/README.md +465 -97
  3. package/dist/index.cjs +1690 -179
  4. package/dist/index.d.cts +2791 -28
  5. package/dist/index.d.ts +2791 -28
  6. package/dist/index.js +1672 -178
  7. package/package.json +2 -1
  8. package/src/i18n/locales/en.json +62 -0
  9. package/src/i18n/locales/zh-TW.json +62 -0
  10. package/src/index.ts +4 -0
  11. package/src/validators/common/boolean.ts +101 -4
  12. package/src/validators/common/date.ts +141 -6
  13. package/src/validators/common/datetime.ts +680 -0
  14. package/src/validators/common/email.ts +120 -4
  15. package/src/validators/common/file.ts +391 -0
  16. package/src/validators/common/id.ts +230 -18
  17. package/src/validators/common/number.ts +132 -4
  18. package/src/validators/common/password.ts +187 -8
  19. package/src/validators/common/text.ts +130 -6
  20. package/src/validators/common/time.ts +607 -0
  21. package/src/validators/common/url.ts +153 -6
  22. package/src/validators/taiwan/business-id.ts +138 -9
  23. package/src/validators/taiwan/fax.ts +164 -10
  24. package/src/validators/taiwan/mobile.ts +151 -10
  25. package/src/validators/taiwan/national-id.ts +233 -17
  26. package/src/validators/taiwan/postal-code.ts +1048 -0
  27. package/src/validators/taiwan/tel.ts +167 -10
  28. package/tests/common/boolean.test.ts +38 -38
  29. package/tests/common/date.test.ts +65 -65
  30. package/tests/common/datetime.test.ts +675 -0
  31. package/tests/common/email.test.ts +24 -28
  32. package/tests/common/file.test.ts +475 -0
  33. package/tests/common/id.test.ts +80 -113
  34. package/tests/common/number.test.ts +24 -25
  35. package/tests/common/password.test.ts +28 -35
  36. package/tests/common/text.test.ts +36 -37
  37. package/tests/common/time.test.ts +510 -0
  38. package/tests/common/url.test.ts +67 -67
  39. package/tests/taiwan/business-id.test.ts +22 -22
  40. package/tests/taiwan/fax.test.ts +33 -42
  41. package/tests/taiwan/mobile.test.ts +32 -41
  42. package/tests/taiwan/national-id.test.ts +31 -31
  43. package/tests/taiwan/postal-code.test.ts +751 -0
  44. package/tests/taiwan/tel.test.ts +33 -42
  45. package/debug.js +0 -21
  46. package/debug.ts +0 -16
package/dist/index.cjs CHANGED
@@ -30,24 +30,39 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ DATETIME_PATTERNS: () => DATETIME_PATTERNS,
33
34
  ID_PATTERNS: () => ID_PATTERNS,
35
+ TIME_PATTERNS: () => TIME_PATTERNS,
36
+ VALID_3_DIGIT_PREFIXES: () => VALID_3_DIGIT_PREFIXES,
34
37
  boolean: () => boolean,
35
38
  businessId: () => businessId,
36
39
  date: () => date,
40
+ datetime: () => datetime,
37
41
  detectIdType: () => detectIdType,
38
42
  email: () => email,
39
43
  fax: () => fax,
44
+ file: () => file,
40
45
  getLocale: () => getLocale,
41
46
  id: () => id,
42
47
  mobile: () => mobile,
43
48
  nationalId: () => nationalId,
49
+ normalizeDateTimeValue: () => normalizeDateTimeValue,
50
+ normalizeTime: () => normalizeTime,
44
51
  number: () => number,
52
+ parseDateTimeValue: () => parseDateTimeValue,
53
+ parseTimeToMinutes: () => parseTimeToMinutes,
45
54
  password: () => password,
55
+ postalCode: () => postalCode,
46
56
  setLocale: () => setLocale,
47
57
  tel: () => tel,
48
58
  text: () => text,
59
+ time: () => time,
49
60
  url: () => url,
61
+ validate3DigitPostalCode: () => validate3DigitPostalCode,
62
+ validate5DigitPostalCode: () => validate5DigitPostalCode,
63
+ validate6DigitPostalCode: () => validate6DigitPostalCode,
50
64
  validateCitizenId: () => validateCitizenId,
65
+ validateDateTimeFormat: () => validateDateTimeFormat,
51
66
  validateIdType: () => validateIdType,
52
67
  validateNewResidentId: () => validateNewResidentId,
53
68
  validateOldResidentId: () => validateOldResidentId,
@@ -55,7 +70,9 @@ __export(index_exports, {
55
70
  validateTaiwanFax: () => validateTaiwanFax,
56
71
  validateTaiwanMobile: () => validateTaiwanMobile,
57
72
  validateTaiwanNationalId: () => validateTaiwanNationalId,
58
- validateTaiwanTel: () => validateTaiwanTel
73
+ validateTaiwanPostalCode: () => validateTaiwanPostalCode,
74
+ validateTaiwanTel: () => validateTaiwanTel,
75
+ validateTimeFormat: () => validateTimeFormat
59
76
  });
60
77
  module.exports = __toCommonJS(index_exports);
61
78
 
@@ -177,6 +194,56 @@ var zh_TW_default = {
177
194
  notToday: "\u4E0D\u5F97\u70BA\u4ECA\u5929",
178
195
  weekday: "\u5FC5\u9808\u70BA\u5DE5\u4F5C\u65E5\uFF08\u9031\u4E00\u81F3\u9031\u4E94\uFF09",
179
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"
180
247
  }
181
248
  },
182
249
  taiwan: {
@@ -202,6 +269,18 @@ var zh_TW_default = {
202
269
  required: "\u5FC5\u586B",
203
270
  invalid: "\u7121\u6548\u7684\u50B3\u771F\u865F\u78BC\u683C\u5F0F",
204
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"
205
284
  }
206
285
  }
207
286
  };
@@ -321,6 +400,56 @@ var en_default = {
321
400
  notToday: "Date must not be today",
322
401
  weekday: "Date must be a weekday (Monday-Friday)",
323
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",
413
+ includes: "Must include ${includes}",
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"
324
453
  }
325
454
  },
326
455
  taiwan: {
@@ -346,6 +475,18 @@ var en_default = {
346
475
  required: "Required",
347
476
  invalid: "Invalid Taiwan fax format",
348
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"
349
490
  }
350
491
  }
351
492
  };
@@ -374,9 +515,8 @@ function getNestedValue(obj, path) {
374
515
  }
375
516
 
376
517
  // src/validators/common/boolean.ts
377
- function boolean(options) {
518
+ function boolean(required, options) {
378
519
  const {
379
- required = true,
380
520
  defaultValue = null,
381
521
  shouldBe,
382
522
  truthyValues = [true, "true", 1, "1", "yes", "on"],
@@ -385,6 +525,7 @@ function boolean(options) {
385
525
  transform,
386
526
  i18n
387
527
  } = options ?? {};
528
+ const isRequired = required ?? false;
388
529
  const getMessage = (key, params) => {
389
530
  if (i18n) {
390
531
  const currentLocale2 = getLocale();
@@ -416,7 +557,7 @@ function boolean(options) {
416
557
  },
417
558
  import_zod.z.union([import_zod.z.literal(true), import_zod.z.literal(false), import_zod.z.literal(null)])
418
559
  );
419
- if (required && defaultValue === null) {
560
+ if (isRequired && defaultValue === null) {
420
561
  result = result.refine((val) => val !== null, { message: getMessage("required") });
421
562
  }
422
563
  if (shouldBe === true) {
@@ -448,9 +589,8 @@ import_dayjs.default.extend(import_isSameOrBefore.default);
448
589
  import_dayjs.default.extend(import_customParseFormat.default);
449
590
  import_dayjs.default.extend(import_isToday.default);
450
591
  import_dayjs.default.extend(import_weekday.default);
451
- function date(options) {
592
+ function date(required, options) {
452
593
  const {
453
- required = true,
454
594
  min,
455
595
  max,
456
596
  format = "YYYY-MM-DD",
@@ -466,7 +606,8 @@ function date(options) {
466
606
  defaultValue = null,
467
607
  i18n
468
608
  } = options ?? {};
469
- const actualDefaultValue = defaultValue ?? (required ? "" : null);
609
+ const isRequired = required ?? false;
610
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
470
611
  const getMessage = (key, params) => {
471
612
  if (i18n) {
472
613
  const currentLocale2 = getLocale();
@@ -488,10 +629,10 @@ function date(options) {
488
629
  }
489
630
  return processed;
490
631
  };
491
- const baseSchema = required ? import_zod2.z.preprocess(preprocessFn, import_zod2.z.string()) : import_zod2.z.preprocess(preprocessFn, import_zod2.z.string().nullable());
632
+ const baseSchema = isRequired ? import_zod2.z.preprocess(preprocessFn, import_zod2.z.string()) : import_zod2.z.preprocess(preprocessFn, import_zod2.z.string().nullable());
492
633
  const schema = baseSchema.refine((val) => {
493
634
  if (val === null) return true;
494
- if (required && (val === "" || val === "null" || val === "undefined")) {
635
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
495
636
  throw new import_zod2.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
496
637
  }
497
638
  if (val !== null && !(0, import_dayjs.default)(val, format, true).isValid()) {
@@ -540,11 +681,280 @@ function date(options) {
540
681
  return schema;
541
682
  }
542
683
 
543
- // src/validators/common/email.ts
684
+ // src/validators/common/datetime.ts
544
685
  var import_zod3 = require("zod");
545
- function email(options) {
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(required, options) {
770
+ const {
771
+ format = "YYYY-MM-DD HH:mm",
772
+ min,
773
+ max,
774
+ minHour,
775
+ maxHour,
776
+ allowedHours,
777
+ minuteStep,
778
+ timezone: timezone2,
779
+ includes,
780
+ excludes,
781
+ regex,
782
+ trimMode = "trim",
783
+ casing = "none",
784
+ mustBePast,
785
+ mustBeFuture,
786
+ mustBeToday,
787
+ mustNotBeToday,
788
+ weekdaysOnly,
789
+ weekendsOnly,
790
+ whitelist,
791
+ whitelistOnly = false,
792
+ transform,
793
+ defaultValue,
794
+ i18n
795
+ } = options ?? {};
796
+ const isRequired = required ?? false;
797
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : 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 (!isRequired) {
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 = isRequired ? 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 (isRequired && (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 (!isRequired && 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
+ });
951
+ return schema;
952
+ }
953
+
954
+ // src/validators/common/email.ts
955
+ var import_zod4 = require("zod");
956
+ function email(required, options) {
546
957
  const {
547
- required = true,
548
958
  domain,
549
959
  domainBlacklist,
550
960
  minLength,
@@ -559,6 +969,7 @@ function email(options) {
559
969
  defaultValue,
560
970
  i18n
561
971
  } = options ?? {};
972
+ const isRequired = required ?? false;
562
973
  const getMessage = (key, params) => {
563
974
  if (i18n) {
564
975
  const currentLocale2 = getLocale();
@@ -573,7 +984,7 @@ function email(options) {
573
984
  const disposableDomains = ["10minutemail.com", "tempmail.org", "guerrillamail.com", "mailinator.com", "yopmail.com", "temp-mail.org", "throwaway.email", "getnada.com", "maildrop.cc"];
574
985
  const freeEmailDomains = ["gmail.com", "yahoo.com", "hotmail.com", "outlook.com", "icloud.com", "aol.com", "protonmail.com", "zoho.com"];
575
986
  const actualDefaultValue = defaultValue ?? null;
576
- const baseSchema = import_zod3.z.preprocess(
987
+ const baseSchema = import_zod4.z.preprocess(
577
988
  (val) => {
578
989
  if (val === "" || val === null || val === void 0) {
579
990
  return actualDefaultValue;
@@ -587,36 +998,36 @@ function email(options) {
587
998
  }
588
999
  return processed;
589
1000
  },
590
- import_zod3.z.union([import_zod3.z.string().email(), import_zod3.z.null()])
1001
+ import_zod4.z.union([import_zod4.z.string().email(), import_zod4.z.null()])
591
1002
  );
592
1003
  const schema = baseSchema.refine((val) => {
593
- if (required && val === null) {
594
- throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1004
+ if (isRequired && val === null) {
1005
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
595
1006
  }
596
1007
  if (val === null) return true;
597
1008
  if (typeof val !== "string") {
598
- throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1009
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
599
1010
  }
600
1011
  if (minLength !== void 0 && val.length < minLength) {
601
- throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("minLength", { minLength }), path: [] }]);
1012
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("minLength", { minLength }), path: [] }]);
602
1013
  }
603
1014
  if (maxLength !== void 0 && val.length > maxLength) {
604
- throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("maxLength", { maxLength }), path: [] }]);
1015
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("maxLength", { maxLength }), path: [] }]);
605
1016
  }
606
1017
  if (includes !== void 0 && !val.includes(includes)) {
607
- throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1018
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
608
1019
  }
609
1020
  if (excludes !== void 0) {
610
1021
  const excludeList = Array.isArray(excludes) ? excludes : [excludes];
611
1022
  for (const exclude of excludeList) {
612
1023
  if (val.includes(exclude)) {
613
- throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("includes", { includes: exclude }), path: [] }]);
1024
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("includes", { includes: exclude }), path: [] }]);
614
1025
  }
615
1026
  }
616
1027
  }
617
1028
  const emailDomain = val.split("@")[1]?.toLowerCase();
618
1029
  if (!emailDomain) {
619
- throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1030
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
620
1031
  }
621
1032
  if (businessOnly) {
622
1033
  const isFreeProvider = freeEmailDomains.some((freeDomain) => {
@@ -626,7 +1037,7 @@ function email(options) {
626
1037
  return emailDomain === freeDomain;
627
1038
  });
628
1039
  if (isFreeProvider) {
629
- throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("businessOnly"), path: [] }]);
1040
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("businessOnly"), path: [] }]);
630
1041
  }
631
1042
  }
632
1043
  if (domainBlacklist && domainBlacklist.length > 0) {
@@ -638,7 +1049,7 @@ function email(options) {
638
1049
  return emailDomain === lowerDomain;
639
1050
  });
640
1051
  if (isBlacklisted) {
641
- throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("domainBlacklist", { domain: emailDomain }), path: [] }]);
1052
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("domainBlacklist", { domain: emailDomain }), path: [] }]);
642
1053
  }
643
1054
  }
644
1055
  if (domain !== void 0) {
@@ -651,7 +1062,7 @@ function email(options) {
651
1062
  return emailDomain === lowerDomain;
652
1063
  });
653
1064
  if (!isAllowed) {
654
- throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("domain", { domain: Array.isArray(domain) ? domain.join(", ") : domain }), path: [] }]);
1065
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("domain", { domain: Array.isArray(domain) ? domain.join(", ") : domain }), path: [] }]);
655
1066
  }
656
1067
  }
657
1068
  if (noDisposable) {
@@ -662,7 +1073,7 @@ function email(options) {
662
1073
  return emailDomain === disposableDomain;
663
1074
  });
664
1075
  if (isDisposable) {
665
- throw new import_zod3.z.ZodError([{ code: "custom", message: getMessage("noDisposable"), path: [] }]);
1076
+ throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("noDisposable"), path: [] }]);
666
1077
  }
667
1078
  }
668
1079
  return true;
@@ -670,8 +1081,179 @@ function email(options) {
670
1081
  return schema;
671
1082
  }
672
1083
 
1084
+ // src/validators/common/file.ts
1085
+ var import_zod5 = require("zod");
1086
+ function file(required, options) {
1087
+ const {
1088
+ maxSize,
1089
+ minSize,
1090
+ type,
1091
+ typeBlacklist,
1092
+ extension,
1093
+ extensionBlacklist,
1094
+ namePattern,
1095
+ nameBlacklist,
1096
+ imageOnly = false,
1097
+ documentOnly = false,
1098
+ videoOnly = false,
1099
+ audioOnly = false,
1100
+ archiveOnly = false,
1101
+ caseSensitive = false,
1102
+ transform,
1103
+ defaultValue,
1104
+ i18n
1105
+ } = options ?? {};
1106
+ const isRequired = required ?? false;
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(
1217
+ (val) => {
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;
1224
+ }
1225
+ }
1226
+ return true;
1227
+ },
1228
+ {
1229
+ message: getMessage("nameBlacklist", { pattern: "" })
1230
+ }
1231
+ );
1232
+ return schema;
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
+ }
1254
+
673
1255
  // src/validators/common/id.ts
674
- var import_zod4 = require("zod");
1256
+ var import_zod6 = require("zod");
675
1257
  var ID_PATTERNS = {
676
1258
  numeric: /^\d+$/,
677
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,
@@ -708,9 +1290,8 @@ var validateIdType = (value, type) => {
708
1290
  const pattern = ID_PATTERNS[type];
709
1291
  return pattern ? pattern.test(value) : false;
710
1292
  };
711
- function id(options) {
1293
+ function id(required, options) {
712
1294
  const {
713
- required = true,
714
1295
  type = "auto",
715
1296
  minLength,
716
1297
  maxLength,
@@ -725,7 +1306,8 @@ function id(options) {
725
1306
  defaultValue,
726
1307
  i18n
727
1308
  } = options ?? {};
728
- const actualDefaultValue = defaultValue ?? (required ? "" : null);
1309
+ const isRequired = required ?? false;
1310
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
729
1311
  const getMessage = (key, params) => {
730
1312
  if (i18n) {
731
1313
  const currentLocale2 = getLocale();
@@ -747,23 +1329,23 @@ function id(options) {
747
1329
  }
748
1330
  return processed;
749
1331
  };
750
- const baseSchema = required ? import_zod4.z.preprocess(preprocessFn, import_zod4.z.string()) : import_zod4.z.preprocess(preprocessFn, import_zod4.z.string().nullable());
1332
+ const baseSchema = isRequired ? import_zod6.z.preprocess(preprocessFn, import_zod6.z.string()) : import_zod6.z.preprocess(preprocessFn, import_zod6.z.string().nullable());
751
1333
  const schema = baseSchema.refine((val) => {
752
1334
  if (val === null) return true;
753
- if (required && (val === "" || val === "null" || val === "undefined")) {
754
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1335
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
1336
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
755
1337
  }
756
1338
  const comparisonVal = !caseSensitive ? val.toLowerCase() : val;
757
1339
  if (val !== null && minLength !== void 0 && val.length < minLength) {
758
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("minLength", { minLength }), path: [] }]);
1340
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("minLength", { minLength }), path: [] }]);
759
1341
  }
760
1342
  if (val !== null && maxLength !== void 0 && val.length > maxLength) {
761
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("maxLength", { maxLength }), path: [] }]);
1343
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("maxLength", { maxLength }), path: [] }]);
762
1344
  }
763
1345
  const hasContentValidations = customRegex !== void 0 || startsWith !== void 0 || endsWith !== void 0 || includes !== void 0 || excludes !== void 0;
764
1346
  if (val !== null && customRegex !== void 0) {
765
1347
  if (!customRegex.test(val)) {
766
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("customFormat"), path: [] }]);
1348
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("customFormat"), path: [] }]);
767
1349
  }
768
1350
  } else if (val !== null && !hasContentValidations) {
769
1351
  let isValidId;
@@ -771,17 +1353,17 @@ function id(options) {
771
1353
  isValidId = allowedTypes.some((allowedType) => validateIdType(val, allowedType));
772
1354
  if (!isValidId) {
773
1355
  const typeNames = allowedTypes.join(", ");
774
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("invalid") + ` (allowed types: ${typeNames})`, path: [] }]);
1356
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("invalid") + ` (allowed types: ${typeNames})`, path: [] }]);
775
1357
  }
776
1358
  } else if (type !== "auto") {
777
1359
  isValidId = validateIdType(val, type);
778
1360
  if (!isValidId) {
779
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage(type) || getMessage("invalid"), path: [] }]);
1361
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage(type) || getMessage("invalid"), path: [] }]);
780
1362
  }
781
1363
  } else {
782
1364
  isValidId = detectIdType(val) !== null;
783
1365
  if (!isValidId) {
784
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1366
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
785
1367
  }
786
1368
  }
787
1369
  } else if (val !== null && hasContentValidations && type !== "auto" && !customRegex) {
@@ -789,11 +1371,11 @@ function id(options) {
789
1371
  const isValidType = allowedTypes.some((allowedType) => validateIdType(val, allowedType));
790
1372
  if (!isValidType) {
791
1373
  const typeNames = allowedTypes.join(", ");
792
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("invalid") + ` (allowed types: ${typeNames})`, path: [] }]);
1374
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("invalid") + ` (allowed types: ${typeNames})`, path: [] }]);
793
1375
  }
794
1376
  } else {
795
1377
  if (!validateIdType(val, type)) {
796
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage(type) || getMessage("invalid"), path: [] }]);
1378
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage(type) || getMessage("invalid"), path: [] }]);
797
1379
  }
798
1380
  }
799
1381
  }
@@ -801,20 +1383,20 @@ function id(options) {
801
1383
  const searchEndsWith = !caseSensitive && endsWith ? endsWith.toLowerCase() : endsWith;
802
1384
  const searchIncludes = !caseSensitive && includes ? includes.toLowerCase() : includes;
803
1385
  if (val !== null && startsWith !== void 0 && !comparisonVal.startsWith(searchStartsWith)) {
804
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("startsWith", { startsWith }), path: [] }]);
1386
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("startsWith", { startsWith }), path: [] }]);
805
1387
  }
806
1388
  if (val !== null && endsWith !== void 0 && !comparisonVal.endsWith(searchEndsWith)) {
807
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("endsWith", { endsWith }), path: [] }]);
1389
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("endsWith", { endsWith }), path: [] }]);
808
1390
  }
809
1391
  if (val !== null && includes !== void 0 && !comparisonVal.includes(searchIncludes)) {
810
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1392
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
811
1393
  }
812
1394
  if (val !== null && excludes !== void 0) {
813
1395
  const excludeList = Array.isArray(excludes) ? excludes : [excludes];
814
1396
  for (const exclude of excludeList) {
815
1397
  const searchExclude = !caseSensitive ? exclude.toLowerCase() : exclude;
816
1398
  if (comparisonVal.includes(searchExclude)) {
817
- throw new import_zod4.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
1399
+ throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
818
1400
  }
819
1401
  }
820
1402
  }
@@ -831,10 +1413,9 @@ function id(options) {
831
1413
  }
832
1414
 
833
1415
  // src/validators/common/number.ts
834
- var import_zod5 = require("zod");
835
- function number(options) {
1416
+ var import_zod7 = require("zod");
1417
+ function number(required, options) {
836
1418
  const {
837
- required = true,
838
1419
  min,
839
1420
  max,
840
1421
  defaultValue,
@@ -850,6 +1431,7 @@ function number(options) {
850
1431
  parseCommas = false,
851
1432
  i18n
852
1433
  } = options ?? {};
1434
+ const isRequired = required ?? false;
853
1435
  const getMessage = (key, params) => {
854
1436
  if (i18n) {
855
1437
  const currentLocale2 = getLocale();
@@ -862,7 +1444,7 @@ function number(options) {
862
1444
  return t(`common.number.${key}`, params);
863
1445
  };
864
1446
  const actualDefaultValue = defaultValue ?? null;
865
- const schema = import_zod5.z.preprocess(
1447
+ const schema = import_zod7.z.preprocess(
866
1448
  (val) => {
867
1449
  if (val === "" || val === void 0 || val === null) {
868
1450
  return actualDefaultValue;
@@ -889,58 +1471,58 @@ function number(options) {
889
1471
  }
890
1472
  return val;
891
1473
  },
892
- import_zod5.z.union([import_zod5.z.number(), import_zod5.z.null(), import_zod5.z.nan(), import_zod5.z.custom((val) => val === Infinity || val === -Infinity)])
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)])
893
1475
  ).refine((val) => {
894
- if (required && val === null) {
895
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1476
+ if (isRequired && val === null) {
1477
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
896
1478
  }
897
1479
  if (val === null) return true;
898
1480
  if (typeof val === "number" && isNaN(val)) {
899
1481
  if (type === "integer") {
900
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("integer"), path: [] }]);
1482
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("integer"), path: [] }]);
901
1483
  } else if (type === "float") {
902
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("float"), path: [] }]);
1484
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("float"), path: [] }]);
903
1485
  } else {
904
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1486
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
905
1487
  }
906
1488
  }
907
1489
  if (typeof val !== "number") {
908
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1490
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
909
1491
  }
910
1492
  if (finite && !Number.isFinite(val)) {
911
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("finite"), path: [] }]);
1493
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("finite"), path: [] }]);
912
1494
  }
913
1495
  if (type === "integer" && !Number.isInteger(val)) {
914
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("integer"), path: [] }]);
1496
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("integer"), path: [] }]);
915
1497
  }
916
1498
  if (type === "float" && Number.isInteger(val)) {
917
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("float"), path: [] }]);
1499
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("float"), path: [] }]);
918
1500
  }
919
1501
  if (positive && val <= 0) {
920
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("positive"), path: [] }]);
1502
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("positive"), path: [] }]);
921
1503
  }
922
1504
  if (negative && val >= 0) {
923
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("negative"), path: [] }]);
1505
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("negative"), path: [] }]);
924
1506
  }
925
1507
  if (nonNegative && val < 0) {
926
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("nonNegative"), path: [] }]);
1508
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("nonNegative"), path: [] }]);
927
1509
  }
928
1510
  if (nonPositive && val > 0) {
929
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("nonPositive"), path: [] }]);
1511
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("nonPositive"), path: [] }]);
930
1512
  }
931
1513
  if (min !== void 0 && val < min) {
932
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
1514
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
933
1515
  }
934
1516
  if (max !== void 0 && val > max) {
935
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
1517
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
936
1518
  }
937
1519
  if (multipleOf !== void 0 && val % multipleOf !== 0) {
938
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("multipleOf", { multipleOf }), path: [] }]);
1520
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("multipleOf", { multipleOf }), path: [] }]);
939
1521
  }
940
1522
  if (precision !== void 0) {
941
1523
  const decimalPlaces = (val.toString().split(".")[1] || "").length;
942
1524
  if (decimalPlaces > precision) {
943
- throw new import_zod5.z.ZodError([{ code: "custom", message: getMessage("precision", { precision }), path: [] }]);
1525
+ throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("precision", { precision }), path: [] }]);
944
1526
  }
945
1527
  }
946
1528
  return true;
@@ -949,7 +1531,7 @@ function number(options) {
949
1531
  }
950
1532
 
951
1533
  // src/validators/common/password.ts
952
- var import_zod6 = require("zod");
1534
+ var import_zod8 = require("zod");
953
1535
  var COMMON_PASSWORDS = [
954
1536
  "password",
955
1537
  "123456",
@@ -984,9 +1566,8 @@ var calculatePasswordStrength = (password2) => {
984
1566
  if (score <= 6) return "strong";
985
1567
  return "very-strong";
986
1568
  };
987
- function password(options) {
1569
+ function password(required, options) {
988
1570
  const {
989
- required = true,
990
1571
  min,
991
1572
  max,
992
1573
  uppercase,
@@ -1004,7 +1585,8 @@ function password(options) {
1004
1585
  defaultValue,
1005
1586
  i18n
1006
1587
  } = options ?? {};
1007
- const actualDefaultValue = defaultValue ?? (required ? "" : null);
1588
+ const isRequired = required ?? false;
1589
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
1008
1590
  const getMessage = (key, params) => {
1009
1591
  if (i18n) {
1010
1592
  const currentLocale2 = getLocale();
@@ -1026,38 +1608,38 @@ function password(options) {
1026
1608
  }
1027
1609
  return processed;
1028
1610
  };
1029
- const baseSchema = required ? import_zod6.z.preprocess(preprocessFn, import_zod6.z.string()) : import_zod6.z.preprocess(preprocessFn, import_zod6.z.string().nullable());
1611
+ const baseSchema = isRequired ? import_zod8.z.preprocess(preprocessFn, import_zod8.z.string()) : import_zod8.z.preprocess(preprocessFn, import_zod8.z.string().nullable());
1030
1612
  const schema = baseSchema.refine((val) => {
1031
1613
  if (val === null) return true;
1032
- if (required && (val === "" || val === "null" || val === "undefined")) {
1033
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1614
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
1615
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1034
1616
  }
1035
1617
  if (val !== null && min !== void 0 && val.length < min) {
1036
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
1618
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
1037
1619
  }
1038
1620
  if (val !== null && max !== void 0 && val.length > max) {
1039
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
1621
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
1040
1622
  }
1041
1623
  if (val !== null && uppercase && !/[A-Z]/.test(val)) {
1042
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("uppercase"), path: [] }]);
1624
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("uppercase"), path: [] }]);
1043
1625
  }
1044
1626
  if (val !== null && lowercase && !/[a-z]/.test(val)) {
1045
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("lowercase"), path: [] }]);
1627
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("lowercase"), path: [] }]);
1046
1628
  }
1047
1629
  if (val !== null && digits && !/[0-9]/.test(val)) {
1048
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("digits"), path: [] }]);
1630
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("digits"), path: [] }]);
1049
1631
  }
1050
1632
  if (val !== null && special && !/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(val)) {
1051
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("special"), path: [] }]);
1633
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("special"), path: [] }]);
1052
1634
  }
1053
1635
  if (val !== null && noRepeating && /(.)\1{2,}/.test(val)) {
1054
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("noRepeating"), path: [] }]);
1636
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("noRepeating"), path: [] }]);
1055
1637
  }
1056
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)) {
1057
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("noSequential"), path: [] }]);
1639
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("noSequential"), path: [] }]);
1058
1640
  }
1059
1641
  if (val !== null && noCommonWords && COMMON_PASSWORDS.some((common) => val.toLowerCase().includes(common.toLowerCase()))) {
1060
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("noCommonWords"), path: [] }]);
1642
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("noCommonWords"), path: [] }]);
1061
1643
  }
1062
1644
  if (val !== null && minStrength) {
1063
1645
  const strength = calculatePasswordStrength(val);
@@ -1065,22 +1647,22 @@ function password(options) {
1065
1647
  const currentLevel = strengthLevels.indexOf(strength);
1066
1648
  const requiredLevel = strengthLevels.indexOf(minStrength);
1067
1649
  if (currentLevel < requiredLevel) {
1068
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("minStrength", { minStrength }), path: [] }]);
1650
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("minStrength", { minStrength }), path: [] }]);
1069
1651
  }
1070
1652
  }
1071
1653
  if (val !== null && includes !== void 0 && !val.includes(includes)) {
1072
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1654
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1073
1655
  }
1074
1656
  if (val !== null && excludes !== void 0) {
1075
1657
  const excludeList = Array.isArray(excludes) ? excludes : [excludes];
1076
1658
  for (const exclude of excludeList) {
1077
1659
  if (val.includes(exclude)) {
1078
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
1660
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
1079
1661
  }
1080
1662
  }
1081
1663
  }
1082
1664
  if (val !== null && regex !== void 0 && !regex.test(val)) {
1083
- throw new import_zod6.z.ZodError([{ code: "custom", message: getMessage("invalid", { regex }), path: [] }]);
1665
+ throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("invalid", { regex }), path: [] }]);
1084
1666
  }
1085
1667
  return true;
1086
1668
  });
@@ -1088,10 +1670,11 @@ function password(options) {
1088
1670
  }
1089
1671
 
1090
1672
  // src/validators/common/text.ts
1091
- var import_zod7 = require("zod");
1092
- function text(options) {
1093
- const { required = true, minLength, maxLength, startsWith, endsWith, includes, excludes, regex, trimMode = "trim", casing = "none", transform, notEmpty, defaultValue, i18n } = options ?? {};
1094
- const actualDefaultValue = defaultValue ?? (required ? "" : null);
1673
+ var import_zod9 = require("zod");
1674
+ function text(required, options) {
1675
+ const { minLength, maxLength, startsWith, endsWith, includes, excludes, regex, trimMode = "trim", casing = "none", transform, notEmpty, defaultValue, i18n } = options ?? {};
1676
+ const isRequired = required ?? false;
1677
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
1095
1678
  const getMessage = (key, params) => {
1096
1679
  if (i18n) {
1097
1680
  const currentLocale2 = getLocale();
@@ -1139,40 +1722,272 @@ function text(options) {
1139
1722
  }
1140
1723
  return processed;
1141
1724
  };
1142
- const baseSchema = required ? import_zod7.z.preprocess(preprocessFn, import_zod7.z.string()) : import_zod7.z.preprocess(preprocessFn, import_zod7.z.string().nullable());
1725
+ const baseSchema = isRequired ? import_zod9.z.preprocess(preprocessFn, import_zod9.z.string()) : import_zod9.z.preprocess(preprocessFn, import_zod9.z.string().nullable());
1143
1726
  const schema = baseSchema.refine((val) => {
1144
1727
  if (val === null) return true;
1145
- if (required && (val === "" || val === "null" || val === "undefined")) {
1146
- throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1728
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
1729
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1147
1730
  }
1148
1731
  if (notEmpty && val !== null && val.trim() === "") {
1149
- throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("notEmpty"), path: [] }]);
1732
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("notEmpty"), path: [] }]);
1150
1733
  }
1151
1734
  if (val !== null && minLength !== void 0 && val.length < minLength) {
1152
- throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("minLength", { minLength }), path: [] }]);
1735
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("minLength", { minLength }), path: [] }]);
1153
1736
  }
1154
1737
  if (val !== null && maxLength !== void 0 && val.length > maxLength) {
1155
- throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("maxLength", { maxLength }), path: [] }]);
1738
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("maxLength", { maxLength }), path: [] }]);
1156
1739
  }
1157
1740
  if (val !== null && startsWith !== void 0 && !val.startsWith(startsWith)) {
1158
- throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("startsWith", { startsWith }), path: [] }]);
1741
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("startsWith", { startsWith }), path: [] }]);
1159
1742
  }
1160
1743
  if (val !== null && endsWith !== void 0 && !val.endsWith(endsWith)) {
1161
- throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("endsWith", { endsWith }), path: [] }]);
1744
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("endsWith", { endsWith }), path: [] }]);
1162
1745
  }
1163
1746
  if (val !== null && includes !== void 0 && !val.includes(includes)) {
1164
- throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1747
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1165
1748
  }
1166
1749
  if (val !== null && excludes !== void 0) {
1167
1750
  const excludeList = Array.isArray(excludes) ? excludes : [excludes];
1168
1751
  for (const exclude of excludeList) {
1169
1752
  if (val.includes(exclude)) {
1170
- throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
1753
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
1171
1754
  }
1172
1755
  }
1173
1756
  }
1174
1757
  if (val !== null && regex !== void 0 && !regex.test(val)) {
1175
- throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("invalid", { regex }), path: [] }]);
1758
+ throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("invalid", { regex }), path: [] }]);
1759
+ }
1760
+ return true;
1761
+ });
1762
+ return schema;
1763
+ }
1764
+
1765
+ // src/validators/common/time.ts
1766
+ var import_zod10 = require("zod");
1767
+ var TIME_PATTERNS = {
1768
+ "HH:mm": /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/,
1769
+ "HH:mm:ss": /^([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/,
1770
+ "hh:mm A": /^(0?[1-9]|1[0-2]):[0-5][0-9]\s?(AM|PM)$/i,
1771
+ "hh:mm:ss A": /^(0?[1-9]|1[0-2]):[0-5][0-9]:[0-5][0-9]\s?(AM|PM)$/i,
1772
+ "H:mm": /^([0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/,
1773
+ "h:mm A": /^([1-9]|1[0-2]):[0-5][0-9]\s?(AM|PM)$/i
1774
+ };
1775
+ var parseTimeToMinutes = (timeStr, format) => {
1776
+ const cleanTime = timeStr.trim();
1777
+ try {
1778
+ if (format.includes("A")) {
1779
+ const match = cleanTime.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?\s?(AM|PM)$/i);
1780
+ if (!match) return null;
1781
+ const [, hourStr, minuteStr, , period] = match;
1782
+ let hour = parseInt(hourStr, 10);
1783
+ const minute = parseInt(minuteStr, 10);
1784
+ if (hour < 1 || hour > 12 || minute < 0 || minute > 59) {
1785
+ return null;
1786
+ }
1787
+ if (period.toUpperCase() === "PM" && hour !== 12) {
1788
+ hour += 12;
1789
+ } else if (period.toUpperCase() === "AM" && hour === 12) {
1790
+ hour = 0;
1791
+ }
1792
+ return hour * 60 + minute;
1793
+ } else {
1794
+ const match = cleanTime.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/);
1795
+ if (!match) return null;
1796
+ const [, hourStr, minuteStr] = match;
1797
+ const hour = parseInt(hourStr, 10);
1798
+ const minute = parseInt(minuteStr, 10);
1799
+ if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
1800
+ return null;
1801
+ }
1802
+ return hour * 60 + minute;
1803
+ }
1804
+ } catch {
1805
+ return null;
1806
+ }
1807
+ };
1808
+ var validateTimeFormat = (value, format) => {
1809
+ const pattern = TIME_PATTERNS[format];
1810
+ return pattern.test(value.trim());
1811
+ };
1812
+ var normalizeTime = (timeStr, format) => {
1813
+ const cleanTime = timeStr.trim();
1814
+ if (format.includes("A")) {
1815
+ const match = cleanTime.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?\s?(AM|PM)$/i);
1816
+ if (!match) return null;
1817
+ const [, hourStr, minuteStr, secondStr = "00", period] = match;
1818
+ let hour = parseInt(hourStr, 10);
1819
+ const minute = parseInt(minuteStr, 10);
1820
+ const second = parseInt(secondStr, 10);
1821
+ if (period.toUpperCase() === "PM" && hour !== 12) {
1822
+ hour += 12;
1823
+ } else if (period.toUpperCase() === "AM" && hour === 12) {
1824
+ hour = 0;
1825
+ }
1826
+ 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")}`;
1827
+ }
1828
+ if (format === "H:mm") {
1829
+ const match = cleanTime.match(/^(\d{1,2}):(\d{2})$/);
1830
+ if (!match) return null;
1831
+ const [, hourStr, minuteStr] = match;
1832
+ return `${hourStr.padStart(2, "0")}:${minuteStr}`;
1833
+ }
1834
+ return cleanTime;
1835
+ };
1836
+ function time(required, options) {
1837
+ const {
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 isRequired = required ?? false;
1858
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
1859
+ const getMessage = (key, params) => {
1860
+ if (i18n) {
1861
+ const currentLocale2 = getLocale();
1862
+ const customMessages = i18n[currentLocale2];
1863
+ if (customMessages && customMessages[key]) {
1864
+ const template = customMessages[key];
1865
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
1866
+ }
1867
+ }
1868
+ return t(`common.time.${key}`, params);
1869
+ };
1870
+ const preprocessFn = (val) => {
1871
+ if (val === null || val === void 0) {
1872
+ return actualDefaultValue;
1873
+ }
1874
+ let processed = String(val);
1875
+ switch (trimMode) {
1876
+ case "trim":
1877
+ processed = processed.trim();
1878
+ break;
1879
+ case "trimStart":
1880
+ processed = processed.trimStart();
1881
+ break;
1882
+ case "trimEnd":
1883
+ processed = processed.trimEnd();
1884
+ break;
1885
+ case "none":
1886
+ break;
1887
+ }
1888
+ if (processed === "") {
1889
+ if (whitelist && whitelist.includes("")) {
1890
+ return "";
1891
+ }
1892
+ if (!isRequired) {
1893
+ return actualDefaultValue;
1894
+ }
1895
+ return actualDefaultValue;
1896
+ }
1897
+ switch (casing) {
1898
+ case "upper":
1899
+ processed = processed.toUpperCase();
1900
+ break;
1901
+ case "lower":
1902
+ processed = processed.toLowerCase();
1903
+ break;
1904
+ case "none":
1905
+ break;
1906
+ }
1907
+ if (transform) {
1908
+ processed = transform(processed);
1909
+ }
1910
+ return processed;
1911
+ };
1912
+ const baseSchema = isRequired ? import_zod10.z.preprocess(preprocessFn, import_zod10.z.string()) : import_zod10.z.preprocess(preprocessFn, import_zod10.z.string().nullable());
1913
+ const schema = baseSchema.refine((val) => {
1914
+ if (val === null) return true;
1915
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
1916
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1917
+ }
1918
+ if (val === null) return true;
1919
+ if (!isRequired && val === "") return true;
1920
+ if (whitelist && whitelist.length > 0) {
1921
+ if (whitelist.includes(val)) {
1922
+ return true;
1923
+ }
1924
+ if (whitelistOnly) {
1925
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
1926
+ }
1927
+ }
1928
+ if (regex) {
1929
+ if (!regex.test(val)) {
1930
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("customRegex"), path: [] }]);
1931
+ }
1932
+ } else {
1933
+ if (!validateTimeFormat(val, format)) {
1934
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("format", { format }), path: [] }]);
1935
+ }
1936
+ }
1937
+ if (includes && !val.includes(includes)) {
1938
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1939
+ }
1940
+ if (excludes) {
1941
+ const excludeList = Array.isArray(excludes) ? excludes : [excludes];
1942
+ for (const exclude of excludeList) {
1943
+ if (val.includes(exclude)) {
1944
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
1945
+ }
1946
+ }
1947
+ }
1948
+ if (regex) {
1949
+ return true;
1950
+ }
1951
+ const timeMinutes = parseTimeToMinutes(val, format);
1952
+ if (timeMinutes === null) {
1953
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1954
+ }
1955
+ const hour = Math.floor(timeMinutes / 60);
1956
+ if (minHour !== void 0 && hour < minHour) {
1957
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("hour", { minHour, maxHour: maxHour ?? 23 }), path: [] }]);
1958
+ }
1959
+ if (maxHour !== void 0 && hour > maxHour) {
1960
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("hour", { minHour: minHour ?? 0, maxHour }), path: [] }]);
1961
+ }
1962
+ if (allowedHours && allowedHours.length > 0) {
1963
+ if (!allowedHours.includes(hour)) {
1964
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("hour", { allowedHours: allowedHours.join(", ") }), path: [] }]);
1965
+ }
1966
+ }
1967
+ const minute = timeMinutes % 60;
1968
+ if (minuteStep !== void 0 && minute % minuteStep !== 0) {
1969
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("minute", { minuteStep }), path: [] }]);
1970
+ }
1971
+ if (secondStep !== void 0 && format.includes("ss")) {
1972
+ const secondMatch = val.match(/:(\d{2})$/);
1973
+ if (secondMatch) {
1974
+ const seconds = parseInt(secondMatch[1], 10);
1975
+ if (seconds % secondStep !== 0) {
1976
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("second", { secondStep }), path: [] }]);
1977
+ }
1978
+ }
1979
+ }
1980
+ if (min) {
1981
+ const minMinutes = parseTimeToMinutes(min, format);
1982
+ if (minMinutes !== null && timeMinutes < minMinutes) {
1983
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
1984
+ }
1985
+ }
1986
+ if (max) {
1987
+ const maxMinutes = parseTimeToMinutes(max, format);
1988
+ if (maxMinutes !== null && timeMinutes > maxMinutes) {
1989
+ throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
1990
+ }
1176
1991
  }
1177
1992
  return true;
1178
1993
  });
@@ -1180,10 +1995,9 @@ function text(options) {
1180
1995
  }
1181
1996
 
1182
1997
  // src/validators/common/url.ts
1183
- var import_zod8 = require("zod");
1184
- function url(options) {
1998
+ var import_zod11 = require("zod");
1999
+ function url(required, options) {
1185
2000
  const {
1186
- required = true,
1187
2001
  min,
1188
2002
  max,
1189
2003
  includes,
@@ -1205,7 +2019,8 @@ function url(options) {
1205
2019
  defaultValue = null,
1206
2020
  i18n
1207
2021
  } = options ?? {};
1208
- const actualDefaultValue = defaultValue ?? (required ? "" : null);
2022
+ const isRequired = required ?? false;
2023
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
1209
2024
  const getMessage = (key, params) => {
1210
2025
  if (i18n) {
1211
2026
  const currentLocale2 = getLocale();
@@ -1227,77 +2042,77 @@ function url(options) {
1227
2042
  }
1228
2043
  return processed;
1229
2044
  };
1230
- const baseSchema = required ? import_zod8.z.preprocess(preprocessFn, import_zod8.z.string()) : import_zod8.z.preprocess(preprocessFn, import_zod8.z.string().nullable());
2045
+ const baseSchema = isRequired ? import_zod11.z.preprocess(preprocessFn, import_zod11.z.string()) : import_zod11.z.preprocess(preprocessFn, import_zod11.z.string().nullable());
1231
2046
  const schema = baseSchema.refine((val) => {
1232
2047
  if (val === null) return true;
1233
- if (required && (val === "" || val === "null" || val === "undefined")) {
1234
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
2048
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
2049
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1235
2050
  }
1236
2051
  let urlObj;
1237
2052
  try {
1238
2053
  urlObj = new URL(val);
1239
2054
  } catch {
1240
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
2055
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1241
2056
  }
1242
2057
  if (val !== null && min !== void 0 && val.length < min) {
1243
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
2058
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("min", { min }), path: [] }]);
1244
2059
  }
1245
2060
  if (val !== null && max !== void 0 && val.length > max) {
1246
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
2061
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("max", { max }), path: [] }]);
1247
2062
  }
1248
2063
  if (val !== null && includes !== void 0 && !val.includes(includes)) {
1249
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
2064
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("includes", { includes }), path: [] }]);
1250
2065
  }
1251
2066
  if (val !== null && excludes !== void 0) {
1252
2067
  const excludeList = Array.isArray(excludes) ? excludes : [excludes];
1253
2068
  for (const exclude of excludeList) {
1254
2069
  if (val.includes(exclude)) {
1255
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
2070
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("excludes", { excludes: exclude }), path: [] }]);
1256
2071
  }
1257
2072
  }
1258
2073
  }
1259
2074
  if (protocols && !protocols.includes(urlObj.protocol.slice(0, -1))) {
1260
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("protocol", { protocols: protocols.join(", ") }), path: [] }]);
2075
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("protocol", { protocols: protocols.join(", ") }), path: [] }]);
1261
2076
  }
1262
2077
  const hostname = urlObj.hostname.toLowerCase();
1263
2078
  if (allowedDomains && !allowedDomains.some((domain) => hostname === domain || hostname.endsWith(`.${domain}`))) {
1264
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("domain", { domains: allowedDomains.join(", ") }), path: [] }]);
2079
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("domain", { domains: allowedDomains.join(", ") }), path: [] }]);
1265
2080
  }
1266
2081
  if (blockedDomains && blockedDomains.some((domain) => hostname === domain || hostname.endsWith(`.${domain}`))) {
1267
2082
  const blockedDomain = blockedDomains.find((domain) => hostname === domain || hostname.endsWith(`.${domain}`));
1268
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("domainBlacklist", { domain: blockedDomain }), path: [] }]);
2083
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("domainBlacklist", { domain: blockedDomain }), path: [] }]);
1269
2084
  }
1270
2085
  const port = urlObj.port ? parseInt(urlObj.port) : urlObj.protocol === "https:" ? 443 : 80;
1271
2086
  if (allowedPorts && !allowedPorts.includes(port)) {
1272
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("port", { ports: allowedPorts.join(", ") }), path: [] }]);
2087
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("port", { ports: allowedPorts.join(", ") }), path: [] }]);
1273
2088
  }
1274
2089
  if (blockedPorts && blockedPorts.includes(port)) {
1275
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("port", { port }), path: [] }]);
2090
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("port", { port }), path: [] }]);
1276
2091
  }
1277
2092
  if (pathStartsWith && !urlObj.pathname.startsWith(pathStartsWith)) {
1278
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("pathStartsWith", { path: pathStartsWith }), path: [] }]);
2093
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("pathStartsWith", { path: pathStartsWith }), path: [] }]);
1279
2094
  }
1280
2095
  if (pathEndsWith && !urlObj.pathname.endsWith(pathEndsWith)) {
1281
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("pathEndsWith", { path: pathEndsWith }), path: [] }]);
2096
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("pathEndsWith", { path: pathEndsWith }), path: [] }]);
1282
2097
  }
1283
2098
  if (mustHaveQuery && !urlObj.search) {
1284
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("hasQuery"), path: [] }]);
2099
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("hasQuery"), path: [] }]);
1285
2100
  }
1286
2101
  if (mustNotHaveQuery && urlObj.search) {
1287
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("noQuery"), path: [] }]);
2102
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("noQuery"), path: [] }]);
1288
2103
  }
1289
2104
  if (mustHaveFragment && !urlObj.hash) {
1290
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("hasFragment"), path: [] }]);
2105
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("hasFragment"), path: [] }]);
1291
2106
  }
1292
2107
  if (mustNotHaveFragment && urlObj.hash) {
1293
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("noFragment"), path: [] }]);
2108
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("noFragment"), path: [] }]);
1294
2109
  }
1295
2110
  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])\./);
1296
2111
  if (blockLocalhost && isLocalhost) {
1297
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("noLocalhost"), path: [] }]);
2112
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("noLocalhost"), path: [] }]);
1298
2113
  }
1299
2114
  if (!allowLocalhost && isLocalhost) {
1300
- throw new import_zod8.z.ZodError([{ code: "custom", message: getMessage("localhost"), path: [] }]);
2115
+ throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("localhost"), path: [] }]);
1301
2116
  }
1302
2117
  return true;
1303
2118
  });
@@ -1305,7 +2120,7 @@ function url(options) {
1305
2120
  }
1306
2121
 
1307
2122
  // src/validators/taiwan/business-id.ts
1308
- var import_zod9 = require("zod");
2123
+ var import_zod12 = require("zod");
1309
2124
  var validateTaiwanBusinessId = (value) => {
1310
2125
  if (!/^\d{8}$/.test(value)) {
1311
2126
  return false;
@@ -1337,14 +2152,14 @@ var validateTaiwanBusinessId = (value) => {
1337
2152
  }
1338
2153
  return false;
1339
2154
  };
1340
- function businessId(options) {
2155
+ function businessId(required, options) {
1341
2156
  const {
1342
- required = true,
1343
2157
  transform,
1344
2158
  defaultValue,
1345
2159
  i18n
1346
2160
  } = options ?? {};
1347
- const actualDefaultValue = defaultValue ?? (required ? "" : null);
2161
+ const isRequired = required ?? false;
2162
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
1348
2163
  const getMessage = (key, params) => {
1349
2164
  if (i18n) {
1350
2165
  const currentLocale2 = getLocale();
@@ -1369,16 +2184,16 @@ function businessId(options) {
1369
2184
  }
1370
2185
  return processed;
1371
2186
  };
1372
- const baseSchema = required ? import_zod9.z.preprocess(preprocessFn, import_zod9.z.string()) : import_zod9.z.preprocess(preprocessFn, import_zod9.z.string().nullable());
2187
+ const baseSchema = isRequired ? import_zod12.z.preprocess(preprocessFn, import_zod12.z.string()) : import_zod12.z.preprocess(preprocessFn, import_zod12.z.string().nullable());
1373
2188
  const schema = baseSchema.refine((val) => {
1374
2189
  if (val === null) return true;
1375
- if (required && (val === "" || val === "null" || val === "undefined")) {
1376
- throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
2190
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
2191
+ throw new import_zod12.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1377
2192
  }
1378
2193
  if (val === null) return true;
1379
- if (!required && val === "") return true;
2194
+ if (!isRequired && val === "") return true;
1380
2195
  if (!validateTaiwanBusinessId(val)) {
1381
- throw new import_zod9.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
2196
+ throw new import_zod12.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1382
2197
  }
1383
2198
  return true;
1384
2199
  });
@@ -1386,7 +2201,7 @@ function businessId(options) {
1386
2201
  }
1387
2202
 
1388
2203
  // src/validators/taiwan/national-id.ts
1389
- var import_zod10 = require("zod");
2204
+ var import_zod13 = require("zod");
1390
2205
  var CITY_CODES = {
1391
2206
  "A": 10,
1392
2207
  "B": 11,
@@ -1483,16 +2298,16 @@ var validateTaiwanNationalId = (value, type = "both", allowOldResident = true) =
1483
2298
  return false;
1484
2299
  }
1485
2300
  };
1486
- function nationalId(options) {
2301
+ function nationalId(required, options) {
1487
2302
  const {
1488
- required = true,
1489
2303
  type = "both",
1490
2304
  allowOldResident = true,
1491
2305
  transform,
1492
2306
  defaultValue,
1493
2307
  i18n
1494
2308
  } = options ?? {};
1495
- const actualDefaultValue = defaultValue ?? (required ? "" : null);
2309
+ const isRequired = required ?? false;
2310
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
1496
2311
  const getMessage = (key, params) => {
1497
2312
  if (i18n) {
1498
2313
  const currentLocale2 = getLocale();
@@ -1517,16 +2332,16 @@ function nationalId(options) {
1517
2332
  }
1518
2333
  return processed;
1519
2334
  };
1520
- const baseSchema = required ? import_zod10.z.preprocess(preprocessFn, import_zod10.z.string()) : import_zod10.z.preprocess(preprocessFn, import_zod10.z.string().nullable());
2335
+ const baseSchema = isRequired ? import_zod13.z.preprocess(preprocessFn, import_zod13.z.string()) : import_zod13.z.preprocess(preprocessFn, import_zod13.z.string().nullable());
1521
2336
  const schema = baseSchema.refine((val) => {
1522
2337
  if (val === null) return true;
1523
- if (required && (val === "" || val === "null" || val === "undefined")) {
1524
- throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
2338
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
2339
+ throw new import_zod13.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1525
2340
  }
1526
2341
  if (val === null) return true;
1527
- if (!required && val === "") return true;
2342
+ if (!isRequired && val === "") return true;
1528
2343
  if (!validateTaiwanNationalId(val, type, allowOldResident)) {
1529
- throw new import_zod10.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
2344
+ throw new import_zod13.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1530
2345
  }
1531
2346
  return true;
1532
2347
  });
@@ -1534,13 +2349,14 @@ function nationalId(options) {
1534
2349
  }
1535
2350
 
1536
2351
  // src/validators/taiwan/mobile.ts
1537
- var import_zod11 = require("zod");
2352
+ var import_zod14 = require("zod");
1538
2353
  var validateTaiwanMobile = (value) => {
1539
2354
  return /^09[0-9]\d{7}$/.test(value);
1540
2355
  };
1541
- function mobile(options) {
1542
- const { required = true, whitelist, transform, defaultValue, i18n } = options ?? {};
1543
- const actualDefaultValue = defaultValue ?? (required ? "" : null);
2356
+ function mobile(required, options) {
2357
+ const { whitelist, transform, defaultValue, i18n } = options ?? {};
2358
+ const isRequired = required ?? false;
2359
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
1544
2360
  const getMessage = (key, params) => {
1545
2361
  if (i18n) {
1546
2362
  const currentLocale2 = getLocale();
@@ -1561,7 +2377,7 @@ function mobile(options) {
1561
2377
  if (whitelist && whitelist.includes("")) {
1562
2378
  return "";
1563
2379
  }
1564
- if (!required) {
2380
+ if (!isRequired) {
1565
2381
  return actualDefaultValue;
1566
2382
  }
1567
2383
  return actualDefaultValue;
@@ -1571,22 +2387,698 @@ function mobile(options) {
1571
2387
  }
1572
2388
  return processed;
1573
2389
  };
1574
- const baseSchema = required ? import_zod11.z.preprocess(preprocessFn, import_zod11.z.string()) : import_zod11.z.preprocess(preprocessFn, import_zod11.z.string().nullable());
2390
+ const baseSchema = isRequired ? import_zod14.z.preprocess(preprocessFn, import_zod14.z.string()) : import_zod14.z.preprocess(preprocessFn, import_zod14.z.string().nullable());
1575
2391
  const schema = baseSchema.refine((val) => {
1576
2392
  if (val === null) return true;
1577
- if (required && (val === "" || val === "null" || val === "undefined")) {
1578
- throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
2393
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
2394
+ throw new import_zod14.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1579
2395
  }
1580
2396
  if (val === null) return true;
1581
- if (!required && val === "") return true;
2397
+ if (!isRequired && val === "") return true;
1582
2398
  if (whitelist && whitelist.length > 0) {
1583
2399
  if (whitelist.includes(val)) {
1584
2400
  return true;
1585
2401
  }
1586
- throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
2402
+ throw new import_zod14.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
1587
2403
  }
1588
2404
  if (!validateTaiwanMobile(val)) {
1589
- throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
2405
+ throw new import_zod14.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
2406
+ }
2407
+ return true;
2408
+ });
2409
+ return schema;
2410
+ }
2411
+
2412
+ // src/validators/taiwan/postal-code.ts
2413
+ var import_zod15 = require("zod");
2414
+ var VALID_3_DIGIT_PREFIXES = [
2415
+ // Taipei City (台北市) - 100-116
2416
+ "100",
2417
+ "103",
2418
+ "104",
2419
+ "105",
2420
+ "106",
2421
+ "108",
2422
+ "110",
2423
+ "111",
2424
+ "112",
2425
+ "114",
2426
+ "115",
2427
+ "116",
2428
+ // New Taipei City (新北市) - 200-253
2429
+ "200",
2430
+ "201",
2431
+ "202",
2432
+ "203",
2433
+ "204",
2434
+ "205",
2435
+ "206",
2436
+ "207",
2437
+ "208",
2438
+ "220",
2439
+ "221",
2440
+ "222",
2441
+ "223",
2442
+ "224",
2443
+ "226",
2444
+ "227",
2445
+ "228",
2446
+ "231",
2447
+ "232",
2448
+ "233",
2449
+ "234",
2450
+ "235",
2451
+ "236",
2452
+ "237",
2453
+ "238",
2454
+ "239",
2455
+ "241",
2456
+ "242",
2457
+ "243",
2458
+ "244",
2459
+ "247",
2460
+ "248",
2461
+ "249",
2462
+ "251",
2463
+ "252",
2464
+ "253",
2465
+ // Keelung City (基隆市) - 200-206
2466
+ "200",
2467
+ "201",
2468
+ "202",
2469
+ "203",
2470
+ "204",
2471
+ "205",
2472
+ "206",
2473
+ // Taoyuan City (桃園市) - 300-338
2474
+ "300",
2475
+ "302",
2476
+ "303",
2477
+ "304",
2478
+ "305",
2479
+ "306",
2480
+ "307",
2481
+ "308",
2482
+ "310",
2483
+ "311",
2484
+ "312",
2485
+ "313",
2486
+ "314",
2487
+ "315",
2488
+ "316",
2489
+ "317",
2490
+ "318",
2491
+ "320",
2492
+ "324",
2493
+ "325",
2494
+ "326",
2495
+ "327",
2496
+ "328",
2497
+ "330",
2498
+ "333",
2499
+ "334",
2500
+ "335",
2501
+ "336",
2502
+ "337",
2503
+ "338",
2504
+ // Hsinchu County (新竹縣) - 300-315
2505
+ "300",
2506
+ "302",
2507
+ "303",
2508
+ "304",
2509
+ "305",
2510
+ "306",
2511
+ "307",
2512
+ "308",
2513
+ "310",
2514
+ "311",
2515
+ "312",
2516
+ "313",
2517
+ "314",
2518
+ "315",
2519
+ // Hsinchu City (新竹市) - 300
2520
+ "300",
2521
+ // Miaoli County (苗栗縣) - 350-369
2522
+ "350",
2523
+ "351",
2524
+ "352",
2525
+ "353",
2526
+ "354",
2527
+ "356",
2528
+ "357",
2529
+ "358",
2530
+ "360",
2531
+ "361",
2532
+ "362",
2533
+ "363",
2534
+ "364",
2535
+ "365",
2536
+ "366",
2537
+ "367",
2538
+ "368",
2539
+ "369",
2540
+ // Taichung City (台中市) - 400-439
2541
+ "400",
2542
+ "401",
2543
+ "402",
2544
+ "403",
2545
+ "404",
2546
+ "406",
2547
+ "407",
2548
+ "408",
2549
+ "411",
2550
+ "412",
2551
+ "413",
2552
+ "414",
2553
+ "420",
2554
+ "421",
2555
+ "422",
2556
+ "423",
2557
+ "424",
2558
+ "426",
2559
+ "427",
2560
+ "428",
2561
+ "429",
2562
+ "432",
2563
+ "433",
2564
+ "434",
2565
+ "435",
2566
+ "436",
2567
+ "437",
2568
+ "438",
2569
+ "439",
2570
+ // Changhua County (彰化縣) - 500-530
2571
+ "500",
2572
+ "502",
2573
+ "503",
2574
+ "504",
2575
+ "505",
2576
+ "506",
2577
+ "507",
2578
+ "508",
2579
+ "509",
2580
+ "510",
2581
+ "511",
2582
+ "512",
2583
+ "513",
2584
+ "514",
2585
+ "515",
2586
+ "516",
2587
+ "520",
2588
+ "521",
2589
+ "522",
2590
+ "523",
2591
+ "524",
2592
+ "525",
2593
+ "526",
2594
+ "527",
2595
+ "528",
2596
+ "530",
2597
+ // Nantou County (南投縣) - 540-558
2598
+ "540",
2599
+ "541",
2600
+ "542",
2601
+ "544",
2602
+ "545",
2603
+ "546",
2604
+ "551",
2605
+ "552",
2606
+ "553",
2607
+ "555",
2608
+ "556",
2609
+ "557",
2610
+ "558",
2611
+ // Yunlin County (雲林縣) - 630-655
2612
+ "630",
2613
+ "631",
2614
+ "632",
2615
+ "633",
2616
+ "634",
2617
+ "635",
2618
+ "636",
2619
+ "637",
2620
+ "638",
2621
+ "640",
2622
+ "643",
2623
+ "646",
2624
+ "647",
2625
+ "648",
2626
+ "649",
2627
+ "651",
2628
+ "652",
2629
+ "653",
2630
+ "654",
2631
+ "655",
2632
+ // Chiayi County (嘉義縣) - 600-625
2633
+ "600",
2634
+ "602",
2635
+ "603",
2636
+ "604",
2637
+ "605",
2638
+ "606",
2639
+ "607",
2640
+ "608",
2641
+ "611",
2642
+ "612",
2643
+ "613",
2644
+ "614",
2645
+ "615",
2646
+ "616",
2647
+ "621",
2648
+ "622",
2649
+ "623",
2650
+ "624",
2651
+ "625",
2652
+ // Chiayi City (嘉義市) - 600
2653
+ "600",
2654
+ // Tainan City (台南市) - 700-745
2655
+ "700",
2656
+ "701",
2657
+ "702",
2658
+ "704",
2659
+ "708",
2660
+ "709",
2661
+ "710",
2662
+ "711",
2663
+ "712",
2664
+ "713",
2665
+ "714",
2666
+ "715",
2667
+ "716",
2668
+ "717",
2669
+ "718",
2670
+ "719",
2671
+ "720",
2672
+ "721",
2673
+ "722",
2674
+ "723",
2675
+ "724",
2676
+ "725",
2677
+ "726",
2678
+ "727",
2679
+ "730",
2680
+ "731",
2681
+ "732",
2682
+ "733",
2683
+ "734",
2684
+ "735",
2685
+ "736",
2686
+ "737",
2687
+ "741",
2688
+ "742",
2689
+ "743",
2690
+ "744",
2691
+ "745",
2692
+ // Kaohsiung City (高雄市) - 800-852
2693
+ "800",
2694
+ "801",
2695
+ "802",
2696
+ "803",
2697
+ "804",
2698
+ "805",
2699
+ "806",
2700
+ "807",
2701
+ "811",
2702
+ "812",
2703
+ "813",
2704
+ "814",
2705
+ "815",
2706
+ "820",
2707
+ "821",
2708
+ "822",
2709
+ "823",
2710
+ "824",
2711
+ "825",
2712
+ "826",
2713
+ "827",
2714
+ "828",
2715
+ "829",
2716
+ "830",
2717
+ "831",
2718
+ "832",
2719
+ "833",
2720
+ "840",
2721
+ "842",
2722
+ "843",
2723
+ "844",
2724
+ "845",
2725
+ "846",
2726
+ "847",
2727
+ "848",
2728
+ "849",
2729
+ "851",
2730
+ "852",
2731
+ // Pingtung County (屏東縣) - 900-947
2732
+ "900",
2733
+ "901",
2734
+ "902",
2735
+ "903",
2736
+ "904",
2737
+ "905",
2738
+ "906",
2739
+ "907",
2740
+ "908",
2741
+ "909",
2742
+ "911",
2743
+ "912",
2744
+ "913",
2745
+ "920",
2746
+ "921",
2747
+ "922",
2748
+ "923",
2749
+ "924",
2750
+ "925",
2751
+ "926",
2752
+ "927",
2753
+ "928",
2754
+ "929",
2755
+ "931",
2756
+ "932",
2757
+ "940",
2758
+ "941",
2759
+ "942",
2760
+ "943",
2761
+ "944",
2762
+ "945",
2763
+ "946",
2764
+ "947",
2765
+ // Yilan County (宜蘭縣) - 260-269
2766
+ "260",
2767
+ "261",
2768
+ "262",
2769
+ "263",
2770
+ "264",
2771
+ "265",
2772
+ "266",
2773
+ "267",
2774
+ "268",
2775
+ "269",
2776
+ // Hualien County (花蓮縣) - 970-983
2777
+ "970",
2778
+ "971",
2779
+ "972",
2780
+ "973",
2781
+ "974",
2782
+ "975",
2783
+ "976",
2784
+ "977",
2785
+ "978",
2786
+ "979",
2787
+ "981",
2788
+ "982",
2789
+ "983",
2790
+ // Taitung County (台東縣) - 950-966
2791
+ "950",
2792
+ "951",
2793
+ "952",
2794
+ "953",
2795
+ "954",
2796
+ "955",
2797
+ "956",
2798
+ "957",
2799
+ "958",
2800
+ "959",
2801
+ "961",
2802
+ "962",
2803
+ "963",
2804
+ "964",
2805
+ "965",
2806
+ "966",
2807
+ // Penghu County (澎湖縣) - 880-885
2808
+ "880",
2809
+ "881",
2810
+ "882",
2811
+ "883",
2812
+ "884",
2813
+ "885",
2814
+ // Kinmen County (金門縣) - 890-896
2815
+ "890",
2816
+ "891",
2817
+ "892",
2818
+ "893",
2819
+ "894",
2820
+ "895",
2821
+ "896",
2822
+ // Lienchiang County (連江縣/馬祖) - 209-212
2823
+ "209",
2824
+ "210",
2825
+ "211",
2826
+ "212"
2827
+ ];
2828
+ var POSTAL_CODE_RANGES = {
2829
+ // Major cities with extensive postal networks
2830
+ "100": { range5: [1, 99], range6: [1, 999] },
2831
+ // Taipei City - Zhongzheng
2832
+ "103": { range5: [1, 99], range6: [1, 999] },
2833
+ // Taipei City - Datong
2834
+ "104": { range5: [1, 99], range6: [1, 999] },
2835
+ // Taipei City - Zhongshan
2836
+ "105": { range5: [1, 99], range6: [1, 999] },
2837
+ // Taipei City - Songshan
2838
+ "106": { range5: [1, 99], range6: [1, 999] },
2839
+ // Taipei City - Da'an
2840
+ "108": { range5: [1, 99], range6: [1, 999] },
2841
+ // Taipei City - Wanhua
2842
+ "110": { range5: [1, 99], range6: [1, 999] },
2843
+ // Taipei City - Xinyi
2844
+ "111": { range5: [1, 99], range6: [1, 999] },
2845
+ // Taipei City - Shilin
2846
+ "112": { range5: [1, 99], range6: [1, 999] },
2847
+ // Taipei City - Beitou
2848
+ "114": { range5: [1, 99], range6: [1, 999] },
2849
+ // Taipei City - Neihu
2850
+ "115": { range5: [1, 99], range6: [1, 999] },
2851
+ // Taipei City - Nangang
2852
+ "116": { range5: [1, 99], range6: [1, 999] },
2853
+ // Taipei City - Wenshan
2854
+ // New Taipei City major areas
2855
+ "220": { range5: [1, 99], range6: [1, 999] },
2856
+ // Banqiao
2857
+ "221": { range5: [1, 99], range6: [1, 999] },
2858
+ // Xizhi
2859
+ "222": { range5: [1, 99], range6: [1, 999] },
2860
+ // Shenkeng
2861
+ "223": { range5: [1, 99], range6: [1, 999] },
2862
+ // Shiding
2863
+ "224": { range5: [1, 99], range6: [1, 999] },
2864
+ // Ruifang
2865
+ // Taoyuan City
2866
+ "320": { range5: [1, 99], range6: [1, 999] },
2867
+ // Zhongli
2868
+ "324": { range5: [1, 99], range6: [1, 999] },
2869
+ // Pingzhen
2870
+ "330": { range5: [1, 99], range6: [1, 999] },
2871
+ // Taoyuan
2872
+ // Taichung City
2873
+ "400": { range5: [1, 99], range6: [1, 999] },
2874
+ // Central District
2875
+ "401": { range5: [1, 99], range6: [1, 999] },
2876
+ // East District
2877
+ "402": { range5: [1, 99], range6: [1, 999] },
2878
+ // South District
2879
+ "403": { range5: [1, 99], range6: [1, 999] },
2880
+ // West District
2881
+ "404": { range5: [1, 99], range6: [1, 999] },
2882
+ // North District
2883
+ // Tainan City
2884
+ "700": { range5: [1, 99], range6: [1, 999] },
2885
+ // Central District
2886
+ "701": { range5: [1, 99], range6: [1, 999] },
2887
+ // East District
2888
+ "702": { range5: [1, 99], range6: [1, 999] },
2889
+ // South District
2890
+ // Kaohsiung City
2891
+ "800": { range5: [1, 99], range6: [1, 999] },
2892
+ // Xinxing
2893
+ "801": { range5: [1, 99], range6: [1, 999] },
2894
+ // Qianjin
2895
+ "802": { range5: [1, 99], range6: [1, 999] },
2896
+ // Lingya
2897
+ "803": { range5: [1, 99], range6: [1, 999] },
2898
+ // Yancheng
2899
+ // Smaller areas with more limited ranges
2900
+ "880": { range5: [1, 50], range6: [1, 500] },
2901
+ // Penghu (smaller population)
2902
+ "890": { range5: [1, 30], range6: [1, 300] },
2903
+ // Kinmen (smaller population)
2904
+ "209": { range5: [1, 20], range6: [1, 200] }
2905
+ // Lienchiang/Matsu (smallest population)
2906
+ };
2907
+ var getPostalCodeRanges = (prefix) => {
2908
+ return POSTAL_CODE_RANGES[prefix] || {
2909
+ range5: [1, 99],
2910
+ // Default range for 5-digit
2911
+ range6: [1, 999]
2912
+ // Default range for 6-digit
2913
+ };
2914
+ };
2915
+ var validate3DigitPostalCode = (value, strictValidation = true, allowedPrefixes, blockedPrefixes) => {
2916
+ if (!/^\d{3}$/.test(value)) {
2917
+ return false;
2918
+ }
2919
+ if (blockedPrefixes && blockedPrefixes.includes(value)) {
2920
+ return false;
2921
+ }
2922
+ if (allowedPrefixes) {
2923
+ return allowedPrefixes.includes(value);
2924
+ }
2925
+ if (strictValidation) {
2926
+ return VALID_3_DIGIT_PREFIXES.includes(value);
2927
+ }
2928
+ const num = parseInt(value, 10);
2929
+ return num >= 100 && num <= 999;
2930
+ };
2931
+ var validate5DigitPostalCode = (value, strictValidation = true, strictSuffixValidation = false, allowedPrefixes, blockedPrefixes) => {
2932
+ if (!/^\d{5}$/.test(value)) {
2933
+ return false;
2934
+ }
2935
+ const prefix = value.substring(0, 3);
2936
+ const suffix = value.substring(3, 5);
2937
+ if (!validate3DigitPostalCode(prefix, strictValidation, allowedPrefixes, blockedPrefixes)) {
2938
+ return false;
2939
+ }
2940
+ if (strictSuffixValidation) {
2941
+ const suffixNum = parseInt(suffix, 10);
2942
+ const ranges = getPostalCodeRanges(prefix);
2943
+ if (suffixNum < ranges.range5[0] || suffixNum > ranges.range5[1]) {
2944
+ return false;
2945
+ }
2946
+ }
2947
+ return true;
2948
+ };
2949
+ var validate6DigitPostalCode = (value, strictValidation = true, strictSuffixValidation = false, allowedPrefixes, blockedPrefixes) => {
2950
+ if (!/^\d{6}$/.test(value)) {
2951
+ return false;
2952
+ }
2953
+ const prefix = value.substring(0, 3);
2954
+ const suffix = value.substring(3, 6);
2955
+ if (!validate3DigitPostalCode(prefix, strictValidation, allowedPrefixes, blockedPrefixes)) {
2956
+ return false;
2957
+ }
2958
+ if (strictSuffixValidation) {
2959
+ const suffixNum = parseInt(suffix, 10);
2960
+ const ranges = getPostalCodeRanges(prefix);
2961
+ if (suffixNum < ranges.range6[0] || suffixNum > ranges.range6[1]) {
2962
+ return false;
2963
+ }
2964
+ }
2965
+ return true;
2966
+ };
2967
+ var validateTaiwanPostalCode = (value, format = "3+6", strictValidation = true, strictSuffixValidation = false, allowDashes = true, allowedPrefixes, blockedPrefixes) => {
2968
+ if (!value || typeof value !== "string") {
2969
+ return false;
2970
+ }
2971
+ const cleanValue = allowDashes ? value.replace(/[-\s]/g, "") : value;
2972
+ if (!allowDashes && /[-\s]/.test(value)) {
2973
+ return false;
2974
+ }
2975
+ switch (format) {
2976
+ case "3":
2977
+ return cleanValue.length === 3 && validate3DigitPostalCode(cleanValue, strictValidation, allowedPrefixes, blockedPrefixes);
2978
+ case "5":
2979
+ return cleanValue.length === 5 && validate5DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes);
2980
+ case "6":
2981
+ return cleanValue.length === 6 && validate6DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes);
2982
+ case "3+5":
2983
+ return cleanValue.length === 3 && validate3DigitPostalCode(cleanValue, strictValidation, allowedPrefixes, blockedPrefixes) || cleanValue.length === 5 && validate5DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes);
2984
+ case "3+6":
2985
+ return cleanValue.length === 3 && validate3DigitPostalCode(cleanValue, strictValidation, allowedPrefixes, blockedPrefixes) || cleanValue.length === 6 && validate6DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes);
2986
+ case "5+6":
2987
+ return cleanValue.length === 5 && validate5DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes) || cleanValue.length === 6 && validate6DigitPostalCode(cleanValue, strictValidation, strictSuffixValidation, allowedPrefixes, blockedPrefixes);
2988
+ case "all":
2989
+ 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);
2990
+ default:
2991
+ return false;
2992
+ }
2993
+ };
2994
+ function postalCode(required, options) {
2995
+ const {
2996
+ format = "3+6",
2997
+ strictValidation = true,
2998
+ allowDashes = true,
2999
+ warn5Digit = true,
3000
+ allowedPrefixes,
3001
+ blockedPrefixes,
3002
+ transform,
3003
+ defaultValue,
3004
+ i18n,
3005
+ strictSuffixValidation = false,
3006
+ deprecate5Digit = false
3007
+ } = options ?? {};
3008
+ const isRequired = required ?? false;
3009
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
3010
+ const getMessage = (key, params) => {
3011
+ if (i18n) {
3012
+ const currentLocale2 = getLocale();
3013
+ const customMessages = i18n[currentLocale2];
3014
+ if (customMessages && customMessages[key]) {
3015
+ const template = customMessages[key];
3016
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
3017
+ }
3018
+ }
3019
+ return t(`taiwan.postalCode.${key}`, params);
3020
+ };
3021
+ const preprocessFn = (val) => {
3022
+ if (val === "" || val === null || val === void 0) {
3023
+ return actualDefaultValue;
3024
+ }
3025
+ let processed = String(val).trim();
3026
+ if (allowDashes) {
3027
+ processed = processed.replace(/[-\s]/g, "");
3028
+ }
3029
+ if (processed === "" && !required) {
3030
+ return null;
3031
+ }
3032
+ if (transform) {
3033
+ processed = transform(processed);
3034
+ }
3035
+ return processed;
3036
+ };
3037
+ const baseSchema = isRequired ? import_zod15.z.preprocess(preprocessFn, import_zod15.z.string()) : import_zod15.z.preprocess(preprocessFn, import_zod15.z.string().nullable());
3038
+ const schema = baseSchema.refine((val) => {
3039
+ if (val === null) return true;
3040
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
3041
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
3042
+ }
3043
+ if (val === null) return true;
3044
+ if (!isRequired && val === "") return true;
3045
+ const cleanValue = val.replace(/[-\s]/g, "");
3046
+ if (format === "3" && cleanValue.length !== 3) {
3047
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("format3Only"), path: [] }]);
3048
+ }
3049
+ if (format === "5" && cleanValue.length !== 5) {
3050
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("format5Only"), path: [] }]);
3051
+ }
3052
+ if (format === "6" && cleanValue.length !== 6) {
3053
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("format6Only"), path: [] }]);
3054
+ }
3055
+ if (deprecate5Digit && cleanValue.length === 5) {
3056
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("deprecated5Digit"), path: [] }]);
3057
+ }
3058
+ if (strictSuffixValidation) {
3059
+ if (cleanValue.length === 5) {
3060
+ const prefix = cleanValue.substring(0, 3);
3061
+ const suffix = cleanValue.substring(3, 5);
3062
+ const suffixNum = parseInt(suffix, 10);
3063
+ const ranges = getPostalCodeRanges(prefix);
3064
+ if (suffixNum < ranges.range5[0] || suffixNum > ranges.range5[1]) {
3065
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("invalidSuffix"), path: [] }]);
3066
+ }
3067
+ } else if (cleanValue.length === 6) {
3068
+ const prefix = cleanValue.substring(0, 3);
3069
+ const suffix = cleanValue.substring(3, 6);
3070
+ const suffixNum = parseInt(suffix, 10);
3071
+ const ranges = getPostalCodeRanges(prefix);
3072
+ if (suffixNum < ranges.range6[0] || suffixNum > ranges.range6[1]) {
3073
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("invalidSuffix"), path: [] }]);
3074
+ }
3075
+ }
3076
+ }
3077
+ if (!validateTaiwanPostalCode(val, format, strictValidation, strictSuffixValidation, allowDashes, allowedPrefixes, blockedPrefixes)) {
3078
+ throw new import_zod15.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
3079
+ }
3080
+ if (warn5Digit && cleanValue.length === 5 && format !== "5" && !deprecate5Digit) {
3081
+ console.warn(getMessage("legacy5DigitWarning"));
1590
3082
  }
1591
3083
  return true;
1592
3084
  });
@@ -1594,7 +3086,7 @@ function mobile(options) {
1594
3086
  }
1595
3087
 
1596
3088
  // src/validators/taiwan/tel.ts
1597
- var import_zod12 = require("zod");
3089
+ var import_zod16 = require("zod");
1598
3090
  var validateTaiwanTel = (value) => {
1599
3091
  const cleanValue = value.replace(/[-\s]/g, "");
1600
3092
  if (!/^0\d{7,10}$/.test(cleanValue)) {
@@ -1635,9 +3127,10 @@ var validateTaiwanTel = (value) => {
1635
3127
  }
1636
3128
  return false;
1637
3129
  };
1638
- function tel(options) {
1639
- const { required = true, whitelist, transform, defaultValue, i18n } = options ?? {};
1640
- const actualDefaultValue = defaultValue ?? (required ? "" : null);
3130
+ function tel(required, options) {
3131
+ const { whitelist, transform, defaultValue, i18n } = options ?? {};
3132
+ const isRequired = required ?? false;
3133
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
1641
3134
  const getMessage = (key, params) => {
1642
3135
  if (i18n) {
1643
3136
  const currentLocale2 = getLocale();
@@ -1658,7 +3151,7 @@ function tel(options) {
1658
3151
  if (whitelist && whitelist.includes("")) {
1659
3152
  return "";
1660
3153
  }
1661
- if (!required) {
3154
+ if (!isRequired) {
1662
3155
  return actualDefaultValue;
1663
3156
  }
1664
3157
  return actualDefaultValue;
@@ -1668,22 +3161,22 @@ function tel(options) {
1668
3161
  }
1669
3162
  return processed;
1670
3163
  };
1671
- const baseSchema = required ? import_zod12.z.preprocess(preprocessFn, import_zod12.z.string()) : import_zod12.z.preprocess(preprocessFn, import_zod12.z.string().nullable());
3164
+ const baseSchema = isRequired ? import_zod16.z.preprocess(preprocessFn, import_zod16.z.string()) : import_zod16.z.preprocess(preprocessFn, import_zod16.z.string().nullable());
1672
3165
  const schema = baseSchema.refine((val) => {
1673
3166
  if (val === null) return true;
1674
- if (required && (val === "" || val === "null" || val === "undefined")) {
1675
- throw new import_zod12.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
3167
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
3168
+ throw new import_zod16.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1676
3169
  }
1677
3170
  if (val === null) return true;
1678
- if (!required && val === "") return true;
3171
+ if (!isRequired && val === "") return true;
1679
3172
  if (whitelist && whitelist.length > 0) {
1680
3173
  if (whitelist.includes(val)) {
1681
3174
  return true;
1682
3175
  }
1683
- throw new import_zod12.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
3176
+ throw new import_zod16.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
1684
3177
  }
1685
3178
  if (!validateTaiwanTel(val)) {
1686
- throw new import_zod12.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
3179
+ throw new import_zod16.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1687
3180
  }
1688
3181
  return true;
1689
3182
  });
@@ -1691,7 +3184,7 @@ function tel(options) {
1691
3184
  }
1692
3185
 
1693
3186
  // src/validators/taiwan/fax.ts
1694
- var import_zod13 = require("zod");
3187
+ var import_zod17 = require("zod");
1695
3188
  var validateTaiwanFax = (value) => {
1696
3189
  const cleanValue = value.replace(/[-\s]/g, "");
1697
3190
  if (!/^0\d{7,10}$/.test(cleanValue)) {
@@ -1732,9 +3225,10 @@ var validateTaiwanFax = (value) => {
1732
3225
  }
1733
3226
  return false;
1734
3227
  };
1735
- function fax(options) {
1736
- const { required = true, whitelist, transform, defaultValue, i18n } = options ?? {};
1737
- const actualDefaultValue = defaultValue ?? (required ? "" : null);
3228
+ function fax(required, options) {
3229
+ const { whitelist, transform, defaultValue, i18n } = options ?? {};
3230
+ const isRequired = required ?? false;
3231
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
1738
3232
  const getMessage = (key, params) => {
1739
3233
  if (i18n) {
1740
3234
  const currentLocale2 = getLocale();
@@ -1755,7 +3249,7 @@ function fax(options) {
1755
3249
  if (whitelist && whitelist.includes("")) {
1756
3250
  return "";
1757
3251
  }
1758
- if (!required) {
3252
+ if (!isRequired) {
1759
3253
  return actualDefaultValue;
1760
3254
  }
1761
3255
  return actualDefaultValue;
@@ -1765,22 +3259,22 @@ function fax(options) {
1765
3259
  }
1766
3260
  return processed;
1767
3261
  };
1768
- const baseSchema = required ? import_zod13.z.preprocess(preprocessFn, import_zod13.z.string()) : import_zod13.z.preprocess(preprocessFn, import_zod13.z.string().nullable());
3262
+ const baseSchema = isRequired ? import_zod17.z.preprocess(preprocessFn, import_zod17.z.string()) : import_zod17.z.preprocess(preprocessFn, import_zod17.z.string().nullable());
1769
3263
  const schema = baseSchema.refine((val) => {
1770
3264
  if (val === null) return true;
1771
- if (required && (val === "" || val === "null" || val === "undefined")) {
1772
- throw new import_zod13.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
3265
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
3266
+ throw new import_zod17.z.ZodError([{ code: "custom", message: getMessage("required"), path: [] }]);
1773
3267
  }
1774
3268
  if (val === null) return true;
1775
- if (!required && val === "") return true;
3269
+ if (!isRequired && val === "") return true;
1776
3270
  if (whitelist && whitelist.length > 0) {
1777
3271
  if (whitelist.includes(val)) {
1778
3272
  return true;
1779
3273
  }
1780
- throw new import_zod13.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
3274
+ throw new import_zod17.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
1781
3275
  }
1782
3276
  if (!validateTaiwanFax(val)) {
1783
- throw new import_zod13.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
3277
+ throw new import_zod17.z.ZodError([{ code: "custom", message: getMessage("invalid"), path: [] }]);
1784
3278
  }
1785
3279
  return true;
1786
3280
  });
@@ -1788,24 +3282,39 @@ function fax(options) {
1788
3282
  }
1789
3283
  // Annotate the CommonJS export names for ESM import in node:
1790
3284
  0 && (module.exports = {
3285
+ DATETIME_PATTERNS,
1791
3286
  ID_PATTERNS,
3287
+ TIME_PATTERNS,
3288
+ VALID_3_DIGIT_PREFIXES,
1792
3289
  boolean,
1793
3290
  businessId,
1794
3291
  date,
3292
+ datetime,
1795
3293
  detectIdType,
1796
3294
  email,
1797
3295
  fax,
3296
+ file,
1798
3297
  getLocale,
1799
3298
  id,
1800
3299
  mobile,
1801
3300
  nationalId,
3301
+ normalizeDateTimeValue,
3302
+ normalizeTime,
1802
3303
  number,
3304
+ parseDateTimeValue,
3305
+ parseTimeToMinutes,
1803
3306
  password,
3307
+ postalCode,
1804
3308
  setLocale,
1805
3309
  tel,
1806
3310
  text,
3311
+ time,
1807
3312
  url,
3313
+ validate3DigitPostalCode,
3314
+ validate5DigitPostalCode,
3315
+ validate6DigitPostalCode,
1808
3316
  validateCitizenId,
3317
+ validateDateTimeFormat,
1809
3318
  validateIdType,
1810
3319
  validateNewResidentId,
1811
3320
  validateOldResidentId,
@@ -1813,5 +3322,7 @@ function fax(options) {
1813
3322
  validateTaiwanFax,
1814
3323
  validateTaiwanMobile,
1815
3324
  validateTaiwanNationalId,
1816
- validateTaiwanTel
3325
+ validateTaiwanPostalCode,
3326
+ validateTaiwanTel,
3327
+ validateTimeFormat
1817
3328
  });