Created
February 27, 2024 00:19
-
-
Save Lissy93/06b8453e791c48ba77a2acddc154259b to your computer and use it in GitHub Desktop.
A quick 'n dirty Cloudflare Worker, for fetching pertinent about a given GitHub repository
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default { | |
async fetch(request, env) { | |
// Extract username and repo from the URL path | |
const url = new URL(request.url); | |
const pathSegments = url.pathname.split('/').filter(Boolean); | |
if (pathSegments.length !== 2) { | |
return new Response('URL must be in the format /{username}/{repo}', { status: 400 }); | |
} | |
const [username, repo] = pathSegments; | |
// Headers for GitHub API requests | |
const headers = { | |
...(env.GITHUB_TOKEN ? { 'Authorization': `token ${env.GITHUB_TOKEN}` } : {}), | |
'User-Agent': 'as93-repo-info-worker', | |
'Accept': 'application/vnd.github.v3+json' | |
}; | |
// API base URL, for given username and repo | |
const baseUrl = `https://api.github.com/repos/${username}/${repo}`; | |
try { | |
// Parallel fetch requests for repository information | |
const [ | |
infoResponse, languagesResponse, updatesResponse, | |
versionsResponse, contributorsResponse, commitsResponse, | |
] = await Promise.all([ | |
fetch(`${baseUrl}`, { headers }), | |
fetch(`${baseUrl}/languages`, { headers }), | |
fetch(`${baseUrl}/events`, { headers }), | |
fetch(`${baseUrl}/tags`, { headers }), | |
fetch(`${baseUrl}/contributors`, { headers }), | |
fetch(`${baseUrl}/commits`, { headers }) | |
]); | |
// Handle potential fetch errors | |
const responses = [ | |
infoResponse, languagesResponse, updatesResponse, | |
versionsResponse, contributorsResponse, commitsResponse, | |
]; | |
for (const response of responses) { | |
if (!response.ok) { | |
throw new Error(`Failed to fetch from GitHub API: ${response.statusText}`); | |
} | |
} | |
// Extract and format JSON data from responses | |
const data = await Promise.all(responses.map(response => response.json())); | |
const [info, languages, updates, versions, contributors, commits] = data; | |
// Construct the final response object, containing only what we need | |
const result = { | |
info: { | |
ownerUsername: info.owner.login, | |
ownerAvatar: info.owner.avatar_url, | |
description: info.description, | |
url: info.html_url, | |
homepage: info.homepage, | |
language: info.language, | |
topics: info.topics, | |
license: info.license?.spdx_id, | |
isFork: info.fork, | |
isArchived: info.archived, | |
createdAt: info.created_at, | |
updatedAt: info.updated_at, | |
size: info.size, | |
scarCount: info.stargazers_count, | |
forksCount: info.forks_count, | |
watchersCount: info.watchers_count | |
}, | |
languages, | |
updates: updates.map(update => ({ | |
type: update.type, | |
actor: { | |
username: update.actor.login, | |
avatar: update.actor.avatar_url | |
}, | |
repo: update.repo.name, | |
action: update.payload.action, | |
number: update.payload.number, | |
createdAt: update.created_at | |
})), | |
versions: versions.map(version => ({ | |
name: version.name, | |
commit: version.commit.sha, | |
zipball: version.zipball_url, | |
tarball: version.tarball_url | |
})), | |
contributors: contributors.map(contributor => ({ | |
username: contributor.login, | |
avatar: contributor.avatar_url, | |
contributions: contributor.contributions | |
})), | |
commits: commits.map(commit => ({ | |
sha: commit.sha, | |
authorName: commit.commit.author.name, | |
authorDate: commit.commit.author.date, | |
message: commit.commit.message, | |
authorUsername: commit.author?.login, | |
authorAvatar: commit.author?.avatar_url | |
})) | |
}; | |
// Return the response as JSON | |
return new Response(JSON.stringify(result), { | |
headers: { 'Content-Type': 'application/json' } | |
}); | |
} catch (error) { | |
// Something fucked up real bad | |
return new Response(error.message, { status: 500 }); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Docs 👇
About
Simple API to return data about a given GitHub repo. Runs as a Cloudflare Worker.
Why?
To fetch full info on a repository, you're required to make several seperate requests to the GitHub REST API. (One for repo meta, languages, update events, versions, contributors, commits, etc). This is a bit of a faf if you're doing this in a frontend app, as you'll be rate-limited if you don't provide a token, yet it's not secure to use your GitHub token client-side.
As you can see, the code is quick and dirty, written in 5 minutes. But it does the job!
Usage
npm i -g wrangler
wrangler init repo-stats
cd repo-stats
andnpm install
wrangler.toml
add your API key to theGITHUB_TOKEN
env varwrangler dev
wrangler deploy
to deploy your app to the world! 🚀You can now make requests to
https://[project-name].workers.dev/[user]/[repo]
License
Licensed under MIT, © Alicia Sykes 2024