Skip to content
10 changes: 10 additions & 0 deletions src/modules/creators/creators.limit.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { DEFAULT_PAGE_SIZE } from '../../constants/pagination.constants';

/**
* Resolve list limit for public creator list endpoints.
*
* Returns the shared default page size when the incoming page size is omitted.
*/
export function resolveCreatorListLimit(pageSize?: number): number {
return pageSize ?? DEFAULT_PAGE_SIZE;
}
13 changes: 11 additions & 2 deletions src/modules/creators/creators.schemas.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// src/modules/creators/creators.schemas.ts
import { z } from 'zod';
import { creatorListSortDirectionQueryParam } from './creators.sort-direction.parse';
import { creatorListIncludeQueryParam } from './creators.include.parse';
Expand All @@ -12,6 +13,7 @@ import {
CREATOR_LIST_SORT_FIELDS,
DEFAULT_CREATOR_LIST_SORT,
} from '../../constants/creator-list-sort.constants';
import { normalizeCreatorListSearchTerm } from './creators.search-term.utils';

/**
* Validation schema for creator list query parameters.
Expand Down Expand Up @@ -39,7 +41,9 @@ export const CreatorListQuerySchema = z.object({

// Sorting
sort: withCreatorListQueryStringNormalization(
z.enum(CREATOR_LIST_SORT_FIELDS).optional().default(DEFAULT_CREATOR_LIST_SORT)
z.enum(CREATOR_LIST_SORT_FIELDS)
.optional()
.default(DEFAULT_CREATOR_LIST_SORT)
),
order: creatorListSortDirectionQueryParam(),
include: creatorListIncludeQueryParam(),
Expand All @@ -54,7 +58,12 @@ export const CreatorListQuerySchema = z.object({
return val === 'true';
})
),
search: withCreatorListQueryStringNormalization(z.string().optional()),
search: withCreatorListQueryStringNormalization(
z
.string()
.optional()
.transform(val => normalizeCreatorListSearchTerm(val))
),
});

export type CreatorListQueryType = z.infer<typeof CreatorListQuerySchema>;
20 changes: 20 additions & 0 deletions src/modules/creators/creators.search-term.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Normalize free-text creator list search terms before filtering.
*
* Scope is intentionally narrow and reusable:
* - Accepts `string | null | undefined`
* - Trims leading/trailing whitespace
* - Collapses internal whitespace to single spaces
* - Returns `undefined` for empty/whitespace-only values
*/
export function normalizeCreatorListSearchTerm(
term: string | null | undefined
): string | undefined {
if (typeof term !== 'string') {
return undefined;
}

const normalized = term.trim().replace(/\s+/g, ' ');
return normalized === '' ? undefined : normalized;
}

9 changes: 6 additions & 3 deletions src/modules/creators/creators.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CreatorListQueryType } from './creators.schemas';
import { mapCreatorListSort } from './creators.sort';
import { serializeCreatorListResponse, CreatorListResponse } from './creators.serializers';
import { buildOffsetPaginationMeta } from '../../utils/pagination.utils';
import { normalizeCreatorListSearchTerm } from './creators.search-term.utils';

type CreatorListWhere = {
isVerified?: boolean;
Expand Down Expand Up @@ -31,10 +32,12 @@ export async function fetchCreatorList(
where.isVerified = verified;
}

if (search) {
const normalizedSearch = normalizeCreatorListSearchTerm(search);

if (normalizedSearch) {
where.OR = [
{ handle: { contains: search, mode: 'insensitive' } },
{ displayName: { contains: search, mode: 'insensitive' } },
{ handle: { contains: normalizedSearch, mode: 'insensitive' } },
{ displayName: { contains: normalizedSearch, mode: 'insensitive' } },
];
}

Expand Down
Loading