/** * @file SearchParamValidators.ts * Pure validation logic for search parameters * No side effects, no dependencies */ export interface ValidationResult { isValid: boolean; errors: string[]; } export class SearchParamValidators { // Auth validators static validateReturnTo(value: string | null): ValidationResult { if (value === null) return { isValid: true, errors: [] }; if (!value.startsWith('/')) { return { isValid: false, errors: ['returnTo must start with /'] }; } if (value.includes('://') || value.includes('//')) { return { isValid: false, errors: ['returnTo must be a relative path'] }; } return { isValid: true, errors: [] }; } static validateToken(value: string | null): ValidationResult { if (value === null) return { isValid: true, errors: [] }; if (value.length === 0) { return { isValid: false, errors: ['token cannot be empty'] }; } return { isValid: true, errors: [] }; } static validateEmail(value: string | null): ValidationResult { if (value === null) return { isValid: true, errors: [] }; if (!value.includes('@')) { return { isValid: false, errors: ['email must be valid'] }; } return { isValid: true, errors: [] }; } // Sponsor validators static validateCampaignType(value: string | null): ValidationResult { if (value === null) return { isValid: true, errors: [] }; const validTypes = ['leagues', 'teams', 'drivers', 'races', 'platform']; if (!validTypes.includes(value)) { return { isValid: false, errors: [`type must be one of: ${validTypes.join(', ')}`] }; } return { isValid: true, errors: [] }; } // Pagination validators static validatePage(value: string | null): ValidationResult { if (value === null) return { isValid: true, errors: [] }; const num = parseInt(value); if (isNaN(num) || num < 1) { return { isValid: false, errors: ['page must be a positive integer'] }; } return { isValid: true, errors: [] }; } static validateLimit(value: string | null): ValidationResult { if (value === null) return { isValid: true, errors: [] }; const num = parseInt(value); if (isNaN(num) || num < 1) { return { isValid: false, errors: ['limit must be a positive integer'] }; } return { isValid: true, errors: [] }; } // Sorting validators static validateOrder(value: string | null): ValidationResult { if (value === null) return { isValid: true, errors: [] }; if (!['asc', 'desc'].includes(value)) { return { isValid: false, errors: ['order must be asc or desc'] }; } return { isValid: true, errors: [] }; } // Generic validators static validateRequired(value: string | null, fieldName: string): ValidationResult { if (value === null || value.length === 0) { return { isValid: false, errors: [`${fieldName} is required`] }; } return { isValid: true, errors: [] }; } static validateOptional(value: string | null): ValidationResult { return { isValid: true, errors: [] }; } }