Skip to content

Commit 5a36b19

Browse files
author
nickbar01234
committed
Add Zod schema for contest route
1 parent 981267f commit 5a36b19

File tree

9 files changed

+117
-69
lines changed

9 files changed

+117
-69
lines changed

src/Controllers/fetchUserDetails.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { Response } from 'express';
2-
import { UserData } from '../types';
32

4-
const fetchUserDetails = async (
3+
const fetchUserDetails = async <T, U>(
54
options: { username: string; limit: number; year: number },
65
res: Response,
76
query: string,
8-
formatData?: (data: UserData) => {},
7+
formatData?: (data: T) => U
98
) => {
109
try {
1110
const response = await fetch('https://leetcode.com/graphql', {
@@ -19,7 +18,7 @@ const fetchUserDetails = async (
1918
variables: {
2019
username: options.username, //username required
2120
limit: options.limit, //only for submission
22-
year: options.year
21+
year: options.year,
2322
},
2423
}),
2524
});
@@ -30,10 +29,9 @@ const fetchUserDetails = async (
3029
return res.send(result);
3130
}
3231

33-
if(formatData == null) {
32+
if (formatData == null) {
3433
return res.json(result.data);
3534
}
36-
3735

3836
return res.json(formatData(result.data));
3937
} catch (err) {

src/FormatUtils/formatter.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { ZodType } from 'zod';
2+
3+
export const withSchema =
4+
<T, U>(schema: ZodType<T>, formatter: (data: T) => U) =>
5+
(input: T) =>
6+
formatter(schema.parse(input));

src/FormatUtils/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1+
import { userContest } from '../schema';
2+
import { withSchema } from './formatter';
3+
import { formatContestData as _formatContestData } from './userData';
4+
15
export * from './userData';
26
export * from './problemData';
37
export * from './trendingTopicData';
4-
export * from './userProfileData';
8+
export * from './userProfileData';
9+
10+
export const formatContestData = withSchema(userContest, _formatContestData);

src/FormatUtils/userData.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { UserContest } from 'src/schema';
12
import { UserData } from '../types';
23

34
export const formatUserData = (data: UserData) => ({
@@ -25,7 +26,7 @@ export const formatBadgesData = (data: UserData) => ({
2526
activeBadge: data.matchedUser.activeBadge,
2627
});
2728

28-
export const formatContestData = (data: UserData) => ({
29+
export const formatContestData = (data: UserContest) => ({
2930
contestAttend: data.userContestRanking?.attendedContestsCount,
3031
contestRating: data.userContestRanking?.rating,
3132
contestGlobalRanking: data.userContestRanking?.globalRanking,
@@ -70,15 +71,15 @@ export const formatSubmissionCalendarData = (data: UserData) => ({
7071
});
7172

7273
export const formatSkillStats = (data: UserData) => ({
73-
fundamental: data.matchedUser.tagProblemCounts.fundamental,
74-
intermediate: data.matchedUser.tagProblemCounts.intermediate,
75-
advanced: data.matchedUser.tagProblemCounts.advanced,
74+
fundamental: data.matchedUser.tagProblemCounts.fundamental,
75+
intermediate: data.matchedUser.tagProblemCounts.intermediate,
76+
advanced: data.matchedUser.tagProblemCounts.advanced,
7677
});
7778

7879
export const formatLanguageStats = (data: UserData) => ({
79-
languageProblemCount: data.matchedUser.languageProblemCount,
80+
languageProblemCount: data.matchedUser.languageProblemCount,
8081
});
8182

8283
export const formatProgressStats = (data: UserData) => ({
83-
numAcceptedQuestions: data.userProfileUserQuestionProgressV2
84+
numAcceptedQuestions: data.userProfileUserQuestionProgressV2,
8485
});

src/__tests__/msw/mockData/singleUserContests.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
"trendDirection": "NONE",
1010
"problemsSolved": 0,
1111
"totalProblems": 3,
12-
"finishTimeInSeconds": 0
12+
"finishTimeInSeconds": 0,
13+
"contest": {
14+
"title": "Weekly contest",
15+
"startTime": ""
16+
}
1317
}
1418
]
1519
}

src/leetCode.ts

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const userData = (req: TransformedUserDataRequest, res: Response) => {
1010
req.body,
1111
res,
1212
gqlQueries.userProfileQuery,
13-
formatUtils.formatUserData,
13+
formatUtils.formatUserData
1414
);
1515
};
1616

@@ -19,7 +19,7 @@ export const userBadges = (req: TransformedUserDataRequest, res: Response) => {
1919
req.body,
2020
res,
2121
gqlQueries.userProfileQuery,
22-
formatUtils.formatBadgesData,
22+
formatUtils.formatBadgesData
2323
);
2424
};
2525

@@ -28,7 +28,7 @@ export const userContest = (req: TransformedUserDataRequest, res: Response) => {
2828
req.body,
2929
res,
3030
gqlQueries.contestQuery,
31-
formatUtils.formatContestData,
31+
formatUtils.formatContestData
3232
);
3333
};
3434

@@ -40,7 +40,7 @@ export const userContestHistory = (
4040
req.body,
4141
res,
4242
gqlQueries.contestQuery,
43-
formatUtils.formatContestHistoryData,
43+
formatUtils.formatContestHistoryData
4444
);
4545
};
4646

@@ -52,7 +52,7 @@ export const solvedProblem = (
5252
req.body,
5353
res,
5454
gqlQueries.userProfileQuery,
55-
formatUtils.formatSolvedProblemsData,
55+
formatUtils.formatSolvedProblemsData
5656
);
5757
};
5858

@@ -61,7 +61,7 @@ export const submission = (req: TransformedUserDataRequest, res: Response) => {
6161
req.body,
6262
res,
6363
gqlQueries.submissionQuery,
64-
formatUtils.formatSubmissionData,
64+
formatUtils.formatSubmissionData
6565
);
6666
};
6767

@@ -73,7 +73,7 @@ export const acSubmission = (
7373
req.body,
7474
res,
7575
gqlQueries.AcSubmissionQuery,
76-
formatUtils.formatAcSubmissionData,
76+
formatUtils.formatAcSubmissionData
7777
);
7878
};
7979

@@ -101,7 +101,7 @@ export const userProfile = (req: Request, res: Response) => {
101101
res,
102102
gqlQueries.getUserProfileQuery,
103103
formatUtils.formatUserProfileData
104-
)
104+
);
105105
};
106106

107107
export const languageStats = (req: Request, res: Response) => {
@@ -110,7 +110,7 @@ export const languageStats = (req: Request, res: Response) => {
110110
res,
111111
gqlQueries.languageStatsQuery,
112112
formatUtils.formatLanguageStats
113-
)
113+
);
114114
};
115115

116116
export const progress = (req: Request, res: Response) => {
@@ -119,7 +119,7 @@ export const progress = (req: Request, res: Response) => {
119119
res,
120120
gqlQueries.userQuestionProgressQuery,
121121
formatUtils.formatProgressStats
122-
)
122+
);
123123
};
124124

125125
//Problems Details
@@ -128,16 +128,12 @@ export const dailyProblem = (_req: Request, res: Response) => {
128128
res,
129129
gqlQueries.dailyProblemQuery,
130130
null,
131-
formatUtils.formatDailyData,
131+
formatUtils.formatDailyData
132132
);
133133
};
134134

135135
export const dailyProblemRaw = (_req: Request, res: Response) => {
136-
controllers.fetchSingleProblem(
137-
res,
138-
gqlQueries.dailyProblemQuery,
139-
null,
140-
);
136+
controllers.fetchSingleProblem(res, gqlQueries.dailyProblemQuery, null);
141137
};
142138

143139
export const selectProblem = (req: Request, res: Response) => {
@@ -147,7 +143,7 @@ export const selectProblem = (req: Request, res: Response) => {
147143
res,
148144
gqlQueries.selectProblemQuery,
149145
title,
150-
formatUtils.formatQuestionData,
146+
formatUtils.formatQuestionData
151147
);
152148
} else {
153149
res.status(400).json({
@@ -161,22 +157,23 @@ export const selectProblem = (req: Request, res: Response) => {
161157
export const selectProblemRaw = (req: Request, res: Response) => {
162158
const title = req.query.titleSlug as string;
163159
if (title !== undefined) {
164-
controllers.fetchSingleProblem(
165-
res,
166-
gqlQueries.selectProblemQuery,
167-
title,
168-
);
160+
controllers.fetchSingleProblem(res, gqlQueries.selectProblemQuery, title);
169161
} else {
170162
res.status(400).json({
171163
error: 'Missing or invalid query parameter: titleSlug',
172164
solution: 'put query after select',
173165
example: 'localhost:3000/select?titleSlug=two-sum',
174166
});
175167
}
176-
}
168+
};
177169

178170
export const problems = (
179-
req: Request<{}, {}, {}, { limit: number; skip: number; tags: string; difficulty: string }>,
171+
req: Request<
172+
{},
173+
{},
174+
{},
175+
{ limit: number; skip: number; tags: string; difficulty: string }
176+
>,
180177
res: Response
181178
) => {
182179
const difficulty = req.query.difficulty;
@@ -198,7 +195,9 @@ export const officialSolution = (req: Request, res: Response) => {
198195
if (!titleSlug) {
199196
return res.status(400).json({ error: 'Missing titleSlug query parameter' });
200197
}
201-
return controllers.handleRequest(res, gqlQueries.officialSolutionQuery, { titleSlug });
198+
return controllers.handleRequest(res, gqlQueries.officialSolutionQuery, {
199+
titleSlug,
200+
});
202201
};
203202

204203
// Discussion
@@ -211,15 +210,13 @@ export const trendingCategoryTopics = (_req: Request, res: Response) => {
211210
formatUtils.formatTrendingCategoryTopicData,
212211
gqlQueries.trendingDiscussQuery
213212
);
214-
}
215-
else {
213+
} else {
216214
res.status(400).json({
217215
error: 'Missing or invalid query parameter: limit',
218216
solution: 'put query after discussion',
219217
example: 'localhost:3000/trendingDiscuss?first=20',
220218
});
221219
}
222-
223220
};
224221

225222
export const discussTopic = (req: Request, res: Response) => {
@@ -242,8 +239,6 @@ export const discussComments = (req: Request, res: Response) => {
242239
});
243240
};
244241

245-
246-
247242
/* ----- Migrated to new functions -> these will be deleted -----*/
248243
export const languageStats_ = (_req: Request, res: Response) => {
249244
const username = _req.query.username as string;
@@ -253,8 +248,7 @@ export const languageStats_ = (_req: Request, res: Response) => {
253248
res,
254249
gqlQueries.languageStatsQuery
255250
);
256-
}
257-
else {
251+
} else {
258252
res.status(400).json({
259253
error: 'Missing or invalid query parameter: username',
260254
solution: 'put query after discussion',
@@ -263,7 +257,6 @@ export const languageStats_ = (_req: Request, res: Response) => {
263257
}
264258
};
265259

266-
267260
export const userProfileCalendar_ = (req: Request, res: Response) => {
268261
const { username, year } = req.query;
269262

@@ -281,9 +274,14 @@ export const userProfileCalendar_ = (req: Request, res: Response) => {
281274

282275
export const userProfile_ = (req: Request, res: Response) => {
283276
const user = req.params.id;
284-
controllers.fetchUserProfile(res, gqlQueries.getUserProfileQuery, {
285-
username: user,
286-
}, formatUtils.formatUserProfileData);
277+
controllers.fetchUserProfile(
278+
res,
279+
gqlQueries.getUserProfileQuery,
280+
{
281+
username: user,
282+
},
283+
formatUtils.formatUserProfileData
284+
);
287285
};
288286

289287
export const dailyQuestion_ = (_req: Request, res: Response) => {
@@ -295,33 +293,28 @@ export const skillStats_ = (req: Request, res: Response) => {
295293
controllers.handleRequest(res, gqlQueries.skillStatsQuery, { username });
296294
};
297295

298-
export const userProfileUserQuestionProgressV2_ = (req: Request, res: Response) => {
296+
export const userProfileUserQuestionProgressV2_ = (
297+
req: Request,
298+
res: Response
299+
) => {
299300
const username = req.params.username;
300-
controllers.handleRequest(res, gqlQueries.userQuestionProgressQuery, { username });
301+
controllers.handleRequest(res, gqlQueries.userQuestionProgressQuery, {
302+
username,
303+
});
301304
};
302305

303306
export const userContestRankingInfo_ = (req: Request, res: Response) => {
304307
const { username } = req.params;
305-
controllers.handleRequest(res, gqlQueries.userContestRankingInfoQuery, { username });
308+
controllers.handleRequest(res, gqlQueries.userContestRankingInfoQuery, {
309+
username,
310+
});
306311
};
307312

308313
//limiting is not supported in the contests unlike problems
309-
export const allContests = (
310-
_req: Request,
311-
res: Response
312-
) => {
313-
controllers.fetchAllContests(
314-
res,
315-
gqlQueries.allContestQuery
316-
);
314+
export const allContests = (_req: Request, res: Response) => {
315+
controllers.fetchAllContests(res, gqlQueries.allContestQuery);
317316
};
318317

319-
export const upcomingContests = (
320-
_req: Request,
321-
res: Response
322-
) => {
323-
controllers.fetchUpcomingContests(
324-
res,
325-
gqlQueries.allContestQuery
326-
);
318+
export const upcomingContests = (_req: Request, res: Response) => {
319+
controllers.fetchUpcomingContests(res, gqlQueries.allContestQuery);
327320
};

src/schema/common/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import z from "zod";
2+
3+
export const badge = z.object({
4+
name: z.string(),
5+
icon: z.string()
6+
})

0 commit comments

Comments
 (0)