website refactor
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @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: [] };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user