From 3781eb5931d8d2deeada2234c6ed77faadfa9972 Mon Sep 17 00:00:00 2001 From: bamiebot Date: Fri, 27 Mar 2026 08:25:39 +0100 Subject: [PATCH] feat: add creator list sort mapper --- src/modules/creators/creators.schemas.ts | 11 +++--- src/modules/creators/creators.sort.ts | 46 ++++++++++++++++++++++++ src/modules/creators/creators.utils.ts | 4 +-- 3 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 src/modules/creators/creators.sort.ts diff --git a/src/modules/creators/creators.schemas.ts b/src/modules/creators/creators.schemas.ts index f6e6f21..57ca5ef 100644 --- a/src/modules/creators/creators.schemas.ts +++ b/src/modules/creators/creators.schemas.ts @@ -1,4 +1,8 @@ import { z } from 'zod'; +import { + CREATOR_LIST_SORT_OPTIONS, + CREATOR_LIST_SORT_ORDERS, +} from './creators.sort'; /** * Validation schema for creator list query parameters. @@ -29,11 +33,8 @@ export const CreatorListQuerySchema = z.object({ }), // Sorting - sort: z - .enum(['createdAt', 'updatedAt', 'displayName', 'handle']) - .optional() - .default('createdAt'), - order: z.enum(['asc', 'desc']).optional().default('desc'), + sort: z.enum(CREATOR_LIST_SORT_OPTIONS).optional().default('createdAt'), + order: z.enum(CREATOR_LIST_SORT_ORDERS).optional().default('desc'), // Filters verified: z diff --git a/src/modules/creators/creators.sort.ts b/src/modules/creators/creators.sort.ts new file mode 100644 index 0000000..a785411 --- /dev/null +++ b/src/modules/creators/creators.sort.ts @@ -0,0 +1,46 @@ +import { Prisma } from '@prisma/client'; + +/** + * Public sort options accepted by creator list endpoints. + * These remain stable even if the internal query implementation changes. + */ +export const CREATOR_LIST_SORT_OPTIONS = [ + 'createdAt', + 'updatedAt', + 'displayName', + 'handle', +] as const; + +export const CREATOR_LIST_SORT_ORDERS = ['asc', 'desc'] as const; + +export type CreatorListSortOption = (typeof CREATOR_LIST_SORT_OPTIONS)[number]; +export type CreatorListSortOrder = (typeof CREATOR_LIST_SORT_ORDERS)[number]; + +const CREATOR_LIST_SORT_FIELD_MAP: Record< + CreatorListSortOption, + keyof Prisma.CreatorProfileOrderByWithRelationInput +> = { + createdAt: 'createdAt', + updatedAt: 'updatedAt', + displayName: 'displayName', + handle: 'handle', +}; + +/** + * Map a public sort option into an internal Prisma orderBy object. + * Throws for unsupported values so invalid sort input is never passed through silently. + */ +export function mapCreatorListSort( + sort: string, + order: CreatorListSortOrder +): Prisma.CreatorProfileOrderByWithRelationInput { + const field = CREATOR_LIST_SORT_FIELD_MAP[sort as CreatorListSortOption]; + + if (!field) { + throw new Error(`Unsupported creator sort option: ${sort}`); + } + + return { + [field]: order, + } as Prisma.CreatorProfileOrderByWithRelationInput; +} diff --git a/src/modules/creators/creators.utils.ts b/src/modules/creators/creators.utils.ts index 1404333..dac7b96 100644 --- a/src/modules/creators/creators.utils.ts +++ b/src/modules/creators/creators.utils.ts @@ -1,6 +1,7 @@ import { prisma } from '../../utils/prisma.utils'; import { CreatorProfile } from '../../types/profile.types'; import { CreatorListQueryType } from './creators.schemas'; +import { mapCreatorListSort } from './creators.sort'; type CreatorListWhere = { isVerified?: boolean; @@ -35,8 +36,7 @@ export async function fetchCreatorList( ]; } - // Build order by clause - const orderBy = { [sort]: order }; + const orderBy = mapCreatorListSort(sort, order); // Fetch creators and total count in parallel const [creators, total] = await Promise.all([