import { z } from "zod"; import { validationMessage } from "@/shared/i18n"; const ASCII_SPACE = 32; const ASCII_DELETE = 127; const MAX_EMAIL_LENGTH = 254; const MIN_PASSWORD_BYTES = 12; const MAX_PASSWORD_BYTES = 72; function isEmailCharacterInvalid(character: string): boolean { return ( /\s/.test(character) || character.charCodeAt(0) < ASCII_SPACE || character.charCodeAt(0) === ASCII_DELETE ); } const email = z .string() .trim() .toLowerCase() .max(MAX_EMAIL_LENGTH) .refine( (value) => value.split("@").length === 2 && value.split("@").every(Boolean) && !value.split("").some(isEmailCharacterInvalid), validationMessage("auth.validation.invalidEmail"), ); const password = z .string() .refine( (value) => new TextEncoder().encode(value).length >= MIN_PASSWORD_BYTES && new TextEncoder().encode(value).length <= MAX_PASSWORD_BYTES, validationMessage("auth.validation.invalidPasswordLength"), ); const loginSchema = z.object({ email, password, passwordConfirmation: z.string().optional(), }); const registerSchema = loginSchema.refine( (value) => value.password === value.passwordConfirmation, (value) => ({ path: ["passwordConfirmation"], ...validationMessage("auth.validation.passwordsDoNotMatch")(value), }), ); type AuthFormValues = z.input; export { type AuthFormValues, loginSchema, registerSchema };