threadsafe frontend()

This commit is contained in:
Chris Wanstrath 2025-12-12 12:06:41 -08:00
parent 80b25b1c88
commit 9b8653ed97
2 changed files with 19 additions and 18 deletions

View File

@ -1,14 +1,14 @@
let funcs: string[] = []
import { AsyncLocalStorage } from 'async_hooks'
export const fnStorage = new AsyncLocalStorage<{ fns: string[] }>()
// Designate a function in a .tsx file as frontend
export function frontend(code: Function) {
funcs.push(code.toString())
const store = fnStorage.getStore()
store?.fns.push(code.toString())
}
export function feFunctions(): string[] {
return funcs
const store = fnStorage.getStore()
return store?.fns ?? []
}
export function clearFeFunctions() {
funcs.length = 0
}

View File

@ -6,7 +6,7 @@ import color from 'kleur'
import { transpile } from './utils'
import defaultLayout from './layout'
import { feFunctions, clearFeFunctions } from './frontend'
import { feFunctions, fnStorage } from './frontend'
const SHOW_HTTP_LOG = true
const CSS_RESET = await Bun.file(join(import.meta.dir, '/reset.css')).text()
@ -90,20 +90,21 @@ export class Hype<
// serve frontend js
this.use('*', async (c, next) => {
await next()
await fnStorage.run({ fns: [] }, async () => {
await next()
const contentType = c.res.headers.get('content-type')
if (!contentType?.includes('text/html')) return
const contentType = c.res.headers.get('content-type')
if (!contentType?.includes('text/html')) return
const fns = feFunctions()
if (!fns.length) return
const fns = feFunctions()
if (!fns.length) return
const res = c.res.clone()
const html = await res.text()
const newHtml = html.replace('</body>', `<script>${fns.join('\n')}</script></body>`)
clearFeFunctions()
const res = c.res.clone()
const html = await res.text()
const newHtml = html.replace('</body>', `<script>${fns.join('\n')}</script></body>`)
c.res = new Response(newHtml, c.res)
c.res = new Response(newHtml, c.res)
})
})
// css reset