Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions src/Controllers/fetchUserDetails.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Response } from 'express';
import { UserData } from '../types';

const fetchUserDetails = async (
const fetchUserDetails = async <T, U>(
options: { username: string; limit: number; year: number },
res: Response,
query: string,
formatData?: (data: UserData) => {},
formatData?: (data: T) => U
) => {
try {
const response = await fetch('https://leetcode.com/graphql', {
Expand All @@ -19,7 +18,7 @@ const fetchUserDetails = async (
variables: {
username: options.username, //username required
limit: options.limit, //only for submission
year: options.year
year: options.year,
},
}),
});
Expand All @@ -30,15 +29,14 @@ const fetchUserDetails = async (
return res.send(result);
}

if(formatData == null) {
if (formatData == null) {
return res.json(result.data);
}


return res.json(formatData(result.data));
} catch (err) {
console.error('Error: ', err);
return res.send(err);
return res.send(err.message);
}
};

Expand Down
11 changes: 11 additions & 0 deletions src/FormatUtils/formatter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ZodType } from 'zod';

export const withSchema =
<T, U>(schema: ZodType<T>, formatter: (data: T) => U) =>
(input: T) => {
const result = schema.safeParse(input);
if (result.success) {
return formatter(result.data);
}
throw new Error(result.error.message);
};
8 changes: 7 additions & 1 deletion src/FormatUtils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { userContest } from '../schema';
import { withSchema } from './formatter';
import { formatContestData as _formatContestData } from './userData';

export * from './userData';
export * from './problemData';
export * from './trendingTopicData';
export * from './userProfileData';
export * from './userProfileData';

export const formatContestData = withSchema(userContest, _formatContestData);
13 changes: 7 additions & 6 deletions src/FormatUtils/userData.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { UserContest } from '../schema';
import { UserData } from '../types';

export const formatUserData = (data: UserData) => ({
Expand Down Expand Up @@ -25,7 +26,7 @@ export const formatBadgesData = (data: UserData) => ({
activeBadge: data.matchedUser.activeBadge,
});

export const formatContestData = (data: UserData) => ({
export const formatContestData = (data: UserContest) => ({
contestAttend: data.userContestRanking?.attendedContestsCount,
contestRating: data.userContestRanking?.rating,
contestGlobalRanking: data.userContestRanking?.globalRanking,
Expand Down Expand Up @@ -70,15 +71,15 @@ export const formatSubmissionCalendarData = (data: UserData) => ({
});

export const formatSkillStats = (data: UserData) => ({
fundamental: data.matchedUser.tagProblemCounts.fundamental,
intermediate: data.matchedUser.tagProblemCounts.intermediate,
advanced: data.matchedUser.tagProblemCounts.advanced,
fundamental: data.matchedUser.tagProblemCounts.fundamental,
intermediate: data.matchedUser.tagProblemCounts.intermediate,
advanced: data.matchedUser.tagProblemCounts.advanced,
});

export const formatLanguageStats = (data: UserData) => ({
languageProblemCount: data.matchedUser.languageProblemCount,
languageProblemCount: data.matchedUser.languageProblemCount,
});

export const formatProgressStats = (data: UserData) => ({
numAcceptedQuestions: data.userProfileUserQuestionProgressV2
numAcceptedQuestions: data.userProfileUserQuestionProgressV2,
});
6 changes: 5 additions & 1 deletion src/__tests__/msw/mockData/singleUserContests.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
"trendDirection": "NONE",
"problemsSolved": 0,
"totalProblems": 3,
"finishTimeInSeconds": 0
"finishTimeInSeconds": 0,
"contest": {
"title": "Biweekly Contest 52",
"startTime": 1621089000
}
}
]
}
Expand Down
103 changes: 48 additions & 55 deletions src/leetCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const userData = (req: TransformedUserDataRequest, res: Response) => {
req.body,
res,
gqlQueries.userProfileQuery,
formatUtils.formatUserData,
formatUtils.formatUserData
);
};

Expand All @@ -19,7 +19,7 @@ export const userBadges = (req: TransformedUserDataRequest, res: Response) => {
req.body,
res,
gqlQueries.userProfileQuery,
formatUtils.formatBadgesData,
formatUtils.formatBadgesData
);
};

Expand All @@ -28,7 +28,7 @@ export const userContest = (req: TransformedUserDataRequest, res: Response) => {
req.body,
res,
gqlQueries.contestQuery,
formatUtils.formatContestData,
formatUtils.formatContestData
);
};

Expand All @@ -40,7 +40,7 @@ export const userContestHistory = (
req.body,
res,
gqlQueries.contestQuery,
formatUtils.formatContestHistoryData,
formatUtils.formatContestHistoryData
);
};

Expand All @@ -52,7 +52,7 @@ export const solvedProblem = (
req.body,
res,
gqlQueries.userProfileQuery,
formatUtils.formatSolvedProblemsData,
formatUtils.formatSolvedProblemsData
);
};

Expand All @@ -61,7 +61,7 @@ export const submission = (req: TransformedUserDataRequest, res: Response) => {
req.body,
res,
gqlQueries.submissionQuery,
formatUtils.formatSubmissionData,
formatUtils.formatSubmissionData
);
};

Expand All @@ -73,7 +73,7 @@ export const acSubmission = (
req.body,
res,
gqlQueries.AcSubmissionQuery,
formatUtils.formatAcSubmissionData,
formatUtils.formatAcSubmissionData
);
};

Expand Down Expand Up @@ -101,7 +101,7 @@ export const userProfile = (req: Request, res: Response) => {
res,
gqlQueries.getUserProfileQuery,
formatUtils.formatUserProfileData
)
);
};

export const languageStats = (req: Request, res: Response) => {
Expand All @@ -110,7 +110,7 @@ export const languageStats = (req: Request, res: Response) => {
res,
gqlQueries.languageStatsQuery,
formatUtils.formatLanguageStats
)
);
};

export const progress = (req: Request, res: Response) => {
Expand All @@ -119,7 +119,7 @@ export const progress = (req: Request, res: Response) => {
res,
gqlQueries.userQuestionProgressQuery,
formatUtils.formatProgressStats
)
);
};

//Problems Details
Expand All @@ -128,16 +128,12 @@ export const dailyProblem = (_req: Request, res: Response) => {
res,
gqlQueries.dailyProblemQuery,
null,
formatUtils.formatDailyData,
formatUtils.formatDailyData
);
};

export const dailyProblemRaw = (_req: Request, res: Response) => {
controllers.fetchSingleProblem(
res,
gqlQueries.dailyProblemQuery,
null,
);
controllers.fetchSingleProblem(res, gqlQueries.dailyProblemQuery, null);
};

export const selectProblem = (req: Request, res: Response) => {
Expand All @@ -147,7 +143,7 @@ export const selectProblem = (req: Request, res: Response) => {
res,
gqlQueries.selectProblemQuery,
title,
formatUtils.formatQuestionData,
formatUtils.formatQuestionData
);
} else {
res.status(400).json({
Expand All @@ -161,22 +157,23 @@ export const selectProblem = (req: Request, res: Response) => {
export const selectProblemRaw = (req: Request, res: Response) => {
const title = req.query.titleSlug as string;
if (title !== undefined) {
controllers.fetchSingleProblem(
res,
gqlQueries.selectProblemQuery,
title,
);
controllers.fetchSingleProblem(res, gqlQueries.selectProblemQuery, title);
} else {
res.status(400).json({
error: 'Missing or invalid query parameter: titleSlug',
solution: 'put query after select',
example: 'localhost:3000/select?titleSlug=two-sum',
});
}
}
};

export const problems = (
req: Request<{}, {}, {}, { limit: number; skip: number; tags: string; difficulty: string }>,
req: Request<
{},
{},
{},
{ limit: number; skip: number; tags: string; difficulty: string }
>,
res: Response
) => {
const difficulty = req.query.difficulty;
Expand All @@ -198,7 +195,9 @@ export const officialSolution = (req: Request, res: Response) => {
if (!titleSlug) {
return res.status(400).json({ error: 'Missing titleSlug query parameter' });
}
return controllers.handleRequest(res, gqlQueries.officialSolutionQuery, { titleSlug });
return controllers.handleRequest(res, gqlQueries.officialSolutionQuery, {
titleSlug,
});
};

// Discussion
Expand All @@ -211,15 +210,13 @@ export const trendingCategoryTopics = (_req: Request, res: Response) => {
formatUtils.formatTrendingCategoryTopicData,
gqlQueries.trendingDiscussQuery
);
}
else {
} else {
res.status(400).json({
error: 'Missing or invalid query parameter: limit',
solution: 'put query after discussion',
example: 'localhost:3000/trendingDiscuss?first=20',
});
}

};

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



/* ----- Migrated to new functions -> these will be deleted -----*/
export const languageStats_ = (_req: Request, res: Response) => {
const username = _req.query.username as string;
Expand All @@ -253,8 +248,7 @@ export const languageStats_ = (_req: Request, res: Response) => {
res,
gqlQueries.languageStatsQuery
);
}
else {
} else {
res.status(400).json({
error: 'Missing or invalid query parameter: username',
solution: 'put query after discussion',
Expand All @@ -263,7 +257,6 @@ export const languageStats_ = (_req: Request, res: Response) => {
}
};


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

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

export const userProfile_ = (req: Request, res: Response) => {
const user = req.params.id;
controllers.fetchUserProfile(res, gqlQueries.getUserProfileQuery, {
username: user,
}, formatUtils.formatUserProfileData);
controllers.fetchUserProfile(
res,
gqlQueries.getUserProfileQuery,
{
username: user,
},
formatUtils.formatUserProfileData
);
};

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

export const userProfileUserQuestionProgressV2_ = (req: Request, res: Response) => {
export const userProfileUserQuestionProgressV2_ = (
req: Request,
res: Response
) => {
const username = req.params.username;
controllers.handleRequest(res, gqlQueries.userQuestionProgressQuery, { username });
controllers.handleRequest(res, gqlQueries.userQuestionProgressQuery, {
username,
});
};

export const userContestRankingInfo_ = (req: Request, res: Response) => {
const { username } = req.params;
controllers.handleRequest(res, gqlQueries.userContestRankingInfoQuery, { username });
controllers.handleRequest(res, gqlQueries.userContestRankingInfoQuery, {
username,
});
};

//limiting is not supported in the contests unlike problems
export const allContests = (
_req: Request,
res: Response
) => {
controllers.fetchAllContests(
res,
gqlQueries.allContestQuery
);
export const allContests = (_req: Request, res: Response) => {
controllers.fetchAllContests(res, gqlQueries.allContestQuery);
};

export const upcomingContests = (
_req: Request,
res: Response
) => {
controllers.fetchUpcomingContests(
res,
gqlQueries.allContestQuery
);
export const upcomingContests = (_req: Request, res: Response) => {
controllers.fetchUpcomingContests(res, gqlQueries.allContestQuery);
};
6 changes: 6 additions & 0 deletions src/schema/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import z from 'zod';

export const badge = z.object({
name: z.string(),
icon: z.string().optional(),
});
Loading