@hy_ong/zod-kit 0.0.6 → 0.1.0

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 (42) hide show
  1. package/.claude/settings.local.json +4 -1
  2. package/dist/index.cjs +93 -89
  3. package/dist/index.d.cts +235 -169
  4. package/dist/index.d.ts +235 -169
  5. package/dist/index.js +93 -89
  6. package/package.json +2 -1
  7. package/src/validators/common/boolean.ts +17 -14
  8. package/src/validators/common/date.ts +21 -14
  9. package/src/validators/common/datetime.ts +21 -14
  10. package/src/validators/common/email.ts +18 -15
  11. package/src/validators/common/file.ts +20 -13
  12. package/src/validators/common/id.ts +14 -14
  13. package/src/validators/common/number.ts +18 -15
  14. package/src/validators/common/password.ts +21 -14
  15. package/src/validators/common/text.ts +21 -17
  16. package/src/validators/common/time.ts +21 -14
  17. package/src/validators/common/url.ts +22 -15
  18. package/src/validators/taiwan/business-id.ts +18 -11
  19. package/src/validators/taiwan/fax.ts +23 -14
  20. package/src/validators/taiwan/mobile.ts +23 -14
  21. package/src/validators/taiwan/national-id.ts +11 -12
  22. package/src/validators/taiwan/postal-code.ts +16 -17
  23. package/src/validators/taiwan/tel.ts +23 -14
  24. package/tests/common/boolean.test.ts +38 -38
  25. package/tests/common/date.test.ts +65 -65
  26. package/tests/common/datetime.test.ts +100 -118
  27. package/tests/common/email.test.ts +24 -28
  28. package/tests/common/file.test.ts +47 -51
  29. package/tests/common/id.test.ts +80 -113
  30. package/tests/common/number.test.ts +24 -25
  31. package/tests/common/password.test.ts +28 -35
  32. package/tests/common/text.test.ts +36 -37
  33. package/tests/common/time.test.ts +64 -82
  34. package/tests/common/url.test.ts +67 -67
  35. package/tests/taiwan/business-id.test.ts +22 -22
  36. package/tests/taiwan/fax.test.ts +33 -42
  37. package/tests/taiwan/mobile.test.ts +32 -41
  38. package/tests/taiwan/national-id.test.ts +31 -31
  39. package/tests/taiwan/postal-code.test.ts +142 -96
  40. package/tests/taiwan/tel.test.ts +33 -42
  41. package/debug.js +0 -21
  42. package/debug.ts +0 -16
@@ -1,31 +1,31 @@
1
1
  import { describe, it, expect, beforeEach } from "vitest"
2
2
  import { email, setLocale } from "../../src"
3
3
 
4
- describe("email() features", () => {
4
+ describe("email(true) features", () => {
5
5
  beforeEach(() => setLocale("en"))
6
6
 
7
7
  describe("multiple domain support", () => {
8
8
  it("should accept multiple allowed domains", () => {
9
- const schema = email({ domain: ["example.com", "company.org"] })
9
+ const schema = email(true, { domain: ["example.com", "company.org"] })
10
10
  expect(schema.parse("test@example.com")).toBe("test@example.com")
11
11
  expect(schema.parse("user@company.org")).toBe("user@company.org")
12
12
  })
13
13
 
14
14
  it("should reject domains not in whitelist", () => {
15
- const schema = email({ domain: ["example.com", "company.org"] })
15
+ const schema = email(true, { domain: ["example.com", "company.org"] })
16
16
  expect(() => schema.parse("test@notallowed.com")).toThrow("Must be from domain: example.com, company.org")
17
17
  })
18
18
  })
19
19
 
20
20
  describe("subdomain support", () => {
21
21
  it("should allow subdomains by default", () => {
22
- const schema = email({ domain: "example.com" })
22
+ const schema = email(true, { domain: "example.com" })
23
23
  expect(schema.parse("test@mail.example.com")).toBe("test@mail.example.com")
24
24
  expect(schema.parse("user@api.example.com")).toBe("user@api.example.com")
25
25
  })
26
26
 
27
27
  it("should reject subdomains when allowSubdomains=false", () => {
28
- const schema = email({ domain: "example.com", allowSubdomains: false })
28
+ const schema = email(true, { domain: "example.com", allowSubdomains: false })
29
29
  expect(schema.parse("test@example.com")).toBe("test@example.com")
30
30
  expect(() => schema.parse("test@mail.example.com")).toThrow("Must be from domain: example.com")
31
31
  })
@@ -33,21 +33,21 @@ describe("email() features", () => {
33
33
 
34
34
  describe("domain blacklist", () => {
35
35
  it("should reject blacklisted domains", () => {
36
- const schema = email({ domainBlacklist: ["spam.com", "fake.org"] })
36
+ const schema = email(true, { domainBlacklist: ["spam.com", "fake.org"] })
37
37
  expect(schema.parse("test@example.com")).toBe("test@example.com")
38
38
  expect(() => schema.parse("test@spam.com")).toThrow("Domain spam.com is not allowed")
39
39
  expect(() => schema.parse("user@fake.org")).toThrow("Domain fake.org is not allowed")
40
40
  })
41
41
 
42
42
  it("should reject blacklisted subdomains when allowSubdomains=true", () => {
43
- const schema = email({ domainBlacklist: ["spam.com"], allowSubdomains: true })
43
+ const schema = email(true, { domainBlacklist: ["spam.com"], allowSubdomains: true })
44
44
  expect(() => schema.parse("test@mail.spam.com")).toThrow("Domain mail.spam.com is not allowed")
45
45
  })
46
46
  })
47
47
 
48
48
  describe("business email validation", () => {
49
49
  it("should reject free email providers when businessOnly=true", () => {
50
- const schema = email({ businessOnly: true })
50
+ const schema = email(true, { businessOnly: true })
51
51
  expect(schema.parse("john@company.com")).toBe("john@company.com")
52
52
  expect(() => schema.parse("john@gmail.com")).toThrow("Only business email addresses are allowed")
53
53
  expect(() => schema.parse("jane@yahoo.com")).toThrow("Only business email addresses are allowed")
@@ -57,7 +57,7 @@ describe("email() features", () => {
57
57
 
58
58
  describe("disposable email detection", () => {
59
59
  it("should reject disposable email addresses when noDisposable=true", () => {
60
- const schema = email({ noDisposable: true })
60
+ const schema = email(true, { noDisposable: true })
61
61
  expect(schema.parse("john@company.com")).toBe("john@company.com")
62
62
  expect(() => schema.parse("test@10minutemail.com")).toThrow("Disposable email addresses are not allowed")
63
63
  expect(() => schema.parse("user@tempmail.org")).toThrow("Disposable email addresses are not allowed")
@@ -67,13 +67,13 @@ describe("email() features", () => {
67
67
 
68
68
  describe("case handling", () => {
69
69
  it("should convert to lowercase by default", () => {
70
- const schema = email()
70
+ const schema = email(true)
71
71
  expect(schema.parse("Test@EXAMPLE.COM")).toBe("test@example.com")
72
72
  expect(schema.parse("USER@Company.Org")).toBe("user@company.org")
73
73
  })
74
74
 
75
75
  it("should preserve case when lowercase=false", () => {
76
- const schema = email({ lowercase: false })
76
+ const schema = email(true, { lowercase: false })
77
77
  expect(schema.parse("Test@EXAMPLE.COM")).toBe("Test@EXAMPLE.COM")
78
78
  expect(schema.parse("USER@Company.Org")).toBe("USER@Company.Org")
79
79
  })
@@ -81,14 +81,14 @@ describe("email() features", () => {
81
81
 
82
82
  describe("excludes functionality", () => {
83
83
  it("should reject emails containing excluded strings", () => {
84
- const schema = email({ excludes: ["test", "demo"] })
84
+ const schema = email(true, { excludes: ["test", "demo"] })
85
85
  expect(schema.parse("john@example.com")).toBe("john@example.com")
86
86
  expect(() => schema.parse("test@example.com")).toThrow("Must include test")
87
87
  expect(() => schema.parse("demo.user@example.com")).toThrow("Must include demo")
88
88
  })
89
89
 
90
90
  it("should handle excludes as array", () => {
91
- const schema = email({ excludes: ["spam", "fake", "test"] })
91
+ const schema = email(true, { excludes: ["spam", "fake", "test"] })
92
92
  expect(() => schema.parse("spam@example.com")).toThrow("Must include spam")
93
93
  expect(() => schema.parse("fake.user@example.com")).toThrow("Must include fake")
94
94
  expect(() => schema.parse("user@test.com")).toThrow("Must include test")
@@ -97,7 +97,7 @@ describe("email() features", () => {
97
97
 
98
98
  describe("transform functionality", () => {
99
99
  it("should apply transform function", () => {
100
- const schema = email({
100
+ const schema = email(true, {
101
101
  transform: (val) => val.replace(/test/g, "user"), // Replace test with user
102
102
  })
103
103
  expect(schema.parse("test@example.com")).toBe("user@example.com")
@@ -105,7 +105,7 @@ describe("email() features", () => {
105
105
  })
106
106
 
107
107
  it("should apply transform after lowercase", () => {
108
- const schema = email({
108
+ const schema = email(true, {
109
109
  lowercase: true,
110
110
  transform: (val) => val.replace(/\+[^@]*/, ""), // Remove + aliases
111
111
  })
@@ -115,14 +115,14 @@ describe("email() features", () => {
115
115
 
116
116
  describe("default value functionality", () => {
117
117
  it("should use defaultValue for empty input when required", () => {
118
- const schema = email({ defaultValue: "default@example.com" })
118
+ const schema = email(true, { defaultValue: "default@example.com" })
119
119
  expect(schema.parse("")).toBe("default@example.com")
120
120
  expect(schema.parse(null)).toBe("default@example.com")
121
121
  expect(schema.parse(undefined)).toBe("default@example.com")
122
122
  })
123
123
 
124
124
  it("should use defaultValue for empty input when not required", () => {
125
- const schema = email({ required: false, defaultValue: "default@example.com" })
125
+ const schema = email(false, { defaultValue: "default@example.com" })
126
126
  expect(schema.parse("")).toBe("default@example.com")
127
127
  expect(schema.parse(null)).toBe("default@example.com")
128
128
  expect(schema.parse(undefined)).toBe("default@example.com")
@@ -131,7 +131,7 @@ describe("email() features", () => {
131
131
 
132
132
  describe("custom i18n messages", () => {
133
133
  it("should use custom messages when provided", () => {
134
- const schema = email({
134
+ const schema = email(true, {
135
135
  domain: "company.com",
136
136
  businessOnly: true,
137
137
  i18n: {
@@ -154,7 +154,7 @@ describe("email() features", () => {
154
154
  })
155
155
 
156
156
  it("should fallback to default messages when custom not provided", () => {
157
- const schema = email({
157
+ const schema = email(true, {
158
158
  noDisposable: true,
159
159
  i18n: {
160
160
  en: {
@@ -172,7 +172,7 @@ describe("email() features", () => {
172
172
 
173
173
  it("should use correct locale for custom messages", () => {
174
174
  setLocale("en")
175
- const schemaEn = email({
175
+ const schemaEn = email(true, {
176
176
  businessOnly: true,
177
177
  i18n: {
178
178
  en: {
@@ -186,7 +186,7 @@ describe("email() features", () => {
186
186
  expect(() => schemaEn.parse("test@gmail.com")).toThrow("English business message")
187
187
 
188
188
  setLocale("zh-TW")
189
- const schemaZh = email({
189
+ const schemaZh = email(true, {
190
190
  businessOnly: true,
191
191
  i18n: {
192
192
  en: {
@@ -203,7 +203,7 @@ describe("email() features", () => {
203
203
 
204
204
  describe("complex scenarios", () => {
205
205
  it("should work with multiple validations", () => {
206
- const schema = email({
206
+ const schema = email(true, {
207
207
  domain: ["company.com", "business.org"],
208
208
  minLength: 10,
209
209
  maxLength: 30,
@@ -222,11 +222,7 @@ describe("email() features", () => {
222
222
  })
223
223
 
224
224
  it("should handle null values correctly when not required", () => {
225
- const schema = email({
226
- required: false,
227
- domain: "example.com",
228
- minLength: 10,
229
- })
225
+ const schema = email(false, { domain: "example.com", minLength: 10 })
230
226
 
231
227
  expect(schema.parse(null)).toBe(null)
232
228
  expect(schema.parse("")).toBe(null)
@@ -235,7 +231,7 @@ describe("email() features", () => {
235
231
  })
236
232
 
237
233
  it("should work with transform, lowercase, and domain validation together", () => {
238
- const schema = email({
234
+ const schema = email(true, {
239
235
  domain: "company.com",
240
236
  lowercase: true,
241
237
  transform: (val) => val.replace(/\+[^@]*/, ""), // Remove + aliases
@@ -1,7 +1,7 @@
1
1
  import { describe, it, expect, beforeEach } from "vitest"
2
2
  import { file, setLocale } from "../../src"
3
3
 
4
- describe("file() features", () => {
4
+ describe("file(true) features", () => {
5
5
  beforeEach(() => setLocale("en"))
6
6
 
7
7
  // Helper function to create mock files for testing
@@ -12,11 +12,11 @@ describe("file() features", () => {
12
12
  const file = new File([blob], name, { type })
13
13
 
14
14
  // Mock the size property since File constructor doesn't always set the exact size
15
- Object.defineProperty(file, 'size', {
15
+ Object.defineProperty(file, "size", {
16
16
  value: size,
17
17
  writable: false,
18
18
  enumerable: true,
19
- configurable: false
19
+ configurable: false,
20
20
  })
21
21
 
22
22
  return file
@@ -24,27 +24,27 @@ describe("file() features", () => {
24
24
 
25
25
  describe("basic file validation", () => {
26
26
  it("should accept valid File objects", () => {
27
- const schema = file()
27
+ const schema = file(true)
28
28
  const mockFile = createMockFile("test.txt", 1024, "text/plain")
29
29
  expect(schema.parse(mockFile)).toBe(mockFile)
30
30
  })
31
31
 
32
32
  it("should reject non-File objects", () => {
33
- const schema = file()
33
+ const schema = file(true)
34
34
  expect(() => schema.parse("not a file")).toThrow()
35
35
  expect(() => schema.parse(123)).toThrow()
36
36
  expect(() => schema.parse({})).toThrow()
37
37
  })
38
38
 
39
39
  it("should handle required validation", () => {
40
- const schema = file()
40
+ const schema = file(true)
41
41
  expect(() => schema.parse(null)).toThrow("Required")
42
42
  expect(() => schema.parse(undefined)).toThrow("Required")
43
43
  expect(() => schema.parse("")).toThrow("Required")
44
44
  })
45
45
 
46
46
  it("should allow null when not required", () => {
47
- const schema = file({ required: false })
47
+ const schema = file(false)
48
48
  expect(schema.parse(null)).toBe(null)
49
49
  expect(schema.parse(undefined)).toBe(null)
50
50
  expect(schema.parse("")).toBe(null)
@@ -53,7 +53,7 @@ describe("file() features", () => {
53
53
 
54
54
  describe("file size validation", () => {
55
55
  it("should validate maximum file size", () => {
56
- const schema = file({ maxSize: 1024 }) // 1KB
56
+ const schema = file(true, { maxSize: 1024 }) // 1KB
57
57
  const smallFile = createMockFile("small.txt", 512, "text/plain")
58
58
  const largeFile = createMockFile("large.txt", 2048, "text/plain")
59
59
 
@@ -62,7 +62,7 @@ describe("file() features", () => {
62
62
  })
63
63
 
64
64
  it("should validate minimum file size", () => {
65
- const schema = file({ minSize: 1024 }) // 1KB
65
+ const schema = file(true, { minSize: 1024 }) // 1KB
66
66
  const smallFile = createMockFile("small.txt", 512, "text/plain")
67
67
  const largeFile = createMockFile("large.txt", 2048, "text/plain")
68
68
 
@@ -71,7 +71,7 @@ describe("file() features", () => {
71
71
  })
72
72
 
73
73
  it("should validate both min and max size", () => {
74
- const schema = file({ minSize: 1024, maxSize: 4096 }) // 1KB - 4KB
74
+ const schema = file(true, { minSize: 1024, maxSize: 4096 }) // 1KB - 4KB
75
75
  const tooSmall = createMockFile("small.txt", 512, "text/plain")
76
76
  const justRight = createMockFile("medium.txt", 2048, "text/plain")
77
77
  const tooLarge = createMockFile("large.txt", 8192, "text/plain")
@@ -84,7 +84,7 @@ describe("file() features", () => {
84
84
 
85
85
  describe("file type validation", () => {
86
86
  it("should accept allowed MIME types", () => {
87
- const schema = file({ type: "text/plain" })
87
+ const schema = file(true, { type: "text/plain" })
88
88
  const textFile = createMockFile("test.txt", 1024, "text/plain")
89
89
  const imageFile = createMockFile("test.jpg", 1024, "image/jpeg")
90
90
 
@@ -93,7 +93,7 @@ describe("file() features", () => {
93
93
  })
94
94
 
95
95
  it("should accept multiple allowed MIME types", () => {
96
- const schema = file({ type: ["text/plain", "image/jpeg", "application/pdf"] })
96
+ const schema = file(true, { type: ["text/plain", "image/jpeg", "application/pdf"] })
97
97
  const textFile = createMockFile("test.txt", 1024, "text/plain")
98
98
  const imageFile = createMockFile("test.jpg", 1024, "image/jpeg")
99
99
  const pdfFile = createMockFile("test.pdf", 1024, "application/pdf")
@@ -106,7 +106,7 @@ describe("file() features", () => {
106
106
  })
107
107
 
108
108
  it("should reject blacklisted MIME types", () => {
109
- const schema = file({ typeBlacklist: ["application/x-executable", "application/x-virus"] })
109
+ const schema = file(true, { typeBlacklist: ["application/x-executable", "application/x-virus"] })
110
110
  const textFile = createMockFile("test.txt", 1024, "text/plain")
111
111
  const exeFile = createMockFile("test.exe", 1024, "application/x-executable")
112
112
 
@@ -117,7 +117,7 @@ describe("file() features", () => {
117
117
 
118
118
  describe("file extension validation", () => {
119
119
  it("should validate single file extension", () => {
120
- const schema = file({ extension: ".txt" })
120
+ const schema = file(true, { extension: ".txt" })
121
121
  const txtFile = createMockFile("test.txt", 1024, "text/plain")
122
122
  const jpgFile = createMockFile("test.jpg", 1024, "image/jpeg")
123
123
 
@@ -126,7 +126,7 @@ describe("file() features", () => {
126
126
  })
127
127
 
128
128
  it("should validate multiple file extensions", () => {
129
- const schema = file({ extension: [".txt", ".pdf", ".doc"] })
129
+ const schema = file(true, { extension: [".txt", ".pdf", ".doc"] })
130
130
  const txtFile = createMockFile("test.txt", 1024, "text/plain")
131
131
  const pdfFile = createMockFile("test.pdf", 1024, "application/pdf")
132
132
  const jpgFile = createMockFile("test.jpg", 1024, "image/jpeg")
@@ -137,7 +137,7 @@ describe("file() features", () => {
137
137
  })
138
138
 
139
139
  it("should handle extensions without dots", () => {
140
- const schema = file({ extension: ["txt", "pdf"] })
140
+ const schema = file(true, { extension: ["txt", "pdf"] })
141
141
  const txtFile = createMockFile("test.txt", 1024, "text/plain")
142
142
  const pdfFile = createMockFile("test.pdf", 1024, "application/pdf")
143
143
 
@@ -146,7 +146,7 @@ describe("file() features", () => {
146
146
  })
147
147
 
148
148
  it("should reject blacklisted extensions", () => {
149
- const schema = file({ extensionBlacklist: [".exe", ".bat", ".cmd"] })
149
+ const schema = file(true, { extensionBlacklist: [".exe", ".bat", ".cmd"] })
150
150
  const txtFile = createMockFile("test.txt", 1024, "text/plain")
151
151
  const exeFile = createMockFile("virus.exe", 1024, "application/x-executable")
152
152
 
@@ -155,8 +155,8 @@ describe("file() features", () => {
155
155
  })
156
156
 
157
157
  it("should handle case sensitivity", () => {
158
- const caseSensitiveSchema = file({ extension: [".txt"], caseSensitive: true })
159
- const caseInsensitiveSchema = file({ extension: [".txt"], caseSensitive: false })
158
+ const caseSensitiveSchema = file(true, { extension: [".txt"], caseSensitive: true })
159
+ const caseInsensitiveSchema = file(true, { extension: [".txt"], caseSensitive: false })
160
160
  const upperCaseFile = createMockFile("test.TXT", 1024, "text/plain")
161
161
 
162
162
  expect(() => caseSensitiveSchema.parse(upperCaseFile)).toThrow("File extension must be one of: .txt")
@@ -166,7 +166,7 @@ describe("file() features", () => {
166
166
 
167
167
  describe("file name validation", () => {
168
168
  it("should validate file name patterns", () => {
169
- const schema = file({ namePattern: /^[a-zA-Z0-9_-]+\.(txt|pdf)$/ })
169
+ const schema = file(true, { namePattern: /^[a-zA-Z0-9_-]+\.(txt|pdf)$/ })
170
170
  const validFile = createMockFile("valid_file-123.txt", 1024, "text/plain")
171
171
  const invalidFile = createMockFile("invalid file!.txt", 1024, "text/plain")
172
172
 
@@ -175,7 +175,7 @@ describe("file() features", () => {
175
175
  })
176
176
 
177
177
  it("should validate file name patterns with strings", () => {
178
- const schema = file({ namePattern: "^report_\\d{4}\\.pdf$" })
178
+ const schema = file(true, { namePattern: "^report_\\d{4}\\.pdf$" })
179
179
  const validFile = createMockFile("report_2023.pdf", 1024, "application/pdf")
180
180
  const invalidFile = createMockFile("report_abc.pdf", 1024, "application/pdf")
181
181
 
@@ -184,7 +184,7 @@ describe("file() features", () => {
184
184
  })
185
185
 
186
186
  it("should reject blacklisted name patterns", () => {
187
- const schema = file({ nameBlacklist: [/temp/i, /^test/] })
187
+ const schema = file(true, { nameBlacklist: [/temp/i, /^test/] })
188
188
  const goodFile = createMockFile("document.pdf", 1024, "application/pdf")
189
189
  const tempFile = createMockFile("TempFile.txt", 1024, "text/plain")
190
190
  const testFile = createMockFile("test_data.csv", 1024, "text/csv")
@@ -195,7 +195,7 @@ describe("file() features", () => {
195
195
  })
196
196
 
197
197
  it("should handle multiple blacklist patterns", () => {
198
- const schema = file({ nameBlacklist: ["virus", /malware/i, /\.(exe|bat)$/] })
198
+ const schema = file(true, { nameBlacklist: ["virus", /malware/i, /\.(exe|bat)$/] })
199
199
  const goodFile = createMockFile("document.pdf", 1024, "application/pdf")
200
200
  const virusFile = createMockFile("virus.txt", 1024, "text/plain")
201
201
  const malwareFile = createMockFile("MALWARE_test.pdf", 1024, "application/pdf")
@@ -210,7 +210,7 @@ describe("file() features", () => {
210
210
 
211
211
  describe("file category validation", () => {
212
212
  it("should validate image files only", () => {
213
- const schema = file({ imageOnly: true })
213
+ const schema = file(true, { imageOnly: true })
214
214
  const imageFile = createMockFile("photo.jpg", 1024, "image/jpeg")
215
215
  const textFile = createMockFile("document.txt", 1024, "text/plain")
216
216
 
@@ -219,7 +219,7 @@ describe("file() features", () => {
219
219
  })
220
220
 
221
221
  it("should validate document files only", () => {
222
- const schema = file({ documentOnly: true })
222
+ const schema = file(true, { documentOnly: true })
223
223
  const pdfFile = createMockFile("document.pdf", 1024, "application/pdf")
224
224
  const imageFile = createMockFile("photo.jpg", 1024, "image/jpeg")
225
225
 
@@ -228,7 +228,7 @@ describe("file() features", () => {
228
228
  })
229
229
 
230
230
  it("should validate video files only", () => {
231
- const schema = file({ videoOnly: true })
231
+ const schema = file(true, { videoOnly: true })
232
232
  const videoFile = createMockFile("movie.mp4", 1024, "video/mp4")
233
233
  const audioFile = createMockFile("song.mp3", 1024, "audio/mpeg")
234
234
 
@@ -237,7 +237,7 @@ describe("file() features", () => {
237
237
  })
238
238
 
239
239
  it("should validate audio files only", () => {
240
- const schema = file({ audioOnly: true })
240
+ const schema = file(true, { audioOnly: true })
241
241
  const audioFile = createMockFile("song.mp3", 1024, "audio/mpeg")
242
242
  const videoFile = createMockFile("movie.mp4", 1024, "video/mp4")
243
243
 
@@ -246,7 +246,7 @@ describe("file() features", () => {
246
246
  })
247
247
 
248
248
  it("should validate archive files only", () => {
249
- const schema = file({ archiveOnly: true })
249
+ const schema = file(true, { archiveOnly: true })
250
250
  const zipFile = createMockFile("archive.zip", 1024, "application/zip")
251
251
  const textFile = createMockFile("document.txt", 1024, "text/plain")
252
252
 
@@ -257,10 +257,10 @@ describe("file() features", () => {
257
257
 
258
258
  describe("transform functionality", () => {
259
259
  it("should apply transform function", () => {
260
- const schema = file({
260
+ const schema = file(true, {
261
261
  transform: (file) => {
262
262
  return new File([file], file.name.toLowerCase(), { type: file.type })
263
- }
263
+ },
264
264
  })
265
265
  const originalFile = createMockFile("TEST.TXT", 1024, "text/plain")
266
266
  const result = schema.parse(originalFile)
@@ -273,7 +273,7 @@ describe("file() features", () => {
273
273
  describe("default value functionality", () => {
274
274
  it("should use defaultValue for empty input when required", () => {
275
275
  const defaultFile = createMockFile("default.txt", 1024, "text/plain")
276
- const schema = file({ defaultValue: defaultFile })
276
+ const schema = file(true, { defaultValue: defaultFile })
277
277
 
278
278
  expect(schema.parse("")).toBe(defaultFile)
279
279
  expect(schema.parse(null)).toBe(defaultFile)
@@ -282,7 +282,7 @@ describe("file() features", () => {
282
282
 
283
283
  it("should use defaultValue for empty input when not required", () => {
284
284
  const defaultFile = createMockFile("default.txt", 1024, "text/plain")
285
- const schema = file({ required: false, defaultValue: defaultFile })
285
+ const schema = file(false, { defaultValue: defaultFile })
286
286
 
287
287
  expect(schema.parse("")).toBe(defaultFile)
288
288
  expect(schema.parse(null)).toBe(defaultFile)
@@ -292,7 +292,7 @@ describe("file() features", () => {
292
292
 
293
293
  describe("custom i18n messages", () => {
294
294
  it("should use custom messages when provided", () => {
295
- const schema = file({
295
+ const schema = file(true, {
296
296
  maxSize: 1024,
297
297
  extension: [".pdf"],
298
298
  imageOnly: true,
@@ -323,7 +323,7 @@ describe("file() features", () => {
323
323
  })
324
324
 
325
325
  it("should fallback to default messages when custom not provided", () => {
326
- const schema = file({
326
+ const schema = file(true, {
327
327
  videoOnly: true,
328
328
  i18n: {
329
329
  en: {
@@ -343,7 +343,7 @@ describe("file() features", () => {
343
343
 
344
344
  it("should use correct locale for custom messages", () => {
345
345
  setLocale("en")
346
- const schemaEn = file({
346
+ const schemaEn = file(true, {
347
347
  imageOnly: true,
348
348
  i18n: {
349
349
  en: {
@@ -358,7 +358,7 @@ describe("file() features", () => {
358
358
  expect(() => schemaEn.parse(nonImageFile)).toThrow("English image message")
359
359
 
360
360
  setLocale("zh-TW")
361
- const schemaZh = file({
361
+ const schemaZh = file(true, {
362
362
  imageOnly: true,
363
363
  i18n: {
364
364
  en: {
@@ -375,7 +375,7 @@ describe("file() features", () => {
375
375
 
376
376
  describe("complex scenarios", () => {
377
377
  it("should work with multiple validations", () => {
378
- const schema = file({
378
+ const schema = file(true, {
379
379
  maxSize: 5 * 1024 * 1024, // 5MB
380
380
  minSize: 1024, // 1KB
381
381
  extension: [".jpg", ".png", ".pdf"],
@@ -397,11 +397,7 @@ describe("file() features", () => {
397
397
  })
398
398
 
399
399
  it("should handle null values correctly when not required", () => {
400
- const schema = file({
401
- required: false,
402
- maxSize: 1024,
403
- extension: [".txt"],
404
- })
400
+ const schema = file(false, { maxSize: 1024, extension: [".txt"] })
405
401
 
406
402
  expect(schema.parse(null)).toBe(null)
407
403
  expect(schema.parse("")).toBe(null)
@@ -412,7 +408,7 @@ describe("file() features", () => {
412
408
  })
413
409
 
414
410
  it("should work with transform and all validations together", () => {
415
- const schema = file({
411
+ const schema = file(true, {
416
412
  maxSize: 2048,
417
413
  extension: [".txt"],
418
414
  namePattern: /^[a-z0-9_-]+\.txt$/,
@@ -429,7 +425,7 @@ describe("file() features", () => {
429
425
  })
430
426
 
431
427
  it("should validate predefined file categories with specific types", () => {
432
- const imageSchema = file({ imageOnly: true, extension: [".jpg", ".png"] })
428
+ const imageSchema = file(true, { imageOnly: true, extension: [".jpg", ".png"] })
433
429
  const jpegFile = createMockFile("photo.jpg", 1024, "image/jpeg")
434
430
  const pngFile = createMockFile("image.png", 1024, "image/png")
435
431
  const gifFile = createMockFile("animated.gif", 1024, "image/gif") // Valid image type but wrong extension
@@ -442,30 +438,30 @@ describe("file() features", () => {
442
438
 
443
439
  describe("edge cases", () => {
444
440
  it("should handle files without extensions", () => {
445
- const schema = file({ extension: [".txt"] })
441
+ const schema = file(true, { extension: [".txt"] })
446
442
  const noExtFile = createMockFile("README", 1024, "text/plain")
447
443
 
448
444
  expect(() => schema.parse(noExtFile)).toThrow("File extension must be one of: .txt")
449
445
  })
450
446
 
451
447
  it("should handle empty file names", () => {
452
- const schema = file({ namePattern: /^.+$/ }) // Must have at least one character
448
+ const schema = file(true, { namePattern: /^.+$/ }) // Must have at least one character
453
449
  const emptyNameFile = createMockFile("", 1024, "text/plain")
454
450
 
455
451
  expect(() => schema.parse(emptyNameFile)).toThrow("File name must match pattern")
456
452
  })
457
453
 
458
454
  it("should handle zero-sized files", () => {
459
- const schema = file({ minSize: 1 })
455
+ const schema = file(true, { minSize: 1 })
460
456
  const emptyFile = createMockFile("empty.txt", 0, "text/plain")
461
457
 
462
458
  expect(() => schema.parse(emptyFile)).toThrow("File size must be at least 1 B")
463
459
  })
464
460
 
465
461
  it("should format file sizes correctly", () => {
466
- const smallSchema = file({ maxSize: 1024 })
467
- const mediumSchema = file({ maxSize: 1024 * 1024 })
468
- const largeSchema = file({ maxSize: 1024 * 1024 * 1024 })
462
+ const smallSchema = file(true, { maxSize: 1024 })
463
+ const mediumSchema = file(true, { maxSize: 1024 * 1024 })
464
+ const largeSchema = file(true, { maxSize: 1024 * 1024 * 1024 })
469
465
 
470
466
  const tooLargeSmall = createMockFile("file.txt", 2048, "text/plain")
471
467
  const tooLargeMedium = createMockFile("file.txt", 2 * 1024 * 1024, "text/plain")
@@ -476,4 +472,4 @@ describe("file() features", () => {
476
472
  expect(() => largeSchema.parse(tooLargeLarge)).toThrow("File size must not exceed 1 GB")
477
473
  })
478
474
  })
479
- })
475
+ })