@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.
- package/.github/workflows/ci.yml +24 -0
- package/CLAUDE.md +184 -0
- package/dist/chunk-36NWHESN.js +124 -0
- package/dist/chunk-4LYZAO3P.js +165 -0
- package/dist/chunk-5GAZQDVS.cjs +206 -0
- package/dist/chunk-5LS4DSRQ.cjs +127 -0
- package/dist/chunk-5OGW2ERW.js +181 -0
- package/dist/chunk-5ZEKWPSE.cjs +69 -0
- package/dist/chunk-6OGDPSWT.js +135 -0
- package/dist/chunk-6X22I6NQ.cjs +136 -0
- package/dist/chunk-77KZUPPN.cjs +177 -0
- package/dist/chunk-AANSHH2O.cjs +165 -0
- package/dist/chunk-AI72FMOF.cjs +130 -0
- package/dist/chunk-AWV2IT66.js +146 -0
- package/dist/chunk-B3U5G3AA.js +160 -0
- package/dist/chunk-CFFCBWYL.cjs +99 -0
- package/dist/chunk-DPXRMSB2.js +130 -0
- package/dist/chunk-DRXPGQM6.cjs +135 -0
- package/dist/chunk-EAU42EVH.js +161 -0
- package/dist/chunk-FC6VDOC7.js +206 -0
- package/dist/chunk-FVO4743A.cjs +134 -0
- package/dist/chunk-G6DV7LX7.cjs +161 -0
- package/dist/chunk-I2RJMDXN.js +90 -0
- package/dist/chunk-IJEEM3DI.js +136 -0
- package/dist/chunk-JBNCMS42.cjs +151 -0
- package/dist/chunk-JZ2SHRGZ.js +87 -0
- package/dist/chunk-KARFFIMP.js +696 -0
- package/dist/chunk-LIQSVJLS.js +177 -0
- package/dist/chunk-LKPXHW5N.cjs +181 -0
- package/dist/chunk-MAQRXYE6.js +118 -0
- package/dist/chunk-MCDESS3T.js +69 -0
- package/dist/chunk-MG25BEV4.cjs +160 -0
- package/dist/chunk-NKCYXBGX.js +99 -0
- package/dist/chunk-OEK7QSQP.js +75 -0
- package/dist/chunk-OMFQ7Z63.cjs +696 -0
- package/dist/chunk-OP4KV3BY.cjs +124 -0
- package/dist/chunk-P2NONIMS.js +257 -0
- package/dist/chunk-P364KRO5.js +61 -0
- package/dist/chunk-PGSDXR2I.js +71 -0
- package/dist/chunk-PL2GERLG.cjs +61 -0
- package/dist/chunk-R5G4V7C6.cjs +75 -0
- package/dist/chunk-RKHX3DGH.js +127 -0
- package/dist/chunk-TSHL7ZO2.js +134 -0
- package/dist/chunk-UFNVCUPQ.cjs +301 -0
- package/dist/chunk-VCRKYMJM.js +301 -0
- package/dist/chunk-VDOAPLA6.cjs +257 -0
- package/dist/chunk-VP5CCP5F.cjs +90 -0
- package/dist/chunk-W2EWMV3A.cjs +87 -0
- package/dist/chunk-WWRFBLCR.cjs +146 -0
- package/dist/chunk-YALLOVNO.cjs +118 -0
- package/dist/chunk-YAU6JCYL.cjs +71 -0
- package/dist/chunk-YWV2BBXN.cjs +2526 -0
- package/dist/chunk-ZBOQCXD4.js +2526 -0
- package/dist/chunk-ZFQQXWNB.js +151 -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 +262 -0
- package/dist/common/id.d.ts +262 -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 -3599
- package/dist/index.d.cts +28 -3150
- package/dist/index.d.ts +28 -3150
- package/dist/index.js +135 -3475
- 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 +128 -2
- package/src/config.ts +2 -2
- package/src/i18n/index.ts +18 -2
- package/src/i18n/locales/en-GB.json +247 -0
- package/src/i18n/locales/{en.json → en-US.json} +43 -0
- package/src/i18n/locales/id-ID.json +247 -0
- package/src/i18n/locales/ja-JP.json +247 -0
- package/src/i18n/locales/ko-KR.json +247 -0
- package/src/i18n/locales/ms-MY.json +247 -0
- package/src/i18n/locales/th-TH.json +247 -0
- package/src/i18n/locales/vi-VN.json +247 -0
- package/src/i18n/locales/zh-CN.json +247 -0
- package/src/i18n/locales/zh-TW.json +43 -0
- package/src/index.ts +10 -2
- package/src/validators/common/boolean.ts +1 -1
- 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/date.ts +1 -1
- package/src/validators/common/datetime.ts +1 -1
- package/src/validators/common/email.ts +1 -1
- package/src/validators/common/file.ts +1 -1
- package/src/validators/common/id.ts +1 -1
- package/src/validators/common/ip.ts +210 -0
- package/src/validators/common/number.ts +1 -1
- package/src/validators/common/password.ts +1 -1
- package/src/validators/common/text.ts +1 -1
- package/src/validators/common/time.ts +1 -1
- package/src/validators/common/url.ts +1 -1
- package/src/validators/taiwan/bank-account.ts +176 -0
- package/src/validators/taiwan/business-id.ts +1 -1
- package/src/validators/taiwan/fax.ts +1 -1
- package/src/validators/taiwan/invoice.ts +84 -0
- package/src/validators/taiwan/license-plate.ts +110 -0
- package/src/validators/taiwan/mobile.ts +1 -1
- package/src/validators/taiwan/national-id.ts +1 -1
- package/src/validators/taiwan/passport.ts +103 -0
- package/src/validators/taiwan/postal-code.ts +1 -1
- package/src/validators/taiwan/tel.ts +1 -1
- package/tests/common/boolean.test.ts +6 -6
- 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/date.test.ts +8 -8
- package/tests/common/datetime.test.ts +7 -7
- package/tests/common/email.test.ts +6 -6
- package/tests/common/file.test.ts +6 -6
- package/tests/common/id.test.ts +5 -5
- package/tests/common/ip.test.ts +419 -0
- package/tests/common/number.test.ts +6 -6
- package/tests/common/password.test.ts +5 -5
- package/tests/common/text.test.ts +7 -7
- package/tests/common/time.test.ts +7 -7
- package/tests/common/url.test.ts +10 -10
- package/tests/taiwan/bank-account.test.ts +286 -0
- package/tests/taiwan/business-id.test.ts +4 -4
- package/tests/taiwan/fax.test.ts +7 -7
- package/tests/taiwan/invoice.test.ts +227 -0
- package/tests/taiwan/license-plate.test.ts +280 -0
- package/tests/taiwan/mobile.test.ts +7 -7
- package/tests/taiwan/national-id.test.ts +4 -4
- package/tests/taiwan/passport.test.ts +277 -0
- package/tests/taiwan/postal-code.test.ts +6 -6
- package/tests/taiwan/tel.test.ts +7 -7
- 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,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 };
|