diff --git a/src/modules/creator/creator.middleware.ts b/src/modules/creator/creator.middleware.ts new file mode 100644 index 0000000..d71c906 --- /dev/null +++ b/src/modules/creator/creator.middleware.ts @@ -0,0 +1,38 @@ +import { NextFunction, Request, Response } from 'express'; +import { z, ZodError } from 'zod'; +import { sendValidationError } from '../../utils/api-response.utils'; + +export const CreatorIdParamsSchema = z.object({ + id: z.string().trim().min(1, 'Creator ID is required'), +}); + +export type CreatorIdParams = z.infer; + +export const validateCreatorIdParam = ( + req: Request, + res: Response, + next: NextFunction +): void => { + try { + const validatedParams = CreatorIdParamsSchema.parse(req.params); + req.params = { + ...req.params, + ...validatedParams, + }; + next(); + } catch (error) { + if (error instanceof ZodError) { + const details = error.errors.map(err => ({ + field: err.path.join('.'), + message: err.message, + })); + return sendValidationError( + res, + 'Invalid creator route parameters', + details + ); + } + + next(error); + } +}; diff --git a/src/modules/creator/creator.routes.ts b/src/modules/creator/creator.routes.ts index 9f7f690..30261f7 100644 --- a/src/modules/creator/creator.routes.ts +++ b/src/modules/creator/creator.routes.ts @@ -70,4 +70,11 @@ router.all('/:creatorId/profile', (_req, res) => { res.set('Allow', 'GET, PUT').sendStatus(405); }); +/** + * @route GET /api/v1/creators/:id/stats + * @desc Get stats for a creator by id + * @access Public + */ +router.get('/:id/stats', validateCreatorIdParam, getCreatorStats); + export default router; diff --git a/src/modules/creators/creators.controllers.ts b/src/modules/creators/creators.controllers.ts index 46c87e1..4bacfb1 100644 --- a/src/modules/creators/creators.controllers.ts +++ b/src/modules/creators/creators.controllers.ts @@ -103,13 +103,6 @@ export const httpGetCreatorStats: AsyncController = async (req, res, next) => { try { const { id } = req.params; - // Validate creator ID format (basic validation) - if (!id || typeof id !== 'string') { - return sendValidationError(res, 'Invalid creator ID', [ - { field: 'id', message: 'Creator ID must be a valid string' }, - ]); - } - // TODO: Fetch actual creator metrics from database/service // For now, return placeholder data const placeholderMetrics = { diff --git a/src/modules/creators/creators.middleware.ts b/src/modules/creators/creators.middleware.ts new file mode 100644 index 0000000..589f805 --- /dev/null +++ b/src/modules/creators/creators.middleware.ts @@ -0,0 +1,52 @@ +import { NextFunction, Request, Response } from 'express'; +import { z, ZodError } from 'zod'; +import { sendValidationError } from '../../utils/api-response.utils'; + +/** + * Zod schema for creator route parameters. + * Validates that 'id' is a non-empty string. + */ +export const CreatorIdParamsSchema = z.object({ + id: z.string().trim().min(1, 'Creator ID is required'), +}); + +export type CreatorIdParams = z.infer; + +/** + * Middleware to validate creator route parameters (e.g., :id). + * + * Uses Zod to parse and validate 'req.params'. + * If validation fails, returns a 400 Bad Request with details. + * If successful, attaches validated params back to 'req.params' and proceeds. + * + * @example + * router.get('/:id/stats', validateCreatorIdParam, httpGetCreatorStats); + */ +export const validateCreatorIdParam = ( + req: Request, + res: Response, + next: NextFunction +): void => { + try { + const validatedParams = CreatorIdParamsSchema.parse(req.params); + req.params = { + ...req.params, + ...validatedParams, + }; + next(); + } catch (error) { + if (error instanceof ZodError) { + const details = error.errors.map(err => ({ + field: err.path.join('.'), + message: err.message, + })); + return sendValidationError( + res, + 'Invalid creator route parameters', + details + ); + } + + next(error); + } +}; diff --git a/src/modules/creators/creators.routes.ts b/src/modules/creators/creators.routes.ts index d1f752c..b6794ac 100644 --- a/src/modules/creators/creators.routes.ts +++ b/src/modules/creators/creators.routes.ts @@ -47,4 +47,4 @@ creatorsRouter.all('/:id/stats', (_req, res) => { res.set('Allow', 'GET').sendStatus(405); }); -export default creatorsRouter; \ No newline at end of file +export default creatorsRouter;