Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: replace npm with bun #5

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ If Pinned runs into an error, it will return a response with a response code oth

Clone the repository, `cd` into it and run the following commands to install dependencies and run the code:

```
npm install
npm run dev
```bash
bun install
bun run dev
```

Pinned is deployed on [Cloudflare Workers](https://workers.cloudflare.com/). To deploy Pinned, run the following command:

```
npm run deploy
```bash
bun run deploy
```
Binary file added bun.lockb
Binary file not shown.
56 changes: 50 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ app.use(

// Enable 5 minute caching for all routes in production
app.use("*", async (c, next) => {
if (!c.env.dev) {
if (c.env.dev === false) {
return cache({
cacheName: "gh-request-cache",
cacheControl: "max-age=300",
Expand All @@ -37,20 +37,46 @@ app.use("*", async (c, next) => {

// Redirect root path to GitHub repository
app.get("/", async (c) => {
return c.redirect("https://github.com/berrysauce/pinned", 301);
// return c.text("📌 PINNED\nPlease use /get/username to get the pinned repositories of a GitHub user")
const accept = c.req.header("Accept") || "";
const userAgent = c.req.header("User-Agent") || "";

// Check if request is from a browser (prefers HTML or is a common browser)
const isBrowser =
accept.includes("text/html") ||
/chrome|firefox|safari|edge|opera/i.test(userAgent);

return isBrowser
? c.redirect("https://github.com/berrysauce/pinned", 301)
: c.text(
"📌 PINNED\nPlease use /get/username to get the pinned repositories of a GitHub user"
);
});

// Define structure for repository data
interface RepositoryData {
author: string;
name: string;
url: string;
description: string;
language: string;
languageColor?: string;
languageIcon?: string;
stars?: number;
forks?: number;
}

// Map special language names to their simple-icons slugs
function mapLanguageName(lang: string): string {
const mapping: Record<string, string> = {
"C#": "csharp",
"F#": "fsharp",
"C++": "cplusplus",
"Visual Basic": "visualbasic",
".NET": "dotnet",
};
return mapping[lang] || lang.toLowerCase();
}

function parseRepository(root: HTMLElement, el: HTMLElement): RepositoryData {
const repoPath =
el.querySelector("a")?.getAttribute("href")?.split("/") || [];
Expand All @@ -71,14 +97,29 @@ function parseRepository(root: HTMLElement, el: HTMLElement): RepositoryData {
}
};

const languageSpan = el.querySelector("span[itemprop='programmingLanguage']");
const languageColorSpan = languageSpan?.parentNode?.querySelector(
".repo-language-color"
);
const language = languageSpan?.text || "";

return {
author,
name,
url: `https://github.com/${author}/${name}`,
description:
el.querySelector("p.pinned-item-desc")?.text?.replace(/\n/g, "").trim() ||
"",
language:
el.querySelector("span[itemprop='programmingLanguage']")?.text || "",
language,
languageColor:
languageColorSpan
?.getAttribute("style")
?.match(/background-color:\s*([^;]+)/)?.[1] || "",
languageIcon: language
? `https://cdn.simpleicons.org/${encodeURIComponent(
mapLanguageName(language)
)}`
: "",
stars: parseMetric(0),
forks: parseMetric(1),
};
Expand All @@ -100,7 +141,10 @@ app.get("/get/:username", async (c) => {
}

// Handle common HTTP error responses
const errorResponses: Record<number, { status: StatusCode; message: string }> = {
const errorResponses: Record<
number,
{ status: StatusCode; message: string }
> = {
404: { status: 404, message: "User not found" },
429: { status: 429, message: "Origin rate limit exceeded" },
};
Expand Down