@hy_ong/zod-kit 0.2.0 → 0.2.2
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/.github/workflows/ci.yml +24 -0
- package/CLAUDE.md +64 -22
- package/dist/chunk-2SWEVDFZ.js +134 -0
- package/dist/chunk-32JI34CV.cjs +146 -0
- package/dist/chunk-42C5OHRK.js +71 -0
- package/dist/chunk-46VAH2BJ.js +160 -0
- package/dist/chunk-5JGTDL3Y.js +87 -0
- package/dist/chunk-5LEXCVLX.js +257 -0
- package/dist/chunk-6AAP4LPF.js +2606 -0
- package/dist/chunk-B4EZYZOK.cjs +215 -0
- package/dist/chunk-COYKBWTI.js +161 -0
- package/dist/chunk-DFJZ3NS2.cjs +151 -0
- package/dist/chunk-EDHT4LPO.js +118 -0
- package/dist/chunk-EGHL277K.cjs +165 -0
- package/dist/chunk-ERH4NIMU.cjs +69 -0
- package/dist/chunk-FM3EZ72O.js +165 -0
- package/dist/chunk-GJIRDBZJ.cjs +90 -0
- package/dist/chunk-H2XTEM4M.js +696 -0
- package/dist/chunk-HMSM6FFA.cjs +181 -0
- package/dist/chunk-HTEHINI7.cjs +177 -0
- package/dist/chunk-JOLSGZGN.cjs +696 -0
- package/dist/chunk-JXY7APBU.js +69 -0
- package/dist/chunk-K2UOY6TB.js +136 -0
- package/dist/chunk-KFOHKTFD.js +61 -0
- package/dist/chunk-L4HSIKTU.cjs +135 -0
- package/dist/chunk-LH7ZB4BK.js +124 -0
- package/dist/chunk-LL4ZWLGO.js +90 -0
- package/dist/chunk-M6MTP3NY.cjs +99 -0
- package/dist/chunk-MHJFYYGV.js +215 -0
- package/dist/chunk-MINMXGW3.js +135 -0
- package/dist/chunk-MM7IL2RG.js +181 -0
- package/dist/chunk-OPQJWHXN.cjs +301 -0
- package/dist/chunk-ORFHDJII.cjs +136 -0
- package/dist/chunk-ORVV4MCF.cjs +87 -0
- package/dist/chunk-QICQ6YEY.js +75 -0
- package/dist/chunk-RKUQREMW.js +127 -0
- package/dist/chunk-RO47DKQG.js +146 -0
- package/dist/chunk-RRPXIRTQ.cjs +257 -0
- package/dist/chunk-RYFG2GKM.cjs +118 -0
- package/dist/chunk-STNHTRG7.cjs +124 -0
- package/dist/chunk-TFGS34VD.cjs +71 -0
- package/dist/chunk-TQXDUMML.cjs +61 -0
- package/dist/chunk-UBK3VCVH.cjs +134 -0
- package/dist/chunk-UCOXAZJF.cjs +2606 -0
- package/dist/chunk-UQZKFAFX.js +130 -0
- package/dist/chunk-VB2KV2ZM.cjs +130 -0
- package/dist/chunk-WABKPFPK.js +151 -0
- package/dist/chunk-WDI4QJMQ.js +177 -0
- package/dist/chunk-YDH3L27K.cjs +127 -0
- package/dist/chunk-YIM3D2AD.js +99 -0
- package/dist/chunk-YPSEIDUR.cjs +160 -0
- package/dist/chunk-ZNJLWJX3.cjs +75 -0
- package/dist/chunk-ZTFCJCPO.cjs +161 -0
- package/dist/chunk-ZXUMK2RR.js +301 -0
- package/dist/common/boolean.cjs +7 -0
- package/dist/common/boolean.d.cts +119 -0
- package/dist/common/boolean.d.ts +119 -0
- package/dist/common/boolean.js +7 -0
- package/dist/common/color.cjs +9 -0
- package/dist/common/color.d.cts +26 -0
- package/dist/common/color.d.ts +26 -0
- package/dist/common/color.js +9 -0
- package/dist/common/coordinate.cjs +11 -0
- package/dist/common/coordinate.d.cts +23 -0
- package/dist/common/coordinate.d.ts +23 -0
- package/dist/common/coordinate.js +11 -0
- package/dist/common/credit-card.cjs +11 -0
- package/dist/common/credit-card.d.cts +22 -0
- package/dist/common/credit-card.d.ts +22 -0
- package/dist/common/credit-card.js +11 -0
- package/dist/common/date.cjs +7 -0
- package/dist/common/date.d.cts +174 -0
- package/dist/common/date.d.ts +174 -0
- package/dist/common/date.js +7 -0
- package/dist/common/datetime.cjs +15 -0
- package/dist/common/datetime.d.cts +301 -0
- package/dist/common/datetime.d.ts +301 -0
- package/dist/common/datetime.js +15 -0
- package/dist/common/email.cjs +7 -0
- package/dist/common/email.d.cts +149 -0
- package/dist/common/email.d.ts +149 -0
- package/dist/common/email.js +7 -0
- package/dist/common/file.cjs +7 -0
- package/dist/common/file.d.cts +178 -0
- package/dist/common/file.d.ts +178 -0
- package/dist/common/file.js +7 -0
- package/dist/common/id.cjs +13 -0
- package/dist/common/id.d.cts +288 -0
- package/dist/common/id.d.ts +288 -0
- package/dist/common/id.js +13 -0
- package/dist/common/ip.cjs +11 -0
- package/dist/common/ip.d.cts +25 -0
- package/dist/common/ip.d.ts +25 -0
- package/dist/common/ip.js +11 -0
- package/dist/common/number.cjs +7 -0
- package/dist/common/number.d.cts +167 -0
- package/dist/common/number.d.ts +167 -0
- package/dist/common/number.js +7 -0
- package/dist/common/password.cjs +7 -0
- package/dist/common/password.d.cts +192 -0
- package/dist/common/password.d.ts +192 -0
- package/dist/common/password.js +7 -0
- package/dist/common/text.cjs +7 -0
- package/dist/common/text.d.cts +156 -0
- package/dist/common/text.d.ts +156 -0
- package/dist/common/text.js +7 -0
- package/dist/common/time.cjs +15 -0
- package/dist/common/time.d.cts +268 -0
- package/dist/common/time.d.ts +268 -0
- package/dist/common/time.js +15 -0
- package/dist/common/url.cjs +7 -0
- package/dist/common/url.d.cts +196 -0
- package/dist/common/url.d.ts +196 -0
- package/dist/common/url.js +7 -0
- package/dist/config-CABSSvAp.d.cts +5 -0
- package/dist/config-CABSSvAp.d.ts +5 -0
- package/dist/index.cjs +180 -5255
- package/dist/index.d.cts +28 -3150
- package/dist/index.d.ts +28 -3150
- package/dist/index.js +135 -5131
- package/dist/taiwan/bank-account.cjs +11 -0
- package/dist/taiwan/bank-account.d.cts +22 -0
- package/dist/taiwan/bank-account.d.ts +22 -0
- package/dist/taiwan/bank-account.js +11 -0
- package/dist/taiwan/business-id.cjs +9 -0
- package/dist/taiwan/business-id.d.cts +133 -0
- package/dist/taiwan/business-id.d.ts +133 -0
- package/dist/taiwan/business-id.js +9 -0
- package/dist/taiwan/fax.cjs +9 -0
- package/dist/taiwan/fax.d.cts +157 -0
- package/dist/taiwan/fax.d.ts +157 -0
- package/dist/taiwan/fax.js +9 -0
- package/dist/taiwan/invoice.cjs +9 -0
- package/dist/taiwan/invoice.d.cts +17 -0
- package/dist/taiwan/invoice.d.ts +17 -0
- package/dist/taiwan/invoice.js +9 -0
- package/dist/taiwan/license-plate.cjs +9 -0
- package/dist/taiwan/license-plate.d.cts +19 -0
- package/dist/taiwan/license-plate.d.ts +19 -0
- package/dist/taiwan/license-plate.js +9 -0
- package/dist/taiwan/mobile.cjs +9 -0
- package/dist/taiwan/mobile.d.cts +146 -0
- package/dist/taiwan/mobile.d.ts +146 -0
- package/dist/taiwan/mobile.js +9 -0
- package/dist/taiwan/national-id.cjs +15 -0
- package/dist/taiwan/national-id.d.cts +214 -0
- package/dist/taiwan/national-id.d.ts +214 -0
- package/dist/taiwan/national-id.js +15 -0
- package/dist/taiwan/passport.cjs +9 -0
- package/dist/taiwan/passport.d.cts +19 -0
- package/dist/taiwan/passport.d.ts +19 -0
- package/dist/taiwan/passport.js +9 -0
- package/dist/taiwan/postal-code.cjs +17 -0
- package/dist/taiwan/postal-code.d.cts +237 -0
- package/dist/taiwan/postal-code.d.ts +237 -0
- package/dist/taiwan/postal-code.js +17 -0
- package/dist/taiwan/tel.cjs +9 -0
- package/dist/taiwan/tel.d.cts +162 -0
- package/dist/taiwan/tel.d.ts +162 -0
- package/dist/taiwan/tel.js +9 -0
- package/package.json +132 -6
- package/src/i18n/locales/en-GB.json +51 -0
- package/src/i18n/locales/en-US.json +52 -1
- package/src/i18n/locales/id-ID.json +51 -0
- package/src/i18n/locales/ja-JP.json +51 -0
- package/src/i18n/locales/ko-KR.json +51 -0
- package/src/i18n/locales/ms-MY.json +51 -0
- package/src/i18n/locales/th-TH.json +51 -0
- package/src/i18n/locales/vi-VN.json +51 -0
- package/src/i18n/locales/zh-CN.json +51 -0
- package/src/i18n/locales/zh-TW.json +51 -0
- package/src/index.ts +10 -2
- package/src/validators/common/color.ts +192 -0
- package/src/validators/common/coordinate.ts +159 -0
- package/src/validators/common/credit-card.ts +134 -0
- package/src/validators/common/id.ts +45 -3
- package/src/validators/common/ip.ts +210 -0
- package/src/validators/taiwan/bank-account.ts +176 -0
- package/src/validators/taiwan/invoice.ts +84 -0
- package/src/validators/taiwan/license-plate.ts +110 -0
- package/src/validators/taiwan/passport.ts +103 -0
- package/tests/common/color.test.ts +587 -0
- package/tests/common/coordinate.test.ts +345 -0
- package/tests/common/credit-card.test.ts +378 -0
- package/tests/common/id.test.ts +68 -3
- package/tests/common/ip.test.ts +419 -0
- package/tests/taiwan/bank-account.test.ts +286 -0
- package/tests/taiwan/invoice.test.ts +227 -0
- package/tests/taiwan/license-plate.test.ts +280 -0
- package/tests/taiwan/passport.test.ts +277 -0
- package/tsup.config.ts +36 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { ZodString, ZodNullable } from 'zod';
|
|
2
|
+
import { L as Locale } from '../config-CABSSvAp.cjs';
|
|
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,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-5LEXCVLX.js";
|
|
8
|
+
import "../chunk-6AAP4LPF.js";
|
|
9
|
+
export {
|
|
10
|
+
TIME_PATTERNS,
|
|
11
|
+
normalizeTime,
|
|
12
|
+
parseTimeToMinutes,
|
|
13
|
+
time,
|
|
14
|
+
validateTimeFormat
|
|
15
|
+
};
|