/** * Input validation utilities */ /** * Date format regex (YYYY-MM-DD) */ const DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/; /** * Validate date format (YYYY-MM-DD) */ export function isValidDate(date: string): boolean { if (!DATE_REGEX.test(date)) { return false; } // Check if it's a valid date const d = new Date(date); return d instanceof Date && !isNaN(d.getTime()); } /** * Validate date format and throw if invalid */ export function validateDate(date: string, fieldName: string): void { if (!isValidDate(date)) { throw new Error(`${fieldName} must be in YYYY-MM-DD format`); } } /** * Validate date range */ export function validateDateRange(startDate: string, endDate: string): void { validateDate(startDate, 'start_date'); validateDate(endDate, 'end_date'); if (new Date(startDate) >= new Date(endDate)) { throw new Error('start_date must be before end_date'); } } /** * Validate required field */ export function validateRequired( value: T | null | undefined, fieldName: string ): asserts value is T { if (value === null || value === undefined) { throw new Error(`${fieldName} is required`); } } /** * Validate array is not empty */ export function validateNonEmptyArray( value: T[], fieldName: string ): asserts value is [T, ...T[]] { if (!Array.isArray(value) || value.length === 0) { throw new Error(`${fieldName} must be a non-empty array`); } } /** * Validate number is positive */ export function validatePositive(value: number, fieldName: string): void { if (value <= 0) { throw new Error(`${fieldName} must be positive`); } } /** * Validate number is within range */ export function validateRange( value: number, min: number, max: number, fieldName: string ): void { if (value < min || value > max) { throw new Error(`${fieldName} must be between ${min} and ${max}`); } } /** * Validate URL format */ export function validateUrl(url: string, fieldName: string): void { try { new URL(url); } catch { throw new Error(`${fieldName} must be a valid URL`); } }