import { z } from "zod"; import { validationMessage } from "@/shared/i18n"; const EMAIL_PART_COUNT = 2; 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 { const codePoint = character.codePointAt(0); return ( /\s/.test(character) || (codePoint !== undefined && codePoint < ASCII_SPACE) || codePoint === ASCII_DELETE ); } const email = z .string() .trim() .toLowerCase() .max(MAX_EMAIL_LENGTH) .refine( value => value.split("@").length === EMAIL_PART_COUNT && value.split("@").every(Boolean) && value.split("").every(element => !isEmailCharacterInvalid(element)), { error: 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, { error: validationMessage("auth.validation.invalidPasswordLength") }, ); const loginSchema = z.object({ email, password, passwordConfirmation: z.string().optional(), }); const registerSchema = loginSchema.refine( value => value.password === value.passwordConfirmation, { error: validationMessage("auth.validation.passwordsDoNotMatch"), path: ["passwordConfirmation"], }, ); type AuthFormValues = z.input; export { type AuthFormValues, loginSchema, registerSchema };