├── .dockerignore ├── .gitignore ├── .prettierrc ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── bun.lockb ├── docker-compose.yml ├── jest.config.ts ├── package-lock.json ├── package.json ├── public └── demo │ ├── contribute.png │ ├── demo1.png │ ├── demo10.png │ ├── demo11.png │ ├── demo12.png │ ├── demo13.png │ ├── demo14.png │ ├── demo15.png │ ├── demo16.png │ ├── demo17.png │ ├── demo2.png │ ├── demo3.png │ ├── demo4.png │ ├── demo5.png │ ├── demo6.png │ ├── demo7.png │ ├── demo8.png │ └── demo9.png ├── setupTests.ts ├── src ├── .DS_Store ├── Controllers │ ├── fetchDataRawFormat.ts │ ├── fetchDiscussion.ts │ ├── fetchProblems.ts │ ├── fetchSingleProblem.ts │ ├── fetchUserDetails.ts │ └── index.ts ├── FormatUtils │ ├── index.ts │ ├── problemData.ts │ ├── trendingTopicData.ts │ └── userData.ts ├── GQLQueries │ ├── contest.ts │ ├── dailyProblem.ts │ ├── index.ts │ ├── languageStats.ts │ ├── newQueries.ts │ ├── problemList.ts │ ├── recentAcSubmit.ts │ ├── recentSubmit.ts │ ├── selectProblem.ts │ ├── trendingDiscuss.ts │ └── userProfile.ts ├── __tests__ │ ├── msw │ │ ├── handlers.ts │ │ ├── index.ts │ │ └── mockData │ │ │ ├── dailyProblem.json │ │ │ ├── index.ts │ │ │ ├── problems.json │ │ │ ├── recentAcSubmissionList.json │ │ │ ├── recentSubmissions.json │ │ │ ├── selectProblem.json │ │ │ ├── singleUser.json │ │ │ └── singleUserContests.json │ ├── problemData.spec.ts │ └── userData.spec.ts ├── app.ts ├── config.ts ├── index.ts ├── leetCode.ts └── types.ts ├── tsconfig.json └── vercel.json /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | leetCode-api.txt 4 | 5 | dist 6 | 7 | .DS_Store -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Wanna Contribute 🤔?? 2 | 3 | ## With Docker 🐳 4 | 5 | - #### 🍴 Create a Fork of this Repo to Your GitHub Account 6 | 7 |  8 | 9 | - #### 🧑🏽💻 Clone Your Repo Locally 10 | 11 | first open your CLI and clone the repo locally. But don't forget to replace **username** with your GitHub username 12 | 13 | ```bash 14 | git clone https://github.com/username/alfa-leetcode-api.git 15 | ``` 16 | 17 | - #### 👋🏽 Go to the Project Folder 18 | 19 | ```bash 20 | cd alfa-leetcode-api 21 | ``` 22 | 23 | - #### 🚀 Start the Project with Docker 24 | ```bash 25 | docker compose up 26 | ``` 27 | 28 | ## Without Docker 🐳❌ 29 | 30 | - #### 🍴 Create a Fork of this repo to Your GitHub Account 31 | 32 |  33 | 34 | - #### 🧑🏽💻 Clone Your Repo Locally 35 | 36 | first open your CLI and clone the repo locally. But don't forget to replace **username** with your GitHub username 37 | 38 | ```bash 39 | git clone https://github.com/username/alfa-leetcode-api.git 40 | ``` 41 | 42 | - #### 👋🏽 Go to the Project Folder 43 | 44 | ```bash 45 | cd alfa-leetcode-api 46 | ``` 47 | 48 | - #### 🚀 Install Required Modules 49 | 50 | ```bash 51 | npm install 52 | ``` 53 | 54 | - #### 🏃🏽♂️Run the Project Locally 55 | 56 | ```bash 57 | npm run dev 58 | ``` 59 | 60 | ## 61 | 62 | - #### 💡 Make Changes & Create Pull Requests 63 | 64 | Make changes as needed and push them to your GitHub repository with proper **commit message**. From there, create a **PR (Pull Request)** and submit it. 65 | 66 | - #### 📌 Additional Tip 67 | 68 | Try to create a new branch relevant to your work. For example - `fix:xyz-issue` 69 | 70 | 📝Note - It's not Necessary for contribution but it will help me to merge it. 71 | 72 | # 73 | 74 | #### 📌 Special Thanks to [@sazsu](https://github.com/sazsu) for improving the documentation 75 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-alpine 2 | 3 | WORKDIR /usr/src/app 4 | 5 | COPY package*.json ./ 6 | 7 | RUN npm install 8 | 9 | COPY . . 10 | 11 | # need to remove when we use dev command 12 | # RUN npm run build 13 | 14 | EXPOSE 3000 15 | 16 | # CMD ["node", "dist/index.js"] 17 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Arghya Das 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
Given a binary array nums
and an integer goal
, return the number of non-empty subarrays with a sum goal
.
A subarray is a contiguous part of the array.
\r\n\r\n\r\n
Example 1:
\r\n\r\n\r\nInput: nums = [1,0,1,0,1], goal = 2\r\nOutput: 4\r\nExplanation: The 4 subarrays are bolded and underlined below:\r\n[1,0,1,0,1]\r\n[1,0,1,0,1]\r\n[1,0,1,0,1]\r\n[1,0,1,0,1]\r\n\r\n\r\n
Example 2:
\r\n\r\n\r\nInput: nums = [0,0,0,0,0], goal = 0\r\nOutput: 15\r\n\r\n\r\n
\r\n
Constraints:
\r\n\r\n1 <= nums.length <= 3 * 104
nums[i]
is either 0
or 1
.0 <= goal <= nums.length
Compiled with clang 17
using the latest C++ 20 standard, and libstdc++
provided by GCC 11.
Your code is compiled with level two optimization (-O2
). AddressSanitizer is also enabled to help detect out-of-bounds and use-after-free bugs.
Most standard library headers are already included automatically for your convenience.
\"], \"java\": [\"Java\", \"OpenJDK 21
. Using compile arguments: --enable-preview --release 21
Most standard library headers are already included automatically for your convenience.
\\r\\nIncludes Pair
class from https://docs.oracle.com/javase/8/javafx/api/javafx/util/Pair.html.
Python 2.7.12
.
Most libraries are already imported automatically for your convenience, such as array, bisect, collections. If you need more libraries, you can import it yourself.
\\r\\n\\r\\nFor Map/TreeMap data structure, you may use sortedcontainers library.
\\r\\n\\r\\nNote that Python 2.7 will not be maintained past 2020. For the latest Python, please choose Python3 instead.
\"], \"c\": [\"C\", \"Compiled with gcc 11
using the gnu11 standard.
Your code is compiled with level one optimization (-O2
). AddressSanitizer is also enabled to help detect out-of-bounds and use-after-free bugs.
Most standard library headers are already included automatically for your convenience.
\\r\\n\\r\\nFor hash table operations, you may use uthash. \\\"uthash.h\\\" is included by default. Below are some examples:
\\r\\n\\r\\n1. Adding an item to a hash.\\r\\n
\\r\\nstruct hash_entry {\\r\\n int id; /* we'll use this field as the key */\\r\\n char name[10];\\r\\n UT_hash_handle hh; /* makes this structure hashable */\\r\\n};\\r\\n\\r\\nstruct hash_entry *users = NULL;\\r\\n\\r\\nvoid add_user(struct hash_entry *s) {\\r\\n HASH_ADD_INT(users, id, s);\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n
2. Looking up an item in a hash:\\r\\n
\\r\\nstruct hash_entry *find_user(int user_id) {\\r\\n struct hash_entry *s;\\r\\n HASH_FIND_INT(users, &user_id, s);\\r\\n return s;\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n
3. Deleting an item in a hash:\\r\\n
\\r\\nvoid delete_user(struct hash_entry *user) {\\r\\n HASH_DEL(users, user); \\r\\n}\\r\\n\\r\\n\"], \"csharp\": [\"C#\", \"
C# 12 with .NET 8 runtime
\"], \"javascript\": [\"JavaScript\", \"Node.js 20.10.0
.
Your code is run with --harmony
flag, enabling new ES6 features.
lodash.js library is included by default.
\\r\\n\\r\\nFor Priority Queue / Queue data structures, you may use 5.4.0 version of datastructures-js/priority-queue and 4.2.3 version of datastructures-js/queue.
\"], \"ruby\": [\"Ruby\", \"Ruby 3.2
Some common data structure implementations are provided in the Algorithms module: https://www.rubydoc.info/github/kanwei/algorithms/Algorithms
\"], \"swift\": [\"Swift\", \"Swift 5.9
.
You may use swift-algorithms 1.2.0 and swift-collections 1.0.6.
\"], \"golang\": [\"Go\", \"Go 1.21
Support https://godoc.org/github.com/emirpasic/gods@v1.18.1 library.
\"], \"python3\": [\"Python3\", \"Python 3.11
.
Most libraries are already imported automatically for your convenience, such as array, bisect, collections. If you need more libraries, you can import it yourself.
\\r\\n\\r\\nFor Map/TreeMap data structure, you may use sortedcontainers library.
\"], \"scala\": [\"Scala\", \"Scala 3.3.1
.
Kotlin 1.9.0
.
We are using an experimental compiler provided by JetBrains.
\"], \"rust\": [\"Rust\", \"Rust 1.74.1
Supports rand v0.6\\u00a0from crates.io
\"], \"php\": [\"PHP\", \"PHP 8.2
.
With bcmath module
\"], \"typescript\": [\"Typescript\", \"TypeScript 5.1.6, Node.js 20.10.0
.
Compile Options: --alwaysStrict --strictBindCallApply --strictFunctionTypes --target ES2022
Your code is run with --harmony
flag, enabling new ES2022 features.
lodash.js library is included by default.
\"], \"racket\": [\"Racket\", \"Racket CS v8.11
\\r\\n\\r\\nUsing #lang racket
Required data/gvector data/queue data/order data/heap
automatically for your convenience
Given an array of integers nums
and an integer target
, return indices of the two numbers such that they add up to target
.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
\n\nYou can return the answer in any order.
\n\n\n
Example 1:
\n\n\nInput: nums = [2,7,11,15], target = 9\nOutput: [0,1]\nExplanation: Because nums[0] + nums[1] == 9, we return [0, 1].\n\n\n
Example 2:
\n\n\nInput: nums = [3,2,4], target = 6\nOutput: [1,2]\n\n\n
Example 3:
\n\n\nInput: nums = [3,3], target = 6\nOutput: [0,1]\n\n\n
\n
Constraints:
\n\n2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
\nFollow-up: Can you come up with an algorithm that is less than
O(n2)
time complexity?",
10 | "translatedTitle": null,
11 | "translatedContent": null,
12 | "isPaidOnly": false,
13 | "difficulty": "Easy",
14 | "likes": 55371,
15 | "dislikes": 1901,
16 | "isLiked": null,
17 | "similarQuestions": "[{\"title\": \"3Sum\", \"titleSlug\": \"3sum\", \"difficulty\": \"Medium\", \"translatedTitle\": null}, {\"title\": \"4Sum\", \"titleSlug\": \"4sum\", \"difficulty\": \"Medium\", \"translatedTitle\": null}, {\"title\": \"Two Sum II - Input Array Is Sorted\", \"titleSlug\": \"two-sum-ii-input-array-is-sorted\", \"difficulty\": \"Medium\", \"translatedTitle\": null}, {\"title\": \"Two Sum III - Data structure design\", \"titleSlug\": \"two-sum-iii-data-structure-design\", \"difficulty\": \"Easy\", \"translatedTitle\": null}, {\"title\": \"Subarray Sum Equals K\", \"titleSlug\": \"subarray-sum-equals-k\", \"difficulty\": \"Medium\", \"translatedTitle\": null}, {\"title\": \"Two Sum IV - Input is a BST\", \"titleSlug\": \"two-sum-iv-input-is-a-bst\", \"difficulty\": \"Easy\", \"translatedTitle\": null}, {\"title\": \"Two Sum Less Than K\", \"titleSlug\": \"two-sum-less-than-k\", \"difficulty\": \"Easy\", \"translatedTitle\": null}, {\"title\": \"Max Number of K-Sum Pairs\", \"titleSlug\": \"max-number-of-k-sum-pairs\", \"difficulty\": \"Medium\", \"translatedTitle\": null}, {\"title\": \"Count Good Meals\", \"titleSlug\": \"count-good-meals\", \"difficulty\": \"Medium\", \"translatedTitle\": null}, {\"title\": \"Count Number of Pairs With Absolute Difference K\", \"titleSlug\": \"count-number-of-pairs-with-absolute-difference-k\", \"difficulty\": \"Easy\", \"translatedTitle\": null}, {\"title\": \"Number of Pairs of Strings With Concatenation Equal to Target\", \"titleSlug\": \"number-of-pairs-of-strings-with-concatenation-equal-to-target\", \"difficulty\": \"Medium\", \"translatedTitle\": null}, {\"title\": \"Find All K-Distant Indices in an Array\", \"titleSlug\": \"find-all-k-distant-indices-in-an-array\", \"difficulty\": \"Easy\", \"translatedTitle\": null}, {\"title\": \"First Letter to Appear Twice\", \"titleSlug\": \"first-letter-to-appear-twice\", \"difficulty\": \"Easy\", \"translatedTitle\": null}, {\"title\": \"Number of Excellent Pairs\", \"titleSlug\": \"number-of-excellent-pairs\", \"difficulty\": \"Hard\", \"translatedTitle\": null}, {\"title\": \"Number of Arithmetic Triplets\", \"titleSlug\": \"number-of-arithmetic-triplets\", \"difficulty\": \"Easy\", \"translatedTitle\": null}, {\"title\": \"Node With Highest Edge Score\", \"titleSlug\": \"node-with-highest-edge-score\", \"difficulty\": \"Medium\", \"translatedTitle\": null}, {\"title\": \"Check Distances Between Same Letters\", \"titleSlug\": \"check-distances-between-same-letters\", \"difficulty\": \"Easy\", \"translatedTitle\": null}, {\"title\": \"Find Subarrays With Equal Sum\", \"titleSlug\": \"find-subarrays-with-equal-sum\", \"difficulty\": \"Easy\", \"translatedTitle\": null}, {\"title\": \"Largest Positive Integer That Exists With Its Negative\", \"titleSlug\": \"largest-positive-integer-that-exists-with-its-negative\", \"difficulty\": \"Easy\", \"translatedTitle\": null}, {\"title\": \"Number of Distinct Averages\", \"titleSlug\": \"number-of-distinct-averages\", \"difficulty\": \"Easy\", \"translatedTitle\": null}, {\"title\": \"Count Pairs Whose Sum is Less than Target\", \"titleSlug\": \"count-pairs-whose-sum-is-less-than-target\", \"difficulty\": \"Easy\", \"translatedTitle\": null}]",
18 | "exampleTestcases": "[2,7,11,15]\n9\n[3,2,4]\n6\n[3,3]\n6",
19 | "contributors": [],
20 | "topicTags": [
21 | { "name": "Array", "slug": "array", "translatedName": null },
22 | { "name": "Hash Table", "slug": "hash-table", "translatedName": null }
23 | ],
24 | "companyTagStats": null,
25 | "codeSnippets": [
26 | {
27 | "lang": "C++",
28 | "langSlug": "cpp",
29 | "code": "class Solution {\npublic:\n vectorx
, we have to scan the entire array to find the next number y
which is value - x
where value is the input parameter. Can we change our array somehow so that this search becomes faster?",
126 | "The second train of thought is, without changing the array, can we use additional space somehow? Like maybe a hash map to speed up the search?"
127 | ],
128 | "solution": {
129 | "id": "7",
130 | "canSeeDetail": true,
131 | "paidOnly": false,
132 | "hasVideoSolution": true,
133 | "paidOnlyVideo": false
134 | },
135 | "status": null,
136 | "sampleTestCase": "[2,7,11,15]\n9",
137 | "metaData": "{\n \"name\": \"twoSum\",\n \"params\": [\n {\n \"name\": \"nums\",\n \"type\": \"integer[]\"\n },\n {\n \"name\": \"target\",\n \"type\": \"integer\"\n }\n ],\n \"return\": {\n \"type\": \"integer[]\",\n \"size\": 2\n },\n \"manual\": false\n}",
138 | "judgerAvailable": true,
139 | "judgeType": "small",
140 | "mysqlSchemas": [],
141 | "enableRunCode": true,
142 | "enableTestMode": false,
143 | "enableDebugger": true,
144 | "envInfo": "{\"cpp\": [\"C++\", \"Compiled with clang 17
using the latest C++ 20 standard, and libstdc++
provided by GCC 11.
Your code is compiled with level two optimization (-O2
). AddressSanitizer is also enabled to help detect out-of-bounds and use-after-free bugs.
Most standard library headers are already included automatically for your convenience.
\"], \"java\": [\"Java\", \"OpenJDK 21
. Using compile arguments: --enable-preview --release 21
Most standard library headers are already included automatically for your convenience.
\\r\\nIncludes Pair
class from https://docs.oracle.com/javase/8/javafx/api/javafx/util/Pair.html.
Python 2.7.12
.
Most libraries are already imported automatically for your convenience, such as array, bisect, collections. If you need more libraries, you can import it yourself.
\\r\\n\\r\\nFor Map/TreeMap data structure, you may use sortedcontainers library.
\\r\\n\\r\\nNote that Python 2.7 will not be maintained past 2020. For the latest Python, please choose Python3 instead.
\"], \"c\": [\"C\", \"Compiled with gcc 11
using the gnu11 standard.
Your code is compiled with level one optimization (-O2
). AddressSanitizer is also enabled to help detect out-of-bounds and use-after-free bugs.
Most standard library headers are already included automatically for your convenience.
\\r\\n\\r\\nFor hash table operations, you may use uthash. \\\"uthash.h\\\" is included by default. Below are some examples:
\\r\\n\\r\\n1. Adding an item to a hash.\\r\\n
\\r\\nstruct hash_entry {\\r\\n int id; /* we'll use this field as the key */\\r\\n char name[10];\\r\\n UT_hash_handle hh; /* makes this structure hashable */\\r\\n};\\r\\n\\r\\nstruct hash_entry *users = NULL;\\r\\n\\r\\nvoid add_user(struct hash_entry *s) {\\r\\n HASH_ADD_INT(users, id, s);\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n
2. Looking up an item in a hash:\\r\\n
\\r\\nstruct hash_entry *find_user(int user_id) {\\r\\n struct hash_entry *s;\\r\\n HASH_FIND_INT(users, &user_id, s);\\r\\n return s;\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n
3. Deleting an item in a hash:\\r\\n
\\r\\nvoid delete_user(struct hash_entry *user) {\\r\\n HASH_DEL(users, user); \\r\\n}\\r\\n\\r\\n\"], \"csharp\": [\"C#\", \"
C# 12 with .NET 8 runtime
\"], \"javascript\": [\"JavaScript\", \"Node.js 20.10.0
.
Your code is run with --harmony
flag, enabling new ES6 features.
lodash.js library is included by default.
\\r\\n\\r\\nFor Priority Queue / Queue data structures, you may use 5.4.0 version of datastructures-js/priority-queue and 4.2.3 version of datastructures-js/queue.
\"], \"ruby\": [\"Ruby\", \"Ruby 3.2
Some common data structure implementations are provided in the Algorithms module: https://www.rubydoc.info/github/kanwei/algorithms/Algorithms
\"], \"swift\": [\"Swift\", \"Swift 5.9
.
You may use swift-algorithms 1.2.0 and swift-collections 1.0.6.
\"], \"golang\": [\"Go\", \"Go 1.21
Support https://godoc.org/github.com/emirpasic/gods@v1.18.1 library.
\"], \"python3\": [\"Python3\", \"Python 3.11
.
Most libraries are already imported automatically for your convenience, such as array, bisect, collections. If you need more libraries, you can import it yourself.
\\r\\n\\r\\nFor Map/TreeMap data structure, you may use sortedcontainers library.
\"], \"scala\": [\"Scala\", \"Scala 3.3.1
.
Kotlin 1.9.0
.
We are using an experimental compiler provided by JetBrains.
\"], \"rust\": [\"Rust\", \"Rust 1.74.1
Supports rand v0.6\\u00a0from crates.io
\"], \"php\": [\"PHP\", \"PHP 8.2
.
With bcmath module
\"], \"typescript\": [\"Typescript\", \"TypeScript 5.1.6, Node.js 20.10.0
.
Compile Options: --alwaysStrict --strictBindCallApply --strictFunctionTypes --target ES2022
Your code is run with --harmony
flag, enabling new ES2022 features.
lodash.js library is included by default.
\"], \"racket\": [\"Racket\", \"Racket CS v8.11
\\r\\n\\r\\nUsing #lang racket
Required data/gvector data/queue data/order data/heap
automatically for your convenience
Dart 3.2
\\r\\n\\r\\nYour code will be run directly without compiling
\"]}", 145 | "libraryUrl": null, 146 | "adminUrl": null, 147 | "challengeQuestion": null, 148 | "note": null 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/__tests__/msw/mockData/singleUser.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "matchedUser": { 4 | "submissionCalendar": "{\"1704153600\": 24, \"1704240000\": 9, \"1704326400\": 5, \"1704412800\": 3, \"1705017600\": 1, \"1705104000\": 6, \"1699315200\": 46, \"1701302400\": 6, \"1701648000\": 24, \"1701734400\": 11, \"1702339200\": 29, \"1702425600\": 7}", 5 | "submitStats": { 6 | "totalSubmissionNum": [ 7 | { "difficulty": "All", "count": 158, "submissions": 463 }, 8 | { "difficulty": "Easy", "count": 131, "submissions": 388 }, 9 | { "difficulty": "Medium", "count": 27, "submissions": 75 }, 10 | { "difficulty": "Hard", "count": 0, "submissions": 0 } 11 | ], 12 | "acSubmissionNum": [ 13 | { "difficulty": "All", "count": 133, "submissions": 215 }, 14 | { "difficulty": "Easy", "count": 122, "submissions": 202 }, 15 | { "difficulty": "Medium", "count": 11, "submissions": 13 }, 16 | { "difficulty": "Hard", "count": 0, "submissions": 0 } 17 | ] 18 | }, 19 | "username": "jambobjones", 20 | "githubUrl": "https://github.com/jambobjones", 21 | "twitterUrl": null, 22 | "linkedinUrl": null, 23 | "contributions": { 24 | "points": 115, 25 | "questionCount": 0, 26 | "testcaseCount": 0 27 | }, 28 | "profile": { 29 | "realName": "Jambob Jones", 30 | "userAvatar": "https://assets.leetcode.com/users/jambobjones/avatar_1617850141.png", 31 | "birthday": null, 32 | "ranking": 630800, 33 | "reputation": 0, 34 | "websites": [], 35 | "countryName": null, 36 | "company": null, 37 | "school": null, 38 | "skillTags": [], 39 | "aboutMe": "", 40 | "starRating": 2 41 | }, 42 | "badges": [], 43 | "upcomingBadges": [ 44 | { 45 | "name": "Mar LeetCoding Challenge", 46 | "icon": "/static/images/badges/dcc-2024-3.png" 47 | } 48 | ], 49 | "activeBadge": null 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/__tests__/msw/mockData/singleUserContests.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "userContestRanking": null, 4 | "userContestRankingHistory": [ 5 | { 6 | "attended": false, 7 | "rating": 1500, 8 | "ranking": 0, 9 | "trendDirection": "NONE", 10 | "problemsSolved": 0, 11 | "totalProblems": 3, 12 | "finishTimeInSeconds": 0 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/__tests__/problemData.spec.ts: -------------------------------------------------------------------------------- 1 | import request from 'supertest'; 2 | import assert from 'assert'; 3 | import app from '../app'; 4 | 5 | describe('Problem Data Tests', () => { 6 | it('Should fetch the daily problem', async () => { 7 | const response = await request(app).get('/daily'); 8 | [ 9 | 'questionLink', 10 | 'date', 11 | 'questionId', 12 | 'questionFrontendId', 13 | 'questionTitle', 14 | 'titleSlug', 15 | 'difficulty', 16 | 'isPaidOnly', 17 | 'question', 18 | 'exampleTestcases', 19 | 'topicTags', 20 | 'hints', 21 | 'solution', 22 | 'companyTagStats', 23 | 'likes', 24 | 'dislikes', 25 | 'similarQuestions', 26 | ].forEach((key) => { 27 | assert(key in response.body); 28 | }); 29 | }); 30 | 31 | it('Should fetch a list of problems', async () => { 32 | const response = await request(app).get('/problems'); 33 | ['totalQuestions', 'count', 'problemsetQuestionList'].forEach((key) => { 34 | assert(key in response.body); 35 | }); 36 | }); 37 | 38 | it('Should Select a Problem', async () => { 39 | const response = await request(app).get('/select?titleSlug=two-sum'); 40 | [ 41 | 'link', 42 | 'questionId', 43 | 'questionFrontendId', 44 | 'questionTitle', 45 | 'titleSlug', 46 | 'difficulty', 47 | 'isPaidOnly', 48 | 'question', 49 | 'exampleTestcases', 50 | 'topicTags', 51 | 'hints', 52 | 'solution', 53 | 'companyTagStats', 54 | 'likes', 55 | 'dislikes', 56 | 'similarQuestions', 57 | ].forEach((key) => assert(key in response.body)); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /src/__tests__/userData.spec.ts: -------------------------------------------------------------------------------- 1 | import request from 'supertest'; 2 | import app from '../app'; 3 | import assert from 'assert'; 4 | 5 | describe('User Data Tests', () => { 6 | it('should fetch a single user', async () => { 7 | const response = await request(app).get('/jambobjones'); 8 | expect(response.body.username).toBe('jambobjones'); 9 | [ 10 | 'username', 11 | 'name', 12 | 'birthday', 13 | 'avatar', 14 | 'ranking', 15 | 'reputation', 16 | 'gitHub', 17 | 'twitter', 18 | 'linkedIN', 19 | 'website', 20 | 'country', 21 | 'company', 22 | 'school', 23 | 'skillTags', 24 | 'about', 25 | ].forEach((key) => { 26 | assert(key in response.body); 27 | }); 28 | }); 29 | 30 | it('should fetch user badges', async () => { 31 | const response = await request(app).get('/jambobjones/badges'); 32 | 33 | ['badgesCount', 'badges', 'upcomingBadges', 'activeBadge'].forEach( 34 | (key) => { 35 | assert(key in response.body); 36 | } 37 | ); 38 | }); 39 | 40 | it('Should fetch users solved problems', async () => { 41 | const response = await request(app).get('/jambobjones/solved'); 42 | [ 43 | 'solvedProblem', 44 | 'easySolved', 45 | 'mediumSolved', 46 | 'hardSolved', 47 | 'totalSubmissionNum', 48 | 'acSubmissionNum', 49 | ].forEach((key) => { 50 | assert(key in response.body); 51 | }); 52 | }); 53 | 54 | it('Should fetch users contests', async () => { 55 | const response = await request(app).get('/jambobjones/contest'); 56 | ['contestParticipation'].forEach((key) => { 57 | assert(key in response.body); 58 | }); 59 | }); 60 | 61 | it('Should fetch user contest history', async () => { 62 | const response = await request(app).get('/jambobjones/contest/history'); 63 | ['count', 'contestHistory'].forEach((key) => { 64 | assert(key in response.body); 65 | }); 66 | }); 67 | 68 | it('Should fetch users recent submissions returning 20 by default', async () => { 69 | const response = await request(app).get('/jambobjones/submission'); 70 | ['count', 'submission'].forEach((key) => { 71 | assert(key in response.body); 72 | }); 73 | 74 | expect(response.body.count).toBeLessThanOrEqual(20); 75 | }); 76 | // Todo: Submission test with Limit Parameter 77 | 78 | it('Should fetch AC Submissions', async () => { 79 | const response = await request(app).get('/jambobjones/acSubmission'); 80 | 81 | ['count', 'submission'].forEach((key) => { 82 | assert(key in response.body); 83 | }); 84 | expect(response.body.count).toBeLessThanOrEqual(20); 85 | }); 86 | 87 | it('Should fetch Users Submission Calendar', async () => { 88 | const response = await request(app).get('/jambobjones/calendar'); 89 | assert('submissionCalendar' in response.body); 90 | expect(typeof response.body.submissionCalendar).toBe('string'); 91 | }); 92 | }); 93 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | import express, { NextFunction, Response } from 'express'; 2 | import cors from 'cors'; 3 | import rateLimit from 'express-rate-limit'; 4 | import * as leetcode from './leetCode'; 5 | import { FetchUserDataRequest } from './types'; 6 | import apicache from 'apicache'; 7 | import axios from 'axios'; 8 | import { 9 | userContestRankingInfoQuery, 10 | discussCommentsQuery, 11 | discussTopicQuery, 12 | userProfileUserQuestionProgressV2Query, 13 | skillStatsQuery, 14 | getUserProfileQuery, 15 | userProfileCalendarQuery, 16 | officialSolutionQuery, 17 | dailyQeustion, 18 | } from './GQLQueries/newQueries'; 19 | 20 | const app = express(); 21 | let cache = apicache.middleware; 22 | const API_URL = process.env.LEETCODE_API_URL || 'https://leetcode.com/graphql'; 23 | 24 | const limiter = rateLimit({ 25 | windowMs: 60 * 60 * 1000, // 1 hour 26 | limit: 60, 27 | standardHeaders: 'draft-7', 28 | legacyHeaders: false, 29 | message: 'Too many request from this IP, try again in 1 hour', 30 | }); 31 | 32 | app.use(cache('5 minutes')); 33 | app.use(cors()); //enable all CORS request 34 | app.use(limiter); //limit to all API 35 | app.use((req: express.Request, _res: Response, next: NextFunction) => { 36 | console.log('Requested URL:', req.originalUrl); 37 | next(); 38 | }); 39 | 40 | async function queryLeetCodeAPI(query: string, variables: any) { 41 | try { 42 | const response = await axios.post(API_URL, { query, variables }); 43 | if (response.data.errors) { 44 | throw new Error(response.data.errors[0].message); 45 | } 46 | return response.data; 47 | } catch (error) { 48 | if (error.response) { 49 | throw new Error(`Error from LeetCode API: ${error.response.data}`); 50 | } else if (error.request) { 51 | throw new Error('No response received from LeetCode API'); 52 | } else { 53 | throw new Error(`Error in setting up the request: ${error.message}`); 54 | } 55 | } 56 | } 57 | 58 | app.get('/', (_req, res) => { 59 | res.json({ 60 | apiOverview: 61 | 'Welcome to the Alfa-Leetcode-API! Alfa-Leetcode-Api is a custom solution born out of the need for a well-documented and detailed LeetCode API. This project is designed to provide developers with endpoints that offer insights into a user"s profile, badges, solved questions, contest details, contest history, submissions, and also daily questions, selected problem, list of problems.', 62 | apiEndpointsLink: 63 | 'https://github.com/alfaarghya/alfa-leetcode-api?tab=readme-ov-file#endpoints-', 64 | routes: { 65 | userDetails: { 66 | description: 67 | 'Endpoints for retrieving detailed user profile information on Leetcode.', 68 | Method: 'GET', 69 | '/:username': 'Get your leetcodevis profile Details', 70 | '/:username/badges': 'Get your badges', 71 | '/:username/solved': 'Get total number of question you solved', 72 | '/:username/contest': 'Get your contest details', 73 | '/:username/contest/history': 'Get all contest history', 74 | '/:username/submission': 'Get your last 20 submission', 75 | '/:username/acSubmission': 'Get your last 20 accepted submission', 76 | '/:username/calendar': 'Get your submission calendar', 77 | '/userProfile/:username': 'Get full profile details in one call', 78 | '/userProfileCalendar?username=yourname&year=2024': 79 | 'Get your calendar details with year', 80 | '/languageStats?username=yourname': 'Get the language stats of a user', 81 | '/userProfileUserQuestionProgressV2/:userSlug': 82 | 'Get your question progress', 83 | '/skillStats/:username': 'Get your skill stats', 84 | }, 85 | contest: { 86 | description: 87 | 'Endpoints for retrieving contest ranking and performance data.', 88 | Method: 'GET', 89 | '/userContestRankingInfo/:username': 'Get user contest ranking info', 90 | }, 91 | discussion: { 92 | description: 'Endpoints for fetching discussion topics and comments.', 93 | Method: 'GET', 94 | '/trendingDiscuss?first=20': 'Get top 20 trending discussions', 95 | '/discussTopic/:topicId': 'Get discussion topic', 96 | '/discussComments/:topicId': 'Get discussion comments', 97 | }, 98 | problems: { 99 | description: 100 | 'Endpoints for fetching problem-related data, including lists, details, and solutions.', 101 | Method: 'GET', 102 | singleProblem: { 103 | '/select?titleSlug=two-sum': 'Get selected Problem', 104 | '/daily': 'Get daily Problem', 105 | '/dailyQuestion': 'Get raw daily question', 106 | }, 107 | problemList: { 108 | '/problems': 'Get list of 20 problems', 109 | '/problems?limit=50': 'Get list of some problems', 110 | '/problems?tags=array+math': 'Get list problems on selected topics', 111 | '/problems?tags=array+math+string&limit=5': 112 | 'Get list some problems on selected topics', 113 | '/officialSolution?titleSlug=two-sum': 114 | 'Get official solution of selected problem', 115 | }, 116 | }, 117 | }, 118 | }); 119 | }); 120 | 121 | app.get('/officialSolution', async (req, res) => { 122 | const { titleSlug } = req.query; 123 | 124 | if (!titleSlug) { 125 | return res.status(400).json({ error: 'Missing titleSlug query parameter' }); 126 | } 127 | try { 128 | const data = await queryLeetCodeAPI(officialSolutionQuery, { titleSlug }); 129 | return res.json(data); 130 | } catch (error) { 131 | return res.status(500).json({ error: error.message }); 132 | } 133 | }); 134 | 135 | app.get('/userProfileCalendar', async (req, res) => { 136 | const { username, year } = req.query; 137 | 138 | if (!username || !year || typeof year !== 'string') { 139 | return res 140 | .status(400) 141 | .json({ error: 'Missing or invalid username or year query parameter' }); 142 | } 143 | 144 | try { 145 | const data = await queryLeetCodeAPI(userProfileCalendarQuery, { 146 | username, 147 | year: parseInt(year), 148 | }); 149 | return res.json(data); 150 | } catch (error) { 151 | return res.status(500).json({ error: error.message }); 152 | } 153 | }); 154 | 155 | // Format data 156 | const formatData = (data: any) => { 157 | return { 158 | totalSolved: data.matchedUser.submitStats.acSubmissionNum[0].count, 159 | totalSubmissions: data.matchedUser.submitStats.totalSubmissionNum, 160 | totalQuestions: data.allQuestionsCount[0].count, 161 | easySolved: data.matchedUser.submitStats.acSubmissionNum[1].count, 162 | totalEasy: data.allQuestionsCount[1].count, 163 | mediumSolved: data.matchedUser.submitStats.acSubmissionNum[2].count, 164 | totalMedium: data.allQuestionsCount[2].count, 165 | hardSolved: data.matchedUser.submitStats.acSubmissionNum[3].count, 166 | totalHard: data.allQuestionsCount[3].count, 167 | ranking: data.matchedUser.profile.ranking, 168 | contributionPoint: data.matchedUser.contributions.points, 169 | reputation: data.matchedUser.profile.reputation, 170 | submissionCalendar: JSON.parse(data.matchedUser.submissionCalendar), 171 | recentSubmissions: data.recentSubmissionList, 172 | matchedUserStats: data.matchedUser.submitStats, 173 | }; 174 | }; 175 | 176 | app.get('/userProfile/:id', async (req, res) => { 177 | const user = req.params.id; 178 | 179 | try { 180 | const data = await queryLeetCodeAPI(getUserProfileQuery, { 181 | username: user, 182 | }); 183 | if (data.errors) { 184 | res.send(data); 185 | } else { 186 | res.send(formatData(data.data)); 187 | } 188 | } catch (error) { 189 | res.send(error); 190 | } 191 | }); 192 | 193 | const handleRequest = async (res: Response, query: string, params: any) => { 194 | try { 195 | const data = await queryLeetCodeAPI(query, params); 196 | res.json(data); 197 | } catch (error) { 198 | res.status(500).json({ error: error.message }); 199 | } 200 | }; 201 | app.get('/dailyQuestion', (_, res) => { 202 | handleRequest(res, dailyQeustion, {}); 203 | }); 204 | 205 | app.get('/skillStats/:username', (req, res) => { 206 | const { username } = req.params; 207 | handleRequest(res, skillStatsQuery, { username }); 208 | }); 209 | 210 | app.get('/userProfileUserQuestionProgressV2/:userSlug', (req, res) => { 211 | const { userSlug } = req.params; 212 | handleRequest(res, userProfileUserQuestionProgressV2Query, { userSlug }); 213 | }); 214 | 215 | app.get('/discussTopic/:topicId', (req, res) => { 216 | const topicId = parseInt(req.params.topicId); 217 | handleRequest(res, discussTopicQuery, { topicId }); 218 | }); 219 | 220 | app.get('/discussComments/:topicId', (req, res) => { 221 | const topicId = parseInt(req.params.topicId); 222 | const { 223 | orderBy = 'newest_to_oldest', 224 | pageNo = 1, 225 | numPerPage = 10, 226 | } = req.query; 227 | handleRequest(res, discussCommentsQuery, { 228 | topicId, 229 | orderBy, 230 | pageNo, 231 | numPerPage, 232 | }); 233 | }); 234 | 235 | app.get('/userContestRankingInfo/:username', (req, res) => { 236 | const { username } = req.params; 237 | handleRequest(res, userContestRankingInfoQuery, { username }); 238 | }); 239 | 240 | //get the daily leetCode problem 241 | app.get('/daily', leetcode.dailyProblem); 242 | 243 | //get the selected question 244 | app.get('/select', leetcode.selectProblem); 245 | 246 | //get list of problems 247 | app.get('/problems', leetcode.problems); 248 | 249 | //get 20 trending Discuss 250 | app.get('/trendingDiscuss', leetcode.trendingCategoryTopics); 251 | 252 | app.get('/languageStats', leetcode.languageStats); 253 | 254 | // Construct options object on all user routes. 255 | app.use( 256 | '/:username*', 257 | (req: FetchUserDataRequest, _res: Response, next: NextFunction) => { 258 | req.body = { 259 | username: req.params.username, 260 | limit: req.query.limit, 261 | }; 262 | next(); 263 | } 264 | ); 265 | 266 | //get user profile details 267 | app.get('/:username', leetcode.userData); 268 | app.get('/:username/badges', leetcode.userBadges); 269 | app.get('/:username/solved', leetcode.solvedProblem); 270 | app.get('/:username/contest', leetcode.userContest); 271 | app.get('/:username/contest/history', leetcode.userContestHistory); 272 | app.get('/:username/submission', leetcode.submission); 273 | app.get('/:username/acSubmission', leetcode.acSubmission); 274 | app.get('/:username/calendar', leetcode.calendar); 275 | 276 | export default app; 277 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | const config = { 2 | port: process.env.PORT || 3000, 3 | }; 4 | 5 | export default config; 6 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import app from './app'; 2 | import config from './config'; 3 | 4 | app.listen(config.port, () => { 5 | console.log(`Server is running at => http://localhost:${config.port} ⚙️`); 6 | }); 7 | -------------------------------------------------------------------------------- /src/leetCode.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import * as gqlQueries from './GQLQueries'; 3 | import * as formatUtils from './FormatUtils'; 4 | import * as controllers from './Controllers'; 5 | import { TransformedUserDataRequest } from './types'; 6 | 7 | export const userData = (req: TransformedUserDataRequest, res: Response) => { 8 | controllers.fetchUserDetails( 9 | req.body, 10 | res, 11 | formatUtils.formatUserData, 12 | gqlQueries.userProfileQuery 13 | ); 14 | }; 15 | 16 | export const userBadges = (req: TransformedUserDataRequest, res: Response) => { 17 | controllers.fetchUserDetails( 18 | req.body, 19 | res, 20 | formatUtils.formatBadgesData, 21 | gqlQueries.userProfileQuery 22 | ); 23 | }; 24 | 25 | export const userContest = (req: TransformedUserDataRequest, res: Response) => { 26 | controllers.fetchUserDetails( 27 | req.body, 28 | res, 29 | formatUtils.formatContestData, 30 | gqlQueries.contestQuery 31 | ); 32 | }; 33 | 34 | export const userContestHistory = ( 35 | req: TransformedUserDataRequest, 36 | res: Response 37 | ) => { 38 | controllers.fetchUserDetails( 39 | req.body, 40 | res, 41 | formatUtils.formatContestHistoryData, 42 | gqlQueries.contestQuery 43 | ); 44 | }; 45 | 46 | export const solvedProblem = ( 47 | req: TransformedUserDataRequest, 48 | res: Response 49 | ) => { 50 | controllers.fetchUserDetails( 51 | req.body, 52 | res, 53 | formatUtils.formatSolvedProblemsData, 54 | gqlQueries.userProfileQuery 55 | ); 56 | }; 57 | 58 | export const submission = (req: TransformedUserDataRequest, res: Response) => { 59 | controllers.fetchUserDetails( 60 | req.body, 61 | res, 62 | formatUtils.formatSubmissionData, 63 | gqlQueries.submissionQuery 64 | ); 65 | }; 66 | 67 | export const acSubmission = ( 68 | req: TransformedUserDataRequest, 69 | res: Response 70 | ) => { 71 | controllers.fetchUserDetails( 72 | req.body, 73 | res, 74 | formatUtils.formatAcSubmissionData, 75 | gqlQueries.AcSubmissionQuery 76 | ); 77 | }; 78 | 79 | export const calendar = (req: TransformedUserDataRequest, res: Response) => { 80 | controllers.fetchUserDetails( 81 | req.body, 82 | res, 83 | formatUtils.formatSubmissionCalendarData, 84 | gqlQueries.userProfileQuery 85 | ); 86 | }; 87 | 88 | //Problems Details 89 | export const dailyProblem = (_req: Request, res: Response) => { 90 | controllers.fetchSingleProblem( 91 | res, 92 | formatUtils.formatDailyData, 93 | gqlQueries.dailyProblemQuery, 94 | null 95 | ); 96 | }; 97 | 98 | export const selectProblem = (req: Request, res: Response) => { 99 | const title = req.query.titleSlug as string; 100 | if (title !== undefined) { 101 | controllers.fetchSingleProblem( 102 | res, 103 | formatUtils.formatQuestionData, 104 | gqlQueries.selectProblemQuery, 105 | title 106 | ); 107 | } else { 108 | res.status(400).json({ 109 | error: 'Missing or invalid query parameter: titleSlug', 110 | solution: 'put query after select', 111 | example: 'localhost:3000/select?titleSlug=two-sum', 112 | }); 113 | } 114 | }; 115 | 116 | export const problems = ( 117 | req: Request<{}, {}, {}, { limit: number; skip: number; tags: string; difficulty: string }>, 118 | res: Response 119 | ) => { 120 | const difficulty=req.query.difficulty; 121 | const limit = req.query.limit; 122 | const skip = req.query.skip; 123 | const tags = req.query.tags; 124 | 125 | controllers.fetchProblems( 126 | { limit, skip, tags, difficulty }, 127 | res, 128 | formatUtils.formatProblemsData, 129 | gqlQueries.problemListQuery 130 | ); 131 | }; 132 | 133 | 134 | export const trendingCategoryTopics = (_req: Request, res: Response) => { 135 | const first = parseInt(_req.query.first as string); 136 | if (!isNaN(first)) { 137 | controllers.fetchTrendingTopics( 138 | { first }, 139 | res, 140 | formatUtils.formatTrendingCategoryTopicData, 141 | gqlQueries.trendingDiscussQuery 142 | ); 143 | } 144 | else { 145 | res.status(400).json({ 146 | error: 'Missing or invalid query parameter: limit', 147 | solution: 'put query after discussion', 148 | example: 'localhost:3000/trendingDiscuss?first=20', 149 | }); 150 | } 151 | 152 | }; 153 | 154 | export const languageStats = (_req: Request, res: Response) => { 155 | const username = _req.query.username as string; 156 | if (username) { 157 | controllers.fetchDataRawFormat( 158 | { username }, 159 | res, 160 | gqlQueries.languageStatsQuery 161 | ); 162 | } 163 | else { 164 | res.status(400).json({ 165 | error: 'Missing or invalid query parameter: username', 166 | solution: 'put query after discussion', 167 | example: 'localhost:3000/languageStats?username=uwi', 168 | }); 169 | } 170 | 171 | }; -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import { Request } from 'express'; 2 | // User Data 3 | interface UserDataProfile { 4 | aboutMe: string; 5 | company?: string; 6 | countryName?: string; 7 | realName: string; 8 | birthday?: string; 9 | userAvatar: string; 10 | ranking: number; 11 | reputation: number; 12 | school?: string; 13 | skillTags: string[]; 14 | websites: string[]; 15 | } 16 | 17 | interface MatchedUser { 18 | activeBadge: Badge; 19 | badges: Badge[]; 20 | githubUrl: string; 21 | linkedinUrl?: string; 22 | profile: UserDataProfile; 23 | upcomingBadges: Badge[]; 24 | username: string; 25 | twitterUrl?: string; 26 | submissionCalendar: string; 27 | submitStats: { 28 | totalSubmissionNum: { 29 | difficulty: Difficulty; 30 | count: number; 31 | submissions: number; 32 | }[]; 33 | acSubmissionNum: { 34 | difficulty: Difficulty; 35 | count: number; 36 | submissions: number; 37 | }[]; 38 | count: number; 39 | }; 40 | } 41 | 42 | export interface UserData { 43 | userContestRanking: null | { 44 | attendedContestsCount: number; 45 | badge: Badge; 46 | globalRanking: number; 47 | rating: number; 48 | totalParticipants: number; 49 | topPercentage: number; 50 | }; 51 | userContestRankingHistory: { 52 | attended: boolean; 53 | rating: number; 54 | ranking: number; 55 | trendDirection: string; 56 | problemsSolved: number; 57 | totalProblems: number; 58 | finishTimeInSeconds: number; 59 | contest: { 60 | title: string; 61 | startTime: string; 62 | }; 63 | }[]; 64 | matchedUser: MatchedUser; 65 | recentAcSubmissionList: {}[]; 66 | recentSubmissionList: Submission[]; 67 | } 68 | 69 | interface Badge { 70 | name: string; 71 | icon: string; 72 | } 73 | 74 | type Difficulty = 'All' | 'Easy' | 'Medium' | 'Hard'; 75 | //User Details 76 | export type FetchUserDataRequest = Request< 77 | { username: string }, 78 | {}, 79 | { username: string; limit: number }, 80 | { limit: number } 81 | >; 82 | 83 | export type TransformedUserDataRequest = Request< 84 | {}, 85 | {}, 86 | { username: string; limit: number } 87 | >; 88 | 89 | // ProblemData 90 | export interface ProblemSetQuestionListData { 91 | problemsetQuestionList: { 92 | total: number; 93 | questions: {}[]; 94 | }; 95 | } 96 | 97 | interface Submission { 98 | title: string; 99 | titleSlug: string; 100 | timestamp: string; 101 | statusDisplay: string; 102 | lang: string; 103 | } 104 | 105 | interface Question { 106 | content: string; 107 | companyTagStats: string[]; 108 | difficulty: Difficulty; 109 | dislikes: number; 110 | exampleTestcases: {}[]; 111 | hints: {}[]; 112 | isPaidOnly: boolean; 113 | likes: number; 114 | questionId: number; 115 | questionFrontendId: number; 116 | solution: string; 117 | similarQuestions: {}[]; 118 | title: string; 119 | titleSlug: string; 120 | topicTags: string[]; 121 | } 122 | 123 | export interface DailyProblemData { 124 | activeDailyCodingChallengeQuestion: { 125 | date: string; 126 | link: string; 127 | question: Question; 128 | }; 129 | } 130 | export interface SelectProblemData { 131 | question: Question; 132 | } 133 | 134 | export interface TrendingDiscussionObject { 135 | data: { 136 | cachedTrendingCategoryTopics: { 137 | id: number; 138 | title: string; 139 | post: { 140 | id: number; 141 | creationDate: number; 142 | contentPreview: string; 143 | author: { 144 | username: string; 145 | isActive: boolean; 146 | profile: { 147 | userAvatar: string; 148 | }; 149 | }; 150 | }; 151 | }[]; 152 | }; 153 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "commonjs", 5 | "lib": ["dom", "es6", "es2017", "esnext.asynciterable"], 6 | "skipLibCheck": true, 7 | "sourceMap": true, 8 | "outDir": "./dist", 9 | "moduleResolution": "node", 10 | "removeComments": true, 11 | "noImplicitAny": true, 12 | "strictNullChecks": true, 13 | "strictFunctionTypes": true, 14 | "noImplicitThis": true, 15 | "noUnusedLocals": true, 16 | "noUnusedParameters": true, 17 | "noImplicitReturns": true, 18 | "noFallthroughCasesInSwitch": true, 19 | "allowSyntheticDefaultImports": true, 20 | "esModuleInterop": true, 21 | "emitDecoratorMetadata": true, 22 | "experimentalDecorators": true, 23 | "resolveJsonModule": true, 24 | "baseUrl": "." 25 | }, 26 | "exclude": ["node_modules", "src/__tests__"], 27 | "include": ["./src/**/*.ts"] 28 | } 29 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "builds": [ 4 | { 5 | "src": "./index.js", 6 | "use": "@vercel/node" 7 | } 8 | ], 9 | "routes": [ 10 | { 11 | "src": "/(.*)", 12 | "dest": "/" 13 | } 14 | ] 15 | } 16 | --------------------------------------------------------------------------------