/** * Common Domain - Schemas * * Shared validation primitives used across all domains. */ import { z } from "zod"; export const emailSchema = z .string() .email("Please enter a valid email address") .toLowerCase() .trim(); export const passwordSchema = z .string() .min(8, "Password must be at least 8 characters") .regex(/[A-Z]/, "Password must contain at least one uppercase letter") .regex(/[a-z]/, "Password must contain at least one lowercase letter") .regex(/[0-9]/, "Password must contain at least one number") .regex(/[^A-Za-z0-9]/, "Password must contain at least one special character"); export const nameSchema = z.string().min(1, "Name is required").max(100, "Name must be less than 100 characters").trim(); export const phoneSchema = z .string() .regex(/^[+]?[0-9\s\-()]{7,20}$/u, "Please enter a valid phone number") .trim(); export const addressSchema = z.object({ street: z.string().max(200, "Street address is too long").nullable(), streetLine2: z.string().max(200, "Street address line 2 is too long").nullable(), city: z.string().max(100, "City name is too long").nullable(), state: z.string().max(100, "State/Prefecture name is too long").nullable(), postalCode: z.string().max(20, "Postal code is too long").nullable(), country: z.string().max(100, "Country name is too long").nullable(), }); export const requiredAddressSchema = z.object({ street: z.string().min(1, "Street address is required").max(200, "Street address is too long").trim(), streetLine2: z.string().max(200, "Street address line 2 is too long").optional(), city: z.string().min(1, "City is required").max(100, "City name is too long").trim(), state: z .string() .min(1, "State/Prefecture is required") .max(100, "State/Prefecture name is too long") .trim(), postalCode: z.string().min(1, "Postal code is required").max(20, "Postal code is too long").trim(), country: z.string().min(1, "Country is required").max(100, "Country name is too long").trim(), }); export const countryCodeSchema = z.string().length(2, "Country code must be 2 characters"); export const currencyCodeSchema = z.string().length(3, "Currency code must be 3 characters"); export const timestampSchema = z.string().datetime("Invalid timestamp format"); export const dateSchema = z.string().date("Invalid date format"); export const moneyAmountSchema = z.number().int().nonnegative("Amount must be non-negative"); export const percentageSchema = z.number().min(0).max(100, "Percentage must be between 0 and 100"); export const genderEnum = z.enum(["male", "female", "other"]); export const statusEnum = z.enum(["active", "inactive", "pending", "suspended"]); export const priorityEnum = z.enum(["low", "medium", "high", "urgent"]); export const categoryEnum = z.enum(["technical", "billing", "account", "general"]); export const billingCycleEnum = z.enum(["Monthly", "Quarterly", "Annually", "Onetime", "Free"]); export const subscriptionBillingCycleEnum = z.enum([ "Monthly", "Quarterly", "Semi-Annually", "Annually", "Biennially", "Triennially", "One-time", "Free", ]);