Files
djledda-web/transpile.ts
Daniel Ledda ea5be77bc9 better
2024-10-31 17:14:30 +01:00

58 lines
2.3 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;
}