@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,268 @@
1
+ import { ZodString, ZodNullable } from 'zod';
2
+ import { L as Locale } from '../config-CABSSvAp.js';
3
+
4
+ /**
5
+ * @fileoverview Time validator for Zod Kit
6
+ *
7
+ * Provides comprehensive time validation with support for multiple time formats,
8
+ * hour/minute constraints, and advanced time-based validation options.
9
+ *
10
+ * @author Ong Hoe Yuan
11
+ * @version 0.0.5
12
+ */
13
+
14
+ /**
15
+ * Type definition for time validation error messages
16
+ *
17
+ * @interface TimeMessages
18
+ * @property {string} [required] - Message when field is required but empty
19
+ * @property {string} [invalid] - Message when time format is invalid
20
+ * @property {string} [format] - Message when time doesn't match expected format
21
+ * @property {string} [min] - Message when time is before minimum allowed
22
+ * @property {string} [max] - Message when time is after maximum allowed
23
+ * @property {string} [hour] - Message when hour is outside allowed range
24
+ * @property {string} [minute] - Message when minute doesn't match step requirement
25
+ * @property {string} [second] - Message when second doesn't match step requirement
26
+ * @property {string} [includes] - Message when time doesn't contain required string
27
+ * @property {string} [excludes] - Message when time contains forbidden string
28
+ * @property {string} [customRegex] - Message when custom regex validation fails
29
+ * @property {string} [notInWhitelist] - Message when value is not in whitelist
30
+ */
31
+ type TimeMessages = {
32
+ required?: string;
33
+ invalid?: string;
34
+ format?: string;
35
+ min?: string;
36
+ max?: string;
37
+ hour?: string;
38
+ minute?: string;
39
+ second?: string;
40
+ includes?: string;
41
+ excludes?: string;
42
+ customRegex?: string;
43
+ notInWhitelist?: string;
44
+ };
45
+ /**
46
+ * Supported time formats for validation
47
+ *
48
+ * @typedef {string} TimeFormat
49
+ *
50
+ * Available formats:
51
+ * - HH:mm: 24-hour format with leading zeros (14:30, 09:30)
52
+ * - HH:mm:ss: 24-hour format with seconds (14:30:45, 09:30:15)
53
+ * - hh:mm A: 12-hour format with AM/PM (02:30 PM, 09:30 AM)
54
+ * - hh:mm:ss A: 12-hour format with seconds and AM/PM (02:30:45 PM)
55
+ * - H:mm: 24-hour format without leading zeros (14:30, 9:30)
56
+ * - h:mm A: 12-hour format without leading zeros (2:30 PM, 9:30 AM)
57
+ */
58
+ type TimeFormat = "HH:mm" | "HH:mm:ss" | "hh:mm A" | "hh:mm:ss A" | "H:mm" | "h:mm A";
59
+ /**
60
+ * Configuration options for time validation
61
+ *
62
+ * @template IsRequired - Whether the field is required (affects return type)
63
+ *
64
+ * @interface TimeOptions
65
+ * @property {IsRequired} [required=true] - Whether the field is required
66
+ * @property {TimeFormat} [format="HH:mm"] - Expected time format
67
+ * @property {string} [min] - Minimum allowed time (e.g., "09:00")
68
+ * @property {string} [max] - Maximum allowed time (e.g., "17:00")
69
+ * @property {number} [minHour] - Minimum allowed hour (0-23)
70
+ * @property {number} [maxHour] - Maximum allowed hour (0-23)
71
+ * @property {number[]} [allowedHours] - Specific hours that are allowed
72
+ * @property {number} [minuteStep] - Required minute intervals (e.g., 15 for :00, :15, :30, :45)
73
+ * @property {number} [secondStep] - Required second intervals
74
+ * @property {string} [includes] - String that must be included in the time
75
+ * @property {string | string[]} [excludes] - String(s) that must not be included
76
+ * @property {RegExp} [regex] - Custom regex for validation (overrides format validation)
77
+ * @property {"trim" | "trimStart" | "trimEnd" | "none"} [trimMode="trim"] - Whitespace handling
78
+ * @property {"upper" | "lower" | "none"} [casing="none"] - Case transformation
79
+ * @property {string[]} [whitelist] - Specific time strings that are always allowed
80
+ * @property {boolean} [whitelistOnly=false] - If true, only values in whitelist are allowed
81
+ * @property {Function} [transform] - Custom transformation function applied before validation
82
+ * @property {string | null} [defaultValue] - Default value when input is empty
83
+ * @property {Record<Locale, TimeMessages>} [i18n] - Custom error messages for different locales
84
+ */
85
+ type TimeOptions<IsRequired extends boolean = true> = {
86
+ format?: TimeFormat;
87
+ min?: string;
88
+ max?: string;
89
+ minHour?: number;
90
+ maxHour?: number;
91
+ allowedHours?: number[];
92
+ minuteStep?: number;
93
+ secondStep?: number;
94
+ includes?: string;
95
+ excludes?: string | string[];
96
+ regex?: RegExp;
97
+ trimMode?: "trim" | "trimStart" | "trimEnd" | "none";
98
+ casing?: "upper" | "lower" | "none";
99
+ whitelist?: string[];
100
+ whitelistOnly?: boolean;
101
+ transform?: (value: string) => string;
102
+ defaultValue?: IsRequired extends true ? string : string | null;
103
+ i18n?: Partial<Record<Locale, Partial<TimeMessages>>>;
104
+ };
105
+ /**
106
+ * Type alias for time validation schema based on required flag
107
+ *
108
+ * @template IsRequired - Whether the field is required
109
+ * @typedef TimeSchema
110
+ * @description Returns ZodString if required, ZodNullable<ZodString> if optional
111
+ */
112
+ type TimeSchema<IsRequired extends boolean> = IsRequired extends true ? ZodString : ZodNullable<ZodString>;
113
+ /**
114
+ * Regular expression patterns for time format validation
115
+ *
116
+ * @constant {Record<TimeFormat, RegExp>} TIME_PATTERNS
117
+ * @description Maps each supported time format to its corresponding regex pattern
118
+ */
119
+ declare const TIME_PATTERNS: Record<TimeFormat, RegExp>;
120
+ /**
121
+ * Parses a time string to minutes since midnight for comparison
122
+ *
123
+ * @param {string} timeStr - The time string to parse
124
+ * @param {TimeFormat} format - The expected time format
125
+ * @returns {number | null} Minutes since midnight (0-1439) or null if parsing fails
126
+ *
127
+ * @description
128
+ * Converts time strings to minutes since midnight for easy comparison and validation.
129
+ * Handles both 12-hour and 24-hour formats with proper AM/PM conversion.
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * parseTimeToMinutes("14:30", "HH:mm") // 870 (14*60 + 30)
134
+ * parseTimeToMinutes("2:30 PM", "h:mm A") // 870 (14*60 + 30)
135
+ * parseTimeToMinutes("12:00 AM", "hh:mm A") // 0 (midnight)
136
+ * parseTimeToMinutes("12:00 PM", "hh:mm A") // 720 (noon)
137
+ * ```
138
+ */
139
+ declare const parseTimeToMinutes: (timeStr: string, format: TimeFormat) => number | null;
140
+ /**
141
+ * Validates if a time string matches the specified format pattern
142
+ *
143
+ * @param {string} value - The time string to validate
144
+ * @param {TimeFormat} format - The expected time format
145
+ * @returns {boolean} True if the time matches the format pattern
146
+ *
147
+ * @description
148
+ * Performs regex pattern matching to validate time format.
149
+ * Does not validate actual time values (e.g., 25:00 would pass pattern but fail logic).
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * validateTimeFormat("14:30", "HH:mm") // true
154
+ * validateTimeFormat("2:30 PM", "h:mm A") // true
155
+ * validateTimeFormat("25:00", "HH:mm") // true (pattern matches)
156
+ * validateTimeFormat("14:30", "h:mm A") // false (wrong format)
157
+ * ```
158
+ */
159
+ declare const validateTimeFormat: (value: string, format: TimeFormat) => boolean;
160
+ /**
161
+ * Normalizes time to 24-hour format for internal processing
162
+ *
163
+ * @param {string} timeStr - The time string to normalize
164
+ * @param {TimeFormat} format - The current time format
165
+ * @returns {string | null} Normalized time string or null if parsing fails
166
+ *
167
+ * @description
168
+ * Converts time strings to a standardized 24-hour format for consistent processing.
169
+ * Handles AM/PM conversion and leading zero normalization.
170
+ *
171
+ * @example
172
+ * ```typescript
173
+ * normalizeTime("2:30 PM", "h:mm A") // "14:30"
174
+ * normalizeTime("12:00 AM", "hh:mm A") // "00:00"
175
+ * normalizeTime("9:30", "H:mm") // "09:30"
176
+ * normalizeTime("14:30:45", "HH:mm:ss") // "14:30:45"
177
+ * ```
178
+ */
179
+ declare const normalizeTime: (timeStr: string, format: TimeFormat) => string | null;
180
+ /**
181
+ * Creates a Zod schema for time validation with comprehensive options
182
+ *
183
+ * @template IsRequired - Whether the field is required (affects return type)
184
+ * @param {IsRequired} [required=false] - Whether the field is required
185
+ * @param {Omit<ValidatorOptions<IsRequired>, 'required'>} [options] - Configuration options for validation
186
+ * @returns {TimeSchema<IsRequired>} Zod schema for time validation
187
+ *
188
+ * @description
189
+ * Creates a comprehensive time validator that supports multiple time formats,
190
+ * hour/minute constraints, step validation, and extensive customization options.
191
+ *
192
+ * Features:
193
+ * - Multiple time formats (24-hour, 12-hour, with/without seconds)
194
+ * - Time range validation (min/max)
195
+ * - Hour and minute constraints
196
+ * - Step validation (e.g., 15-minute intervals)
197
+ * - Whitelist/blacklist support
198
+ * - Custom regex patterns
199
+ * - String transformation and case handling
200
+ * - Comprehensive internationalization
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * // Basic time validation (24-hour format)
205
+ * const basicSchema = time()
206
+ * basicSchema.parse("14:30") // ✓ Valid
207
+ * basicSchema.parse(null) // ✓ Valid (optional)
208
+ *
209
+ * // Required validation
210
+ * const requiredSchema = parse("14:30") // ✓ Valid
211
+ (true)
212
+ * requiredSchema.parse(null) // ✗ Invalid (required)
213
+ *
214
+ * basicSchema.parse("2:30 PM") // ✗ Invalid (wrong format)
215
+ *
216
+ * // 12-hour format with AM/PM
217
+ * const ampmSchema = time(false, { format: "hh:mm A" })
218
+ * ampmSchema.parse("02:30 PM") // ✓ Valid
219
+ * ampmSchema.parse("14:30") // ✗ Invalid (wrong format)
220
+ *
221
+ * // Business hours validation
222
+ * const businessHours = time({
223
+ * format: "HH:mm",
224
+ * minHour: 9,
225
+ * maxHour: 17,
226
+ * minuteStep: 15 // Only :00, :15, :30, :45
227
+ * })
228
+ * businessHours.parse("09:15") // ✓ Valid
229
+ * businessHours.parse("18:00") // ✗ Invalid (after maxHour)
230
+ * businessHours.parse("09:05") // ✗ Invalid (not 15-minute step)
231
+ *
232
+ * // Time range validation
233
+ * const timeRangeSchema = time(false, {
234
+ * min: "09:00",
235
+ * max: "17:00"
236
+ * })
237
+ * timeRangeSchema.parse("12:30") // ✓ Valid
238
+ * timeRangeSchema.parse("08:00") // ✗ Invalid (before min)
239
+ *
240
+ * // Allowed hours only
241
+ * const specificHours = time({
242
+ * allowedHours: [9, 12, 15, 18]
243
+ * })
244
+ * specificHours.parse("12:30") // ✓ Valid
245
+ * specificHours.parse("11:30") // ✗ Invalid (hour not allowed)
246
+ *
247
+ * // Whitelist specific times
248
+ * const whitelistSchema = time(false, {
249
+ * whitelist: ["09:00", "12:00", "17:00"],
250
+ * whitelistOnly: true
251
+ * })
252
+ * whitelistSchema.parse("12:00") // ✓ Valid (in whitelist)
253
+ * whitelistSchema.parse("13:00") // ✗ Invalid (not in whitelist)
254
+ *
255
+ * // Optional with default
256
+ * const optionalSchema = time(false, {
257
+ * defaultValue: "09:00"
258
+ * })
259
+ * optionalSchema.parse("") // ✓ Valid (returns "09:00")
260
+ * ```
261
+ *
262
+ * @throws {z.ZodError} When validation fails with specific error messages
263
+ * @see {@link TimeOptions} for all available configuration options
264
+ * @see {@link TimeFormat} for supported time formats
265
+ */
266
+ declare function time<IsRequired extends boolean = false>(required?: IsRequired, options?: Omit<TimeOptions<IsRequired>, 'required'>): TimeSchema<IsRequired>;
267
+
268
+ export { TIME_PATTERNS, type TimeFormat, type TimeMessages, type TimeOptions, type TimeSchema, normalizeTime, parseTimeToMinutes, time, validateTimeFormat };
@@ -0,0 +1,15 @@
1
+ import {
2
+ TIME_PATTERNS,
3
+ normalizeTime,
4
+ parseTimeToMinutes,
5
+ time,
6
+ validateTimeFormat
7
+ } from "../chunk-P2NONIMS.js";
8
+ import "../chunk-ZBOQCXD4.js";
9
+ export {
10
+ TIME_PATTERNS,
11
+ normalizeTime,
12
+ parseTimeToMinutes,
13
+ time,
14
+ validateTimeFormat
15
+ };
@@ -0,0 +1,7 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+ var _chunkJBNCMS42cjs = require('../chunk-JBNCMS42.cjs');
4
+ require('../chunk-YWV2BBXN.cjs');
5
+
6
+
7
+ exports.url = _chunkJBNCMS42cjs.url;
@@ -0,0 +1,196 @@
1
+ import { ZodString, ZodNullable } from 'zod';
2
+ import { L as Locale } from '../config-CABSSvAp.cjs';
3
+
4
+ /**
5
+ * @fileoverview URL validator for Zod Kit
6
+ *
7
+ * Provides comprehensive URL validation with protocol filtering, domain control,
8
+ * port validation, path constraints, and localhost handling.
9
+ *
10
+ * @author Ong Hoe Yuan
11
+ * @version 0.0.5
12
+ */
13
+
14
+ /**
15
+ * Type definition for URL validation error messages
16
+ *
17
+ * @interface UrlMessages
18
+ * @property {string} [required] - Message when field is required but empty
19
+ * @property {string} [invalid] - Message when URL format is invalid
20
+ * @property {string} [min] - Message when URL is too short
21
+ * @property {string} [max] - Message when URL is too long
22
+ * @property {string} [includes] - Message when URL doesn't contain required string
23
+ * @property {string} [excludes] - Message when URL contains forbidden string
24
+ * @property {string} [protocol] - Message when protocol is not allowed
25
+ * @property {string} [domain] - Message when domain is not allowed
26
+ * @property {string} [domainBlacklist] - Message when domain is blacklisted
27
+ * @property {string} [port] - Message when port is not allowed
28
+ * @property {string} [pathStartsWith] - Message when path doesn't start with required string
29
+ * @property {string} [pathEndsWith] - Message when path doesn't end with required string
30
+ * @property {string} [hasQuery] - Message when query parameters are required
31
+ * @property {string} [noQuery] - Message when query parameters are forbidden
32
+ * @property {string} [hasFragment] - Message when fragment is required
33
+ * @property {string} [noFragment] - Message when fragment is forbidden
34
+ * @property {string} [localhost] - Message when localhost is forbidden
35
+ * @property {string} [noLocalhost] - Message when localhost is required
36
+ */
37
+ type UrlMessages = {
38
+ required?: string;
39
+ invalid?: string;
40
+ min?: string;
41
+ max?: string;
42
+ includes?: string;
43
+ excludes?: string;
44
+ protocol?: string;
45
+ domain?: string;
46
+ domainBlacklist?: string;
47
+ port?: string;
48
+ pathStartsWith?: string;
49
+ pathEndsWith?: string;
50
+ hasQuery?: string;
51
+ noQuery?: string;
52
+ hasFragment?: string;
53
+ noFragment?: string;
54
+ localhost?: string;
55
+ noLocalhost?: string;
56
+ };
57
+ /**
58
+ * Configuration options for URL validation
59
+ *
60
+ * @template IsRequired - Whether the field is required (affects return type)
61
+ *
62
+ * @interface UrlOptions
63
+ * @property {IsRequired} [required=true] - Whether the field is required
64
+ * @property {number} [min] - Minimum length of URL
65
+ * @property {number} [max] - Maximum length of URL
66
+ * @property {string} [includes] - String that must be included in URL
67
+ * @property {string | string[]} [excludes] - String(s) that must not be included
68
+ * @property {string[]} [protocols] - Allowed protocols (e.g., ["https", "http"])
69
+ * @property {string[]} [allowedDomains] - Domains that are allowed
70
+ * @property {string[]} [blockedDomains] - Domains that are blocked
71
+ * @property {number[]} [allowedPorts] - Ports that are allowed
72
+ * @property {number[]} [blockedPorts] - Ports that are blocked
73
+ * @property {string} [pathStartsWith] - Path must start with this string
74
+ * @property {string} [pathEndsWith] - Path must end with this string
75
+ * @property {boolean} [mustHaveQuery] - Whether URL must have query parameters
76
+ * @property {boolean} [mustNotHaveQuery] - Whether URL must not have query parameters
77
+ * @property {boolean} [mustHaveFragment] - Whether URL must have fragment
78
+ * @property {boolean} [mustNotHaveFragment] - Whether URL must not have fragment
79
+ * @property {boolean} [allowLocalhost=true] - Whether to allow localhost URLs
80
+ * @property {boolean} [blockLocalhost] - Whether to explicitly block localhost URLs
81
+ * @property {Function} [transform] - Custom transformation function for URL strings
82
+ * @property {string | null} [defaultValue] - Default value when input is empty
83
+ * @property {Record<Locale, UrlMessages>} [i18n] - Custom error messages for different locales
84
+ */
85
+ type UrlOptions<IsRequired extends boolean = true> = {
86
+ min?: number;
87
+ max?: number;
88
+ includes?: string;
89
+ excludes?: string | string[];
90
+ protocols?: string[];
91
+ allowedDomains?: string[];
92
+ blockedDomains?: string[];
93
+ allowedPorts?: number[];
94
+ blockedPorts?: number[];
95
+ pathStartsWith?: string;
96
+ pathEndsWith?: string;
97
+ mustHaveQuery?: boolean;
98
+ mustNotHaveQuery?: boolean;
99
+ mustHaveFragment?: boolean;
100
+ mustNotHaveFragment?: boolean;
101
+ allowLocalhost?: boolean;
102
+ blockLocalhost?: boolean;
103
+ transform?: (value: string) => string;
104
+ defaultValue?: IsRequired extends true ? string : string | null;
105
+ i18n?: Partial<Record<Locale, Partial<UrlMessages>>>;
106
+ };
107
+ /**
108
+ * Type alias for URL validation schema based on required flag
109
+ *
110
+ * @template IsRequired - Whether the field is required
111
+ * @typedef UrlSchema
112
+ * @description Returns ZodString if required, ZodNullable<ZodString> if optional
113
+ */
114
+ type UrlSchema<IsRequired extends boolean> = IsRequired extends true ? ZodString : ZodNullable<ZodString>;
115
+ /**
116
+ * Creates a Zod schema for URL validation with comprehensive constraints
117
+ *
118
+ * @template IsRequired - Whether the field is required (affects return type)
119
+ * @param {IsRequired} [required=false] - Whether the field is required
120
+ * @param {Omit<ValidatorOptions<IsRequired>, 'required'>} [options] - Configuration options for validation
121
+ * @returns {UrlSchema<IsRequired>} Zod schema for URL validation
122
+ *
123
+ * @description
124
+ * Creates a comprehensive URL validator with protocol filtering, domain control,
125
+ * port validation, path constraints, and localhost handling.
126
+ *
127
+ * Features:
128
+ * - RFC-compliant URL format validation
129
+ * - Protocol whitelist/blacklist (http, https, ftp, etc.)
130
+ * - Domain whitelist/blacklist with subdomain support
131
+ * - Port validation and filtering
132
+ * - Path prefix/suffix validation
133
+ * - Query parameter requirements
134
+ * - Fragment requirements
135
+ * - Localhost detection and control
136
+ * - Length validation
137
+ * - Content inclusion/exclusion
138
+ * - Custom transformation functions
139
+ * - Comprehensive internationalization
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * // Basic URL validation
144
+ * const basicSchema = url() // optional by default
145
+ * basicSchema.parse("https://example.com") // ✓ Valid
146
+ * basicSchema.parse(null) // ✓ Valid (optional)
147
+ *
148
+ * // Required validation
149
+ * const requiredSchema = parse("https://example.com") // ✓ Valid
150
+ (true)
151
+ * requiredSchema.parse(null) // ✗ Invalid (required)
152
+ *
153
+ *
154
+ * // HTTPS only
155
+ * const httpsSchema = url(false, { protocols: ["https"] })
156
+ * httpsSchema.parse("https://example.com") // ✓ Valid
157
+ * httpsSchema.parse("http://example.com") // ✗ Invalid
158
+ *
159
+ * // Domain restriction
160
+ * const domainSchema = url(false, {
161
+ * allowedDomains: ["company.com", "trusted.org"]
162
+ * })
163
+ * domainSchema.parse("https://app.company.com") // ✓ Valid (subdomain)
164
+ * domainSchema.parse("https://example.com") // ✗ Invalid
165
+ *
166
+ * // Block localhost
167
+ * const noLocalhostSchema = url(false, { blockLocalhost: true })
168
+ * noLocalhostSchema.parse("https://example.com") // ✓ Valid
169
+ * noLocalhostSchema.parse("http://localhost:3000") // ✗ Invalid
170
+ *
171
+ * // API endpoints with path requirements
172
+ * const apiSchema = url(false, {
173
+ * pathStartsWith: "/api/",
174
+ * mustHaveQuery: true
175
+ * })
176
+ * apiSchema.parse("https://api.com/api/users?page=1") // ✓ Valid
177
+ *
178
+ * // Port restrictions
179
+ * const portSchema = url(false, {
180
+ * allowedPorts: [80, 443, 8080]
181
+ * })
182
+ * portSchema.parse("https://example.com:443") // ✓ Valid
183
+ * portSchema.parse("https://example.com:3000") // ✗ Invalid
184
+ *
185
+ * // Optional with default
186
+ * const optionalSchema = url(false, {
187
+ * defaultValue: null
188
+ * })
189
+ * ```
190
+ *
191
+ * @throws {z.ZodError} When validation fails with specific error messages
192
+ * @see {@link UrlOptions} for all available configuration options
193
+ */
194
+ declare function url<IsRequired extends boolean = false>(required?: IsRequired, options?: Omit<UrlOptions<IsRequired>, 'required'>): UrlSchema<IsRequired>;
195
+
196
+ export { type UrlMessages, type UrlOptions, type UrlSchema, url };
@@ -0,0 +1,196 @@
1
+ import { ZodString, ZodNullable } from 'zod';
2
+ import { L as Locale } from '../config-CABSSvAp.js';
3
+
4
+ /**
5
+ * @fileoverview URL validator for Zod Kit
6
+ *
7
+ * Provides comprehensive URL validation with protocol filtering, domain control,
8
+ * port validation, path constraints, and localhost handling.
9
+ *
10
+ * @author Ong Hoe Yuan
11
+ * @version 0.0.5
12
+ */
13
+
14
+ /**
15
+ * Type definition for URL validation error messages
16
+ *
17
+ * @interface UrlMessages
18
+ * @property {string} [required] - Message when field is required but empty
19
+ * @property {string} [invalid] - Message when URL format is invalid
20
+ * @property {string} [min] - Message when URL is too short
21
+ * @property {string} [max] - Message when URL is too long
22
+ * @property {string} [includes] - Message when URL doesn't contain required string
23
+ * @property {string} [excludes] - Message when URL contains forbidden string
24
+ * @property {string} [protocol] - Message when protocol is not allowed
25
+ * @property {string} [domain] - Message when domain is not allowed
26
+ * @property {string} [domainBlacklist] - Message when domain is blacklisted
27
+ * @property {string} [port] - Message when port is not allowed
28
+ * @property {string} [pathStartsWith] - Message when path doesn't start with required string
29
+ * @property {string} [pathEndsWith] - Message when path doesn't end with required string
30
+ * @property {string} [hasQuery] - Message when query parameters are required
31
+ * @property {string} [noQuery] - Message when query parameters are forbidden
32
+ * @property {string} [hasFragment] - Message when fragment is required
33
+ * @property {string} [noFragment] - Message when fragment is forbidden
34
+ * @property {string} [localhost] - Message when localhost is forbidden
35
+ * @property {string} [noLocalhost] - Message when localhost is required
36
+ */
37
+ type UrlMessages = {
38
+ required?: string;
39
+ invalid?: string;
40
+ min?: string;
41
+ max?: string;
42
+ includes?: string;
43
+ excludes?: string;
44
+ protocol?: string;
45
+ domain?: string;
46
+ domainBlacklist?: string;
47
+ port?: string;
48
+ pathStartsWith?: string;
49
+ pathEndsWith?: string;
50
+ hasQuery?: string;
51
+ noQuery?: string;
52
+ hasFragment?: string;
53
+ noFragment?: string;
54
+ localhost?: string;
55
+ noLocalhost?: string;
56
+ };
57
+ /**
58
+ * Configuration options for URL validation
59
+ *
60
+ * @template IsRequired - Whether the field is required (affects return type)
61
+ *
62
+ * @interface UrlOptions
63
+ * @property {IsRequired} [required=true] - Whether the field is required
64
+ * @property {number} [min] - Minimum length of URL
65
+ * @property {number} [max] - Maximum length of URL
66
+ * @property {string} [includes] - String that must be included in URL
67
+ * @property {string | string[]} [excludes] - String(s) that must not be included
68
+ * @property {string[]} [protocols] - Allowed protocols (e.g., ["https", "http"])
69
+ * @property {string[]} [allowedDomains] - Domains that are allowed
70
+ * @property {string[]} [blockedDomains] - Domains that are blocked
71
+ * @property {number[]} [allowedPorts] - Ports that are allowed
72
+ * @property {number[]} [blockedPorts] - Ports that are blocked
73
+ * @property {string} [pathStartsWith] - Path must start with this string
74
+ * @property {string} [pathEndsWith] - Path must end with this string
75
+ * @property {boolean} [mustHaveQuery] - Whether URL must have query parameters
76
+ * @property {boolean} [mustNotHaveQuery] - Whether URL must not have query parameters
77
+ * @property {boolean} [mustHaveFragment] - Whether URL must have fragment
78
+ * @property {boolean} [mustNotHaveFragment] - Whether URL must not have fragment
79
+ * @property {boolean} [allowLocalhost=true] - Whether to allow localhost URLs
80
+ * @property {boolean} [blockLocalhost] - Whether to explicitly block localhost URLs
81
+ * @property {Function} [transform] - Custom transformation function for URL strings
82
+ * @property {string | null} [defaultValue] - Default value when input is empty
83
+ * @property {Record<Locale, UrlMessages>} [i18n] - Custom error messages for different locales
84
+ */
85
+ type UrlOptions<IsRequired extends boolean = true> = {
86
+ min?: number;
87
+ max?: number;
88
+ includes?: string;
89
+ excludes?: string | string[];
90
+ protocols?: string[];
91
+ allowedDomains?: string[];
92
+ blockedDomains?: string[];
93
+ allowedPorts?: number[];
94
+ blockedPorts?: number[];
95
+ pathStartsWith?: string;
96
+ pathEndsWith?: string;
97
+ mustHaveQuery?: boolean;
98
+ mustNotHaveQuery?: boolean;
99
+ mustHaveFragment?: boolean;
100
+ mustNotHaveFragment?: boolean;
101
+ allowLocalhost?: boolean;
102
+ blockLocalhost?: boolean;
103
+ transform?: (value: string) => string;
104
+ defaultValue?: IsRequired extends true ? string : string | null;
105
+ i18n?: Partial<Record<Locale, Partial<UrlMessages>>>;
106
+ };
107
+ /**
108
+ * Type alias for URL validation schema based on required flag
109
+ *
110
+ * @template IsRequired - Whether the field is required
111
+ * @typedef UrlSchema
112
+ * @description Returns ZodString if required, ZodNullable<ZodString> if optional
113
+ */
114
+ type UrlSchema<IsRequired extends boolean> = IsRequired extends true ? ZodString : ZodNullable<ZodString>;
115
+ /**
116
+ * Creates a Zod schema for URL validation with comprehensive constraints
117
+ *
118
+ * @template IsRequired - Whether the field is required (affects return type)
119
+ * @param {IsRequired} [required=false] - Whether the field is required
120
+ * @param {Omit<ValidatorOptions<IsRequired>, 'required'>} [options] - Configuration options for validation
121
+ * @returns {UrlSchema<IsRequired>} Zod schema for URL validation
122
+ *
123
+ * @description
124
+ * Creates a comprehensive URL validator with protocol filtering, domain control,
125
+ * port validation, path constraints, and localhost handling.
126
+ *
127
+ * Features:
128
+ * - RFC-compliant URL format validation
129
+ * - Protocol whitelist/blacklist (http, https, ftp, etc.)
130
+ * - Domain whitelist/blacklist with subdomain support
131
+ * - Port validation and filtering
132
+ * - Path prefix/suffix validation
133
+ * - Query parameter requirements
134
+ * - Fragment requirements
135
+ * - Localhost detection and control
136
+ * - Length validation
137
+ * - Content inclusion/exclusion
138
+ * - Custom transformation functions
139
+ * - Comprehensive internationalization
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * // Basic URL validation
144
+ * const basicSchema = url() // optional by default
145
+ * basicSchema.parse("https://example.com") // ✓ Valid
146
+ * basicSchema.parse(null) // ✓ Valid (optional)
147
+ *
148
+ * // Required validation
149
+ * const requiredSchema = parse("https://example.com") // ✓ Valid
150
+ (true)
151
+ * requiredSchema.parse(null) // ✗ Invalid (required)
152
+ *
153
+ *
154
+ * // HTTPS only
155
+ * const httpsSchema = url(false, { protocols: ["https"] })
156
+ * httpsSchema.parse("https://example.com") // ✓ Valid
157
+ * httpsSchema.parse("http://example.com") // ✗ Invalid
158
+ *
159
+ * // Domain restriction
160
+ * const domainSchema = url(false, {
161
+ * allowedDomains: ["company.com", "trusted.org"]
162
+ * })
163
+ * domainSchema.parse("https://app.company.com") // ✓ Valid (subdomain)
164
+ * domainSchema.parse("https://example.com") // ✗ Invalid
165
+ *
166
+ * // Block localhost
167
+ * const noLocalhostSchema = url(false, { blockLocalhost: true })
168
+ * noLocalhostSchema.parse("https://example.com") // ✓ Valid
169
+ * noLocalhostSchema.parse("http://localhost:3000") // ✗ Invalid
170
+ *
171
+ * // API endpoints with path requirements
172
+ * const apiSchema = url(false, {
173
+ * pathStartsWith: "/api/",
174
+ * mustHaveQuery: true
175
+ * })
176
+ * apiSchema.parse("https://api.com/api/users?page=1") // ✓ Valid
177
+ *
178
+ * // Port restrictions
179
+ * const portSchema = url(false, {
180
+ * allowedPorts: [80, 443, 8080]
181
+ * })
182
+ * portSchema.parse("https://example.com:443") // ✓ Valid
183
+ * portSchema.parse("https://example.com:3000") // ✗ Invalid
184
+ *
185
+ * // Optional with default
186
+ * const optionalSchema = url(false, {
187
+ * defaultValue: null
188
+ * })
189
+ * ```
190
+ *
191
+ * @throws {z.ZodError} When validation fails with specific error messages
192
+ * @see {@link UrlOptions} for all available configuration options
193
+ */
194
+ declare function url<IsRequired extends boolean = false>(required?: IsRequired, options?: Omit<UrlOptions<IsRequired>, 'required'>): UrlSchema<IsRequired>;
195
+
196
+ export { type UrlMessages, type UrlOptions, type UrlSchema, url };