experimental new frontend() style
This commit is contained in:
parent
7b9cade936
commit
b9b4e205c9
|
|
@ -1,11 +1,11 @@
|
||||||
import { frontend as fe } from 'hype'
|
import { fe } from 'hype'
|
||||||
|
|
||||||
fe(function test() {
|
const test = fe(() => {
|
||||||
alert('ding dong')
|
alert('ding dong')
|
||||||
})
|
})
|
||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<section>
|
<section>
|
||||||
<a href="#" onclick="test()">test</a>
|
<a href="#" onclick={test}>test</a>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|
@ -1,14 +1,48 @@
|
||||||
import { AsyncLocalStorage } from 'async_hooks'
|
import { AsyncLocalStorage } from 'async_hooks'
|
||||||
|
|
||||||
export const fnStorage = new AsyncLocalStorage<{ fns: string[] }>()
|
export const fnStorage = new AsyncLocalStorage<{
|
||||||
|
fns: Map<string, string>
|
||||||
|
counter: number
|
||||||
|
}>()
|
||||||
|
|
||||||
// Designate a function in a .tsx file as frontend
|
export function fe<T extends Record<string, unknown>>(
|
||||||
export function frontend(code: Function) {
|
fn: (args?: T) => void,
|
||||||
|
args?: T
|
||||||
|
): string {
|
||||||
const store = fnStorage.getStore()
|
const store = fnStorage.getStore()
|
||||||
store?.fns.push(code.toString())
|
if (!store) {
|
||||||
|
// Fallback to IIFE if outside request context
|
||||||
|
return args
|
||||||
|
? `(${fn.toString()})(${JSON.stringify(args)})`
|
||||||
|
: `(${fn.toString()})()`
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnStr = fn.toString()
|
||||||
|
|
||||||
|
// Dedupe by function body
|
||||||
|
for (const [name, body] of store.fns)
|
||||||
|
if (body === fnStr)
|
||||||
|
return args ? `${name}(${JSON.stringify(args)})` : `${name}()`
|
||||||
|
|
||||||
|
const name = `frontendFn${store.counter++}`
|
||||||
|
store.fns.set(name, fnStr)
|
||||||
|
|
||||||
|
return args ? `${name}(${JSON.stringify(args)})` : `${name}()`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function feFunctions(): string[] {
|
export function feFunctions(): string[] {
|
||||||
const store = fnStorage.getStore()
|
const store = fnStorage.getStore()
|
||||||
return store?.fns ?? []
|
if (!store?.fns.size) return []
|
||||||
|
|
||||||
|
return [...store.fns.entries()].map(([name, body]) => {
|
||||||
|
// Handle arrow functions vs regular functions
|
||||||
|
if (body.startsWith('(') || body.startsWith('async ('))
|
||||||
|
return `const ${name} = ${body};`
|
||||||
|
|
||||||
|
// Named function - rename it
|
||||||
|
return body.replace(/^(async\s+)?function\s*\w*/, `$1function ${name}`)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep for backwards compat
|
||||||
|
export const frontend = fe
|
||||||
|
|
@ -13,7 +13,7 @@ const CSS_RESET = await Bun.file(join(import.meta.dir, '/css/reset.css')).text()
|
||||||
const PICO_CSS = await Bun.file(join(import.meta.dir, '/css/pico.css')).text()
|
const PICO_CSS = await Bun.file(join(import.meta.dir, '/css/pico.css')).text()
|
||||||
|
|
||||||
export * from './utils'
|
export * from './utils'
|
||||||
export { frontend } from './frontend'
|
export { frontend, frontend as fe } from './frontend'
|
||||||
export type { Context } from 'hono'
|
export type { Context } from 'hono'
|
||||||
|
|
||||||
const pageCache = new Map()
|
const pageCache = new Map()
|
||||||
|
|
@ -94,7 +94,7 @@ export class Hype<
|
||||||
|
|
||||||
// serve frontend js
|
// serve frontend js
|
||||||
this.use('*', async (c, next) => {
|
this.use('*', async (c, next) => {
|
||||||
await fnStorage.run({ fns: [] }, async () => {
|
await fnStorage.run({ fns: new Map(), counter: 0 }, async () => {
|
||||||
await next()
|
await next()
|
||||||
|
|
||||||
const contentType = c.res.headers.get('content-type')
|
const contentType = c.res.headers.get('content-type')
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user