Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/modules/creator/creator.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import { safeIntParam } from '../../utils/query.utils';
import { parsePublicQuery } from '../../utils/public-query-parse.utils';
import { wrapPublicCreatorListResponse } from '../creators/public-creator-list-envelope.utils';
import { resolveCreatorListLimit } from '../creators/creators.limit.utils';
import { buildCreatorListRequestContext } from '../creators/creator-list-context.utils';
import { normalizeCreatorListPage } from './creator-list-page.guard';
import {
Expand All @@ -28,7 +29,7 @@
label: 'Page',
}),
limit: safeIntParam({
defaultValue: PUBLIC_PAGE_PAGINATION_DEFAULTS.limit,
defaultValue: resolveCreatorListLimit() ?? PUBLIC_PAGE_PAGINATION_DEFAULTS.limit,
min: MIN_PAGE_SIZE,
max: MAX_PAGE_SIZE,
label: 'Limit',
Expand All @@ -41,16 +42,18 @@
try {
const ctx = buildCreatorListRequestContext(req);
const parsed = parsePublicQuery(LegacyCreatorQuerySchema, ctx.query);

if (!parsed.ok) {
return sendValidationError(
res,
'Invalid query parameters',
parsed.details
);
}
const { limit, sortBy, sortOrder } = parsed.data;
const page = normalizeCreatorListPage(parsed.data.page);
const { limit, sortBy, sortOrder } = parsed.data;

Check failure on line 53 in src/modules/creator/creator.controller.ts

View workflow job for this annotation

GitHub Actions / verify

Cannot redeclare block-scoped variable 'sortOrder'.

Check failure on line 53 in src/modules/creator/creator.controller.ts

View workflow job for this annotation

GitHub Actions / verify

Cannot redeclare block-scoped variable 'sortBy'.

Check failure on line 53 in src/modules/creator/creator.controller.ts

View workflow job for this annotation

GitHub Actions / verify

Cannot redeclare block-scoped variable 'limit'.
const page = normalizeCreatorListPage(parsed.data.page);

Check failure on line 54 in src/modules/creator/creator.controller.ts

View workflow job for this annotation

GitHub Actions / verify

Cannot redeclare block-scoped variable 'page'.

const { page, limit, sortBy, sortOrder } = parsed.data;

Check failure on line 56 in src/modules/creator/creator.controller.ts

View workflow job for this annotation

GitHub Actions / verify

Cannot redeclare block-scoped variable 'sortOrder'.

Check failure on line 56 in src/modules/creator/creator.controller.ts

View workflow job for this annotation

GitHub Actions / verify

Cannot redeclare block-scoped variable 'sortBy'.

Check failure on line 56 in src/modules/creator/creator.controller.ts

View workflow job for this annotation

GitHub Actions / verify

Cannot redeclare block-scoped variable 'limit'.

Check failure on line 56 in src/modules/creator/creator.controller.ts

View workflow job for this annotation

GitHub Actions / verify

Cannot redeclare block-scoped variable 'page'.
const sort = parseCreatorSortOptions(sortBy, sortOrder);

const { creators, meta } = await getPaginatedCreators({
Expand Down
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;
}
16 changes: 12 additions & 4 deletions src/modules/creators/creators.schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import { creatorListSortDirectionQueryParam } from './creators.sort-direction.pa
import { withCreatorListQueryStringNormalization } from './creators.query-string.utils';
import { safeIntParam } from '../../utils/query.utils';
import {
MIN_PAGE_SIZE,
MAX_PAGE_SIZE,
MIN_PAGE_SIZE,
MAX_PAGE_SIZE,
} from '../../constants/pagination.constants';

import { PUBLIC_OFFSET_PAGINATION_DEFAULTS } from '../../utils/public-list-query-defaults';
import { DEFAULT_CREATOR_LIST_SORT } from '../../constants/creator-list-sort.constants';
import { resolveCreatorListLimit } from './creators.limit.utils';
import { normalizeCreatorListSearchTerm } from './creators.search-term.utils';

/**
* Validation schema for creator list query parameters.
Expand All @@ -22,7 +25,7 @@ import { DEFAULT_CREATOR_LIST_SORT } from '../../constants/creator-list-sort.con
export const CreatorListQuerySchema = z.object({
// Pagination
limit: safeIntParam({
defaultValue: PUBLIC_OFFSET_PAGINATION_DEFAULTS.limit,
defaultValue: resolveCreatorListLimit() ?? PUBLIC_OFFSET_PAGINATION_DEFAULTS.limit,
min: MIN_PAGE_SIZE,
max: MAX_PAGE_SIZE,
label: 'Limit',
Expand Down Expand Up @@ -50,7 +53,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 @@ -5,6 +5,7 @@ import { mapCreatorListSort } from './creators.sort';
import { CreatorListResponse } from './creators.serializers';
import { wrapPublicCreatorListResponse } from './public-creator-list-envelope.utils';
import { buildOffsetPaginationMeta } from '../../utils/pagination.utils';
import { normalizeCreatorListSearchTerm } from './creators.search-term.utils';

type CreatorListWhere = {
isVerified?: boolean;
Expand Down Expand Up @@ -32,10 +33,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