djledda.de main
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

58 lines
2.3 KiB

  1. import { CompilerOptions, transpile, TranspileOptions } from "jsr:@deno/emit";
  2. import denoJson from "./deno.json" with { type: "json" };
  3. const contentTypes = {
  4. 'js': "application/javascript; charset=utf-8",
  5. // https://github.com/denoland/deno_ast/blob/ea1ccec37e1aa8e5e1e70f983a7ed1472d0e132a/src/media_type.rs#L117
  6. 'ts': "text/typescript; charset=utf-8",
  7. 'jsx': "text/jsx; charset=utf-8",
  8. 'tsx': "text/tsx; charset=utf-8",
  9. } as const;
  10. const transpileOptions = (extension: keyof typeof contentTypes, tsCode: string, targetUrlStr: string): TranspileOptions => ({
  11. importMap: {
  12. imports: denoJson.imports,
  13. },
  14. compilerOptions: denoJson.compilerOptions as CompilerOptions,
  15. load(specifier) {
  16. const correctContent = specifier === targetUrlStr;
  17. return Promise.resolve({
  18. kind: "module",
  19. specifier,
  20. content: correctContent ? tsCode : "",
  21. headers: { "content-type": contentTypes[correctContent ? extension : 'js'] },
  22. });
  23. },
  24. });
  25. export default async function transpileResponse(response: Response, requestUrl: string, filepath?: string): Promise<Response> {
  26. const url = new URL(`ts-serve:///${ requestUrl }`);
  27. const pathname = filepath !== undefined ? filepath : url.pathname;
  28. const extension = pathname.split('.').at(-1) ?? '';
  29. if (response.status === 200 && (extension === 'ts' || extension === 'tsx' || extension === 'jsx')) {
  30. const tsCode = await response.text();
  31. const targetUrlStr = url.toString();
  32. try {
  33. const result = await transpile(url, transpileOptions(extension, tsCode, targetUrlStr));
  34. const jsCode = result.get(targetUrlStr);
  35. response.headers.delete("content-length");
  36. response.headers.set("content-type", contentTypes.js);
  37. return new Response(jsCode, {
  38. status: response.status,
  39. statusText: response.statusText,
  40. headers: response.headers,
  41. });
  42. } catch (e) {
  43. console.error('[transpileResponse]: Error transpiling!\n', e);
  44. if (typeof e === 'string') {
  45. return new Response('Internal Server Error', {
  46. status: 500,
  47. headers: response.headers,
  48. });
  49. }
  50. }
  51. }
  52. return response;
  53. }