206 lines
5.3 KiB
TypeScript
206 lines
5.3 KiB
TypeScript
/**
|
|
* @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;
|
|
}
|
|
|
|
// Wizard params
|
|
step(value: string | null): this {
|
|
if (value !== null) {
|
|
this.params.set('step', 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();
|
|
}
|
|
}
|