import { AsyncLocalStorage } from 'async_hooks' export const fnStorage = new AsyncLocalStorage<{ fns: Map counter: number }>() export function fe>( fn: (args?: T) => void, args?: T ): string { const store = fnStorage.getStore() 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[] { const store = fnStorage.getStore() 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