66 lines
2.4 KiB
TypeScript
66 lines
2.4 KiB
TypeScript
import { CompilerOptions, transpile, TranspileOptions } from "jsr:@deno/emit";
|
|
import denoJson from "./deno.json" with { type: "json" };
|
|
|
|
const contentTypes = {
|
|
"js": "application/javascript; charset=utf-8",
|
|
|
|
// https://github.com/denoland/deno_ast/blob/ea1ccec37e1aa8e5e1e70f983a7ed1472d0e132a/src/media_type.rs#L117
|
|
"ts": "text/typescript; charset=utf-8",
|
|
"jsx": "text/jsx; charset=utf-8",
|
|
"tsx": "text/tsx; charset=utf-8",
|
|
} as const;
|
|
|
|
const transpileOptions = (
|
|
extension: keyof typeof contentTypes,
|
|
tsCode: string,
|
|
targetUrlStr: string,
|
|
): TranspileOptions => ({
|
|
importMap: {
|
|
imports: denoJson.imports,
|
|
},
|
|
compilerOptions: denoJson.compilerOptions as CompilerOptions,
|
|
load(specifier) {
|
|
const correctContent = specifier === targetUrlStr;
|
|
return Promise.resolve({
|
|
kind: "module",
|
|
specifier,
|
|
content: correctContent ? tsCode : "",
|
|
headers: { "content-type": contentTypes[correctContent ? extension : "js"] },
|
|
});
|
|
},
|
|
});
|
|
|
|
export default async function transpileResponse(
|
|
response: Response,
|
|
requestUrl: string,
|
|
filepath?: string,
|
|
): Promise<Response> {
|
|
const url = new URL(`ts-serve:///${requestUrl}`);
|
|
const pathname = filepath !== undefined ? filepath : url.pathname;
|
|
const extension = pathname.split(".").at(-1) ?? "";
|
|
if (response.status === 200 && (extension === "ts" || extension === "tsx" || extension === "jsx")) {
|
|
const tsCode = await response.text();
|
|
const targetUrlStr = url.toString();
|
|
try {
|
|
const result = await transpile(url, transpileOptions(extension, tsCode, targetUrlStr));
|
|
const jsCode = result.get(targetUrlStr);
|
|
response.headers.delete("content-length");
|
|
response.headers.set("content-type", contentTypes.js);
|
|
return new Response(jsCode, {
|
|
status: response.status,
|
|
statusText: response.statusText,
|
|
headers: response.headers,
|
|
});
|
|
} catch (e) {
|
|
console.error("[transpileResponse]: Error transpiling!\n", e);
|
|
if (typeof e === "string") {
|
|
return new Response("Internal Server Error", {
|
|
status: 500,
|
|
headers: response.headers,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
return response;
|
|
}
|