Files
gridpilot.gg/apps/website/lib/routing/search-params/SearchParamValidators.ts
2026-01-16 01:00:03 +01:00

91 lines
3.0 KiB
TypeScript

/**
* @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: [] };
}
}