/** * Common Domain - Schemas * * Shared validation primitives used across all domains. */ import { z } from "zod"; import { createPaginationSchema } from "../toolkit/validation/helpers.js"; 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 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", ]); // ============================================================================ // Salesforce and SOQL Validation Schemas // ============================================================================ /** * Schema for validating Salesforce Account IDs */ export const salesforceAccountIdSchema = z.string().min(1, "Salesforce AccountId is required"); /** * Schema for validating Salesforce IDs (15 or 18 characters) */ export const salesforceIdSchema = z .string() .regex(/^[a-zA-Z0-9]{15,18}$/, "Invalid Salesforce ID format") .trim(); /** * Schema for validating non-empty strings */ export const nonEmptyStringSchema = z.string().min(1, "Value cannot be empty").trim(); /** * Schema for validating SOQL field names */ export const soqlFieldNameSchema = z .string() .trim() .regex(/^[A-Za-z0-9_.]+$/, "Invalid SOQL field name"); // ============================================================================ // API Response Schemas // ============================================================================ /** * Schema for action acknowledgement responses (no payload). * Used for endpoints that confirm an operation succeeded without returning data. * * @example * // Controller returns: * return {}; // Empty object as acknowledgement */ export const actionAckResponseSchema = z.object({}); /** * Schema for action responses with a human-readable message. * Used for endpoints that return a confirmation message. * * @example * // Controller returns: * return { message: "SIM top-up completed successfully" }; */ export const actionMessageResponseSchema = z.object({ message: z.string(), }); /** * Schema for error API responses. * Used by the exception filter to return structured errors. */ export const apiErrorResponseSchema = z.object({ success: z.literal(false), error: z.object({ code: z.string(), message: z.string(), details: z.unknown().optional(), }), }); // ============================================================================ // Pagination Schemas // ============================================================================ /** * Schema for pagination query parameters */ export const paginationParamsSchema = createPaginationSchema({ defaultLimit: 20 }); /** * Schema for paginated response data */ export const paginatedResponseSchema = (itemSchema: T) => z.object({ items: z.array(itemSchema), total: z.number().int().nonnegative(), page: z.number().int().positive(), limit: z.number().int().positive(), hasMore: z.boolean(), }); // ============================================================================ // Query Parameter Schemas // ============================================================================ /** * Schema for common filter parameters */ export const filterParamsSchema = z.object({ search: z.string().optional(), sortBy: z.string().optional(), sortOrder: z.enum(["asc", "desc"]).optional(), }); /** * Combined query params schema (pagination + filters) */ export const queryParamsSchema = paginationParamsSchema.merge(filterParamsSchema);