Skip to content

Commit

Permalink
feat: add zod to deal with type validation
Browse files Browse the repository at this point in the history
  • Loading branch information
BoonHianLim committed Jan 27, 2024
1 parent 02b95b4 commit 1bdfd21
Show file tree
Hide file tree
Showing 4 changed files with 1,816 additions and 46 deletions.
3 changes: 2 additions & 1 deletion apps/challenges/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"supertest": "^6.3.4",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.2",
"turbo": "^1.10.1"
"turbo": "^1.10.1",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/express": "^4.17.21",
Expand Down
56 changes: 25 additions & 31 deletions apps/challenges/src/controllers/season.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Request, Response } from "express";
import asyncHandler from "express-async-handler";

import { isValidObjectId } from "../utils/db";
import { isValidObjectId, paramsSchema } from "../utils/db";
import SeasonService from "../service/seasonService";
import isValidDate from "../utils/checkObjectProperties";
import { z } from "zod";

interface CreateSeasonRequest {
title: string;
Expand Down Expand Up @@ -141,45 +142,37 @@ const getUserAllSeasonRankings = asyncHandler(async (req: Request, res: Response
// @route GET /api/seasons/:seasonID/rankings
// @access Public
const getSeasonRankings = asyncHandler(async (req: Request, res: Response) => {
const { seasonID } = req.params;
const { page, limit } = req.query;

if (!isValidObjectId(seasonID)) {
res.status(400).json({ message: 'Invalid request' });
return;
}
if((page != null && limit == null) || (page == null && limit != null)){
res.status(400).json({ message: 'Invalid request' });
return;
}
if (page != null && typeof page !== "string") {
res.status(400).json({ message: 'Invalid request' });
return;
}
if (limit != null && typeof limit !== "string") {
res.status(400).json({ message: 'Invalid request' });
return;
}

const _page = parseInt((page) as string);
const _limit = parseInt((limit) as string);
try {
const {rankings , rankingsCount} = await SeasonService.getSeasonRankingsByPagination(seasonID, _page, _limit);
const seasonID = paramsSchema.parse(req.params);
const querySchema = z.object({
page: z.number().int().min(0).optional(),
limit: z.number().int().min(1).optional()
}).refine(
data => (data.page && data.limit) && (!data.page && !data.limit),
{ message: "Invalid request" }
);
const { page, limit } = querySchema.parse(req.query);

const { rankings, rankingsCount } = await SeasonService.getSeasonRankingsByPagination(seasonID, page!, limit!);
const metaData = {
page: _page,
limit: _limit,
pageCount: Math.ceil(rankingsCount / _limit) || 0,
page: page,
limit: limit,
pageCount: Math.ceil(rankingsCount / limit!) || 0,
itemCount: rankingsCount || 0,
links: getLinks(seasonID, _page, _limit, rankingsCount)
links: getLinks(seasonID, page!, limit!, rankingsCount)
}
res.setHeader("access-control-expose-headers", "pagination");
res.setHeader("pagination", JSON.stringify(metaData));
res.status(200).json({
rankings: rankings,
_metaData: metaData
});
} catch (error) {
res.status(500).json({ message: 'Internal Server Error' });
} catch (err) {
if(err instanceof z.ZodError){
res.status(400).json({ message: 'Invalid request' });
}else{
res.status(500).json({ message: 'Internal Server Error' });
}
}
});

Expand Down Expand Up @@ -251,7 +244,8 @@ const SeasonController = {
getSeasonRankings,
getUserSeasonRanking,
getUserAllSeasonRankings,
updateSeasonRankings
updateSeasonRankings,
getLinks
};

export { SeasonController as default };
8 changes: 7 additions & 1 deletion apps/challenges/src/utils/db.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import mongoose from 'mongoose';
import { z } from 'zod';

// Helper function to validate ObjectId
function isValidObjectId(id: string): boolean {
return mongoose.Types.ObjectId.isValid(id);
}

export { isValidObjectId };
// Helper zod function to validate ObjectId
const paramsSchema = z.string().refine((val) => {
return mongoose.Types.ObjectId.isValid(val);
});

export { isValidObjectId, paramsSchema };
Loading

0 comments on commit 1bdfd21

Please sign in to comment.