import { contentType } from "jsr:@std/media-types"; import { transpile } from "jsr:@deno/emit"; import config from "./deno.json" with { type: "json" }; const jsContentType = contentType(".js"); export enum MediaType { TypeScript, JSX, TSX, }; // https://github.com/denoland/deno_ast/blob/ea1ccec37e1aa8e5e1e70f983a7ed1472d0e132a/src/media_type.rs#L117 const customContentType = { [MediaType.TypeScript]: "text/typescript; charset=utf-8", [MediaType.JSX]: "text/jsx; charset=utf-8", [MediaType.TSX]: "text/tsx; charset=utf-8", }; async function rewriteTsResponse(response: Response, url: URL, mediaType: MediaType) { const tsCode = await response.text(); const targetUrlStr = url.toString(); try { const result = await transpile(url, { importMap: config, compilerOptions: config.compilerOptions, load(specifier) { if (specifier !== targetUrlStr) { return Promise.resolve({ kind: "module", specifier, content: "", headers: { "content-type": "application/javascript; charset=utf-8" }, }); } else { return Promise.resolve({ kind: "module", specifier, content: tsCode, headers: { "content-type": customContentType[mediaType], }, }); } }, }); const jsCode = result.get(targetUrlStr); const { headers } = response; headers.set("content-type", jsContentType); headers.delete("content-length"); return new Response(jsCode, { status: response.status, statusText: response.statusText, headers, }); } catch (e) { console.error(e); return new Response(`${e}`, { status: 500, statusText: `${e}`, headers: response.headers, }); } } export default async function transpileResponse(response: Response, requestUrl: string, filepath?: string): Promise { const url = new URL(`ts-serve:///${ requestUrl }`); if (response.status !== 200) { return response; } const pathname = filepath !== undefined ? filepath : url.pathname; const extension = pathname.split('.').at(-1) ?? null; switch (extension) { case 'ts': return await rewriteTsResponse(response, url, MediaType.TypeScript); case 'tsx': return await rewriteTsResponse(response, url, MediaType.TSX); case 'jsx': return await rewriteTsResponse(response, url, MediaType.JSX); default: return response; } }