diff --git a/.gitignore b/.gitignore index 09777b5..acb77b8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ node_modules .vercel .idea -.claude \ No newline at end of file +.claude +.env*.local diff --git a/scripts/github/__mock__/mockGithubApiResponse.ts b/scripts/github/__mock__/mockGithubApiResponse.ts new file mode 100644 index 0000000..fb1bbb0 --- /dev/null +++ b/scripts/github/__mock__/mockGithubApiResponse.ts @@ -0,0 +1,51 @@ +import { GitHubApiResponse } from "../../../types"; + +const MOCK_RESPONSE: GitHubApiResponse = { + data: { + user: { + followers: { totalCount: 42 }, + repositories: { + edges: [ + { + node: { + stargazerCount: 15, + forkCount: 3, + languages: { + edges: [ + { node: { name: "TypeScript", color: "#3178c6" } }, + { node: { name: "JavaScript", color: "#f1e05a" } }, + ], + }, + }, + }, + { + node: { + stargazerCount: 8, + forkCount: 1, + languages: { + edges: [ + { node: { name: "TypeScript", color: "#3178c6" } }, + { node: { name: "CSS", color: "#563d7c" } }, + ], + }, + }, + }, + { + node: { + stargazerCount: 5, + forkCount: 0, + languages: { + edges: [{ node: { name: "Python", color: "#3572A5" } }], + }, + }, + }, + ], + }, + contributionsCollection: { + contributionCalendar: { totalContributions: 847 }, + }, + }, + }, +}; + +export { MOCK_RESPONSE }; diff --git a/scripts/github/githubApiClient.ts b/scripts/github/githubApiClient.ts index f4921a3..0fe15a1 100644 --- a/scripts/github/githubApiClient.ts +++ b/scripts/github/githubApiClient.ts @@ -1,62 +1,59 @@ import https from "https"; import dotenv from "dotenv"; import { GitHubApiResponse } from "../../types"; +import { MOCK_RESPONSE } from "./__mock__/mockGithubApiResponse"; dotenv.config(); const createHeaders = (): Record => ({ - "user-agent": "Github-Stats", - Authorization: `Bearer ${process.env.GITHUB_TOKEN}`, - "Content-Type": "application/json", - Accept: "application/json", + "user-agent": "Github-Stats", + Authorization: `Bearer ${process.env.GITHUB_TOKEN}`, + "Content-Type": "application/json", + Accept: "application/json", }); const makeGraphQLRequest = (query: string): Promise => { - const options: https.RequestOptions = { - hostname: "api.github.com", - path: "/graphql", - method: "POST", - headers: createHeaders(), - }; - - return new Promise((resolve, reject) => { - const req = https.request(options, (res) => { - const buffers: Buffer[] = []; - - res.on("data", (d: Buffer) => { - buffers.push(d); - }); - - res.on("end", () => { - try { - resolve( - JSON.parse( - Buffer.concat(buffers).toString() - ) as GitHubApiResponse - ); - } catch (e) { - reject( - new Error( - `Failed to parse GitHub API response: ${(e as Error).message}` - ) - ); - } - }); - }); - - req.on("error", (error: Error) => { - console.log(error); - reject(error); - }); - - req.setTimeout(30000, () => { - req.destroy(); - reject(new Error("GitHub API request timed out")); - }); - - req.write(JSON.stringify({ query })); - req.end(); - }); + if (process.env.MOCK_GITHUB === "true") { + return Promise.resolve(MOCK_RESPONSE); + } + + const options: https.RequestOptions = { + hostname: "api.github.com", + path: "/graphql", + method: "POST", + headers: createHeaders(), + }; + + return new Promise((resolve, reject) => { + const req = https.request(options, (res) => { + const buffers: Buffer[] = []; + + res.on("data", (d: Buffer) => { + buffers.push(d); + }); + + res.on("end", () => { + try { + resolve(JSON.parse(Buffer.concat(buffers).toString()) as GitHubApiResponse); + } catch (e) { + reject(new Error(`Failed to parse GitHub API response: ${(e as Error).message}`)); + } + }); + }); + + req.on("error", (error: Error) => { + console.log(error); + reject(error); + }); + + req.setTimeout(30000, () => { + req.destroy(); + reject(new Error("GitHub API request timed out")); + }); + + req.write(JSON.stringify({ query })); + req.end(); + }); }; export { makeGraphQLRequest };