From 88a1d271319a9b1445aca2bf6c191b81df5dd9b9 Mon Sep 17 00:00:00 2001 From: Shoaib Ansari Date: Sun, 29 Mar 2026 09:26:44 +0530 Subject: [PATCH] fix(creators): validate include query values --- .../creators/creators.include.parse.test.ts | 35 ++++++++++++++++++ .../creators/creators.include.parse.ts | 36 +++++++++++++++++++ src/modules/creators/creators.schemas.ts | 2 ++ 3 files changed, 73 insertions(+) create mode 100644 src/modules/creators/creators.include.parse.test.ts create mode 100644 src/modules/creators/creators.include.parse.ts diff --git a/src/modules/creators/creators.include.parse.test.ts b/src/modules/creators/creators.include.parse.test.ts new file mode 100644 index 0000000..b126497 --- /dev/null +++ b/src/modules/creators/creators.include.parse.test.ts @@ -0,0 +1,35 @@ +import { strict as assert } from 'assert'; +import { CreatorListQuerySchema } from './creators.schemas'; +import { parsePublicQuery } from '../../utils/public-query-parse.utils'; + +function run() { + const parsed = CreatorListQuerySchema.parse({ + limit: '10', + offset: '0', + include: 'stats', + }); + + assert.deepEqual(parsed.include, ['stats']); + + const invalid = parsePublicQuery(CreatorListQuerySchema, { + limit: '10', + offset: '0', + include: 'unknown', + }); + + assert.equal(invalid.ok, false); + if (invalid.ok) { + throw new Error('Expected invalid include value to fail validation'); + } + + assert.deepEqual(invalid.details, [ + { + field: 'include.0', + message: "Invalid enum value. Expected 'stats', received 'unknown'", + }, + ]); + + console.log('creators.include.parse tests passed'); +} + +run(); diff --git a/src/modules/creators/creators.include.parse.ts b/src/modules/creators/creators.include.parse.ts new file mode 100644 index 0000000..af09d19 --- /dev/null +++ b/src/modules/creators/creators.include.parse.ts @@ -0,0 +1,36 @@ +import { z } from 'zod'; +import { normalizeCreatorListQueryStringValue } from './creators.query-string.utils'; + +export const CREATOR_LIST_INCLUDE_VALUES = ['stats'] as const; + +export type CreatorListIncludeValue = + (typeof CREATOR_LIST_INCLUDE_VALUES)[number]; + +const creatorListIncludeValueEnum = z.enum(CREATOR_LIST_INCLUDE_VALUES); + +function normalizeCreatorListIncludeValue(value: unknown): unknown { + if (Array.isArray(value)) { + return value.map(item => normalizeCreatorListQueryStringValue(item)); + } + + const normalized = normalizeCreatorListQueryStringValue(value); + if (typeof normalized !== 'string') { + return normalized; + } + + return normalized.split(',').map(part => part.trim()); +} + +/** + * Zod schema for the creator list `include` query parameter. + * + * - Supports comma-separated include values such as `stats`. + * - Rejects unsupported include values through normal schema validation. + * - Can be reused anywhere creator list query params are parsed. + */ +export function creatorListIncludeQueryParam() { + return z.preprocess( + normalizeCreatorListIncludeValue, + z.array(creatorListIncludeValueEnum).optional() + ); +} diff --git a/src/modules/creators/creators.schemas.ts b/src/modules/creators/creators.schemas.ts index 703e24d..1ef9286 100644 --- a/src/modules/creators/creators.schemas.ts +++ b/src/modules/creators/creators.schemas.ts @@ -1,5 +1,6 @@ import { z } from 'zod'; import { creatorListSortDirectionQueryParam } from './creators.sort-direction.parse'; +import { creatorListIncludeQueryParam } from './creators.include.parse'; import { withCreatorListQueryStringNormalization } from './creators.query-string.utils'; import { safeIntParam } from '../../utils/query.utils'; import { @@ -41,6 +42,7 @@ export const CreatorListQuerySchema = z.object({ z.enum(CREATOR_LIST_SORT_FIELDS).optional().default(DEFAULT_CREATOR_LIST_SORT) ), order: creatorListSortDirectionQueryParam(), + include: creatorListIncludeQueryParam(), // Filters verified: withCreatorListQueryStringNormalization(