46 lines
1.7 KiB
TypeScript
46 lines
1.7 KiB
TypeScript
import { z } from "zod"
|
|
|
|
// Plain z.string(), not z.preprocess(): preprocess widens the schema's INPUT type to
|
|
// `unknown`, so zodResolver produced a Resolver<{email: unknown, …}> that could not be
|
|
// assigned to useForm<LoginValues> — the long-standing type error on the login page.
|
|
// Form fields always yield strings (RHF defaults them to ""), so the null/undefined
|
|
// coercion it was guarding against cannot occur here.
|
|
function requiredString(message: string) {
|
|
return z.string().min(1, message)
|
|
}
|
|
|
|
// Email validation schema
|
|
export const emailSchema = z.string().min(1, "Email is required").email("Enter a valid email")
|
|
|
|
// Login schema (email + password) for reuse across the app
|
|
export const loginSchema = z.object({
|
|
email: emailSchema,
|
|
password: requiredString("Password is required")
|
|
.refine((val) => val.length >= 8, { message: "Password must be at least 8 characters" })
|
|
.refine((val) => /[A-Z]/.test(val), {
|
|
message: "Password must contain at least one uppercase letter",
|
|
})
|
|
.refine((val) => /[a-z]/.test(val), {
|
|
message: "Password must contain at least one lowercase letter",
|
|
})
|
|
.refine((val) => /[0-9]/.test(val), { message: "Password must contain at least one number" })
|
|
.refine((val) => /[!@#$%^&*(),.?":{}|<>\[\]\\/`~;'+=-]/.test(val), {
|
|
message: "Password must contain at least one special character",
|
|
}),
|
|
})
|
|
|
|
export type LoginValues = z.infer<typeof loginSchema>
|
|
|
|
// Helper to validate email synchronously
|
|
export function validateEmail(value: unknown) {
|
|
const result = emailSchema.safeParse(value)
|
|
return result.success ? { valid: true, value: result.data } : { valid: false, error: result.error }
|
|
}
|
|
|
|
export default {
|
|
emailSchema,
|
|
loginSchema,
|
|
validateEmail,
|
|
}
|
|
|