原仓库代码:/select?titleSlug=selected-question 这个端点函数的调用关系是?
The /select?titleSlug=selected-question endpoint in the alfaarghya/alfa-leetcode-api repository is implemented using a GraphQL query defined in src/GQLQueries/selectProblem.ts. The query fetches detailed information about a specific question based on the titleSlug.
Here is the source code for the implementation.
The code in src/GQLQueries is imported and used in src/GQLQueries/index.ts. You can view the details here.
解释export { default as selectProblemQuery } from ‘./selectProblem’;
This line of code in src/GQLQueries/index.ts re-exports the default export from the ./selectProblem module and names it selectProblemQuery. This allows other modules to import selectProblemQuery directly from src/GQLQueries/index.ts instead of importing from ./selectProblem directly.
export const selectProblem = (req: Request, res: Response) => {const title = req.query.titleSlug as string;if (title !== undefined) {controllers.fetchSingleProblem(res,formatUtils.formatQuestionData,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',});}
};
This code defines and exports a function named selectProblem which acts as a route handler for an Express.js application. Here’s what it does:
- It extracts the
titleSlugquery parameter from the request (req). - If
titleSlugis defined, it calls thefetchSingleProblemfunction from thecontrollersmodule, passing it the response object (res), a format function (formatUtils.formatQuestionData), a GraphQL query (gqlQueries.selectProblemQuery), and thetitleSlug. - If
titleSlugis not defined, it responds with a 400 status and a JSON error message indicating the missing or invalid query parameter. The response includes an example of the correct usage.
import { Response } from 'express';
import { DailyProblemData, SelectProblemData } from '../types';const fetchSingleProblem = async (res: Response,formatData: (data: DailyProblemData & SelectProblemData) => void,query: string,titleSlug: string | null
) => {try {const response = await fetch('https://leetcode.com/graphql', {method: 'POST',headers: {'Content-Type': 'application/json',Referer: 'https://leetcode.com',},body: JSON.stringify({query: query,variables: {titleSlug, //search question using titleSlug},}),});const result = await response.json();if (result.errors) {return res.send(result);}return res.json(formatData(result.data));} catch (err) {console.error('Error: ', err);return res.send(err);}
};export default fetchSingleProblem;
This code defines and exports an asynchronous function fetchSingleProblem which performs the following actions:
- Imports
Responsefromexpressand two types,DailyProblemDataandSelectProblemData, from../types. - The function
fetchSingleProblemtakes four parameters:res(Express response object),formatData(a function to format the fetched data),query(a GraphQL query string), andtitleSlug(the title slug of the problem). - It sends a POST request to the LeetCode GraphQL API with the provided query and titleSlug.
- If the request is successful and there are no errors, it formats the data using
formatDataand sends it in the response. - If an error occurs, it logs the error and sends the error in the response.
总结
要实现一个独立的 /select?titleSlug=selected-question 端点,下面是一个完整的项目结构、运行和测试步骤。
项目结构
my-leetcode-api/
├── src/
│ ├── GQLQueries/
│ │ ├── selectProblem.ts
│ ├── controllers/
│ │ ├── fetchSingleProblem.ts
│ │ └── problemController.ts
│ ├── routes/
│ │ └── problemRoutes.ts
│ ├── types/
│ │ └── index.ts
│ ├── app.ts
│ └── server.ts
├── package.json
├── tsconfig.json
└── README.md
代码实现
src/GQLQueries/selectProblem.ts
const query = `#graphql
query selectProblem($titleSlug: String!) {question(titleSlug: $titleSlug) {questionIdquestionFrontendIdboundTopicIdtitletitleSlugcontenttranslatedTitletranslatedContentisPaidOnlydifficultylikesdislikesisLikedsimilarQuestionsexampleTestcasescontributors {usernameprofileUrlavatarUrl}topicTags {nameslugtranslatedName}companyTagStatscodeSnippets {langlangSlugcode}statshintssolution {idcanSeeDetailpaidOnlyhasVideoSolutionpaidOnlyVideo}statussampleTestCasemetaDatajudgerAvailablejudgeTypemysqlSchemasenableRunCodeenableTestModeenableDebuggerenvInfolibraryUrladminUrlchallengeQuestion {iddateincompleteChallengeCountstreakCounttype}note}
}`;
export default query;
src/controllers/fetchSingleProblem.ts
import { Response } from 'express';
import { DailyProblemData, SelectProblemData } from '../types';const fetchSingleProblem = async (res: Response,formatData: (data: DailyProblemData & SelectProblemData) => void,query: string,titleSlug: string | null
) => {try {const response = await fetch('https://leetcode.com/graphql', {method: 'POST',headers: {'Content-Type': 'application/json',Referer: 'https://leetcode.com',},body: JSON.stringify({query: query,variables: {titleSlug,},}),});const result = await response.json();if (result.errors) {return res.send(result);}return res.json(formatData(result.data));} catch (err) {console.error('Error: ', err);return res.send(err);}
};export default fetchSingleProblem;
src/controllers/problemController.ts
import { Request, Response } from 'express';
import fetchSingleProblem from './fetchSingleProblem';
import { formatQuestionData } from '../utils/formatUtils';
import selectProblemQuery from '../GQLQueries/selectProblem';export const selectProblem = (req: Request, res: Response) => {const title = req.query.titleSlug as string;if (title !== undefined) {fetchSingleProblem(res,formatQuestionData,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',});}
};
src/routes/problemRoutes.ts
import express from 'express';
import { selectProblem } from '../controllers/problemController';const router = express.Router();router.get('/select', selectProblem);export default router;
src/types/index.ts
export interface DailyProblemData {// Define your DailyProblemData properties here
}export interface SelectProblemData {// Define your SelectProblemData properties here
}
src/app.ts
import express from 'express';
import problemRoutes from './routes/problemRoutes';const app = express();app.use(express.json());
app.use('/api/problems', problemRoutes);export default app;
src/server.ts
import app from './app';const PORT = process.env.PORT || 3000;app.listen(PORT, () => {console.log(`Server is running on port ${PORT}`);
});
运行项目
-
初始化项目:
npm init -y npm install express typescript ts-node @types/node @types/express -
创建
tsconfig.json文件:{"compilerOptions": {"target": "ES6","module": "commonjs","outDir": "./dist","rootDir": "./src","strict": true,"esModuleInterop": true},"include": ["src"],"exclude": ["node_modules"] } -
在
package.json中添加脚本:"scripts": {"start": "ts-node src/server.ts" } -
运行项目:
npm start
测试
-
使用 Postman 或 cURL 测试端点:
curl -X GET "http://localhost:3000/api/problems/select?titleSlug=two-sum" -
确保返回正确的数据格式和内容。
以上便是实现独立的 /select?titleSlug=selected-question 端点的完整项目结构、代码实现、运行步骤和测试方法。
