Skip to content

Instantly share code, notes, and snippets.

@yusukebe
Created November 3, 2023 08:06
Show Gist options
  • Save yusukebe/f135da089e34bcc8dc13e6f5ec3abcb4 to your computer and use it in GitHub Desktop.
Save yusukebe/f135da089e34bcc8dc13e6f5ec3abcb4 to your computer and use it in GitHub Desktop.
import { readFile } from 'node:fs/promises'
import initSwc, { transformSync } from '@swc/wasm-web/wasm-web'
import type { MiddlewareHandler } from 'hono'
import wasm from './wasm-web_bg.wasm'
// Cache that maps from code itself to transpiled code (since this is to be
// used in development only, no need to cap the cache size)
const cache = new Map<string, string>()
// See https://swc.rs/docs/usage/core
async function transpile(ts: string) {
//const res = await fetch('')
const resolvedUrl = (await import('./wasm-web_bg.wasm?url')).default
const buffer = await readFile('.' + resolvedUrl)
await initSwc(buffer)
const result = transformSync(ts, {
sourceMaps: false,
jsc: {
parser: { syntax: 'typescript', tsx: true },
transform: {
react: {},
},
},
})
return result.code
}
// Typescript middleware
const typescriptTranspiler = (): MiddlewareHandler => {
return async (c, next) => {
// Transpiling needs to go at the end
await next()
// If the pathname is like '*.ts' we will transpile
const url = new URL(c.req.url)
if (!url.pathname.endsWith('.ts') && !url.pathname.endsWith('.tsx')) return
// Transpile the code and return the right content type
// Code below is based on the pretty JSON middleware from Hono
// See https://github.com/honojs/hono/tree/main/src/middleware/pretty-json
const headers = { 'content-type': 'text/javascript; charset=utf-8' }
const ts = await c.res.text()
// If it is in the cache, use that, otherwise transpile and put in the cache
if (cache.has(ts)) {
c.res = new Response(cache.get(ts), { headers })
} else {
// Declare a random name for the specifier
try {
const js = await transpile(ts)
c.res = new Response(js, { headers })
} catch (ex) {
console.warn('Error transpiling ' + url.pathname + ': ' + ex)
// Send original response (with the right JS content type, things will break in the browser)
c.res = new Response(ts, { status: 500, headers })
}
}
}
}
export { typescriptTranspiler as transpiler }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment