refactor: migrated to zod 4 and improved form validations

This commit is contained in:
2025-07-22 09:35:43 +05:30
parent 495b6f2129
commit acd600f06d
4 changed files with 29 additions and 15 deletions

8
package-lock.json generated
View File

@@ -65,7 +65,7 @@
"sonner": "^2.0.6", "sonner": "^2.0.6",
"tailwind-merge": "^3.3.1", "tailwind-merge": "^3.3.1",
"vaul": "^1.1.2", "vaul": "^1.1.2",
"zod": "^3.25.76", "zod": "^4.0.5",
"zustand": "^5.0.6" "zustand": "^5.0.6"
}, },
"devDependencies": { "devDependencies": {
@@ -5069,9 +5069,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/zod": { "node_modules/zod": {
"version": "3.25.76", "version": "4.0.5",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.5.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "integrity": "sha512-/5UuuRPStvHXu7RS+gmvRf4NXrNxpSllGwDnCBcJZtQsKrviYXm54yDGV2KYNLT5kq0lHGcl7lqWJLgSaG+tgA==",
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"url": "https://github.com/sponsors/colinhacks" "url": "https://github.com/sponsors/colinhacks"

View File

@@ -67,7 +67,7 @@
"sonner": "^2.0.6", "sonner": "^2.0.6",
"tailwind-merge": "^3.3.1", "tailwind-merge": "^3.3.1",
"vaul": "^1.1.2", "vaul": "^1.1.2",
"zod": "^3.25.76", "zod": "^4.0.5",
"zustand": "^5.0.6" "zustand": "^5.0.6"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -26,8 +26,11 @@ import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { invoke } from "@tauri-apps/api/core"; import { invoke } from "@tauri-apps/api/core";
const searchFormSchema = z.object({ const searchFormSchema = z.object({
url: z.string().min(1, { message: "URL is required" }) url: z.url({
.url({message: "Invalid URL format." }), error: (issue) => issue.input === undefined || issue.input === null || issue.input === ""
? "URL is required"
: "Invalid URL format"
}),
}); });
export default function DownloaderPage() { export default function DownloaderPage() {
@@ -206,6 +209,7 @@ export default function DownloaderPage() {
mode: "onChange", mode: "onChange",
}) })
const watchedUrl = searchForm.watch("url"); const watchedUrl = searchForm.watch("url");
const { errors: searchFormErrors } = searchForm.formState;
function handleSearchSubmit(values: z.infer<typeof searchFormSchema>) { function handleSearchSubmit(values: z.infer<typeof searchFormSchema>) {
setVideoMetadata(null); setVideoMetadata(null);
@@ -371,7 +375,7 @@ export default function DownloaderPage() {
)} )}
<Button <Button
type="submit" type="submit"
disabled={!videoUrl || isMetadataLoading} disabled={!videoUrl || Object.keys(searchFormErrors).length > 0 || isMetadataLoading}
> >
{isMetadataLoading ? ( {isMetadataLoading ? (
<> <>

View File

@@ -29,9 +29,12 @@ import { join } from "@tauri-apps/api/path";
import { formatSpeed } from "@/utils"; import { formatSpeed } from "@/utils";
const websocketPortSchema = z.object({ const websocketPortSchema = z.object({
port: z.coerce.number({ port: z.coerce.number<number>({
required_error: "Websocket Port is required", error: (issue) => issue.input === undefined || issue.input === null || issue.input === ""
invalid_type_error: "Websocket Port must be a valid number", ? "Websocket Port is required"
: "Websocket Port must be a valid number"
}).int({
message: "Websocket Port must be an integer"
}).min(50000, { }).min(50000, {
message: "Websocket Port must be at least 50000" message: "Websocket Port must be at least 50000"
}).max(60000, { }).max(60000, {
@@ -40,13 +43,20 @@ const websocketPortSchema = z.object({
}) })
const proxyUrlSchema = z.object({ const proxyUrlSchema = z.object({
url: z.string().min(1, { message: "Proxy URL is required" }).url({ message: "Invalid URL format" }) url: z.url({
error: (issue) => issue.input === undefined || issue.input === null || issue.input === ""
? "Proxy URL is required"
: "Invalid URL format"
})
}); });
const rateLimitSchema = z.object({ const rateLimitSchema = z.object({
rate_limit: z.coerce.number({ rate_limit: z.coerce.number<number>({
required_error: "Rate Limit is required", error: (issue) => issue.input === undefined || issue.input === null || issue.input === ""
invalid_type_error: "Rate Limit must be a valid number", ? "Rate Limit is required"
: "Rate Limit must be a valid number"
}).int({
message: "Rate Limit must be an integer"
}).min(1024, { }).min(1024, {
message: "Rate Limit must be at least 1024 bytes/s (1 KB/s)" message: "Rate Limit must be at least 1024 bytes/s (1 KB/s)"
}).max(104857600, { }).max(104857600, {