Skip to content

Commit 852f0ae

Browse files
committed
✨ deploy github user contribution endpoint to cloudflare
1 parent 10c4c3c commit 852f0ae

File tree

9 files changed

+257
-287
lines changed

9 files changed

+257
-287
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ dist
44
!svg-only/dist
55
build
66
.env
7+
.wrangler
8+
.dev.vars

bun.lock

Lines changed: 172 additions & 245 deletions
Large diffs are not rendered by default.
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
11
# @snk/github-user-contribution-service
22

3-
Expose github-user-contribution as an endpoint, using vercel.sh
3+
Expose github-user-contribution as an endpoint. hosted on cloudflare
4+
5+
```sh
6+
7+
8+
# deploy
9+
bunx wrangler deploy --branch=production
10+
11+
# change secret
12+
bunx wrangler secret put GITHUB_TOKEN
13+
14+
```

packages/github-user-contribution-service/api/github-user-contribution/[userName].ts

Lines changed: 0 additions & 33 deletions
This file was deleted.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { getGithubUserContribution } from "@snk/github-user-contribution";
2+
3+
const cors =
4+
<
5+
Req extends { headers: Headers },
6+
Res extends { headers: Headers },
7+
A extends Array<any>,
8+
>(
9+
f: (req: Req, ...args: A) => Res | Promise<Res>,
10+
) =>
11+
async (req: Req, ...args: A) => {
12+
const res = await f(req, ...args);
13+
14+
const origin = req.headers.get("origin");
15+
16+
if (origin) {
17+
const { host, hostname } = new URL(origin);
18+
19+
if (hostname === "localhost" || host === "platane.github.io")
20+
res.headers.set("Access-Control-Allow-Origin", origin);
21+
}
22+
23+
res.headers.set("Access-Control-Allow-Methods", "GET, OPTIONS");
24+
res.headers.set("Access-Control-Allow-Headers", "Content-Type");
25+
return res;
26+
};
27+
28+
export default {
29+
fetch: cors(async (req: Request, env: { GITHUB_TOKEN: string }) => {
30+
const url = new URL(req.url);
31+
32+
const [, userName] =
33+
url.pathname.match(/^\/github-user-contribution\/([^\/]*)\/?$/) ?? [];
34+
35+
if (req.method === "OPTIONS") return new Response();
36+
37+
if (!userName || req.method !== "GET")
38+
return new Response("unknown route", { status: 404 });
39+
40+
const body = await getGithubUserContribution(userName, {
41+
githubToken: env.GITHUB_TOKEN,
42+
});
43+
44+
return new Response(JSON.stringify(body), {
45+
status: 200,
46+
headers: {
47+
"Cache-Control": "max-age=21600, s-maxage=21600",
48+
"Content-Type": "application/json",
49+
},
50+
});
51+
}),
52+
};

packages/github-user-contribution-service/package.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22
"name": "@snk/github-user-contribution-service",
33
"version": "1.0.0",
44
"dependencies": {
5-
"@snk/github-user-contribution": "1.0.0",
6-
"@vercel/node": "5.1.7"
5+
"@snk/github-user-contribution": "1.0.0"
6+
},
7+
"devDependencies": {
8+
"wrangler": "3.109.2",
9+
"@cloudflare/workers-types": "4.20250214.0"
10+
},
11+
"scripts": {
12+
"deploy": "wrangler deploy"
713
}
814
}

packages/github-user-contribution-service/vercel.json

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name = "github-user-contribution"
2+
main = "index.ts"
3+
compatibility_date = "2024-09-02"
4+
5+
account_id = "56268cde636c288343cb0767952ecf2e"
6+
workers_dev = true
7+
8+
[observability]
9+
enabled = true

packages/github-user-contribution/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,13 @@ export const getGithubUserContribution = async (
4242
headers: {
4343
Authorization: `bearer ${o.githubToken}`,
4444
"Content-Type": "application/json",
45+
"User-Agent": "me@platane.me",
4546
},
4647
method: "POST",
4748
body: JSON.stringify({ variables, query }),
4849
});
4950

50-
if (!res.ok) throw new Error(res.statusText);
51+
if (!res.ok) throw new Error(await res.text().catch(() => res.statusText));
5152

5253
const { data, errors } = (await res.json()) as {
5354
data: GraphQLRes;

0 commit comments

Comments
 (0)