[READ-ONLY] Mirror of https://github.com/flo-bit/edge-function-github-contribution. edge-function-github-contribution.vercel.app
0

Configure Feed

Select the types of activity you want to include in your feed.

add readme, license

+237 -5
+21
LICENSE
··· 1 + MIT License Copyright (c) 2024 flo-bit 2 + 3 + Permission is hereby granted, free of 4 + charge, to any person obtaining a copy of this software and associated 5 + documentation files (the "Software"), to deal in the Software without 6 + restriction, including without limitation the rights to use, copy, modify, merge, 7 + publish, distribute, sublicense, and/or sell copies of the Software, and to 8 + permit persons to whom the Software is furnished to do so, subject to the 9 + following conditions: 10 + 11 + The above copyright notice and this permission notice 12 + (including the next paragraph) shall be included in all copies or substantial 13 + portions of the Software. 14 + 15 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 + ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 18 + EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 + THE SOFTWARE.
+204
Readme.md
··· 1 + # edge-function-github-contributions 2 + 3 + vercel edge function that returns some infos of your github account as a json (contributions, repositories, followers, following, issues, prs, status). 4 + 5 + can be called from any frontend application, including static sites. 6 + 7 + detailed infos: 8 + 9 + - contributions of the last year total, and split by day 10 + (return the contribution count of each day and a color for each day, that is used to color the heatmap on github) 11 + 12 + - contributions of the last year split by type (commits, pull requests, issues) 13 + 14 + - up to 100 user owned repositories sorted by most stars 15 + (return the name, description, stars, forks, watchers, top 10 languages each with a name and size in bytes) 16 + 17 + - count of: starred repositories, followers, following, repositories, pr requests, issues 18 + 19 + - current status of user 20 + 21 + ## Usage 22 + 23 + 1. create a personal access token on github, go to `settings` -> `developer settings` -> `personal access tokens (classic)` -> `generate new token (classic)`, set expiration date to "No expiration" and add the `public_repo`, `read:user` and `repo:status` scopes. 24 + 25 + 2. fork repository 26 + 27 + 3. deploy to vercel 28 + 29 + [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fflo-bit%2Fedge-function-github-contribution&env=GITHUB_TOKEN) 30 + 31 + 4. set environment variable `GITHUB_TOKEN` to the personal access token you created in step 1 32 + 33 + 5. get the url of the deployed function and use it in your application, by sending a GET request to the url 34 + 35 + ``` 36 + https://<your-deployment-url>/api/github-data 37 + ``` 38 + 39 + 6. simple example using fetch: 40 + 41 + ```js 42 + const res = await fetch('https://edge-function-github-contribution.vercel.app/api/github-data'); 43 + const json = await res.json(); // as GitHubResponse, see below 44 + 45 + console.log(json); 46 + ``` 47 + 48 + 7. it's recommended to remove data points you don't need, to reduce the size of the response and speed up the request 49 + 50 + ## development 51 + 52 + to run the function locally, you need to have the vercel cli installed: 53 + 54 + ``` 55 + npm i -g vercel@latest 56 + ``` 57 + 58 + then clone the repository: 59 + 60 + ``` 61 + git clone https://github.com/flo-bit/edge-function-github-contribution 62 + cd edge-function-github-contribution 63 + ``` 64 + 65 + add a `.env` file with the `GITHUB_TOKEN` environment variable and run: 66 + 67 + ``` 68 + vercel dev 69 + ``` 70 + 71 + ## response type 72 + 73 + if you're using it in a typescript project, here the type definition of the (successful) response: 74 + 75 + ```ts 76 + const githubGraphColors = ['#ebedf0', '#9be9a8', '#40c463', '#30a14e', '#216e39'] as const; 77 + 78 + // Define a type based on the color values 79 + export type GithubGraphColor = (typeof githubGraphColors)[number]; 80 + 81 + export type GitHubResponse = { 82 + data: { 83 + viewer: { 84 + login: string; 85 + contributionsCollection: { 86 + totalCommitContributions: number; 87 + totalIssueContributions: number; 88 + totalPullRequestContributions: number; 89 + totalPullRequestReviewContributions: number; 90 + contributionCalendar: { 91 + totalContributions: number; 92 + weeks: { 93 + contributionDays: { 94 + date: string; 95 + contributionCount: number; 96 + color: GithubGraphColor; 97 + }[]; 98 + }[]; 99 + }; 100 + }; 101 + repositories: { 102 + totalCount: number; 103 + nodes: { 104 + name: string; 105 + stargazerCount: number; 106 + forkCount: number; 107 + watchers: { 108 + totalCount: number; 109 + }; 110 + languages: { 111 + totalSize: number; 112 + edges: { 113 + node: { 114 + name: string; 115 + }; 116 + size: number; 117 + }[]; 118 + }; 119 + }[]; 120 + }; 121 + starredRepositories: { 122 + totalCount: number; 123 + }; 124 + followers: { 125 + totalCount: number; 126 + }; 127 + following: { 128 + totalCount: number; 129 + }; 130 + issues_sum: { 131 + totalCount: number; 132 + }; 133 + issues_open: { 134 + totalCount: number; 135 + }; 136 + issues_closed: { 137 + totalCount: number; 138 + }; 139 + pr_sum: { 140 + totalCount: number; 141 + }; 142 + pr_open: { 143 + totalCount: number; 144 + }; 145 + pr_closed: { 146 + totalCount: number; 147 + }; 148 + pr_merged: { 149 + totalCount: number; 150 + }; 151 + status: { 152 + emoji?: string; 153 + message?: string; 154 + expiresAt?: string; 155 + updatedAt?: string; 156 + } | null; 157 + }; 158 + }; 159 + }; 160 + ``` 161 + 162 + ## calculate more infos 163 + 164 + here is a typescript example to combine some of the infos to get: 165 + 166 + - total stars of user owned repositories 167 + - total forks of user owned repositories 168 + - total watchers of user owned repositories 169 + - total size of user owned repositories 170 + - total size of each language in user owned repositories 171 + 172 + ```ts 173 + let totalStars = 0; 174 + let totalSize = 0; 175 + let totalForks = 0; 176 + let totalWatchers = 0; 177 + 178 + const languages = new Map<string, number>(); 179 + 180 + for (const repo of json.data.viewer.repositories.nodes) { 181 + totalStars += repo.stargazerCount; 182 + totalSize += repo.languages.totalSize; 183 + totalForks += repo.forkCount; 184 + totalWatchers += repo.watchers.totalCount; 185 + 186 + for (const edge of repo.languages.edges) { 187 + const language = edge.node.name; 188 + const size = edge.size; 189 + languages.set(language, (languages.get(language) ?? 0) + size); 190 + } 191 + } 192 + 193 + json.data.viewer.totalStars = totalStars; 194 + json.data.viewer.totalSize = totalSize; 195 + json.data.viewer.totalForks = totalForks; 196 + json.data.viewer.totalWatchers = totalWatchers; 197 + json.data.viewer.languages = Array.from(languages, ([name, size]) => ({ name, size })).sort( 198 + (a, b) => b.size - a.size 199 + ); 200 + ``` 201 + 202 + ## license 203 + 204 + MIT
+9 -3
api/hello.ts api/github-data.ts
··· 36 36 nodes { 37 37 name 38 38 stargazerCount 39 + description 39 40 forkCount 40 41 watchers { 41 42 totalCount ··· 88 89 updatedAt 89 90 } 90 91 } 91 - rateLimit { 92 - cost 93 - } 94 92 } 95 93 `; 94 + 95 + // 96 + // to check cost of query, add this to the query (before the last } bracket) 97 + // rateLimit { 98 + // cost 99 + // remaining 100 + // } 101 + // cost of current query is 1 (rate limit 5000 per hour) 96 102 97 103 // Fetch data from GitHub using the token stored in Vercel environment variables 98 104 const response = await fetch('https://api.github.com/graphql', {
+3 -2
package.json
··· 2 2 "dependencies": { 3 3 "@types/node": "^22.7.5", 4 4 "next": "^14.2.14" 5 - } 6 - } 5 + }, 6 + "license": "MIT" 7 + }