@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.
- package/.claude/settings.local.json +9 -1
- package/README.md +465 -97
- package/dist/index.cjs +1690 -179
- package/dist/index.d.cts +2791 -28
- package/dist/index.d.ts +2791 -28
- package/dist/index.js +1672 -178
- package/package.json +2 -1
- package/src/i18n/locales/en.json +62 -0
- package/src/i18n/locales/zh-TW.json +62 -0
- package/src/index.ts +4 -0
- package/src/validators/common/boolean.ts +101 -4
- package/src/validators/common/date.ts +141 -6
- package/src/validators/common/datetime.ts +680 -0
- package/src/validators/common/email.ts +120 -4
- package/src/validators/common/file.ts +391 -0
- package/src/validators/common/id.ts +230 -18
- package/src/validators/common/number.ts +132 -4
- package/src/validators/common/password.ts +187 -8
- package/src/validators/common/text.ts +130 -6
- package/src/validators/common/time.ts +607 -0
- package/src/validators/common/url.ts +153 -6
- package/src/validators/taiwan/business-id.ts +138 -9
- package/src/validators/taiwan/fax.ts +164 -10
- package/src/validators/taiwan/mobile.ts +151 -10
- package/src/validators/taiwan/national-id.ts +233 -17
- package/src/validators/taiwan/postal-code.ts +1048 -0
- package/src/validators/taiwan/tel.ts +167 -10
- package/tests/common/boolean.test.ts +38 -38
- package/tests/common/date.test.ts +65 -65
- package/tests/common/datetime.test.ts +675 -0
- package/tests/common/email.test.ts +24 -28
- package/tests/common/file.test.ts +475 -0
- package/tests/common/id.test.ts +80 -113
- package/tests/common/number.test.ts +24 -25
- package/tests/common/password.test.ts +28 -35
- package/tests/common/text.test.ts +36 -37
- package/tests/common/time.test.ts +510 -0
- package/tests/common/url.test.ts +67 -67
- package/tests/taiwan/business-id.test.ts +22 -22
- package/tests/taiwan/fax.test.ts +33 -42
- package/tests/taiwan/mobile.test.ts +32 -41
- package/tests/taiwan/national-id.test.ts +31 -31
- package/tests/taiwan/postal-code.test.ts +751 -0
- package/tests/taiwan/tel.test.ts +33 -42
- package/debug.js +0 -21
- 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
|
-
|
|
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 (
|
|
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
|
|
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 =
|
|
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 (
|
|
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/
|
|
684
|
+
// src/validators/common/datetime.ts
|
|
544
685
|
var import_zod3 = require("zod");
|
|
545
|
-
|
|
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 =
|
|
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
|
-
|
|
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 (
|
|
594
|
-
throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 (
|
|
754
|
-
throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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 (
|
|
895
|
-
throw new
|
|
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
|
|
1482
|
+
throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("integer"), path: [] }]);
|
|
901
1483
|
} else if (type === "float") {
|
|
902
|
-
throw new
|
|
1484
|
+
throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("float"), path: [] }]);
|
|
903
1485
|
} else {
|
|
904
|
-
throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1499
|
+
throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("float"), path: [] }]);
|
|
918
1500
|
}
|
|
919
1501
|
if (positive && val <= 0) {
|
|
920
|
-
throw new
|
|
1502
|
+
throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("positive"), path: [] }]);
|
|
921
1503
|
}
|
|
922
1504
|
if (negative && val >= 0) {
|
|
923
|
-
throw new
|
|
1505
|
+
throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("negative"), path: [] }]);
|
|
924
1506
|
}
|
|
925
1507
|
if (nonNegative && val < 0) {
|
|
926
|
-
throw new
|
|
1508
|
+
throw new import_zod7.z.ZodError([{ code: "custom", message: getMessage("nonNegative"), path: [] }]);
|
|
927
1509
|
}
|
|
928
1510
|
if (nonPositive && val > 0) {
|
|
929
|
-
throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 (
|
|
1033
|
-
throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1092
|
-
function text(options) {
|
|
1093
|
-
const {
|
|
1094
|
-
const
|
|
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 =
|
|
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 (
|
|
1146
|
-
throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 (
|
|
1234
|
-
throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
2099
|
+
throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("hasQuery"), path: [] }]);
|
|
1285
2100
|
}
|
|
1286
2101
|
if (mustNotHaveQuery && urlObj.search) {
|
|
1287
|
-
throw new
|
|
2102
|
+
throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("noQuery"), path: [] }]);
|
|
1288
2103
|
}
|
|
1289
2104
|
if (mustHaveFragment && !urlObj.hash) {
|
|
1290
|
-
throw new
|
|
2105
|
+
throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("hasFragment"), path: [] }]);
|
|
1291
2106
|
}
|
|
1292
2107
|
if (mustNotHaveFragment && urlObj.hash) {
|
|
1293
|
-
throw new
|
|
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
|
|
2112
|
+
throw new import_zod11.z.ZodError([{ code: "custom", message: getMessage("noLocalhost"), path: [] }]);
|
|
1298
2113
|
}
|
|
1299
2114
|
if (!allowLocalhost && isLocalhost) {
|
|
1300
|
-
throw new
|
|
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
|
|
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
|
|
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 =
|
|
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 (
|
|
1376
|
-
throw new
|
|
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 (!
|
|
2194
|
+
if (!isRequired && val === "") return true;
|
|
1380
2195
|
if (!validateTaiwanBusinessId(val)) {
|
|
1381
|
-
throw new
|
|
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
|
|
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
|
|
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 =
|
|
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 (
|
|
1524
|
-
throw new
|
|
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 (!
|
|
2342
|
+
if (!isRequired && val === "") return true;
|
|
1528
2343
|
if (!validateTaiwanNationalId(val, type, allowOldResident)) {
|
|
1529
|
-
throw new
|
|
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
|
|
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 {
|
|
1543
|
-
const
|
|
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 (!
|
|
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 =
|
|
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 (
|
|
1578
|
-
throw new
|
|
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 (!
|
|
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
|
|
2402
|
+
throw new import_zod14.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
|
|
1587
2403
|
}
|
|
1588
2404
|
if (!validateTaiwanMobile(val)) {
|
|
1589
|
-
throw new
|
|
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
|
|
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 {
|
|
1640
|
-
const
|
|
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 (!
|
|
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 =
|
|
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 (
|
|
1675
|
-
throw new
|
|
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 (!
|
|
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
|
|
3176
|
+
throw new import_zod16.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
|
|
1684
3177
|
}
|
|
1685
3178
|
if (!validateTaiwanTel(val)) {
|
|
1686
|
-
throw new
|
|
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
|
|
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 {
|
|
1737
|
-
const
|
|
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 (!
|
|
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 =
|
|
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 (
|
|
1772
|
-
throw new
|
|
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 (!
|
|
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
|
|
3274
|
+
throw new import_zod17.z.ZodError([{ code: "custom", message: getMessage("notInWhitelist"), path: [] }]);
|
|
1781
3275
|
}
|
|
1782
3276
|
if (!validateTaiwanFax(val)) {
|
|
1783
|
-
throw new
|
|
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
|
-
|
|
3325
|
+
validateTaiwanPostalCode,
|
|
3326
|
+
validateTaiwanTel,
|
|
3327
|
+
validateTimeFormat
|
|
1817
3328
|
});
|