Skip to content

Commit c297410

Browse files
authored
Merge pull request #81 from nickbar01234/feature/contest-schema
added zod parsing for contest route
2 parents 981267f + c3031a2 commit c297410

File tree

8 files changed

+75
-15
lines changed

8 files changed

+75
-15
lines changed

src/Controllers/fetchUserDetails.ts

Lines changed: 5 additions & 7 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,15 +29,14 @@ 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) {
4038
console.error('Error: ', err);
41-
return res.send(err);
39+
return res.send(err.message);
4240
}
4341
};
4442

src/FormatUtils/formatter.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { ZodType } from 'zod';
2+
3+
export const withSchema =
4+
<T, U>(schema: ZodType<T>, formatter: (data: T) => U) =>
5+
(input: T) => {
6+
const result = schema.safeParse(input);
7+
if (result.success) {
8+
return formatter(result.data);
9+
}
10+
throw new Error(result.error.message);
11+
};

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 '../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": "Biweekly Contest 52",
15+
"startTime": 1621089000
16+
}
1317
}
1418
]
1519
}

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().optional(),
6+
});

src/schema/contests.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import z from 'zod';
2+
import { badge } from './common';
3+
4+
const userContestRanking = z.object({
5+
attendedContestsCount: z.number().nonnegative(),
6+
badge: badge.nullable(),
7+
globalRanking: z.number().nonnegative(),
8+
rating: z.number().nonnegative(),
9+
totalParticipants: z.number().nonnegative(),
10+
topPercentage: z.number().nonnegative(),
11+
});
12+
13+
const userContestRankingHistory = z.object({
14+
attended: z.boolean(),
15+
rating: z.number().nonnegative(),
16+
ranking: z.number().nonnegative(),
17+
trendDirection: z.string(),
18+
problemsSolved: z.number().nonnegative(),
19+
totalProblems: z.number().positive(),
20+
finishTimeInSeconds: z.number().nonnegative(),
21+
contest: z.object({
22+
title: z.string(),
23+
startTime: z.number(),
24+
}),
25+
});
26+
27+
const userContest = z.object({
28+
userContestRanking: userContestRanking.nullable(),
29+
userContestRankingHistory: z.array(userContestRankingHistory),
30+
});
31+
32+
export default userContest;
33+
export type UserContest = z.infer<typeof userContest>;

src/schema/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as userContest, UserContest } from './contests';

0 commit comments

Comments
 (0)