1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import { decodeBase64 } from "jsr:@std/encoding@0.224.3/base64";
import { contentType } from "jsr:@std/media-types@1.0.0";
import { extname, join } from "jsr:@std/path@0.225.2";
export function serveGithubRepo(params: {
owner: string;
repo: string;
ref?: string;
root?: string;
prefix?: string;
}): (req: Request) => Promise<Response> {
return async (req: Request) => {
const url = new URL(req.url);
let pathname = url.pathname;
if (pathname.endsWith("/")) {
pathname += "index.html";
}
let prefix = params.prefix;
if (prefix) {
if (!prefix.startsWith("/")) {
prefix = "/" + prefix;
}
if (prefix.endsWith("/")) {
prefix = prefix.slice(0, -1);
}
pathname = pathname.replace(prefix, "");
}
if (params.root) {
if (!params.root.startsWith("/")) {
params.root = "/" + params.root;
}
pathname = join(params.root, pathname);
}
// we use import instead of fetch to leverage deno's caching
const { default: res } = await import(
`https://2json.deno.dev/raw.githubusercontent.com/${params.owner}/${params.repo}/${params.ref || "main"}`
+ pathname,
{ with: { type: "json" } }
);
return new Response(decodeBase64(res.body), {
headers: {
"content-type": contentType(extname(pathname))
|| "application/octet-stream",
},
});
};
}