bundler/server.ts

94 lines
2.4 KiB
TypeScript
Raw Permalink Normal View History

2020-05-13 14:39:34 +00:00
// Automated bundle server
2020-05-14 09:24:38 +00:00
export async function processRequest(
req: Request,
2021-07-27 20:17:38 +00:00
hostpath: string,
2020-05-14 09:24:38 +00:00
runner = Deno.run,
fetcher = fetch,
2020-05-14 09:24:38 +00:00
): Promise<Response> {
2022-09-01 21:50:17 +00:00
if (req.method == "OPTIONS") {
return new Response(undefined, {
headers: {
"Access-Control-Allow-Origin": "*",
},
});
}
2021-07-27 20:17:38 +00:00
if (req.method != "GET") {
return new Response(undefined, { status: 405 });
2021-07-27 20:17:38 +00:00
}
const params = req.url.split("/").filter((x) => !!x).slice(2);
2021-07-27 20:17:38 +00:00
if (params.length < 2) {
return new Response(undefined, { status: 404 });
2021-07-27 20:17:38 +00:00
}
const [lib, version] = params[0].split("@", 2);
const file = params.slice(1).join("/");
const branch = version || "master";
const path = `https://${hostpath}/${lib}/raw/${branch}/${file}`;
if (!isName(lib) || !isName(branch) || !isPath(file)) {
return new Response(
`console.error("bundler error - Invalid path ${path}");`,
{ status: 400 },
);
2020-05-14 09:24:38 +00:00
}
2021-07-27 20:17:38 +00:00
if (path.endsWith(".js")) {
return await bundle(path.slice(0, -3) + ".ts", runner);
} else {
return await fetcher(path, { redirect: "follow" });
2021-07-27 20:17:38 +00:00
}
}
async function bundle(
path: string,
runner: typeof Deno.run,
): Promise<Response> {
2020-05-14 09:24:38 +00:00
const process = runner({
cmd: ["deno", "bundle", path],
stdout: "piped",
});
const output = await process.output();
const status = await process.status();
if (status.success) {
2022-09-01 21:50:17 +00:00
return new Response(output, {
headers: {
"Content-Type": "text/javascript",
"Access-Control-Allow-Origin": "*",
},
});
2020-05-14 09:24:38 +00:00
} else {
return new Response(
`console.error("bundler error - Failed to bundle ${path}");`,
{ status: 500 },
);
2020-05-14 09:24:38 +00:00
}
}
2021-07-27 20:17:38 +00:00
export async function serveBundles(hostpath: string, port: number) {
const listen = { hostname: "0.0.0.0", port };
console.log(
`Serving ${hostpath} bundles on ${listen.hostname}:${listen.port} ...`,
);
for await (const conn of Deno.listen(listen)) {
for await (const req of Deno.serveHttp(conn)) {
try {
const response = await processRequest(req.request, hostpath);
await req.respondWith(response);
} catch (err) {
2022-09-01 21:50:17 +00:00
console.error(err);
await req.respondWith(Response.error());
}
2021-07-27 20:17:38 +00:00
}
2020-05-13 14:39:34 +00:00
}
}
2020-05-13 16:00:14 +00:00
2021-07-27 20:17:38 +00:00
function isName(input: string): boolean {
return !!input.match(/^[a-zA-Z0-9_\-\.]+$/);
}
function isPath(input: string): boolean {
return !input.split("/").some((part) => !isName(part));
}