website refactor
This commit is contained in:
197
apps/website/lib/routing/search-params/SearchParamBuilder.ts
Normal file
197
apps/website/lib/routing/search-params/SearchParamBuilder.ts
Normal file
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* @file SearchParamBuilder.ts
|
||||
* Type-safe builder for constructing search parameter strings
|
||||
* Pure function, no side effects
|
||||
*/
|
||||
|
||||
import { SearchParamValidators } from './SearchParamValidators';
|
||||
|
||||
export class SearchParamBuilder {
|
||||
private params: URLSearchParams;
|
||||
|
||||
constructor() {
|
||||
this.params = new URLSearchParams();
|
||||
}
|
||||
|
||||
// Auth params
|
||||
returnTo(value: string | null): this {
|
||||
if (value !== null) {
|
||||
const validation = SearchParamValidators.validateReturnTo(value);
|
||||
if (!validation.isValid) {
|
||||
throw new Error(`Invalid returnTo: ${validation.errors.join(', ')}`);
|
||||
}
|
||||
this.params.set('returnTo', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
token(value: string | null): this {
|
||||
if (value !== null) {
|
||||
const validation = SearchParamValidators.validateToken(value);
|
||||
if (!validation.isValid) {
|
||||
throw new Error(`Invalid token: ${validation.errors.join(', ')}`);
|
||||
}
|
||||
this.params.set('token', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
email(value: string | null): this {
|
||||
if (value !== null) {
|
||||
const validation = SearchParamValidators.validateEmail(value);
|
||||
if (!validation.isValid) {
|
||||
throw new Error(`Invalid email: ${validation.errors.join(', ')}`);
|
||||
}
|
||||
this.params.set('email', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
error(value: string | null): this {
|
||||
if (value !== null) {
|
||||
this.params.set('error', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
message(value: string | null): this {
|
||||
if (value !== null) {
|
||||
this.params.set('message', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Sponsor params
|
||||
campaignType(value: string | null): this {
|
||||
if (value !== null) {
|
||||
const validation = SearchParamValidators.validateCampaignType(value);
|
||||
if (!validation.isValid) {
|
||||
throw new Error(`Invalid campaign type: ${validation.errors.join(', ')}`);
|
||||
}
|
||||
this.params.set('type', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
campaignId(value: string | null): this {
|
||||
if (value !== null) {
|
||||
this.params.set('campaignId', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Pagination params
|
||||
page(value: number | null): this {
|
||||
if (value !== null) {
|
||||
const validation = SearchParamValidators.validatePage(value.toString());
|
||||
if (!validation.isValid) {
|
||||
throw new Error(`Invalid page: ${validation.errors.join(', ')}`);
|
||||
}
|
||||
this.params.set('page', value.toString());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
limit(value: number | null): this {
|
||||
if (value !== null) {
|
||||
const validation = SearchParamValidators.validateLimit(value.toString());
|
||||
if (!validation.isValid) {
|
||||
throw new Error(`Invalid limit: ${validation.errors.join(', ')}`);
|
||||
}
|
||||
this.params.set('limit', value.toString());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
offset(value: number | null): this {
|
||||
if (value !== null) {
|
||||
this.params.set('offset', value.toString());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Sorting params
|
||||
sortBy(value: string | null): this {
|
||||
if (value !== null) {
|
||||
this.params.set('sortBy', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
order(value: string | null): this {
|
||||
if (value !== null) {
|
||||
const validation = SearchParamValidators.validateOrder(value);
|
||||
if (!validation.isValid) {
|
||||
throw new Error(`Invalid order: ${validation.errors.join(', ')}`);
|
||||
}
|
||||
this.params.set('order', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Filtering params
|
||||
status(value: string | null): this {
|
||||
if (value !== null) {
|
||||
this.params.set('status', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
role(value: string | null): this {
|
||||
if (value !== null) {
|
||||
this.params.set('role', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
tier(value: string | null): this {
|
||||
if (value !== null) {
|
||||
this.params.set('tier', value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Generic setter
|
||||
set(key: string, value: string | null): this {
|
||||
if (value !== null) {
|
||||
this.params.set(key, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Build the query string
|
||||
build(): string {
|
||||
const queryString = this.params.toString();
|
||||
return queryString ? `?${queryString}` : '';
|
||||
}
|
||||
|
||||
// Static factory methods for common scenarios
|
||||
static auth(returnTo?: string | null, token?: string | null, email?: string | null): string {
|
||||
const builder = new SearchParamBuilder();
|
||||
if (returnTo !== undefined) builder.returnTo(returnTo);
|
||||
if (token !== undefined) builder.token(token);
|
||||
if (email !== undefined) builder.email(email);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static pagination(page?: number | null, limit?: number | null): string {
|
||||
const builder = new SearchParamBuilder();
|
||||
if (page !== undefined) builder.page(page);
|
||||
if (limit !== undefined) builder.limit(limit);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static sorting(sortBy?: string | null, order?: string | null): string {
|
||||
const builder = new SearchParamBuilder();
|
||||
if (sortBy !== undefined) builder.sortBy(sortBy);
|
||||
if (order !== undefined) builder.order(order);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static sponsorCampaign(type?: string | null, campaignId?: string | null): string {
|
||||
const builder = new SearchParamBuilder();
|
||||
if (type !== undefined) builder.campaignType(type);
|
||||
if (campaignId !== undefined) builder.campaignId(campaignId);
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user