@withl5e/l5e 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entry-server.js +3 -3
- package/dist/{generateMetadata-Cn2uJjg_.js → generateMetadata-DmoLxT6v.js} +2 -2
- package/dist/{generateMetadata-Cn2uJjg_.js.map → generateMetadata-DmoLxT6v.js.map} +1 -1
- package/dist/index.js +2 -2
- package/dist/island.js +1 -1
- package/dist/{jsx-runtime-Bokflh8Q.js → jsx-runtime-5m2ZiNtU.js} +92 -82
- package/dist/jsx-runtime-5m2ZiNtU.js.map +1 -0
- package/dist/jsx-runtime.js +1 -1
- package/dist/{render-DTXfJu0d.js → render-BaTAJ4Ha.js} +2 -2
- package/dist/{render-DTXfJu0d.js.map → render-BaTAJ4Ha.js.map} +1 -1
- package/dist/seo.js +2 -2
- package/dist/server.js +33 -33
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/core/jsx-runtime.ts +23 -4
- package/src/core/server.ts +8 -1
- package/dist/jsx-runtime-Bokflh8Q.js.map +0 -1
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sources":["../src/core/bundler.ts","../src/core/server.ts"],"sourcesContent":["/// <reference path=\"./jsx-types.d.ts\" />\nimport { createHash } from 'node:crypto';\nimport fs from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { OutputOptions, Plugin, RollupOptions } from 'rollup';\n\nlet rollupModulePromise: Promise<typeof import('rollup')> | null = null;\n\n/**\n * Resolve rollup lazily. We can't `import 'rollup'` directly because when the\n * framework gets bundled into the consumer's SSR output the bare specifier is\n * hoisted to a static import that pnpm doesn't satisfy. Resolve through `vite`\n * instead — vite is a peer dep so it's always installed, and it always ships\n * rollup as a direct dependency.\n */\nfunction loadRollup(): Promise<typeof import('rollup')> {\n if (!rollupModulePromise) {\n rollupModulePromise = (async () => {\n const require = createRequire(import.meta.url);\n const vitePath = require.resolve('vite');\n const rollupPath = require.resolve('rollup', { paths: [path.dirname(vitePath)] });\n return (await import(pathToFileURL(rollupPath).href)) as typeof import('rollup');\n })();\n }\n return rollupModulePromise;\n}\n\ninterface BundledFile {\n content: string;\n hash: string;\n filename: string;\n mimeType: string;\n}\n\ninterface BundleResult {\n hash: string;\n filename: string;\n content: string;\n}\n\nconst EMPTY_RESULT: BundleResult = { hash: '', filename: '', content: '' };\n\n// Memory map để lưu bundled files\nconst bundledFilesMap = new Map<string, BundledFile>();\n\n/**\n * Single-flight map: cacheKey → promise của lần bundle đang chạy (hoặc đã xong).\n * Vì promise được giữ lại sau khi resolve, map này vừa là in-flight dedup vừa là\n * result cache. Bundle lỗi bị xoá khỏi map để request sau được thử lại.\n */\nconst bundlePromises = new Map<string, Promise<BundleResult>>();\n\n/**\n * Chạy `work` đúng một lần cho mỗi cacheKey, kể cả khi nhiều request đến đồng thời.\n */\nfunction dedupe(cacheKey: string, work: () => Promise<BundleResult>): Promise<BundleResult> {\n const pending = bundlePromises.get(cacheKey);\n if (pending) {\n return pending;\n }\n\n const promise = work().catch((error) => {\n bundlePromises.delete(cacheKey);\n throw error;\n });\n bundlePromises.set(cacheKey, promise);\n return promise;\n}\n\n/**\n * Generate hash từ content\n */\nfunction generateHash(content: string): string {\n return createHash('sha256').update(content).digest('hex').substring(0, 16);\n}\n\n// Rollup coi id bắt đầu bằng \\0 là virtual — nó sẽ không cố đọc từ đĩa.\nconst VIRTUAL_ENTRY_ID = '\\0l5e:bundle-entry';\n\n/**\n * Entry của mỗi lần bundle chỉ là một danh sách import. Giữ nó trong memory thay\n * vì ghi ra đĩa: hai request đồng thời cùng một tập script sinh ra cùng nội dung\n * entry, nên file tạm dùng chung path sẽ bị request này xoá trong lúc rollup của\n * request kia còn đang đọc.\n */\nfunction virtualEntryPlugin(entryContent: string): Plugin {\n return {\n name: 'l5e-virtual-entry',\n resolveId(source) {\n return source === VIRTUAL_ENTRY_ID ? VIRTUAL_ENTRY_ID : null;\n },\n load(id) {\n return id === VIRTUAL_ENTRY_ID ? entryContent : null;\n },\n };\n}\n\n/**\n * Rewrite vendor/chunk/global imports thành web path và để chúng external.\n * Global files (*.global.*) đã được client.global.ts load — bundle lại sẽ tạo\n * module instance trùng (vd nanostores).\n */\nfunction vendorPathRewriterPlugin(distClientDir: string): Plugin {\n const toWebPath = (absolutePath: string) =>\n '/' + path.relative(distClientDir, absolutePath).replace(/\\\\/g, '/');\n\n return {\n name: 'vendor-path-rewriter',\n resolveId(source, importer) {\n if (\n !source.includes('vendor-') &&\n !source.includes('chunk-') &&\n !source.includes('.global')\n ) {\n return null;\n }\n\n if (path.isAbsolute(source)) {\n // e.g. C:\\...\\dist\\client\\assets\\vendor-react-XXX.js -> /assets/vendor-react-XXX.js\n return { id: toWebPath(source), external: true };\n }\n\n if (importer && source.startsWith('.')) {\n // Relative path như ./auth.global-BOVr81Z5.js — resolve từ importer\n return { id: toWebPath(path.resolve(path.dirname(importer), source)), external: true };\n }\n\n return null;\n },\n };\n}\n\nasync function runScriptBundle(\n uniquePaths: string[],\n distClientDir: string,\n): Promise<BundleResult> {\n const entryContent = uniquePaths\n .map((p) => {\n const filePath = p.startsWith('/')\n ? path.join(distClientDir, p.substring(1))\n : path.join(distClientDir, p);\n return `import ${JSON.stringify(filePath)};`;\n })\n .join('\\n');\n\n const rollupOptions: RollupOptions = {\n input: VIRTUAL_ENTRY_ID,\n plugins: [virtualEntryPlugin(entryContent), vendorPathRewriterPlugin(distClientDir)],\n external: (id) => {\n // External node_modules\n if (!id.startsWith('.') && !path.isAbsolute(id) && id !== VIRTUAL_ENTRY_ID) {\n return true;\n }\n\n // Vendor/chunk/global do plugin resolveId lo phần rewrite path\n return false;\n },\n };\n\n const outputOptions: OutputOptions = {\n format: 'es',\n inlineDynamicImports: false,\n entryFileNames: 'bundle-[hash].js',\n chunkFileNames: 'bundle-[hash].js',\n };\n\n const { rollup } = await loadRollup();\n const bundle = await rollup(rollupOptions);\n let output;\n try {\n ({ output } = await bundle.generate(outputOptions));\n } finally {\n await bundle.close();\n }\n\n for (const chunk of output) {\n if (chunk.type !== 'chunk') {\n continue;\n }\n bundledFilesMap.set(chunk.fileName, {\n content: chunk.code || '',\n hash: generateHash(chunk.code || ''),\n filename: chunk.fileName,\n mimeType: 'application/javascript',\n });\n }\n\n const entryChunk = output[0];\n if (entryChunk?.type !== 'chunk') {\n throw new Error('[bundler] rollup produced no entry chunk');\n }\n\n return {\n hash: generateHash(entryChunk.code || ''),\n filename: entryChunk.fileName,\n content: entryChunk.code || '',\n };\n}\n\n/**\n * Bundle JavaScript files từ dist/client thành 1 file\n * Trong production, các file đã được build sẵn trong dist/client\n */\nexport async function bundleScripts(\n scriptPaths: string[],\n distClientDir: string,\n): Promise<BundleResult> {\n if (scriptPaths.length === 0) {\n return EMPTY_RESULT;\n }\n\n const uniquePaths = [...new Set(scriptPaths)].sort();\n const cacheKey = `scripts:${uniquePaths.join(',')}`;\n\n try {\n return await dedupe(cacheKey, () => runScriptBundle(uniquePaths, distClientDir));\n } catch (error) {\n console.error('[bundler] Error bundling scripts:', error);\n return EMPTY_RESULT;\n }\n}\n\nasync function runCssBundle(\n uniquePaths: string[],\n distClientDir: string,\n): Promise<BundleResult> {\n const cssContents: string[] = [];\n\n for (const cssPath of uniquePaths) {\n // cssPath có thể là \"/assets/xxx.css\" hoặc từ manifest\n const filePath = cssPath.startsWith('/')\n ? path.join(distClientDir, cssPath.substring(1))\n : path.join(distClientDir, cssPath);\n\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n cssContents.push(`/* ${cssPath} */\\n${content}\\n`);\n } catch (err) {\n console.warn(`[bundler] Failed to read CSS file: ${cssPath}`, err);\n }\n }\n\n const bundledContent = cssContents.join('\\n\\n');\n const hash = generateHash(bundledContent);\n const filename = `bundle-${hash}.css`;\n\n bundledFilesMap.set(filename, {\n content: bundledContent,\n hash,\n filename,\n mimeType: 'text/css',\n });\n\n return { hash, filename, content: bundledContent };\n}\n\n/**\n * Bundle CSS files từ dist/client thành 1 file\n * Trong production, các file đã được build sẵn trong dist/client\n */\nexport async function bundleCss(\n cssPaths: string[],\n distClientDir: string,\n): Promise<BundleResult> {\n if (cssPaths.length === 0) {\n return EMPTY_RESULT;\n }\n\n const uniquePaths = [...new Set(cssPaths)].sort();\n const cacheKey = `css:${uniquePaths.join(',')}`;\n\n try {\n return await dedupe(cacheKey, () => runCssBundle(uniquePaths, distClientDir));\n } catch (error) {\n console.error('[bundler] Error bundling CSS:', error);\n return EMPTY_RESULT;\n }\n}\n\n/**\n * Get bundled file từ map\n */\nexport function getBundledFile(filename: string): BundledFile | undefined {\n return bundledFilesMap.get(filename);\n}\n\n/**\n * Clear bundled files map (useful for testing)\n */\nexport function clearBundledFiles(): void {\n bundledFilesMap.clear();\n bundlePromises.clear();\n}\n","import type { Request as ExpressRequest, Response as ExpressResponse } from 'express';\nimport { existsSync } from 'fs';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport requestIp from 'request-ip';\nimport serialize from 'serialize-javascript';\nimport type { ViteDevServer } from 'vite';\nimport { createContext, type MiddlewareHandler, type RewritePayload } from '../middleware';\nimport { bundleCss, bundleScripts, getBundledFile } from './bundler';\nimport type { RenderResult, RequestInfo } from './entry-server';\nimport { escapeProp } from './render';\nimport { createHeadersFromExpressRequest, parseCookies } from './request';\n\nexport interface ServerOptions {\n root?: string;\n port?: number;\n base?: string;\n publicDir?: string;\n setupApp?: (app: any) => void | Promise<void>;\n app?: any; // Express\n}\n\nexport interface ServerContext {\n app: any; // Express app\n vite?: ViteDevServer;\n}\n\n/**\n * Apply or replace lang attribute on <html> tag\n */\nexport function applyHtmlLang(template: string, lang: string): string {\n // Escape so a loader-supplied lang (possibly derived from user input) cannot\n // break out of the attribute / <html> tag (XSS). escapeProp handles \", <, >, &.\n const safeLang = escapeProp(lang);\n return template.replace(/<html\\b([^>]*)>/i, (match, attrs) => {\n // Check if lang already exists\n if (/\\blang\\s*=/i.test(attrs)) {\n // Replace existing lang value (function replacer avoids $-pattern issues)\n return match.replace(/lang\\s*=\\s*\"[^\"]*\"/i, () => `lang=\"${safeLang}\"`);\n } else {\n // Add lang attribute\n return `<html lang=\"${safeLang}\"${attrs}>`;\n }\n });\n}\n\ntype EntryServerModule = {\n render: (url: string, requestInfo?: RequestInfo) => Promise<RenderResult>;\n loadMiddleware?: () => Promise<MiddlewareHandler | undefined>;\n};\n\nfunction getRequestUrl(req: ExpressRequest): URL {\n return new URL(`${req.protocol}://${req.get('host')}${req.originalUrl}`);\n}\n\nfunction getRenderUrl(urlObject: URL, base: string): string {\n const requestPath = `${urlObject.pathname}${urlObject.search}`;\n return requestPath.replace(base, '') || '/';\n}\n\nfunction createWebRequestFromExpress(req: ExpressRequest): globalThis.Request {\n const init: RequestInit & { duplex?: 'half' } = {\n method: req.method,\n headers: createHeadersFromExpressRequest(req),\n };\n\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n init.body = req as unknown as BodyInit;\n init.duplex = 'half';\n }\n\n return new globalThis.Request(getRequestUrl(req).href, init);\n}\n\nfunction createRequestInfo(\n req: ExpressRequest,\n webRequest: globalThis.Request,\n base: string,\n locals: Record<string, unknown>,\n): RequestInfo {\n const urlObject = new URL(webRequest.url);\n const renderUrl = getRenderUrl(urlObject, base);\n const normalizedPath = renderUrl.startsWith('/') ? renderUrl : `/${renderUrl}`;\n const headers: Record<string, string> = {};\n webRequest.headers.forEach((value, key) => {\n headers[key] = value;\n });\n\n return {\n url: urlObject,\n path: normalizedPath,\n pathname: urlObject.pathname,\n method: webRequest.method,\n headers,\n cookies: parseCookies(webRequest.headers.get('cookie') ?? undefined),\n query: Object.fromEntries(urlObject.searchParams.entries()),\n ip: requestIp.getClientIp(req) ?? undefined,\n locals,\n };\n}\n\nfunction createRewriteRequest(\n payload: RewritePayload | undefined,\n currentRequest: globalThis.Request,\n currentUrl: URL,\n): globalThis.Request {\n if (!payload) {\n return currentRequest;\n }\n\n if (payload instanceof globalThis.Request) {\n return payload;\n }\n\n if (payload instanceof URL) {\n return new globalThis.Request(payload.href, currentRequest.clone());\n }\n\n return new globalThis.Request(new URL(payload, currentUrl).href, currentRequest.clone());\n}\n\nasync function sendWebResponse(\n req: ExpressRequest,\n res: ExpressResponse,\n response: globalThis.Response,\n): Promise<void> {\n res.status(response.status);\n const setCookieValues = getSetCookieHeaders(response.headers);\n response.headers.forEach((value, key) => {\n if (key.toLowerCase() === 'set-cookie') {\n return;\n }\n res.setHeader(key, value);\n });\n if (setCookieValues.length > 0) {\n res.setHeader('Set-Cookie', setCookieValues);\n }\n\n if (req.method === 'HEAD') {\n res.end();\n return;\n }\n\n const body = Buffer.from(await response.arrayBuffer());\n res.send(body);\n}\n\nfunction getSetCookieHeaders(headers: Headers): string[] {\n const getSetCookie = (headers as Headers & { getSetCookie?: () => string[] }).getSetCookie;\n if (typeof getSetCookie === 'function') {\n return getSetCookie.call(headers);\n }\n\n const raw = (headers as Headers & { raw?: () => Record<string, string[]> }).raw?.();\n if (raw?.['set-cookie']) {\n return raw['set-cookie'];\n }\n\n const value = headers.get('set-cookie');\n return value ? splitSetCookieHeader(value) : [];\n}\n\nfunction splitSetCookieHeader(value: string): string[] {\n const cookies: string[] = [];\n let start = 0;\n\n for (let i = 0; i < value.length; i++) {\n if (value[i] !== ',') continue;\n\n const rest = value.slice(i + 1);\n if (/^\\s*[^=;,]+=/.test(rest)) {\n cookies.push(value.slice(start, i).trim());\n start = i + 1;\n }\n }\n\n cookies.push(value.slice(start).trim());\n return cookies.filter(Boolean);\n}\n\nfunction createRawResponse(rendered: RenderResult): globalThis.Response | null {\n if (!rendered.rawResponse) {\n return null;\n }\n\n const { body, contentType, statusCode, headers } = rendered.rawResponse;\n const responseHeaders = new Headers(headers);\n responseHeaders.set('Content-Type', contentType);\n\n return new globalThis.Response(body as BodyInit, {\n status: statusCode || 200,\n headers: responseHeaders,\n });\n}\n\nasync function createPageResponse({\n rendered,\n template,\n manifest,\n root,\n distClientDir,\n isProduction,\n}: {\n rendered: RenderResult;\n template: string;\n manifest?: Record<string, any>;\n root: string;\n distClientDir: string;\n isProduction: boolean;\n}): Promise<globalThis.Response> {\n const rawResponse = createRawResponse(rendered);\n if (rawResponse) {\n return rawResponse;\n }\n\n if (rendered.redirect) {\n return new globalThis.Response(null, {\n status: rendered.redirect.statusCode,\n headers: {\n Location: rendered.redirect.url,\n },\n });\n }\n\n let scriptSrcList: string[] = rendered.scripts || [];\n let cssSrcList: string[] = rendered.styles || [];\n const islandEntries = rendered.islands || [];\n let cacheTags: string[] = rendered.cacheTags || [];\n const maxAge: number | undefined = rendered.maxAge;\n const sMaxAge: number | undefined = rendered.sMaxAge;\n const swr: number | undefined = rendered.swr;\n\n let extraHead = '';\n let globalScripts: string[] = [];\n let islandRegistryScript = '';\n\n if (isProduction && manifest) {\n scriptSrcList = scriptSrcList.filter((src) => !src.includes('.global.'));\n cssSrcList = cssSrcList.filter((src) => !src.includes('.global.'));\n\n const cssFiles = new Set<string>();\n const preloadFiles = new Set<string>();\n\n function collectFromEntry(entryKey: string): { file: string | null } {\n const entry = manifest![entryKey];\n if (!entry) return { file: null };\n\n if (entry.css) entry.css.forEach((css: string) => cssFiles.add(css));\n if (entry.imports) {\n entry.imports.forEach((importKey: string) => {\n const importedChunk = manifest![importKey];\n if (importedChunk?.file) preloadFiles.add(importedChunk.file);\n if (importedChunk?.css) {\n importedChunk.css.forEach((css: string) => cssFiles.add(css));\n }\n if (importedChunk?.imports) {\n importedChunk.imports.forEach((key: string) => {\n const chunk = manifest![key];\n if (chunk?.file) preloadFiles.add(chunk.file);\n if (chunk?.css) chunk.css.forEach((css: string) => cssFiles.add(css));\n });\n }\n });\n }\n\n return { file: entry.file };\n }\n\n const mappedScripts: string[] = [];\n for (const src of scriptSrcList) {\n const entryKey = src.replace(/^\\//, '');\n const { file } = collectFromEntry(entryKey);\n if (file) mappedScripts.push(`/${file}`);\n }\n\n const mappedCssFiles: string[] = [];\n for (const src of cssSrcList) {\n const entryKey = src.replace(/^\\//, '');\n const { file } = collectFromEntry(entryKey);\n if (file) {\n mappedCssFiles.push(`/${file}`);\n cssFiles.add(file);\n }\n }\n\n if (mappedScripts.length > 0) {\n const bundledScript = await bundleScripts(mappedScripts, distClientDir);\n scriptSrcList = bundledScript.filename ? [`/${bundledScript.filename}`] : mappedScripts;\n }\n\n if (mappedCssFiles.length > 0) {\n const bundledCss = await bundleCss(mappedCssFiles, distClientDir);\n if (bundledCss.filename) {\n cssSrcList = [`/${bundledCss.filename}`];\n }\n }\n\n const globalEntry = manifest['src/client.global.ts'];\n if (globalEntry) {\n if (globalEntry.css && globalEntry.css.length > 0) {\n globalEntry.css.forEach((cssFile: string) => {\n extraHead += `<link rel=\"stylesheet\" crossorigin href=\"/${cssFile}\">`;\n });\n }\n if (globalEntry.file) {\n globalScripts.push(`/${globalEntry.file}`);\n }\n }\n\n if (islandEntries.length > 0) {\n const islandMap: Record<string, string> = {};\n for (const island of islandEntries) {\n const entry = manifest[island.src];\n if (entry?.file) {\n islandMap[island.key] = `/${entry.file}`;\n }\n }\n if (Object.keys(islandMap).length > 0) {\n islandRegistryScript = `<script>window.__L5E_ISLANDS__=${serialize(islandMap)}</script>`;\n }\n }\n\n if (cssSrcList.length > 0) {\n extraHead += cssSrcList\n .map((file) => `<link rel=\"stylesheet\" crossorigin href=\"${file}\">`)\n .join('');\n }\n }\n\n let cssHtml = '';\n if (!isProduction) {\n cssHtml = cssSrcList.map((src) => `<link rel=\"stylesheet\" href=\"${src}\">`).join('');\n }\n\n let allScripts = [...globalScripts, ...scriptSrcList];\n\n if (!isProduction) {\n const globalTsPath = path.join(root, 'src', 'client.global.ts');\n if (existsSync(globalTsPath)) {\n allScripts = ['/src/client.global.ts', ...allScripts];\n }\n\n if (islandEntries.length > 0) {\n const islandMap: Record<string, string> = {};\n for (const island of islandEntries) {\n islandMap[island.key] = `/${island.src}`;\n }\n islandRegistryScript = `<script>window.__L5E_ISLANDS__=${serialize(islandMap)}</script>`;\n }\n }\n\n const scriptsHtml =\n islandRegistryScript +\n allScripts.map((src) => `<script type=\"module\" src=\"${src}\"></script>`).join('');\n\n const templateWithLang = rendered.lang ? applyHtmlLang(template, rendered.lang) : template;\n\n // Replacer fns (not strings) so `$`-sequences in rendered HTML — e.g. an SSR\n // island body or user text containing \"$$\" / \"$&\" — aren't interpreted as\n // special String.replace replacement patterns.\n const html = rendered.rawHtml\n ? rendered.html || ''\n : templateWithLang\n .replace(`<!--app-head-->`, () => (rendered.head ?? '') + extraHead + cssHtml)\n .replace(`<!--app-html-->`, () => rendered.html ?? '')\n .replace(`<!--app-scripts-->`, () => scriptsHtml);\n\n const headers = new Headers({\n 'Content-Type': 'text/html',\n });\n\n const cacheControlParts: string[] = ['public'];\n if (maxAge !== undefined) cacheControlParts.push(`max-age=${maxAge}`);\n if (sMaxAge !== undefined) cacheControlParts.push(`s-maxage=${sMaxAge}`);\n if (swr !== undefined) cacheControlParts.push(`stale-while-revalidate=${swr}`);\n\n if (cacheControlParts.length > 1 && isProduction) {\n headers.set('Cache-Control', cacheControlParts.join(', '));\n }\n\n if (process.env.NODE_ENV === 'production') {\n cacheTags = optimizeCacheTags(cacheTags);\n }\n headers.set('Cache-Tag', ['global', ...cacheTags].join(','));\n\n return new globalThis.Response(html, {\n status: rendered.statusCode || 200,\n headers,\n });\n}\n\nexport async function createServer(options: ServerOptions = {}): Promise<ServerContext> {\n const root = options.root || process.cwd();\n const base = options.base || '/';\n const isProduction = process.env.NODE_ENV === 'production';\n\n // Cached production assets\n const templateHtml = isProduction\n ? await fs.readFile(path.join(root, './index.html'), 'utf-8')\n : '';\n\n // Create http server\n // @ts-ignore\n const express = (await import('express')).default;\n const app = options.app || express();\n\n // Serve static files from public directory\n if (options.publicDir) {\n const publicPath = path.isAbsolute(options.publicDir)\n ? options.publicDir\n : path.join(root, options.publicDir);\n\n if (existsSync(publicPath)) {\n app.use(express.static(publicPath));\n }\n }\n\n // Add Vite or respective production middlewares\n let vite: ViteDevServer | undefined;\n const distClientDir = path.join(root, './dist/client');\n\n if (!isProduction) {\n const { createServer } = await import('vite');\n const configFile = path.join(root, 'vite.config.js');\n vite = await createServer({\n root,\n configFile,\n server: { middlewareMode: true },\n appType: 'custom',\n base,\n optimizeDeps: {\n exclude: ['@withl5e/l5e', 'file-type'],\n },\n ssr: {\n resolve: {\n conditions: ['development', 'default'],\n },\n },\n resolve: {\n conditions: ['development', 'default'],\n },\n });\n app.use(vite.middlewares);\n } else {\n // @ts-ignore\n const compression = (await import('compression')).default;\n // @ts-ignore\n const sirv = (await import('sirv')).default;\n app.use(compression());\n app.use(base, sirv(distClientDir, { extensions: [] }));\n\n // Route để serve bundled files từ memory map\n // Äặt route nà y trước route HTML để catch request trước\n app.get(\n `${base === '/' ? '' : base}/bundle-:hash.:ext`,\n async (req: ExpressRequest, res: ExpressResponse) => {\n try {\n const { hash, ext } = req.params;\n const filename = `bundle-${hash}.${ext}`;\n const bundledFile = getBundledFile(filename);\n\n if (!bundledFile) {\n return res.status(404).send('Bundled file not found');\n }\n\n res.set({\n 'Content-Type': bundledFile.mimeType,\n 'Cache-Control': 'public, max-age=31536000, immutable',\n });\n res.send(bundledFile.content);\n } catch (e: any) {\n console.error('[server] Error serving bundled file:', e);\n res.status(500).end('Internal server error');\n }\n },\n );\n }\n\n // Action routes — JSON body parsing scoped to action endpoints only\n app.use('/_l5e/action', express.json({ limit: '100kb' }));\n\n // Validate action key format: actionName_hexHash\n const ACTION_KEY_RE = /^[a-zA-Z]\\w+_[0-9a-f]{1,4}$/;\n\n // Load action registry and viewActions glob from virtual module (dev) or built bundle (prod)\n let prodActionRegistry: Record<string, { modulePath: string; actionName: string }> | null = null;\n let prodViewActions: Record<string, () => Promise<any>> | null = null;\n\n async function getActionRegistry(): Promise<\n Record<string, { modulePath: string; actionName: string }>\n > {\n if (!isProduction) {\n const mod = await vite!.ssrLoadModule('virtual:l5e-actions');\n return mod.actionRegistry || {};\n }\n if (!prodActionRegistry) {\n const registryPath = path.join(root, './dist/server/action-registry.json');\n const json = await fs.readFile(registryPath, 'utf-8');\n prodActionRegistry = JSON.parse(json);\n }\n return prodActionRegistry!;\n }\n\n async function getViewActions(): Promise<Record<string, () => Promise<any>>> {\n if (!isProduction) {\n const mod = await vite!.ssrLoadModule('virtual:l5e-actions');\n return mod.viewActions || {};\n }\n if (!prodViewActions) {\n const entryServerPath = path.join(root, './dist/server/entry-server.js');\n const mod = await import(pathToFileURL(entryServerPath).href);\n prodViewActions = mod.viewActions || {};\n }\n return prodViewActions!;\n }\n\n // Action route handler — hashed action keys\n // URL: /_l5e/action/:actionKey (e.g., /_l5e/action/loadMoreComments_a1b2)\n app.all('/_l5e/action/:actionKey', async (req: ExpressRequest, res: ExpressResponse) => {\n try {\n const { actionKey } = req.params;\n\n // Validate action key format\n if (!ACTION_KEY_RE.test(actionKey)) {\n return res.status(400).send('Invalid action key');\n }\n\n // Look up action in registry\n const registry = await getActionRegistry();\n const entry = registry[actionKey];\n if (!entry) {\n return res.status(404).send('Action not found');\n }\n\n const { modulePath, actionName } = entry;\n\n // Import action module via viewActions glob (works in both dev and prod)\n let actionModule: any;\n if (!isProduction) {\n try {\n actionModule = await vite!.ssrLoadModule(`/src/${modulePath}/actions.tsx`);\n } catch {\n actionModule = await vite!.ssrLoadModule(`/src/${modulePath}/actions.ts`);\n }\n } else {\n const viewActions = await getViewActions();\n // Find matching glob entry by modulePath\n const globKey = viewActions[`/src/${modulePath}/actions.tsx`]\n ? `/src/${modulePath}/actions.tsx`\n : viewActions[`/src/${modulePath}/actions.ts`]\n ? `/src/${modulePath}/actions.ts`\n : null;\n if (!globKey) {\n return res.status(404).send('Action module not found');\n }\n actionModule = await viewActions[globKey]();\n }\n\n // Look up exported action — use hasOwnProperty to avoid prototype pollution\n if (!Object.prototype.hasOwnProperty.call(actionModule, actionName)) {\n return res.status(404).send('Action not found');\n }\n const action = actionModule[actionName];\n if (!action || !action.handler) {\n return res.status(404).send('Action not found');\n }\n\n // Enforce the action's declared HTTP method. Previously `app.all` accepted\n // any method and `action.method` was ignored, so a state-changing POST\n // action could be triggered via GET (e.g. <img src>) — a CSRF vector.\n const allowedMethod = (action.method || 'GET').toUpperCase();\n if (req.method.toUpperCase() !== allowedMethod) {\n return res.status(405).set('Allow', allowedMethod).send('Method Not Allowed');\n }\n\n // Run the request through the middleware chain first — same as the HTML\n // handler — so `locals` (locale, country, preview flags, ...) is\n // populated for actions too. Previously this endpoint built its own\n // bare `requestInfo` and never invoked middleware at all, so `locals`\n // (and thus `getLocale()`) was always empty inside an action handler.\n //\n // Crucially, the action must run *inside* the `next` callback passed to\n // the middleware — not after `await`ing the middleware call — because a\n // middleware like `fromFetchMiddleware(paraglideMiddleware)` calls\n // `next()` synchronously inside a library-owned `AsyncLocalStorage.run()`\n // scope. Running the action afterward, once that scope has already\n // closed, would silently lose the library's own ambient `getLocale()`.\n const entryServerPath = path.join(root, './dist/server/entry-server.js');\n const entryServerModule: EntryServerModule = isProduction\n ? await import(pathToFileURL(entryServerPath).href)\n : await vite!.ssrLoadModule('@withl5e/l5e/entry-server');\n const { runInRenderContext } = await (isProduction\n ? import(pathToFileURL(entryServerPath).href)\n : vite!.ssrLoadModule('@withl5e/l5e/jsx-runtime'));\n const { renderJsxToHtmlString } = await (isProduction\n ? import(pathToFileURL(entryServerPath).href)\n : vite!.ssrLoadModule('@withl5e/l5e'));\n\n const locals: Record<string, unknown> = {};\n const initialRequest = createWebRequestFromExpress(req);\n const middlewareContext = createContext({\n request: initialRequest,\n locals,\n clientAddress: requestIp.getClientIp(req) ?? undefined,\n });\n\n const loadedMiddleware = await entryServerModule.loadMiddleware?.();\n const middlewareHandler: MiddlewareHandler =\n typeof loadedMiddleware === 'function' ? loadedMiddleware : (_ctx, dummyNext) => dummyNext();\n\n // If middleware short-circuits (returns its own Response — a redirect, a\n // 403, ...) instead of calling `next`, this callback never runs and that\n // response wins, same as it would for a page request.\n const response = await middlewareHandler(middlewareContext, async (payload) => {\n const nextRequest = createRewriteRequest(payload, middlewareContext.request, middlewareContext.url);\n const requestInfo = {\n ...createRequestInfo(req, nextRequest, base, locals),\n path: req.originalUrl,\n body: req.body,\n };\n\n const html = await runInRenderContext(\n async () => {\n const jsx = await action.handler(requestInfo);\n return renderJsxToHtmlString(jsx);\n },\n requestInfo,\n modulePath,\n );\n\n return new Response(html, { headers: { 'Content-Type': 'text/html' } });\n });\n\n await sendWebResponse(req, res, response);\n } catch (e: any) {\n vite?.ssrFixStacktrace?.(e);\n console.error('[l5e] Action error:', e.stack || e);\n res.status(500).send('Internal server error');\n }\n });\n\n // Serve HTML\n app.use(async (req: ExpressRequest, res: ExpressResponse) => {\n try {\n const url = req.originalUrl.replace(base, '');\n\n let template: string;\n let render: (url: string, requestInfo?: any) => Promise<any>;\n let loadMiddleware: EntryServerModule['loadMiddleware'];\n let manifest: Record<string, any> | undefined;\n\n if (!isProduction) {\n // Always read fresh template in development\n template = await fs.readFile(path.join(root, './index.html'), 'utf-8');\n template = await vite!.transformIndexHtml(url, template);\n\n // Inject Vite HMR client for hot reload\n if (!template.includes('@vite/client')) {\n template = template.replace(\n '</head>',\n '<script type=\"module\" src=\"/@vite/client\"></script></head>',\n );\n }\n\n const entryServer = (await vite!.ssrLoadModule(\n '@withl5e/l5e/entry-server',\n )) as EntryServerModule;\n render = entryServer.render;\n loadMiddleware = entryServer.loadMiddleware;\n } else {\n template = templateHtml;\n const entryServerPath = path.join(root, './dist/server/entry-server.js');\n const entryServer = (await import(\n pathToFileURL(entryServerPath).href\n )) as EntryServerModule;\n render = entryServer.render;\n loadMiddleware = entryServer.loadMiddleware;\n // Read manifest to map hashed assets\n const manifestJson = await fs.readFile(\n path.join(root, './dist/client/.vite/manifest.json'),\n 'utf-8',\n );\n manifest = JSON.parse(manifestJson);\n }\n\n const loadedMiddleware = await loadMiddleware?.();\n const handler: MiddlewareHandler =\n typeof loadedMiddleware === 'function' ? loadedMiddleware : (_ctx, next) => next();\n\n const locals: Record<string, unknown> = {};\n const initialRequest = createWebRequestFromExpress(req);\n const context = createContext({\n request: initialRequest,\n requestInfo: createRequestInfo(req, initialRequest, base, locals),\n locals,\n clientAddress: requestIp.getClientIp(req),\n });\n\n const renderResponse = async (webRequest: globalThis.Request) => {\n const nextRequestInfo = createRequestInfo(req, webRequest, base, locals);\n const nextUrl = getRenderUrl(nextRequestInfo.url!, base);\n const nextRendered = await render(nextUrl, nextRequestInfo);\n return createPageResponse({\n rendered: nextRendered,\n template,\n manifest,\n root,\n distClientDir,\n isProduction,\n });\n };\n\n const next = async (payload?: RewritePayload) => {\n const nextRequest = createRewriteRequest(payload, context.request, context.url);\n context.request = nextRequest;\n context.url = new URL(nextRequest.url);\n context.cookies = parseCookies(nextRequest.headers.get('cookie') ?? undefined);\n context.requestInfo = createRequestInfo(req, nextRequest, base, locals);\n return renderResponse(nextRequest);\n };\n\n context.rewrite = (payload: RewritePayload) => next(payload);\n\n const response = await handler(context, next);\n await sendWebResponse(req, res, response);\n } catch (e: any) {\n vite?.ssrFixStacktrace?.(e);\n console.error(e.stack);\n // Never leak stack traces to the client in production (info disclosure).\n res.status(500).end(isProduction ? 'Internal Server Error' : e.stack);\n }\n });\n\n return { app, vite };\n}\n\nexport async function startServer(options: ServerOptions = {}): Promise<void> {\n const port = options.port || 5173;\n\n // Create Express app first\n // @ts-ignore\n const express = (await import('express')).default;\n const app = express();\n\n // Call callback if provided to allow custom routes before setting up L5E server\n if (options.setupApp) {\n console.log('setupApp');\n await options.setupApp(app);\n }\n\n const { app: serverApp } = await createServer({ ...options, app });\n\n serverApp.listen(port, () => {\n console.log(`Server started at http://localhost:${port}`);\n });\n}\n\nconst MAX_TAGS = 1000;\n\nexport function hashTag(tag: string): string {\n // global tag is not hashed, better for ci/cd\n if (tag === 'global') {\n return 'global';\n }\n\n let hash = 0;\n for (let i = 0; i < tag.length; i++) {\n const char = tag.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return Math.abs(hash).toString(36).substring(0, 8);\n}\n\nexport function optimizeCacheTags(tags: Set<string> | string[]): string[] {\n const _tags = Array.isArray(tags) ? tags : [...tags];\n const result = _tags.slice(0, MAX_TAGS).map(hashTag);\n return result;\n}\n"],"names":["rollupModulePromise","loadRollup","require","createRequire","vitePath","rollupPath","path","pathToFileURL","EMPTY_RESULT","bundledFilesMap","bundlePromises","dedupe","cacheKey","work","pending","promise","error","generateHash","content","createHash","VIRTUAL_ENTRY_ID","virtualEntryPlugin","entryContent","source","id","vendorPathRewriterPlugin","distClientDir","toWebPath","absolutePath","importer","runScriptBundle","uniquePaths","p","filePath","rollupOptions","outputOptions","rollup","bundle","output","chunk","entryChunk","bundleScripts","scriptPaths","runCssBundle","cssContents","cssPath","fs","err","bundledContent","hash","filename","bundleCss","cssPaths","getBundledFile","applyHtmlLang","template","lang","safeLang","escapeProp","match","attrs","getRequestUrl","req","getRenderUrl","urlObject","base","createWebRequestFromExpress","init","createHeadersFromExpressRequest","createRequestInfo","webRequest","locals","renderUrl","normalizedPath","headers","value","key","parseCookies","requestIp","createRewriteRequest","payload","currentRequest","currentUrl","sendWebResponse","res","response","setCookieValues","getSetCookieHeaders","body","getSetCookie","raw","splitSetCookieHeader","cookies","start","i","rest","createRawResponse","rendered","contentType","statusCode","responseHeaders","createPageResponse","manifest","root","isProduction","rawResponse","scriptSrcList","cssSrcList","islandEntries","cacheTags","maxAge","sMaxAge","swr","extraHead","globalScripts","islandRegistryScript","collectFromEntry","entryKey","entry","css","cssFiles","importKey","importedChunk","preloadFiles","src","mappedScripts","file","mappedCssFiles","bundledScript","bundledCss","globalEntry","cssFile","islandMap","island","serialize","cssHtml","allScripts","globalTsPath","existsSync","scriptsHtml","templateWithLang","html","cacheControlParts","optimizeCacheTags","createServer","options","templateHtml","express","app","publicPath","vite","compression","sirv","ext","bundledFile","e","configFile","ACTION_KEY_RE","prodActionRegistry","prodViewActions","getActionRegistry","registryPath","json","getViewActions","entryServerPath","actionKey","modulePath","actionName","actionModule","viewActions","globKey","action","allowedMethod","entryServerModule","runInRenderContext","renderJsxToHtmlString","initialRequest","middlewareContext","createContext","loadedMiddleware","_ctx","dummyNext","nextRequest","requestInfo","jsx","url","render","loadMiddleware","entryServer","manifestJson","handler","next","context","renderResponse","nextRequestInfo","nextUrl","nextRendered","startServer","port","serverApp","MAX_TAGS","hashTag","tag","char","tags"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.js","sources":["../src/core/bundler.ts","../src/core/server.ts"],"sourcesContent":["/// <reference path=\"./jsx-types.d.ts\" />\nimport { createHash } from 'node:crypto';\nimport fs from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { OutputOptions, Plugin, RollupOptions } from 'rollup';\n\nlet rollupModulePromise: Promise<typeof import('rollup')> | null = null;\n\n/**\n * Resolve rollup lazily. We can't `import 'rollup'` directly because when the\n * framework gets bundled into the consumer's SSR output the bare specifier is\n * hoisted to a static import that pnpm doesn't satisfy. Resolve through `vite`\n * instead — vite is a peer dep so it's always installed, and it always ships\n * rollup as a direct dependency.\n */\nfunction loadRollup(): Promise<typeof import('rollup')> {\n if (!rollupModulePromise) {\n rollupModulePromise = (async () => {\n const require = createRequire(import.meta.url);\n const vitePath = require.resolve('vite');\n const rollupPath = require.resolve('rollup', { paths: [path.dirname(vitePath)] });\n return (await import(pathToFileURL(rollupPath).href)) as typeof import('rollup');\n })();\n }\n return rollupModulePromise;\n}\n\ninterface BundledFile {\n content: string;\n hash: string;\n filename: string;\n mimeType: string;\n}\n\ninterface BundleResult {\n hash: string;\n filename: string;\n content: string;\n}\n\nconst EMPTY_RESULT: BundleResult = { hash: '', filename: '', content: '' };\n\n// Memory map để lưu bundled files\nconst bundledFilesMap = new Map<string, BundledFile>();\n\n/**\n * Single-flight map: cacheKey → promise của lần bundle đang chạy (hoặc đã xong).\n * Vì promise được giữ lại sau khi resolve, map này vừa là in-flight dedup vừa là\n * result cache. Bundle lỗi bị xoá khỏi map để request sau được thử lại.\n */\nconst bundlePromises = new Map<string, Promise<BundleResult>>();\n\n/**\n * Chạy `work` đúng một lần cho mỗi cacheKey, kể cả khi nhiều request đến đồng thời.\n */\nfunction dedupe(cacheKey: string, work: () => Promise<BundleResult>): Promise<BundleResult> {\n const pending = bundlePromises.get(cacheKey);\n if (pending) {\n return pending;\n }\n\n const promise = work().catch((error) => {\n bundlePromises.delete(cacheKey);\n throw error;\n });\n bundlePromises.set(cacheKey, promise);\n return promise;\n}\n\n/**\n * Generate hash từ content\n */\nfunction generateHash(content: string): string {\n return createHash('sha256').update(content).digest('hex').substring(0, 16);\n}\n\n// Rollup coi id bắt đầu bằng \\0 là virtual — nó sẽ không cố đọc từ đĩa.\nconst VIRTUAL_ENTRY_ID = '\\0l5e:bundle-entry';\n\n/**\n * Entry của mỗi lần bundle chỉ là một danh sách import. Giữ nó trong memory thay\n * vì ghi ra đĩa: hai request đồng thời cùng một tập script sinh ra cùng nội dung\n * entry, nên file tạm dùng chung path sẽ bị request này xoá trong lúc rollup của\n * request kia còn đang đọc.\n */\nfunction virtualEntryPlugin(entryContent: string): Plugin {\n return {\n name: 'l5e-virtual-entry',\n resolveId(source) {\n return source === VIRTUAL_ENTRY_ID ? VIRTUAL_ENTRY_ID : null;\n },\n load(id) {\n return id === VIRTUAL_ENTRY_ID ? entryContent : null;\n },\n };\n}\n\n/**\n * Rewrite vendor/chunk/global imports thành web path và để chúng external.\n * Global files (*.global.*) đã được client.global.ts load — bundle lại sẽ tạo\n * module instance trùng (vd nanostores).\n */\nfunction vendorPathRewriterPlugin(distClientDir: string): Plugin {\n const toWebPath = (absolutePath: string) =>\n '/' + path.relative(distClientDir, absolutePath).replace(/\\\\/g, '/');\n\n return {\n name: 'vendor-path-rewriter',\n resolveId(source, importer) {\n if (\n !source.includes('vendor-') &&\n !source.includes('chunk-') &&\n !source.includes('.global')\n ) {\n return null;\n }\n\n if (path.isAbsolute(source)) {\n // e.g. C:\\...\\dist\\client\\assets\\vendor-react-XXX.js -> /assets/vendor-react-XXX.js\n return { id: toWebPath(source), external: true };\n }\n\n if (importer && source.startsWith('.')) {\n // Relative path như ./auth.global-BOVr81Z5.js — resolve từ importer\n return { id: toWebPath(path.resolve(path.dirname(importer), source)), external: true };\n }\n\n return null;\n },\n };\n}\n\nasync function runScriptBundle(\n uniquePaths: string[],\n distClientDir: string,\n): Promise<BundleResult> {\n const entryContent = uniquePaths\n .map((p) => {\n const filePath = p.startsWith('/')\n ? path.join(distClientDir, p.substring(1))\n : path.join(distClientDir, p);\n return `import ${JSON.stringify(filePath)};`;\n })\n .join('\\n');\n\n const rollupOptions: RollupOptions = {\n input: VIRTUAL_ENTRY_ID,\n plugins: [virtualEntryPlugin(entryContent), vendorPathRewriterPlugin(distClientDir)],\n external: (id) => {\n // External node_modules\n if (!id.startsWith('.') && !path.isAbsolute(id) && id !== VIRTUAL_ENTRY_ID) {\n return true;\n }\n\n // Vendor/chunk/global do plugin resolveId lo phần rewrite path\n return false;\n },\n };\n\n const outputOptions: OutputOptions = {\n format: 'es',\n inlineDynamicImports: false,\n entryFileNames: 'bundle-[hash].js',\n chunkFileNames: 'bundle-[hash].js',\n };\n\n const { rollup } = await loadRollup();\n const bundle = await rollup(rollupOptions);\n let output;\n try {\n ({ output } = await bundle.generate(outputOptions));\n } finally {\n await bundle.close();\n }\n\n for (const chunk of output) {\n if (chunk.type !== 'chunk') {\n continue;\n }\n bundledFilesMap.set(chunk.fileName, {\n content: chunk.code || '',\n hash: generateHash(chunk.code || ''),\n filename: chunk.fileName,\n mimeType: 'application/javascript',\n });\n }\n\n const entryChunk = output[0];\n if (entryChunk?.type !== 'chunk') {\n throw new Error('[bundler] rollup produced no entry chunk');\n }\n\n return {\n hash: generateHash(entryChunk.code || ''),\n filename: entryChunk.fileName,\n content: entryChunk.code || '',\n };\n}\n\n/**\n * Bundle JavaScript files từ dist/client thành 1 file\n * Trong production, các file đã được build sẵn trong dist/client\n */\nexport async function bundleScripts(\n scriptPaths: string[],\n distClientDir: string,\n): Promise<BundleResult> {\n if (scriptPaths.length === 0) {\n return EMPTY_RESULT;\n }\n\n const uniquePaths = [...new Set(scriptPaths)].sort();\n const cacheKey = `scripts:${uniquePaths.join(',')}`;\n\n try {\n return await dedupe(cacheKey, () => runScriptBundle(uniquePaths, distClientDir));\n } catch (error) {\n console.error('[bundler] Error bundling scripts:', error);\n return EMPTY_RESULT;\n }\n}\n\nasync function runCssBundle(\n uniquePaths: string[],\n distClientDir: string,\n): Promise<BundleResult> {\n const cssContents: string[] = [];\n\n for (const cssPath of uniquePaths) {\n // cssPath có thể là \"/assets/xxx.css\" hoặc từ manifest\n const filePath = cssPath.startsWith('/')\n ? path.join(distClientDir, cssPath.substring(1))\n : path.join(distClientDir, cssPath);\n\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n cssContents.push(`/* ${cssPath} */\\n${content}\\n`);\n } catch (err) {\n console.warn(`[bundler] Failed to read CSS file: ${cssPath}`, err);\n }\n }\n\n const bundledContent = cssContents.join('\\n\\n');\n const hash = generateHash(bundledContent);\n const filename = `bundle-${hash}.css`;\n\n bundledFilesMap.set(filename, {\n content: bundledContent,\n hash,\n filename,\n mimeType: 'text/css',\n });\n\n return { hash, filename, content: bundledContent };\n}\n\n/**\n * Bundle CSS files từ dist/client thành 1 file\n * Trong production, các file đã được build sẵn trong dist/client\n */\nexport async function bundleCss(\n cssPaths: string[],\n distClientDir: string,\n): Promise<BundleResult> {\n if (cssPaths.length === 0) {\n return EMPTY_RESULT;\n }\n\n const uniquePaths = [...new Set(cssPaths)].sort();\n const cacheKey = `css:${uniquePaths.join(',')}`;\n\n try {\n return await dedupe(cacheKey, () => runCssBundle(uniquePaths, distClientDir));\n } catch (error) {\n console.error('[bundler] Error bundling CSS:', error);\n return EMPTY_RESULT;\n }\n}\n\n/**\n * Get bundled file từ map\n */\nexport function getBundledFile(filename: string): BundledFile | undefined {\n return bundledFilesMap.get(filename);\n}\n\n/**\n * Clear bundled files map (useful for testing)\n */\nexport function clearBundledFiles(): void {\n bundledFilesMap.clear();\n bundlePromises.clear();\n}\n","import type { Request as ExpressRequest, Response as ExpressResponse } from 'express';\nimport { existsSync } from 'fs';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport requestIp from 'request-ip';\nimport serialize from 'serialize-javascript';\nimport type { ViteDevServer } from 'vite';\nimport { createContext, type MiddlewareHandler, type RewritePayload } from '../middleware';\nimport { bundleCss, bundleScripts, getBundledFile } from './bundler';\nimport type { RenderResult, RequestInfo } from './entry-server';\nimport { escapeProp } from './render';\nimport { createHeadersFromExpressRequest, parseCookies } from './request';\n\nexport interface ServerOptions {\n root?: string;\n port?: number;\n base?: string;\n publicDir?: string;\n setupApp?: (app: any) => void | Promise<void>;\n app?: any; // Express\n}\n\nexport interface ServerContext {\n app: any; // Express app\n vite?: ViteDevServer;\n}\n\n/**\n * Apply or replace lang attribute on <html> tag\n */\nexport function applyHtmlLang(template: string, lang: string): string {\n // Escape so a loader-supplied lang (possibly derived from user input) cannot\n // break out of the attribute / <html> tag (XSS). escapeProp handles \", <, >, &.\n const safeLang = escapeProp(lang);\n return template.replace(/<html\\b([^>]*)>/i, (match, attrs) => {\n // Check if lang already exists\n if (/\\blang\\s*=/i.test(attrs)) {\n // Replace existing lang value (function replacer avoids $-pattern issues)\n return match.replace(/lang\\s*=\\s*\"[^\"]*\"/i, () => `lang=\"${safeLang}\"`);\n } else {\n // Add lang attribute\n return `<html lang=\"${safeLang}\"${attrs}>`;\n }\n });\n}\n\ntype EntryServerModule = {\n render: (url: string, requestInfo?: RequestInfo) => Promise<RenderResult>;\n loadMiddleware?: () => Promise<MiddlewareHandler | undefined>;\n};\n\nfunction getRequestUrl(req: ExpressRequest): URL {\n return new URL(`${req.protocol}://${req.get('host')}${req.originalUrl}`);\n}\n\nfunction getRenderUrl(urlObject: URL, base: string): string {\n const requestPath = `${urlObject.pathname}${urlObject.search}`;\n return requestPath.replace(base, '') || '/';\n}\n\nfunction createWebRequestFromExpress(req: ExpressRequest): globalThis.Request {\n const init: RequestInit & { duplex?: 'half' } = {\n method: req.method,\n headers: createHeadersFromExpressRequest(req),\n };\n\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n init.body = req as unknown as BodyInit;\n init.duplex = 'half';\n }\n\n return new globalThis.Request(getRequestUrl(req).href, init);\n}\n\nfunction createRequestInfo(\n req: ExpressRequest,\n webRequest: globalThis.Request,\n base: string,\n locals: Record<string, unknown>,\n): RequestInfo {\n const urlObject = new URL(webRequest.url);\n const renderUrl = getRenderUrl(urlObject, base);\n const normalizedPath = renderUrl.startsWith('/') ? renderUrl : `/${renderUrl}`;\n const headers: Record<string, string> = {};\n webRequest.headers.forEach((value, key) => {\n headers[key] = value;\n });\n\n return {\n url: urlObject,\n path: normalizedPath,\n pathname: urlObject.pathname,\n method: webRequest.method,\n headers,\n cookies: parseCookies(webRequest.headers.get('cookie') ?? undefined),\n query: Object.fromEntries(urlObject.searchParams.entries()),\n ip: requestIp.getClientIp(req) ?? undefined,\n locals,\n };\n}\n\nfunction createRewriteRequest(\n payload: RewritePayload | undefined,\n currentRequest: globalThis.Request,\n currentUrl: URL,\n): globalThis.Request {\n if (!payload) {\n return currentRequest;\n }\n\n if (payload instanceof globalThis.Request) {\n return payload;\n }\n\n if (payload instanceof URL) {\n return new globalThis.Request(payload.href, currentRequest.clone());\n }\n\n return new globalThis.Request(new URL(payload, currentUrl).href, currentRequest.clone());\n}\n\nasync function sendWebResponse(\n req: ExpressRequest,\n res: ExpressResponse,\n response: globalThis.Response,\n): Promise<void> {\n res.status(response.status);\n const setCookieValues = getSetCookieHeaders(response.headers);\n response.headers.forEach((value, key) => {\n if (key.toLowerCase() === 'set-cookie') {\n return;\n }\n res.setHeader(key, value);\n });\n if (setCookieValues.length > 0) {\n res.setHeader('Set-Cookie', setCookieValues);\n }\n\n if (req.method === 'HEAD') {\n res.end();\n return;\n }\n\n const body = Buffer.from(await response.arrayBuffer());\n res.send(body);\n}\n\nfunction getSetCookieHeaders(headers: Headers): string[] {\n const getSetCookie = (headers as Headers & { getSetCookie?: () => string[] }).getSetCookie;\n if (typeof getSetCookie === 'function') {\n return getSetCookie.call(headers);\n }\n\n const raw = (headers as Headers & { raw?: () => Record<string, string[]> }).raw?.();\n if (raw?.['set-cookie']) {\n return raw['set-cookie'];\n }\n\n const value = headers.get('set-cookie');\n return value ? splitSetCookieHeader(value) : [];\n}\n\nfunction splitSetCookieHeader(value: string): string[] {\n const cookies: string[] = [];\n let start = 0;\n\n for (let i = 0; i < value.length; i++) {\n if (value[i] !== ',') continue;\n\n const rest = value.slice(i + 1);\n if (/^\\s*[^=;,]+=/.test(rest)) {\n cookies.push(value.slice(start, i).trim());\n start = i + 1;\n }\n }\n\n cookies.push(value.slice(start).trim());\n return cookies.filter(Boolean);\n}\n\nfunction createRawResponse(rendered: RenderResult): globalThis.Response | null {\n if (!rendered.rawResponse) {\n return null;\n }\n\n const { body, contentType, statusCode, headers } = rendered.rawResponse;\n const responseHeaders = new Headers(headers);\n responseHeaders.set('Content-Type', contentType);\n\n return new globalThis.Response(body as BodyInit, {\n status: statusCode || 200,\n headers: responseHeaders,\n });\n}\n\nasync function createPageResponse({\n rendered,\n template,\n manifest,\n root,\n distClientDir,\n isProduction,\n}: {\n rendered: RenderResult;\n template: string;\n manifest?: Record<string, any>;\n root: string;\n distClientDir: string;\n isProduction: boolean;\n}): Promise<globalThis.Response> {\n const rawResponse = createRawResponse(rendered);\n if (rawResponse) {\n return rawResponse;\n }\n\n if (rendered.redirect) {\n return new globalThis.Response(null, {\n status: rendered.redirect.statusCode,\n headers: {\n Location: rendered.redirect.url,\n },\n });\n }\n\n let scriptSrcList: string[] = rendered.scripts || [];\n let cssSrcList: string[] = rendered.styles || [];\n const islandEntries = rendered.islands || [];\n let cacheTags: string[] = rendered.cacheTags || [];\n const maxAge: number | undefined = rendered.maxAge;\n const sMaxAge: number | undefined = rendered.sMaxAge;\n const swr: number | undefined = rendered.swr;\n\n let extraHead = '';\n let globalScripts: string[] = [];\n let islandRegistryScript = '';\n\n if (isProduction && manifest) {\n scriptSrcList = scriptSrcList.filter((src) => !src.includes('.global.'));\n cssSrcList = cssSrcList.filter((src) => !src.includes('.global.'));\n\n const cssFiles = new Set<string>();\n const preloadFiles = new Set<string>();\n\n function collectFromEntry(entryKey: string): { file: string | null } {\n const entry = manifest![entryKey];\n if (!entry) return { file: null };\n\n if (entry.css) entry.css.forEach((css: string) => cssFiles.add(css));\n if (entry.imports) {\n entry.imports.forEach((importKey: string) => {\n const importedChunk = manifest![importKey];\n if (importedChunk?.file) preloadFiles.add(importedChunk.file);\n if (importedChunk?.css) {\n importedChunk.css.forEach((css: string) => cssFiles.add(css));\n }\n if (importedChunk?.imports) {\n importedChunk.imports.forEach((key: string) => {\n const chunk = manifest![key];\n if (chunk?.file) preloadFiles.add(chunk.file);\n if (chunk?.css) chunk.css.forEach((css: string) => cssFiles.add(css));\n });\n }\n });\n }\n\n return { file: entry.file };\n }\n\n const mappedScripts: string[] = [];\n for (const src of scriptSrcList) {\n const entryKey = src.replace(/^\\//, '');\n const { file } = collectFromEntry(entryKey);\n if (file) mappedScripts.push(`/${file}`);\n }\n\n const mappedCssFiles: string[] = [];\n for (const src of cssSrcList) {\n const entryKey = src.replace(/^\\//, '');\n const { file } = collectFromEntry(entryKey);\n if (file) {\n mappedCssFiles.push(`/${file}`);\n cssFiles.add(file);\n }\n }\n\n if (mappedScripts.length > 0) {\n const bundledScript = await bundleScripts(mappedScripts, distClientDir);\n scriptSrcList = bundledScript.filename ? [`/${bundledScript.filename}`] : mappedScripts;\n }\n\n if (mappedCssFiles.length > 0) {\n const bundledCss = await bundleCss(mappedCssFiles, distClientDir);\n if (bundledCss.filename) {\n cssSrcList = [`/${bundledCss.filename}`];\n }\n }\n\n const globalEntry = manifest['src/client.global.ts'];\n if (globalEntry) {\n if (globalEntry.css && globalEntry.css.length > 0) {\n globalEntry.css.forEach((cssFile: string) => {\n extraHead += `<link rel=\"stylesheet\" crossorigin href=\"/${cssFile}\">`;\n });\n }\n if (globalEntry.file) {\n globalScripts.push(`/${globalEntry.file}`);\n }\n }\n\n if (islandEntries.length > 0) {\n const islandMap: Record<string, string> = {};\n for (const island of islandEntries) {\n const entry = manifest[island.src];\n if (entry?.file) {\n islandMap[island.key] = `/${entry.file}`;\n }\n }\n if (Object.keys(islandMap).length > 0) {\n islandRegistryScript = `<script>window.__L5E_ISLANDS__=${serialize(islandMap)}</script>`;\n }\n }\n\n if (cssSrcList.length > 0) {\n extraHead += cssSrcList\n .map((file) => `<link rel=\"stylesheet\" crossorigin href=\"${file}\">`)\n .join('');\n }\n }\n\n let cssHtml = '';\n if (!isProduction) {\n // Registry đã dedupe, nhưng vẫn lọc lại ở đây để dev không bao giờ ra thẻ trùng\n cssHtml = [...new Set(cssSrcList)]\n .map((src) => `<link rel=\"stylesheet\" href=\"${src}\">`)\n .join('');\n }\n\n let allScripts = [...globalScripts, ...scriptSrcList];\n\n if (!isProduction) {\n const globalTsPath = path.join(root, 'src', 'client.global.ts');\n if (existsSync(globalTsPath)) {\n allScripts = ['/src/client.global.ts', ...allScripts];\n }\n\n // useClientJs('/src/client.global.ts') do user tự gọi sẽ trùng với entry\n // được prepend ở trên — registry không bắt được ca này nên dedupe lại\n allScripts = [...new Set(allScripts)];\n\n if (islandEntries.length > 0) {\n const islandMap: Record<string, string> = {};\n for (const island of islandEntries) {\n islandMap[island.key] = `/${island.src}`;\n }\n islandRegistryScript = `<script>window.__L5E_ISLANDS__=${serialize(islandMap)}</script>`;\n }\n }\n\n const scriptsHtml =\n islandRegistryScript +\n allScripts.map((src) => `<script type=\"module\" src=\"${src}\"></script>`).join('');\n\n const templateWithLang = rendered.lang ? applyHtmlLang(template, rendered.lang) : template;\n\n // Replacer fns (not strings) so `$`-sequences in rendered HTML — e.g. an SSR\n // island body or user text containing \"$$\" / \"$&\" — aren't interpreted as\n // special String.replace replacement patterns.\n const html = rendered.rawHtml\n ? rendered.html || ''\n : templateWithLang\n .replace(`<!--app-head-->`, () => (rendered.head ?? '') + extraHead + cssHtml)\n .replace(`<!--app-html-->`, () => rendered.html ?? '')\n .replace(`<!--app-scripts-->`, () => scriptsHtml);\n\n const headers = new Headers({\n 'Content-Type': 'text/html',\n });\n\n const cacheControlParts: string[] = ['public'];\n if (maxAge !== undefined) cacheControlParts.push(`max-age=${maxAge}`);\n if (sMaxAge !== undefined) cacheControlParts.push(`s-maxage=${sMaxAge}`);\n if (swr !== undefined) cacheControlParts.push(`stale-while-revalidate=${swr}`);\n\n if (cacheControlParts.length > 1 && isProduction) {\n headers.set('Cache-Control', cacheControlParts.join(', '));\n }\n\n if (process.env.NODE_ENV === 'production') {\n cacheTags = optimizeCacheTags(cacheTags);\n }\n headers.set('Cache-Tag', ['global', ...cacheTags].join(','));\n\n return new globalThis.Response(html, {\n status: rendered.statusCode || 200,\n headers,\n });\n}\n\nexport async function createServer(options: ServerOptions = {}): Promise<ServerContext> {\n const root = options.root || process.cwd();\n const base = options.base || '/';\n const isProduction = process.env.NODE_ENV === 'production';\n\n // Cached production assets\n const templateHtml = isProduction\n ? await fs.readFile(path.join(root, './index.html'), 'utf-8')\n : '';\n\n // Create http server\n // @ts-ignore\n const express = (await import('express')).default;\n const app = options.app || express();\n\n // Serve static files from public directory\n if (options.publicDir) {\n const publicPath = path.isAbsolute(options.publicDir)\n ? options.publicDir\n : path.join(root, options.publicDir);\n\n if (existsSync(publicPath)) {\n app.use(express.static(publicPath));\n }\n }\n\n // Add Vite or respective production middlewares\n let vite: ViteDevServer | undefined;\n const distClientDir = path.join(root, './dist/client');\n\n if (!isProduction) {\n const { createServer } = await import('vite');\n const configFile = path.join(root, 'vite.config.js');\n vite = await createServer({\n root,\n configFile,\n server: { middlewareMode: true },\n appType: 'custom',\n base,\n optimizeDeps: {\n exclude: ['@withl5e/l5e', 'file-type'],\n },\n ssr: {\n resolve: {\n conditions: ['development', 'default'],\n },\n },\n resolve: {\n conditions: ['development', 'default'],\n },\n });\n app.use(vite.middlewares);\n } else {\n // @ts-ignore\n const compression = (await import('compression')).default;\n // @ts-ignore\n const sirv = (await import('sirv')).default;\n app.use(compression());\n app.use(base, sirv(distClientDir, { extensions: [] }));\n\n // Route để serve bundled files từ memory map\n // Äặt route nà y trước route HTML để catch request trước\n app.get(\n `${base === '/' ? '' : base}/bundle-:hash.:ext`,\n async (req: ExpressRequest, res: ExpressResponse) => {\n try {\n const { hash, ext } = req.params;\n const filename = `bundle-${hash}.${ext}`;\n const bundledFile = getBundledFile(filename);\n\n if (!bundledFile) {\n return res.status(404).send('Bundled file not found');\n }\n\n res.set({\n 'Content-Type': bundledFile.mimeType,\n 'Cache-Control': 'public, max-age=31536000, immutable',\n });\n res.send(bundledFile.content);\n } catch (e: any) {\n console.error('[server] Error serving bundled file:', e);\n res.status(500).end('Internal server error');\n }\n },\n );\n }\n\n // Action routes — JSON body parsing scoped to action endpoints only\n app.use('/_l5e/action', express.json({ limit: '100kb' }));\n\n // Validate action key format: actionName_hexHash\n const ACTION_KEY_RE = /^[a-zA-Z]\\w+_[0-9a-f]{1,4}$/;\n\n // Load action registry and viewActions glob from virtual module (dev) or built bundle (prod)\n let prodActionRegistry: Record<string, { modulePath: string; actionName: string }> | null = null;\n let prodViewActions: Record<string, () => Promise<any>> | null = null;\n\n async function getActionRegistry(): Promise<\n Record<string, { modulePath: string; actionName: string }>\n > {\n if (!isProduction) {\n const mod = await vite!.ssrLoadModule('virtual:l5e-actions');\n return mod.actionRegistry || {};\n }\n if (!prodActionRegistry) {\n const registryPath = path.join(root, './dist/server/action-registry.json');\n const json = await fs.readFile(registryPath, 'utf-8');\n prodActionRegistry = JSON.parse(json);\n }\n return prodActionRegistry!;\n }\n\n async function getViewActions(): Promise<Record<string, () => Promise<any>>> {\n if (!isProduction) {\n const mod = await vite!.ssrLoadModule('virtual:l5e-actions');\n return mod.viewActions || {};\n }\n if (!prodViewActions) {\n const entryServerPath = path.join(root, './dist/server/entry-server.js');\n const mod = await import(pathToFileURL(entryServerPath).href);\n prodViewActions = mod.viewActions || {};\n }\n return prodViewActions!;\n }\n\n // Action route handler — hashed action keys\n // URL: /_l5e/action/:actionKey (e.g., /_l5e/action/loadMoreComments_a1b2)\n app.all('/_l5e/action/:actionKey', async (req: ExpressRequest, res: ExpressResponse) => {\n try {\n const { actionKey } = req.params;\n\n // Validate action key format\n if (!ACTION_KEY_RE.test(actionKey)) {\n return res.status(400).send('Invalid action key');\n }\n\n // Look up action in registry\n const registry = await getActionRegistry();\n const entry = registry[actionKey];\n if (!entry) {\n return res.status(404).send('Action not found');\n }\n\n const { modulePath, actionName } = entry;\n\n // Import action module via viewActions glob (works in both dev and prod)\n let actionModule: any;\n if (!isProduction) {\n try {\n actionModule = await vite!.ssrLoadModule(`/src/${modulePath}/actions.tsx`);\n } catch {\n actionModule = await vite!.ssrLoadModule(`/src/${modulePath}/actions.ts`);\n }\n } else {\n const viewActions = await getViewActions();\n // Find matching glob entry by modulePath\n const globKey = viewActions[`/src/${modulePath}/actions.tsx`]\n ? `/src/${modulePath}/actions.tsx`\n : viewActions[`/src/${modulePath}/actions.ts`]\n ? `/src/${modulePath}/actions.ts`\n : null;\n if (!globKey) {\n return res.status(404).send('Action module not found');\n }\n actionModule = await viewActions[globKey]();\n }\n\n // Look up exported action — use hasOwnProperty to avoid prototype pollution\n if (!Object.prototype.hasOwnProperty.call(actionModule, actionName)) {\n return res.status(404).send('Action not found');\n }\n const action = actionModule[actionName];\n if (!action || !action.handler) {\n return res.status(404).send('Action not found');\n }\n\n // Enforce the action's declared HTTP method. Previously `app.all` accepted\n // any method and `action.method` was ignored, so a state-changing POST\n // action could be triggered via GET (e.g. <img src>) — a CSRF vector.\n const allowedMethod = (action.method || 'GET').toUpperCase();\n if (req.method.toUpperCase() !== allowedMethod) {\n return res.status(405).set('Allow', allowedMethod).send('Method Not Allowed');\n }\n\n // Run the request through the middleware chain first — same as the HTML\n // handler — so `locals` (locale, country, preview flags, ...) is\n // populated for actions too. Previously this endpoint built its own\n // bare `requestInfo` and never invoked middleware at all, so `locals`\n // (and thus `getLocale()`) was always empty inside an action handler.\n //\n // Crucially, the action must run *inside* the `next` callback passed to\n // the middleware — not after `await`ing the middleware call — because a\n // middleware like `fromFetchMiddleware(paraglideMiddleware)` calls\n // `next()` synchronously inside a library-owned `AsyncLocalStorage.run()`\n // scope. Running the action afterward, once that scope has already\n // closed, would silently lose the library's own ambient `getLocale()`.\n const entryServerPath = path.join(root, './dist/server/entry-server.js');\n const entryServerModule: EntryServerModule = isProduction\n ? await import(pathToFileURL(entryServerPath).href)\n : await vite!.ssrLoadModule('@withl5e/l5e/entry-server');\n const { runInRenderContext } = await (isProduction\n ? import(pathToFileURL(entryServerPath).href)\n : vite!.ssrLoadModule('@withl5e/l5e/jsx-runtime'));\n const { renderJsxToHtmlString } = await (isProduction\n ? import(pathToFileURL(entryServerPath).href)\n : vite!.ssrLoadModule('@withl5e/l5e'));\n\n const locals: Record<string, unknown> = {};\n const initialRequest = createWebRequestFromExpress(req);\n const middlewareContext = createContext({\n request: initialRequest,\n locals,\n clientAddress: requestIp.getClientIp(req) ?? undefined,\n });\n\n const loadedMiddleware = await entryServerModule.loadMiddleware?.();\n const middlewareHandler: MiddlewareHandler =\n typeof loadedMiddleware === 'function' ? loadedMiddleware : (_ctx, dummyNext) => dummyNext();\n\n // If middleware short-circuits (returns its own Response — a redirect, a\n // 403, ...) instead of calling `next`, this callback never runs and that\n // response wins, same as it would for a page request.\n const response = await middlewareHandler(middlewareContext, async (payload) => {\n const nextRequest = createRewriteRequest(payload, middlewareContext.request, middlewareContext.url);\n const requestInfo = {\n ...createRequestInfo(req, nextRequest, base, locals),\n path: req.originalUrl,\n body: req.body,\n };\n\n const html = await runInRenderContext(\n async () => {\n const jsx = await action.handler(requestInfo);\n return renderJsxToHtmlString(jsx);\n },\n requestInfo,\n modulePath,\n );\n\n return new Response(html, { headers: { 'Content-Type': 'text/html' } });\n });\n\n await sendWebResponse(req, res, response);\n } catch (e: any) {\n vite?.ssrFixStacktrace?.(e);\n console.error('[l5e] Action error:', e.stack || e);\n res.status(500).send('Internal server error');\n }\n });\n\n // Serve HTML\n app.use(async (req: ExpressRequest, res: ExpressResponse) => {\n try {\n const url = req.originalUrl.replace(base, '');\n\n let template: string;\n let render: (url: string, requestInfo?: any) => Promise<any>;\n let loadMiddleware: EntryServerModule['loadMiddleware'];\n let manifest: Record<string, any> | undefined;\n\n if (!isProduction) {\n // Always read fresh template in development\n template = await fs.readFile(path.join(root, './index.html'), 'utf-8');\n template = await vite!.transformIndexHtml(url, template);\n\n // Inject Vite HMR client for hot reload\n if (!template.includes('@vite/client')) {\n template = template.replace(\n '</head>',\n '<script type=\"module\" src=\"/@vite/client\"></script></head>',\n );\n }\n\n const entryServer = (await vite!.ssrLoadModule(\n '@withl5e/l5e/entry-server',\n )) as EntryServerModule;\n render = entryServer.render;\n loadMiddleware = entryServer.loadMiddleware;\n } else {\n template = templateHtml;\n const entryServerPath = path.join(root, './dist/server/entry-server.js');\n const entryServer = (await import(\n pathToFileURL(entryServerPath).href\n )) as EntryServerModule;\n render = entryServer.render;\n loadMiddleware = entryServer.loadMiddleware;\n // Read manifest to map hashed assets\n const manifestJson = await fs.readFile(\n path.join(root, './dist/client/.vite/manifest.json'),\n 'utf-8',\n );\n manifest = JSON.parse(manifestJson);\n }\n\n const loadedMiddleware = await loadMiddleware?.();\n const handler: MiddlewareHandler =\n typeof loadedMiddleware === 'function' ? loadedMiddleware : (_ctx, next) => next();\n\n const locals: Record<string, unknown> = {};\n const initialRequest = createWebRequestFromExpress(req);\n const context = createContext({\n request: initialRequest,\n requestInfo: createRequestInfo(req, initialRequest, base, locals),\n locals,\n clientAddress: requestIp.getClientIp(req),\n });\n\n const renderResponse = async (webRequest: globalThis.Request) => {\n const nextRequestInfo = createRequestInfo(req, webRequest, base, locals);\n const nextUrl = getRenderUrl(nextRequestInfo.url!, base);\n const nextRendered = await render(nextUrl, nextRequestInfo);\n return createPageResponse({\n rendered: nextRendered,\n template,\n manifest,\n root,\n distClientDir,\n isProduction,\n });\n };\n\n const next = async (payload?: RewritePayload) => {\n const nextRequest = createRewriteRequest(payload, context.request, context.url);\n context.request = nextRequest;\n context.url = new URL(nextRequest.url);\n context.cookies = parseCookies(nextRequest.headers.get('cookie') ?? undefined);\n context.requestInfo = createRequestInfo(req, nextRequest, base, locals);\n return renderResponse(nextRequest);\n };\n\n context.rewrite = (payload: RewritePayload) => next(payload);\n\n const response = await handler(context, next);\n await sendWebResponse(req, res, response);\n } catch (e: any) {\n vite?.ssrFixStacktrace?.(e);\n console.error(e.stack);\n // Never leak stack traces to the client in production (info disclosure).\n res.status(500).end(isProduction ? 'Internal Server Error' : e.stack);\n }\n });\n\n return { app, vite };\n}\n\nexport async function startServer(options: ServerOptions = {}): Promise<void> {\n const port = options.port || 5173;\n\n // Create Express app first\n // @ts-ignore\n const express = (await import('express')).default;\n const app = express();\n\n // Call callback if provided to allow custom routes before setting up L5E server\n if (options.setupApp) {\n console.log('setupApp');\n await options.setupApp(app);\n }\n\n const { app: serverApp } = await createServer({ ...options, app });\n\n serverApp.listen(port, () => {\n console.log(`Server started at http://localhost:${port}`);\n });\n}\n\nconst MAX_TAGS = 1000;\n\nexport function hashTag(tag: string): string {\n // global tag is not hashed, better for ci/cd\n if (tag === 'global') {\n return 'global';\n }\n\n let hash = 0;\n for (let i = 0; i < tag.length; i++) {\n const char = tag.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return Math.abs(hash).toString(36).substring(0, 8);\n}\n\nexport function optimizeCacheTags(tags: Set<string> | string[]): string[] {\n const _tags = Array.isArray(tags) ? tags : [...tags];\n const result = _tags.slice(0, MAX_TAGS).map(hashTag);\n return result;\n}\n"],"names":["rollupModulePromise","loadRollup","require","createRequire","vitePath","rollupPath","path","pathToFileURL","EMPTY_RESULT","bundledFilesMap","bundlePromises","dedupe","cacheKey","work","pending","promise","error","generateHash","content","createHash","VIRTUAL_ENTRY_ID","virtualEntryPlugin","entryContent","source","id","vendorPathRewriterPlugin","distClientDir","toWebPath","absolutePath","importer","runScriptBundle","uniquePaths","p","filePath","rollupOptions","outputOptions","rollup","bundle","output","chunk","entryChunk","bundleScripts","scriptPaths","runCssBundle","cssContents","cssPath","fs","err","bundledContent","hash","filename","bundleCss","cssPaths","getBundledFile","applyHtmlLang","template","lang","safeLang","escapeProp","match","attrs","getRequestUrl","req","getRenderUrl","urlObject","base","createWebRequestFromExpress","init","createHeadersFromExpressRequest","createRequestInfo","webRequest","locals","renderUrl","normalizedPath","headers","value","key","parseCookies","requestIp","createRewriteRequest","payload","currentRequest","currentUrl","sendWebResponse","res","response","setCookieValues","getSetCookieHeaders","body","getSetCookie","raw","splitSetCookieHeader","cookies","start","i","rest","createRawResponse","rendered","contentType","statusCode","responseHeaders","createPageResponse","manifest","root","isProduction","rawResponse","scriptSrcList","cssSrcList","islandEntries","cacheTags","maxAge","sMaxAge","swr","extraHead","globalScripts","islandRegistryScript","collectFromEntry","entryKey","entry","css","cssFiles","importKey","importedChunk","preloadFiles","src","mappedScripts","file","mappedCssFiles","bundledScript","bundledCss","globalEntry","cssFile","islandMap","island","serialize","cssHtml","allScripts","globalTsPath","existsSync","scriptsHtml","templateWithLang","html","cacheControlParts","optimizeCacheTags","createServer","options","templateHtml","express","app","publicPath","vite","compression","sirv","ext","bundledFile","e","configFile","ACTION_KEY_RE","prodActionRegistry","prodViewActions","getActionRegistry","registryPath","json","getViewActions","entryServerPath","actionKey","modulePath","actionName","actionModule","viewActions","globKey","action","allowedMethod","entryServerModule","runInRenderContext","renderJsxToHtmlString","initialRequest","middlewareContext","createContext","loadedMiddleware","_ctx","dummyNext","nextRequest","requestInfo","jsx","url","render","loadMiddleware","entryServer","manifestJson","handler","next","context","renderResponse","nextRequestInfo","nextUrl","nextRendered","startServer","port","serverApp","MAX_TAGS","hashTag","tag","char","tags"],"mappings":"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"}
|
package/package.json
CHANGED
package/src/core/jsx-runtime.ts
CHANGED
|
@@ -107,11 +107,26 @@ function createRequestContext(requestInfo: RequestInfo): RenderContext {
|
|
|
107
107
|
};
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Chuẩn hoá path asset về dạng web path có leading `/`.
|
|
112
|
+
* Dev sinh thẻ thẳng từ path này, còn prod strip leading `/` để tra manifest —
|
|
113
|
+
* không normalize thì `'src/a.css'` và `'/src/a.css'` là hai entry khác nhau ở
|
|
114
|
+
* dev nhưng lại trỏ cùng một manifest key ở prod.
|
|
115
|
+
*/
|
|
116
|
+
function normalizeAssetPath(path: string): string {
|
|
117
|
+
const normalized = path.trim().replace(/\\/g, '/');
|
|
118
|
+
return normalized.startsWith('/') ? normalized : `/${normalized}`;
|
|
119
|
+
}
|
|
120
|
+
|
|
110
121
|
export function useClientJs(path: string): string {
|
|
111
|
-
if (typeof path === 'string' && path.length > 0) {
|
|
122
|
+
if (typeof path === 'string' && path.trim().length > 0) {
|
|
112
123
|
const renderContext = renderStore.getStore();
|
|
113
124
|
if (renderContext) {
|
|
114
|
-
|
|
125
|
+
const normalized = normalizeAssetPath(path);
|
|
126
|
+
// Dedupe theo path, giữ thứ tự lần gọi đầu tiên
|
|
127
|
+
if (!renderContext.clientJsRegistry.some((entry) => entry.path === normalized)) {
|
|
128
|
+
renderContext.clientJsRegistry.push({ path: normalized, from: 'Unknown' });
|
|
129
|
+
}
|
|
115
130
|
}
|
|
116
131
|
}
|
|
117
132
|
return '';
|
|
@@ -153,10 +168,14 @@ export function getSsrIslands(): SsrIslandEntry[] {
|
|
|
153
168
|
}
|
|
154
169
|
|
|
155
170
|
export function useCss(path: string): string {
|
|
156
|
-
if (typeof path === 'string' && path.length > 0) {
|
|
171
|
+
if (typeof path === 'string' && path.trim().length > 0) {
|
|
157
172
|
const renderContext = renderStore.getStore();
|
|
158
173
|
if (renderContext) {
|
|
159
|
-
|
|
174
|
+
const normalized = normalizeAssetPath(path);
|
|
175
|
+
// Dedupe theo path — thứ tự lần gọi đầu tiên quyết định thứ tự cascade
|
|
176
|
+
if (!renderContext.cssRegistry.some((entry) => entry.path === normalized)) {
|
|
177
|
+
renderContext.cssRegistry.push({ path: normalized, from: 'Unknown' });
|
|
178
|
+
}
|
|
160
179
|
}
|
|
161
180
|
}
|
|
162
181
|
return '';
|
package/src/core/server.ts
CHANGED
|
@@ -330,7 +330,10 @@ async function createPageResponse({
|
|
|
330
330
|
|
|
331
331
|
let cssHtml = '';
|
|
332
332
|
if (!isProduction) {
|
|
333
|
-
|
|
333
|
+
// Registry đã dedupe, nhưng vẫn lọc lại ở đây để dev không bao giờ ra thẻ trùng
|
|
334
|
+
cssHtml = [...new Set(cssSrcList)]
|
|
335
|
+
.map((src) => `<link rel="stylesheet" href="${src}">`)
|
|
336
|
+
.join('');
|
|
334
337
|
}
|
|
335
338
|
|
|
336
339
|
let allScripts = [...globalScripts, ...scriptSrcList];
|
|
@@ -341,6 +344,10 @@ async function createPageResponse({
|
|
|
341
344
|
allScripts = ['/src/client.global.ts', ...allScripts];
|
|
342
345
|
}
|
|
343
346
|
|
|
347
|
+
// useClientJs('/src/client.global.ts') do user tự gọi sẽ trùng với entry
|
|
348
|
+
// được prepend ở trên — registry không bắt được ca này nên dedupe lại
|
|
349
|
+
allScripts = [...new Set(allScripts)];
|
|
350
|
+
|
|
344
351
|
if (islandEntries.length > 0) {
|
|
345
352
|
const islandMap: Record<string, string> = {};
|
|
346
353
|
for (const island of islandEntries) {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jsx-runtime-Bokflh8Q.js","sources":["../src/core/head-priority.ts","../src/seo/mergeMetadata.ts","../src/core/const.ts","../src/core/jsx-runtime.ts"],"sourcesContent":["/**\n * Priority constants for Head component rendering order\n * Lower numbers render first (higher priority)\n */\nexport const HEAD_PRIORITY = {\n CRITICAL: 0, // charset, viewport - must be first\n HIGH: 10, // title, description, canonical\n MEDIUM: 50, // meta tags, robots\n SEO: 80, // OpenGraph, Twitter\n LOW: 100, // Custom head elements\n SCRIPTS: 200, // Scripts\n STYLES: 300, // Styles\n} as const;\n\nexport type HeadPriority = (typeof HEAD_PRIORITY)[keyof typeof HEAD_PRIORITY] | number;\n","import type { Metadata } from './types';\n\n/**\n * Merges parent and child metadata objects\n * Follows Next.js shallow merge pattern with deep merge for nested objects\n *\n * @param parent - Parent metadata (from layout/global loader)\n * @param child - Child metadata (from page/view loader)\n * @returns Merged metadata object\n */\nexport function mergeMetadata(\n parent: Metadata | null | undefined,\n child: Metadata | null | undefined,\n): Metadata {\n // If no parent, return child (or empty object)\n if (!parent) {\n return child || {};\n }\n\n // If no child, return parent\n if (!child) {\n return parent;\n }\n\n // Shallow merge base properties (child overrides parent)\n const merged: Metadata = {\n ...parent,\n ...child,\n };\n\n // Deep merge for nested objects\n // OpenGraph: merge nested properties\n if (child.openGraph || parent.openGraph) {\n if (child.openGraph && parent.openGraph) {\n merged.openGraph = {\n ...parent.openGraph,\n ...child.openGraph,\n // Deep merge for nested arrays/objects in openGraph\n images: child.openGraph.images ?? parent.openGraph.images,\n videos: child.openGraph.videos ?? parent.openGraph.videos,\n audio: child.openGraph.audio ?? parent.openGraph.audio,\n alternateLocale: child.openGraph.alternateLocale ?? parent.openGraph.alternateLocale,\n authors: child.openGraph.authors ?? parent.openGraph.authors,\n tags: child.openGraph.tags ?? parent.openGraph.tags,\n };\n } else {\n merged.openGraph = child.openGraph || parent.openGraph;\n }\n }\n\n // Twitter: merge nested properties\n if (child.twitter || parent.twitter) {\n if (child.twitter && parent.twitter) {\n merged.twitter = {\n ...parent.twitter,\n ...child.twitter,\n // Deep merge for nested objects\n images: child.twitter.images ?? parent.twitter.images,\n app: child.twitter.app\n ? {\n ...parent.twitter.app,\n ...child.twitter.app,\n id: {\n ...parent.twitter.app?.id,\n ...child.twitter.app.id,\n },\n url: {\n ...parent.twitter.app?.url,\n ...child.twitter.app.url,\n },\n }\n : parent.twitter.app,\n };\n } else {\n merged.twitter = child.twitter || parent.twitter;\n }\n }\n\n // Icons: merge nested properties\n if (child.icons || parent.icons) {\n if (child.icons && parent.icons) {\n merged.icons = {\n icon: child.icons.icon ?? parent.icons.icon,\n shortcut: child.icons.shortcut ?? parent.icons.shortcut,\n apple: child.icons.apple ?? parent.icons.apple,\n other: child.icons.other ?? parent.icons.other,\n };\n } else {\n merged.icons = child.icons || parent.icons;\n }\n }\n\n // Verification: merge nested properties\n if (child.verification || parent.verification) {\n if (child.verification && parent.verification) {\n merged.verification = {\n ...parent.verification,\n ...child.verification,\n // Deep merge for other verification tags\n other: child.verification.other\n ? {\n ...parent.verification.other,\n ...child.verification.other,\n }\n : parent.verification.other,\n me: child.verification.me ?? parent.verification.me,\n };\n } else {\n merged.verification = child.verification || parent.verification;\n }\n }\n\n // AppLinks: merge nested properties\n if (child.appLinks || parent.appLinks) {\n if (child.appLinks && parent.appLinks) {\n merged.appLinks = {\n ios: child.appLinks.ios\n ? {\n ...parent.appLinks.ios,\n ...child.appLinks.ios,\n }\n : parent.appLinks.ios,\n android: child.appLinks.android\n ? {\n ...parent.appLinks.android,\n ...child.appLinks.android,\n }\n : parent.appLinks.android,\n web: child.appLinks.web\n ? {\n ...parent.appLinks.web,\n ...child.appLinks.web,\n }\n : parent.appLinks.web,\n };\n } else {\n merged.appLinks = child.appLinks || parent.appLinks;\n }\n }\n\n // FormatDetection: merge nested properties\n if (child.formatDetection || parent.formatDetection) {\n if (child.formatDetection && parent.formatDetection) {\n merged.formatDetection = {\n ...parent.formatDetection,\n ...child.formatDetection,\n };\n } else {\n merged.formatDetection = child.formatDetection || parent.formatDetection;\n }\n }\n\n // Viewport: merge if both are objects\n if (child.viewport && parent.viewport) {\n if (typeof child.viewport === 'object' && typeof parent.viewport === 'object') {\n merged.viewport = {\n ...parent.viewport,\n ...child.viewport,\n } as Metadata['viewport'];\n } else {\n // If either is string, child overrides\n merged.viewport = child.viewport;\n }\n }\n\n // Robots: merge if both are objects\n if (child.robots && parent.robots) {\n if (typeof child.robots === 'object' && typeof parent.robots === 'object') {\n merged.robots = {\n ...parent.robots,\n ...child.robots,\n } as Metadata['robots'];\n } else {\n // If either is string, child overrides\n merged.robots = child.robots;\n }\n }\n\n // Array fields: child overrides parent (shallow merge behavior)\n // These are already handled by spread operator above\n // But we explicitly handle them for clarity:\n merged.keywords = child.keywords ?? parent.keywords;\n merged.themeColor = child.themeColor ?? parent.themeColor;\n merged.archives = child.archives ?? parent.archives;\n merged.assets = child.assets ?? parent.assets;\n\n // Other: merge objects\n if (child.other || parent.other) {\n if (child.other && parent.other) {\n merged.other = {\n ...parent.other,\n ...child.other,\n };\n } else {\n merged.other = child.other || parent.other;\n }\n }\n\n return merged;\n}\n","// Marker object để đánh dấu raw HTML không escape\nexport const RAW_HTML_MARKER = Symbol('rawHtml');\n","import { mergeMetadata } from '../seo/mergeMetadata';\nimport type { Metadata } from '../seo/types';\nimport { RAW_HTML_MARKER } from './const';\nimport { RequestInfo } from './entry-server';\nimport { HEAD_PRIORITY, type HeadPriority } from './head-priority';\n\nexport type JSXChild =\n | string\n | number\n | boolean\n | null\n | undefined\n | JSXNode\n | JSXChild[]\n | RawHtmlObject\n | HtmlContentObject;\n\nexport type RawHtmlObject = {\n [RAW_HTML_MARKER]: true;\n content: string;\n};\n\nexport type HtmlContentObject = {\n htmlContent: string;\n};\n\nexport type RenderedNode = {\n string: string;\n};\n\nexport type JSXNode = {\n type: string | ((props: any) => JSXChild);\n props: Record<string, any>;\n children: JSXChild[];\n};\n\nexport function jsxFactory(type: any, props: any, ...children: any): JSXNode {\n return { type, props: props || {}, children: children.flat() };\n}\n\nexport function Fragment({\n children,\n ...props\n}: { children?: JSXChild; setHtml?: unknown } & Record<string, any>): JSXChild {\n // Hỗ trợ setHtml cho Fragment\n if (props.setHtml !== undefined) {\n // Trả về object đặc biệt để không bị escape\n return { [RAW_HTML_MARKER]: true, content: props.setHtml?.toString() || '' };\n }\n return children;\n}\n\n// AsyncLocalStorage for render context (request-level)\nimport { AsyncLocalStorage } from 'async_hooks';\n\ninterface HeadEntry {\n content: JSXChild;\n priority: number; // Số càng nhỏ, render càng sớm\n source?: string; // Để debug (ví dụ: 'layout', 'page', 'seo')\n}\n\ninterface IslandEntry {\n key: string; // \"Counter_a3f2\" — registry key\n src: string; // \"src/views/.../Counter.tsx\" — manifest-compatible path\n name: string; // \"Counter\" — export name\n}\n\n/**\n * A pending server-side render request for an `ssr` island.\n * Collected during the synchronous render pass and filled in afterwards by\n * entry-server (which can `await import()` the component + call renderToString).\n */\ninterface SsrIslandEntry {\n token: string; // unique placeholder token embedded in the HTML body\n src: string; // \"src/views/.../Counter.tsx\" — manifest-compatible path (no leading slash)\n name: string; // \"Counter\" — export name\n props: Record<string, any>;\n}\n\ninterface RenderContext {\n clientJsRegistry: Array<{ path: string; from: string }>;\n cssRegistry: Array<{ path: string; from: string }>;\n islandRegistry: IslandEntry[];\n ssrIslands: SsrIslandEntry[];\n cacheTags: Set<string>;\n headRegistry: HeadEntry[]; // Thay vì JSXChild[]\n metadataStack: Metadata[]; // Stack để track metadata hierarchy\n schemaRegistry: Array<Record<string, any>>; // Schema.org structured data từ loaders\n request: RequestInfo;\n viewName?: string; // View name from route handler\n}\n\nconst renderStore = new AsyncLocalStorage<RenderContext>();\n\n// Create context for each request\nfunction createRequestContext(requestInfo: RequestInfo): RenderContext {\n return {\n clientJsRegistry: [],\n cssRegistry: [],\n islandRegistry: [],\n ssrIslands: [],\n cacheTags: new Set(),\n headRegistry: [],\n metadataStack: [],\n schemaRegistry: [],\n request: requestInfo,\n };\n}\n\nexport function useClientJs(path: string): string {\n if (typeof path === 'string' && path.length > 0) {\n const renderContext = renderStore.getStore();\n if (renderContext) {\n renderContext.clientJsRegistry.push({ path, from: 'Unknown' });\n }\n }\n return '';\n}\n\nexport function registerIsland(key: string, src: string, name: string): void {\n const renderContext = renderStore.getStore();\n if (renderContext) {\n // Dedupe by key\n if (!renderContext.islandRegistry.some((e) => e.key === key)) {\n renderContext.islandRegistry.push({ key, src, name });\n }\n }\n}\n\nexport function getIslandEntries(): IslandEntry[] {\n const context = renderStore.getStore();\n if (!context) return [];\n return context.islandRegistry.slice();\n}\n\n/**\n * Register a pending SSR island render. Returns a unique placeholder token that\n * the caller embeds (as raw HTML) in the island's body. entry-server replaces\n * the token with the server-rendered component HTML after the sync render pass.\n */\nexport function registerSsrIsland(src: string, name: string, props: Record<string, any>): string {\n const renderContext = renderStore.getStore();\n if (!renderContext) return '';\n const token = `__L5E_SSR_${renderContext.ssrIslands.length}__`;\n renderContext.ssrIslands.push({ token, src, name, props });\n return token;\n}\n\nexport function getSsrIslands(): SsrIslandEntry[] {\n const context = renderStore.getStore();\n if (!context) return [];\n return context.ssrIslands.slice();\n}\n\nexport function useCss(path: string): string {\n if (typeof path === 'string' && path.length > 0) {\n const renderContext = renderStore.getStore();\n if (renderContext) {\n renderContext.cssRegistry.push({ path, from: 'Unknown' });\n }\n }\n return '';\n}\n\n// Wrapper to run render in async context\nexport function runInRenderContext<T>(\n renderFn: () => T | Promise<T>,\n requestInfo: RequestInfo,\n viewName?: string,\n): Promise<T> {\n const context = createRequestContext(requestInfo);\n if (viewName) {\n context.viewName = viewName;\n }\n return renderStore.run(context, () => Promise.resolve(renderFn()));\n}\n\n// Set view name in current render context\nexport function setViewName(viewName: string): void {\n const context = renderStore.getStore();\n if (context) {\n context.viewName = viewName;\n }\n}\n\n// Get entries from current context\nexport function getClientJsEntries(): Array<{ path: string; from: string }> {\n const context = renderStore.getStore();\n if (!context) return [];\n return context.clientJsRegistry.slice();\n}\n\n// Get cache tags from current context\nexport function getCacheTags(): string[] {\n const context = renderStore.getStore();\n if (!context) return [];\n return Array.from(context.cacheTags);\n}\n\n// Add cache tags to current context\nexport function addCacheTag(tag: string | string[] | Record<string, boolean>): void {\n const context = renderStore.getStore();\n if (!context) return;\n\n if (Array.isArray(tag)) {\n tag.forEach((t) => {\n if (typeof t === 'string' && t.trim()) {\n context.cacheTags.add(t.trim());\n }\n });\n } else if (typeof tag === 'string' && tag.trim()) {\n context.cacheTags.add(tag.trim());\n } else if (typeof tag === 'object' && tag !== null) {\n Object.entries(tag).forEach(([key, value]) => {\n if (value && typeof key === 'string' && key.trim()) {\n context.cacheTags.add(key.trim());\n }\n });\n }\n}\n\n// Get CSS entries from current context\nexport function getCssEntries(): Array<{ path: string; from: string }> {\n const context = renderStore.getStore();\n if (!context) return [];\n return context.cssRegistry.slice();\n}\n\n// Head component to collect head elements with priority support\nexport function Head({\n children,\n priority = HEAD_PRIORITY.LOW, // Default priority\n}: {\n children?: JSXChild;\n priority?: HeadPriority;\n}): null {\n const renderContext = renderStore.getStore();\n if (renderContext && children) {\n renderContext.headRegistry.push({\n content: children,\n priority: typeof priority === 'number' ? priority : HEAD_PRIORITY.LOW,\n source: 'manual',\n });\n\n // Sort theo priority sau mỗi lần push để đảm bảo thứ tự đúng\n renderContext.headRegistry.sort((a, b) => a.priority - b.priority);\n }\n return null;\n}\n\n// Get head content from current context (already sorted by priority)\nexport function getHeadContent(): JSXChild[] {\n const context = renderStore.getStore();\n if (!context) return [];\n // Đã được sort trong Head component, chỉ cần map để lấy content\n return context.headRegistry.map((entry) => entry.content);\n}\n\n// Push metadata to stack (for hierarchical metadata support)\nexport function pushMetadata(metadata: Metadata): void {\n const context = renderStore.getStore();\n if (context && metadata) {\n context.metadataStack.push(metadata);\n }\n}\n\n// Resolve and merge all metadata from stack (root → leaf)\nexport function resolveMetadata(): Metadata | null {\n const context = renderStore.getStore();\n if (!context || context.metadataStack.length === 0) {\n return null;\n }\n\n // Merge from root → leaf (reduce left to right)\n return context.metadataStack.reduce(\n (acc, current) => mergeMetadata(acc, current),\n null as Metadata | null,\n );\n}\n\n// Push schema to registry (for schema markup from loaders)\n// Accepts schema-dts types (WithContext<T> or array of schemas)\nexport function pushSchema(schema: any | Array<any>): void {\n const context = renderStore.getStore();\n if (!context) return;\n\n if (Array.isArray(schema)) {\n context.schemaRegistry.push(...schema);\n } else {\n context.schemaRegistry.push(schema);\n }\n}\n\n// Get all schemas from registry\nexport function getSchemas(): Array<Record<string, any>> {\n const context = renderStore.getStore();\n if (!context) return [];\n return context.schemaRegistry.slice();\n}\n\n// Hook to get render request context\nexport function useRequest() {\n const context = renderStore.getStore();\n\n if (!context) {\n throw new Error('useRequest called outside of render context');\n }\n\n return {\n request: context.request,\n view: context.viewName,\n locals: (context.request.locals ?? {}) as Record<string, unknown>,\n params: (context.request.params ?? {}) as Record<string, any>,\n\n // Add cache tags\n addCacheTag: (tag: string | string[] | Record<string, boolean>) => {\n addCacheTag(tag);\n },\n\n // Get all cache tags\n getCacheTags: () => {\n return Array.from(context.cacheTags);\n },\n };\n}\n\n/**\n * Checks if a value is a valid JSX element (JSXNode)\n * Similar to React.isValidElement\n */\nexport function isValidElement(value: any): value is JSXNode {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'type' in value &&\n 'props' in value &&\n 'children' in value &&\n (typeof value.type === 'string' || typeof value.type === 'function')\n );\n}\n\n/**\n * Clones a JSX element with new props and/or children\n * Similar to React.cloneElement\n */\nexport function cloneElement(\n element: JSXNode,\n props?: Record<string, any>,\n ...children: JSXChild[]\n): JSXNode {\n const newProps = { ...element.props, ...props };\n const newChildren = children.length > 0 ? children.flat() : element.children;\n\n return {\n type: element.type,\n props: newProps,\n children: newChildren,\n };\n}\n"],"names":["HEAD_PRIORITY","mergeMetadata","parent","child","merged","RAW_HTML_MARKER","jsxFactory","type","props","children","Fragment","renderStore","AsyncLocalStorage","createRequestContext","requestInfo","useClientJs","path","renderContext","registerIsland","key","src","name","e","getIslandEntries","context","registerSsrIsland","token","getSsrIslands","useCss","runInRenderContext","renderFn","viewName","setViewName","getClientJsEntries","getCacheTags","addCacheTag","tag","t","value","getCssEntries","Head","priority","a","b","getHeadContent","entry","pushMetadata","metadata","resolveMetadata","acc","current","pushSchema","schema","getSchemas","useRequest","isValidElement","cloneElement","element","newProps","newChildren"],"mappings":"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"}
|