@hy_ong/zod-kit 0.0.5 → 0.0.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hy_ong/zod-kit",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "Zod Kit",
5
5
  "keywords": [
6
6
  "hy_ong",
@@ -112,6 +112,56 @@
112
112
  "notToday": "Date must not be today",
113
113
  "weekday": "Date must be a weekday (Monday-Friday)",
114
114
  "weekend": "Date must be a weekend (Saturday-Sunday)"
115
+ },
116
+ "time": {
117
+ "required": "Required",
118
+ "invalid": "Invalid time format",
119
+ "format": "Must be in ${format} format",
120
+ "min": "Time must be after ${min}",
121
+ "max": "Time must be before ${max}",
122
+ "hour": "Hour must be between ${minHour} and ${maxHour}",
123
+ "minute": "Minutes must be in ${minuteStep}-minute intervals",
124
+ "second": "Seconds must be in ${secondStep}-second intervals",
125
+ "includes": "Must include ${includes}",
126
+ "excludes": "Must not contain ${excludes}",
127
+ "customRegex": "Invalid time format",
128
+ "notInWhitelist": "Time is not in the allowed list"
129
+ },
130
+ "datetime": {
131
+ "required": "Required",
132
+ "invalid": "Invalid datetime format",
133
+ "format": "Must be in ${format} format",
134
+ "min": "DateTime must be after ${min}",
135
+ "max": "DateTime must be before ${max}",
136
+ "hour": "Hour must be between ${minHour} and ${maxHour}",
137
+ "minute": "Minutes must be in ${minuteStep}-minute intervals",
138
+ "includes": "Must include ${includes}",
139
+ "excludes": "Must not contain ${excludes}",
140
+ "past": "DateTime must be in the past",
141
+ "future": "DateTime must be in the future",
142
+ "today": "DateTime must be today",
143
+ "notToday": "DateTime must not be today",
144
+ "weekday": "DateTime must be a weekday (Monday-Friday)",
145
+ "weekend": "DateTime must be a weekend (Saturday-Sunday)",
146
+ "customRegex": "Invalid datetime format",
147
+ "notInWhitelist": "DateTime is not in the allowed list"
148
+ },
149
+ "file": {
150
+ "required": "Required",
151
+ "invalid": "Invalid file format",
152
+ "size": "File size must not exceed ${size}",
153
+ "minSize": "File size must be at least ${minSize}",
154
+ "maxSize": "File size must not exceed ${maxSize}",
155
+ "type": "File type must be one of: ${type}",
156
+ "extension": "File extension must be one of: ${extension}",
157
+ "extensionBlacklist": "File extension ${extension} is not allowed",
158
+ "name": "File name must match pattern ${pattern}",
159
+ "nameBlacklist": "File name must not match pattern ${pattern}",
160
+ "imageOnly": "Only image files are allowed",
161
+ "documentOnly": "Only document files are allowed",
162
+ "videoOnly": "Only video files are allowed",
163
+ "audioOnly": "Only audio files are allowed",
164
+ "archiveOnly": "Only archive files are allowed"
115
165
  }
116
166
  },
117
167
  "taiwan": {
@@ -137,6 +187,18 @@
137
187
  "required": "Required",
138
188
  "invalid": "Invalid Taiwan fax format",
139
189
  "notInWhitelist": "Not in allowed fax list"
190
+ },
191
+ "postalCode": {
192
+ "required": "Required",
193
+ "invalid": "Invalid Taiwan postal code",
194
+ "invalidFormat": "Invalid postal code format",
195
+ "invalidRange": "Postal code is outside valid range",
196
+ "legacy5DigitWarning": "5-digit postal codes are legacy format, consider using 6-digit format",
197
+ "format3Only": "Only 3-digit postal codes are allowed",
198
+ "format5Only": "Only 5-digit postal codes are allowed",
199
+ "format6Only": "Only 6-digit postal codes are allowed",
200
+ "invalidSuffix": "Invalid postal code suffix - must be 01-99 for 5-digit or 001-999 for 6-digit codes",
201
+ "deprecated5Digit": "5-digit postal codes are deprecated and no longer supported"
140
202
  }
141
203
  }
142
204
  }
@@ -112,6 +112,56 @@
112
112
  "notToday": "不得為今天",
113
113
  "weekday": "必須為工作日(週一至週五)",
114
114
  "weekend": "必須為週末(週六至週日)"
115
+ },
116
+ "time": {
117
+ "required": "必填",
118
+ "invalid": "無效的時間格式",
119
+ "format": "必須為 ${format} 格式",
120
+ "min": "時間不得早於 ${min}",
121
+ "max": "時間不得晚於 ${max}",
122
+ "hour": "小時必須介於 ${minHour} 與 ${maxHour} 之間",
123
+ "minute": "分鐘必須為 ${minuteStep} 分鐘間隔",
124
+ "second": "秒數必須為 ${secondStep} 秒間隔",
125
+ "includes": "必須包含「${includes}」",
126
+ "excludes": "不得包含「${excludes}」",
127
+ "customRegex": "無效的時間格式",
128
+ "notInWhitelist": "時間不在允許清單中"
129
+ },
130
+ "datetime": {
131
+ "required": "必填",
132
+ "invalid": "無效的日期時間格式",
133
+ "format": "必須為 ${format} 格式",
134
+ "min": "日期時間不得早於 ${min}",
135
+ "max": "日期時間不得晚於 ${max}",
136
+ "hour": "小時必須介於 ${minHour} 與 ${maxHour} 之間",
137
+ "minute": "分鐘必須為 ${minuteStep} 分鐘間隔",
138
+ "includes": "必須包含「${includes}」",
139
+ "excludes": "不得包含「${excludes}」",
140
+ "past": "必須為過去的日期時間",
141
+ "future": "必須為未來的日期時間",
142
+ "today": "必須為今天",
143
+ "notToday": "不得為今天",
144
+ "weekday": "必須為工作日(週一至週五)",
145
+ "weekend": "必須為週末(週六至週日)",
146
+ "customRegex": "無效的日期時間格式",
147
+ "notInWhitelist": "日期時間不在允許清單中"
148
+ },
149
+ "file": {
150
+ "required": "必填",
151
+ "invalid": "無效的檔案格式",
152
+ "size": "檔案大小不得超過 ${size}",
153
+ "minSize": "檔案大小至少 ${minSize}",
154
+ "maxSize": "檔案大小不得超過 ${maxSize}",
155
+ "type": "檔案類型必須為:${type}",
156
+ "extension": "副檔名必須為:${extension}",
157
+ "extensionBlacklist": "不允許使用副檔名 ${extension}",
158
+ "name": "檔案名稱必須符合格式 ${pattern}",
159
+ "nameBlacklist": "檔案名稱不得符合格式 ${pattern}",
160
+ "imageOnly": "僅允許圖片檔案",
161
+ "documentOnly": "僅允許文件檔案",
162
+ "videoOnly": "僅允許影片檔案",
163
+ "audioOnly": "僅允許音訊檔案",
164
+ "archiveOnly": "僅允許壓縮檔案"
115
165
  }
116
166
  },
117
167
  "taiwan": {
@@ -137,6 +187,18 @@
137
187
  "required": "必填",
138
188
  "invalid": "無效的傳真號碼格式",
139
189
  "notInWhitelist": "不在允許的傳真號碼清單中"
190
+ },
191
+ "postalCode": {
192
+ "required": "必填",
193
+ "invalid": "無效的郵遞區號",
194
+ "invalidFormat": "郵遞區號格式錯誤",
195
+ "invalidRange": "郵遞區號超出有效範圍",
196
+ "legacy5DigitWarning": "5 碼郵遞區號為舊式格式,建議使用 6 碼格式",
197
+ "format3Only": "僅允許 3 碼郵遞區號",
198
+ "format5Only": "僅允許 5 碼郵遞區號",
199
+ "format6Only": "僅允許 6 碼郵遞區號",
200
+ "invalidSuffix": "無效的郵遞區號後碼 - 5 碼格式須為 01-99,6 碼格式須為 001-999",
201
+ "deprecated5Digit": "5 碼郵遞區號已棄用且不再支援"
140
202
  }
141
203
  }
142
204
  }
package/src/index.ts CHANGED
@@ -1,14 +1,18 @@
1
1
  export * from "./validators/common/boolean"
2
2
  export * from "./validators/common/date"
3
+ export * from "./validators/common/datetime"
3
4
  export * from "./validators/common/email"
5
+ export * from "./validators/common/file"
4
6
  export * from "./validators/common/id"
5
7
  export * from "./validators/common/number"
6
8
  export * from "./validators/common/password"
7
9
  export * from "./validators/common/text"
10
+ export * from "./validators/common/time"
8
11
  export * from "./validators/common/url"
9
12
  export * from "./validators/taiwan/business-id"
10
13
  export * from "./validators/taiwan/national-id"
11
14
  export * from "./validators/taiwan/mobile"
15
+ export * from "./validators/taiwan/postal-code"
12
16
  export * from "./validators/taiwan/tel"
13
17
  export * from "./validators/taiwan/fax"
14
18
  export * from "./config"
@@ -1,7 +1,26 @@
1
+ /**
2
+ * @fileoverview Boolean validator for Zod Kit
3
+ *
4
+ * Provides flexible boolean validation with support for various truthy/falsy values,
5
+ * strict mode validation, and comprehensive transformation options.
6
+ *
7
+ * @author Ong Hoe Yuan
8
+ * @version 0.0.5
9
+ */
10
+
1
11
  import { z, ZodBoolean, ZodNullable, ZodType } from "zod"
2
12
  import { t } from "../../i18n"
3
13
  import { getLocale, type Locale } from "../../config"
4
14
 
15
+ /**
16
+ * Type definition for boolean validation error messages
17
+ *
18
+ * @interface BooleanMessages
19
+ * @property {string} [required] - Message when field is required but empty
20
+ * @property {string} [shouldBeTrue] - Message when value should be true but isn't
21
+ * @property {string} [shouldBeFalse] - Message when value should be false but isn't
22
+ * @property {string} [invalid] - Message when value is not a valid boolean
23
+ */
5
24
  export type BooleanMessages = {
6
25
  required?: string
7
26
  shouldBeTrue?: string
@@ -9,6 +28,21 @@ export type BooleanMessages = {
9
28
  invalid?: string
10
29
  }
11
30
 
31
+ /**
32
+ * Configuration options for boolean validation
33
+ *
34
+ * @template IsRequired - Whether the field is required (affects return type)
35
+ *
36
+ * @interface BooleanOptions
37
+ * @property {IsRequired} [required=true] - Whether the field is required
38
+ * @property {boolean | null} [defaultValue] - Default value when input is empty
39
+ * @property {boolean} [shouldBe] - Specific boolean value that must be matched
40
+ * @property {unknown[]} [truthyValues] - Array of values that should be treated as true
41
+ * @property {unknown[]} [falsyValues] - Array of values that should be treated as false
42
+ * @property {boolean} [strict=false] - If true, only accepts actual boolean values
43
+ * @property {Function} [transform] - Custom transformation function for boolean values
44
+ * @property {Record<Locale, BooleanMessages>} [i18n] - Custom error messages for different locales
45
+ */
12
46
  export type BooleanOptions<IsRequired extends boolean = true> = {
13
47
  required?: IsRequired
14
48
  defaultValue?: IsRequired extends true ? boolean : boolean | null
@@ -20,8 +54,68 @@ export type BooleanOptions<IsRequired extends boolean = true> = {
20
54
  i18n?: Record<Locale, BooleanMessages>
21
55
  }
22
56
 
57
+ /**
58
+ * Type alias for boolean validation schema based on required flag
59
+ *
60
+ * @template IsRequired - Whether the field is required
61
+ * @typedef BooleanSchema
62
+ * @description Returns ZodBoolean if required, ZodNullable<ZodBoolean> if optional
63
+ */
23
64
  export type BooleanSchema<IsRequired extends boolean> = IsRequired extends true ? ZodBoolean : ZodNullable<ZodBoolean>
24
65
 
66
+ /**
67
+ * Creates a Zod schema for boolean validation with flexible value interpretation
68
+ *
69
+ * @template IsRequired - Whether the field is required (affects return type)
70
+ * @param {BooleanOptions<IsRequired>} [options] - Configuration options for boolean validation
71
+ * @returns {BooleanSchema<IsRequired>} Zod schema for boolean validation
72
+ *
73
+ * @description
74
+ * Creates a flexible boolean validator that can interpret various values as true/false,
75
+ * supports strict mode for type safety, and provides comprehensive transformation options.
76
+ *
77
+ * Features:
78
+ * - Flexible truthy/falsy value interpretation
79
+ * - Strict mode for type safety
80
+ * - Custom transformation functions
81
+ * - Specific boolean value requirements
82
+ * - Comprehensive internationalization
83
+ * - Default value support
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * // Basic boolean validation
88
+ * const basicSchema = boolean()
89
+ * basicSchema.parse(true) // ✓ Valid
90
+ * basicSchema.parse("true") // ✓ Valid (converted to true)
91
+ *
92
+ * // Strict mode (only actual booleans)
93
+ * const strictSchema = boolean({ strict: true })
94
+ * strictSchema.parse(true) // ✓ Valid
95
+ * strictSchema.parse("true") // ✗ Invalid
96
+ *
97
+ * // Must be true
98
+ * const mustBeTrueSchema = boolean({ shouldBe: true })
99
+ * mustBeTrueSchema.parse(true) // ✓ Valid
100
+ * mustBeTrueSchema.parse(false) // ✗ Invalid
101
+ *
102
+ * // Custom truthy/falsy values
103
+ * const customSchema = boolean({
104
+ * truthyValues: ["yes", "on", 1],
105
+ * falsyValues: ["no", "off", 0]
106
+ * })
107
+ * customSchema.parse("yes") // ✓ Valid (converted to true)
108
+ *
109
+ * // Optional with default
110
+ * const optionalSchema = boolean({
111
+ * required: false,
112
+ * defaultValue: false
113
+ * })
114
+ * ```
115
+ *
116
+ * @throws {z.ZodError} When validation fails with specific error messages
117
+ * @see {@link BooleanOptions} for all available configuration options
118
+ */
25
119
  export function boolean<IsRequired extends boolean = true>(options?: BooleanOptions<IsRequired>): BooleanSchema<IsRequired> {
26
120
  const {
27
121
  required = true,
@@ -1,3 +1,13 @@
1
+ /**
2
+ * @fileoverview Date validator for Zod Kit
3
+ *
4
+ * Provides comprehensive date validation with format support, range validation,
5
+ * temporal constraints, and weekday/weekend filtering using dayjs library.
6
+ *
7
+ * @author Ong Hoe Yuan
8
+ * @version 0.0.5
9
+ */
10
+
1
11
  import { z, ZodNullable, ZodString } from "zod"
2
12
  import { t } from "../../i18n"
3
13
  import { getLocale, type Locale } from "../../config"
@@ -8,12 +18,33 @@ import isSameOrBefore from "dayjs/plugin/isSameOrBefore"
8
18
  import isToday from "dayjs/plugin/isToday"
9
19
  import weekday from "dayjs/plugin/weekday"
10
20
 
21
+ // Initialize dayjs plugins for extended date functionality
11
22
  dayjs.extend(isSameOrAfter)
12
23
  dayjs.extend(isSameOrBefore)
13
24
  dayjs.extend(customParseFormat)
14
25
  dayjs.extend(isToday)
15
26
  dayjs.extend(weekday)
16
27
 
28
+ /**
29
+ * Type definition for date validation error messages
30
+ *
31
+ * @interface DateMessages
32
+ * @property {string} [required] - Message when field is required but empty
33
+ * @property {string} [invalid] - Message when date is invalid
34
+ * @property {string} [format] - Message when date doesn't match expected format
35
+ * @property {string} [min] - Message when date is before minimum allowed
36
+ * @property {string} [max] - Message when date is after maximum allowed
37
+ * @property {string} [includes] - Message when date string doesn't contain required text
38
+ * @property {string} [excludes] - Message when date string contains forbidden text
39
+ * @property {string} [past] - Message when date must be in the past
40
+ * @property {string} [future] - Message when date must be in the future
41
+ * @property {string} [today] - Message when date must be today
42
+ * @property {string} [notToday] - Message when date must not be today
43
+ * @property {string} [weekday] - Message when date must be a weekday
44
+ * @property {string} [notWeekday] - Message when date must not be a weekday
45
+ * @property {string} [weekend] - Message when date must be a weekend
46
+ * @property {string} [notWeekend] - Message when date must not be a weekend
47
+ */
17
48
  export type DateMessages = {
18
49
  required?: string
19
50
  invalid?: string
@@ -32,6 +63,28 @@ export type DateMessages = {
32
63
  notWeekend?: string
33
64
  }
34
65
 
66
+ /**
67
+ * Configuration options for date validation
68
+ *
69
+ * @template IsRequired - Whether the field is required (affects return type)
70
+ *
71
+ * @interface DateOptions
72
+ * @property {IsRequired} [required=true] - Whether the field is required
73
+ * @property {string} [min] - Minimum allowed date (in same format as specified)
74
+ * @property {string} [max] - Maximum allowed date (in same format as specified)
75
+ * @property {string} [format="YYYY-MM-DD"] - Date format for parsing and validation
76
+ * @property {string} [includes] - String that must be included in the date
77
+ * @property {string | string[]} [excludes] - String(s) that must not be included
78
+ * @property {boolean} [mustBePast] - Whether date must be in the past
79
+ * @property {boolean} [mustBeFuture] - Whether date must be in the future
80
+ * @property {boolean} [mustBeToday] - Whether date must be today
81
+ * @property {boolean} [mustNotBeToday] - Whether date must not be today
82
+ * @property {boolean} [weekdaysOnly] - Whether date must be a weekday (Monday-Friday)
83
+ * @property {boolean} [weekendsOnly] - Whether date must be a weekend (Saturday-Sunday)
84
+ * @property {Function} [transform] - Custom transformation function for date strings
85
+ * @property {string | null} [defaultValue] - Default value when input is empty
86
+ * @property {Record<Locale, DateMessages>} [i18n] - Custom error messages for different locales
87
+ */
35
88
  export type DateOptions<IsRequired extends boolean = true> = {
36
89
  required?: IsRequired
37
90
  min?: string
@@ -50,8 +103,83 @@ export type DateOptions<IsRequired extends boolean = true> = {
50
103
  i18n?: Record<Locale, DateMessages>
51
104
  }
52
105
 
106
+ /**
107
+ * Type alias for date validation schema based on required flag
108
+ *
109
+ * @template IsRequired - Whether the field is required
110
+ * @typedef DateSchema
111
+ * @description Returns ZodString if required, ZodNullable<ZodString> if optional
112
+ */
53
113
  export type DateSchema<IsRequired extends boolean> = IsRequired extends true ? ZodString : ZodNullable<ZodString>
54
114
 
115
+ /**
116
+ * Creates a Zod schema for date validation with temporal constraints
117
+ *
118
+ * @template IsRequired - Whether the field is required (affects return type)
119
+ * @param {DateOptions<IsRequired>} [options] - Configuration options for date validation
120
+ * @returns {DateSchema<IsRequired>} Zod schema for date validation
121
+ *
122
+ * @description
123
+ * Creates a comprehensive date validator with format support, range validation,
124
+ * temporal constraints, and weekday/weekend filtering using dayjs library.
125
+ *
126
+ * Features:
127
+ * - Flexible date format parsing (default: YYYY-MM-DD)
128
+ * - Range validation (min/max dates)
129
+ * - Temporal validation (past/future/today)
130
+ * - Weekday/weekend filtering
131
+ * - Content inclusion/exclusion
132
+ * - Custom transformation functions
133
+ * - Comprehensive internationalization
134
+ * - Strict date parsing with format validation
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * // Basic date validation (YYYY-MM-DD)
139
+ * const basicSchema = date()
140
+ * basicSchema.parse("2024-03-15") // ✓ Valid
141
+ * basicSchema.parse("2024-13-01") // ✗ Invalid (month 13)
142
+ *
143
+ * // Custom format
144
+ * const customFormatSchema = date({ format: "DD/MM/YYYY" })
145
+ * customFormatSchema.parse("15/03/2024") // ✓ Valid
146
+ * customFormatSchema.parse("2024-03-15") // ✗ Invalid (wrong format)
147
+ *
148
+ * // Date range validation
149
+ * const rangeSchema = date({
150
+ * min: "2024-01-01",
151
+ * max: "2024-12-31"
152
+ * })
153
+ * rangeSchema.parse("2024-06-15") // ✓ Valid
154
+ * rangeSchema.parse("2023-12-31") // ✗ Invalid (before min)
155
+ *
156
+ * // Future dates only
157
+ * const futureSchema = date({ mustBeFuture: true })
158
+ * futureSchema.parse("2030-01-01") // ✓ Valid (assuming current date < 2030)
159
+ * futureSchema.parse("2020-01-01") // ✗ Invalid (past date)
160
+ *
161
+ * // Weekdays only (Monday-Friday)
162
+ * const weekdaySchema = date({ weekdaysOnly: true })
163
+ * weekdaySchema.parse("2024-03-15") // ✓ Valid (if Friday)
164
+ * weekdaySchema.parse("2024-03-16") // ✗ Invalid (if Saturday)
165
+ *
166
+ * // Business date validation
167
+ * const businessSchema = date({
168
+ * format: "YYYY-MM-DD",
169
+ * mustBeFuture: true,
170
+ * weekdaysOnly: true
171
+ * })
172
+ *
173
+ * // Optional with default
174
+ * const optionalSchema = date({
175
+ * required: false,
176
+ * defaultValue: "2024-01-01"
177
+ * })
178
+ * ```
179
+ *
180
+ * @throws {z.ZodError} When validation fails with specific error messages
181
+ * @see {@link DateOptions} for all available configuration options
182
+ */
55
183
  export function date<IsRequired extends boolean = true>(options?: DateOptions<IsRequired>): DateSchema<IsRequired> {
56
184
  const {
57
185
  required = true,