From 580a396cf5cee4e29cfc702497ec12efe555ca48 Mon Sep 17 00:00:00 2001 From: rolled-potatoes Date: Sun, 31 Dec 2023 13:29:33 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=BB=A4=EB=B0=8B=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .husky/pre-commit | 4 +++ .lintstagedrc | 4 +++ bun.lockb | Bin 47838 -> 68623 bytes package.json | 7 ++-- src/routes/v1/index.ts | 55 ++++++++++------------------- src/services/index.ts | 78 +++++++++++++++++++++++++++++++++++------ 6 files changed, 98 insertions(+), 50 deletions(-) create mode 100755 .husky/pre-commit create mode 100644 .lintstagedrc diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..fad85ff --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +bunx lint-staged diff --git a/.lintstagedrc b/.lintstagedrc new file mode 100644 index 0000000..aaeac94 --- /dev/null +++ b/.lintstagedrc @@ -0,0 +1,4 @@ +{ + "*.ts": ["prettier --write"], + "*.js": ["prettier --write"] +} diff --git a/bun.lockb b/bun.lockb index 1852f15fab7827936e6729abfae7b67e9a8e0257..8b8ef37d7aaefb2b5029763360081d07ff0e8b06 100755 GIT binary patch delta 18803 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 GsQ(Yvv0AnO delta 6443 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 { +router.get('/callback', async (req, res) => { const { code } = req.query; const result = await axios({ - method: "post", + method: 'post', url: `https://github.com/login/oauth/access_token`, headers: { - accept: "application/json", + accept: 'application/json', }, data: { client_id: Bun.env.CLIENT_ID, @@ -34,53 +34,34 @@ router.get("/callback", async (req, res) => { res.json(true); }); -router.get("/test", async (req, res) => { - const accessToken = "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"; +router.get('/data', async (req, res) => { + const { accessToken } = req.query; const user = await getUser(accessToken); const userName = user.login; - /* const data = await getUserCommits(accessToken, userName, { + const commits = await getUserCommits(accessToken, userName, { since: '2023-01-01T00:00:00Z', until: '2024-01-01T00:00:00Z', per_page: 100, - }); */ - const data = await getRepoCommits( - accessToken, - "rolled-potatoes", - "utterance" - ); - - res.json(data); -}); - -router.get("/data", async (req, res) => { - const { accessToken } = req.body; - - const user = await getUser(accessToken); - const userName = user.login; - - const commits = await getUserCommits(accessToken, userName, { - since: "2023-01-01T00:00:00Z", - until: "2024-01-01T00:00:00Z", - per_page: 100, }); const starCount = await getUserRepoStars(accessToken, userName); const { followerCount, followingCount } = await getFriendsCount(accessToken); - const mostUsedLanguage = ["JavaScript", "TypeScript", "Python"]; // string[] - const moreThan = "high"; // high, middle, low + const mostUsedLanguage = ['JavaScript', 'TypeScript', 'Python']; // string[] + const moreThan = 'high'; // high, middle, low const commitCount = 1234; // number - const commitDate = "월요일"; // 월요일, 화요일, 수요일, 목요일, 금요일, 토요일, 일요일 + const commitDate = '월요일'; // 월요일, 화요일, 수요일, 목요일, 금요일, 토요일, 일요일 const mostCommunication = { // 여기 줄때 github profile 주소도 주면 좋지 않을까 ? - name: "bsy1141", // string - image: "https://avatars.githubusercontent.com/u/60652298?v=4", // string + name: 'bsy1141', // string + image: 'https://avatars.githubusercontent.com/u/60652298?v=4', // string }; - const mbti = "INFP"; // string + const mbti = 'INFP'; // string res.json({ + commits, starCount, followerCount, followingCount, diff --git a/src/services/index.ts b/src/services/index.ts index 8eee0da..ad0c944 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -1,31 +1,87 @@ -import { getRepos, getRepoStars } from "./repo"; -import { getRepoCommits } from "./commit/"; -import { getUser } from "./user"; +import { getRepos, getRepoStars } from './repo'; +import { getRepoCommits } from './commit/'; +import { getUser } from './user'; +async function getTotalRepoCommits({ + ownerName, + repoName, + accessToken, + query, +}: { + [key: string]: any; +}) { + const mergedQuery = { + ...query, + page: 1, + per_page: 100, + }; + let res: any = []; + + try { + while (true) { + const data = await getRepoCommits( + accessToken, + ownerName, + repoName, + mergedQuery, + ); + if (!data) return []; + res = res.concat(data); + const lastCommitItem = data.slice(-1); + const hasMorePage = lastCommitItem[0]?.parents + ? lastCommitItem[0].parents.length > 0 + : false; + if (hasMorePage) { + mergedQuery.page += 1; + } else { + break; + } + } + } catch (e) { + //TODO: github api error 처리 + } + + return res; +} + +//parents 가 빈 오브젝으면 페이지 네이션끝 export const getUserCommits = async ( accessToken: string, ownerName: string, - query?: any + query?: any, ) => { + const repositoryObject: Record = {}; + const repos = await getRepos(accessToken, ownerName); - const queue = repos.map((repo: any) => { + + const jobs = repos.map(async (repo: any) => { const ownerName = repo.owner.login; - const repoName = repo.name; + const repositoryName = repo.name; + const repositoryPath = `${ownerName}/${repositoryName}`; + + if (!repositoryObject[repositoryPath]) { + repositoryObject[repositoryPath] = []; + } - return () => getRepoCommits(accessToken, ownerName, repoName, query); + repositoryObject[repositoryPath] = await getTotalRepoCommits({ + ownerName, + accessToken, + query, + repoName: repositoryName, + }); + return repositoryObject[repositoryPath]; }); - const jobs = Promise.all(queue.slice(10, 15).map((q: any) => q())); + await Promise.all(jobs); - return jobs; + return repositoryObject; }; export const getUserRepoStars = async ( accessToken: string, - ownerName: string + ownerName: string, ) => { const repos = await getRepos(accessToken, ownerName); - const queue = repos.map((repo: any) => { const ownerName = repo.owner.login; const repoName = repo.name;