@hy_ong/zod-kit 0.1.16 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/.github/workflows/ci.yml +24 -0
  2. package/CLAUDE.md +184 -0
  3. package/dist/chunk-36NWHESN.js +124 -0
  4. package/dist/chunk-4LYZAO3P.js +165 -0
  5. package/dist/chunk-5GAZQDVS.cjs +206 -0
  6. package/dist/chunk-5LS4DSRQ.cjs +127 -0
  7. package/dist/chunk-5OGW2ERW.js +181 -0
  8. package/dist/chunk-5ZEKWPSE.cjs +69 -0
  9. package/dist/chunk-6OGDPSWT.js +135 -0
  10. package/dist/chunk-6X22I6NQ.cjs +136 -0
  11. package/dist/chunk-77KZUPPN.cjs +177 -0
  12. package/dist/chunk-AANSHH2O.cjs +165 -0
  13. package/dist/chunk-AI72FMOF.cjs +130 -0
  14. package/dist/chunk-AWV2IT66.js +146 -0
  15. package/dist/chunk-B3U5G3AA.js +160 -0
  16. package/dist/chunk-CFFCBWYL.cjs +99 -0
  17. package/dist/chunk-DPXRMSB2.js +130 -0
  18. package/dist/chunk-DRXPGQM6.cjs +135 -0
  19. package/dist/chunk-EAU42EVH.js +161 -0
  20. package/dist/chunk-FC6VDOC7.js +206 -0
  21. package/dist/chunk-FVO4743A.cjs +134 -0
  22. package/dist/chunk-G6DV7LX7.cjs +161 -0
  23. package/dist/chunk-I2RJMDXN.js +90 -0
  24. package/dist/chunk-IJEEM3DI.js +136 -0
  25. package/dist/chunk-JBNCMS42.cjs +151 -0
  26. package/dist/chunk-JZ2SHRGZ.js +87 -0
  27. package/dist/chunk-KARFFIMP.js +696 -0
  28. package/dist/chunk-LIQSVJLS.js +177 -0
  29. package/dist/chunk-LKPXHW5N.cjs +181 -0
  30. package/dist/chunk-MAQRXYE6.js +118 -0
  31. package/dist/chunk-MCDESS3T.js +69 -0
  32. package/dist/chunk-MG25BEV4.cjs +160 -0
  33. package/dist/chunk-NKCYXBGX.js +99 -0
  34. package/dist/chunk-OEK7QSQP.js +75 -0
  35. package/dist/chunk-OMFQ7Z63.cjs +696 -0
  36. package/dist/chunk-OP4KV3BY.cjs +124 -0
  37. package/dist/chunk-P2NONIMS.js +257 -0
  38. package/dist/chunk-P364KRO5.js +61 -0
  39. package/dist/chunk-PGSDXR2I.js +71 -0
  40. package/dist/chunk-PL2GERLG.cjs +61 -0
  41. package/dist/chunk-R5G4V7C6.cjs +75 -0
  42. package/dist/chunk-RKHX3DGH.js +127 -0
  43. package/dist/chunk-TSHL7ZO2.js +134 -0
  44. package/dist/chunk-UFNVCUPQ.cjs +301 -0
  45. package/dist/chunk-VCRKYMJM.js +301 -0
  46. package/dist/chunk-VDOAPLA6.cjs +257 -0
  47. package/dist/chunk-VP5CCP5F.cjs +90 -0
  48. package/dist/chunk-W2EWMV3A.cjs +87 -0
  49. package/dist/chunk-WWRFBLCR.cjs +146 -0
  50. package/dist/chunk-YALLOVNO.cjs +118 -0
  51. package/dist/chunk-YAU6JCYL.cjs +71 -0
  52. package/dist/chunk-YWV2BBXN.cjs +2526 -0
  53. package/dist/chunk-ZBOQCXD4.js +2526 -0
  54. package/dist/chunk-ZFQQXWNB.js +151 -0
  55. package/dist/common/boolean.cjs +7 -0
  56. package/dist/common/boolean.d.cts +119 -0
  57. package/dist/common/boolean.d.ts +119 -0
  58. package/dist/common/boolean.js +7 -0
  59. package/dist/common/color.cjs +9 -0
  60. package/dist/common/color.d.cts +26 -0
  61. package/dist/common/color.d.ts +26 -0
  62. package/dist/common/color.js +9 -0
  63. package/dist/common/coordinate.cjs +11 -0
  64. package/dist/common/coordinate.d.cts +23 -0
  65. package/dist/common/coordinate.d.ts +23 -0
  66. package/dist/common/coordinate.js +11 -0
  67. package/dist/common/credit-card.cjs +11 -0
  68. package/dist/common/credit-card.d.cts +22 -0
  69. package/dist/common/credit-card.d.ts +22 -0
  70. package/dist/common/credit-card.js +11 -0
  71. package/dist/common/date.cjs +7 -0
  72. package/dist/common/date.d.cts +174 -0
  73. package/dist/common/date.d.ts +174 -0
  74. package/dist/common/date.js +7 -0
  75. package/dist/common/datetime.cjs +15 -0
  76. package/dist/common/datetime.d.cts +301 -0
  77. package/dist/common/datetime.d.ts +301 -0
  78. package/dist/common/datetime.js +15 -0
  79. package/dist/common/email.cjs +7 -0
  80. package/dist/common/email.d.cts +149 -0
  81. package/dist/common/email.d.ts +149 -0
  82. package/dist/common/email.js +7 -0
  83. package/dist/common/file.cjs +7 -0
  84. package/dist/common/file.d.cts +178 -0
  85. package/dist/common/file.d.ts +178 -0
  86. package/dist/common/file.js +7 -0
  87. package/dist/common/id.cjs +13 -0
  88. package/dist/common/id.d.cts +262 -0
  89. package/dist/common/id.d.ts +262 -0
  90. package/dist/common/id.js +13 -0
  91. package/dist/common/ip.cjs +11 -0
  92. package/dist/common/ip.d.cts +25 -0
  93. package/dist/common/ip.d.ts +25 -0
  94. package/dist/common/ip.js +11 -0
  95. package/dist/common/number.cjs +7 -0
  96. package/dist/common/number.d.cts +167 -0
  97. package/dist/common/number.d.ts +167 -0
  98. package/dist/common/number.js +7 -0
  99. package/dist/common/password.cjs +7 -0
  100. package/dist/common/password.d.cts +192 -0
  101. package/dist/common/password.d.ts +192 -0
  102. package/dist/common/password.js +7 -0
  103. package/dist/common/text.cjs +7 -0
  104. package/dist/common/text.d.cts +156 -0
  105. package/dist/common/text.d.ts +156 -0
  106. package/dist/common/text.js +7 -0
  107. package/dist/common/time.cjs +15 -0
  108. package/dist/common/time.d.cts +268 -0
  109. package/dist/common/time.d.ts +268 -0
  110. package/dist/common/time.js +15 -0
  111. package/dist/common/url.cjs +7 -0
  112. package/dist/common/url.d.cts +196 -0
  113. package/dist/common/url.d.ts +196 -0
  114. package/dist/common/url.js +7 -0
  115. package/dist/config-CABSSvAp.d.cts +5 -0
  116. package/dist/config-CABSSvAp.d.ts +5 -0
  117. package/dist/index.cjs +180 -3599
  118. package/dist/index.d.cts +28 -3150
  119. package/dist/index.d.ts +28 -3150
  120. package/dist/index.js +135 -3475
  121. package/dist/taiwan/bank-account.cjs +11 -0
  122. package/dist/taiwan/bank-account.d.cts +22 -0
  123. package/dist/taiwan/bank-account.d.ts +22 -0
  124. package/dist/taiwan/bank-account.js +11 -0
  125. package/dist/taiwan/business-id.cjs +9 -0
  126. package/dist/taiwan/business-id.d.cts +133 -0
  127. package/dist/taiwan/business-id.d.ts +133 -0
  128. package/dist/taiwan/business-id.js +9 -0
  129. package/dist/taiwan/fax.cjs +9 -0
  130. package/dist/taiwan/fax.d.cts +157 -0
  131. package/dist/taiwan/fax.d.ts +157 -0
  132. package/dist/taiwan/fax.js +9 -0
  133. package/dist/taiwan/invoice.cjs +9 -0
  134. package/dist/taiwan/invoice.d.cts +17 -0
  135. package/dist/taiwan/invoice.d.ts +17 -0
  136. package/dist/taiwan/invoice.js +9 -0
  137. package/dist/taiwan/license-plate.cjs +9 -0
  138. package/dist/taiwan/license-plate.d.cts +19 -0
  139. package/dist/taiwan/license-plate.d.ts +19 -0
  140. package/dist/taiwan/license-plate.js +9 -0
  141. package/dist/taiwan/mobile.cjs +9 -0
  142. package/dist/taiwan/mobile.d.cts +146 -0
  143. package/dist/taiwan/mobile.d.ts +146 -0
  144. package/dist/taiwan/mobile.js +9 -0
  145. package/dist/taiwan/national-id.cjs +15 -0
  146. package/dist/taiwan/national-id.d.cts +214 -0
  147. package/dist/taiwan/national-id.d.ts +214 -0
  148. package/dist/taiwan/national-id.js +15 -0
  149. package/dist/taiwan/passport.cjs +9 -0
  150. package/dist/taiwan/passport.d.cts +19 -0
  151. package/dist/taiwan/passport.d.ts +19 -0
  152. package/dist/taiwan/passport.js +9 -0
  153. package/dist/taiwan/postal-code.cjs +17 -0
  154. package/dist/taiwan/postal-code.d.cts +237 -0
  155. package/dist/taiwan/postal-code.d.ts +237 -0
  156. package/dist/taiwan/postal-code.js +17 -0
  157. package/dist/taiwan/tel.cjs +9 -0
  158. package/dist/taiwan/tel.d.cts +162 -0
  159. package/dist/taiwan/tel.d.ts +162 -0
  160. package/dist/taiwan/tel.js +9 -0
  161. package/package.json +128 -2
  162. package/src/config.ts +2 -2
  163. package/src/i18n/index.ts +18 -2
  164. package/src/i18n/locales/en-GB.json +247 -0
  165. package/src/i18n/locales/{en.json → en-US.json} +43 -0
  166. package/src/i18n/locales/id-ID.json +247 -0
  167. package/src/i18n/locales/ja-JP.json +247 -0
  168. package/src/i18n/locales/ko-KR.json +247 -0
  169. package/src/i18n/locales/ms-MY.json +247 -0
  170. package/src/i18n/locales/th-TH.json +247 -0
  171. package/src/i18n/locales/vi-VN.json +247 -0
  172. package/src/i18n/locales/zh-CN.json +247 -0
  173. package/src/i18n/locales/zh-TW.json +43 -0
  174. package/src/index.ts +10 -2
  175. package/src/validators/common/boolean.ts +1 -1
  176. package/src/validators/common/color.ts +192 -0
  177. package/src/validators/common/coordinate.ts +159 -0
  178. package/src/validators/common/credit-card.ts +134 -0
  179. package/src/validators/common/date.ts +1 -1
  180. package/src/validators/common/datetime.ts +1 -1
  181. package/src/validators/common/email.ts +1 -1
  182. package/src/validators/common/file.ts +1 -1
  183. package/src/validators/common/id.ts +1 -1
  184. package/src/validators/common/ip.ts +210 -0
  185. package/src/validators/common/number.ts +1 -1
  186. package/src/validators/common/password.ts +1 -1
  187. package/src/validators/common/text.ts +1 -1
  188. package/src/validators/common/time.ts +1 -1
  189. package/src/validators/common/url.ts +1 -1
  190. package/src/validators/taiwan/bank-account.ts +176 -0
  191. package/src/validators/taiwan/business-id.ts +1 -1
  192. package/src/validators/taiwan/fax.ts +1 -1
  193. package/src/validators/taiwan/invoice.ts +84 -0
  194. package/src/validators/taiwan/license-plate.ts +110 -0
  195. package/src/validators/taiwan/mobile.ts +1 -1
  196. package/src/validators/taiwan/national-id.ts +1 -1
  197. package/src/validators/taiwan/passport.ts +103 -0
  198. package/src/validators/taiwan/postal-code.ts +1 -1
  199. package/src/validators/taiwan/tel.ts +1 -1
  200. package/tests/common/boolean.test.ts +6 -6
  201. package/tests/common/color.test.ts +587 -0
  202. package/tests/common/coordinate.test.ts +345 -0
  203. package/tests/common/credit-card.test.ts +378 -0
  204. package/tests/common/date.test.ts +8 -8
  205. package/tests/common/datetime.test.ts +7 -7
  206. package/tests/common/email.test.ts +6 -6
  207. package/tests/common/file.test.ts +6 -6
  208. package/tests/common/id.test.ts +5 -5
  209. package/tests/common/ip.test.ts +419 -0
  210. package/tests/common/number.test.ts +6 -6
  211. package/tests/common/password.test.ts +5 -5
  212. package/tests/common/text.test.ts +7 -7
  213. package/tests/common/time.test.ts +7 -7
  214. package/tests/common/url.test.ts +10 -10
  215. package/tests/taiwan/bank-account.test.ts +286 -0
  216. package/tests/taiwan/business-id.test.ts +4 -4
  217. package/tests/taiwan/fax.test.ts +7 -7
  218. package/tests/taiwan/invoice.test.ts +227 -0
  219. package/tests/taiwan/license-plate.test.ts +280 -0
  220. package/tests/taiwan/mobile.test.ts +7 -7
  221. package/tests/taiwan/national-id.test.ts +4 -4
  222. package/tests/taiwan/passport.test.ts +277 -0
  223. package/tests/taiwan/postal-code.test.ts +6 -6
  224. package/tests/taiwan/tel.test.ts +7 -7
  225. package/tsup.config.ts +36 -0
@@ -0,0 +1,161 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+ var _chunkYWV2BBXNcjs = require('./chunk-YWV2BBXN.cjs');
5
+
6
+ // src/validators/taiwan/national-id.ts
7
+ var _zod = require('zod');
8
+ var CITY_CODES = {
9
+ "A": 10,
10
+ "B": 11,
11
+ "C": 12,
12
+ "D": 13,
13
+ "E": 14,
14
+ "F": 15,
15
+ "G": 16,
16
+ "H": 17,
17
+ "I": 34,
18
+ "J": 18,
19
+ "K": 19,
20
+ "L": 20,
21
+ "M": 21,
22
+ "N": 22,
23
+ "O": 35,
24
+ "P": 23,
25
+ "Q": 24,
26
+ "R": 25,
27
+ "S": 26,
28
+ "T": 27,
29
+ "U": 28,
30
+ "V": 29,
31
+ "W": 32,
32
+ "X": 30,
33
+ "Y": 31,
34
+ "Z": 33
35
+ };
36
+ var validateCitizenId = (value) => {
37
+ if (!/^[A-Z][1-2]\d{8}$/.test(value)) {
38
+ return false;
39
+ }
40
+ const letter = value[0];
41
+ const digits = value.slice(1).split("").map(Number);
42
+ const cityCode = CITY_CODES[letter];
43
+ if (!cityCode) return false;
44
+ const cityDigits = [Math.floor(cityCode / 10), cityCode % 10];
45
+ const coefficients = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1];
46
+ let sum = cityDigits[0] * coefficients[0] + cityDigits[1] * coefficients[1];
47
+ for (let i = 0; i < 8; i++) {
48
+ sum += digits[i] * coefficients[i + 2];
49
+ }
50
+ const checksum = (10 - sum % 10) % 10;
51
+ return checksum === digits[8];
52
+ };
53
+ var validateOldResidentId = (value) => {
54
+ if (!/^[A-Z][ABCD]\d{8}$/.test(value)) {
55
+ return false;
56
+ }
57
+ const letter = value[0];
58
+ const genderCode = value[1];
59
+ const digits = value.slice(2).split("").map(Number);
60
+ const cityCode = CITY_CODES[letter];
61
+ if (!cityCode) return false;
62
+ const genderValue = genderCode === "A" || genderCode === "C" ? 1 : 0;
63
+ const cityDigits = [Math.floor(cityCode / 10), cityCode % 10];
64
+ const coefficients = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1];
65
+ let sum = cityDigits[0] * coefficients[0] + cityDigits[1] * coefficients[1] + genderValue * coefficients[2];
66
+ for (let i = 0; i < 7; i++) {
67
+ sum += digits[i] * coefficients[i + 3];
68
+ }
69
+ const checksum = (10 - sum % 10) % 10;
70
+ return checksum === digits[7];
71
+ };
72
+ var validateNewResidentId = (value) => {
73
+ if (!/^[A-Z][89]\d{8}$/.test(value)) {
74
+ return false;
75
+ }
76
+ const letter = value[0];
77
+ const digits = value.slice(1).split("").map(Number);
78
+ const cityCode = CITY_CODES[letter];
79
+ if (!cityCode) return false;
80
+ const cityDigits = [Math.floor(cityCode / 10), cityCode % 10];
81
+ const coefficients = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1];
82
+ let sum = cityDigits[0] * coefficients[0] + cityDigits[1] * coefficients[1];
83
+ for (let i = 0; i < 8; i++) {
84
+ sum += digits[i] * coefficients[i + 2];
85
+ }
86
+ const checksum = (10 - sum % 10) % 10;
87
+ return checksum === digits[8];
88
+ };
89
+ var validateTaiwanNationalId = (value, type = "both", allowOldResident = true) => {
90
+ if (!/^[A-Z].{9}$/.test(value)) {
91
+ return false;
92
+ }
93
+ switch (type) {
94
+ case "citizen":
95
+ return validateCitizenId(value);
96
+ case "resident":
97
+ return (allowOldResident ? validateOldResidentId(value) : false) || validateNewResidentId(value);
98
+ case "both":
99
+ return validateCitizenId(value) || (allowOldResident ? validateOldResidentId(value) : false) || validateNewResidentId(value);
100
+ default:
101
+ return false;
102
+ }
103
+ };
104
+ function twNationalId(required, options) {
105
+ const {
106
+ type = "both",
107
+ allowOldResident = true,
108
+ transform,
109
+ defaultValue,
110
+ i18n
111
+ } = _nullishCoalesce(options, () => ( {}));
112
+ const isRequired = _nullishCoalesce(required, () => ( false));
113
+ const actualDefaultValue = _nullishCoalesce(defaultValue, () => ( (isRequired ? "" : null)));
114
+ const getMessage = (key, params) => {
115
+ if (i18n) {
116
+ const currentLocale = _chunkYWV2BBXNcjs.getLocale.call(void 0, );
117
+ const customMessages = i18n[currentLocale];
118
+ if (customMessages && customMessages[key]) {
119
+ const template = customMessages[key];
120
+ return template.replace(/\$\{(\w+)}/g, (_, k) => _nullishCoalesce(_optionalChain([params, 'optionalAccess', _2 => _2[k]]), () => ( "")));
121
+ }
122
+ }
123
+ return _chunkYWV2BBXNcjs.t.call(void 0, `taiwan.nationalId.${key}`, params);
124
+ };
125
+ const preprocessFn = (val) => {
126
+ if (val === "" || val === null || val === void 0) {
127
+ return actualDefaultValue;
128
+ }
129
+ let processed = String(val).trim().toUpperCase();
130
+ if (processed === "" && !required) {
131
+ return null;
132
+ }
133
+ if (transform) {
134
+ processed = transform(processed);
135
+ }
136
+ return processed;
137
+ };
138
+ const baseSchema = isRequired ? _zod.z.preprocess(preprocessFn, _zod.z.string()) : _zod.z.preprocess(preprocessFn, _zod.z.string().nullable());
139
+ const schema = baseSchema.superRefine((val, ctx) => {
140
+ if (val === null) return;
141
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
142
+ ctx.addIssue({ code: "custom", message: getMessage("required") });
143
+ return;
144
+ }
145
+ if (val === null) return;
146
+ if (!isRequired && val === "") return;
147
+ if (!validateTaiwanNationalId(val, type, allowOldResident)) {
148
+ ctx.addIssue({ code: "custom", message: getMessage("invalid") });
149
+ return;
150
+ }
151
+ });
152
+ return schema;
153
+ }
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+ exports.validateCitizenId = validateCitizenId; exports.validateOldResidentId = validateOldResidentId; exports.validateNewResidentId = validateNewResidentId; exports.validateTaiwanNationalId = validateTaiwanNationalId; exports.twNationalId = twNationalId;
@@ -0,0 +1,90 @@
1
+ import {
2
+ getLocale,
3
+ t
4
+ } from "./chunk-ZBOQCXD4.js";
5
+
6
+ // src/validators/taiwan/license-plate.ts
7
+ import { z } from "zod";
8
+ var CAR_PATTERNS = [
9
+ /^[A-Z]{3}\d{4}$/,
10
+ // ABC-1234 (new)
11
+ /^\d{4}[A-Z]{2}$/,
12
+ // 1234-AB (new/legacy)
13
+ /^[A-Z]{2}\d{4}$/,
14
+ // AB-1234 (legacy)
15
+ /^[A-Z]\d{5}$/
16
+ // A1-2345 -> A12345 (legacy mixed)
17
+ ];
18
+ var MOTORCYCLE_PATTERNS = [
19
+ /^[A-Z]{3}\d{4}$/,
20
+ // ABC-1234
21
+ /^\d{3}[A-Z]{3}$/,
22
+ // 123-ABC
23
+ /^[A-Z]{2}\d{4}$/,
24
+ // AB-1234 (legacy)
25
+ /^\d{4}[A-Z]{2}$/
26
+ // 1234-AB (legacy)
27
+ ];
28
+ var validateTaiwanLicensePlate = (value, plateType = "any") => {
29
+ const patterns = [];
30
+ if (plateType === "car" || plateType === "any") {
31
+ patterns.push(...CAR_PATTERNS);
32
+ }
33
+ if (plateType === "motorcycle" || plateType === "any") {
34
+ for (const pattern of MOTORCYCLE_PATTERNS) {
35
+ if (!patterns.some((p) => p.source === pattern.source)) {
36
+ patterns.push(pattern);
37
+ }
38
+ }
39
+ }
40
+ return patterns.some((pattern) => pattern.test(value));
41
+ };
42
+ function twLicensePlate(required, options) {
43
+ const { plateType = "any", transform, defaultValue, i18n } = options ?? {};
44
+ const isRequired = required ?? false;
45
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
46
+ const getMessage = (key, params) => {
47
+ if (i18n) {
48
+ const currentLocale = getLocale();
49
+ const customMessages = i18n[currentLocale];
50
+ if (customMessages && customMessages[key]) {
51
+ const template = customMessages[key];
52
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
53
+ }
54
+ }
55
+ return t(`taiwan.licensePlate.${key}`, params);
56
+ };
57
+ const preprocessFn = (val) => {
58
+ if (val === "" || val === null || val === void 0) {
59
+ return actualDefaultValue;
60
+ }
61
+ let processed = String(val).trim().toUpperCase().replace(/[-\s]/g, "");
62
+ if (processed === "" && !required) {
63
+ return null;
64
+ }
65
+ if (transform) {
66
+ processed = transform(processed);
67
+ }
68
+ return processed;
69
+ };
70
+ const baseSchema = isRequired ? z.preprocess(preprocessFn, z.string()) : z.preprocess(preprocessFn, z.string().nullable());
71
+ const schema = baseSchema.superRefine((val, ctx) => {
72
+ if (val === null) return;
73
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
74
+ ctx.addIssue({ code: "custom", message: getMessage("required") });
75
+ return;
76
+ }
77
+ if (val === null) return;
78
+ if (!isRequired && val === "") return;
79
+ if (!validateTaiwanLicensePlate(val, plateType)) {
80
+ ctx.addIssue({ code: "custom", message: getMessage("invalid") });
81
+ return;
82
+ }
83
+ });
84
+ return schema;
85
+ }
86
+
87
+ export {
88
+ validateTaiwanLicensePlate,
89
+ twLicensePlate
90
+ };
@@ -0,0 +1,136 @@
1
+ import {
2
+ getLocale,
3
+ t
4
+ } from "./chunk-ZBOQCXD4.js";
5
+
6
+ // src/validators/common/text.ts
7
+ import { z } from "zod";
8
+ function text(required, options) {
9
+ const { minLength, maxLength, startsWith, endsWith, includes, excludes, regex, trimMode = "trim", casing = "none", transform, notEmpty, defaultValue, i18n } = options ?? {};
10
+ const isRequired = required ?? false;
11
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
12
+ const getMessage = (key, params) => {
13
+ if (i18n) {
14
+ const currentLocale = getLocale();
15
+ const customMessages = i18n[currentLocale];
16
+ if (customMessages && customMessages[key]) {
17
+ const template = customMessages[key];
18
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
19
+ }
20
+ }
21
+ return t(`common.text.${key}`, params);
22
+ };
23
+ const applyTrim = (str) => {
24
+ switch (trimMode) {
25
+ case "trimStart":
26
+ return str.trimStart();
27
+ case "trimEnd":
28
+ return str.trimEnd();
29
+ case "none":
30
+ return str;
31
+ default:
32
+ return str.trim();
33
+ }
34
+ };
35
+ const applyCasing = (str) => {
36
+ switch (casing) {
37
+ case "upper":
38
+ return str.toUpperCase();
39
+ case "lower":
40
+ return str.toLowerCase();
41
+ case "title":
42
+ return str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase());
43
+ default:
44
+ return str;
45
+ }
46
+ };
47
+ const preprocessFn = (val) => {
48
+ if (val === "" || val === null || val === void 0) {
49
+ return actualDefaultValue;
50
+ }
51
+ let processed = String(val);
52
+ processed = applyTrim(processed);
53
+ processed = applyCasing(processed);
54
+ if (transform) {
55
+ processed = transform(processed);
56
+ }
57
+ return processed;
58
+ };
59
+ const baseSchema = isRequired ? z.preprocess(preprocessFn, z.string()) : z.preprocess(preprocessFn, z.string().nullable());
60
+ const schema = baseSchema.superRefine((val, ctx) => {
61
+ if (val === null) return;
62
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
63
+ ctx.addIssue({
64
+ code: "custom",
65
+ message: getMessage("required")
66
+ });
67
+ return;
68
+ }
69
+ if (notEmpty && val !== null && val.trim() === "") {
70
+ ctx.addIssue({
71
+ code: "custom",
72
+ message: getMessage("notEmpty")
73
+ });
74
+ return;
75
+ }
76
+ if (val !== null && minLength !== void 0 && val.length < minLength) {
77
+ ctx.addIssue({
78
+ code: "custom",
79
+ message: getMessage("minLength", { minLength })
80
+ });
81
+ return;
82
+ }
83
+ if (val !== null && maxLength !== void 0 && val.length > maxLength) {
84
+ ctx.addIssue({
85
+ code: "custom",
86
+ message: getMessage("maxLength", { maxLength })
87
+ });
88
+ return;
89
+ }
90
+ if (val !== null && startsWith !== void 0 && !val.startsWith(startsWith)) {
91
+ ctx.addIssue({
92
+ code: "custom",
93
+ message: getMessage("startsWith", { startsWith })
94
+ });
95
+ return;
96
+ }
97
+ if (val !== null && endsWith !== void 0 && !val.endsWith(endsWith)) {
98
+ ctx.addIssue({
99
+ code: "custom",
100
+ message: getMessage("endsWith", { endsWith })
101
+ });
102
+ return;
103
+ }
104
+ if (val !== null && includes !== void 0 && !val.includes(includes)) {
105
+ ctx.addIssue({
106
+ code: "custom",
107
+ message: getMessage("includes", { includes })
108
+ });
109
+ return;
110
+ }
111
+ if (val !== null && excludes !== void 0) {
112
+ const excludeList = Array.isArray(excludes) ? excludes : [excludes];
113
+ for (const exclude of excludeList) {
114
+ if (val.includes(exclude)) {
115
+ ctx.addIssue({
116
+ code: "custom",
117
+ message: getMessage("excludes", { excludes: exclude })
118
+ });
119
+ return;
120
+ }
121
+ }
122
+ }
123
+ if (val !== null && regex !== void 0 && !regex.test(val)) {
124
+ ctx.addIssue({
125
+ code: "custom",
126
+ message: getMessage("invalid", { regex })
127
+ });
128
+ return;
129
+ }
130
+ });
131
+ return schema;
132
+ }
133
+
134
+ export {
135
+ text
136
+ };
@@ -0,0 +1,151 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+ var _chunkYWV2BBXNcjs = require('./chunk-YWV2BBXN.cjs');
5
+
6
+ // src/validators/common/url.ts
7
+ var _zod = require('zod');
8
+ function url(required, options) {
9
+ const {
10
+ min,
11
+ max,
12
+ includes,
13
+ excludes,
14
+ protocols,
15
+ allowedDomains,
16
+ blockedDomains,
17
+ allowedPorts,
18
+ blockedPorts,
19
+ pathStartsWith,
20
+ pathEndsWith,
21
+ mustHaveQuery,
22
+ mustNotHaveQuery,
23
+ mustHaveFragment,
24
+ mustNotHaveFragment,
25
+ allowLocalhost = true,
26
+ blockLocalhost,
27
+ transform,
28
+ defaultValue = null,
29
+ i18n
30
+ } = _nullishCoalesce(options, () => ( {}));
31
+ const isRequired = _nullishCoalesce(required, () => ( false));
32
+ const actualDefaultValue = _nullishCoalesce(defaultValue, () => ( (isRequired ? "" : null)));
33
+ const getMessage = (key, params) => {
34
+ if (i18n) {
35
+ const currentLocale = _chunkYWV2BBXNcjs.getLocale.call(void 0, );
36
+ const customMessages = i18n[currentLocale];
37
+ if (customMessages && customMessages[key]) {
38
+ const template = customMessages[key];
39
+ return template.replace(/\$\{(\w+)}/g, (_, k) => _nullishCoalesce(_optionalChain([params, 'optionalAccess', _2 => _2[k]]), () => ( "")));
40
+ }
41
+ }
42
+ return _chunkYWV2BBXNcjs.t.call(void 0, `common.url.${key}`, params);
43
+ };
44
+ const preprocessFn = (val) => {
45
+ if (val === "" || val === null || val === void 0) {
46
+ return actualDefaultValue;
47
+ }
48
+ let processed = String(val).trim();
49
+ if (transform) {
50
+ processed = transform(processed);
51
+ }
52
+ return processed;
53
+ };
54
+ const baseSchema = isRequired ? _zod.z.preprocess(preprocessFn, _zod.z.string()) : _zod.z.preprocess(preprocessFn, _zod.z.string().nullable());
55
+ const schema = baseSchema.superRefine((val, ctx) => {
56
+ if (val === null) return;
57
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
58
+ ctx.addIssue({ code: "custom", message: getMessage("required") });
59
+ return;
60
+ }
61
+ let urlObj;
62
+ try {
63
+ urlObj = new URL(val);
64
+ } catch (e) {
65
+ ctx.addIssue({ code: "custom", message: getMessage("invalid") });
66
+ return;
67
+ }
68
+ if (val !== null && min !== void 0 && val.length < min) {
69
+ ctx.addIssue({ code: "custom", message: getMessage("min", { min }) });
70
+ return;
71
+ }
72
+ if (val !== null && max !== void 0 && val.length > max) {
73
+ ctx.addIssue({ code: "custom", message: getMessage("max", { max }) });
74
+ return;
75
+ }
76
+ if (val !== null && includes !== void 0 && !val.includes(includes)) {
77
+ ctx.addIssue({ code: "custom", message: getMessage("includes", { includes }) });
78
+ return;
79
+ }
80
+ if (val !== null && excludes !== void 0) {
81
+ const excludeList = Array.isArray(excludes) ? excludes : [excludes];
82
+ for (const exclude of excludeList) {
83
+ if (val.includes(exclude)) {
84
+ ctx.addIssue({ code: "custom", message: getMessage("excludes", { excludes: exclude }) });
85
+ return;
86
+ }
87
+ }
88
+ }
89
+ if (protocols && !protocols.includes(urlObj.protocol.slice(0, -1))) {
90
+ ctx.addIssue({ code: "custom", message: getMessage("protocol", { protocols: protocols.join(", ") }) });
91
+ return;
92
+ }
93
+ const hostname = urlObj.hostname.toLowerCase();
94
+ if (allowedDomains && !allowedDomains.some((domain) => hostname === domain || hostname.endsWith(`.${domain}`))) {
95
+ ctx.addIssue({ code: "custom", message: getMessage("domain", { domains: allowedDomains.join(", ") }) });
96
+ return;
97
+ }
98
+ if (blockedDomains && blockedDomains.some((domain) => hostname === domain || hostname.endsWith(`.${domain}`))) {
99
+ const blockedDomain = blockedDomains.find((domain) => hostname === domain || hostname.endsWith(`.${domain}`));
100
+ ctx.addIssue({ code: "custom", message: getMessage("domainBlacklist", { domain: blockedDomain }) });
101
+ return;
102
+ }
103
+ const port = urlObj.port ? parseInt(urlObj.port) : urlObj.protocol === "https:" ? 443 : 80;
104
+ if (allowedPorts && !allowedPorts.includes(port)) {
105
+ ctx.addIssue({ code: "custom", message: getMessage("port", { ports: allowedPorts.join(", ") }) });
106
+ return;
107
+ }
108
+ if (blockedPorts && blockedPorts.includes(port)) {
109
+ ctx.addIssue({ code: "custom", message: getMessage("port", { port }) });
110
+ return;
111
+ }
112
+ if (pathStartsWith && !urlObj.pathname.startsWith(pathStartsWith)) {
113
+ ctx.addIssue({ code: "custom", message: getMessage("pathStartsWith", { path: pathStartsWith }) });
114
+ return;
115
+ }
116
+ if (pathEndsWith && !urlObj.pathname.endsWith(pathEndsWith)) {
117
+ ctx.addIssue({ code: "custom", message: getMessage("pathEndsWith", { path: pathEndsWith }) });
118
+ return;
119
+ }
120
+ if (mustHaveQuery && !urlObj.search) {
121
+ ctx.addIssue({ code: "custom", message: getMessage("hasQuery") });
122
+ return;
123
+ }
124
+ if (mustNotHaveQuery && urlObj.search) {
125
+ ctx.addIssue({ code: "custom", message: getMessage("noQuery") });
126
+ return;
127
+ }
128
+ if (mustHaveFragment && !urlObj.hash) {
129
+ ctx.addIssue({ code: "custom", message: getMessage("hasFragment") });
130
+ return;
131
+ }
132
+ if (mustNotHaveFragment && urlObj.hash) {
133
+ ctx.addIssue({ code: "custom", message: getMessage("noFragment") });
134
+ return;
135
+ }
136
+ 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])\./);
137
+ if (blockLocalhost && isLocalhost) {
138
+ ctx.addIssue({ code: "custom", message: getMessage("noLocalhost") });
139
+ return;
140
+ }
141
+ if (!allowLocalhost && isLocalhost) {
142
+ ctx.addIssue({ code: "custom", message: getMessage("localhost") });
143
+ return;
144
+ }
145
+ });
146
+ return schema;
147
+ }
148
+
149
+
150
+
151
+ exports.url = url;
@@ -0,0 +1,87 @@
1
+ import {
2
+ getLocale,
3
+ t
4
+ } from "./chunk-ZBOQCXD4.js";
5
+
6
+ // src/validators/taiwan/business-id.ts
7
+ import { z } from "zod";
8
+ var validateTaiwanBusinessId = (value) => {
9
+ if (!/^\d{8}$/.test(value)) {
10
+ return false;
11
+ }
12
+ const digits = value.split("").map(Number);
13
+ const coefficients = [1, 2, 1, 2, 1, 2, 4];
14
+ let sum = 0;
15
+ for (let i = 0; i < 7; i++) {
16
+ const product = digits[i] * coefficients[i];
17
+ sum += Math.floor(product / 10) + product % 10;
18
+ }
19
+ sum += digits[7];
20
+ if (sum % 5 === 0) {
21
+ return true;
22
+ }
23
+ if (sum % 10 === 0) {
24
+ return true;
25
+ }
26
+ if (digits[6] === 7) {
27
+ let altSum = 0;
28
+ for (let i = 0; i < 7; i++) {
29
+ const product = digits[i] * coefficients[i];
30
+ altSum += Math.floor(product / 10) + product % 10;
31
+ }
32
+ altSum += 1 + digits[7];
33
+ if (altSum % 5 === 0 || altSum % 10 === 0) {
34
+ return true;
35
+ }
36
+ }
37
+ return false;
38
+ };
39
+ function twBusinessId(required, options) {
40
+ const { transform, defaultValue, i18n } = options ?? {};
41
+ const isRequired = required ?? false;
42
+ const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
43
+ const getMessage = (key, params) => {
44
+ if (i18n) {
45
+ const currentLocale = getLocale();
46
+ const customMessages = i18n[currentLocale];
47
+ if (customMessages && customMessages[key]) {
48
+ const template = customMessages[key];
49
+ return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
50
+ }
51
+ }
52
+ return t(`taiwan.businessId.${key}`, params);
53
+ };
54
+ const preprocessFn = (val) => {
55
+ if (val === "" || val === null || val === void 0) {
56
+ return actualDefaultValue;
57
+ }
58
+ let processed = String(val).trim();
59
+ if (processed === "" && !required) {
60
+ return null;
61
+ }
62
+ if (transform) {
63
+ processed = transform(processed);
64
+ }
65
+ return processed;
66
+ };
67
+ const baseSchema = isRequired ? z.preprocess(preprocessFn, z.string()) : z.preprocess(preprocessFn, z.string().nullable());
68
+ const schema = baseSchema.superRefine((val, ctx) => {
69
+ if (val === null) return;
70
+ if (isRequired && (val === "" || val === "null" || val === "undefined")) {
71
+ ctx.addIssue({ code: "custom", message: getMessage("required") });
72
+ return;
73
+ }
74
+ if (val === null) return;
75
+ if (!isRequired && val === "") return;
76
+ if (!validateTaiwanBusinessId(val)) {
77
+ ctx.addIssue({ code: "custom", message: getMessage("invalid") });
78
+ return;
79
+ }
80
+ });
81
+ return schema;
82
+ }
83
+
84
+ export {
85
+ validateTaiwanBusinessId,
86
+ twBusinessId
87
+ };