website refactor
This commit is contained in:
208
apps/website/lib/routing/search-params/SearchParamParser.ts
Normal file
208
apps/website/lib/routing/search-params/SearchParamParser.ts
Normal file
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* @file SearchParamParser.ts
|
||||
* Type-safe parser for search parameters from URL
|
||||
* Returns Result type for clean error handling
|
||||
*/
|
||||
|
||||
import { Result } from '@/lib/contracts/Result';
|
||||
import { SearchParamValidators } from './SearchParamValidators';
|
||||
|
||||
export interface ParsedAuthParams {
|
||||
returnTo?: string | null;
|
||||
token?: string | null;
|
||||
email?: string | null;
|
||||
error?: string | null;
|
||||
message?: string | null;
|
||||
}
|
||||
|
||||
export interface ParsedSponsorParams {
|
||||
type?: string | null;
|
||||
campaignId?: string | null;
|
||||
}
|
||||
|
||||
export interface ParsedPaginationParams {
|
||||
page?: number;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export interface ParsedSortingParams {
|
||||
sortBy?: string | null;
|
||||
order?: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
export interface ParsedFilterParams {
|
||||
status?: string | null;
|
||||
role?: string | null;
|
||||
tier?: string | null;
|
||||
}
|
||||
|
||||
export class SearchParamParser {
|
||||
// Parse auth parameters
|
||||
static parseAuth(params: URLSearchParams): Result<ParsedAuthParams, string> {
|
||||
const errors: string[] = [];
|
||||
|
||||
const returnTo = params.get('returnTo');
|
||||
if (returnTo !== null) {
|
||||
const validation = SearchParamValidators.validateReturnTo(returnTo);
|
||||
if (!validation.isValid) {
|
||||
errors.push(...validation.errors);
|
||||
}
|
||||
}
|
||||
|
||||
const token = params.get('token');
|
||||
if (token !== null) {
|
||||
const validation = SearchParamValidators.validateToken(token);
|
||||
if (!validation.isValid) {
|
||||
errors.push(...validation.errors);
|
||||
}
|
||||
}
|
||||
|
||||
const email = params.get('email');
|
||||
if (email !== null) {
|
||||
const validation = SearchParamValidators.validateEmail(email);
|
||||
if (!validation.isValid) {
|
||||
errors.push(...validation.errors);
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
return Result.err(errors.join(', '));
|
||||
}
|
||||
|
||||
return Result.ok({
|
||||
returnTo: params.get('returnTo'),
|
||||
token: params.get('token'),
|
||||
email: params.get('email'),
|
||||
error: params.get('error'),
|
||||
message: params.get('message'),
|
||||
});
|
||||
}
|
||||
|
||||
// Parse sponsor parameters
|
||||
static parseSponsor(params: URLSearchParams): Result<ParsedSponsorParams, string> {
|
||||
const errors: string[] = [];
|
||||
|
||||
const type = params.get('type');
|
||||
if (type !== null) {
|
||||
const validation = SearchParamValidators.validateCampaignType(type);
|
||||
if (!validation.isValid) {
|
||||
errors.push(...validation.errors);
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
return Result.err(errors.join(', '));
|
||||
}
|
||||
|
||||
return Result.ok({
|
||||
type: params.get('type'),
|
||||
campaignId: params.get('campaignId'),
|
||||
});
|
||||
}
|
||||
|
||||
// Parse pagination parameters
|
||||
static parsePagination(params: URLSearchParams): Result<ParsedPaginationParams, string> {
|
||||
const result: ParsedPaginationParams = {};
|
||||
const errors: string[] = [];
|
||||
|
||||
const page = params.get('page');
|
||||
if (page !== null) {
|
||||
const validation = SearchParamValidators.validatePage(page);
|
||||
if (!validation.isValid) {
|
||||
errors.push(...validation.errors);
|
||||
} else {
|
||||
result.page = parseInt(page);
|
||||
}
|
||||
}
|
||||
|
||||
const limit = params.get('limit');
|
||||
if (limit !== null) {
|
||||
const validation = SearchParamValidators.validateLimit(limit);
|
||||
if (!validation.isValid) {
|
||||
errors.push(...validation.errors);
|
||||
} else {
|
||||
result.limit = parseInt(limit);
|
||||
}
|
||||
}
|
||||
|
||||
const offset = params.get('offset');
|
||||
if (offset !== null) {
|
||||
const num = parseInt(offset);
|
||||
if (!isNaN(num)) {
|
||||
result.offset = num;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
return Result.err(errors.join(', '));
|
||||
}
|
||||
|
||||
return Result.ok(result);
|
||||
}
|
||||
|
||||
// Parse sorting parameters
|
||||
static parseSorting(params: URLSearchParams): Result<ParsedSortingParams, string> {
|
||||
const errors: string[] = [];
|
||||
|
||||
const order = params.get('order');
|
||||
if (order !== null) {
|
||||
const validation = SearchParamValidators.validateOrder(order);
|
||||
if (!validation.isValid) {
|
||||
errors.push(...validation.errors);
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
return Result.err(errors.join(', '));
|
||||
}
|
||||
|
||||
return Result.ok({
|
||||
sortBy: params.get('sortBy'),
|
||||
order: (params.get('order') as 'asc' | 'desc') || undefined,
|
||||
});
|
||||
}
|
||||
|
||||
// Parse filter parameters
|
||||
static parseFilters(params: URLSearchParams): Result<ParsedFilterParams, string> {
|
||||
return Result.ok({
|
||||
status: params.get('status'),
|
||||
role: params.get('role'),
|
||||
tier: params.get('tier'),
|
||||
});
|
||||
}
|
||||
|
||||
// Parse all parameters at once
|
||||
static parseAll(params: URLSearchParams): Result<
|
||||
{
|
||||
auth: ParsedAuthParams;
|
||||
sponsor: ParsedSponsorParams;
|
||||
pagination: ParsedPaginationParams;
|
||||
sorting: ParsedSortingParams;
|
||||
filters: ParsedFilterParams;
|
||||
},
|
||||
string
|
||||
> {
|
||||
const authResult = this.parseAuth(params);
|
||||
if (authResult.isErr()) return Result.err(authResult.getError());
|
||||
|
||||
const sponsorResult = this.parseSponsor(params);
|
||||
if (sponsorResult.isErr()) return Result.err(sponsorResult.getError());
|
||||
|
||||
const paginationResult = this.parsePagination(params);
|
||||
if (paginationResult.isErr()) return Result.err(paginationResult.getError());
|
||||
|
||||
const sortingResult = this.parseSorting(params);
|
||||
if (sortingResult.isErr()) return Result.err(sortingResult.getError());
|
||||
|
||||
const filtersResult = this.parseFilters(params);
|
||||
|
||||
return Result.ok({
|
||||
auth: authResult.unwrap(),
|
||||
sponsor: sponsorResult.unwrap(),
|
||||
pagination: paginationResult.unwrap(),
|
||||
sorting: sortingResult.unwrap(),
|
||||
filters: filtersResult.unwrap(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user