@hy_ong/zod-kit 0.0.6 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/.claude/settings.local.json +4 -1
  2. package/README.md +134 -68
  3. package/dist/index.cjs +93 -89
  4. package/dist/index.d.cts +235 -169
  5. package/dist/index.d.ts +235 -169
  6. package/dist/index.js +93 -89
  7. package/package.json +15 -5
  8. package/src/validators/common/boolean.ts +17 -14
  9. package/src/validators/common/date.ts +21 -14
  10. package/src/validators/common/datetime.ts +21 -14
  11. package/src/validators/common/email.ts +18 -15
  12. package/src/validators/common/file.ts +20 -13
  13. package/src/validators/common/id.ts +14 -14
  14. package/src/validators/common/number.ts +18 -15
  15. package/src/validators/common/password.ts +21 -14
  16. package/src/validators/common/text.ts +21 -17
  17. package/src/validators/common/time.ts +21 -14
  18. package/src/validators/common/url.ts +22 -15
  19. package/src/validators/taiwan/business-id.ts +18 -11
  20. package/src/validators/taiwan/fax.ts +23 -14
  21. package/src/validators/taiwan/mobile.ts +23 -14
  22. package/src/validators/taiwan/national-id.ts +11 -12
  23. package/src/validators/taiwan/postal-code.ts +16 -17
  24. package/src/validators/taiwan/tel.ts +23 -14
  25. package/tests/common/boolean.test.ts +38 -38
  26. package/tests/common/date.test.ts +65 -65
  27. package/tests/common/datetime.test.ts +100 -118
  28. package/tests/common/email.test.ts +24 -28
  29. package/tests/common/file.test.ts +47 -51
  30. package/tests/common/id.test.ts +80 -113
  31. package/tests/common/number.test.ts +24 -25
  32. package/tests/common/password.test.ts +28 -35
  33. package/tests/common/text.test.ts +36 -37
  34. package/tests/common/time.test.ts +64 -82
  35. package/tests/common/url.test.ts +67 -67
  36. package/tests/taiwan/business-id.test.ts +22 -22
  37. package/tests/taiwan/fax.test.ts +33 -42
  38. package/tests/taiwan/mobile.test.ts +32 -41
  39. package/tests/taiwan/national-id.test.ts +31 -31
  40. package/tests/taiwan/postal-code.test.ts +142 -96
  41. package/tests/taiwan/tel.test.ts +33 -42
  42. package/debug.js +0 -21
  43. package/debug.ts +0 -16
@@ -6,7 +6,7 @@ describe("postalCode() features", () => {
6
6
 
7
7
  describe("3-digit postal code validation", () => {
8
8
  it("should accept valid 3-digit postal codes", () => {
9
- const schema = postalCode({ format: "3" })
9
+ const schema = postalCode(true, { format: "3" })
10
10
  expect(schema.parse("100")).toBe("100") // Taipei
11
11
  expect(schema.parse("200")).toBe("200") // Keelung
12
12
  expect(schema.parse("300")).toBe("300") // Taoyuan/Hsinchu
@@ -19,20 +19,20 @@ describe("postalCode() features", () => {
19
19
  })
20
20
 
21
21
  it("should reject invalid 3-digit postal codes", () => {
22
- const schema = postalCode({ format: "3" })
22
+ const schema = postalCode(true, { format: "3" })
23
23
  expect(() => schema.parse("000")).toThrow("Invalid Taiwan postal code")
24
24
  expect(() => schema.parse("099")).toThrow("Invalid Taiwan postal code")
25
25
  expect(() => schema.parse("999")).toThrow("Invalid Taiwan postal code")
26
26
  })
27
27
 
28
28
  it("should reject non-3-digit formats when format is '3'", () => {
29
- const schema = postalCode({ format: "3" })
29
+ const schema = postalCode(true, { format: "3" })
30
30
  expect(() => schema.parse("10001")).toThrow("Only 3-digit postal codes are allowed")
31
31
  expect(() => schema.parse("100001")).toThrow("Only 3-digit postal codes are allowed")
32
32
  })
33
33
 
34
34
  it("should validate specific Taipei area postal codes", () => {
35
- const schema = postalCode({ format: "3" })
35
+ const schema = postalCode(true, { format: "3" })
36
36
  expect(schema.parse("100")).toBe("100") // Zhongzheng
37
37
  expect(schema.parse("103")).toBe("103") // Datong
38
38
  expect(schema.parse("104")).toBe("104") // Zhongshan
@@ -50,7 +50,7 @@ describe("postalCode() features", () => {
50
50
 
51
51
  describe("5-digit postal code validation", () => {
52
52
  it("should accept valid 5-digit postal codes", () => {
53
- const schema = postalCode({ format: "5" })
53
+ const schema = postalCode(true, { format: "5" })
54
54
  expect(schema.parse("10001")).toBe("10001")
55
55
  expect(schema.parse("20001")).toBe("20001")
56
56
  expect(schema.parse("30001")).toBe("30001")
@@ -59,20 +59,20 @@ describe("postalCode() features", () => {
59
59
  })
60
60
 
61
61
  it("should reject invalid 5-digit postal codes", () => {
62
- const schema = postalCode({ format: "5" })
62
+ const schema = postalCode(true, { format: "5" })
63
63
  expect(() => schema.parse("00001")).toThrow("Invalid Taiwan postal code")
64
64
  expect(() => schema.parse("09901")).toThrow("Invalid Taiwan postal code")
65
65
  expect(() => schema.parse("99901")).toThrow("Invalid Taiwan postal code")
66
66
  })
67
67
 
68
68
  it("should reject non-5-digit formats when format is '5'", () => {
69
- const schema = postalCode({ format: "5" })
69
+ const schema = postalCode(true, { format: "5" })
70
70
  expect(() => schema.parse("100")).toThrow("Only 5-digit postal codes are allowed")
71
71
  expect(() => schema.parse("100001")).toThrow("Only 5-digit postal codes are allowed")
72
72
  })
73
73
 
74
74
  it("should validate 5-digit postal codes with valid prefixes", () => {
75
- const schema = postalCode({ format: "5" })
75
+ const schema = postalCode(true, { format: "5" })
76
76
  expect(schema.parse("10099")).toBe("10099") // Valid Taipei prefix
77
77
  expect(schema.parse("20099")).toBe("20099") // Valid Keelung prefix
78
78
  expect(schema.parse("88099")).toBe("88099") // Valid Penghu prefix
@@ -81,7 +81,7 @@ describe("postalCode() features", () => {
81
81
 
82
82
  describe("6-digit postal code validation", () => {
83
83
  it("should accept valid 6-digit postal codes", () => {
84
- const schema = postalCode({ format: "6" })
84
+ const schema = postalCode(true, { format: "6" })
85
85
  expect(schema.parse("100001")).toBe("100001")
86
86
  expect(schema.parse("200001")).toBe("200001")
87
87
  expect(schema.parse("300001")).toBe("300001")
@@ -90,20 +90,20 @@ describe("postalCode() features", () => {
90
90
  })
91
91
 
92
92
  it("should reject invalid 6-digit postal codes", () => {
93
- const schema = postalCode({ format: "6" })
93
+ const schema = postalCode(true, { format: "6" })
94
94
  expect(() => schema.parse("000001")).toThrow("Invalid Taiwan postal code")
95
95
  expect(() => schema.parse("099001")).toThrow("Invalid Taiwan postal code")
96
96
  expect(() => schema.parse("999001")).toThrow("Invalid Taiwan postal code")
97
97
  })
98
98
 
99
99
  it("should reject non-6-digit formats when format is '6'", () => {
100
- const schema = postalCode({ format: "6" })
100
+ const schema = postalCode(true, { format: "6" })
101
101
  expect(() => schema.parse("100")).toThrow("Only 6-digit postal codes are allowed")
102
102
  expect(() => schema.parse("10001")).toThrow("Only 6-digit postal codes are allowed")
103
103
  })
104
104
 
105
105
  it("should validate 6-digit postal codes with all valid prefixes", () => {
106
- const schema = postalCode({ format: "6" })
106
+ const schema = postalCode(true, { format: "6" })
107
107
  expect(schema.parse("100999")).toBe("100999") // Taipei
108
108
  expect(schema.parse("880999")).toBe("880999") // Penghu
109
109
  expect(schema.parse("890999")).toBe("890999") // Kinmen
@@ -113,7 +113,7 @@ describe("postalCode() features", () => {
113
113
 
114
114
  describe("combined format validation", () => {
115
115
  it("should accept both 3 and 5 digit formats with '3+5'", () => {
116
- const schema = postalCode({ format: "3+5" })
116
+ const schema = postalCode(true, { format: "3+5" })
117
117
  expect(schema.parse("100")).toBe("100")
118
118
  expect(schema.parse("10001")).toBe("10001")
119
119
  expect(() => schema.parse("100001")).toThrow("Invalid Taiwan postal code")
@@ -127,14 +127,14 @@ describe("postalCode() features", () => {
127
127
  })
128
128
 
129
129
  it("should accept both 5 and 6 digit formats with '5+6'", () => {
130
- const schema = postalCode({ format: "5+6" })
130
+ const schema = postalCode(true, { format: "5+6" })
131
131
  expect(schema.parse("10001")).toBe("10001")
132
132
  expect(schema.parse("100001")).toBe("100001")
133
133
  expect(() => schema.parse("100")).toThrow("Invalid Taiwan postal code")
134
134
  })
135
135
 
136
136
  it("should accept all formats with 'all'", () => {
137
- const schema = postalCode({ format: "all" })
137
+ const schema = postalCode(true, { format: "all" })
138
138
  expect(schema.parse("100")).toBe("100")
139
139
  expect(schema.parse("10001")).toBe("10001")
140
140
  expect(schema.parse("100001")).toBe("100001")
@@ -143,7 +143,7 @@ describe("postalCode() features", () => {
143
143
 
144
144
  describe("dash and space handling", () => {
145
145
  it("should handle dashes in postal codes when allowDashes is true", () => {
146
- const schema = postalCode({ format: "all", allowDashes: true })
146
+ const schema = postalCode(true, { format: "all", allowDashes: true })
147
147
  expect(schema.parse("100")).toBe("100")
148
148
  expect(schema.parse("100-01")).toBe("10001")
149
149
  expect(schema.parse("100-001")).toBe("100001")
@@ -151,14 +151,14 @@ describe("postalCode() features", () => {
151
151
  })
152
152
 
153
153
  it("should reject dashes when allowDashes is false", () => {
154
- const schema = postalCode({ format: "all", allowDashes: false })
154
+ const schema = postalCode(true, { format: "all", allowDashes: false })
155
155
  expect(schema.parse("100")).toBe("100")
156
156
  expect(() => schema.parse("100-01")).toThrow("Invalid Taiwan postal code")
157
157
  expect(() => schema.parse("100-001")).toThrow("Invalid Taiwan postal code")
158
158
  })
159
159
 
160
160
  it("should normalize various dash and space formats", () => {
161
- const schema = postalCode({ format: "6", allowDashes: true })
161
+ const schema = postalCode(true, { format: "6", allowDashes: true })
162
162
  expect(schema.parse("100-001")).toBe("100001")
163
163
  expect(schema.parse("100 001")).toBe("100001")
164
164
  expect(schema.parse("100 001")).toBe("100001")
@@ -168,9 +168,9 @@ describe("postalCode() features", () => {
168
168
 
169
169
  describe("prefix filtering", () => {
170
170
  it("should only allow specified prefixes", () => {
171
- const schema = postalCode({
171
+ const schema = postalCode(true, {
172
172
  format: "all",
173
- allowedPrefixes: ["100", "200", "300"]
173
+ allowedPrefixes: ["100", "200", "300"],
174
174
  })
175
175
  expect(schema.parse("100")).toBe("100")
176
176
  expect(schema.parse("10001")).toBe("10001")
@@ -181,9 +181,9 @@ describe("postalCode() features", () => {
181
181
  })
182
182
 
183
183
  it("should block specified prefixes", () => {
184
- const schema = postalCode({
184
+ const schema = postalCode(true, {
185
185
  format: "all",
186
- blockedPrefixes: ["999", "000"]
186
+ blockedPrefixes: ["999", "000"],
187
187
  })
188
188
  expect(schema.parse("100")).toBe("100")
189
189
  expect(() => schema.parse("999")).toThrow("Invalid Taiwan postal code")
@@ -192,19 +192,19 @@ describe("postalCode() features", () => {
192
192
  })
193
193
 
194
194
  it("should prioritize allowedPrefixes over strict validation", () => {
195
- const schema = postalCode({
195
+ const schema = postalCode(true, {
196
196
  format: "3",
197
197
  allowedPrefixes: ["999"], // Not in official list
198
- strictValidation: true
198
+ strictValidation: true,
199
199
  })
200
200
  expect(schema.parse("999")).toBe("999")
201
201
  })
202
202
 
203
203
  it("should respect blockedPrefixes even with allowedPrefixes", () => {
204
- const schema = postalCode({
204
+ const schema = postalCode(true, {
205
205
  format: "3",
206
206
  allowedPrefixes: ["100", "200", "999"],
207
- blockedPrefixes: ["999"]
207
+ blockedPrefixes: ["999"],
208
208
  })
209
209
  expect(schema.parse("100")).toBe("100")
210
210
  expect(schema.parse("200")).toBe("200")
@@ -214,20 +214,20 @@ describe("postalCode() features", () => {
214
214
 
215
215
  describe("strict validation", () => {
216
216
  it("should validate against official postal code list when strict", () => {
217
- const schema = postalCode({ format: "3", strictValidation: true })
217
+ const schema = postalCode(true, { format: "3", strictValidation: true })
218
218
  expect(schema.parse("100")).toBe("100") // Valid official code
219
219
  expect(() => schema.parse("199")).toThrow("Invalid Taiwan postal code") // Not in official list
220
220
  })
221
221
 
222
222
  it("should allow broader range when not strict", () => {
223
- const schema = postalCode({ format: "3", strictValidation: false })
223
+ const schema = postalCode(true, { format: "3", strictValidation: false })
224
224
  expect(schema.parse("100")).toBe("100") // Valid official code
225
225
  expect(schema.parse("199")).toBe("199") // Not in official list but in range 100-999
226
226
  expect(() => schema.parse("099")).toThrow("Invalid Taiwan postal code") // Still below 100
227
227
  })
228
228
 
229
229
  it("should validate all Taiwan regions with strict validation", () => {
230
- const schema = postalCode({ format: "3", strictValidation: true })
230
+ const schema = postalCode(true, { format: "3", strictValidation: true })
231
231
 
232
232
  // Major cities
233
233
  expect(schema.parse("100")).toBe("100") // Taipei City
@@ -254,28 +254,28 @@ describe("postalCode() features", () => {
254
254
 
255
255
  describe("required and optional validation", () => {
256
256
  it("should handle required validation", () => {
257
- const schema = postalCode()
257
+ const schema = postalCode(true)
258
258
  expect(() => schema.parse(null)).toThrow("Required")
259
259
  expect(() => schema.parse(undefined)).toThrow("Required")
260
260
  expect(() => schema.parse("")).toThrow("Required")
261
261
  })
262
262
 
263
263
  it("should allow null when not required", () => {
264
- const schema = postalCode({ required: false })
264
+ const schema = postalCode(false)
265
265
  expect(schema.parse(null)).toBe(null)
266
266
  expect(schema.parse(undefined)).toBe(null)
267
267
  expect(schema.parse("")).toBe(null)
268
268
  })
269
269
 
270
270
  it("should use default value when provided", () => {
271
- const schema = postalCode({ defaultValue: "100001" })
271
+ const schema = postalCode(true, { defaultValue: "100001" })
272
272
  expect(schema.parse("")).toBe("100001")
273
273
  expect(schema.parse(null)).toBe("100001")
274
274
  expect(schema.parse(undefined)).toBe("100001")
275
275
  })
276
276
 
277
277
  it("should use default value for optional fields", () => {
278
- const schema = postalCode({ required: false, defaultValue: "100001" })
278
+ const schema = postalCode(false, { defaultValue: "100001" })
279
279
  expect(schema.parse("")).toBe("100001")
280
280
  expect(schema.parse(null)).toBe("100001")
281
281
  expect(schema.parse(undefined)).toBe("100001")
@@ -284,9 +284,9 @@ describe("postalCode() features", () => {
284
284
 
285
285
  describe("transform functionality", () => {
286
286
  it("should apply transform function", () => {
287
- const schema = postalCode({
287
+ const schema = postalCode(true, {
288
288
  format: "6",
289
- transform: (val) => val.replace(/\D/g, "") // Remove non-digits
289
+ transform: (val) => val.replace(/\D/g, ""), // Remove non-digits
290
290
  })
291
291
  expect(schema.parse("100-001")).toBe("100001")
292
292
  expect(schema.parse("100.001")).toBe("100001")
@@ -294,10 +294,10 @@ describe("postalCode() features", () => {
294
294
  })
295
295
 
296
296
  it("should apply transform after dash removal", () => {
297
- const schema = postalCode({
297
+ const schema = postalCode(true, {
298
298
  format: "3",
299
299
  allowDashes: true,
300
- transform: (val) => val.padEnd(3, "0") // Pad to 3 digits
300
+ transform: (val) => val.padEnd(3, "0"), // Pad to 3 digits
301
301
  })
302
302
  expect(schema.parse("10")).toBe("100")
303
303
  expect(schema.parse("1")).toBe("100")
@@ -306,8 +306,8 @@ describe("postalCode() features", () => {
306
306
 
307
307
  describe("legacy 5-digit warning", () => {
308
308
  it("should emit warning for 5-digit codes when warn5Digit is true", () => {
309
- const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
310
- const schema = postalCode({ format: "all", warn5Digit: true })
309
+ const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => {})
310
+ const schema = postalCode(true, { format: "all", warn5Digit: true })
311
311
 
312
312
  schema.parse("10001") // Should emit warning
313
313
  expect(consoleSpy).toHaveBeenCalledWith("5-digit postal codes are legacy format, consider using 6-digit format")
@@ -319,8 +319,8 @@ describe("postalCode() features", () => {
319
319
  })
320
320
 
321
321
  it("should not emit warning when warn5Digit is false", () => {
322
- const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
323
- const schema = postalCode({ format: "all", warn5Digit: false })
322
+ const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => {})
323
+ const schema = postalCode(true, { format: "all", warn5Digit: false })
324
324
 
325
325
  schema.parse("10001") // Should not emit warning
326
326
  expect(consoleSpy).not.toHaveBeenCalled()
@@ -329,8 +329,8 @@ describe("postalCode() features", () => {
329
329
  })
330
330
 
331
331
  it("should not emit warning for 5-digit only format", () => {
332
- const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
333
- const schema = postalCode({ format: "5", warn5Digit: true })
332
+ const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => {})
333
+ const schema = postalCode(true, { format: "5", warn5Digit: true })
334
334
 
335
335
  schema.parse("10001") // Should not emit warning for 5-digit only format
336
336
  expect(consoleSpy).not.toHaveBeenCalled()
@@ -341,7 +341,7 @@ describe("postalCode() features", () => {
341
341
 
342
342
  describe("custom i18n messages", () => {
343
343
  it("should use custom messages when provided", () => {
344
- const schema = postalCode({
344
+ const schema = postalCode(true, {
345
345
  format: "3",
346
346
  i18n: {
347
347
  en: {
@@ -363,7 +363,7 @@ describe("postalCode() features", () => {
363
363
  })
364
364
 
365
365
  it("should fallback to default messages when custom not provided", () => {
366
- const schema = postalCode({
366
+ const schema = postalCode(true, {
367
367
  format: "6",
368
368
  i18n: {
369
369
  en: {
@@ -381,7 +381,7 @@ describe("postalCode() features", () => {
381
381
 
382
382
  it("should use correct locale for custom messages", () => {
383
383
  setLocale("en")
384
- const schemaEn = postalCode({
384
+ const schemaEn = postalCode(true, {
385
385
  format: "3",
386
386
  i18n: {
387
387
  en: {
@@ -395,7 +395,7 @@ describe("postalCode() features", () => {
395
395
  expect(() => schemaEn.parse("999")).toThrow("English invalid message")
396
396
 
397
397
  setLocale("zh-TW")
398
- const schemaZh = postalCode({
398
+ const schemaZh = postalCode(true, {
399
399
  format: "3",
400
400
  i18n: {
401
401
  en: {
@@ -412,12 +412,12 @@ describe("postalCode() features", () => {
412
412
 
413
413
  describe("complex scenarios", () => {
414
414
  it("should work with multiple validations", () => {
415
- const schema = postalCode({
415
+ const schema = postalCode(true, {
416
416
  format: "6",
417
417
  allowDashes: true,
418
418
  strictValidation: true,
419
419
  allowedPrefixes: ["100", "200", "300"],
420
- transform: (val) => val.replace(/\D/g, "").padEnd(6, "0")
420
+ transform: (val) => val.replace(/\D/g, "").padEnd(6, "0"),
421
421
  })
422
422
 
423
423
  expect(schema.parse("100-001")).toBe("100001")
@@ -429,10 +429,10 @@ describe("postalCode() features", () => {
429
429
  })
430
430
 
431
431
  it("should handle edge cases with transforms and dashes", () => {
432
- const schema = postalCode({
432
+ const schema = postalCode(true, {
433
433
  format: "all",
434
434
  allowDashes: true,
435
- transform: (val) => val.toUpperCase().replace(/[^0-9-]/g, "")
435
+ transform: (val) => val.toUpperCase().replace(/[^0-9-]/g, ""),
436
436
  })
437
437
 
438
438
  expect(schema.parse("100ABC-001DEF")).toBe("100001")
@@ -441,57 +441,103 @@ describe("postalCode() features", () => {
441
441
  })
442
442
 
443
443
  it("should validate comprehensive Taiwan postal code coverage", () => {
444
- const schema = postalCode({ format: "all", strictValidation: true })
444
+ const schema = postalCode(true, { format: "all", strictValidation: true })
445
445
 
446
446
  // Test various regions
447
447
  const validCodes = [
448
448
  // Taipei area
449
- "100", "103", "104", "105", "106", "108", "110", "111", "112", "114", "115", "116",
450
- "10001", "10301", "100001", "103001",
449
+ "100",
450
+ "103",
451
+ "104",
452
+ "105",
453
+ "106",
454
+ "108",
455
+ "110",
456
+ "111",
457
+ "112",
458
+ "114",
459
+ "115",
460
+ "116",
461
+ "10001",
462
+ "10301",
463
+ "100001",
464
+ "103001",
451
465
 
452
466
  // New Taipei area
453
- "220", "221", "222", "223", "224", "226", "227", "228",
454
- "22001", "221001",
467
+ "220",
468
+ "221",
469
+ "222",
470
+ "223",
471
+ "224",
472
+ "226",
473
+ "227",
474
+ "228",
475
+ "22001",
476
+ "221001",
455
477
 
456
478
  // Taoyuan area
457
- "320", "324", "325", "326", "327", "328", "330", "333",
458
- "32001", "320001",
479
+ "320",
480
+ "324",
481
+ "325",
482
+ "326",
483
+ "327",
484
+ "328",
485
+ "330",
486
+ "333",
487
+ "32001",
488
+ "320001",
459
489
 
460
490
  // Offshore islands
461
- "880", "881", "882", "883", "884", "885", // Penghu
462
- "890", "891", "892", "893", "894", "895", "896", // Kinmen
463
- "209", "210", "211", "212", // Lienchiang (Matsu)
464
- "88001", "890001", "209001"
491
+ "880",
492
+ "881",
493
+ "882",
494
+ "883",
495
+ "884",
496
+ "885", // Penghu
497
+ "890",
498
+ "891",
499
+ "892",
500
+ "893",
501
+ "894",
502
+ "895",
503
+ "896", // Kinmen
504
+ "209",
505
+ "210",
506
+ "211",
507
+ "212", // Lienchiang (Matsu)
508
+ "88001",
509
+ "890001",
510
+ "209001",
465
511
  ]
466
512
 
467
- validCodes.forEach(code => {
513
+ validCodes.forEach((code) => {
468
514
  expect(schema.parse(code)).toBe(code)
469
515
  })
470
516
  })
471
517
 
472
518
  it("should work with real-world postal codes", () => {
473
- const schema = postalCode({ format: "all", allowDashes: true })
519
+ const schema = postalCode(true, { format: "all", allowDashes: true })
474
520
 
475
521
  // Real Taiwan postal codes
476
- expect(schema.parse("100")).toBe("100") // Taipei Main Post Office
477
- expect(schema.parse("110")).toBe("110") // Xinyi District, Taipei
478
- expect(schema.parse("220")).toBe("220") // Banqiao District, New Taipei
479
- expect(schema.parse("300")).toBe("300") // East District, Hsinchu City
480
- expect(schema.parse("400")).toBe("400") // Central District, Taichung
481
- expect(schema.parse("700")).toBe("700") // Central District, Tainan
482
- expect(schema.parse("800")).toBe("800") // Xinxing District, Kaohsiung
483
- expect(schema.parse("880")).toBe("880") // Magong City, Penghu
484
- expect(schema.parse("890")).toBe("890") // Jincheng Township, Kinmen
522
+ expect(schema.parse("100")).toBe("100") // Taipei Main Post Office
523
+ expect(schema.parse("110")).toBe("110") // Xinyi District, Taipei
524
+ expect(schema.parse("220")).toBe("220") // Banqiao District, New Taipei
525
+ expect(schema.parse("300")).toBe("300") // East District, Hsinchu City
526
+ expect(schema.parse("400")).toBe("400") // Central District, Taichung
527
+ expect(schema.parse("700")).toBe("700") // Central District, Tainan
528
+ expect(schema.parse("800")).toBe("800") // Xinxing District, Kaohsiung
529
+ expect(schema.parse("880")).toBe("880") // Magong City, Penghu
530
+ expect(schema.parse("890")).toBe("890") // Jincheng Township, Kinmen
485
531
 
486
532
  // With dashes
487
- expect(schema.parse("100-01")).toBe("10001") // 5-digit format
533
+ expect(schema.parse("100-01")).toBe("10001") // 5-digit format
488
534
  expect(schema.parse("100-001")).toBe("100001") // 6-digit format
489
535
  })
490
536
  })
491
537
 
492
538
  describe("strict suffix validation with regional ranges", () => {
493
539
  it("should validate 5-digit suffix ranges for major cities", () => {
494
- const schema = postalCode({ format: "5", strictSuffixValidation: true })
540
+ const schema = postalCode(true, { format: "5", strictSuffixValidation: true })
495
541
  // Taipei areas (full range 01-99)
496
542
  expect(schema.parse("10001")).toBe("10001") // Valid suffix 01
497
543
  expect(schema.parse("10099")).toBe("10099") // Valid suffix 99
@@ -500,7 +546,7 @@ describe("postalCode() features", () => {
500
546
  })
501
547
 
502
548
  it("should validate 6-digit suffix ranges for major cities", () => {
503
- const schema = postalCode({ format: "6", strictSuffixValidation: true })
549
+ const schema = postalCode(true, { format: "6", strictSuffixValidation: true })
504
550
  // Taipei areas (full range 001-999)
505
551
  expect(schema.parse("100001")).toBe("100001") // Valid suffix 001
506
552
  expect(schema.parse("100999")).toBe("100999") // Valid suffix 999
@@ -509,7 +555,7 @@ describe("postalCode() features", () => {
509
555
  })
510
556
 
511
557
  it("should validate restricted ranges for smaller areas", () => {
512
- const schema = postalCode({ format: "all", strictSuffixValidation: true })
558
+ const schema = postalCode(true, { format: "all", strictSuffixValidation: true })
513
559
 
514
560
  // Penghu (limited range)
515
561
  expect(schema.parse("88001")).toBe("88001") // Valid for Penghu
@@ -531,7 +577,7 @@ describe("postalCode() features", () => {
531
577
  })
532
578
 
533
579
  it("should allow any suffix when strictSuffixValidation is disabled", () => {
534
- const schema = postalCode({ format: "all", strictSuffixValidation: false })
580
+ const schema = postalCode(true, { format: "all", strictSuffixValidation: false })
535
581
  expect(schema.parse("10000")).toBe("10000") // Suffix 00 allowed
536
582
  expect(schema.parse("100000")).toBe("100000") // Suffix 000 allowed
537
583
  expect(schema.parse("10099")).toBe("10099") // Normal suffix
@@ -540,24 +586,24 @@ describe("postalCode() features", () => {
540
586
 
541
587
  describe("5-digit deprecation", () => {
542
588
  it("should reject 5-digit codes when deprecate5Digit is enabled", () => {
543
- const schema = postalCode({ format: "all", deprecate5Digit: true })
589
+ const schema = postalCode(true, { format: "all", deprecate5Digit: true })
544
590
  expect(schema.parse("100")).toBe("100") // 3-digit still allowed
545
591
  expect(schema.parse("100001")).toBe("100001") // 6-digit still allowed
546
592
  expect(() => schema.parse("10001")).toThrow("5-digit postal codes are deprecated") // 5-digit rejected
547
593
  })
548
594
 
549
595
  it("should allow 5-digit codes when deprecate5Digit is disabled", () => {
550
- const schema = postalCode({ format: "all", deprecate5Digit: false })
596
+ const schema = postalCode(true, { format: "all", deprecate5Digit: false })
551
597
  expect(schema.parse("10001")).toBe("10001") // 5-digit allowed
552
598
  })
553
599
  })
554
600
 
555
601
  describe("combined strict validation scenarios", () => {
556
602
  it("should work with both strictSuffixValidation and deprecate5Digit", () => {
557
- const schema = postalCode({
603
+ const schema = postalCode(true, {
558
604
  format: "6",
559
605
  strictSuffixValidation: true,
560
- deprecate5Digit: true
606
+ deprecate5Digit: true,
561
607
  })
562
608
  expect(schema.parse("100001")).toBe("100001") // Valid 6-digit
563
609
  expect(() => schema.parse("100000")).toThrow("Invalid postal code suffix") // Invalid suffix
@@ -565,10 +611,10 @@ describe("postalCode() features", () => {
565
611
  })
566
612
 
567
613
  it("should provide specific error for real-world validation scenarios", () => {
568
- const realWorldSchema = postalCode({
614
+ const realWorldSchema = postalCode(true, {
569
615
  format: "6",
570
616
  strictSuffixValidation: true,
571
- strictValidation: true
617
+ strictValidation: true,
572
618
  })
573
619
 
574
620
  // Valid real postal codes from major cities
@@ -598,11 +644,11 @@ describe("postalCode() features", () => {
598
644
 
599
645
  describe("regional-specific validation", () => {
600
646
  it("should validate major cities with full ranges", () => {
601
- const schema = postalCode({ format: "all", strictSuffixValidation: true })
647
+ const schema = postalCode(true, { format: "all", strictSuffixValidation: true })
602
648
 
603
649
  // Taipei City areas - should have full 01-99 and 001-999 ranges
604
650
  const taipeiAreas = ["100", "103", "104", "105", "106", "108", "110", "111", "112", "114", "115", "116"]
605
- taipeiAreas.forEach(area => {
651
+ taipeiAreas.forEach((area) => {
606
652
  expect(schema.parse(`${area}01`)).toBe(`${area}01`) // Min 5-digit
607
653
  expect(schema.parse(`${area}99`)).toBe(`${area}99`) // Max 5-digit
608
654
  expect(schema.parse(`${area}001`)).toBe(`${area}001`) // Min 6-digit
@@ -617,7 +663,7 @@ describe("postalCode() features", () => {
617
663
  })
618
664
 
619
665
  it("should enforce restricted ranges for offshore islands", () => {
620
- const schema = postalCode({ format: "all", strictSuffixValidation: true })
666
+ const schema = postalCode(true, { format: "all", strictSuffixValidation: true })
621
667
 
622
668
  // Penghu County (880) - limited to 01-50 and 001-500
623
669
  expect(schema.parse("88001")).toBe("88001")
@@ -645,7 +691,7 @@ describe("postalCode() features", () => {
645
691
  })
646
692
 
647
693
  it("should use default ranges for areas not in specific mapping", () => {
648
- const schema = postalCode({ format: "all", strictSuffixValidation: true })
694
+ const schema = postalCode(true, { format: "all", strictSuffixValidation: true })
649
695
 
650
696
  // Areas not specifically mapped should use default ranges (01-99, 001-999)
651
697
  expect(schema.parse("26001")).toBe("26001") // Yilan - uses default
@@ -659,7 +705,7 @@ describe("postalCode() features", () => {
659
705
 
660
706
  describe("edge cases", () => {
661
707
  it("should handle empty and whitespace inputs", () => {
662
- const schema = postalCode({ required: false })
708
+ const schema = postalCode(false)
663
709
  expect(schema.parse("")).toBe(null)
664
710
  expect(schema.parse(" ")).toBe(null)
665
711
  expect(schema.parse("\t")).toBe(null)
@@ -667,22 +713,22 @@ describe("postalCode() features", () => {
667
713
  })
668
714
 
669
715
  it("should handle numeric inputs", () => {
670
- const schema = postalCode({ format: "3" })
716
+ const schema = postalCode(true, { format: "3" })
671
717
  expect(schema.parse(100)).toBe("100")
672
718
  expect(schema.parse(200)).toBe("200")
673
719
  })
674
720
 
675
721
  it("should reject codes with letters when not using transform", () => {
676
- const schema = postalCode({ format: "3", allowDashes: false })
722
+ const schema = postalCode(true, { format: "3", allowDashes: false })
677
723
  expect(() => schema.parse("10A")).toThrow("Invalid Taiwan postal code")
678
724
  expect(() => schema.parse("ABC")).toThrow("Invalid Taiwan postal code")
679
725
  })
680
726
 
681
727
  it("should handle very specific area restrictions", () => {
682
728
  // Only allow Taipei city areas
683
- const taipeiOnlySchema = postalCode({
729
+ const taipeiOnlySchema = postalCode(true, {
684
730
  format: "all",
685
- allowedPrefixes: ["100", "103", "104", "105", "106", "108", "110", "111", "112", "114", "115", "116"]
731
+ allowedPrefixes: ["100", "103", "104", "105", "106", "108", "110", "111", "112", "114", "115", "116"],
686
732
  })
687
733
 
688
734
  expect(taipeiOnlySchema.parse("100")).toBe("100")
@@ -691,15 +737,15 @@ describe("postalCode() features", () => {
691
737
  })
692
738
 
693
739
  it("should handle format combinations correctly", () => {
694
- const schema35 = postalCode({ format: "3+5" })
740
+ const schema35 = postalCode(true, { format: "3+5" })
695
741
  expect(schema35.parse("100")).toBe("100")
696
742
  expect(schema35.parse("10001")).toBe("10001")
697
743
  expect(() => schema35.parse("100001")).toThrow("Invalid Taiwan postal code")
698
744
 
699
- const schema56 = postalCode({ format: "5+6" })
745
+ const schema56 = postalCode(true, { format: "5+6" })
700
746
  expect(schema56.parse("10001")).toBe("10001")
701
747
  expect(schema56.parse("100001")).toBe("100001")
702
748
  expect(() => schema56.parse("100")).toThrow("Invalid Taiwan postal code")
703
749
  })
704
750
  })
705
- })
751
+ })