@elurjs/kit 2.5.0 → 2.6.0-beta.0
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/CHANGELOG.md +31 -0
- package/README.md +53 -6
- package/dist/lib/cli.cjs +1 -9
- package/dist/lib/cli.cjs.map +1 -1
- package/dist/lib/cli.js +1 -9
- package/dist/lib/cli.js.map +1 -1
- package/package.json +5 -5
package/dist/lib/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.cjs","names":[],"sources":["../../src/router/route-scanner.ts","../../src/island/scan.ts","../../src/island/generate-entry.ts","../../src/render/ssr-flag.ts","../../src/render/render-to-string.ts","../../src/build/document-shell.ts","../../src/island/island.ts","../../src/action/error-store.ts","../../src/cache/policy.ts","../../src/ssr/render.ts","../../src/action/scan.ts","../../__vite-optional-peer-dep:sharp:@elurjs/kit","../../src/image/service.ts","../../src/integrations/index.ts","../../src/seo/index.ts","../../src/seo/sitemap-from-routes.ts","../../src/build/build.ts","../../src/vite/interpolation-plugin.ts","../../src/build/transform-source.ts","../../src/runtime/node-http.ts","../../src/runtime/logger.ts","../../src/config/index.ts","../../src/manifest/index.ts","../../src/runtime/capabilities.ts","../../src/cli/output.ts","../../src/cli/ports.ts","../../src/build/vite-build.ts","../../src/ssr/match.ts","../../src/middleware/index.ts","../../src/errors.ts","../../src/action/origin.ts","../../src/cache/adapter.ts","../../src/cache/invalidation.ts","../../src/action/server.ts","../../src/ssr/stream.ts","../../src/runtime/static.ts","../../src/runtime/context.ts","../../src/runtime/security-headers.ts","../../src/router/redirects.ts","../../src/middleware/stream-boundary.ts","../../src/ssr/stream-response.ts","../../src/runtime/handler.ts","../../src/adapters/shared.ts","../../src/adapters/vercel.ts","../../src/adapters/netlify.ts","../../src/adapters/bun.ts","../../src/adapters/node.ts","../../src/cli/commands.ts","../../src/cli.ts"],"sourcesContent":["import { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\n// --- Route scanner ---\n//\n// Walks src/app/ and maps file conventions to URL paths.\n//\n// Supported conventions:\n// - page.ts -> URL path\n// - page.data.ts -> loader for that page\n// - layout.ts -> layout wrapping pages in the same segment\n// - route.ts -> API endpoint (collected separately)\n//\n// Dynamic segments:\n// - [slug] -> :slug\n// - [...slug] -> catch-all (rendered as :slug*)\n// - [[...slug]] -> optional catch-all (rendered as :slug* but matches\n// the base path too)\n//\n// Route conflicts (two routes with the same path pattern) cause an error\n// during scanRoutes (plan §11.1).\n\n/** A page route discovered by the scanner. */\nexport interface PageRoute {\n /** URL path, e.g. \"/blog/:slug\". */\n path: string;\n /** File system path to the page.ts module. */\n pagePath: string;\n /** File system path to the page.data.ts module, if any. */\n dataPath?: string;\n /** File system path to the page.action.ts module, if any. */\n actionPath?: string;\n /** Ordered list of layout.ts modules from root to leaf. */\n layouts: string[];\n /** File system path to the loading.ts module, if any. */\n loadingPath?: string;\n /** Dynamic parameter names extracted from the path. */\n params: string[];\n /** Whether the route has an optional catch-all segment. */\n optionalCatchAll?: boolean;\n /**\n * Named slot modules discovered in the same directory as the page.\n * Keyed by slot name (filename without `.slot.ts` suffix).\n * (v2.1 — Fix #2: Layout Slots)\n */\n slots?: Record<string, string>;\n}\n\n/** An API route discovered by the scanner. */\nexport interface ApiRoute {\n /** URL path, e.g. \"/api/posts\". */\n path: string;\n /** File system path to the route.ts module. */\n routePath: string;\n /** Dynamic parameter names extracted from the path. */\n params: string[];\n}\n\n/** Result of scanning the app directory. */\nexport interface ScannedRoutes {\n pages: PageRoute[];\n api: ApiRoute[];\n /** Optional 404 error page. */\n error404?: PageRoute;\n /** Optional 500 error page. */\n error500?: PageRoute;\n}\n\nfunction isRouteGroup(segment: string): boolean {\n return segment.startsWith(\"(\") && segment.endsWith(\")\");\n}\n\nfunction segmentToUrl(segment: string): string {\n // Optional catch-all: [[...slug]] -> :slug* (matches base path too)\n if (segment.startsWith(\"[[...\") && segment.endsWith(\"]]\")) {\n return `:${segment.slice(5, -2)}*`;\n }\n // Catch-all: [...slug] -> :slug*\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\n return `:${segment.slice(4, -1)}*`;\n }\n // Dynamic: [slug] -> :slug\n if (segment.startsWith(\"[\") && segment.endsWith(\"]\")) {\n return `:${segment.slice(1, -1)}`;\n }\n return segment;\n}\n\nfunction extractParams(segment: string): string[] {\n if (segment.startsWith(\"[[...\") && segment.endsWith(\"]]\")) {\n return [segment.slice(5, -2)];\n }\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\n return [segment.slice(4, -1)];\n }\n if (segment.startsWith(\"[\") && segment.endsWith(\"]\")) {\n return [segment.slice(1, -1)];\n }\n return [];\n}\n\nfunction isOptionalCatchAll(segment: string): boolean {\n return segment.startsWith(\"[[...\") && segment.endsWith(\"]]\");\n}\n\nasync function collectFiles(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries\n .filter((e) => e.isFile() && e.name.endsWith(\".ts\"))\n .map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nasync function collectDirs(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nasync function scanRecursive(\n appDir: string,\n currentDir: string,\n urlSegments: string[],\n params: string[],\n layouts: string[],\n result: ScannedRoutes,\n hasOptionalCatchAll = false,\n): Promise<void> {\n const files = await collectFiles(currentDir);\n const dirs = await collectDirs(currentDir);\n\n const pagePath = files.includes(\"page.ts\")\n ? join(currentDir, \"page.ts\")\n : undefined;\n const dataPath = files.includes(\"page.data.ts\")\n ? join(currentDir, \"page.data.ts\")\n : undefined;\n const actionPath = files.includes(\"page.action.ts\")\n ? join(currentDir, \"page.action.ts\")\n : undefined;\n const loadingPath = files.includes(\"loading.ts\")\n ? join(currentDir, \"loading.ts\")\n : undefined;\n const layoutPath = files.includes(\"layout.ts\")\n ? join(currentDir, \"layout.ts\")\n : undefined;\n const routePath = files.includes(\"route.ts\")\n ? join(currentDir, \"route.ts\")\n : undefined;\n\n const currentLayouts = layoutPath\n ? [...layouts, layoutPath]\n : [...layouts];\n\n if (routePath) {\n result.api.push({\n path: urlSegments.length === 0 ? \"/\" : \"/\" + urlSegments.join(\"/\"),\n routePath,\n params: [...params],\n });\n }\n\n if (pagePath) {\n const path = urlSegments.length === 0 ? \"/\" : \"/\" + urlSegments.join(\"/\");\n // Detect named slot files: *.slot.ts (v2.1 — Fix #2: Layout Slots)\n const slots: Record<string, string> = {};\n for (const file of files) {\n const slotMatch = file.match(/^(.+)\\.slot\\.ts$/);\n if (slotMatch) {\n slots[slotMatch[1]] = join(currentDir, file);\n }\n }\n result.pages.push({\n path,\n pagePath,\n dataPath,\n actionPath,\n layouts: currentLayouts,\n loadingPath,\n params: [...params],\n optionalCatchAll: hasOptionalCatchAll,\n slots: Object.keys(slots).length > 0 ? slots : undefined,\n });\n }\n\n for (const dir of dirs) {\n if (isRouteGroup(dir)) {\n // Route groups do not add a URL segment, but they can add a layout.\n const groupDir = join(currentDir, dir);\n const groupFiles = await collectFiles(groupDir);\n const groupLayout = groupFiles.includes(\"layout.ts\")\n ? join(groupDir, \"layout.ts\")\n : undefined;\n await scanRecursive(\n appDir,\n groupDir,\n urlSegments,\n params,\n groupLayout ? [...currentLayouts, groupLayout] : currentLayouts,\n result,\n );\n continue;\n }\n\n const optional = isOptionalCatchAll(dir);\n await scanRecursive(\n appDir,\n join(currentDir, dir),\n [...urlSegments, segmentToUrl(dir)],\n [...params, ...extractParams(dir)],\n currentLayouts,\n result,\n optional,\n );\n }\n}\n\n/**\n * Scans an app directory for Elur Kit file-based routes.\n *\n * @param appDir Absolute path to the app directory (e.g. \"src/app\").\n * @returns Discovered page and API routes.\n */\nexport async function scanRoutes(appDir: string): Promise<ScannedRoutes> {\n const result: ScannedRoutes = { pages: [], api: [] };\n const rootFiles = await collectFiles(appDir);\n const rootLayout = rootFiles.includes(\"layout.ts\")\n ? join(appDir, \"layout.ts\")\n : undefined;\n\n if (rootFiles.includes(\"404.page.ts\")) {\n result.error404 = {\n path: \"/404\",\n pagePath: join(appDir, \"404.page.ts\"),\n dataPath: rootFiles.includes(\"404.page.data.ts\")\n ? join(appDir, \"404.page.data.ts\")\n : undefined,\n layouts: rootLayout ? [rootLayout] : [],\n params: [],\n };\n }\n\n if (rootFiles.includes(\"500.page.ts\")) {\n result.error500 = {\n path: \"/500\",\n pagePath: join(appDir, \"500.page.ts\"),\n dataPath: rootFiles.includes(\"500.page.data.ts\")\n ? join(appDir, \"500.page.data.ts\")\n : undefined,\n layouts: rootLayout ? [rootLayout] : [],\n params: [],\n };\n }\n\n await scanRecursive(appDir, appDir, [], [], [], result);\n\n // Detect route conflicts (plan §11.1): two routes with the same path\n // pattern is an error during manifest generation.\n detectRouteConflicts(result);\n\n return result;\n}\n\n/**\n * Detects and throws on route conflicts (plan §11.1, runtime-security §10).\n * Two routes with the same path pattern cause an error.\n */\nfunction detectRouteConflicts(routes: ScannedRoutes): void {\n const pagePaths = new Map<string, string>();\n for (const page of routes.pages) {\n const existing = pagePaths.get(page.path);\n if (existing) {\n throw new Error(\n `[elur-kit] Route conflict: \"${page.path}\" is defined by both ` +\n `\"${existing}\" and \"${page.pagePath}\". ` +\n `Remove one of the conflicting page.ts files.`,\n );\n }\n pagePaths.set(page.path, page.pagePath);\n }\n\n // Also check API route conflicts.\n const apiPaths = new Map<string, string>();\n for (const api of routes.api) {\n const existing = apiPaths.get(api.path);\n if (existing) {\n throw new Error(\n `[elur-kit] API route conflict: \"${api.path}\" is defined by both ` +\n `\"${existing}\" and \"${api.routePath}\".`,\n );\n }\n apiPaths.set(api.path, api.routePath);\n }\n}\n","import { readdir } from \"node:fs/promises\";\nimport type { Dirent } from \"node:fs\";\nimport { join, relative, sep } from \"node:path\";\n\n// --- Island scanner ---\n//\n// Walks `src/islands/` and lists every island component module. Each `.ts`\n// file (recursively) is treated as one island whose name is derived from its\n// path relative to the islands root:\n//\n// src/islands/LikeButton.ts -> \"LikeButton\"\n// src/islands/nav/MobileMenu.ts -> \"nav/MobileMenu\"\n//\n// The name must match the first argument passed to `island(name, ...)` on the\n// server so the client registry can look the component up during hydration.\n\n/** A single island component discovered by the scanner. */\nexport interface IslandModule {\n /** Registry name, derived from the path relative to the islands dir. */\n name: string;\n /** Absolute file system path to the island module. */\n filePath: string;\n}\n\nasync function walk(dir: string): Promise<string[]> {\n let entries: Dirent<string>[];\n try {\n entries = (await readdir(dir, {\n withFileTypes: true,\n encoding: \"utf8\",\n })) as Dirent<string>[];\n } catch {\n return [];\n }\n\n const files: string[] = [];\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await walk(full)));\n } else if (\n entry.isFile() &&\n entry.name.endsWith(\".ts\") &&\n !entry.name.endsWith(\".d.ts\") &&\n !entry.name.endsWith(\".test.ts\")\n ) {\n files.push(full);\n }\n }\n return files;\n}\n\nfunction toIslandName(islandsDir: string, filePath: string): string {\n return relative(islandsDir, filePath)\n .replace(/\\.ts$/, \"\")\n .split(sep)\n .join(\"/\");\n}\n\n/**\n * Scans an islands directory for island component modules.\n *\n * @param islandsDir Absolute path to the islands directory (e.g. \"src/islands\").\n * @returns Discovered island modules, sorted by name.\n */\nexport async function scanIslands(islandsDir: string): Promise<IslandModule[]> {\n const files = await walk(islandsDir);\n return files\n .map((filePath) => ({ name: toIslandName(islandsDir, filePath), filePath }))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative, sep } from \"node:path\";\nimport type { IslandModule } from \"./scan.js\";\n\n// --- Client entry generator ---\n//\n// Turns a list of scanned islands into a client entry module that imports each\n// island and registers it with `hydrateIslands`. This removes the need to hand-\n// maintain `entry-client.ts` as islands are added or removed.\n//\n// The generated file imports island default exports and passes them to\n// `hydrateIslands` keyed by their registry name.\n\n/**\n * Router options for the generated client entry (Fase 8.3).\n */\nexport interface RouterEntryOptions {\n /**\n * Include SPA navigation code. When `false` the generated entry is\n * hydrate-only and no router file is emitted. Default: `true`.\n */\n enabled?: boolean;\n /** Forwarded to `startClientRouter({ prefetch })`. Default: `true`. */\n prefetch?: boolean;\n /** Forwarded to `startClientRouter({ morph })` (idiomorph swap). */\n morph?: boolean;\n /** Forwarded to `startClientRouter({ loadingIndicator })`. */\n loadingIndicator?: boolean;\n /**\n * Split mode: the entry hydrates islands only and the router lives in a\n * separate generated module (`router.ts` next to the entry, emitted as its\n * own chunk). This is what lets pages without islands load only the router.\n */\n separate?: boolean;\n /** Absolute path of the generated router module when `separate` is set. */\n outFile?: string;\n}\n\n/** Options for generating the client entry module. */\nexport interface GenerateEntryOptions {\n /** Islands to register, from `scanIslands`. */\n islands: IslandModule[];\n /** Absolute path of the entry file to write (e.g. \".elur/entry-client.ts\"). */\n outFile: string;\n /**\n * Import specifier for the kit's client island helpers.\n * Defaults to the published subpath `@elurjs/kit/island`.\n */\n hydrateImport?: string;\n /**\n * Import specifier for the kit's client router.\n * Defaults to the published subpath `@elurjs/kit/router`.\n */\n routerImport?: string;\n /**\n * Router inclusion. Omit for the legacy combined entry (router embedded).\n * With `separate: true`, a standalone router module is also generated at\n * `router.outFile`.\n */\n router?: RouterEntryOptions;\n}\n\n/** Turns a registry name into a safe JS identifier for the import binding. */\nfunction toIdentifier(name: string, index: number): string {\n const cleaned = name.replace(/[^a-zA-Z0-9_$]/g, \"_\");\n return /^[a-zA-Z_$]/.test(cleaned) ? `${cleaned}_${index}` : `_${cleaned}_${index}`;\n}\n\n/**\n * Source for the standalone router module emitted in split builds. Router\n * options are baked in so the public module takes no arguments.\n */\nexport function buildRouterEntrySource(\n routerImport = \"@elurjs/kit/router\",\n options: Omit<RouterEntryOptions, \"enabled\" | \"separate\" | \"outFile\"> = {},\n): string {\n const opts: Record<string, boolean> = {};\n if (options.prefetch === false) opts.prefetch = false;\n if (options.morph === true) opts.morph = true;\n if (options.loadingIndicator === true) opts.loadingIndicator = true;\n const args = Object.keys(opts).length > 0 ? JSON.stringify(opts) : \"\";\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { startClientRouter } from ${JSON.stringify(routerImport)};\n\nstartClientRouter(${args});\n`;\n}\n\n/**\n * Serializes the startClientRouter options embedded in a combined entry.\n * Only non-default flags are emitted to keep the generated code minimal.\n */\nfunction routerCallArgs(router?: RouterEntryOptions): string {\n const opts: Record<string, boolean> = {};\n if (router?.prefetch === false) opts.prefetch = false;\n if (router?.morph === true) opts.morph = true;\n if (router?.loadingIndicator === true) opts.loadingIndicator = true;\n return Object.keys(opts).length > 0 ? JSON.stringify(opts) : \"\";\n}\n\n/** Builds the source code of the client entry module. */\nexport function buildEntrySource(\n islands: IslandModule[],\n outFile: string,\n hydrateImport = \"@elurjs/kit/island\",\n routerImport = \"@elurjs/kit/router\",\n router?: RouterEntryOptions,\n): string {\n const bindings = islands.map((island, i) => ({\n ident: toIdentifier(island.name, i),\n name: island.name,\n // Relative import specifier from the entry file to the island module.\n spec: toImportSpecifier(outFile, island.filePath),\n }));\n\n // Lazy registry: each island is loaded on-demand via dynamic import().\n // This enables code-splitting — islands not on the current page (or not yet\n // triggered by their directive) stay out of the initial bundle.\n //\n // The registry maps island name → discriminated lazy loader `{ load }`.\n // hydrateIslands() awaits `entry.load()` before hydrating, so the first\n // paint only needs the small entry chunk + the islands on the page. The\n // discriminated form lets the hydrator tell eager components from lazy\n // loaders without executing a probe.\n const registryLines = bindings\n .map((b) => ` ${JSON.stringify(b.name)}: { load: () => import(${JSON.stringify(b.spec)}).then(m => m.default) },`)\n .join(\"\\n\");\n\n const islandHydration = registryLines\n ? `const registry = {\n${registryLines}\n};\nconst hydrate = () => hydrateIslands(registry);\n// Islands inside persisted nodes must not be disposed across navigations.\n// The router announces the survivors in the elur:before-render detail; the\n// DOM query fallback covers hosts that dispatch it without detail.\nconst cleanup = (persisted) =>\n cleanupHydratedIslands({\n except: persisted ?? document.querySelectorAll(\"[data-elur-persist]\"),\n });\nlet sawBeforeRender = false;\n\n// Hydrate right after parse: module scripts are deferred, so this already\n// runs once the DOM is ready. Directives schedule themselves inside\n// hydrateIslands — \"load\"/\"only\" run immediately (real Astro semantics),\n// \"idle\"/\"visible\" keep their deferred scheduling.\nhydrate();\n\n// The router dispatches elur:before-render BEFORE swapping #app: islands are\n// disposed while still attached (Fase A2), except persisted subtrees.\ndocument.addEventListener(\"elur:before-render\", (event) => {\n sawBeforeRender = true;\n cleanup(event.detail?.persisted);\n});\n\n// Re-hydrate after SPA navigations.\ndocument.addEventListener(\"elur:rendered\", () => {\n // Compat fallback: hosts that only dispatch elur:rendered (streaming swap\n // script, hand-rolled integrations) still need the cleanup pass.\n if (!sawBeforeRender) cleanup();\n sawBeforeRender = false;\n hydrate();\n});\n\n// Vite HMR: when an island module (or the entry itself) updates, dispose the\n// current islands and re-hydrate from the updated modules — the registry's\n// dynamic import() resolves to the fresh modules, so no full page reload is\n// needed (progressive enhancement, audit §10.2 / §12.2).\nif (import.meta.hot) {\n import.meta.hot.accept(() => {\n cleanupHydratedIslands();\n hydrateIslands(registry);\n });\n}`\n : \"\";\n\n // The router is embedded in the entry unless a separate chunk was\n // requested (split builds) or the router is disabled outright.\n const embedRouter = router ? router.enabled !== false && !router.separate : true;\n\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\n${embedRouter ? `import { startClientRouter } from ${JSON.stringify(routerImport)};\\n` : \"\"}import { hydrateIslands, cleanupHydratedIslands } from ${JSON.stringify(hydrateImport)};\n${embedRouter ? `\\nstartClientRouter(${routerCallArgs(router)});\\n` : \"\"}${islandHydration}\n`;\n}\n\n/** Computes a POSIX-style relative import specifier between two files. */\nfunction toImportSpecifier(fromFile: string, toFile: string): string {\n let spec = relative(dirname(fromFile), toFile).split(sep).join(\"/\");\n if (!spec.startsWith(\".\")) spec = `./${spec}`;\n return spec;\n}\n\n/**\n * Generates and writes the client entry module for the given islands. When\n * `options.router.separate` is set (and the router is enabled), a standalone\n * router module is written alongside it (default: `router.ts` next to the\n * entry — bundle it as a second input to emit `/_elur/router.js`).\n *\n * @param options Generation options.\n * @returns The absolute path of the written entry file.\n */\nexport async function generateClientEntry(\n options: GenerateEntryOptions,\n): Promise<string> {\n const source = buildEntrySource(\n options.islands,\n options.outFile,\n options.hydrateImport,\n options.routerImport,\n options.router,\n );\n await mkdir(dirname(options.outFile), { recursive: true });\n await writeFile(options.outFile, source, \"utf8\");\n\n // Always emit the router module whenever router options were provided —\n // even in combined mode or with the router disabled — so a two-input user\n // config (`.elur/router.ts` as second input) never breaks on a missing\n // file. In combined mode the file is simply never emitted as a page script.\n if (options.router) {\n const routerFile =\n options.router.outFile ?? join(dirname(options.outFile), \"router.ts\");\n const routerSource =\n options.router.enabled === false\n ? `// AUTO-GENERATED by @elurjs/kit. Do not edit.\\n// router.enabled: false — intentionally empty.\\nexport {};\\n`\n : buildRouterEntrySource(options.routerImport ?? \"@elurjs/kit/router\", options.router);\n await writeFile(routerFile, routerSource, \"utf8\");\n }\n return options.outFile;\n}\n","// --- SSR flag utility ---\n//\n// `@elurjs/core` does not export `_setSSR`/`_isSSR`. The reactivity state lives\n// on `globalThis[Symbol.for(\"@elurjs/core/reactivity-state\")]` and the kit owns\n// the `ssr` boolean on it: `renderToString` sets it to `true` while server\n// rendering so `isSSR()` reflects the current render mode for user code\n// (environment reads, client-only guards, ...).\n//\n// This module manipulates that flag directly so the kit does not depend on\n// private exports that may or may not be present in a given elur release.\n\nconst STATE_KEY = Symbol.for(\"@elurjs/core/reactivity-state\");\n\ntype ReactivityState = { ssr?: boolean };\n\nfunction getState(): ReactivityState | undefined {\n return (globalThis as Record<symbol, unknown>)[STATE_KEY] as\n | ReactivityState\n | undefined;\n}\n\n/** Sets the SSR flag on the Elur reactivity state. No-op if state is absent. */\nexport function setSSR(value: boolean): void {\n const state = getState();\n if (state) state.ssr = value;\n}\n\n/** Reads the SSR flag from the Elur reactivity state. Defaults to false. */\nexport function isSSR(): boolean {\n return getState()?.ssr ?? false;\n}\n","import type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString as renderCoreTemplate } from \"@elurjs/core/server\";\nimport { setSSR } from \"./ssr-flag\";\n\n// --- Build-time / server rendering ---\n//\n// The Elur core ships a DOM-free `renderToString` (`@elurjs/core/server`)\n// that streams template output without ever touching a `document`. The kit used\n// to inject a Node-side DOM (happy-dom) as a fallback for legacy compatibility;\n// that fallback has been removed together with the happy-dom dependency.\n\n/**\n * Renders a Elur template to an HTML string in Node.\n *\n * Accepts a *factory* (not a template) because `html`` evaluates at call time.\n *\n * @param factory Thunk that builds the template, e.g. `() => Page({ data })`.\n * @returns Serialized HTML of the rendered template.\n */\nexport async function renderToString(\n factory: () => ElurTemplate,\n options: { markers?: \"none\" | \"hydration\" } = {},\n): Promise<string> {\n setSSR(true);\n try {\n return await renderCoreTemplate(factory(), {\n markers: options.markers ?? \"hydration\",\n });\n } finally {\n setSSR(false);\n }\n}\n","//\n// The <!DOCTYPE>, <head> and <body> wrapper — plus the serialized loader data\n// and the client entry — are injected here at build time.\n\nimport type { PageMetadata } from \"../types.js\";\nexport type SpeculationMode = \"prefetch\" | \"prerender\";\n\nexport interface ShellOptions {\n /** Rendered inner HTML that goes inside `#app`. */\n body: string;\n /** `<title>` text. */\n title?: string;\n /** `<html lang>` attribute. */\n lang?: string;\n /** Additional attributes for the `<html>` element, e.g. `{ \"data-theme\": \"dark\" }`. */\n htmlAttributes?: Record<string, string>;\n /**\n * Inline scripts injected into `<head>`. They run synchronously while the\n * document parses — before the first paint and before the (deferred) client\n * bundle — so they are the right place for no-flash bootstrapping (e.g.\n * applying a stored theme before the page becomes visible).\n */\n headScripts?: string[];\n /**\n * Raw HTML strings injected into `<head>` — e.g. `<link rel=\"icon\">`,\n * `<link rel=\"manifest\">`, `<meta name=\"theme-color\">`. Each string is\n * rendered as-is inside `<head>`.\n */\n headLinks?: string[];\n /** Loader data serialized into `<script id=\"elur-data\">`. */\n data?: unknown;\n /** Per-page action names serialized into `<script id=\"elur-actions\">`. */\n actions?: Record<string, string[]>;\n /**\n * Path to the client entry module, e.g. `/_elur/entry-client.js`. In split\n * builds this is the hydrate-only entry; callers gate it per page so it is\n * only emitted when the rendered body actually contains islands.\n */\n clientEntry?: string;\n /**\n * Path to the standalone client router module, e.g. `/_elur/router.js`\n * (split builds only). Emitted as a second `<script type=\"module\">` so pages\n * without islands still get SPA navigation without paying for the islands\n * entry.\n */\n routerEntry?: string;\n /**\n * Whether the client router is enabled for this page. When `false`, the\n * `elur:render-endpoint` meta is omitted entirely: no client router will run,\n * so there is nothing to advertise endpoint availability to.\n */\n routerEnabled?: boolean;\n /**\n * Speculation Rules API mode emitted as\n * `<script type=\"speculationrules\">` with document rules and\n * `eagerness: \"moderate\"`. Chromium-only progressive enhancement — other\n * browsers ignore the unknown script type. Only set this for static builds;\n * never apply to URLs reachable via server actions.\n */\n speculation?: SpeculationMode;\n /** Page metadata emitted as `<meta>`, `<link>` and OG/Twitter tags in `<head>`. */\n metadata?: PageMetadata;\n /**\n * Whether the SSR render endpoint (`/__elur-js/render`) is available at\n * runtime. Defaults to `true`. When `false` (static deployments), the shell\n * emits `<meta name=\"elur:render-endpoint\" content=\"off\" />` so the client\n * router skips probing the endpoint entirely — preventing a storm of 404\n * requests on fully static sites.\n */\n renderEndpoint?: boolean;\n}\n\nconst HTML_ESCAPES: Record<string, string> = {\n \"&\": \"&\",\n \"<\": \"<\",\n \">\": \">\",\n '\"': \""\",\n \"'\": \"'\",\n};\n\n/**\n * Explicit delimiters around the `#app` content. The streaming pipeline\n * (`createStreamingResponse`) and adapter render endpoints extract the page\n * body with these markers instead of parsing the shell layout by hand, so\n * changes to the shell markup never break extraction. They are HTML comments:\n * invisible, and ignored by hydration and the SPA router.\n */\nexport const APP_START_MARKER = \"<!--elur:app:start-->\";\nexport const APP_END_MARKER = \"<!--elur:app:end-->\";\n\n/**\n * Extracts the inner HTML of `#app` from a full document produced by\n * `documentShell`. Returns `undefined` when the markers are missing (e.g. a\n * hand-written document).\n */\nexport function extractAppBody(html: string): string | undefined {\n const start = html.indexOf(APP_START_MARKER);\n if (start < 0) return undefined;\n const end = html.indexOf(APP_END_MARKER, start + APP_START_MARKER.length);\n if (end < 0) return undefined;\n return html.slice(start + APP_START_MARKER.length, end);\n}\n\nfunction escapeHtml(value: string): string {\n return value.replace(/[&<>\"']/g, (c) => HTML_ESCAPES[c]);\n}\n\n/**\n * Serializes data for embedding inside a `<script>` tag. Escapes `<` so a\n * `</script>` sequence in the data cannot break out of the tag.\n */\nexport function serializeData(data: unknown): string {\n return JSON.stringify(data ?? null).replace(/</g, \"\\\\u003c\");\n}\n\n/**\n * Builds the `<head>` tags for a `PageMetadata` object. Every tag is marked with\n * `data-elur-head` so the client-side router can replace them on navigation\n * without touching charset/viewport or user-supplied `headScripts`.\n */\nexport function buildHeadTags(metadata: PageMetadata, fallbackTitle: string): string {\n const tags: string[] = [];\n const title = metadata.title ?? fallbackTitle;\n if (metadata.title) {\n tags.push(`<title data-elur-head>${escapeHtml(title)}</title>`);\n }\n\n if (metadata.description) {\n tags.push(`<meta data-elur-head name=\"description\" content=\"${escapeHtml(metadata.description)}\" />`);\n }\n\n if (metadata.canonical) {\n tags.push(`<link data-elur-head rel=\"canonical\" href=\"${escapeHtml(metadata.canonical)}\" />`);\n }\n\n if (metadata.robots) {\n tags.push(`<meta data-elur-head name=\"robots\" content=\"${escapeHtml(metadata.robots)}\" />`);\n }\n\n const og = metadata.openGraph;\n if (og) {\n if (og.type) tags.push(`<meta data-elur-head property=\"og:type\" content=\"${escapeHtml(og.type)}\" />`);\n tags.push(`<meta data-elur-head property=\"og:title\" content=\"${escapeHtml(og.title ?? title)}\" />`);\n if (og.description ?? metadata.description) {\n tags.push(`<meta data-elur-head property=\"og:description\" content=\"${escapeHtml(og.description ?? metadata.description!)}\" />`);\n }\n if (og.url ?? metadata.canonical) {\n tags.push(`<meta data-elur-head property=\"og:url\" content=\"${escapeHtml(og.url ?? metadata.canonical!)}\" />`);\n }\n if (og.image) tags.push(`<meta data-elur-head property=\"og:image\" content=\"${escapeHtml(og.image)}\" />`);\n if (og.image && og.imageAlt) tags.push(`<meta data-elur-head property=\"og:image:alt\" content=\"${escapeHtml(og.imageAlt)}\" />`);\n if (og.image && og.imageWidth) tags.push(`<meta data-elur-head property=\"og:image:width\" content=\"${String(og.imageWidth)}\" />`);\n if (og.image && og.imageHeight) tags.push(`<meta data-elur-head property=\"og:image:height\" content=\"${String(og.imageHeight)}\" />`);\n if (og.image && og.imageType) tags.push(`<meta data-elur-head property=\"og:image:type\" content=\"${escapeHtml(og.imageType)}\" />`);\n if (og.siteName) tags.push(`<meta data-elur-head property=\"og:site_name\" content=\"${escapeHtml(og.siteName)}\" />`);\n if (og.locale) tags.push(`<meta data-elur-head property=\"og:locale\" content=\"${escapeHtml(og.locale)}\" />`);\n }\n\n const tw = metadata.twitter;\n if (tw) {\n if (tw.card) tags.push(`<meta data-elur-head name=\"twitter:card\" content=\"${escapeHtml(tw.card)}\" />`);\n if (tw.title ?? title) tags.push(`<meta data-elur-head name=\"twitter:title\" content=\"${escapeHtml(tw.title ?? title)}\" />`);\n if (tw.description ?? metadata.description) {\n tags.push(`<meta data-elur-head name=\"twitter:description\" content=\"${escapeHtml(tw.description ?? metadata.description!)}\" />`);\n }\n if (tw.image) tags.push(`<meta data-elur-head name=\"twitter:image\" content=\"${escapeHtml(tw.image)}\" />`);\n if (tw.image && tw.imageAlt) tags.push(`<meta data-elur-head name=\"twitter:image:alt\" content=\"${escapeHtml(tw.imageAlt)}\" />`);\n }\n\n if (metadata.other) {\n for (const [name, content] of Object.entries(metadata.other)) {\n tags.push(`<meta data-elur-head name=\"${escapeHtml(name)}\" content=\"${escapeHtml(content)}\" />`);\n }\n }\n\n return tags.map((t) => `\\n ${t}`).join(\"\");\n}\n\n/**\n * Document-level Speculation Rules (Chromium-only, ignored elsewhere).\n *\n * `href_matches: \"/*\"` scopes the rule to same-origin path links; the\n * `selector_matches` exclusions keep downloads, new-tab links, router-opt-outs\n * and explicit `data-no-speculation` links out of speculation. Actions are\n * POST endpoints reached through forms/`callAction`, never through document\n * links, so they are not speculated. `eagerness: \"moderate\"` speculates on\n * hover — the same trigger as the client router's prefetch.\n */\nfunction speculationRulesScript(mode: SpeculationMode): string {\n const rules = {\n [mode]: [\n {\n source: \"document\",\n where: {\n and: [\n { href_matches: \"/*\" },\n {\n not: {\n selector_matches:\n \"a[download], a[target], a[data-no-router], a[data-no-speculation]\",\n },\n },\n ],\n },\n eagerness: \"moderate\",\n },\n ],\n };\n return `\\n <script type=\"speculationrules\">${JSON.stringify(rules)}</script>`;\n}\n\n/** Wraps rendered body HTML into a full HTML document. */\nexport function documentShell(opts: ShellOptions): string {\n const { body, title = \"Elur Kit App\", lang = \"es\", data, actions, clientEntry, routerEntry, htmlAttributes, headScripts, headLinks, metadata } = opts;\n\n const dataScript =\n data !== undefined\n ? `\\n <script type=\"application/json\" id=\"elur-data\">${serializeData(data)}</script>`\n : \"\";\n\n const actionsScript = actions && Object.keys(actions).length > 0\n ? `\\n <script type=\"application/json\" id=\"elur-actions\">${serializeData(actions)}</script>`\n : \"\";\n\n // Every emitted module script also gets a <link rel=\"modulepreload\"> so the\n // fetch starts during HTML parsing instead of waiting for the deferred\n // script discovery (Fase 8.5 — paso 1).\n const modulePreload = (src: string) =>\n `\\n <link rel=\"modulepreload\" href=\"${escapeHtml(src)}\" />`;\n\n const preloads =\n (clientEntry ? modulePreload(clientEntry) : \"\") +\n (routerEntry ? modulePreload(routerEntry) : \"\");\n\n const entryScript = clientEntry\n ? `\\n <script type=\"module\" src=\"${escapeHtml(clientEntry)}\"></script>`\n : \"\";\n\n const routerScript = routerEntry\n ? `\\n <script type=\"module\" src=\"${escapeHtml(routerEntry)}\"></script>`\n : \"\";\n\n const speculationScript = opts.speculation\n ? speculationRulesScript(opts.speculation)\n : \"\";\n\n const htmlAttrs = htmlAttributes\n ? Object.entries(htmlAttributes)\n .filter(([, value]) => value !== undefined && value !== null && value !== \"\")\n .map(([key, value]) => ` ${escapeHtml(key)}=\"${escapeHtml(String(value))}\"`)\n .join(\"\")\n : \"\";\n\n const headScriptsHtml = headScripts\n ? headScripts\n .filter((script) => typeof script === \"string\" && script.trim().length > 0)\n .map((script) => {\n // If the script is already a complete <script> tag (e.g. JSON-LD),\n // render it as-is without wrapping.\n if (script.trimStart().startsWith(\"<script\")) {\n return `\\n ${script}`;\n }\n return `\\n <script>${script.replace(/<\\/script>/gi, \"<\\\\/script>\")}</script>`;\n })\n .join(\"\")\n : \"\";\n\n const headTags = metadata ? buildHeadTags(metadata, title) : \"\";\n const titleTag = metadata?.title\n ? \"\" // already emitted by buildHeadTags\n : `\\n <title>${escapeHtml(title)}</title>`;\n\n const headLinksHtml = headLinks\n ? headLinks\n .filter((link) => typeof link === \"string\" && link.trim().length > 0)\n .map((link) => `\\n ${link}`)\n .join(\"\")\n : \"\";\n\n // The render-endpoint marker only exists for the client router; when the\n // router is disabled for the page there is nothing to advertise.\n const renderEndpointMeta =\n opts.renderEndpoint === false && opts.routerEnabled !== false\n ? '\\n <meta name=\"elur:render-endpoint\" content=\"off\" />'\n : \"\";\n\n return `<!DOCTYPE html>\n<html lang=\"${escapeHtml(lang)}\"${htmlAttrs}>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />${renderEndpointMeta}${titleTag}${headTags}${headLinksHtml}${headScriptsHtml}${preloads}${speculationScript}\n </head>\n <body>\n <div id=\"app\">${APP_START_MARKER}${body}${APP_END_MARKER}</div>${dataScript}${actionsScript}${entryScript}${routerScript}\n </body>\n</html>\n`;\n}\n","import { ELUR_RENDER_PROTOCOL, type ElurTemplate, type ServerRenderProtocolContext } from \"@elurjs/core\";\n\n// --- Islands helper ---\n//\n// Marks a component as an island. During server-side rendering it emits a\n// static placeholder with `data-elur-island` attributes. The client entry finds\n// these markers and hydrates them with the real component + reactive signals.\n//\n// SSR strategy\n// ------------\n// By default the component is executed on the server to produce a fallback HTML\n// fragment (better first paint, SEO, less layout shift). Components that access\n// browser-only globals (`document`, `window`, `navigator`, ...) in their body\n// cannot run on the server. Two opt-out mechanisms are provided, mirroring the\n// industry standard (Astro `client:only`, Next.js `dynamic(..., { ssr: false })`):\n//\n// 1. directive: \"only\" — shortcut for client-only with `load` scheduling.\n// 2. options: { ssr: false } — client-only with any directive (load/idle/visible).\n//\n// When SSR is skipped, only `options.fallback` (a ElurTemplate or string) is\n// rendered into the marker. The client hydrates from scratch.\n//\n// When SSR runs and the component throws, the error is NOT swallowed: it is\n// re-thrown wrapped with an actionable message naming the island and suggesting\n// `directive: \"only\"` / `{ ssr: false }` / `isSSR()`. This matches Astro and\n// Next.js, which never try/catch to \"auto-detect\" client-only components.\n\nexport type IslandDirective = \"load\" | \"idle\" | \"visible\" | \"only\";\n\n/**\n * HTML attribute that marks an island marker element. The renderer scans the\n * rendered body for this attribute to decide whether the page needs the\n * hydration entry at all (0% JS gating); the client hydrator queries the DOM\n * with `[data-elur-island]`.\n */\nexport const ISLAND_MARKER_ATTR = \"data-elur-island\";\n\n/**\n * HTML attribute that marks an element whose live DOM node is moved (not\n * re-rendered) across SPA navigations — the Astro `transition:persist` /\n * Turbo `data-turbo-permanent` pattern. The client router matches nodes by\n * the attribute value (`data-elur-persist=\"key\"`) between the old and new\n * page, preserving component state, media playback, scroll position, etc.\n */\nexport const PERSIST_ATTR = \"data-elur-persist\";\n\nexport interface IslandComponent<TProps = unknown> {\n (props: TProps): ElurTemplate | null | false | undefined;\n}\n\n/**\n * Options for {@link island}.\n *\n * - `ssr`: Whether to execute the component on the server. Defaults to `true`\n * unless `directive === \"only\"` (then `false`). When `false`, the component\n * is never called during SSR; only `fallback` is rendered.\n * - `fallback`: HTML to render inside the island marker when SSR is skipped or\n * the component returns null/false. Accepts a `ElurTemplate` (reactive, with\n * signals) or a plain string. Defaults to an empty string.\n */\nexport interface IslandOptions {\n ssr?: boolean;\n fallback?: ElurTemplate | string;\n}\n\n/**\n * Renders a component to a static HTML string with island markers.\n *\n * @param name Unique island name used by the client entry to look up the module.\n * @param component Island component. Executed on the server unless `directive`\n * is `\"only\"` or `options.ssr` is `false`.\n * @param props Props passed to the component and serialized for hydration.\n * @param directive When to hydrate on the client. Use `\"only\"` to skip SSR\n * entirely (client-only island).\n * @param options SSR strategy and fallback content.\n * @returns A ElurTemplate that renders the island placeholder.\n */\nexport function island<TProps>(\n name: string,\n component: IslandComponent<TProps>,\n props: TProps,\n directive: IslandDirective = \"load\",\n options?: IslandOptions,\n): ElurTemplate {\n // `directive: \"only\"` forces ssr off; explicit `options.ssr` wins otherwise.\n const ssr = directive === \"only\" ? false : (options?.ssr ?? true);\n const fallback = options?.fallback;\n\n const markerHtml = (innerHtml: string) =>\n `<div ${ISLAND_MARKER_ATTR}=\"${escapeHtml(name)}\" data-directive=\"${directive}\" data-props='${serializeProps(props)}'>${innerHtml}</div>`;\n\n return {\n __isElurTemplate: true as const,\n [ELUR_RENDER_PROTOCOL]: {\n async renderServer(context: ServerRenderProtocolContext) {\n let innerHtml = \"\";\n if (ssr) {\n try {\n const template = component(props);\n if (template !== null && template !== false && template !== undefined) {\n innerHtml = await context.render(template, { markers: true });\n } else {\n // Component returned null/false/undefined — render fallback if any.\n innerHtml = await renderFallback(fallback, context);\n }\n } catch (error) {\n throw wrapIslandSSRError(name, error);\n }\n } else {\n innerHtml = await renderFallback(fallback, context);\n }\n return markerHtml(innerHtml);\n },\n },\n _render(parent: Node, before: Node | null): () => void {\n const container = document.createElement(\"div\");\n let innerHtml = \"\";\n if (ssr) {\n const template = component(props);\n if (template !== null && template !== false && template !== undefined) {\n const dispose = template._render(container, null);\n innerHtml = container.innerHTML;\n dispose();\n } else {\n // null/false/undefined — render fallback if any.\n innerHtml = renderFallbackSync(fallback, container);\n }\n } else {\n innerHtml = renderFallbackSync(fallback, container);\n }\n const wrapper = document.createElement(\"template\");\n wrapper.innerHTML = markerHtml(innerHtml);\n const fragment = wrapper.content;\n const inserted = fragment.firstChild;\n parent.insertBefore(fragment, before);\n return () => {\n if (inserted?.parentNode) inserted.parentNode.removeChild(inserted);\n };\n },\n } as unknown as ElurTemplate;\n}\n\n/**\n * Wraps an SSR error from an island component with an actionable message.\n *\n * Following the Astro/Next.js convention, SSR errors are never silently\n * swallowed — they propagate so real bugs surface. The wrapper adds the island\n * name and three concrete remediation paths.\n */\nfunction wrapIslandSSRError(name: string, error: unknown): Error {\n const cause = error instanceof Error ? error : new Error(String(error));\n const msg = error instanceof Error ? error.message : String(error);\n return new Error(\n `[elur-kit] Island \"${name}\" threw during SSR: ${msg}\\n` +\n ` If the component accesses browser-only globals (document, window, etc.),\\n` +\n ` use directive: \"only\" or options: { ssr: false } to skip server rendering.\\n` +\n ` For environment reads (matchMedia, localStorage, navigator) you may guard\\n` +\n ` the access with isSSR() from \"@elurjs/kit\".`,\n { cause },\n );\n}\n\n/** Renders the fallback (ElurTemplate or string) to an HTML string on the server. */\nasync function renderFallback(\n fallback: ElurTemplate | string | undefined,\n context: ServerRenderProtocolContext,\n): Promise<string> {\n if (fallback == null || fallback === \"\") return \"\";\n if (typeof fallback === \"string\") return fallback;\n return context.render(fallback, { markers: false });\n}\n\n/** Renders the fallback into a container and returns its innerHTML (client path). */\nfunction renderFallbackSync(fallback: ElurTemplate | string | undefined, container: HTMLElement): string {\n if (fallback == null || fallback === \"\") return \"\";\n if (typeof fallback === \"string\") return fallback;\n const dispose = fallback._render(container, null);\n const html = container.innerHTML;\n dispose();\n return html;\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nfunction serializeProps(props: unknown): string {\n return JSON.stringify(props ?? null)\n .replace(/</g, \"\\\\u003c\")\n .replace(/'/g, \"\\\\u0027\");\n}\n","// --- Ephemeral action error store ---\n//\n// Action failures submitted via plain HTML forms (progressive enhancement)\n// need to be relayed back to the page so the user sees validation errors.\n//\n// Previously the failure data was serialized into a `?__elur_js_action_error=`\n// query param on the redirect. That leaks errors into browser history,\n// server logs and third-party Referer headers.\n//\n// Now we stash the failure in a short-lived in-memory store keyed by a random\n// id, set a small cookie `__elur_js_action_error=<id>` (Max-Age=15s, SameSite=Lax),\n// and the next render reads the cookie, fetches the payload, exposes it as\n// `props.form`, and clears the entry.\n//\n// The store is process-local, which is fine for the single-process SSR server\n// and the dev server. For multi-instance deployments the cookie carries the\n// payload directly when it fits (see `encodeActionErrorCookie`); the store is\n// only the overflow path for large payloads.\n\nimport { createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\n\nconst COOKIE_NAME = \"__elur_js_action_error\";\nconst MAX_COOKIE_SIZE = 3500; // bytes; leaves headroom under the 4KB cookie limit\nconst TTL_MS = 15_000;\n\n// HMAC key for signing action error cookies. In production this should be\n// set via ELUR_JS_ACTION_SECRET env var; otherwise we derive a per-process\n// key (sufficient for single-process dev/preview, but NOT for multi-instance).\nconst ACTION_SECRET =\n process.env.ELUR_JS_ACTION_SECRET ?? randomBytes(32).toString(\"hex\");\n\ninterface StoredError {\n data: unknown;\n status: number;\n expiresAt: number;\n}\n\nconst store = new Map<string, StoredError>();\n\n// Periodically purge expired entries so the map does not grow unbounded.\nlet sweepScheduled = false;\nfunction scheduleSweep(): void {\n if (sweepScheduled) return;\n sweepScheduled = true;\n setTimeout(() => {\n sweepScheduled = false;\n const now = Date.now();\n for (const [key, entry] of store) {\n if (entry.expiresAt <= now) store.delete(key);\n }\n }, TTL_MS).unref?.();\n}\n\n/**\n * Signs a payload with HMAC-SHA256 using the action secret.\n * Returns `signature.payload` (both hex/base64url).\n */\nfunction sign(payload: string): string {\n const sig = createHmac(\"sha256\", ACTION_SECRET).update(payload).digest(\"hex\");\n return `${sig}.${payload}`;\n}\n\n/**\n * Verifies a signed value and returns the payload if valid, or undefined.\n * Uses timingSafeEqual to prevent timing attacks.\n */\nfunction verify(value: string): string | undefined {\n const dotIndex = value.indexOf(\".\");\n if (dotIndex === -1) return undefined;\n const sig = value.slice(0, dotIndex);\n const payload = value.slice(dotIndex + 1);\n const expectedSig = createHmac(\"sha256\", ACTION_SECRET).update(payload).digest(\"hex\");\n if (sig.length !== expectedSig.length) return undefined;\n try {\n if (timingSafeEqual(Buffer.from(sig), Buffer.from(expectedSig))) {\n return payload;\n }\n } catch {\n // Length mismatch — invalid.\n }\n return undefined;\n}\n\n/**\n * Encodes an action failure for the redirect cookie. When the payload fits\n * inside the cookie limit, it is embedded directly as a signed base64url JSON\n * value. When it is too large, it is stored in memory and only a short signed\n * id is written to the cookie.\n *\n * The cookie is signed with HMAC-SHA256 to prevent forgery (A-20).\n *\n * @returns The cookie value to set on the redirect response.\n */\nexport function encodeActionErrorCookie(\n data: unknown,\n status: number,\n): { value: string; storeId?: string } {\n const payload = JSON.stringify({ d: data, s: status });\n const encoded = Buffer.from(payload, \"utf8\").toString(\"base64url\");\n const signed = sign(encoded);\n if (signed.length <= MAX_COOKIE_SIZE) {\n return { value: signed };\n }\n\n // Overflow: stash in memory and reference by signed id.\n const id = randomBytes(12).toString(\"hex\");\n store.set(id, { data, status, expiresAt: Date.now() + TTL_MS });\n scheduleSweep();\n return { value: sign(`id:${id}`), storeId: id };\n}\n\n/**\n * Decodes a cookie value (previously produced by `encodeActionErrorCookie`)\n * into the failure payload. Verifies the HMAC signature first, then resolves\n * in-memory overflow entries and deletes them after reading.\n */\nexport function decodeActionErrorCookie(value: string | undefined | null):\n | { data: unknown; status: number }\n | undefined {\n if (!value) return undefined;\n\n // Verify signature first.\n const verifiedPayload = verify(value);\n if (verifiedPayload === undefined) return undefined;\n\n // Check if it's an in-memory store reference.\n if (verifiedPayload.startsWith(\"id:\")) {\n const id = verifiedPayload.slice(3);\n const entry = store.get(id);\n if (!entry) return undefined;\n store.delete(id);\n if (entry.expiresAt <= Date.now()) return undefined;\n return { data: entry.data, status: entry.status };\n }\n\n try {\n const json = Buffer.from(verifiedPayload, \"base64url\").toString(\"utf8\");\n const parsed = JSON.parse(json) as { d: unknown; s: number };\n return { data: parsed.d, status: parsed.s };\n } catch {\n return undefined;\n }\n}\n\n/** Name of the cookie used to relay action errors. */\nexport const ACTION_ERROR_COOKIE = COOKIE_NAME;\n\n/** Builds the Set-Cookie header value that clears the error cookie. */\nexport function clearActionErrorCookieHeader(): string {\n return `${COOKIE_NAME}=; Path=/; Max-Age=0; SameSite=Lax`;\n}\n\n/** Builds the Set-Cookie header value that sets the error cookie. */\nexport function setActionErrorCookieHeader(value: string): string {\n return `${COOKIE_NAME}=${value}; Path=/; Max-Age=15; SameSite=Lax; HttpOnly`;\n}\n","// --- Cache policy per route (runtime-security §9.1) ---\n//\n// Authors can declare a cache policy in their page.data.ts:\n//\n// export const cache = {\n// mode: \"public\", // \"public\" | \"private\" | \"dynamic\"\n// revalidate: 60, // seconds\n// tags: [\"products\"], // for tag-based invalidation\n// };\n//\n// Default policy: \"dynamic\" (no public ISR caching).\n// Requests with Cookie/Authorization are never cached publicly.\n// Responses with Set-Cookie/private/no-store are never cached publicly.\n\n/** Cache mode for a route. */\nexport type CacheMode = \"public\" | \"private\" | \"dynamic\";\n\n/** Cache policy declared by the route's data module. */\nexport interface CachePolicy {\n mode: CacheMode;\n revalidate: number;\n tags?: string[];\n}\n\n/** Default cache policy when none is declared. */\nexport const DEFAULT_CACHE_POLICY: CachePolicy = {\n mode: \"dynamic\",\n revalidate: 0,\n};\n\n/**\n * Normalizes a raw cache export from a data module into a CachePolicy.\n * Returns the default policy if the input is invalid or missing.\n */\nexport function normalizeCachePolicy(raw: unknown): CachePolicy {\n if (!raw || typeof raw !== \"object\") return DEFAULT_CACHE_POLICY;\n const obj = raw as Record<string, unknown>;\n const mode = obj.mode;\n if (mode !== \"public\" && mode !== \"private\" && mode !== \"dynamic\") {\n return DEFAULT_CACHE_POLICY;\n }\n const revalidate = typeof obj.revalidate === \"number\" ? obj.revalidate : 0;\n const tags = Array.isArray(obj.tags) ? obj.tags.filter((t) => typeof t === \"string\") : undefined;\n return { mode, revalidate, tags };\n}\n\n/**\n * Determines whether a route's cache policy allows public caching for the\n * given request.\n *\n * Per §9.1:\n * - \"dynamic\" → never cache\n * - \"private\" → never cache publicly (requires private adapter)\n * - \"public\" → cache only if request has no Cookie/Authorization\n */\nexport function shouldCachePublic(\n policy: CachePolicy,\n request: Request,\n): boolean {\n if (policy.mode !== \"public\") return false;\n if (policy.revalidate <= 0) return false;\n if (request.headers.get(\"Cookie\")) return false;\n if (request.headers.get(\"Authorization\")) return false;\n return true;\n}\n","import type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString } from \"../render/render-to-string.js\";\nimport { documentShell, buildHeadTags } from \"../build/document-shell.js\";\nimport { ISLAND_MARKER_ATTR } from \"../island/island.js\";\nimport type { PageRoute, ScannedRoutes } from \"../router/route-scanner.js\";\nimport type { BuildConfig } from \"../build/build.js\";\nimport type { PageDataLoad, PageProps, RouteParams, PageMetadata, GenerateMetadata } from \"../types.js\";\nimport { existsSync } from \"node:fs\";\nimport { decodeActionErrorCookie, ACTION_ERROR_COOKIE } from \"../action/error-store.js\";\nimport { normalizeCachePolicy, type CachePolicy } from \"../cache/policy.js\";\n\nexport interface RenderPageOptions {\n route: PageRoute;\n params?: RouteParams;\n searchParams?: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\" | \"renderEndpoint\" | \"router\" | \"js\">;\n /** Custom module loader. Defaults to native dynamic import. */\n importer?: (path: string) => Promise<unknown>;\n /** Per-page action names exposed in the HTML shell. */\n actions?: Record<string, string[]>;\n /** Current request, used to hydrate data loaders that need cookies/headers. */\n request?: Request;\n}\n\nexport interface RenderPageResult {\n html: string;\n revalidate?: number;\n /**\n * `Set-Cookie` header value that clears the action error cookie, when the\n * page consumed a relayed action failure. The SSR server should append it to\n * the outgoing response so the cookie does not persist.\n */\n clearActionErrorCookie?: string;\n /** `<head>` tags (title, meta, OG, twitter) for the SPA router to merge. */\n head?: string;\n /** Resolved page title (from metadata or fallback). */\n resolvedTitle?: string;\n /**\n * Loader data as rendered into `<script id=\"elur-data\">`. Exposed so the\n * SPA render endpoint can ship it in the payload and the client router can\n * keep the serialized data fresh across navigations.\n */\n data?: unknown;\n /**\n * When a loader or layout throws a `Response` (e.g. `throw new Response(...,\n * { status: 404 })`), it is captured here as a first-class response instead\n * of being treated as an internal error (A-22).\n */\n response?: Response;\n /** HTTP status code for the rendered page (e.g. 404 for not-found pages). */\n status?: number;\n /** Cache policy declared by the route (§9.1). */\n cachePolicy?: CachePolicy;\n}\n\nconst defaultImport = (path: string) => import(path);\n\n/**\n * Collects `<html>` attributes and head scripts declared by data loaders\n * (page and layouts) via top-level `htmlAttributes` / `headScripts` fields.\n */\nexport function collectShellExtras(\n pageData: unknown,\n layoutDataList: unknown[],\n): { htmlAttributes: Record<string, string>; headScripts: string[]; headLinks: string[] } {\n const htmlAttributes: Record<string, string> = {};\n const headScripts: string[] = [];\n const headLinks: string[] = [];\n const merge = (value: unknown) => {\n if (!value || typeof value !== \"object\") return;\n const attrs = (value as { htmlAttributes?: Record<string, string> }).htmlAttributes;\n if (attrs) Object.assign(htmlAttributes, attrs);\n const scripts = (value as { headScripts?: string[] }).headScripts;\n if (Array.isArray(scripts)) headScripts.push(...scripts);\n const links = (value as { headLinks?: string[] }).headLinks;\n if (Array.isArray(links)) headLinks.push(...links);\n };\n for (const layoutData of layoutDataList) merge(layoutData);\n merge(pageData);\n // Deduplicate headScripts and headLinks (e.g. from both layout and page data)\n const uniqueScripts = [...new Set(headScripts)];\n const uniqueLinks = [...new Set(headLinks)];\n return { htmlAttributes, headScripts: uniqueScripts, headLinks: uniqueLinks };\n}\n\nexport async function renderPage(options: RenderPageOptions): Promise<RenderPageResult> {\n const { route, params = {}, searchParams = new URLSearchParams(), config, importer = defaultImport, actions, request } = options;\n\n const pageModule = await importer(route.pagePath) as {\n default: (props: PageProps<unknown>) => ElurTemplate;\n generateMetadata?: GenerateMetadata;\n };\n const { default: PageComponent, generateMetadata } = pageModule;\n\n let data: unknown;\n let revalidate: number | undefined;\n let cachePolicy: import(\"../cache/policy.js\").CachePolicy | undefined;\n // Use a mutable container so TypeScript doesn't narrow the type after\n // the first `if (thrownResponse)` check.\n const thrown: { response: Response | undefined } = { response: undefined };\n if (route.dataPath) {\n const mod = await importer(route.dataPath) as {\n load?: PageDataLoad;\n revalidate?: number;\n cache?: unknown;\n };\n if (mod.load) {\n try {\n data = await mod.load({ params, searchParams, request });\n } catch (err) {\n if (err instanceof Response) {\n thrown.response = err;\n } else {\n throw err;\n }\n }\n }\n if (typeof mod.revalidate === \"number\") {\n revalidate = mod.revalidate;\n }\n // Read cache policy from the data module (§9.1).\n if (mod.cache) {\n cachePolicy = normalizeCachePolicy(mod.cache);\n if (cachePolicy.revalidate > 0) {\n revalidate = cachePolicy.revalidate;\n }\n }\n }\n\n // If a loader threw a Response (redirect, 404, etc.), return it as a\n // first-class response instead of rendering the page (A-22).\n if (thrown.response) {\n return { html: \"\", response: thrown.response, status: thrown.response.status };\n }\n\n // Relay an action failure previously stored in the ephemeral cookie so the\n // page can render validation errors via `props.form`. The cookie is cleared\n // on the outgoing response (see `clearActionErrorCookie` in the result).\n let form: unknown;\n let clearActionErrorCookie: string | undefined;\n if (request) {\n const cookieHeader = request.headers.get(\"Cookie\") ?? \"\";\n const match = cookieHeader.match(new RegExp(`(?:^|;\\\\s*)${ACTION_ERROR_COOKIE}=([^;]+)`));\n if (match) {\n const decoded = decodeActionErrorCookie(match[1]);\n if (decoded) {\n form = { __elur_js_action_error: true, status: decoded.status, data: decoded.data };\n clearActionErrorCookie = `${ACTION_ERROR_COOKIE}=; Path=/; Max-Age=0; SameSite=Lax`;\n }\n }\n }\n\n const props: PageProps<unknown> = {\n data: data ?? {},\n params,\n searchParams,\n form,\n };\n\n const layoutModules = await Promise.all(\n route.layouts.map(async (layoutPath) => importer(layoutPath)),\n );\n const layoutDataList = await Promise.all(\n route.layouts.map(async (layoutPath) => {\n const dataPath = layoutPath.replace(/layout\\.ts$/, \"layout.data.ts\");\n if (!existsSync(dataPath)) return undefined;\n const mod = (await importer(dataPath)) as { load?: PageDataLoad };\n if (mod.load) {\n try {\n return await mod.load({ params, searchParams, request });\n } catch (err) {\n if (err instanceof Response) {\n thrown.response = err;\n return undefined;\n }\n throw err;\n }\n }\n return undefined;\n }),\n );\n\n // If a layout loader threw a Response, return it as first-class (A-22).\n const layoutThrown = thrown.response as Response | undefined;\n if (layoutThrown) {\n return { html: \"\", response: layoutThrown, status: layoutThrown.status };\n }\n\n // Load slot modules if the route has them (v2.1 — Fix #2: Layout Slots).\n let slotTemplates: Record<string, ElurTemplate> | undefined;\n if (route.slots) {\n slotTemplates = {};\n for (const [slotName, slotPath] of Object.entries(route.slots)) {\n const slotMod = await importer(slotPath) as { default: (props: PageProps<unknown>) => ElurTemplate };\n slotTemplates[slotName] = slotMod.default(props);\n }\n }\n\n const body = await renderToString(() => {\n let template = PageComponent(props);\n for (let i = layoutModules.length - 1; i >= 0; i--) {\n const { default: Layout } = layoutModules[i] as {\n default: (props: { children: ElurTemplate; data?: unknown; slots?: Record<string, ElurTemplate> }) => ElurTemplate;\n };\n template = Layout({ children: template, data: layoutDataList[i], slots: slotTemplates });\n }\n return template;\n });\n\n const title = typeof data === \"object\" && data && \"title\" in data\n ? String((data as { title?: unknown }).title ?? \"Elur Kit\")\n : \"Elur Kit\";\n\n const { htmlAttributes, headScripts, headLinks } = collectShellExtras(data, layoutDataList);\n\n // Resolve page metadata. Priority: `generateMetadata` from page.ts > `metadata`\n // field in the page loader data > `metadata` field in layout loader data.\n let metadata: PageMetadata | undefined;\n if (typeof generateMetadata === \"function\") {\n metadata = await generateMetadata({ params, searchParams, request, data });\n }\n if (!metadata) {\n metadata = extractMetadata(data) ?? extractMetadataFromList(layoutDataList);\n }\n // The title from metadata takes precedence over the data.title fallback.\n const resolvedTitle = metadata?.title ?? title;\n\n // --- 0% JS gating (Fase 8.2) ---\n // Scan the rendered body for island markers. A false positive (e.g. a\n // `data-elur-island` string inside user markdown) only loads the hydration\n // entry unnecessarily — benign. A false negative would mean dead islands in\n // production, which is why we scan output instead of tracking render context.\n const hasIslands = body.includes(ISLAND_MARKER_ATTR);\n\n // Decide which module scripts the shell emits. Three modes:\n // legacy (`js: \"legacy\"` or no router config at all): the combined\n // entry is emitted unconditionally — the pre-Fase-8 behavior.\n // split (router.entry set): entry-client hydrates islands only, the\n // router lives in its own chunk → emit router.js whenever the\n // router is enabled, and entry-client only when islands exist.\n // combined (router configured, no entry): the entry embeds the router\n // (single-input bundles) → emit it when there are islands or the\n // router is on; a page with neither ships 0 KB of JS.\n const routerCfg = config.router;\n const routerEnabled = routerCfg?.enabled !== false;\n let clientEntry: string | undefined;\n let routerEntry: string | undefined;\n if (!routerCfg || config.js === \"legacy\") {\n clientEntry = config.clientEntry;\n } else if (routerCfg.entry) {\n if (hasIslands) clientEntry = config.clientEntry;\n if (routerEnabled) routerEntry = routerCfg.entry;\n } else if (hasIslands || routerEnabled) {\n clientEntry = config.clientEntry;\n }\n\n const html = documentShell({\n title: resolvedTitle,\n lang: config.lang,\n body,\n data,\n actions,\n htmlAttributes,\n headScripts,\n headLinks,\n metadata,\n clientEntry,\n routerEntry,\n routerEnabled: routerCfg ? routerEnabled : undefined,\n speculation: routerCfg?.speculation,\n renderEndpoint: config.renderEndpoint,\n });\n\n const head = metadata ? buildHeadTags(metadata, resolvedTitle) : \"\";\n return { html, revalidate, clearActionErrorCookie, head, resolvedTitle, cachePolicy, data };\n}\n\n/** Extracts a `metadata` field from a loader data object, if present. */\nfunction extractMetadata(value: unknown): PageMetadata | undefined {\n if (value && typeof value === \"object\" && \"metadata\" in value) {\n const meta = (value as { metadata?: unknown }).metadata;\n if (meta && typeof meta === \"object\") return meta as PageMetadata;\n }\n return undefined;\n}\n\n/** Extracts metadata from the first layout data object that has one. */\nfunction extractMetadataFromList(list: unknown[]): PageMetadata | undefined {\n for (const item of list) {\n const meta = extractMetadata(item);\n if (meta) return meta;\n }\n return undefined;\n}\n\nexport interface RenderErrorPageOptions {\n routes: ScannedRoutes;\n status: 404 | 500;\n error?: unknown;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\" | \"renderEndpoint\" | \"router\" | \"js\">;\n actions?: Record<string, string[]>;\n importer?: (path: string) => Promise<unknown>;\n}\n\nexport async function renderErrorPage(\n options: RenderErrorPageOptions,\n): Promise<{ html: string; status: number } | undefined> {\n const route = options.status === 404 ? options.routes.error404 : options.routes.error500;\n if (!route) return undefined;\n\n try {\n const { html } = await renderPage({\n route,\n params: {},\n searchParams: new URLSearchParams(),\n config: options.config,\n actions: options.actions,\n importer: options.importer,\n });\n return { html, status: options.status };\n } catch (err) {\n console.error(`[render] error ${options.status} page failed`, err);\n return undefined;\n }\n}\n","import { resolve, relative } from \"node:path\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\n\n/**\n * Registry of server actions grouped by page path.\n *\n * The outer key is the page URL path (e.g. \"/contact\"). The inner object maps\n * each exported action name to the absolute file path of the `page.action.ts`\n * module that defines it.\n */\nexport type ActionRegistry = Record<string, Record<string, string>>;\n\n/**\n * Scans `page.action.ts` modules and returns a per-page registry of server actions.\n *\n * Only named function exports are collected; default exports are ignored. The\n * registry is keyed by page URL path so the client can resolve actions scoped\n * to a specific page and avoid name collisions between different routes.\n */\nexport async function scanActions(appDir: string): Promise<ActionRegistry> {\n const routes = await scanRoutes(appDir);\n const actions: ActionRegistry = {};\n\n for (const page of routes.pages) {\n if (!page.actionPath) continue;\n const actionPath = resolve(page.actionPath);\n const mod = (await import(actionPath)) as Record<string, unknown>;\n const pageActions: Record<string, string> = {};\n for (const [name, value] of Object.entries(mod)) {\n if (name === \"default\") continue;\n if (typeof value === \"function\") {\n pageActions[name] = actionPath;\n }\n }\n if (Object.keys(pageActions).length > 0) {\n actions[page.path] = pageActions;\n }\n }\n\n return actions;\n}\n\n/**\n * Return a copy of the action registry where every file path is made relative to\n * the given project root. Useful for serializing actions into the HTML shell\n * without exposing absolute server paths.\n */\nexport function relativeActions(actions: ActionRegistry, root: string): ActionRegistry {\n const result: ActionRegistry = {};\n for (const [page, pageActions] of Object.entries(actions)) {\n const entries: Record<string, string> = {};\n for (const [name, actionPath] of Object.entries(pageActions)) {\n entries[name] = relative(root, actionPath);\n }\n result[page] = entries;\n }\n return result;\n}\n\n/**\n * Return only the names of available actions per page, without file paths.\n * This is the safe format to serialize into the HTML shell: the client only\n * needs to know which actions exist, never where they are implemented.\n */\nexport function actionNames(actions: ActionRegistry): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n for (const [page, pageActions] of Object.entries(actions)) {\n result[page] = Object.keys(pageActions);\n }\n return result;\n}\n","export default {};\nthrow new Error(`Could not resolve \"sharp\" imported by \"@elurjs/kit\". Is it installed?`)","import { readFile, mkdir, writeFile, rename, rm, stat } from \"node:fs/promises\";\nimport { join, dirname, extname, basename, resolve, sep } from \"node:path\";\nimport { createHash, randomBytes } from \"node:crypto\";\nimport type { ImageFormat } from \"./index.js\";\n\n// --- ImageService: metadata-driven image processing and manifest ---\n//\n// * Reads real image dimensions from the source file (sharp metadata).\n// * Generates hashed variant filenames from a SHA-256 transform key that\n// incorporates: content digest + normalized transform options +\n// encoder/service version + output naming version (§4.2).\n// * Applies path containment for sources and outputs (no traversal, no NUL,\n// no symlink escape, no Unicode/separator tricks).\n// * Writes outputs atomically (temp + rename) with single-flight per\n// transform key and a bounded concurrency pool.\n// * Supports `strict` mode: fails the build on missing sources or failed\n// transforms instead of emitting a partially-written variant.\n// * Falls back gracefully when sharp is not installed.\n\nconst ENCODER_VERSION = \"sharp-1\";\nconst NAMING_VERSION = \"v1\";\nconst HASH_LENGTH = 12;\nconst DEFAULT_QUALITY = 80;\nconst DEFAULT_CONCURRENCY = 4;\n\nexport interface ImageVariant {\n /** URL path relative to the site root, e.g. \"/images/hero.abc123def456.800w.webp\". */\n url: string;\n /** Width in pixels. */\n width: number;\n /** Height in pixels (preserves aspect ratio). */\n height: number;\n /** Format of the variant. */\n format: ImageFormat;\n /** File size in bytes. */\n size: number;\n}\n\nexport interface ImageEntry {\n /** Original source URL, e.g. \"/images/hero.jpg\". */\n src: string;\n /** Intrinsic width of the source. */\n width: number;\n /** Intrinsic height of the source. */\n height: number;\n /** All generated variants. */\n variants: ImageVariant[];\n /** Content hash of the source file. */\n hash: string;\n}\n\nexport interface ImageManifest {\n version: 1;\n entries: Record<string, ImageEntry>;\n}\n\nexport interface ProcessOptions {\n /** Absolute path to the public directory (source images). */\n publicDir: string;\n /** Absolute path to the output directory. */\n outDir: string;\n /** Formats to generate. Defaults to [\"webp\", \"avif\"]. */\n formats?: ImageFormat[];\n /** Quality (1-100). Defaults to 80. */\n quality?: number;\n /** Path to write the manifest JSON. */\n manifestPath?: string;\n /** When true, missing sources or failed transforms fail the build. */\n strict?: boolean;\n /** Max concurrent sharp transforms. Defaults to 4. */\n concurrency?: number;\n /** Optional URL base prefix applied to variant URLs. */\n base?: string;\n}\n\nexport interface ProcessResult {\n manifest: ImageManifest;\n /** Number of variants generated. */\n count: number;\n /** Whether sharp was available. */\n optimized: boolean;\n}\n\nlet sharpLoader: (() => Promise<any>) | null | undefined;\n\nasync function loadSharp(): Promise<any | null> {\n if (sharpLoader === null) return null;\n if (sharpLoader) return sharpLoader();\n try {\n // @ts-ignore — `sharp` is an optional peer dependency.\n const mod = await import(\"sharp\");\n const sharp = mod.default;\n if (typeof sharp !== \"function\") {\n sharpLoader = null;\n return null;\n }\n sharpLoader = async () => sharp;\n return sharp;\n } catch {\n sharpLoader = null;\n return null;\n }\n}\n\nexport async function isSharpAvailable(): Promise<boolean> {\n const sharp = await loadSharp();\n return sharp !== null;\n}\n\n// --- Transform identity (§4.2) ---\n\n/**\n * SHA-256 transform key. Stable for identical content+options and invalidated\n * whenever the source bytes, the effective transform options, the encoder\n * version or the naming scheme change.\n */\nexport function transformHash(sourceBuffer: Buffer, width: number, format: ImageFormat, quality: number): string {\n const contentDigest = createHash(\"sha256\").update(sourceBuffer).digest(\"hex\");\n const normalizedOptions = JSON.stringify({\n width,\n format,\n quality,\n withoutEnlargement: true,\n });\n return createHash(\"sha256\")\n .update(`${contentDigest}|${normalizedOptions}|${ENCODER_VERSION}|${NAMING_VERSION}`)\n .digest(\"hex\")\n .slice(0, HASH_LENGTH);\n}\n\n// --- Path containment (§9.5) ---\n\nfunction isSafeRelativePath(value: string): boolean {\n if (value.includes(\"\\0\") || value.includes(\"\\\\\")) return false;\n if (/%[0-9a-f]{2}/i.test(value)) return false;\n const segments = value.replace(/^\\/+/, \"\").split(\"/\");\n return !segments.some((segment) => segment === \"..\" || segment === \".\" || segment === \"\");\n}\n\nfunction isInside(root: string, candidate: string): boolean {\n return candidate === root || candidate.startsWith(`${root}${sep}`);\n}\n\nfunction assertInside(root: string, candidate: string, label: string): void {\n const resolvedRoot = resolve(root);\n const resolvedCandidate = resolve(candidate);\n if (!isInside(resolvedRoot, resolvedCandidate)) {\n throw new Error(`[elur-kit] Image ${label} escapes its allowed root (${resolvedCandidate}).`);\n }\n}\n\n// --- Concurrency: bounded pool + single-flight ---\n\nfunction createPool(limit: number) {\n let active = 0;\n const waiters: Array<() => void> = [];\n const acquire = () =>\n new Promise<void>((resolve) => {\n if (active < limit) {\n active++;\n resolve();\n } else {\n waiters.push(() => {\n active++;\n resolve();\n });\n }\n });\n const release = () => {\n active--;\n const next = waiters.shift();\n if (next) next();\n else if (active < 0) active = 0;\n };\n return {\n async run<T>(fn: () => Promise<T>): Promise<T> {\n await acquire();\n try {\n return await fn();\n } finally {\n release();\n }\n },\n };\n}\n\n// --- Atomic writes (§9.6) ---\n\nasync function atomicWriteFile(path: string, data: Buffer | string): Promise<void> {\n const temp = `${path}.${process.pid}.${randomBytes(6).toString(\"hex\")}.tmp`;\n try {\n await writeFile(temp, data);\n await rename(temp, path);\n } catch (error) {\n await rm(temp, { force: true }).catch(() => { });\n throw error;\n }\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\n// --- Public programmatic API (§3.1 / §3.3) ---\n\nexport interface ImageRequest {\n src: string;\n alt: string;\n widths?: readonly number[];\n formats?: readonly ImageFormat[];\n sizes?: string;\n width?: number;\n height?: number;\n priority?: boolean;\n loading?: \"lazy\" | \"eager\";\n decoding?: \"async\" | \"sync\" | \"auto\";\n quality?: number;\n fit?: string;\n class?: string;\n attributes?: Record<string, unknown>;\n}\n\nexport interface GeneratedImage {\n url: string;\n width: number;\n height: number;\n format: ImageFormat;\n size: number;\n}\n\nexport interface ImageMetadata {\n src: string;\n width?: number;\n height?: number;\n sources: Array<{ type: string; srcset: string }>;\n attributes: Record<string, string | number | boolean | undefined>;\n generated: readonly GeneratedImage[];\n}\n\nexport interface ImageServiceContext {\n publicDir: string;\n outDir: string;\n manifest: ImageManifest;\n}\n\nexport interface ImageServiceCapabilities {\n /** Whether the encoder (sharp) is available. */\n encoding: boolean;\n /** Whether remote images can be fetched. */\n remote: boolean;\n /** Whether a runtime image endpoint exists. */\n runtimeEndpoint: boolean;\n /** Whether the host exposes a writable filesystem. */\n filesystem: boolean;\n}\n\nexport interface ImageService {\n resolve(request: ImageRequest, context: ImageServiceContext): Promise<ImageMetadata>;\n capabilities: ImageServiceCapabilities;\n}\n\n/**\n * Creates a build-time ImageService bound to a public/output directory pair.\n */\nexport function createImageService(options: ProcessOptions): ImageService {\n return {\n capabilities: {\n encoding: false,\n remote: false,\n runtimeEndpoint: false,\n filesystem: true,\n },\n async resolve(request, context) {\n return getImage(request, { ...options, publicDir: context.publicDir, outDir: context.outDir });\n },\n };\n}\n\n/**\n * Programmatic async image API (§3.1). Ensures the requested variants exist on\n * disk (build-time), then returns deterministic metadata (not opaque markup).\n */\nexport async function getImage(\n request: ImageRequest,\n options: ProcessOptions,\n): Promise<ImageMetadata> {\n const { src, alt, widths, formats, quality, priority, loading, decoding, class: className, attributes = {} } = request;\n const targetWidths = widths?.length ? [...widths] : [request.width ?? 0];\n const targetFormats = formats?.length ? [...formats] : options.formats ?? [\"webp\", \"avif\"];\n const result = await processImageBatch(\n [{ src, widths: targetWidths, formats: targetFormats }],\n { ...options, quality: quality ?? options.quality },\n );\n const entry = result.manifest.entries[src];\n const generated: GeneratedImage[] = entry\n ? entry.variants.map((v) => ({ url: v.url, width: v.width, height: v.height, format: v.format, size: v.size }))\n : [];\n\n const sources: ImageMetadata[\"sources\"] = [];\n for (const format of targetFormats) {\n const srcset = entry ? buildSrcset(entry, format) : \"\";\n if (srcset) sources.push({ type: format === \"jpeg\" ? \"image/jpeg\" : `image/${format}`, srcset });\n }\n\n return {\n src,\n width: entry?.width,\n height: entry?.height,\n sources,\n attributes: {\n alt,\n width: entry?.width ?? request.width,\n height: entry?.height ?? request.height,\n loading: priority ? \"eager\" : (loading ?? \"lazy\"),\n decoding: decoding ?? \"async\",\n ...(priority ? { fetchpriority: \"high\" } : {}),\n ...(className ? { class: className } : {}),\n ...attributes,\n },\n generated,\n };\n}\n\n// --- Batch processing ---\n\nexport async function processImageBatch(\n images: { src: string; widths: number[]; formats?: ImageFormat[] }[],\n options: ProcessOptions,\n): Promise<ProcessResult> {\n const sharp = await loadSharp();\n const {\n publicDir,\n outDir,\n formats = [\"webp\", \"avif\"],\n quality = DEFAULT_QUALITY,\n strict = false,\n concurrency = DEFAULT_CONCURRENCY,\n base = \"\",\n } = options;\n const entries: Record<string, ImageEntry> = {};\n let count = 0;\n const pool = createPool(concurrency);\n const inFlight = new Map<string, Promise<void>>();\n\n const warned = new Set<string>();\n const warnOnce = (key: string, message: string): void => {\n if (warned.has(key)) return;\n warned.add(key);\n console.warn(`[elur-kit] ${message}`);\n };\n\n if (!sharp) {\n // Without sharp, build a manifest with only the original source entries.\n for (const { src } of images) {\n if (entries[src]) continue;\n if (!isSafeRelativePath(src)) {\n if (strict) throw new Error(`[elur-kit] Invalid image source path: ${src}`);\n warnOnce(`path:${src}`, `Skipping invalid image source path: ${src}`);\n continue;\n }\n const sourcePath = join(publicDir, src.replace(/^\\//, \"\"));\n assertInside(publicDir, sourcePath, `source \"${src}\"`);\n try {\n const buffer = await readFile(sourcePath);\n entries[src] = {\n src,\n width: 0,\n height: 0,\n variants: [],\n hash: createHash(\"sha256\").update(buffer).digest(\"hex\").slice(0, 8),\n };\n } catch (error) {\n if (strict) throw new Error(`[elur-kit] Image source not found: ${src}`);\n warnOnce(`missing:${src}`, `Image source not found: ${src}. Skipping.`);\n }\n }\n const manifest: ImageManifest = { version: 1, entries };\n if (options.manifestPath) await writeManifest(options.manifestPath, manifest);\n return { manifest, count: 0, optimized: false };\n }\n\n for (const { src, widths, formats: imgFormats } of images) {\n if (entries[src]) continue;\n\n if (!isSafeRelativePath(src)) {\n if (strict) throw new Error(`[elur-kit] Invalid image source path: ${src}`);\n warnOnce(`path:${src}`, `Skipping invalid image source path: ${src}`);\n continue;\n }\n\n const sourcePath = join(publicDir, src.replace(/^\\//, \"\"));\n assertInside(publicDir, sourcePath, `source \"${src}\"`);\n\n let sourceBuffer: Buffer;\n try {\n sourceBuffer = await readFile(sourcePath);\n } catch (error) {\n if (strict) throw new Error(`[elur-kit] Image source not found: ${src}`);\n warnOnce(`missing:${src}`, `Image not found: ${src}. Skipping.`);\n continue;\n }\n\n const ext = extname(src);\n const safeBase = basename(src, ext).replace(/[^a-zA-Z0-9._-]+/g, \"-\");\n const dir = dirname(src);\n const targetFormats = imgFormats?.length ? imgFormats : formats;\n\n // Read real metadata from the source.\n let sourceWidth = 0;\n let sourceHeight = 0;\n try {\n const meta = await sharp(sourceBuffer).metadata();\n sourceWidth = meta.width ?? 0;\n sourceHeight = meta.height ?? 0;\n } catch {\n // Fallback: no metadata.\n }\n\n const variants: ImageVariant[] = [];\n\n const processVariant = async (width: number, format: ImageFormat): Promise<void> => {\n // Never upscale: skip widths larger than the source.\n if (sourceWidth > 0 && width > sourceWidth) return;\n\n const hash = transformHash(sourceBuffer, width, format, quality);\n const variantName = `${safeBase}.${hash}.${width}w.${format}`;\n const variantRelPath = join(dir, variantName);\n const variantAbsPath = join(outDir, variantRelPath.replace(/^\\//, \"\"));\n assertInside(outDir, variantAbsPath, `variant \"${variantRelPath}\"`);\n const variantUrl = `${base.replace(/\\/$/, \"\")}/${variantRelPath.replace(/\\\\/g, \"/\").replace(/^\\//, \"\")}`;\n\n // Reuse an existing, valid output file (validated, not guessed).\n if (await fileExists(variantAbsPath)) {\n try {\n const info = await sharp(variantAbsPath).metadata();\n variants.push({\n url: variantUrl,\n width: info.width ?? width,\n height: info.height ?? Math.round((info.height ?? 0) || (sourceHeight && sourceWidth ? (width * sourceHeight) / sourceWidth : 0)),\n format,\n size: (await stat(variantAbsPath)).size,\n });\n count++;\n return;\n } catch {\n // Existing file invalid — regenerate below.\n }\n }\n\n const key = variantAbsPath;\n if (inFlight.has(key)) {\n await inFlight.get(key);\n variants.push({\n url: variantUrl,\n width,\n height: Math.round(sourceHeight && sourceWidth ? (width * sourceHeight) / sourceWidth : 0),\n format,\n size: (await stat(variantAbsPath)).size,\n });\n count++;\n return;\n }\n\n const task = (async () => {\n try {\n const buffer = await sharp(sourceBuffer)\n .resize({ width, withoutEnlargement: true })\n .toFormat(format, { quality })\n .toBuffer();\n await mkdir(dirname(variantAbsPath), { recursive: true });\n await atomicWriteFile(variantAbsPath, buffer);\n } catch (error) {\n if (strict) throw new Error(`[elur-kit] Failed to generate ${variantName}: ${error instanceof Error ? error.message : String(error)}`);\n warnOnce(`fail:${variantName}`, `Failed to generate ${variantName}.`);\n return;\n }\n variants.push({\n url: variantUrl,\n width,\n height: Math.round(sourceHeight && sourceWidth ? (width * sourceHeight) / sourceWidth : 0),\n format,\n size: (await stat(variantAbsPath)).size,\n });\n count++;\n })().finally(() => inFlight.delete(key));\n\n inFlight.set(key, task);\n await pool.run(() => task);\n };\n\n const tasks: Promise<void>[] = [];\n for (const width of widths) {\n for (const format of targetFormats) {\n tasks.push(processVariant(width, format));\n }\n }\n await Promise.all(tasks);\n\n entries[src] = {\n src,\n width: sourceWidth,\n height: sourceHeight,\n variants,\n hash: createHash(\"sha256\").update(sourceBuffer).digest(\"hex\").slice(0, 8),\n };\n }\n\n const manifest: ImageManifest = { version: 1, entries };\n if (options.manifestPath) await writeManifest(options.manifestPath, manifest);\n return { manifest, count, optimized: true };\n}\n\n/**\n * Read a manifest from disk, or return an empty one if it doesn't exist.\n */\nexport async function readManifest(path: string): Promise<ImageManifest> {\n try {\n const data = await readFile(path, \"utf8\");\n return JSON.parse(data) as ImageManifest;\n } catch {\n return { version: 1, entries: {} };\n }\n}\n\n/**\n * Write a manifest to disk atomically.\n */\nexport async function writeManifest(path: string, manifest: ImageManifest): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await atomicWriteFile(path, JSON.stringify(manifest, null, 2));\n}\n\n/**\n * Look up an image entry in the manifest by its source URL.\n */\nexport function getManifestEntry(manifest: ImageManifest, src: string): ImageEntry | undefined {\n return manifest.entries[src];\n}\n\n/**\n * Build a srcset string from manifest variants of a given format.\n * Returns e.g. \"/images/hero.abc.400w.webp 400w, /images/hero.abc.800w.webp 800w\".\n */\nexport function buildSrcset(entry: ImageEntry, format: ImageFormat): string {\n return entry.variants\n .filter((v) => v.format === format)\n .map((v) => `${v.url} ${v.width}w`)\n .join(\", \");\n}\n\n/**\n * Build the full <picture> markup for an image entry, with <source> per format\n * and a fallback <img>.\n */\nexport function buildPictureMarkup(entry: ImageEntry, opts: {\n alt: string;\n sizes?: string;\n priority?: boolean;\n class?: string;\n attributes?: Record<string, string>;\n fallbackSrc?: string;\n fallbackWidth?: number;\n fallbackHeight?: number;\n}): string {\n const {\n alt,\n sizes,\n priority = false,\n class: className,\n attributes = {},\n fallbackSrc = entry.src,\n fallbackWidth = entry.width,\n fallbackHeight = entry.height,\n } = opts;\n\n const formats = [...new Set(entry.variants.map((v) => v.format))];\n const loadingAttr = priority ? \"\" : ' loading=\"lazy\"';\n const fetchPriorityAttr = priority ? ' fetchpriority=\"high\"' : \"\";\n const sizesAttr = sizes ? ` sizes=\"${escapeAttr(sizes)}\"` : \"\";\n const classAttr = className ? ` class=\"${escapeAttr(className)}\"` : \"\";\n const extraAttrs = Object.entries(attributes)\n .map(([key, value]) => ` ${escapeAttr(key)}=\"${escapeAttr(String(value))}\"`)\n .join(\"\");\n\n const sources = formats\n .map((format) => {\n const srcset = buildSrcset(entry, format);\n if (!srcset) return \"\";\n const type = format === \"jpeg\" ? \"image/jpeg\" : `image/${format}`;\n return `<source srcset=\"${srcset}\"${sizesAttr} type=\"${type}\" />`;\n })\n .filter(Boolean)\n .join(\"\");\n\n const img = `<img src=\"${escapeAttr(fallbackSrc)}\" alt=\"${escapeAttr(alt)}\" width=\"${fallbackWidth}\" height=\"${fallbackHeight}\"${loadingAttr} decoding=\"async\"${fetchPriorityAttr}${classAttr}${extraAttrs} />`;\n\n return sources ? `<picture>${sources}${img}</picture>` : img;\n}\n\n/**\n * Validate that every variant URL in the manifest corresponds to a real file\n * in the output directory. Returns a list of missing URLs.\n */\nexport async function validateManifestUrls(\n manifest: ImageManifest,\n outDir: string,\n): Promise<string[]> {\n const missing: string[] = [];\n for (const entry of Object.values(manifest.entries)) {\n for (const variant of entry.variants) {\n const relative = variant.url.replace(/^\\/+/, \"\");\n const resolved = resolve(outDir, relative);\n if (!isInside(resolve(outDir), resolved)) {\n missing.push(variant.url);\n continue;\n }\n try {\n await stat(resolved);\n } catch {\n missing.push(variant.url);\n }\n }\n }\n return missing;\n}\n\nfunction escapeAttr(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n","export interface ElurKitIntegrationContext {\n root: string;\n command: \"dev\" | \"build\" | \"preview\" | \"start\" | \"check\" | \"routes\" | \"doctor\";\n}\n\nexport interface ElurKitIntegration {\n name: string;\n config?(config: Record<string, unknown>, context: ElurKitIntegrationContext): void | Promise<void>;\n routes?(manifest: unknown, context: ElurKitIntegrationContext): void | Promise<void>;\n request?(request: Request, context: ElurKitIntegrationContext): void | Response | Promise<void | Response>;\n render?(result: { html: string }, context: ElurKitIntegrationContext): void | Promise<void>;\n build?(result: unknown, context: ElurKitIntegrationContext): void | Promise<void>;\n clientEntry?(source: string, context: ElurKitIntegrationContext): string | void | Promise<string | void>;\n error?(error: unknown, context: ElurKitIntegrationContext): void | Promise<void>;\n}\n\nexport async function runIntegrationHook<K extends keyof Omit<ElurKitIntegration, \"name\">>(\n integrations: readonly ElurKitIntegration[],\n hook: K,\n args: Parameters<NonNullable<ElurKitIntegration[K]>>,\n): Promise<void> {\n for (const integration of integrations) {\n const handler = integration[hook];\n if (typeof handler === \"function\") await (handler as (...values: unknown[]) => unknown)(...args);\n }\n}\n\n// Typed integration hooks for optional packages (plan §11.6).\nexport {\n type I18nIntegration,\n type AuthIntegration,\n type QueryIntegration,\n type TestingIntegration,\n registerIntegration,\n getI18nIntegration,\n getAuthIntegration,\n getQueryIntegration,\n getTestingIntegration,\n getCustomIntegrations,\n clearIntegrations,\n} from \"./hooks.js\";\n","/**\n * SEO utilities — sitemap.xml and robots.txt generation.\n *\n * @module\n */\n\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\n\n// Sitemap generation from the scanned route manifest (wired into `build`).\nexport { generateSitemapFromRoutes, type SitemapFromRoutesOptions } from \"./sitemap-from-routes.js\";\n\n// Types\n\nexport interface SitemapEntry {\n /** URL path, e.g. \"/docs/getting-started/introduction\". */\n url: string;\n /** Last modification date (ISO 8601 or YYYY-MM-DD). */\n lastmod?: string;\n /** Change frequency: always, hourly, daily, weekly, monthly, yearly, never. */\n changefreq?: \"always\" | \"hourly\" | \"daily\" | \"weekly\" | \"monthly\" | \"yearly\" | \"never\";\n /** Priority 0.0–1.0. */\n priority?: number;\n}\n\nexport interface SitemapConfig {\n /** Base URL of the site, e.g. \"https://example.com\". */\n siteUrl: string;\n /** List of URL entries to include in the sitemap. */\n urls: (SitemapEntry | string)[];\n /** Output directory where sitemap.xml will be written. */\n outDir: string;\n}\n\nexport interface RobotsConfig {\n /** Base URL of the site, e.g. \"https://example.com\". */\n siteUrl: string;\n /** Output directory where robots.txt will be written. */\n outDir: string;\n /** Rules for specific user agents. */\n rules?: RobotsRule[];\n /** Paths to disallow for all crawlers (shorthand for rules). */\n disallow?: string[];\n /** Sitemap URL override. If not set, defaults to `${siteUrl}/sitemap.xml`. */\n sitemapUrl?: string;\n}\n\nexport interface RobotsRule {\n /** User-agent, e.g. \"Googlebot\" or \"*\" for all. */\n userAgent: string;\n /** Paths to disallow. */\n disallow?: string[];\n /** Paths to allow. */\n allow?: string[];\n /** Crawl delay in seconds. */\n crawlDelay?: number;\n}\n\n// Sitemap generation\n\n/**\n * Generates a `sitemap.xml` file from a list of URLs.\n *\n * @example\n * ```ts\n * import { generateSitemap } from \"@elurjs/kit/seo\";\n *\n * await generateSitemap({\n * siteUrl: \"https://elur-kit.dev\",\n * outDir: \"./dist\",\n * urls: [\n * \"/\",\n * \"/docs/introduction\",\n * { url: \"/docs/routing\", changefreq: \"weekly\", priority: 0.8 },\n * ],\n * });\n * ```\n */\nexport async function generateSitemap(config: SitemapConfig): Promise<string> {\n const { siteUrl, urls, outDir } = config;\n const base = siteUrl.replace(/\\/$/, \"\");\n\n const entries: string[] = urls.map((entry) => {\n const e = typeof entry === \"string\" ? { url: entry } : entry;\n const loc = `${base}${e.url.startsWith(\"/\") ? \"\" : \"/\"}${e.url}`;\n const lines = [` <url>`, ` <loc>${escapeXml(loc)}</loc>`];\n if (e.lastmod) lines.push(` <lastmod>${e.lastmod}</lastmod>`);\n if (e.changefreq) lines.push(` <changefreq>${e.changefreq}</changefreq>`);\n if (e.priority !== undefined) lines.push(` <priority>${e.priority.toFixed(1)}</priority>`);\n lines.push(` </url>`);\n return lines.join(\"\\n\");\n });\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${entries.join(\"\\n\")}\n</urlset>\n`;\n\n const filePath = join(outDir, \"sitemap.xml\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, xml, \"utf8\");\n return filePath;\n}\n\n// Robots.txt generation\n\n/**\n * Generates a `robots.txt` file.\n *\n * @example\n * ```ts\n * import { generateRobots } from \"@elurjs/kit/seo\";\n *\n * await generateRobots({\n * siteUrl: \"https://elur-kit.dev\",\n * outDir: \"./dist\",\n * disallow: [\"/api/\", \"/_elur/\"],\n * });\n * ```\n */\nexport async function generateRobots(config: RobotsConfig): Promise<string> {\n const { siteUrl, outDir, rules, disallow, sitemapUrl } = config;\n const base = siteUrl.replace(/\\/$/, \"\");\n const lines: string[] = [];\n\n if (rules && rules.length > 0) {\n for (const rule of rules) {\n lines.push(`User-agent: ${rule.userAgent}`);\n if (rule.allow) {\n for (const path of rule.allow) lines.push(`Allow: ${path}`);\n }\n if (rule.disallow) {\n for (const path of rule.disallow) lines.push(`Disallow: ${path}`);\n }\n if (rule.crawlDelay !== undefined) {\n lines.push(`Crawl-delay: ${rule.crawlDelay}`);\n }\n lines.push(\"\");\n }\n } else {\n lines.push(\"User-agent: *\");\n if (disallow && disallow.length > 0) {\n for (const path of disallow) lines.push(`Disallow: ${path}`);\n } else {\n lines.push(\"Disallow:\");\n }\n lines.push(\"\");\n }\n\n const sitemap = sitemapUrl ?? `${base}/sitemap.xml`;\n lines.push(`Sitemap: ${sitemap}`);\n\n const content = lines.join(\"\\n\") + \"\\n\";\n const filePath = join(outDir, \"robots.txt\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, content, \"utf8\");\n return filePath;\n}\n\n// JSON-LD / Structured data\n\nexport interface JsonLdSchema {\n [key: string]: unknown;\n}\n\n/**\n * Serializes a JSON-LD structured data object into a `<script type=\"application/ld+json\">` tag.\n *\n * @example\n * ```ts\n * import { jsonLd } from \"@elurjs/kit/seo\";\n *\n * const schema = jsonLd({\n * \"@context\": \"https://schema.org\",\n * \"@type\": \"TechArticle\",\n * headline: \"Routing\",\n * author: { \"@type\": \"Person\", name: \"Deiver Vasquez\" },\n * });\n * // Returns: <script type=\"application/ld+json\">{...}</script>\n * ```\n */\nexport function jsonLd(schema: JsonLdSchema | JsonLdSchema[]): string {\n const data = JSON.stringify(Array.isArray(schema) ? schema : schema);\n // Escape sequences that could close the <script> tag or introduce markup.\n // Per the HTML spec, inside a <script> block the only dangerous sequence\n // is \"</script\" (case-insensitive). We also escape \"<\" more broadly to\n // prevent any interpreter from seeing markup-like content, and escape\n // \"<!--\" to prevent HTML comment-based escapes.\n const safe = data\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/&/g, \"\\\\u0026\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n return `<script type=\"application/ld+json\">${safe}</script>`;\n}\n\n// Helpers\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n","// --- Sitemap generation from route manifest (plan §11.3) ---\n//\n// Generates a sitemap.xml from the scanned routes, excluding:\n// - API routes\n// - Dynamic routes (they require data to generate URLs)\n// - Error pages (404, 500)\n// - Routes with noindex metadata\n//\n// For dynamic routes, the author should provide a `generateSitemapUrls()`\n// function in their page.data.ts that returns concrete URLs.\n//\n// Supports large sitemaps via sitemap index files (split at 50,000 URLs).\n\nimport type { ScannedRoutes } from \"../router/route-scanner.js\";\nimport { generateSitemap, type SitemapEntry } from \"./index.js\";\n\nexport interface SitemapFromRoutesOptions {\n siteUrl: string;\n outDir: string;\n routes: ScannedRoutes;\n /** Additional URLs to include (e.g. from dynamic routes). */\n extraUrls?: (SitemapEntry | string)[];\n /** Max URLs per sitemap file. Default: 50000. */\n maxUrlsPerSitemap?: number;\n /** Default changefreq for routes. */\n defaultChangefreq?: SitemapEntry[\"changefreq\"];\n /** Default priority for routes. */\n defaultPriority?: number;\n}\n\n/**\n * Generates a sitemap.xml from the route manifest.\n *\n * Static routes are included automatically. Dynamic routes require the author\n * to provide URLs via `extraUrls` or a `generateSitemapUrls()` export.\n *\n * For large sites (>50,000 URLs), a sitemap index is generated.\n */\nexport async function generateSitemapFromRoutes(\n options: SitemapFromRoutesOptions,\n): Promise<string[]> {\n const { siteUrl, outDir, routes, extraUrls = [], maxUrlsPerSitemap = 50000 } = options;\n\n // Collect static route URLs.\n const routeUrls: SitemapEntry[] = [];\n for (const page of routes.pages) {\n // Skip dynamic routes (they have params).\n if (page.params.length > 0) continue;\n // Skip error pages.\n if (page.path === \"/404\" || page.path === \"/500\") continue;\n // Skip internal namespaces.\n if (page.path.startsWith(\"/_elur\") || page.path.startsWith(\"/__elur-js\")) continue;\n\n routeUrls.push({\n url: page.path,\n changefreq: options.defaultChangefreq,\n priority: options.defaultPriority,\n });\n }\n\n // Merge with extra URLs.\n const allUrls = [...routeUrls, ...extraUrls];\n\n // If under the limit, generate a single sitemap.\n if (allUrls.length <= maxUrlsPerSitemap) {\n const path = await generateSitemap({ siteUrl, outDir, urls: allUrls });\n return [path];\n }\n\n // For large sitemaps, split into multiple files with an index.\n return generateSitemapIndex({ siteUrl, outDir, urls: allUrls, maxUrlsPerSitemap });\n}\n\n/**\n * Generates a sitemap index file that references multiple sitemap files.\n * Used for large sites (>50,000 URLs).\n */\nasync function generateSitemapIndex(\n options: { siteUrl: string; outDir: string; urls: (SitemapEntry | string)[]; maxUrlsPerSitemap: number },\n): Promise<string[]> {\n const { siteUrl, outDir, urls, maxUrlsPerSitemap } = options;\n const base = siteUrl.replace(/\\/$/, \"\");\n const files: string[] = [];\n const sitemapUrls: string[] = [];\n\n // Split URLs into chunks.\n for (let i = 0; i < urls.length; i += maxUrlsPerSitemap) {\n const chunk = urls.slice(i, i + maxUrlsPerSitemap);\n const filename = `sitemap-${Math.floor(i / maxUrlsPerSitemap) + 1}.xml`;\n const { writeFile, mkdir } = await import(\"node:fs/promises\");\n const { join, dirname } = await import(\"node:path\");\n\n // Generate the chunk sitemap.\n const entries = chunk.map((entry) => {\n const e = typeof entry === \"string\" ? { url: entry } : entry;\n const loc = `${base}${e.url.startsWith(\"/\") ? \"\" : \"/\"}${e.url}`;\n const lines = [` <url>`, ` <loc>${escapeXml(loc)}</loc>`];\n if (e.lastmod) lines.push(` <lastmod>${e.lastmod}</lastmod>`);\n if (e.changefreq) lines.push(` <changefreq>${e.changefreq}</changefreq>`);\n if (e.priority !== undefined) lines.push(` <priority>${e.priority.toFixed(1)}</priority>`);\n lines.push(` </url>`);\n return lines.join(\"\\n\");\n });\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${entries.join(\"\\n\")}\\n</urlset>\\n`;\n const filePath = join(outDir, filename);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, xml, \"utf8\");\n files.push(filePath);\n sitemapUrls.push(`${base}/${filename}`);\n }\n\n // Generate the index file.\n const { writeFile, mkdir } = await import(\"node:fs/promises\");\n const { join, dirname } = await import(\"node:path\");\n\n const indexEntries = sitemapUrls.map((url) => ` <sitemap>\\n <loc>${escapeXml(url)}</loc>\\n </sitemap>`).join(\"\\n\");\n const indexXml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${indexEntries}\\n</sitemapindex>\\n`;\n const indexPath = join(outDir, \"sitemap.xml\");\n await mkdir(dirname(indexPath), { recursive: true });\n await writeFile(indexPath, indexXml, \"utf8\");\n files.push(indexPath);\n\n return files;\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n","import { cp, mkdir, stat, writeFile } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { scanRoutes, type PageRoute, type ScannedRoutes } from \"../router/route-scanner.js\";\nimport { scanIslands, type IslandModule } from \"../island/scan.js\";\nimport { generateClientEntry } from \"../island/generate-entry.js\";\nimport { renderPage, renderErrorPage } from \"../ssr/render.js\";\nimport { scanActions, actionNames } from \"../action/scan.js\";\nimport { consumeImageRegistry, setImageManifest, type ImageFormat } from \"../image/index.js\";\nimport { processImageBatch, type ImageManifest } from \"../image/service.js\";\nimport { runIntegrationHook, type ElurKitIntegration } from \"../integrations/index.js\";\nimport { generateSitemapFromRoutes } from \"../seo/sitemap-from-routes.js\";\nimport type { RouteParams, GenerateStaticParams } from \"../types.js\";\n\nexport interface BuildConfig {\n /** Absolute path to the app directory (e.g. /project/src/app). */\n appDir: string;\n /** Absolute path to the output directory (e.g. /project/dist). */\n outDir: string;\n /** Absolute path to the project root (e.g. /project). When provided, action\n * paths in the serialized HTML shell are made relative to this root. */\n root?: string;\n /** Base path for the client entry module, e.g. \"/_elur/entry-client.js\". */\n clientEntry?: string;\n /** Default language for the HTML shell. */\n lang?: string;\n /**\n * Absolute path to the islands directory (e.g. /project/src/islands).\n * When set, `build` scans it and generates a client entry module listing\n * every island so you don't have to maintain `entry-client.ts` by hand.\n */\n islandsDir?: string;\n /**\n * Absolute path where the generated client entry module is written\n * (e.g. /project/.elur/entry-client.ts). Required when `islandsDir` is set.\n */\n generatedEntry?: string;\n /**\n * Import specifier the generated entry uses for `hydrateIslands`.\n * Defaults to the published subpath `@elurjs/kit/island`.\n */\n hydrateImport?: string;\n /**\n * Import specifier the generated entry uses for `startClientRouter`.\n * Defaults to the published subpath `@elurjs/kit/router`.\n */\n routerImport?: string;\n /** Absolute path to the public directory for static assets (optional). */\n publicDir?: string;\n /** Image formats to generate when sharp is available. Defaults to [\"webp\", \"avif\"]. */\n imageFormats?: ImageFormat[];\n /**\n * Whether the SSR render endpoint (`/__elur-js/render`) exists at runtime.\n * Defaults to `true` (dev, preview and SSR deployments). Set to `false` for\n * fully static outputs so the emitted HTML tells the client router to skip\n * the endpoint (no 404 storms on static hosts like Vercel).\n */\n renderEndpoint?: boolean;\n /**\n * Client router options (Fase 8.3 + §9). `enabled`/`prefetch`/`morph`/\n * `loadingIndicator` are baked into the generated entry; `separate` makes\n * the router its own generated module (emitted as its own chunk when the\n * client bundle declares it as an input) so pages without islands only\n * load `router.js`; `entry` is that chunk's public URL; `speculation`\n * emits a Speculation Rules block on static pages.\n */\n router?: {\n enabled?: boolean;\n prefetch?: boolean;\n morph?: boolean;\n loadingIndicator?: boolean;\n speculation?: \"prefetch\" | \"prerender\";\n /** Generate a standalone router module next to the client entry. */\n separate?: boolean;\n /** Public URL of the router chunk (default: \"/_elur/router.js\"). */\n entry?: string;\n /** Path of the generated router module (default: sibling \"router.ts\"). */\n outFile?: string;\n };\n /**\n * Client JS emission mode: `\"modern\"` gates the entry per page (0% JS);\n * `\"legacy\"` emits the combined entry unconditionally on every page.\n */\n js?: \"modern\" | \"legacy\";\n /**\n * Public site URL (e.g. \"https://example.com\"). When set, the build\n * generates `sitemap.xml` from the scanned routes automatically, unless\n * one already exists in the output (from `public/` or an integration).\n */\n site?: string;\n /**\n * Integrations to invoke during the build lifecycle. When provided, the\n * `build` hook fires after all pages and image variants are generated,\n * giving integrations a chance to write post-build artifacts (sitemaps,\n * robots.txt, search indexes, etc.) into the output directory.\n */\n integrations?: ElurKitIntegration[];\n /**\n * Optional observer invoked once per build phase with its duration in\n * milliseconds (\"scan\", \"pages\", \"images\", \"integrations\", \"sitemap\").\n * Phases that don't run (no images, no integrations, no site URL) are not\n * reported. Used by the CLI to render progress; the build itself stays\n * silent.\n */\n onPhase?: (name: string, durationMs: number) => void;\n}\n\nexport interface BuildResult {\n /** Number of static HTML pages generated. */\n pages: number;\n /** Paths that were skipped because they are dynamic without a static param list. */\n skipped: string[];\n /** Absolute paths to the generated HTML files. */\n files: string[];\n /** Islands discovered when `islandsDir` is set. */\n islands: IslandModule[];\n /** Absolute path to the generated client entry, if one was written. */\n generatedEntry?: string;\n /** Number of image variants generated (0 if sharp is not installed). */\n imagesProcessed: number;\n /** Absolute path to the output directory where build artifacts were written.\n * When called via the CLI, this is the atomic staging directory (not the\n * final `dist/`). Integration `build` hooks should write post-build\n * artifacts here so they survive the atomic swap. */\n outDir: string;\n}\n\nfunction urlToFilePath(outDir: string, urlPath: string): string {\n if (urlPath === \"/\") {\n return join(outDir, \"index.html\");\n }\n\n const segments = urlPath.slice(1).split(\"/\");\n return join(outDir, ...segments, \"index.html\");\n}\n\nfunction isDynamic(path: string): boolean {\n return path.includes(\":\");\n}\n\nfunction buildConcreteUrl(path: string, params: RouteParams): string {\n return path.replace(/:([a-zA-Z0-9_]+)(\\*)?/g, (_, name, catchAll) => {\n const value = params[name];\n if (value === undefined || value === null) {\n throw new Error(\n `Missing value for dynamic segment \"${name}\" in path \"${path}\"`,\n );\n }\n if (catchAll) {\n return Array.isArray(value) ? value.join(\"/\") : String(value);\n }\n return String(value);\n });\n}\n\n/**\n * Builds a static site from a scanned route tree.\n *\n * @param config Build configuration.\n * @returns Summary of generated files.\n */\nexport async function build(config: BuildConfig): Promise<BuildResult> {\n if (config.publicDir) {\n try {\n if ((await stat(config.publicDir)).isDirectory()) {\n await mkdir(config.outDir, { recursive: true });\n await cp(config.publicDir, config.outDir, { recursive: true, force: true });\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n }\n\n const reportPhase = (name: string, start: number): void => {\n config.onPhase?.(name, performance.now() - start);\n };\n\n let phaseStart = performance.now();\n const routes = await scanRoutes(config.appDir);\n const actions = await scanActions(config.appDir);\n reportPhase(\"scan\", phaseStart);\n // Only action names are serialized into the HTML shell; full paths stay on the server.\n const publicActions = actionNames(actions);\n const result: BuildResult = { pages: 0, skipped: [], files: [], islands: [], imagesProcessed: 0, outDir: config.outDir };\n\n // Scan islands and generate the client entry before rendering pages, so the\n // hydration bundle stays in sync with what the app actually uses.\n if (config.islandsDir) {\n result.islands = await scanIslands(config.islandsDir);\n }\n\n if (config.generatedEntry) {\n result.generatedEntry = await generateClientEntry({\n islands: result.islands,\n outFile: config.generatedEntry,\n hydrateImport: config.hydrateImport,\n routerImport: config.routerImport,\n router: config.router\n ? {\n enabled: config.router.enabled !== false,\n prefetch: config.router.prefetch,\n morph: config.router.morph,\n loadingIndicator: config.router.loadingIndicator,\n separate: config.router.separate === true && config.js !== \"legacy\",\n outFile: config.router.outFile,\n }\n : undefined,\n });\n }\n\n phaseStart = performance.now();\n for (const route of routes.pages) {\n if (!isDynamic(route.path)) {\n const filePath = await buildPage(config, route, publicActions);\n result.pages++;\n result.files.push(filePath);\n continue;\n }\n\n const dynamicFiles = await buildDynamicPages(config, route, publicActions);\n if (dynamicFiles.length === 0) {\n result.skipped.push(route.path);\n } else {\n result.pages += dynamicFiles.length;\n result.files.push(...dynamicFiles);\n }\n }\n\n // Generate static 404 and 500 error pages when they exist.\n const errorConfig = {\n lang: config.lang,\n clientEntry: config.clientEntry,\n renderEndpoint: false,\n router: pageRouterConfig(config),\n js: config.js,\n };\n if (routes.error404) {\n const result404 = await renderErrorPage({\n routes,\n status: 404,\n config: errorConfig,\n actions: publicActions,\n });\n if (result404) {\n const filePath = join(config.outDir, \"404.html\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, result404.html, \"utf8\");\n result.files.push(filePath);\n }\n }\n\n if (routes.error500) {\n const result500 = await renderErrorPage({\n routes,\n status: 500,\n config: errorConfig,\n actions: publicActions,\n });\n if (result500) {\n const filePath = join(config.outDir, \"500.html\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, result500.html, \"utf8\");\n result.files.push(filePath);\n }\n }\n reportPhase(\"pages\", phaseStart);\n\n // Process registered images with the ImageService (if sharp is installed).\n // This is a two-pass process:\n // 1. First render pass registers all images (already done above).\n // 2. Process registered images → produce manifest.\n // 3. If variants were generated, set the manifest and re-render pages\n // so the markup uses real <picture>/<source> with hashed URLs.\n const registeredImages = consumeImageRegistry();\n let manifest: ImageManifest | null = null;\n if (registeredImages.length > 0 && config.publicDir) {\n phaseStart = performance.now();\n const manifestPath = join(config.outDir, \".elur\", \"image-manifest.json\");\n const processResult = await processImageBatch(registeredImages, {\n publicDir: config.publicDir,\n outDir: config.outDir,\n formats: config.imageFormats,\n manifestPath,\n });\n result.imagesProcessed = processResult.count;\n\n if (processResult.optimized && processResult.count > 0) {\n manifest = processResult.manifest;\n setImageManifest(manifest);\n\n // Re-render all pages with the manifest so image() emits <picture>.\n result.pages = 0;\n result.files = [];\n for (const route of routes.pages) {\n if (!isDynamic(route.path)) {\n const filePath = await buildPage(config, route, publicActions);\n result.pages++;\n result.files.push(filePath);\n continue;\n }\n const dynamicFiles = await buildDynamicPages(config, route, publicActions);\n if (dynamicFiles.length === 0) {\n result.skipped.push(route.path);\n } else {\n result.pages += dynamicFiles.length;\n result.files.push(...dynamicFiles);\n }\n }\n\n // Re-render error pages too.\n if (routes.error404) {\n const result404 = await renderErrorPage({\n routes,\n status: 404,\n config: errorConfig,\n actions: publicActions,\n });\n if (result404) {\n const filePath = join(config.outDir, \"404.html\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, result404.html, \"utf8\");\n result.files.push(filePath);\n }\n }\n if (routes.error500) {\n const result500 = await renderErrorPage({\n routes,\n status: 500,\n config: errorConfig,\n actions: publicActions,\n });\n if (result500) {\n const filePath = join(config.outDir, \"500.html\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, result500.html, \"utf8\");\n result.files.push(filePath);\n }\n }\n }\n reportPhase(\"images\", phaseStart);\n }\n\n // Clear the manifest so subsequent builds start fresh.\n setImageManifest(null);\n\n // Fire the `build` integration hook so integrations can write\n // post-build artifacts (sitemaps, robots.txt, search indexes, etc.)\n // into the output directory. This runs after all pages, image variants,\n // and the manifest are written, but before the atomic staging commit\n // (when called via the CLI), so integration artifacts survive the swap.\n if (config.integrations && config.integrations.length > 0) {\n phaseStart = performance.now();\n await runIntegrationHook(config.integrations, \"build\", [\n result,\n { root: config.root ?? config.outDir, command: \"build\" },\n ]);\n reportPhase(\"integrations\", phaseStart);\n }\n\n // Automatic sitemap from the scanned routes when the site URL is known.\n // Runs after the integration hook; an existing sitemap.xml (copied from\n // public/ or written by an integration) always takes precedence.\n if (config.site) {\n phaseStart = performance.now();\n let sitemapExists = false;\n try {\n sitemapExists = (await stat(join(config.outDir, \"sitemap.xml\"))).isFile();\n } catch {\n // No sitemap yet.\n }\n if (!sitemapExists) {\n const sitemapFiles = await generateSitemapFromRoutes({\n siteUrl: config.site,\n outDir: config.outDir,\n routes,\n });\n result.files.push(...sitemapFiles);\n }\n reportPhase(\"sitemap\", phaseStart);\n }\n\n return result;\n}\n\nasync function buildPage(\n config: BuildConfig,\n route: PageRoute,\n actions: Record<string, string[]>,\n): Promise<string> {\n return buildConcretePage(config, route, {}, actions);\n}\n\nasync function buildDynamicPages(\n config: BuildConfig,\n route: PageRoute,\n actions: Record<string, string[]>,\n): Promise<string[]> {\n const { generateStaticParams } = (await import(\n route.pagePath\n )) as { generateStaticParams?: GenerateStaticParams };\n\n if (!generateStaticParams) {\n return [];\n }\n\n const paramList = await generateStaticParams();\n if (!Array.isArray(paramList) || paramList.length === 0) {\n return [];\n }\n\n const files: string[] = [];\n for (const params of paramList) {\n files.push(await buildConcretePage(config, route, params, actions));\n }\n return files;\n}\n\nasync function buildConcretePage(\n config: BuildConfig,\n route: PageRoute,\n params: RouteParams,\n actions: Record<string, string[]>,\n): Promise<string> {\n const { html: htmlOut } = await renderPage({\n route,\n params,\n searchParams: new URLSearchParams(),\n config: {\n lang: config.lang,\n clientEntry: config.clientEntry,\n renderEndpoint: false,\n router: pageRouterConfig(config),\n js: config.js,\n },\n actions,\n });\n\n const urlPath = isDynamic(route.path) ? buildConcreteUrl(route.path, params) : route.path;\n const filePath = urlToFilePath(config.outDir, urlPath);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, htmlOut, \"utf8\");\n\n return filePath;\n}\n\n/**\n * The router slice of the per-page render config: `enabled` gates script/meta\n * emission, `entry` is advertised only for split bundles, and `speculation`\n * produces the Speculation Rules block on static pages.\n */\nfunction pageRouterConfig(config: BuildConfig) {\n if (!config.router) return undefined;\n const separate = config.router.separate === true && config.js !== \"legacy\";\n return {\n enabled: config.router.enabled !== false,\n entry: separate ? config.router.entry ?? \"/_elur/router.js\" : undefined,\n speculation: config.router.speculation,\n };\n}\n\nexport { scanRoutes, type PageRoute, type ScannedRoutes };\n","import { createRequire } from \"node:module\";\nimport type { Plugin } from \"vite\";\n\n/**\n * How the legacy interpolation transform is handled relative to the installed\n * Elur core and Vite plugin:\n *\n * - `\"auto\"` (default): the kit's legacy transform is only applied when the\n * Vite plugin (`@elurjs/vite-plugin-elur` >= 1.1.0) is NOT installed.\n * The plugin has a more powerful state-machine lexer and takes precedence.\n * - `\"legacy\"`: always apply the kit's transform (for migrations), with a\n * one-time deprecation warning.\n * - `\"off\"`: never apply the kit's transform. Recommended when the Vite\n * plugin is installed.\n */\nexport type InterpolationMode = \"auto\" | \"legacy\" | \"off\";\n\nconst require = createRequire(import.meta.url);\n\nlet _warnedLegacy = false;\n\nfunction warnLegacyOnce(): void {\n if (_warnedLegacy) return;\n _warnedLegacy = true;\n console.warn(\n \"[elur-kit] The legacy interpolation transform is deprecated. \" +\n \"Install @elurjs/vite-plugin-elur >= 1.1.0 for compile-time \" +\n \"partial attribute interpolation. Remove `interpolation: \\\"legacy\\\"` \" +\n \"once migration is complete.\",\n );\n}\n\n/**\n * Detects whether the Vite plugin (`@elurjs/vite-plugin-elur`) is\n * installed and provides compile-time partial attribute interpolation.\n */\nexport function pluginSupportsPartialInterpolation(): boolean {\n try {\n const pkg = require(\"@elurjs/vite-plugin-elur/package.json\") as {\n version?: string;\n };\n // >= 1.1.0 has the interpolation lexer\n const [major, minor] = (pkg.version ?? \"0.0.0\").split(\".\").map(Number);\n return major > 1 || (major === 1 && minor >= 1);\n } catch {\n return false;\n }\n}\n\n/**\n * Detects whether the installed Elur core supports partial attribute\n * interpolation natively (via the public `templateFeatures` capability).\n * Note: as of core v3.4.0, this is always false — the lexer moved to the\n * Vite plugin.\n */\nexport function coreSupportsPartialInterpolation(): boolean {\n try {\n const core = require(\"@elurjs/core\") as {\n templateFeatures?: { partialAttributeInterpolation?: boolean };\n };\n return core?.templateFeatures?.partialAttributeInterpolation === true;\n } catch {\n return false;\n }\n}\n\n/**\n * Resolves whether the kit's legacy transform should be applied.\n *\n * In `\"auto\"` mode, the kit's transform runs only when neither the Vite\n * plugin nor the core provides partial interpolation. When the Vite plugin\n * is installed (>= 1.1.0), it takes precedence and the kit's transform is\n * skipped to avoid double-processing.\n */\nexport function shouldUseLegacyInterpolation(mode: InterpolationMode): boolean {\n if (mode === \"off\") return false;\n if (mode === \"legacy\") {\n warnLegacyOnce();\n return true;\n }\n // auto: skip if the Vite plugin handles it\n if (pluginSupportsPartialInterpolation()) return false;\n // fallback: use legacy if core doesn't support it natively\n return !coreSupportsPartialInterpolation();\n}\n\n/**\n * Transforms Elur `html\\`\\`` templates so that attributes with partial\n * interpolation become a single interpolation expression.\n *\n * Elur requires every dynamic attribute to be a single interpolation covering\n * the whole value. This plugin rewrites patterns such as:\n *\n * html\\`<a href=\"/blog/${slug}\">...</a>\\`\n *\n * into:\n *\n * html\\`<a href=${\"/blog/\" + slug}>...</a>\\`\n *\n * Only files inside the app and islands directories are processed.\n *\n * @deprecated Elur core supports partial attribute interpolation natively.\n * Keep this transform only for migrations against older cores\n * (`interpolation: \"legacy\"`).\n */\nexport interface InterpolationPluginOptions {\n appDir?: string;\n islandsDir?: string;\n}\n\nconst HTML_TAG = \"html\";\nconst TEMPLATE_START = \"`\";\n\n/**\n * Scans a `${...}` interpolation starting at `start` (where content[start] is\n * `$` and content[start + 1] is `{`), honoring nested braces, strings and\n * escape sequences. Returns the index just past the closing `}`.\n */\nfunction scanInterpolation(content: string, start: number): number {\n let depth = 1;\n let i = start + 2;\n while (i < content.length && depth > 0) {\n const c = content[i];\n if (c === \"\\\\\") {\n i += 2;\n continue;\n }\n if (c === '\"' || c === \"'\" || c === \"`\") {\n const q = c;\n i++;\n while (i < content.length) {\n if (content[i] === \"\\\\\") {\n i += 2;\n continue;\n }\n if (content[i] === q) break;\n i++;\n }\n i++;\n continue;\n }\n if (c === \"{\") depth++;\n else if (c === \"}\") depth--;\n i++;\n }\n return i;\n}\n\n/**\n * Scans a quoted attribute value starting at `start` (where content[start] is\n * the quote character). Handles escapes, `${...}` interpolations with nested\n * braces, and nested quotes. Returns the index just past the closing quote,\n * the raw inner text (escapes preserved as in the source) and whether the\n * value contains at least one interpolation.\n */\nfunction scanQuotedValue(\n content: string,\n start: number,\n quote: string,\n): { end: number; inside: string; hasInterp: boolean } {\n let i = start + 1;\n let inside = \"\";\n let hasInterp = false;\n while (i < content.length) {\n const c = content[i];\n if (c === \"\\\\\") {\n inside += c + (content[i + 1] ?? \"\");\n i += 2;\n continue;\n }\n if (c === quote) {\n i++;\n break;\n }\n if (c === \"$\" && content[i + 1] === \"{\") {\n const end = scanInterpolation(content, i);\n inside += content.slice(i, end);\n i = end;\n hasInterp = true;\n continue;\n }\n inside += c;\n i++;\n }\n return { end: i, inside, hasInterp };\n}\n\n/**\n * Converts the inner text of a quoted attribute value (which may contain\n * `${...}` interpolations) into a JS expression. Literal parts are JSON\n * encoded; interpolations keep their raw expression text.\n *\n * Examples:\n * /blog/${slug} -> \"/blog/\" + (slug)\n * ${slug} -> (slug)\n * tag ${cls({a:1})} -> \"tag \" + (cls({a:1}))\n */\nfunction valueToExpression(value: string): string {\n const parts: string[] = [];\n let i = 0;\n let literal = \"\";\n const flush = () => {\n if (literal) {\n parts.push(JSON.stringify(unescapeAttributeLiteral(literal)));\n literal = \"\";\n }\n };\n\n while (i < value.length) {\n if (value[i] === \"\\\\\") {\n literal += value[i] + (value[i + 1] ?? \"\");\n i += 2;\n continue;\n }\n if (value[i] === \"$\" && value[i + 1] === \"{\") {\n flush();\n const end = scanInterpolation(value, i);\n const expr = value.slice(i + 2, end - 1).trim();\n if (expr) parts.push(`(${expr})`);\n i = end;\n continue;\n }\n literal += value[i];\n i++;\n }\n flush();\n\n if (parts.length === 0) return '\"\"';\n if (parts.length === 1) return parts[0] as string;\n return parts.join(\" + \");\n}\n\n/**\n * Unescapes escape sequences that appear inside a JS template literal so the\n * JSON.stringify output matches the runtime string value.\n */\nfunction unescapeAttributeLiteral(literal: string): string {\n const escapes: Record<string, string> = {\n n: \"\\n\",\n t: \"\\t\",\n r: \"\\r\",\n };\n let out = \"\";\n let i = 0;\n while (i < literal.length) {\n const c = literal[i];\n if (c === \"\\\\\" && i + 1 < literal.length) {\n const next = literal[i + 1];\n if (next in escapes) {\n out += escapes[next];\n i += 2;\n continue;\n }\n out += next;\n i += 2;\n continue;\n }\n out += c;\n i++;\n }\n return out;\n}\n\n/**\n * Rewrites quoted attribute values that contain interpolations inside html``\n * templates, leaving everything else untouched.\n */\nfunction transformTemplateContent(content: string): string {\n let out = \"\";\n let i = 0;\n const n = content.length;\n\n while (i < n) {\n const lt = content.indexOf(\"<\", i);\n if (lt === -1) {\n out += content.slice(i);\n break;\n }\n out += content.slice(i, lt);\n i = lt;\n\n // HTML comments: copy verbatim.\n if (content.startsWith(\"<!--\", i)) {\n const end = content.indexOf(\"-->\", i + 4);\n if (end === -1) {\n out += content.slice(i);\n break;\n }\n out += content.slice(i, end + 3);\n i = end + 3;\n continue;\n }\n\n // Closing tags, doctype, CDATA, processing instructions: copy verbatim.\n if (content[i + 1] === \"/\" || content[i + 1] === \"!\" || content[i + 1] === \"?\") {\n const gt = content.indexOf(\">\", i + 1);\n if (gt === -1) {\n out += content.slice(i);\n break;\n }\n out += content.slice(i, gt + 1);\n i = gt + 1;\n continue;\n }\n\n // Opening tag. Copy the tag name, then walk its attributes.\n let j = i + 1;\n while (j < n && /[a-zA-Z0-9-]/.test(content[j])) j++;\n out += content.slice(i, j);\n i = j;\n\n while (i < n) {\n let ws = \"\";\n while (i < n && /\\s/.test(content[i])) {\n ws += content[i];\n i++;\n }\n if (i >= n) {\n out += ws;\n break;\n }\n if (content[i] === \">\") {\n out += ws + \">\";\n i++;\n break;\n }\n if (content[i] === \"/\" && content[i + 1] === \">\") {\n out += ws + \"/>\";\n i += 2;\n break;\n }\n // Interpolation in the tag body (dynamic attrs/spread): copy verbatim.\n if (content[i] === \"$\" && content[i + 1] === \"{\") {\n const end = scanInterpolation(content, i);\n out += ws + content.slice(i, end);\n i = end;\n continue;\n }\n\n // Attribute name.\n let nameStart = i;\n while (i < n && !/[\\s=/>\"'$]/.test(content[i])) i++;\n const name = content.slice(nameStart, i);\n if (!name) {\n out += ws + content[i];\n i++;\n continue;\n }\n\n let eqWs = \"\";\n while (i < n && /\\s/.test(content[i])) {\n eqWs += content[i];\n i++;\n }\n\n if (content[i] !== \"=\") {\n out += ws + name + eqWs;\n continue;\n }\n\n i++; // consume \"=\"\n let valWs = \"\";\n while (i < n && /\\s/.test(content[i])) {\n valWs += content[i];\n i++;\n }\n\n const quote = content[i];\n if (quote === '\"' || quote === \"'\") {\n const { end, inside, hasInterp } = scanQuotedValue(content, i, quote);\n if (hasInterp) {\n // Skip values that are a single full interpolation: Elur handles\n // `attr=\"${expr}\"` natively, so only partial interpolations need the\n // rewrite.\n const first = scanInterpolation(inside, 0);\n const fullValue =\n inside.startsWith(\"${\") &&\n first === inside.length &&\n !inside.slice(2, first - 1).includes(\"${\");\n if (!fullValue) {\n // Elur needs the interpolation to start right after \"=\" (no space),\n // so the whitespace before the original value is dropped.\n out += ws + name + eqWs + \"=\" + \"${\" + valueToExpression(inside) + \"}\";\n i = end;\n continue;\n }\n out += ws + name + eqWs + \"=\" + valWs + content.slice(i, end);\n } else {\n out += ws + name + eqWs + \"=\" + valWs + content.slice(i, end);\n }\n i = end;\n continue;\n }\n\n // Unquoted value: copy up to whitespace, \">\" or \"/>\".\n let v = \"\";\n while (\n i < n &&\n !/\\s/.test(content[i]) &&\n content[i] !== \">\" &&\n !(content[i] === \"/\" && content[i + 1] === \">\")\n ) {\n v += content[i];\n i++;\n }\n out += ws + name + eqWs + \"=\" + valWs + v;\n }\n }\n\n return out;\n}\n\n/**\n * @deprecated Use the native partial attribute interpolation of Elur core\n * (core >= 3.3). Kept for legacy migrations and direct consumers.\n */\nexport function transformPartialInterpolations(source: string): string {\n let result = \"\";\n let i = 0;\n while (i < source.length) {\n // Find the next html` sequence.\n const htmlIndex = source.indexOf(HTML_TAG, i);\n if (htmlIndex === -1) {\n result += source.slice(i);\n break;\n }\n result += source.slice(i, htmlIndex + HTML_TAG.length);\n i = htmlIndex + HTML_TAG.length;\n\n // Skip whitespace before the backtick.\n while (i < source.length && /\\s/.test(source[i])) {\n result += source[i];\n i++;\n }\n if (i >= source.length || source[i] !== TEMPLATE_START) {\n continue;\n }\n result += source[i];\n i++;\n\n // Parse the template literal until the matching backtick.\n let depth = 1;\n let templateContent = \"\";\n while (i < source.length && depth > 0) {\n const char = source[i];\n if (char === \"\\\\\") {\n templateContent += char + source[i + 1];\n i += 2;\n continue;\n }\n if (char === TEMPLATE_START) {\n depth--;\n if (depth === 0) {\n i++;\n break;\n }\n }\n if (char === \"$\") {\n // Look ahead for ${...}\n if (source[i + 1] === \"{\") {\n const end = scanInterpolation(source, i);\n templateContent += source.slice(i, end);\n i = end;\n continue;\n }\n }\n templateContent += char;\n i++;\n }\n\n const transformed = transformTemplateContent(templateContent);\n result += transformed;\n result += TEMPLATE_START;\n }\n return result;\n}\n\nexport function elurJsInterpolationPlugin(options: InterpolationPluginOptions = {}): Plugin {\n const appDir = options.appDir ?? \"src/app\";\n const islandsDir = options.islandsDir ?? \"src/islands\";\n return {\n name: \"elur-kit-interpolation\",\n enforce: \"pre\",\n transform(code, id) {\n if (!id.endsWith(\".ts\") && !id.endsWith(\".js\")) return;\n if (!id.includes(appDir) && !id.includes(islandsDir)) return;\n if (!code.includes(\"html`\")) return;\n const transformed = transformPartialInterpolations(code);\n if (transformed === code) return;\n return { code: transformed, map: null };\n },\n };\n}\n","import { mkdir, readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { dirname, extname, relative, resolve, sep } from \"node:path\";\nimport { shouldUseLegacyInterpolation, transformPartialInterpolations, type InterpolationMode } from \"../vite/interpolation-plugin.js\";\n\nexport interface TransformProjectOptions {\n root: string;\n appDir: string;\n islandsDir?: string;\n /**\n * Absolute path to the transformed tree root. The tree mirrors the project\n * layout relative to the common ancestor of `appDir`/`islandsDir`, so\n * relative imports between app and islands keep resolving. Relative imports\n * that escape that ancestor are compensated for the added directory depth.\n */\n outDir: string;\n /**\n * How the legacy interpolation transform is handled (default: \"auto\").\n * With a Elur core that supports partial attribute interpolation natively\n * the transform is not applied; use \"legacy\" for migrations against older\n * cores and \"off\" to never transform.\n */\n interpolation?: InterpolationMode;\n}\n\n/**\n * Copy app (and optionally islands) source files to a transformed directory,\n * rewriting partial Elur attribute interpolations so they can be imported\n * by the SSG/SSR build without requiring manual syntax changes.\n */\nasync function collectTsFiles(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n const files: string[] = [];\n for (const entry of entries) {\n const path = resolve(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await collectTsFiles(path)));\n } else if (entry.isFile() && extname(path) === \".ts\") {\n files.push(path);\n }\n }\n return files;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") return [];\n throw err;\n }\n}\n\nfunction segments(rel: string): string[] {\n return rel.split(/[\\\\/]+/).filter(Boolean);\n}\n\n/** Number of path segments in `rel`. */\nfunction depth(rel: string): number {\n return segments(rel).length;\n}\n\n/** Common ancestor directory of two paths (both absolute). */\nfunction commonBase(a: string, b: string): string {\n const sa = segments(a);\n const sb = segments(b);\n const prefix: string[] = [];\n for (let i = 0; i < Math.min(sa.length, sb.length); i++) {\n if (sa[i] === sb[i]) prefix.push(sa[i]);\n else break;\n }\n return resolve(\"/\" + prefix.join(sep));\n}\n\n/**\n * Absolute path of the transformed app directory inside the mirror tree,\n * matching where `transformProjectFiles` copies the app files.\n */\nexport function transformedAppDir(\n root: string,\n appDir: string,\n islandsDir: string | undefined,\n outDir: string,\n): string {\n const absAppDir = resolve(root, appDir);\n const absIslandsDir = islandsDir ? resolve(root, islandsDir) : absAppDir;\n return resolve(outDir, relative(commonBase(absAppDir, absIslandsDir), absAppDir));\n}\n\n/**\n * Rewrites relative import specifiers in non-template regions so they resolve\n * to the same targets from the transformed location.\n *\n * Imports that stay inside the mirrored subtree need no changes. Imports that\n * escape it are moved `delta` levels: a positive delta prepends that many\n * `../`, a negative one strips leading `../` segments.\n */\nfunction compensateRelativeImports(source: string, delta: number, maxUps: number): string {\n if (delta === 0) return source;\n const prepend = \"..\".repeat(delta) + \"/\";\n const strip = -delta;\n return source.replace(\n /(?:(\\bfrom\\s*)|(\\bimport\\s*\\()|(\\bimport\\s+)|(\\bexport\\s*\\*\\s*from\\s*))([\"'])(\\.[^\"']*)\\5/g,\n (_match, fromKw, importCall, importKw, exportStar, quote, specifier) => {\n let ups = 0;\n let idx = 0;\n while (specifier.startsWith(\"../\", idx)) {\n ups++;\n idx += 3;\n }\n // Imports crossing the mirrored subtree boundary (more `..` than the\n // file's depth below the mirror base) point outside the tree.\n const crosses = ups > maxUps;\n let spec = specifier;\n if (crosses && delta > 0) {\n spec = prepend + spec;\n } else if (crosses && delta < 0) {\n let removed = 0;\n while (removed < strip && spec.startsWith(\"../\")) {\n spec = spec.slice(3);\n removed++;\n }\n if (removed < strip && spec === \"..\") {\n spec = spec.slice(0, -2);\n removed++;\n }\n if (!spec.startsWith(\".\")) spec = \"./\" + spec;\n }\n return (fromKw || importCall || importKw || exportStar) + quote + spec + quote;\n },\n );\n}\n\n/**\n * Applies import compensation to every region of `source` that is not inside\n * an `html` template literal, so attribute strings like `from \"./x.js\"` are\n * never rewritten.\n */\nfunction rewriteImportsOutsideTemplates(source: string, delta: number, maxUps: number): string {\n if (delta === 0) return source;\n let result = \"\";\n let i = 0;\n while (i < source.length) {\n const htmlIndex = source.indexOf(\"html\", i);\n if (htmlIndex === -1) {\n result += compensateRelativeImports(source.slice(i), delta, maxUps);\n break;\n }\n let j = htmlIndex + 4;\n while (j < source.length && /\\s/.test(source[j])) j++;\n if (source[j] !== \"`\") {\n result += compensateRelativeImports(source.slice(i, htmlIndex + 4), delta, maxUps);\n i = htmlIndex + 4;\n continue;\n }\n result += compensateRelativeImports(source.slice(i, htmlIndex + 4), delta, maxUps);\n // Copy the template literal verbatim (interpolations included).\n let depth = 1;\n let k = j + 1;\n while (k < source.length && depth > 0) {\n const c = source[k];\n if (c === \"\\\\\") {\n k += 2;\n continue;\n }\n if (c === \"`\") {\n depth--;\n if (depth === 0) break;\n }\n if (c === \"$\" && source[k + 1] === \"{\") {\n // Jump over the interpolation, honoring nested braces.\n let braceDepth = 1;\n let l = k + 2;\n while (l < source.length && braceDepth > 0) {\n if (source[l] === \"{\") braceDepth++;\n else if (source[l] === \"}\") braceDepth--;\n l++;\n }\n k = l;\n continue;\n }\n k++;\n }\n if (k >= source.length) {\n result += source.slice(j);\n break;\n }\n result += source.slice(j, k + 1);\n i = k + 1;\n }\n return result;\n}\n\nexport async function transformProjectFiles(options: TransformProjectOptions): Promise<void> {\n const { root, appDir, islandsDir, outDir } = options;\n const dirs = islandsDir ? [appDir, islandsDir] : [appDir];\n const files: string[] = [];\n for (const dir of dirs) {\n files.push(...(await collectTsFiles(resolve(root, dir))));\n }\n\n const absAppDir = resolve(root, appDir);\n const absIslandsDir = islandsDir ? resolve(root, islandsDir) : absAppDir;\n const base = commonBase(absAppDir, absIslandsDir);\n\n // Transformed files sit `delta` levels further from root than originals.\n const delta = depth(relative(root, outDir)) - depth(relative(root, base));\n\n for (const file of files) {\n const source = await readFile(file, \"utf8\");\n let output = source;\n if (source.includes(\"html`\") && shouldUseLegacyInterpolation(options.interpolation ?? \"auto\")) {\n const transformed = transformPartialInterpolations(source);\n if (transformed !== source) {\n output = transformed;\n }\n }\n const rel = relative(root, file);\n if (rel.startsWith(\"..\")) {\n continue;\n }\n const baseDepth = depth(relative(base, dirname(file)));\n output = rewriteImportsOutsideTemplates(output, delta, baseDepth);\n const outFile = resolve(outDir, relative(base, file));\n await mkdir(dirname(outFile), { recursive: true });\n await writeFile(outFile, output, \"utf8\");\n }\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\n// Capture the global AbortController at module load time so it's immune to\n// test frameworks that replace or delete globalThis.AbortController.\nconst GlobalAbortController =\n (globalThis as { AbortController?: typeof AbortController }).AbortController ?? AbortController;\n\nexport function incomingMessageToRequest(req: IncomingMessage, body?: BodyInit | null): Request {\n const headers = new Headers();\n for (let index = 0; index < req.rawHeaders.length; index += 2) {\n headers.append(req.rawHeaders[index], req.rawHeaders[index + 1]);\n }\n\n const controller = new GlobalAbortController();\n req.once(\"aborted\", () => controller.abort());\n req.once(\"close\", () => {\n if (!req.complete) controller.abort();\n });\n\n const protocol = (req.socket as typeof req.socket & { encrypted?: boolean }).encrypted ? \"https\" : \"http\";\n const init: RequestInit = {\n method: req.method ?? \"GET\",\n headers,\n signal: controller.signal,\n };\n if (body !== undefined && body !== null && init.method !== \"GET\" && init.method !== \"HEAD\") init.body = body;\n\n return new Request(`${protocol}://${headers.get(\"host\") ?? \"localhost\"}${req.url ?? \"/\"}`, init);\n}\n\n/**\n * Writes a Web `Response` to a Node `ServerResponse`, streaming the body.\n *\n * Unlike `res.end(Buffer.from(await response.arrayBuffer()))`, this forwards\n * chunks as they are produced — required for streaming SSR responses to reach\n * the client progressively. Buffered (non-stream) bodies behave exactly as\n * before. Honors backpressure (`drain`) and cancels the upstream stream when\n * the client disconnects (`close` before `finish`).\n */\nexport async function sendWebResponse(res: ServerResponse, response: Response): Promise<void> {\n const headers = Object.fromEntries(response.headers.entries());\n if (response.body !== null) {\n // Chunk boundaries are decided as the body is read; a Content-Length\n // captured earlier would be wrong for streams. Transfer-Encoding is\n // managed by Node itself (it chunks when no length is set) — forwarding\n // it would duplicate the header (`chunked, chunked`).\n delete headers[\"content-length\"];\n delete headers[\"transfer-encoding\"];\n }\n res.writeHead(response.status, headers);\n\n const body = response.body;\n if (!body) {\n res.end();\n return;\n }\n\n const reader = body.getReader();\n let done = false;\n const onClose = () => {\n if (!done) void reader.cancel().catch(() => {});\n };\n res.once(\"close\", onClose);\n\n try {\n for (;;) {\n const { done: readDone, value } = await reader.read();\n if (readDone) break;\n if (value && value.byteLength > 0 && !res.write(value)) {\n // Socket buffer is full: wait for it to drain before reading more.\n await new Promise<void>((resolveDrain) => res.once(\"drain\", resolveDrain));\n }\n }\n done = true;\n res.end();\n } catch {\n done = true;\n // The client went away or the upstream stream failed: tear the socket\n // down instead of leaving a half-written response hanging.\n res.destroy();\n } finally {\n res.removeListener(\"close\", onClose);\n }\n}\n","// --- Structured logger with request ID and Server-Timing (plan §12.3) ---\n//\n// Provides a structured logger that:\n// - Generates a unique request ID per request.\n// - Attaches the request ID to all log entries.\n// - Supports structured fields (not just string messages).\n// - Redacts sensitive data (cookies, auth headers, tokens).\n// - Supports Server-Timing header accumulation.\n//\n// OpenTelemetry/analytics are external integrations — no automatic telemetry.\n\nimport { randomUUID } from \"node:crypto\";\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\nconst SENSITIVE_HEADERS = new Set([\n \"cookie\",\n \"authorization\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-auth-token\",\n]);\n\nexport interface LogEntry {\n level: LogLevel;\n message: string;\n requestId?: string;\n timestamp: string;\n fields?: Record<string, unknown>;\n}\n\nexport interface ServerTimingMetric {\n name: string;\n description?: string;\n durationMs: number;\n}\n\nexport class StructuredLogger {\n private minLevel: LogLevel;\n private requestId: string;\n private timings: ServerTimingMetric[] = [];\n private entries: LogEntry[] = [];\n\n constructor(options: { minLevel?: LogLevel; requestId?: string } = {}) {\n this.minLevel = options.minLevel ?? (process.env.NODE_ENV === \"production\" ? \"info\" : \"debug\");\n this.requestId = options.requestId ?? randomUUID();\n }\n\n /** Returns the request ID for this logger instance. */\n getRequestId(): string {\n return this.requestId;\n }\n\n /** Logs a debug message. */\n debug(message: string, fields?: Record<string, unknown>): void {\n this.log(\"debug\", message, fields);\n }\n\n /** Logs an info message. */\n info(message: string, fields?: Record<string, unknown>): void {\n this.log(\"info\", message, fields);\n }\n\n /** Logs a warning. */\n warn(message: string, fields?: Record<string, unknown>): void {\n this.log(\"warn\", message, fields);\n }\n\n /** Logs an error. */\n error(message: string, fields?: Record<string, unknown>): void {\n this.log(\"error\", message, fields);\n }\n\n /** Records a Server-Timing metric. */\n timing(name: string, durationMs: number, description?: string): void {\n this.timings.push({ name, durationMs, description });\n }\n\n /** Starts a timer and returns a function to stop it and record the timing. */\n startTimer(name: string, description?: string): () => void {\n const start = performance.now();\n return () => {\n this.timing(name, performance.now() - start, description);\n };\n }\n\n /** Returns the Server-Timing header value. */\n getServerTimingHeader(): string {\n return this.timings\n .map((t) => {\n const desc = t.description ? `;desc=\"${t.description}\"` : \"\";\n return `${t.name};dur=${t.durationMs.toFixed(1)}${desc}`;\n })\n .join(\", \");\n }\n\n /** Returns all log entries collected so far. */\n getEntries(): readonly LogEntry[] {\n return this.entries;\n }\n\n private log(level: LogLevel, message: string, fields?: Record<string, unknown>): void {\n if (LEVEL_PRIORITY[level] < LEVEL_PRIORITY[this.minLevel]) return;\n\n const entry: LogEntry = {\n level,\n message,\n requestId: this.requestId,\n timestamp: new Date().toISOString(),\n fields: fields ? redactSensitive(fields) : undefined,\n };\n\n this.entries.push(entry);\n\n // Output to console in development, structured JSON in production.\n if (process.env.NODE_ENV === \"production\") {\n const output = JSON.stringify(entry);\n if (level === \"error\") console.error(output);\n else if (level === \"warn\") console.warn(output);\n else console.log(output);\n } else {\n const prefix = `[${level.toUpperCase()}]`;\n const fieldsStr = entry.fields ? \" \" + JSON.stringify(entry.fields) : \"\";\n const output = `${prefix} ${message}${fieldsStr}`;\n if (level === \"error\") console.error(output);\n else if (level === \"warn\") console.warn(output);\n else console.log(output);\n }\n }\n}\n\n/**\n * Redacts sensitive fields from a log fields object.\n * Recursively redacts keys that match sensitive header names.\n */\nfunction redactSensitive(fields: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(fields)) {\n const lowerKey = key.toLowerCase();\n if (SENSITIVE_HEADERS.has(lowerKey)) {\n result[key] = \"[REDACTED]\";\n } else if (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n result[key] = redactSensitive(value as Record<string, unknown>);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Creates a logger for a request, optionally using the request's\n * X-Request-ID header if present.\n */\nexport function createRequestLogger(request?: Request, minLevel?: LogLevel): StructuredLogger {\n const requestId = request?.headers.get(\"X-Request-ID\") ?? undefined;\n return new StructuredLogger({ minLevel, requestId });\n}\n","import { access } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { loadConfigFromFile } from \"vite\";\nimport type { Adapter } from \"../adapters/index.js\";\nimport type { ImageFormat } from \"../image/index.js\";\nimport type { ElurKitIntegration } from \"../integrations/index.js\";\nimport { runIntegrationHook } from \"../integrations/index.js\";\nimport type { LogLevel } from \"../runtime/logger.js\";\nimport type { CacheAdapter } from \"../cache/adapter.js\";\nimport type { RedirectRule, RewriteRule, RouteHeadersRule } from \"../router/redirects.js\";\n\nexport type ElurOutputMode = \"static\" | \"server\" | \"hybrid\";\nexport type TrailingSlashMode = \"always\" | \"never\" | \"ignore\";\n\nexport interface ElurConfig {\n root?: string;\n appDir?: string;\n islandsDir?: string;\n contentDir?: string;\n publicDir?: string;\n outDir?: string;\n site?: string;\n base?: string;\n trailingSlash?: TrailingSlashMode;\n output?: ElurOutputMode;\n adapter?: Adapter;\n images?: {\n formats?: ImageFormat[];\n quality?: number;\n strict?: boolean;\n };\n cache?: {\n dir?: string;\n defaultRevalidate?: number;\n /**\n * Pluggable ISR cache adapter (programmatic only — not serializable).\n * Default: filesystem adapter rooted at `cache.dir`.\n */\n adapter?: CacheAdapter;\n };\n security?: {\n allowedOrigins?: string[];\n strictOrigin?: boolean;\n bodyLimit?: number;\n /** Security response headers. Set to `false` to disable defaults. */\n headers?: SecurityHeadersConfig | false;\n };\n /**\n * Client-side router options.\n */\n router?: {\n /**\n * Enable the SPA router on the client (default: `true`). When `false`,\n * no router code is generated and pages without islands ship 0 KB of\n * client JavaScript.\n */\n enabled?: boolean;\n /**\n * Enable link prefetching on hover/focus/pointerdown (default: `true`).\n * Prefetch already opts out on Save-Data and 2g-class connections.\n */\n prefetch?: boolean;\n /**\n * Swap `#app` via idiomorph DOM morphing instead of replacing children\n * (default: `false`, experimental). Hydrated islands and\n * `data-elur-persist` nodes are treated as opaque.\n */\n morph?: boolean;\n /**\n * Emit a `<script type=\"speculationrules\">` block on statically built\n * pages (default: off). Chromium-only progressive enhancement; other\n * browsers ignore it.\n */\n speculation?: \"prefetch\" | \"prerender\";\n /**\n * Show a minimal top progress bar on SPA navigations slower than\n * ~200 ms (default: `false`).\n */\n loadingIndicator?: boolean;\n };\n /**\n * Client JavaScript emission mode (default: `\"modern\"`).\n *\n * - `\"modern\"`: per-page gating — pages without islands emit only the\n * router chunk (or nothing when `router.enabled: false`), and split\n * client builds emit `entry-client.js` + `router.js` separately.\n * - `\"legacy\"`: escape hatch restoring the pre-0%-JS behavior — the\n * combined client entry (hydration + router) is emitted unconditionally\n * on every page.\n */\n js?: \"modern\" | \"legacy\";\n logger?: {\n /** Minimum log level. Default: \"info\" in production, \"debug\" otherwise. */\n level?: LogLevel;\n };\n /** Redirect rules (first match wins; default status 308). */\n redirects?: RedirectRule[];\n /**\n * Opt-in streaming SSR (experimental). When `true`, dynamic routes with a\n * `loading` boundary stream the document shell immediately and swap in the\n * resolved content as a follow-up chunk. Streamed pages bypass the ISR\n * cache. Default: `false` (fully buffered rendering).\n */\n streaming?: boolean;\n /** Rewrite rules: transparently change the pathname before routing. */\n rewrites?: RewriteRule[];\n /** Extra response headers applied to matching request paths. */\n headers?: RouteHeadersRule[];\n integrations?: ElurKitIntegration[];\n}\n\n/** Security headers configuration (runtime-security §14). */\nexport interface SecurityHeadersConfig {\n /** X-Content-Type-Options: nosniff. Default: true. */\n noSniff?: boolean;\n /** Referrer-Policy. Default: \"strict-origin-when-cross-origin\". */\n referrerPolicy?: string;\n /**\n * Content-Security-Policy. Set to a string to enable.\n * Use \"nonce\" placeholder to inject per-request nonces.\n */\n contentSecurityPolicy?: string;\n /** Strict-Transport-Security. Only applied under HTTPS. Default: unset. */\n hsts?: string | true;\n /** X-Frame-Options or CSP frame-ancestors. Default: \"SAMEORIGIN\". */\n frameAncestors?: string;\n /** Permissions-Policy. Default: unset. */\n permissionsPolicy?: string;\n}\n\nexport interface ResolvedElurConfig {\n root: string;\n appDir: string;\n islandsDir: string;\n contentDir: string;\n publicDir: string;\n outDir: string;\n site?: string;\n base: string;\n trailingSlash: TrailingSlashMode;\n output: ElurOutputMode;\n adapter?: Adapter;\n images: {\n formats: ImageFormat[];\n quality: number;\n strict: boolean;\n };\n cache: {\n dir: string;\n defaultRevalidate?: number;\n adapter?: CacheAdapter;\n };\n security: {\n allowedOrigins: string[];\n strictOrigin: boolean;\n bodyLimit: number;\n headers: SecurityHeadersConfig | false;\n };\n router: {\n enabled: boolean;\n prefetch: boolean;\n morph: boolean;\n speculation?: \"prefetch\" | \"prerender\";\n loadingIndicator: boolean;\n };\n /** Client JS emission mode: \"modern\" (0% JS gating) or \"legacy\". */\n js: \"modern\" | \"legacy\";\n logger: {\n level?: LogLevel;\n };\n redirects: RedirectRule[];\n rewrites: RewriteRule[];\n /** Opt-in streaming SSR (experimental). Default: `false`. */\n streaming: boolean;\n headers: RouteHeadersRule[];\n integrations: ElurKitIntegration[];\n configFile?: string;\n}\n\nexport interface LoadElurConfigOptions {\n root?: string;\n configFile?: string;\n command?: \"dev\" | \"build\" | \"preview\" | \"start\" | \"check\" | \"routes\" | \"doctor\";\n mode?: string;\n overrides?: ElurConfig;\n}\n\nexport function defineConfig(config: ElurConfig): ElurConfig {\n return config;\n}\n\nexport async function loadElurConfig(options: LoadElurConfigOptions = {}): Promise<ResolvedElurConfig> {\n const initialRoot = resolve(options.root ?? process.cwd());\n const configFile = options.configFile\n ? resolve(initialRoot, options.configFile)\n : await findConfigFile(initialRoot);\n let loaded: ElurConfig = {};\n\n if (configFile) {\n const result = await loadConfigFromFile(\n { command: options.command === \"build\" ? \"build\" : \"serve\", mode: options.mode ?? \"development\" },\n configFile,\n initialRoot,\n );\n if (!result) throw new Error(`[elur-kit] Could not load config: ${configFile}`);\n loaded = result.config as ElurConfig;\n }\n\n const merged = mergeConfig(loaded, options.overrides ?? {});\n const root = resolve(initialRoot, merged.root ?? \".\");\n const resolved = resolveConfig(root, merged, configFile);\n await runIntegrationHook(resolved.integrations, \"config\", [\n resolved as unknown as Record<string, unknown>,\n { root, command: options.command ?? \"dev\" },\n ]);\n return resolved;\n}\n\nfunction resolveConfig(root: string, config: ElurConfig, configFile?: string): ResolvedElurConfig {\n if (config.site) new URL(config.site);\n const base = normalizeBase(config.base ?? \"/\");\n const imageQuality = config.images?.quality ?? 80;\n if (!Number.isFinite(imageQuality) || imageQuality < 1 || imageQuality > 100) {\n throw new Error(\"[elur-kit] images.quality must be between 1 and 100\");\n }\n\n return {\n root,\n appDir: resolveInside(root, config.appDir ?? \"src/app\", \"appDir\"),\n islandsDir: resolveInside(root, config.islandsDir ?? \"src/islands\", \"islandsDir\"),\n contentDir: resolveInside(root, config.contentDir ?? \"src/content\", \"contentDir\"),\n publicDir: resolveInside(root, config.publicDir ?? \"public\", \"publicDir\"),\n outDir: resolveInside(root, config.outDir ?? \"dist\", \"outDir\"),\n site: config.site,\n base,\n trailingSlash: config.trailingSlash ?? \"ignore\",\n output: config.output ?? \"static\",\n adapter: config.adapter,\n images: {\n formats: config.images?.formats ?? [\"webp\", \"avif\"],\n quality: imageQuality,\n strict: config.images?.strict ?? false,\n },\n cache: {\n dir: resolveInside(root, config.cache?.dir ?? \".elur/cache\", \"cache.dir\"),\n defaultRevalidate: config.cache?.defaultRevalidate,\n adapter: config.cache?.adapter,\n },\n security: {\n allowedOrigins: config.security?.allowedOrigins ?? [],\n strictOrigin: config.security?.strictOrigin ?? false,\n bodyLimit: config.security?.bodyLimit ?? 1_048_576,\n headers: config.security?.headers === false\n ? false\n : config.security?.headers ?? {},\n },\n router: {\n enabled: config.router?.enabled ?? true,\n prefetch: config.router?.prefetch ?? true,\n morph: config.router?.morph ?? false,\n speculation: config.router?.speculation,\n loadingIndicator: config.router?.loadingIndicator ?? false,\n },\n js: config.js ?? \"modern\",\n // No forced level: the StructuredLogger defaults to \"info\" in production\n // and \"debug\" in development when `level` is undefined.\n logger: {\n level: config.logger?.level,\n },\n redirects: config.redirects ?? [],\n rewrites: config.rewrites ?? [],\n streaming: config.streaming ?? false,\n headers: config.headers ?? [],\n integrations: config.integrations ?? [],\n configFile,\n };\n}\n\nfunction mergeConfig(base: ElurConfig, override: ElurConfig): ElurConfig {\n return {\n ...base,\n ...override,\n images: { ...base.images, ...override.images },\n cache: { ...base.cache, ...override.cache },\n security: { ...base.security, ...override.security },\n router: { ...base.router, ...override.router },\n logger: { ...base.logger, ...override.logger },\n // Rule arrays match first-match-wins, so override rules go first: they\n // win over base rules for the same path while base keeps the rest.\n redirects: [...(override.redirects ?? []), ...(base.redirects ?? [])],\n rewrites: [...(override.rewrites ?? []), ...(base.rewrites ?? [])],\n headers: [...(override.headers ?? []), ...(base.headers ?? [])],\n integrations: override.integrations ?? base.integrations,\n };\n}\n\nfunction resolveInside(root: string, path: string, name: string): string {\n const resolved = isAbsolute(path) ? resolve(path) : resolve(root, path);\n const rel = relative(root, resolved);\n if (rel === \"..\" || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {\n throw new Error(`[elur-kit] ${name} must stay inside root: ${resolved}`);\n }\n return resolved;\n}\n\nfunction normalizeBase(base: string): string {\n if (!base.startsWith(\"/\")) throw new Error(\"[elur-kit] base must start with /\");\n return base === \"/\" ? base : `${base.replace(/\\/+$/, \"\")}/`;\n}\n\nconst PREFERRED_CONFIG_FILES = [\"elur.config.ts\", \"elur.config.js\", \"elur.config.mjs\"];\n\nasync function findConfigFile(root: string): Promise<string | undefined> {\n for (const name of PREFERRED_CONFIG_FILES) {\n const path = resolve(root, name);\n try {\n await access(path);\n return path;\n } catch {\n }\n }\n return undefined;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, relative } from \"node:path\";\nimport { scanActions, type ActionRegistry } from \"../action/scan.js\";\nimport type { ResolvedElurConfig } from \"../config/index.js\";\nimport { runIntegrationHook } from \"../integrations/index.js\";\nimport { scanIslands, type IslandModule } from \"../island/scan.js\";\nimport { scanRoutes, type ScannedRoutes } from \"../router/route-scanner.js\";\n\nexport interface AppManifest {\n version: 1;\n root: string;\n routes: ScannedRoutes;\n actions: ActionRegistry;\n islands: IslandModule[];\n base: string;\n output: ResolvedElurConfig[\"output\"];\n}\n\nexport async function createAppManifest(config: ResolvedElurConfig): Promise<AppManifest> {\n const [routes, actions, islands] = await Promise.all([\n scanRoutes(config.appDir),\n scanActions(config.appDir),\n scanIslands(config.islandsDir),\n ]);\n validateManifestRoutes(routes);\n validateIslands(islands);\n const manifest: AppManifest = {\n version: 1,\n root: config.root,\n routes,\n actions,\n islands,\n base: config.base,\n output: config.output,\n };\n await runIntegrationHook(config.integrations, \"routes\", [\n manifest,\n { root: config.root, command: \"build\" },\n ]);\n return manifest;\n}\n\nexport async function writeAppManifest(manifest: AppManifest, path: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, JSON.stringify(toPortableManifest(manifest), null, 2), \"utf8\");\n}\n\nexport async function writeRouteTypes(manifest: AppManifest, path: string): Promise<void> {\n const routePaths = manifest.routes.pages.map((route) => JSON.stringify(route.path));\n const actionNames = Object.values(manifest.actions)\n .flatMap((actions) => Object.keys(actions))\n .filter((name, index, names) => names.indexOf(name) === index)\n .map((name) => JSON.stringify(name));\n const source = [\n `export type ElurRoutePath = ${routePaths.length ? routePaths.join(\" | \") : \"never\"};`,\n `export type ElurActionName = ${actionNames.length ? actionNames.join(\" | \") : \"never\"};`,\n \"export interface ElurRouteParams { [name: string]: string | string[] | undefined }\",\n \"\",\n ].join(\"\\n\");\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, source, \"utf8\");\n}\n\nexport function validateManifestRoutes(routes: ScannedRoutes): void {\n const seen = new Map<string, string>();\n for (const route of routes.pages) {\n registerRoute(seen, route.path, route.pagePath, \"page\");\n assertNotReserved(route.path, route.pagePath);\n }\n for (const route of routes.api) {\n registerRoute(seen, route.path, route.routePath, \"API\");\n assertNotReserved(route.path, route.routePath);\n }\n}\n\nexport function assertClientImportAllowed(id: string, importer?: string): void {\n if (/\\.server\\.[cm]?[jt]sx?$/.test(id)) {\n throw new Error(`[elur-kit] Server-only module imported by client${importer ? ` from ${importer}` : \"\"}: ${id}`);\n }\n}\n\nfunction registerRoute(seen: Map<string, string>, path: string, file: string, kind: string): void {\n const existing = seen.get(path);\n if (existing) {\n throw new Error(`[elur-kit] Duplicate ${kind} route \"${path}\": ${existing} and ${file}`);\n }\n seen.set(path, file);\n}\n\nfunction assertNotReserved(path: string, file: string): void {\n if (path === \"/__elur-js\" || path.startsWith(\"/__elur-js/\") || path === \"/_elur\" || path.startsWith(\"/_elur/\")) {\n throw new Error(`[elur-kit] Reserved route \"${path}\" declared by ${file}`);\n }\n}\n\nfunction validateIslands(islands: readonly IslandModule[]): void {\n const names = new Set<string>();\n for (const island of islands) {\n if (names.has(island.name)) throw new Error(`[elur-kit] Duplicate island name: ${island.name}`);\n names.add(island.name);\n }\n}\n\nfunction toPortableManifest(manifest: AppManifest): AppManifest {\n const relativePath = (path: string | undefined) => path ? relative(manifest.root, path).split(\"\\\\\").join(\"/\") : undefined;\n const routes: ScannedRoutes = {\n pages: manifest.routes.pages.map((route) => ({\n ...route,\n pagePath: relativePath(route.pagePath)!,\n dataPath: relativePath(route.dataPath),\n actionPath: relativePath(route.actionPath),\n loadingPath: relativePath(route.loadingPath),\n layouts: route.layouts.map((layout) => relativePath(layout)!),\n })),\n api: manifest.routes.api.map((route) => ({ ...route, routePath: relativePath(route.routePath)! })),\n error404: manifest.routes.error404 ? {\n ...manifest.routes.error404,\n pagePath: relativePath(manifest.routes.error404.pagePath)!,\n dataPath: relativePath(manifest.routes.error404.dataPath),\n actionPath: relativePath(manifest.routes.error404.actionPath),\n loadingPath: relativePath(manifest.routes.error404.loadingPath),\n layouts: manifest.routes.error404.layouts.map((layout) => relativePath(layout)!),\n } : undefined,\n error500: manifest.routes.error500 ? {\n ...manifest.routes.error500,\n pagePath: relativePath(manifest.routes.error500.pagePath)!,\n dataPath: relativePath(manifest.routes.error500.dataPath),\n actionPath: relativePath(manifest.routes.error500.actionPath),\n loadingPath: relativePath(manifest.routes.error500.loadingPath),\n layouts: manifest.routes.error500.layouts.map((layout) => relativePath(layout)!),\n } : undefined,\n };\n const actions: ActionRegistry = {};\n for (const [page, pageActions] of Object.entries(manifest.actions)) {\n actions[page] = Object.fromEntries(\n Object.entries(pageActions).map(([name, path]) => [name, relativePath(path)!]),\n );\n }\n return {\n ...manifest,\n root: \".\",\n routes,\n actions,\n islands: manifest.islands.map((island) => ({ ...island, filePath: relativePath(island.filePath)! })),\n };\n}\n","// --- Adapter capabilities contract (§8.5) ---\n//\n// Every runtime host (Node CLI, Vite dev, Node/Bun adapters, Vercel, Netlify)\n// declares an explicit `AdapterCapabilities` object. The framework uses it to\n// decide which features are safe to enable: streaming, filesystem access,\n// runtime image transforms, background work, body size limits, ISR persistence.\n//\n// Invalid or incompatible capability combinations fail fast during build.\n\nexport type FilesystemCapability = \"none\" | \"readonly\" | \"persistent\" | \"ephemeral\";\n\nexport interface AdapterCapabilities {\n /** Whether the host supports streaming responses (ReadableStream bodies). */\n streaming: boolean;\n /** Filesystem access model of the host. */\n filesystem: FilesystemCapability;\n /** Whether the host can run image transforms at request time. */\n imageRuntime: boolean;\n /** Whether the host allows background work after the response completes. */\n backgroundWork: boolean;\n /** Maximum request body size in bytes accepted by the host (if any). */\n maxBodySize?: number;\n}\n\nexport interface CapabilityOptions {\n streaming?: boolean;\n filesystem?: FilesystemCapability;\n imageRuntime?: boolean;\n backgroundWork?: boolean;\n maxBodySize?: number;\n}\n\n/** Default capabilities for a full-featured long-lived Node/Bun process. */\nexport const DEFAULT_CAPABILITIES: AdapterCapabilities = {\n streaming: true,\n filesystem: \"persistent\",\n imageRuntime: true,\n backgroundWork: true,\n};\n\n/** Default capabilities for a stateless serverless function (Vercel/Netlify). */\nexport const SERVERLESS_CAPABILITIES: AdapterCapabilities = {\n streaming: true,\n filesystem: \"ephemeral\",\n imageRuntime: false,\n backgroundWork: false,\n maxBodySize: 1_048_576,\n};\n\n/** Default capabilities for an edge runtime (read-only filesystem). */\nexport const EDGE_CAPABILITIES: AdapterCapabilities = {\n streaming: true,\n filesystem: \"readonly\",\n imageRuntime: false,\n backgroundWork: false,\n maxBodySize: 1_048_576,\n};\n\nexport function createCapabilities(options: CapabilityOptions = {}): AdapterCapabilities {\n return {\n ...DEFAULT_CAPABILITIES,\n ...options,\n };\n}\n\n/** True when the host supports streaming responses (streaming !== false). */\nexport function supportsStreaming(capabilities: Pick<AdapterCapabilities, \"streaming\"> = { streaming: true }): boolean {\n return capabilities.streaming !== false;\n}\n\n/** True when the host can write to persistent storage (for ISR/cache/image writes). */\nexport function supportsPersistentStorage(capabilities: Pick<AdapterCapabilities, \"filesystem\">): boolean {\n return capabilities.filesystem === \"persistent\";\n}\n\n/** True when the host exposes a writable filesystem at build/runtime. */\nexport function supportsWritableFilesystem(capabilities: Pick<AdapterCapabilities, \"filesystem\">): boolean {\n return capabilities.filesystem === \"persistent\" || capabilities.filesystem === \"ephemeral\";\n}\n\nexport interface CapabilityDiagnostics {\n ok: boolean;\n problems: string[];\n}\n\n/**\n * Validates a capability declaration and reports incompatible combinations.\n * Used by the build pipeline so invalid hosts fail at build time instead of\n * producing a broken runtime.\n */\nexport function validateCapabilities(\n capabilities: AdapterCapabilities,\n features: { isr?: boolean; images?: boolean; streaming?: boolean } = {},\n): CapabilityDiagnostics {\n const problems: string[] = [];\n\n if (features.isr && !supportsPersistentStorage(capabilities)) {\n problems.push(\n `ISR requires a persistent filesystem; the host declares filesystem=\"${capabilities.filesystem}\".`,\n );\n }\n if (features.images && capabilities.imageRuntime === false && capabilities.filesystem === \"none\") {\n problems.push(\n \"On-demand image transforms require either imageRuntime=true or a readable filesystem; the host has neither.\",\n );\n }\n if (features.streaming && capabilities.streaming === false) {\n problems.push(\"Streaming was requested but the host declares streaming=false.\");\n }\n\n return { ok: problems.length === 0, problems };\n}\n","// --- CLI output formatting ---\n//\n// Lightweight colored output without extra dependencies. Colors are enabled\n// only when stdout is a TTY and NO_COLOR is not set (https://no-color.org).\n//\n// Message shape (sober, Vite/Astro style):\n// ✓ message success\n// → message info / pointer\n// ! message warning\n// ✗ message error\n// [tag] message lifecycle events (dev supervisor)\n//\n// `--quiet` suppresses everything except errors.\n\nimport { networkInterfaces } from \"node:os\";\n\nconst useColor = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;\n\nfunction paint(code: number, text: string): string {\n return useColor ? `\\x1b[${code}m${text}\\x1b[0m` : text;\n}\n\nexport const bold = (text: string): string => paint(1, text);\nexport const dim = (text: string): string => paint(2, text);\nexport const red = (text: string): string => paint(31, text);\nexport const green = (text: string): string => paint(32, text);\nexport const yellow = (text: string): string => paint(33, text);\nexport const cyan = (text: string): string => paint(36, text);\n\nlet quiet = false;\n\n/** Enables quiet mode: only errors are printed. */\nexport function setQuiet(value: boolean): void {\n quiet = value;\n}\n\n/** Success message with a green check. */\nexport function success(message: string): void {\n if (quiet) return;\n console.log(`${green(\"✓\")} ${message}`);\n}\n\n/** Indented info line with a cyan arrow. */\nexport function info(message: string): void {\n if (quiet) return;\n console.log(` ${cyan(\"→\")} ${message}`);\n}\n\n/** Indented detail line (file lists, sub-items). */\nexport function detail(message: string): void {\n if (quiet) return;\n console.log(dim(` - ${message}`));\n}\n\n/** Lifecycle event with a dim bracket tag, e.g. [dev], [change]. */\nexport function event(tag: string, message: string): void {\n if (quiet) return;\n console.log(`${dim(`[${tag}]`)} ${message}`);\n}\n\n/** Warning; suppressed in quiet mode. */\nexport function warn(message: string): void {\n if (quiet) return;\n console.warn(`${yellow(\"!\")} ${message}`);\n}\n\n/** Error; always printed, even in quiet mode. */\nexport function error(message: string): void {\n console.error(`${red(\"✗\")} ${message}`);\n}\n\n/** Formats a byte count as \"640 B\", \"1.5 kB\", \"2.3 MB\". */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} kB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/** Formats a duration as \"45ms\" or \"1.23s\". */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) return `${Math.round(ms)}ms`;\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\n/** Build phase line: checkmark + label + dim duration. */\nexport function phase(label: string, durationMs: number): void {\n if (quiet) return;\n console.log(` ${green(\"✓\")} ${label} ${dim(formatDuration(durationMs))}`);\n}\n\nexport interface FileEntry {\n path: string;\n bytes: number;\n}\n\nconst MAX_FILE_ROWS = 20;\nconst SHOWN_FILE_ROWS = 10;\n\n/**\n * Renders the generated-file list as aligned \"path size\" rows (plain text,\n * no color). With more than MAX_FILE_ROWS entries, shows the SHOWN_FILE_ROWS\n * largest plus a \"… and N more\" line.\n */\nexport function fileRows(files: FileEntry[], max = MAX_FILE_ROWS, shown = SHOWN_FILE_ROWS): string[] {\n const sorted = files.length > max\n ? [...files].sort((a, b) => b.bytes - a.bytes)\n : files;\n const visible = sorted.slice(0, files.length > max ? shown : sorted.length);\n const pathWidth = Math.max(...visible.map((f) => f.path.length), 0);\n const sizeWidth = Math.max(...visible.map((f) => formatBytes(f.bytes).length), 0);\n const rows = visible.map(\n (f) => `${f.path.padEnd(pathWidth)} ${formatBytes(f.bytes).padStart(sizeWidth)}`,\n );\n const hidden = files.length - visible.length;\n if (hidden > 0) rows.push(`… and ${hidden} more`);\n return rows;\n}\n\n/** Prints the generated-file list: dim paths, aligned sizes. */\nexport function fileList(files: FileEntry[]): void {\n if (quiet || files.length === 0) return;\n for (const row of fileRows(files)) {\n const sizeMatch = /^(.*?)( \\S+)$/.exec(row);\n if (sizeMatch) {\n console.log(` ${dim(sizeMatch[1])} ${dim(sizeMatch[2])}`);\n } else {\n console.log(` ${dim(row)}`);\n }\n }\n}\n\nexport interface ServerBannerOptions {\n name: string;\n version: string;\n /** Command label, e.g. \"dev\" or \"preview\". */\n command: string;\n localUrl: string;\n networkUrl?: string;\n}\n\n/**\n * Plain-text lines of the server startup banner (Astro-style, no box):\n *\n * elur-kit v2.4.10 dev server running at:\n * → Local: http://localhost:3000/\n * → Network: http://192.168.1.20:3000/\n */\nexport function serverBannerLines(options: ServerBannerOptions): string[] {\n const lines = [\n `${options.name} ${options.version} ${options.command} server running at:`,\n \"\",\n ];\n const labelWidth = options.networkUrl ? \"Network:\".length : \"Local:\".length;\n lines.push(` → ${\"Local:\".padEnd(labelWidth)} ${options.localUrl}`);\n if (options.networkUrl) {\n lines.push(` → ${\"Network:\".padEnd(labelWidth)} ${options.networkUrl}`);\n }\n return lines;\n}\n\n/** Prints the server startup banner with brand colors. */\nexport function serverBanner(options: ServerBannerOptions): void {\n if (quiet) return;\n const [title, blank, ...urls] = serverBannerLines(options);\n console.log();\n console.log(` ${bold(cyan(title))}`);\n console.log(blank);\n for (const line of urls) {\n const arrowEnd = line.indexOf(\"→\") + 1;\n console.log(` ${cyan(\"→\")}${dim(line.slice(arrowEnd))}`);\n }\n}\n\n/** First external (LAN) IPv4 address, for the Network URL. */\nexport function getNetworkAddress(): string | undefined {\n for (const infos of Object.values(networkInterfaces())) {\n for (const info of infos ?? []) {\n if (info.family === \"IPv4\" && !info.internal) return info.address;\n }\n }\n return undefined;\n}\n","// --- Port fallback for dev/preview servers ---\n//\n// When the requested port is busy (EADDRINUSE), the server retries on\n// port+1, port+2, ... up to MAX_PORT_FALLBACK_TRIES times. Detection is\n// error-driven (the listen itself fails) rather than a bind/close probe, so\n// there is no TOCTOU race between checking and binding.\n//\n// When every candidate port is busy the caller should exit with\n// PORT_UNAVAILABLE_EXIT_CODE so the dev supervisor does not restart-loop.\n\nimport type { Server } from \"node:http\";\n\n/** Max ports tried after the requested one before giving up. */\nexport const MAX_PORT_FALLBACK_TRIES = 20;\n\n/**\n * Exit code used when no port in the fallback range is available. The dev\n * supervisor treats it as fatal and does not restart the worker.\n */\nexport const PORT_UNAVAILABLE_EXIT_CODE = 78;\n\nexport interface ListenFallbackOptions {\n /** Max fallbacks after the requested port. Default: MAX_PORT_FALLBACK_TRIES. */\n maxTries?: number;\n /** Called when a busy port is skipped: (busyPort, nextPort). */\n onFallback?: (busyPort: number, nextPort: number) => void;\n}\n\n/**\n * Listens on host:port, falling back to the next port while the failure is\n * EADDRINUSE. Resolves with the port actually bound. Rejects with the\n * original error for non-port failures or when the range is exhausted.\n */\nexport function listenWithFallback(\n server: Server,\n host: string,\n port: number,\n options: ListenFallbackOptions = {},\n): Promise<number> {\n const maxTries = options.maxTries ?? MAX_PORT_FALLBACK_TRIES;\n return new Promise((resolvePromise, reject) => {\n let attempt = 0;\n let candidate = port;\n // Shared listeners: the per-listen callback style would leave stale\n // \"listening\" handlers behind after a failed attempt, resolving with the\n // original (busy) port when the fallback succeeds.\n const onListening = () => {\n server.removeListener(\"error\", onError);\n resolvePromise(candidate);\n };\n const onError = (err: NodeJS.ErrnoException) => {\n server.removeListener(\"listening\", onListening);\n if (err.code === \"EADDRINUSE\" && attempt < maxTries) {\n attempt++;\n const nextPort = port + attempt;\n options.onFallback?.(nextPort - 1, nextPort);\n tryListen(nextPort);\n return;\n }\n reject(err);\n };\n const tryListen = (next: number) => {\n candidate = next;\n server.once(\"error\", onError);\n server.once(\"listening\", onListening);\n server.listen(candidate, host);\n };\n tryListen(port);\n });\n}\n","import { mkdir, rm, rename, stat, cp, access } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join, resolve, dirname, relative } from \"node:path\";\nimport { build as viteBuild, type InlineConfig, type PluginOption } from \"vite\";\nimport { elurJsInterpolationPlugin, shouldUseLegacyInterpolation, type InterpolationMode } from \"../vite/interpolation-plugin.js\";\n\n// --- Programmatic Vite build orchestration ---\n//\n// Replaces the previous `spawnSync(\"npx\", [\"vite\", \"build\", ...])` approach\n// with direct use of the Vite JavaScript API. Benefits:\n//\n// * No child-process overhead or `npx` resolution latency.\n// * Shared module cache across build phases (faster large builds).\n// * Structured errors instead of exit-code parsing.\n// * Atomic output staging: build into a temp directory, then rename to the\n// final destination so a crashed build never leaves a half-written dist.\n\nexport interface ClientBuildOptions {\n /** Project root (absolute). */\n root: string;\n /**\n * Absolute path to the user's Vite client config (e.g.\n * vite.client.config.ts). When omitted, a default config is generated\n * from `defaultInputs` — the generated entry plus, in split builds, the\n * generated router module — so projects get a working bundle with zero\n * client config.\n */\n userConfigPath?: string;\n /**\n * Default bundle inputs (name → absolute entry path) used when no user\n * config is present. With `entry-client` + `router` keys the output is\n * `entry-client.js` + `router.js`.\n */\n defaultInputs?: Record<string, string>;\n /** Absolute path to the app directory (used by the interpolation plugin). */\n appDir: string;\n /** Absolute path to the islands directory (used by the interpolation plugin). */\n islandsDir: string;\n /** Output directory for the client bundle (absolute). */\n outDir: string;\n /** Optional base path. */\n base?: string;\n /** Optional log prefix. */\n logPrefix?: string;\n /** Suppress bundle logs (kit's and Vite's); errors still surface. */\n quiet?: boolean;\n /**\n * How the legacy interpolation transform is handled (default: \"auto\").\n * With a Elur core that supports partial attribute interpolation natively\n * the transform is not applied; use \"legacy\" for migrations against older\n * cores and \"off\" to never transform.\n */\n interpolation?: InterpolationMode;\n}\n\nexport interface ClientBuildResult {\n /** Output directory (same as `outDir` input). */\n outDir: string;\n /** Number of chunks/assets emitted, if reported by Vite. */\n outputCount: number;\n}\n\n/**\n * Build the client hydration bundle using the Vite JavaScript API.\n *\n * The user's config is loaded programmatically and the elur interpolation\n * plugin is injected so partial attribute interpolations inside islands are\n * transformed before reaching the browser.\n */\nexport async function buildClientBundle(options: ClientBuildOptions): Promise<ClientBuildResult> {\n const log = options.logPrefix ?? \"[client]\";\n const quiet = options.quiet ?? false;\n if (!quiet) console.log(`${log} Building hydration bundle...`);\n\n const userConfig = options.userConfigPath\n ? await loadUserConfig(options.userConfigPath, options.root)\n : defaultClientConfig(options.defaultInputs);\n const pluginOptions: PluginOption = shouldUseLegacyInterpolation(options.interpolation ?? \"auto\")\n ? elurJsInterpolationPlugin({\n appDir: options.appDir,\n islandsDir: options.islandsDir,\n })\n : [];\n\n const config: InlineConfig = {\n ...userConfig,\n root: options.root,\n base: options.base ?? userConfig.base ?? \"/\",\n logLevel: quiet ? \"silent\" : userConfig.logLevel,\n build: {\n ...(userConfig.build ?? {}),\n outDir: options.outDir,\n emptyOutDir: true,\n },\n plugins: [...(userConfig.plugins ?? []), pluginOptions],\n configFile: false,\n };\n\n const result = await viteBuild(config);\n const outputs = Array.isArray(result) ? result : [result];\n const outputCount = outputs.reduce(\n (n, r) => n + (\"output\" in r ? (r.output?.length ?? 0) : 0),\n 0,\n );\n if (!quiet) console.log(`${log} ✓ ${outputCount} asset(s) emitted → ${relative(options.root, options.outDir)}`);\n return { outDir: options.outDir, outputCount };\n}\n\nexport async function loadUserConfig(path: string, _root: string): Promise<InlineConfig> {\n const mod = await import(path);\n const raw = mod.default ?? mod;\n const resolved = typeof raw === \"function\" ? await raw({ command: \"build\", mode: \"production\" }) : raw;\n return (resolved && typeof resolved.then === \"function\" ? await resolved : resolved) ?? {};\n}\n\n/**\n * Resolves a user Vite config's `build.rollupOptions.input` to a list of\n * absolute entry paths. Used to detect whether the bundle will emit the\n * generated router module as its own chunk (split build) or not (legacy\n * single-entry bundle — the router stays embedded in the entry).\n */\nexport async function resolveClientInputs(userConfigPath: string, root: string): Promise<string[]> {\n const config = await loadUserConfig(userConfigPath, root);\n const input = config.build?.rollupOptions?.input;\n if (!input || typeof input === \"string\") {\n return input ? [resolve(root, input)] : [];\n }\n const list = Array.isArray(input) ? input : Object.values(input);\n return list\n .filter((v): v is string => typeof v === \"string\")\n .map((v) => resolve(root, v));\n}\n\n/**\n * The synthesized client bundle config used when the project does not ship\n * its own `vite.client.config.*`: named inputs with `[name].js` filenames in\n * ES format — the same contract the docs give to hand-written client\n * configs, so `entry-client` → `entry-client.js` and `router` → `router.js`.\n */\nfunction defaultClientConfig(defaultInputs?: Record<string, string>): InlineConfig {\n return {\n build: {\n rollupOptions: {\n input: defaultInputs ?? {},\n output: { entryFileNames: \"[name].js\", format: \"es\" },\n },\n },\n };\n}\n\n// --- Atomic output staging ---\n\nexport interface AtomicStageOptions {\n /** Final destination directory (absolute). */\n outDir: string;\n /** Build into this temp directory first, then rename to `outDir`. */\n tempDir?: string;\n /** Whether to preserve existing content in `outDir` during the swap. */\n keepExisting?: boolean;\n}\n\nexport interface AtomicStage {\n tempDir: string;\n /** Call after the build succeeds to atomically swap temp → outDir. */\n commit: () => Promise<void>;\n /** Call on failure to clean up the temp directory. */\n rollback: () => Promise<void>;\n}\n\n/**\n * Prepare an atomic staging directory for build output.\n *\n * Usage:\n * const stage = await beginAtomicStage({ outDir });\n * try {\n * await buildInto(stage.tempDir);\n * await stage.commit();\n * } catch (err) {\n * await stage.rollback();\n * throw err;\n * }\n */\nexport async function beginAtomicStage(options: AtomicStageOptions): Promise<AtomicStage> {\n const outDir = resolve(options.outDir);\n const tempDir = resolve(options.tempDir ?? join(dirname(outDir), `.${basename(outDir)}.tmp-${process.pid}`));\n\n // Start from a clean temp directory.\n await rm(tempDir, { recursive: true, force: true });\n await mkdir(tempDir, { recursive: true });\n\n const commit = async () => {\n // Backup the existing output if requested, then swap.\n const backup = options.keepExisting && existsSync(outDir) ? `${outDir}.bak-${process.pid}` : undefined;\n if (backup) {\n await rm(backup, { recursive: true, force: true });\n await safeRename(outDir, backup);\n }\n try {\n await safeRename(tempDir, outDir);\n } catch (err) {\n // On some platforms, renaming across mount points fails. Fall back to a\n // recursive copy + clean, which is not atomic but still correct.\n if (isCrossDevice(err)) {\n await cp(tempDir, outDir, { recursive: true, force: true });\n await rm(tempDir, { recursive: true, force: true });\n } else {\n if (backup) await safeRename(backup, outDir);\n throw err;\n }\n }\n if (backup) await rm(backup, { recursive: true, force: true });\n };\n\n const rollback = async () => {\n await rm(tempDir, { recursive: true, force: true });\n };\n\n return { tempDir, commit, rollback };\n}\n\nfunction basename(path: string): string {\n const parts = path.split(/[\\\\/]+/).filter(Boolean);\n return parts[parts.length - 1] ?? \"output\";\n}\n\nasync function safeRename(src: string, dest: string): Promise<void> {\n await rm(dest, { recursive: true, force: true });\n try {\n await rename(src, dest);\n } catch (err) {\n if (isCrossDevice(err)) {\n await cp(src, dest, { recursive: true, force: true });\n await rm(src, { recursive: true, force: true });\n } else {\n throw err;\n }\n }\n}\n\nfunction isCrossDevice(err: unknown): boolean {\n const code = (err as NodeJS.ErrnoException)?.code;\n return code === \"EXDEV\";\n}\n\n// --- Public asset copy ---\n\nexport interface CopyPublicAssetsOptions {\n /** Absolute path to the public directory. */\n publicDir: string;\n /** Absolute path to the output directory. */\n outDir: string;\n}\n\n/**\n * Copy the public directory into the output directory.\n * Returns the number of files copied.\n */\nexport async function copyPublicAssets(options: CopyPublicAssetsOptions): Promise<number> {\n try {\n await access(options.publicDir);\n const s = await stat(options.publicDir);\n if (!s.isDirectory()) return 0;\n } catch {\n return 0;\n }\n await mkdir(options.outDir, { recursive: true });\n await cp(options.publicDir, options.outDir, { recursive: true, force: true });\n return countFiles(options.outDir);\n}\n\nasync function countFiles(dir: string): Promise<number> {\n const { readdir } = await import(\"node:fs/promises\");\n let count = 0;\n async function walk(d: string): Promise<void> {\n const entries = await readdir(d, { withFileTypes: true });\n for (const entry of entries) {\n const path = join(d, entry.name);\n if (entry.isDirectory()) await walk(path);\n else count++;\n }\n }\n await walk(dir);\n return count;\n}\n","import type { ApiRoute, PageRoute } from \"../router/route-scanner.js\";\n\nexport interface MatchResult {\n route: PageRoute;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n}\n\n/**\n * Match a request pathname against a list of page routes.\n *\n * Routes are sorted by specificity (static > dynamic > catch-all) before\n * matching, so `/about` wins over `/:slug` even if the catch-all appears first.\n *\n * URL segments are safely decoded (plan §11.1, runtime-security §10).\n */\nexport function matchRoute(\n pathname: string,\n routes: PageRoute[],\n): MatchResult | undefined {\n const cleanPath = pathname.split(\"?\")[0];\n const requestSegments = cleanPath.split(\"/\").filter(Boolean).map(safeDecodeURIComponent);\n\n const sorted = [...routes].sort((a, b) => specificity(b.path) - specificity(a.path));\n\n for (const route of sorted) {\n const routeSegments = route.path.split(\"/\").filter(Boolean);\n const match = tryMatch(requestSegments, routeSegments, route.optionalCatchAll);\n if (match) {\n return { route, params: match, searchParams: new URLSearchParams() };\n }\n }\n\n return undefined;\n}\n\nexport interface ApiMatchResult<T = ApiRoute> {\n route: T;\n params: Record<string, string | string[]>;\n}\n\n/**\n * Match a request pathname against a list of API routes.\n */\nexport function matchApiRoute<T extends { path: string }>(pathname: string, routes: T[]): ApiMatchResult<T> | undefined {\n const cleanPath = pathname.split(\"?\")[0];\n const requestSegments = cleanPath.split(\"/\").filter(Boolean).map(safeDecodeURIComponent);\n\n const sorted = [...routes].sort((a, b) => specificity(b.path) - specificity(a.path));\n\n for (const route of sorted) {\n const routeSegments = route.path.split(\"/\").filter(Boolean);\n const match = tryMatch(requestSegments, routeSegments);\n if (match) {\n return { route, params: match };\n }\n }\n\n return undefined;\n}\n\n/**\n * Safely decodes a URI component. If decoding fails (malformed % sequences),\n * returns the original string rather than throwing (runtime-security §10).\n */\nfunction safeDecodeURIComponent(segment: string): string {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n}\n\nfunction specificity(path: string): number {\n return path.split(\"/\").filter(Boolean).reduce((score, segment) => {\n if (segment.endsWith(\"*\")) return score;\n if (segment.startsWith(\":\")) return score + 1;\n return score + 2;\n }, 0);\n}\n\nfunction tryMatch(\n requestSegments: string[],\n routeSegments: string[],\n optionalCatchAll = false,\n): Record<string, string | string[]> | undefined {\n const params: Record<string, string | string[]> = {};\n\n let i = 0;\n for (let r = 0; r < routeSegments.length; r++) {\n const routeSeg = routeSegments[r];\n\n if (routeSeg.endsWith(\"*\")) {\n // Catch-all consumes the rest of the request segments.\n const name = routeSeg.slice(1, -1);\n const rest = requestSegments.slice(i);\n // For optional catch-all, empty rest is OK.\n if (rest.length === 0 && !optionalCatchAll) return undefined;\n params[name] = rest.length > 0 ? rest : [];\n return params;\n }\n\n if (routeSeg.startsWith(\":\")) {\n const requestSeg = requestSegments[i];\n if (requestSeg === undefined) return undefined;\n params[routeSeg.slice(1)] = requestSeg;\n i++;\n continue;\n }\n\n if (routeSeg !== requestSegments[i]) {\n return undefined;\n }\n i++;\n }\n\n if (i !== requestSegments.length) return undefined;\n return params;\n}\n","// --- Middleware ---\n//\n// Convention: `src/middleware.ts` in the project root exports a default\n// function and an optional `config` with a `matcher` array.\n//\n// import type { Middleware } from \"@elurjs/kit\";\n//\n// export default function middleware(request: Request) {\n// if (!request.headers.get(\"Cookie\")?.includes(\"session=\")) {\n// return Response.redirect(new URL(\"/login\", request.url), 307);\n// }\n// }\n//\n// export const config = { matcher: [\"/dashboard/:path*\", \"/admin/:path*\"] };\n//\n// The middleware runs before routing. Return a `Response` to short-circuit\n// (redirect, rewrite, 401, etc.). Return `undefined` or nothing to continue.\n// Use `next()` to pass headers to the loader.\n\nimport { matchRoute } from \"../ssr/match.js\";\nimport type { PageRoute } from \"../router/route-scanner.js\";\n\n/** The middleware function signature. */\nexport type Middleware = (request: Request, context: MiddlewareContext) =>\n | Response\n | void\n | Promise<Response | void>;\n\n/** Context passed to the middleware function. */\nexport interface MiddlewareContext {\n /** Helper to continue to the next handler. Can attach headers, params, and locals. */\n next(options?: {\n headers?: Record<string, string>;\n params?: Record<string, string | string[]>;\n locals?: Record<string, unknown>;\n }): void;\n /** Matched route params (only available if the path matches a page route). */\n params?: Record<string, string | string[]>;\n /** Per-request locals (populated by middleware, available to loaders/actions). */\n locals?: Record<string, unknown>;\n}\n\n/** Configuration for the middleware module. */\nexport interface MiddlewareConfig {\n /** Path patterns that trigger the middleware. Supports `:param` and `:param*`. */\n matcher?: string[];\n}\n\nexport interface LoadedMiddleware {\n handler: Middleware;\n config: MiddlewareConfig;\n}\n\n/** Result of running middleware: either a response to short-circuit with, or continue. */\nexport type MiddlewareResult =\n | { kind: \"response\"; response: Response }\n | {\n kind: \"continue\";\n headers?: Record<string, string>;\n params?: Record<string, string | string[]>;\n locals?: Record<string, unknown>;\n };\n\n/**\n * Loads the user's `src/middleware.ts` module. Returns `null` if no middleware\n * file exists. Distinguishes \"file not found\" from \"file has errors\" (§6):\n * an import error is not silently treated as \"no middleware\".\n */\nexport async function loadMiddleware(root: string): Promise<LoadedMiddleware | null> {\n const candidates = [\n `${root}/src/middleware.ts`,\n `${root}/middleware.ts`,\n ];\n\n for (const path of candidates) {\n try {\n const mod = await import(path);\n const handler = (mod.default ?? mod.middleware) as Middleware | undefined;\n if (typeof handler !== \"function\") continue;\n const config = (mod.config ?? {}) as MiddlewareConfig;\n return { handler, config };\n } catch (err) {\n // Distinguish \"module not found\" from actual errors.\n // If the error is a module resolution error for this specific file,\n // it means the file doesn't exist — try the next candidate.\n // If it's a syntax/runtime error, rethrow so the user sees it.\n // Note: Bun's ResolveMessage is not `instanceof Error`, so match on the\n // message property instead of relying on the class hierarchy.\n const msg =\n typeof err === \"object\" && err !== null && \"message\" in err\n ? String((err as { message: unknown }).message)\n : String(err);\n if (\n msg.includes(\"Cannot find module\") ||\n msg.includes(\"Cannot find package\") ||\n msg.includes(\"ENOENT\") ||\n msg.includes(\"Module not found\")\n ) {\n // File doesn't exist — try next candidate.\n continue;\n }\n // Actual error in the middleware file — rethrow (§6).\n throw new Error(`[elur-kit] Error loading middleware: ${msg}`, { cause: err });\n }\n }\n\n return null;\n}\n\n/**\n * Checks if a pathname matches any of the middleware's matcher patterns.\n * If no matcher is configured, the middleware runs for every request.\n *\n * Catch-all patterns (`:param*`) match both the base path and any sub-paths,\n * e.g. `/dashboard/:path*` matches `/dashboard` and `/dashboard/settings/users`.\n */\nexport function matchesMiddleware(pathname: string, config: MiddlewareConfig): boolean {\n if (!config.matcher || config.matcher.length === 0) return true;\n\n const cleanPath = pathname.split(\"?\")[0];\n\n for (const pattern of config.matcher) {\n // Exact match.\n if (pattern === cleanPath) return true;\n\n // Check for catch-all: `/foo/:bar*` should also match `/foo`.\n const catchAllMatch = pattern.match(/^(.*)\\/:[\\w]+\\*$/);\n if (catchAllMatch) {\n const base = catchAllMatch[1];\n if (cleanPath === base) return true;\n }\n\n // Use matchRoute for param matching.\n const pseudoRoutes: PageRoute[] = [{\n path: pattern,\n pagePath: \"\",\n params: [],\n layouts: [],\n }];\n if (matchRoute(cleanPath, pseudoRoutes)) return true;\n }\n\n return false;\n}\n\n/**\n * Runs the middleware for a request. Returns the result indicating whether to\n * short-circuit with a response or continue with propagated headers/params/locals.\n *\n * Per §6: cleanup runs in `finally`, response short-circuits the pipeline,\n * headers/params/locals are propagated to downstream handlers.\n */\nexport async function runMiddleware(\n middleware: LoadedMiddleware,\n request: Request,\n params?: Record<string, string | string[]>,\n): Promise<MiddlewareResult> {\n let nextHeaders: Record<string, string> | undefined;\n let nextParams: Record<string, string | string[]> | undefined;\n let nextLocals: Record<string, unknown> | undefined;\n const cleanups: Array<() => void | Promise<void>> = [];\n\n const context: MiddlewareContext = {\n next(options) {\n if (options?.headers) nextHeaders = options.headers;\n if (options?.params) nextParams = options.params;\n if (options?.locals) nextLocals = options.locals;\n },\n params,\n locals: {},\n };\n\n try {\n const result = await middleware.handler(request, context);\n\n if (result instanceof Response) {\n return { kind: \"response\", response: result };\n }\n\n return {\n kind: \"continue\",\n headers: nextHeaders,\n params: nextParams ?? params,\n locals: nextLocals,\n };\n } finally {\n // Run any cleanup functions (§6). Errors in cleanup are logged but\n // do not propagate to the caller.\n for (const cleanup of cleanups) {\n try {\n await cleanup();\n } catch (err) {\n console.error(\"[elur-kit] middleware cleanup error:\", err);\n }\n }\n }\n}\n","/**\n * Represents a failed action result. Returned by `fail()` from server actions.\n *\n * The `__elur_js_action_failure` marker is set on the instance so the server can\n * detect it even when the value crosses a bundling boundary (e.g. the CLI is\n * bundled separately from the user's action modules).\n */\nexport class ActionFailure<TData = unknown> {\n readonly __elur_js_action_failure = true;\n constructor(\n public status: number,\n public data: TData,\n ) {}\n}\n\n/**\n * Represents a redirect returned by a server action. Returned by `redirect()`.\n */\nexport class RedirectResponse {\n readonly __elur_js_action_redirect = true;\n constructor(\n public status: number,\n public location: string,\n ) {}\n}\n\n/**\n * Helper to return a validation/error response from a server action.\n *\n * Both argument orders are accepted:\n *\n * ```ts\n * return fail(400, { email: \"Invalid email\" });\n * return fail({ email: \"Invalid email\" }, 400);\n * return fail({ email: \"Invalid email\" }); // defaults to status 400\n * ```\n */\nexport function fail<TData>(\n statusOrData: number | TData,\n dataOrStatus?: TData | number,\n): ActionFailure<unknown> {\n if (typeof statusOrData === \"number\") {\n return new ActionFailure(statusOrData, dataOrStatus as TData);\n }\n return new ActionFailure((dataOrStatus as number) ?? 400, statusOrData);\n}\n\n/**\n * Helper to return a redirect from a server action.\n *\n * Both argument orders are accepted:\n *\n * ```ts\n * return redirect(303, \"/login\");\n * return redirect(\"/login\"); // defaults to status 303\n * ```\n */\nexport function redirect(\n statusOrLocation: number | string,\n locationOrStatus?: string | number,\n): RedirectResponse {\n if (typeof statusOrLocation === \"number\") {\n return new RedirectResponse(statusOrLocation, locationOrStatus as string);\n }\n return new RedirectResponse((locationOrStatus as number) ?? 303, statusOrLocation);\n}\n\n/**\n * Type guard for action failures. Uses the marker field so it works across\n * bundling boundaries where `instanceof` fails.\n */\nexport function isActionFailure(value: unknown): value is ActionFailure {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as { __elur_js_action_failure?: unknown }).__elur_js_action_failure === true\n );\n}\n\n/**\n * Type guard for redirects. Uses the marker field so it works across bundling\n * boundaries where `instanceof` fails.\n */\nexport function isRedirectResponse(value: unknown): value is RedirectResponse {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as { __elur_js_action_redirect?: unknown }).__elur_js_action_redirect === true\n );\n}\n\n// --- Public error sanitization (production-safe 500 responses) ---\n\n/**\n * A stable, publicly safe error description. Never includes stacks, internal\n * paths or messages that could leak secrets or filesystem details.\n */\nexport interface PublicErrorInfo {\n /** Stable machine-readable code for the response body. */\n code: string;\n /** Stable public message. In non-production this may include the raw message. */\n message: string;\n status: number;\n}\n\n/**\n * Maps an arbitrary thrown value to a public-safe error info. By default the\n * public message is generic; `includeDetail` (dev/verbose mode) appends the\n * original `Error.message` for local debugging.\n */\nexport function toPublicErrorInfo(error: unknown, options: { includeDetail?: boolean } = {}): PublicErrorInfo {\n const code = \"INTERNAL_SERVER_ERROR\";\n const status = 500;\n if (options.includeDetail && error instanceof Error && error.message) {\n return { code, status, message: error.message };\n }\n return { code, status, message: \"Internal Server Error\" };\n}\n\n/**\n * Builds a production-safe JSON error Response. Logs the raw error separately\n * (never reflected in the response body) and keeps the request id header.\n */\nexport function publicErrorResponse(\n error: unknown,\n options: { includeDetail?: boolean; requestId?: string } = {},\n): Response {\n const info = toPublicErrorInfo(error, options);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n };\n if (options.requestId) headers[\"X-Request-Id\"] = options.requestId;\n return new Response(JSON.stringify({ error: info }), {\n status: info.status,\n headers,\n });\n}\n\n/** True when the error should be re-thrown as control flow instead of a 500. */\nexport function isFirstClassResponse(error: unknown): error is Response {\n return typeof Response !== \"undefined\" && error instanceof Response;\n}\n","// --- Origin verification (CSRF protection for server actions) ---\n//\n// Server actions accept POST requests from the browser. Without origin\n// verification, any third-party site could submit forged requests to\n// `/__elur-js/actions` on behalf of a logged-in user (CSRF).\n//\n// Strategy: compare the request's `Origin` (or `Referer` fallback) host against\n// the target `Host` header. Same-origin requests pass; cross-origin requests\n// are rejected with 403 unless the origin is explicitly allow-listed.\n//\n// Requests without `Origin` AND without `Referer` (e.g. curl, server-to-server)\n// are accepted by default for DX, unless `strictOrigin: true` is configured.\n\nexport interface OriginCheckOptions {\n /** Extra origins allowed to call actions (e.g. preview deployments). */\n allowedOrigins?: string[];\n /**\n * When true, requests missing both `Origin` and `Referer` are rejected.\n * Defaults to false so curl/server-to-server calls keep working.\n */\n strictOrigin?: boolean;\n}\n\n/**\n * Returns the host:port of a URL string, or undefined if it cannot be parsed.\n */\nfunction originOf(urlString: string | null | undefined): string | undefined {\n if (!urlString) return undefined;\n try {\n const url = new URL(urlString);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") return undefined;\n return url.origin;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Verifies that a request originates from the same host (or an allow-listed\n * origin). Returns an error message when the request must be rejected, or\n * undefined when it is allowed.\n *\n * @param request The incoming Request to actions.\n * @param options Origin check configuration.\n */\nexport function verifyOrigin(\n request: Request,\n options: OriginCheckOptions = {},\n): string | undefined {\n const targetOrigin = originOf(request.url);\n if (!targetOrigin) return \"Invalid target URL\";\n\n const origin = request.headers.get(\"Origin\");\n const referer = request.headers.get(\"Referer\");\n if (!origin && !referer) {\n return options.strictOrigin\n ? \"Missing Origin and Referer headers\"\n : undefined;\n }\n\n const sourceOrigin = origin ? originOf(origin) : originOf(referer);\n if (!sourceOrigin) return origin ? \"Invalid Origin header\" : \"Invalid Referer header\";\n if (sourceOrigin === targetOrigin) return undefined;\n\n if (options.allowedOrigins?.some((allowed) => originOf(allowed) === sourceOrigin)) return undefined;\n\n return `Cross-origin request blocked: source \"${sourceOrigin}\" != target \"${targetOrigin}\"`;\n}\n\n/** Builds a 403 Response for a rejected origin. */\nexport function originForbidden(message: string): Response {\n return new Response(message, {\n status: 403,\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\" },\n });\n}\n","// --- CacheAdapter: pluggable cache with single-flight, SWR, tags (§9.2) ---\n//\n// Implements the CacheAdapter interface from the runtime-security design:\n// - SHA-256 keys for normalized identity\n// - temp + atomic rename writes\n// - single-flight per process (deduplicates concurrent gets for same key)\n// - stale-while-revalidate (serves stale, refreshes in background)\n// - tag-based invalidation\n// - size limits and periodic cleanup\n//\n// The filesystem adapter is the default. External adapters (Redis, KV, etc.)\n// can implement the same interface and be plugged in via config.\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, writeFile, readdir, stat } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\n// Types\n\nexport interface CacheEntry {\n html: string;\n generatedAt: number;\n revalidate: number;\n tags?: string[];\n version?: string;\n}\n\nexport interface CacheWriteOptions {\n revalidate: number;\n tags?: string[];\n version?: string;\n}\n\nexport interface CacheAdapter {\n get(key: string): Promise<CacheEntry | null>;\n set(key: string, value: CacheEntry, options: CacheWriteOptions): Promise<void>;\n delete(key: string): Promise<void>;\n invalidateTags(tags: readonly string[]): Promise<void>;\n}\n\n// Helpers\n\n/** Computes a SHA-256 key from a normalized identity string. */\nexport function cacheKey(...parts: string[]): string {\n return createHash(\"sha256\").update(parts.join(\"\\n\")).digest(\"hex\");\n}\n\n// Filesystem CacheAdapter\n\nexport interface FsCacheAdapterOptions {\n cacheDir: string;\n /** Max entries before cleanup runs. Default: 1000. */\n maxEntries?: number;\n /** Max age in ms for entries. Default: 24h. */\n maxAgeMs?: number;\n}\n\nexport function createFsCacheAdapter(options: FsCacheAdapterOptions): CacheAdapter {\n const { cacheDir } = options;\n const maxEntries = options.maxEntries ?? 1000;\n const maxAgeMs = options.maxAgeMs ?? 24 * 60 * 60 * 1000;\n\n // Single-flight: deduplicates concurrent gets for the same key.\n const inFlight = new Map<string, Promise<CacheEntry | null>>();\n\n // Tag index: maps tag -> set of cache keys.\n // Persisted to a JSON file for cross-process visibility.\n const tagIndexPath = join(cacheDir, \"_tag-index.json\");\n\n async function loadTagIndex(): Promise<Record<string, string[]>> {\n try {\n const raw = await readFile(tagIndexPath, \"utf8\");\n return JSON.parse(raw) as Record<string, string[]>;\n } catch {\n return {};\n }\n }\n\n async function saveTagIndex(index: Record<string, string[]>): Promise<void> {\n await mkdir(dirname(tagIndexPath), { recursive: true });\n const tmp = `${tagIndexPath}.${process.pid}.${randomUUID()}.tmp`;\n try {\n await writeFile(tmp, JSON.stringify(index), \"utf8\");\n await rename(tmp, tagIndexPath);\n } finally {\n await rm(tmp, { force: true });\n }\n }\n\n function entryPath(key: string): string {\n return join(cacheDir, `${key}.html.json`);\n }\n\n async function get(key: string): Promise<CacheEntry | null> {\n // Single-flight: if a get is already in progress for this key, wait for it.\n const existing = inFlight.get(key);\n if (existing) return existing;\n\n const promise = (async () => {\n try {\n const raw = await readFile(entryPath(key), \"utf8\");\n const entry = JSON.parse(raw) as CacheEntry;\n return entry;\n } catch {\n return null;\n }\n })();\n\n inFlight.set(key, promise);\n try {\n return await promise;\n } finally {\n inFlight.delete(key);\n }\n }\n\n async function set(key: string, value: CacheEntry, opts: CacheWriteOptions): Promise<void> {\n const path = entryPath(key);\n await mkdir(dirname(path), { recursive: true });\n\n const entry: CacheEntry = {\n html: value.html,\n generatedAt: value.generatedAt ?? Date.now(),\n revalidate: opts.revalidate,\n tags: opts.tags,\n version: opts.version,\n };\n\n // Atomic write: temp + rename.\n const tmp = `${path}.${process.pid}.${randomUUID()}.tmp`;\n try {\n await writeFile(tmp, JSON.stringify(entry), \"utf8\");\n await rename(tmp, path);\n } finally {\n await rm(tmp, { force: true });\n }\n\n // Update tag index.\n if (opts.tags && opts.tags.length > 0) {\n const index = await loadTagIndex();\n for (const tag of opts.tags) {\n if (!index[tag]) index[tag] = [];\n if (!index[tag].includes(key)) index[tag].push(key);\n }\n await saveTagIndex(index);\n }\n\n // Periodic cleanup.\n await maybeCleanup();\n }\n\n async function del(key: string): Promise<void> {\n await rm(entryPath(key), { force: true });\n }\n\n async function invalidateTags(tags: readonly string[]): Promise<void> {\n if (tags.length === 0) return;\n const index = await loadTagIndex();\n const keysToDelete = new Set<string>();\n for (const tag of tags) {\n const keys = index[tag];\n if (keys) {\n for (const key of keys) keysToDelete.add(key);\n delete index[tag];\n }\n }\n await Promise.all([...keysToDelete].map((key) => del(key)));\n await saveTagIndex(index);\n }\n\n let lastCleanup = 0;\n async function maybeCleanup(): Promise<void> {\n const now = Date.now();\n if (now - lastCleanup < 60_000) return; // at most once per minute\n lastCleanup = now;\n try {\n const files = await readdir(cacheDir);\n let entryCount = 0;\n const toDelete: string[] = [];\n for (const file of files) {\n if (!file.endsWith(\".html.json\")) continue;\n entryCount++;\n const filePath = join(cacheDir, file);\n try {\n const stats = await stat(filePath);\n if (now - stats.mtimeMs > maxAgeMs) {\n toDelete.push(filePath);\n }\n } catch {\n // stat failed, skip\n }\n }\n // If over limit, delete oldest (by mtime).\n if (entryCount - toDelete.length > maxEntries) {\n const candidates: Array<{ path: string; mtime: number }> = [];\n for (const file of files) {\n if (!file.endsWith(\".html.json\")) continue;\n const filePath = join(cacheDir, file);\n if (toDelete.includes(filePath)) continue;\n try {\n const stats = await stat(filePath);\n candidates.push({ path: filePath, mtime: stats.mtimeMs });\n } catch {\n // skip\n }\n }\n candidates.sort((a, b) => a.mtime - b.mtime);\n const excess = entryCount - toDelete.length - maxEntries;\n for (let i = 0; i < excess && i < candidates.length; i++) {\n toDelete.push(candidates[i].path);\n }\n }\n await Promise.all(toDelete.map((p) => rm(p, { force: true })));\n } catch {\n // cleanup is best-effort\n }\n }\n\n return { get, set, delete: del, invalidateTags };\n}\n\n// Stale-while-revalidate wrapper\n\n/**\n * Gets a cached entry. If the entry is stale (past revalidate), serves it\n * immediately and triggers a background revalidation.\n *\n * @param adapter The cache adapter.\n * @param key The cache key.\n * @param revalidate The revalidation function (called if stale or missing).\n * @returns The cache entry (fresh or stale), or null if missing.\n */\nexport async function getWithSWR(\n adapter: CacheAdapter,\n key: string,\n revalidate: () => Promise<CacheEntry | null>,\n): Promise<{ entry: CacheEntry | null; stale: boolean }> {\n const entry = await adapter.get(key);\n if (!entry) {\n // Cache miss: revalidate synchronously.\n const fresh = await revalidate();\n return { entry: fresh, stale: false };\n }\n\n const ageMs = Date.now() - entry.generatedAt;\n const isStale = ageMs >= entry.revalidate * 1000;\n\n if (isStale) {\n // Serve stale, revalidate in background (fire-and-forget).\n revalidate().then(\n (fresh) => {\n if (fresh) {\n adapter.set(key, fresh, {\n revalidate: entry.revalidate,\n tags: entry.tags,\n version: entry.version,\n }).catch((err) => {\n console.error(\"[elur-kit] background cache write failed:\", err);\n });\n }\n },\n (err) => {\n console.error(\"[elur-kit] background revalidation failed:\", err);\n },\n );\n return { entry, stale: true };\n }\n\n return { entry, stale: false };\n}\n","// --- Cache invalidation hooks (runtime-security §9.4) ---\n//\n// Actions can emit tags/paths to invalidate via a generic context. The cache\n// server listens to these hooks and invalidates the appropriate entries.\n// Integrations like elur-query can also listen, but they are NOT a dependency\n// of the cache server.\n//\n// Design:\n// - `CacheInvalidator` is a simple pub/sub for invalidation events.\n// - The runtime registers an invalidator with the cache adapter.\n// - Actions call `invalidateTags()` / `invalidatePaths()` from their context.\n// - The invalidator dispatches to all registered listeners.\n\nexport interface InvalidationEvent {\n tags?: readonly string[];\n paths?: readonly string[];\n /** Source of the invalidation (e.g. action name). */\n source?: string;\n}\n\nexport type InvalidationListener = (event: InvalidationEvent) => void | Promise<void>;\n\n/**\n * A pub/sub hub for cache invalidation events. Actions emit events;\n * the cache adapter (and optionally elur-query or other integrations) listen.\n */\nexport class CacheInvalidator {\n private listeners = new Set<InvalidationListener>();\n\n /** Registers a listener for invalidation events. Returns an unsubscribe function. */\n on(listener: InvalidationListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /** Emits an invalidation event to all listeners. */\n async emit(event: InvalidationEvent): Promise<void> {\n const promises: Array<Promise<void>> = [];\n for (const listener of this.listeners) {\n try {\n const result = listener(event);\n if (result instanceof Promise) {\n // Wrap to prevent unhandled rejection from failing the whole emit.\n promises.push(result.catch((err) => {\n console.error(\"[elur-kit] invalidation listener error:\", err);\n }));\n }\n } catch (err) {\n console.error(\"[elur-kit] invalidation listener error:\", err);\n }\n }\n await Promise.all(promises);\n }\n\n /** Convenience: invalidate by tags. */\n async invalidateTags(tags: readonly string[], source?: string): Promise<void> {\n if (tags.length === 0) return;\n await this.emit({ tags, source });\n }\n\n /** Convenience: invalidate by paths. */\n async invalidatePaths(paths: readonly string[], source?: string): Promise<void> {\n if (paths.length === 0) return;\n await this.emit({ paths, source });\n }\n\n /** Removes all listeners. */\n clear(): void {\n this.listeners.clear();\n }\n}\n\n/** Global default invalidator. The runtime registers the cache adapter here. */\nexport const defaultInvalidator = new CacheInvalidator();\n\n/**\n * Connects a CacheAdapter to the default invalidator so that tag/path\n * invalidation events from actions are dispatched to the cache.\n *\n * Returns an unsubscribe function.\n */\nexport function connectCacheAdapter(\n adapter: {\n invalidateTags: (tags: readonly string[]) => Promise<void>;\n delete?: (key: string) => Promise<void>;\n },\n invalidator: CacheInvalidator = defaultInvalidator,\n): () => void {\n return invalidator.on(async (event) => {\n if (event.tags && event.tags.length > 0) {\n await adapter.invalidateTags(event.tags);\n }\n // Path-based invalidation: the adapter needs to know which cache keys\n // correspond to which paths. This is handled by the runtime mapping\n // paths to cache keys before calling delete().\n if (event.paths && event.paths.length > 0 && adapter.delete) {\n // The runtime should register a path-to-key mapper.\n // For now, we use the path as the cache key directly (SHA-256 of path).\n const { cacheKey } = await import(\"./adapter.js\");\n await Promise.all(event.paths.map((p) => adapter.delete!(cacheKey(p))));\n }\n });\n}\n","import type { ActionRequest } from \"./index.js\";\nimport { isActionFailure, isRedirectResponse, publicErrorResponse } from \"../errors.js\";\nimport { verifyOrigin, originForbidden, type OriginCheckOptions } from \"./origin.js\";\nimport type { ActionContext } from \"./define.js\";\nimport { defaultInvalidator } from \"../cache/invalidation.js\";\nimport {\n encodeActionErrorCookie,\n setActionErrorCookieHeader,\n} from \"./error-store.js\";\n\n/**\n * Resolves a server action by name and optional page scope.\n */\nexport type ActionResolver = (\n name: string,\n page?: string,\n) => Promise<((...args: unknown[]) => unknown) | undefined>;\n\n/** Options shared by `handleActionRequest` callers for CSRF protection. */\nexport interface ActionSecurityOptions extends OriginCheckOptions {\n /** Maximum body size in bytes. Defaults to 1MB (1_048_576). */\n bodyLimit?: number;\n}\n\n/** Default body size limit: 1MB. */\nconst DEFAULT_BODY_LIMIT = 1_048_576;\n\n/**\n * Reads the request body as text, enforcing a maximum size.\n * Returns a 413 response if the body exceeds the limit.\n */\nasync function readBodyWithLimit(\n request: Request,\n limit: number,\n): Promise<{ ok: true; text: string } | { ok: false; response: Response }> {\n const contentLength = request.headers.get(\"Content-Length\");\n if (contentLength && parseInt(contentLength, 10) > limit) {\n return {\n ok: false,\n response: new Response(\"Request body too large\", {\n status: 413,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n // Read the body as a stream with a size cap to prevent memory exhaustion\n // from chunked transfer encoding without Content-Length.\n const reader = request.body?.getReader();\n if (!reader) {\n return { ok: true, text: \"\" };\n }\n const chunks: Uint8Array[] = [];\n let totalSize = 0;\n try {\n for (; ;) {\n const { done, value } = await reader.read();\n if (done) break;\n totalSize += value.byteLength;\n if (totalSize > limit) {\n try { reader.cancel(); } catch { /* ignore */ }\n return {\n ok: false,\n response: new Response(\"Request body too large\", {\n status: 413,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n chunks.push(value);\n }\n } finally {\n try { reader.releaseLock(); } catch { /* ignore */ }\n }\n const total = new Uint8Array(totalSize);\n let offset = 0;\n for (const chunk of chunks) {\n total.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return { ok: true, text: new TextDecoder().decode(total) };\n}\n\nfunction parseFormBody(body: string): Record<string, unknown> {\n const params = new URLSearchParams(body);\n const result: Record<string, unknown> = {};\n for (const [key, value] of params) {\n if (result[key] === undefined) {\n result[key] = value;\n } else if (Array.isArray(result[key])) {\n (result[key] as unknown[]).push(value);\n } else {\n result[key] = [result[key], value];\n }\n }\n return result;\n}\n\nasync function parseActionRequest(\n request: Request,\n bodyLimit: number = DEFAULT_BODY_LIMIT,\n): Promise<\n | { ok: true; name: string; page?: string; args: unknown[]; wantsJson: boolean }\n | { ok: false; response: Response }\n> {\n if (request.method !== \"POST\") {\n return {\n ok: false,\n response: new Response(\"Method not allowed\", {\n status: 405,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n\n const contentType = request.headers.get(\"Content-Type\") ?? \"\";\n const wantsJson = (request.headers.get(\"Accept\") ?? \"\").includes(\"application/json\");\n\n let name: string | undefined;\n let page: string | undefined;\n let args: unknown[] = [];\n\n if (contentType.includes(\"application/json\")) {\n const bodyResult = await readBodyWithLimit(request, bodyLimit);\n if (!bodyResult.ok) return { ok: false, response: bodyResult.response };\n let body: ActionRequest;\n try {\n body = JSON.parse(bodyResult.text) as ActionRequest;\n } catch {\n return {\n ok: false,\n response: new Response(\"Invalid JSON body\", {\n status: 400,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n name = body.name;\n page = body.page;\n args = Array.isArray(body.args) ? body.args : [];\n } else if (\n contentType.includes(\"application/x-www-form-urlencoded\") ||\n contentType.includes(\"multipart/form-data\")\n ) {\n // For multipart, use the native formData() parser after checking\n // Content-Length against the limit. For urlencoded, use our size-capped\n // reader to handle chunked encoding without Content-Length.\n if (contentType.includes(\"multipart/form-data\")) {\n const contentLength = request.headers.get(\"Content-Length\");\n if (contentLength && parseInt(contentLength, 10) > bodyLimit) {\n return {\n ok: false,\n response: new Response(\"Request body too large\", {\n status: 413,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n let form: FormData;\n try {\n form = await request.formData();\n } catch {\n return {\n ok: false,\n response: new Response(\"Invalid form body\", {\n status: 400,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n name = form.get(\"__elur_js_action_name\") as string | null ?? undefined;\n page = form.get(\"__elur_js_action_page\") as string | null ?? undefined;\n const input: Record<string, unknown> = {};\n for (const [key, value] of form) {\n if (key === \"__elur_js_action_name\" || key === \"__elur_js_action_page\") continue;\n input[key] = value;\n }\n args = [input];\n } else {\n const bodyResult = await readBodyWithLimit(request, bodyLimit);\n if (!bodyResult.ok) return { ok: false, response: bodyResult.response };\n const form = parseFormBody(bodyResult.text);\n name = form.__elur_js_action_name as string | undefined;\n page = form.__elur_js_action_page as string | undefined;\n const input: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(form)) {\n if (key === \"__elur_js_action_name\" || key === \"__elur_js_action_page\") continue;\n input[key] = value;\n }\n args = [input];\n }\n } else {\n // Try to parse a plain form body as a fallback for progressive enhancement.\n const bodyResult = await readBodyWithLimit(request, bodyLimit);\n if (!bodyResult.ok) return { ok: false, response: bodyResult.response };\n const form = parseFormBody(bodyResult.text);\n name = form.__elur_js_action_name as string | undefined;\n page = form.__elur_js_action_page as string | undefined;\n const input: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(form)) {\n if (key === \"__elur_js_action_name\" || key === \"__elur_js_action_page\") continue;\n input[key] = value;\n }\n args = [input];\n }\n\n if (!name || typeof name !== \"string\") {\n return {\n ok: false,\n response: new Response(\"Missing action name\", {\n status: 400,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n\n return { ok: true, name, page, args, wantsJson };\n}\n\n/**\n * Handles a POST request to the server action endpoint.\n *\n * Accepts both JSON requests (`{ name, page?, args }`) and HTML form submissions\n * for progressive enhancement. The provided resolver looks up the action\n * implementation, invokes it with the supplied arguments and returns the result\n * as JSON or redirects back to the request origin for form submissions.\n *\n * Origin verification (CSRF protection) runs before parsing the body: any\n * cross-origin POST is rejected with 403 unless its origin is allow-listed via\n * `security.allowedOrigins`.\n *\n * For progressive-enhancement form submissions that fail, the failure payload\n * is relayed back via a short-lived `__elur_js_action_error` cookie (SameSite=Lax,\n * Max-Age=15s) instead of a query param, so errors do not leak into browser\n * history, server logs or third-party Referer headers.\n */\nexport async function handleActionRequest(\n request: Request,\n resolveAction: ActionResolver,\n security: ActionSecurityOptions = {},\n): Promise<Response> {\n // CSRF: verify same-origin (or allow-listed) before doing any work.\n const originError = verifyOrigin(request, security);\n if (originError) return originForbidden(originError);\n\n const parsed = await parseActionRequest(request, security.bodyLimit ?? DEFAULT_BODY_LIMIT);\n if (!parsed.ok) return parsed.response;\n\n const { name, page, args, wantsJson } = parsed;\n\n try {\n const action = await resolveAction(name, page);\n if (!action) {\n const message = page ? `Action not found: ${name} (page: ${page})` : `Action not found: ${name}`;\n return new Response(message, {\n status: 404,\n headers: { \"Content-Type\": \"text/plain\" },\n });\n }\n\n // defineAction() functions take (input, ctx) and carry __elurAction\n // metadata; legacy plain actions take (...args). Route params are not\n // known at this endpoint (actions resolve by page path), so params and\n // locals start empty — middleware/page context can fill them elsewhere.\n const actionMeta = (action as { __elurAction?: { invalidateTags?: readonly string[]; invalidatePaths?: readonly string[] } }).__elurAction;\n let result: unknown;\n if (actionMeta) {\n const ctx: ActionContext = {\n request,\n signal: request.signal,\n idempotencyKey: request.headers.get(\"Idempotency-Key\") ?? undefined,\n params: {},\n locals: {},\n };\n result = await action(args[0], ctx);\n } else {\n result = await action(...args);\n }\n\n // Cache invalidation (§9.4): actions defined with defineAction() declare\n // invalidateTags/invalidatePaths metadata; dispatch them to connected\n // cache adapters after a successful run (not on ActionFailure).\n if (!isActionFailure(result) && actionMeta) {\n const tags = actionMeta.invalidateTags ?? [];\n const paths = actionMeta.invalidatePaths ?? [];\n if (tags.length > 0 || paths.length > 0) {\n await defaultInvalidator.emit({ tags, paths, source: name });\n }\n }\n\n if (isActionFailure(result)) {\n if (wantsJson) {\n return new Response(JSON.stringify({ __elur_js_action_failure: true, status: result.status, data: result.data }), {\n status: result.status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n // Progressive enhancement: redirect back with the failure in a cookie.\n const referer = request.headers.get(\"Referer\") ?? \"/\";\n const url = new URL(referer, \"http://localhost\");\n const { value } = encodeActionErrorCookie(result.data, result.status);\n return new Response(null, {\n status: 303,\n headers: {\n Location: url.pathname + url.search,\n \"Content-Type\": \"text/plain\",\n \"Set-Cookie\": setActionErrorCookieHeader(value),\n },\n });\n }\n\n if (isRedirectResponse(result)) {\n if (wantsJson) {\n return new Response(\n JSON.stringify({ __elur_js_action_redirect: true, status: result.status, location: result.location }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n }\n return new Response(null, {\n status: result.status,\n headers: { Location: result.location, \"Content-Type\": \"text/plain\" },\n });\n }\n\n if (wantsJson) {\n return new Response(JSON.stringify(result ?? null), {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n // For progressive enhancement (plain form POST), redirect back.\n const referer = request.headers.get(\"Referer\") ?? \"/\";\n return new Response(null, {\n status: 303,\n headers: {\n Location: typeof result === \"string\" ? result : referer,\n \"Content-Type\": \"text/plain\",\n },\n });\n } catch (err) {\n console.error(\"[elur-kit] Action error:\", err);\n return publicErrorResponse(err, { includeDetail: false });\n }\n}\n\nexport { verifyOrigin, originForbidden, type OriginCheckOptions } from \"./origin.js\";\nexport {\n decodeActionErrorCookie,\n clearActionErrorCookieHeader,\n setActionErrorCookieHeader,\n ACTION_ERROR_COOKIE,\n} from \"./error-store.js\";\n","import type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString } from \"../render/render-to-string.js\";\nimport { documentShell, extractAppBody, serializeData } from \"../build/document-shell.js\";\nimport type { PageRoute, ScannedRoutes } from \"../router/route-scanner.js\";\nimport type { BuildConfig } from \"../build/build.js\";\nimport type { PageDataLoad } from \"../types.js\";\nimport { matchRoute } from \"./match.js\";\nimport { renderPage } from \"./render.js\";\n\nexport interface StreamingPageOptions {\n route: PageRoute;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\">;\n importer?: (path: string) => Promise<unknown>;\n actions?: Record<string, string[]>;\n request?: Request;\n}\n\nconst defaultImport = (path: string) => import(path);\n\n/** Builds the concrete URL path for a route pattern given matched params. */\nfunction buildConcretePath(\n routePath: string,\n params: Record<string, string | string[]>,\n): string {\n return routePath.replace(/:([a-zA-Z0-9_]+)(\\*)?/g, (_m, name: string, catchAll?: string) => {\n const value = params[name];\n if (value === undefined || value === null) return \"\";\n return catchAll ? (Array.isArray(value) ? value.join(\"/\") : String(value)) : String(value);\n });\n}\n\nfunction streamingScript(page: string, search: string): string {\n const src = `\n async function __elurJsStreamRender() {\n try {\n const url = \"/__elur-js/render?page=\" + encodeURIComponent(${JSON.stringify(page)}) + \"&search=\" + encodeURIComponent(${JSON.stringify(search)});\n const res = await fetch(url);\n if (!res.ok) throw new Error(\"Streaming render failed: \" + res.status);\n const html = await res.text();\n const app = document.getElementById(\"app\");\n if (app) app.innerHTML = html;\n document.dispatchEvent(new CustomEvent(\"elur:rendered\"));\n } catch (err) {\n console.error(\"[elur-kit] streaming render failed\", err);\n }\n }\n __elurJsStreamRender();\n `;\n return `<script type=\"module\">${src}</script>`;\n}\n\n/**\n * Render a page shell that shows the loading boundary while the real content\n * is fetched and injected by the client.\n *\n * @deprecated Legacy shell + client-fetch approach, only used by the\n * deprecated `createSsrServer`. Real streaming SSR (shell first, resolved\n * content streamed as a swap chunk) lives in `createStreamingResponse`\n * (`src/ssr/stream-response.ts`, exported from the package root).\n */\nexport async function renderStreamingPage(options: StreamingPageOptions): Promise<string> {\n const { route, params, searchParams, config, importer = defaultImport, actions } = options;\n if (!route.loadingPath) {\n throw new Error(\"Cannot stream a page without a loading.ts boundary\");\n }\n\n const { default: Loading } = (await importer(route.loadingPath)) as {\n default: () => ElurTemplate;\n };\n\n const loadingBody = await renderToString(() => Loading());\n const concretePath = buildConcretePath(route.path, params);\n const body = `<div id=\"elur-loading\">${loadingBody}</div>${streamingScript(concretePath, searchParams.toString())}`;\n\n // Apply <html> attributes and head scripts (e.g. data-theme and the no-flash\n // theme script) from the root layout loader so the shell paints correctly\n // before the real content arrives.\n const htmlAttributes: Record<string, string> = {};\n const headScripts: string[] = [];\n const headLinks: string[] = [];\n if (route.layouts.length > 0) {\n const rootLayout = route.layouts[0];\n const dataPath = rootLayout.replace(/layout\\.ts$/, \"layout.data.ts\");\n if (dataPath !== rootLayout) {\n try {\n const mod = (await importer(dataPath)) as { load?: PageDataLoad };\n const layoutData = mod.load ? await mod.load({ params, searchParams, request: options.request }) : undefined;\n if (layoutData && typeof layoutData === \"object\") {\n const attrs = (layoutData as { htmlAttributes?: Record<string, string> }).htmlAttributes;\n if (attrs) Object.assign(htmlAttributes, attrs);\n const scripts = (layoutData as { headScripts?: string[] }).headScripts;\n if (Array.isArray(scripts)) headScripts.push(...scripts);\n const links = (layoutData as { headLinks?: string[] }).headLinks;\n if (Array.isArray(links)) headLinks.push(...links);\n }\n } catch {\n // The root layout loader is optional; ignore failures here.\n }\n }\n }\n\n return documentShell({\n title: \"Loading...\",\n lang: config.lang,\n body,\n data: { __elur_js_streaming: true, page: route.path },\n actions,\n htmlAttributes,\n headScripts,\n headLinks,\n clientEntry: config.clientEntry,\n });\n}\n\nexport interface RenderPageBodyOptions {\n routes: ScannedRoutes;\n pathname: string;\n searchParams: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\" | \"router\" | \"js\">;\n actions?: Record<string, string[]>;\n importer?: (path: string) => Promise<unknown>;\n request?: Request;\n}\n\nexport interface RenderPageBodyResult {\n /** Inner HTML body for the page (without the document shell). */\n body: string;\n /** Page title extracted from the rendered shell. */\n title: string;\n /** Full rendered document shell (used for ISR caching). */\n fullHtml?: string;\n /** `Set-Cookie` value that clears a consumed action error cookie. */\n clearActionErrorCookie?: string;\n /** `<head>` tags (title, meta, OG, twitter) for the SPA router to merge. */\n head?: string;\n /**\n * Serialized contents of `<script id=\"elur-data\">` for this page, when the\n * shell emitted it. Lets the SPA router refresh the inert data script after\n * navigation instead of leaving the initial page's data frozen.\n */\n data?: string;\n /**\n * Serialized contents of `<script id=\"elur-actions\">`, when emitted.\n */\n actions?: string;\n /** First-class Response when a loader threw one (A-22). */\n response?: Response;\n}\n\n/** Thrown by `renderPageBody` when the requested path has no matching route. */\nexport class RouteNotFoundError extends Error {\n constructor(pathname: string) {\n super(`No route found for ${pathname}`);\n this.name = \"RouteNotFoundError\";\n }\n}\n\n/**\n * Render only the inner HTML body for a page. Used by the streaming endpoint\n * to inject the real content into the shell.\n */\nexport async function renderPageBody(options: RenderPageBodyOptions): Promise<RenderPageBodyResult> {\n const { routes, pathname, searchParams, config, actions, importer = defaultImport, request } = options;\n const match = matchRoute(pathname, routes.pages);\n if (!match) {\n throw new RouteNotFoundError(pathname);\n }\n\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams,\n config,\n actions,\n importer,\n request,\n });\n\n // If a loader threw a Response (redirect, 404, etc.), propagate it (A-22).\n if (result.response) {\n return {\n body: \"\",\n title: \"\",\n response: result.response,\n };\n }\n\n const body = extractAppBody(result.html)?.trim()\n ?? result.html.match(/<div id=\"app\">([\\s\\S]*)<\\/div>\\s*(<script|$)/)?.[1]?.trim()\n ?? result.html;\n const titleMatch = result.html.match(/<title[^>]*>([^<]*)<\\/title>/);\n return {\n body,\n title: titleMatch ? titleMatch[1] : result.resolvedTitle ?? \"\",\n fullHtml: result.html,\n clearActionErrorCookie: result.clearActionErrorCookie,\n head: result.head,\n data: result.data !== undefined ? serializeData(result.data) : undefined,\n actions: actions && Object.keys(actions).length > 0 ? serializeData(actions) : undefined,\n };\n}\n","import { realpath, stat } from \"node:fs/promises\";\nimport { extname, resolve, sep } from \"node:path\";\n\nfunction isInside(root: string, candidate: string): boolean {\n return candidate === root || candidate.startsWith(`${root}${sep}`);\n}\n\nfunction decodePathname(pathname: string): string | null {\n try {\n const decoded = decodeURIComponent(pathname);\n if (decoded.includes(\"\\0\") || decoded.includes(\"\\\\\") || /%(?:00|2e|2f|5c)/i.test(decoded)) return null;\n if (decoded.split(\"/\").some((segment) => segment === \"..\")) return null;\n return decoded;\n } catch {\n return null;\n }\n}\n\nexport async function resolveStaticFile(root: string, pathname: string): Promise<string | null> {\n const decoded = decodePathname(pathname);\n if (decoded === null) return null;\n\n const resolvedRoot = resolve(root);\n const relativePath = decoded.replace(/^\\/+/, \"\");\n let candidate = resolve(resolvedRoot, relativePath);\n if (!isInside(resolvedRoot, candidate)) return null;\n\n try {\n const candidateStat = await stat(candidate);\n if (candidateStat.isDirectory()) candidate = resolve(candidate, \"index.html\");\n } catch {\n if (decoded.endsWith(\"/\") || extname(decoded) === \"\") candidate = resolve(candidate, \"index.html\");\n }\n\n if (!isInside(resolvedRoot, candidate)) return null;\n\n try {\n const [canonicalRoot, canonicalCandidate, candidateStat] = await Promise.all([\n realpath(resolvedRoot),\n realpath(candidate),\n stat(candidate),\n ]);\n if (!candidateStat.isFile() || !isInside(canonicalRoot, canonicalCandidate)) return null;\n return canonicalCandidate;\n } catch {\n return null;\n }\n}\n","import type { ResolvedElurConfig } from \"../config/index.js\";\nimport { randomUUID } from \"node:crypto\";\n\n// --- RequestContext: unified per-request runtime context ---\n//\n// Every runtime path (SSR server, CLI preview/dev, adapters, Vite plugin)\n// eventually funnels through a single Web handler that receives a Web Request\n// and returns a Web Response. RequestContext carries the resolved config,\n// route tables, action registry and request-scoped state so handlers do not\n// re-derive this information on every request.\n//\n// Design goals (runtime-security §4):\n// * One type used by every runtime entry point.\n// * No Node-specific APIs on the type — only Web standards.\n// * Carries per-request state: params, locals, cookies, signal, requestId.\n// * response.headers supports multiple Set-Cookie without collapsing them.\n// * signal aborts when the host disconnects (when the platform allows it).\n// * Middleware/loaders/actions share the same context or readonly views.\n\nexport interface RouteTable {\n pages: import(\"../router/route-scanner.js\").PageRoute[];\n api: import(\"../router/route-scanner.js\").ApiRoute[];\n error404?: import(\"../router/route-scanner.js\").PageRoute;\n error500?: import(\"../router/route-scanner.js\").PageRoute;\n}\n\n// --- CookieJar: read cookies from request, write to response ---\n\n/** Read-only access to request cookies. */\nexport interface CookieJar {\n /** Gets a cookie value by name, or undefined if not present. */\n get(name: string): string | undefined;\n /** Returns all cookie name-value pairs. */\n getAll(): Record<string, string>;\n /** Checks if a cookie exists. */\n has(name: string): boolean;\n}\n\n/** Write access to response cookies (Set-Cookie headers). */\nexport interface ResponseCookieJar {\n /** Sets a Set-Cookie header. */\n set(name: string, value: string, options?: CookieOptions): void;\n /** Removes a cookie by setting it expired. */\n clear(name: string, options?: CookieOptions): void;\n /** Returns all Set-Cookie header values accumulated so far. */\n getAll(): string[];\n}\n\nexport interface CookieOptions {\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n maxAge?: number;\n expires?: Date;\n path?: string;\n domain?: string;\n}\n\n/** Mutable response state accumulated during the request lifecycle. */\nexport interface ResponseState {\n status?: number;\n headers: Headers;\n cookies: ResponseCookieJar;\n}\n\n// --- Cookie implementation ---\n\nclass RequestCookieJar implements CookieJar {\n private cookies: Record<string, string>;\n\n constructor(request: Request) {\n this.cookies = parseCookies(request.headers.get(\"Cookie\") ?? \"\");\n }\n\n get(name: string): string | undefined {\n return this.cookies[name];\n }\n\n getAll(): Record<string, string> {\n return { ...this.cookies };\n }\n\n has(name: string): boolean {\n return name in this.cookies;\n }\n}\n\nclass MutableResponseCookieJar implements ResponseCookieJar {\n private entries: string[] = [];\n\n set(name: string, value: string, options: CookieOptions = {}): void {\n this.entries.push(serializeCookie(name, value, options));\n }\n\n clear(name: string, options: CookieOptions = {}): void {\n this.entries.push(serializeCookie(name, \"\", { ...options, maxAge: 0, expires: new Date(0) }));\n }\n\n getAll(): string[] {\n return [...this.entries];\n }\n}\n\nfunction parseCookies(header: string): Record<string, string> {\n const result: Record<string, string> = {};\n if (!header) return result;\n for (const pair of header.split(\";\")) {\n const idx = pair.indexOf(\"=\");\n if (idx === -1) continue;\n const name = pair.slice(0, idx).trim();\n const value = pair.slice(idx + 1).trim();\n result[name] = value;\n }\n return result;\n}\n\nfunction serializeCookie(name: string, value: string, options: CookieOptions): string {\n const parts = [`${name}=${value}`];\n if (options.httpOnly) parts.push(\"HttpOnly\");\n if (options.secure) parts.push(\"Secure\");\n if (options.sameSite) parts.push(`SameSite=${options.sameSite}`);\n if (options.maxAge !== undefined) parts.push(`Max-Age=${options.maxAge}`);\n if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);\n if (options.path) parts.push(`Path=${options.path}`);\n if (options.domain) parts.push(`Domain=${options.domain}`);\n return parts.join(\"; \");\n}\n\nexport interface RequestContextOptions {\n request: Request;\n config: ResolvedElurConfig;\n routes: RouteTable;\n actions: import(\"../action/scan.js\").ActionRegistry;\n /** Public action names serialized into the HTML shell. */\n publicActions: Record<string, string[]>;\n /** Optional module loader for adapter-bundled entries. */\n importer?: (path: string) => unknown | Promise<unknown>;\n /** Whether the render endpoint (/__elur-js/render) is available. */\n renderEndpoint?: boolean;\n /** Whether to bypass the ISR cache (dev mode). */\n noCache?: boolean;\n /** ISR cache directory (absolute). */\n cacheDir?: string;\n /** Default ISR revalidate interval in seconds. */\n defaultRevalidate?: number;\n /** Route params (populated after route matching). */\n params?: Record<string, string | string[] | undefined>;\n /** Per-request locals (populated by middleware). */\n locals?: Record<string, unknown>;\n /** Abort signal for the request (from host disconnect). */\n signal?: AbortSignal;\n /** Request ID (auto-generated if not provided). */\n requestId?: string;\n /** Platform-specific context (e.g. Vercel, Netlify). */\n platform?: unknown;\n /** Matched route (populated after route matching). */\n route?: import(\"../router/route-scanner.js\").PageRoute | import(\"../router/route-scanner.js\").ApiRoute;\n}\n\nexport class RequestContext {\n readonly request: Request;\n readonly url: URL;\n readonly config: ResolvedElurConfig;\n readonly routes: RouteTable;\n readonly actions: import(\"../action/scan.js\").ActionRegistry;\n readonly publicActions: Record<string, string[]>;\n readonly importer?: (path: string) => unknown | Promise<unknown>;\n readonly renderEndpoint: boolean;\n readonly noCache: boolean;\n readonly cacheDir?: string;\n readonly defaultRevalidate?: number;\n\n // Per-request state (runtime-security §4)\n /** Route params derived from the matched route. */\n params: Readonly<Record<string, string | string[] | undefined>>;\n /** Per-request locals, populated by middleware. Not global. */\n locals: Record<string, unknown>;\n /** Read-only access to request cookies. */\n readonly cookies: CookieJar;\n /** Abort signal (from host disconnect when platform allows). */\n readonly signal: AbortSignal;\n /** Unique request ID for logging/correlation. */\n readonly requestId: string;\n /** Platform-specific context (Vercel, Netlify, etc.). */\n readonly platform: unknown;\n /** Matched route after route matching. */\n route?: import(\"../router/route-scanner.js\").PageRoute | import(\"../router/route-scanner.js\").ApiRoute;\n /** Mutable response state accumulated during the request. */\n readonly response: ResponseState;\n\n constructor(options: RequestContextOptions) {\n this.request = options.request;\n this.url = new URL(options.request.url);\n this.config = options.config;\n this.routes = options.routes;\n this.actions = options.actions;\n this.publicActions = options.publicActions;\n this.importer = options.importer;\n this.renderEndpoint = options.renderEndpoint ?? true;\n this.noCache = options.noCache ?? false;\n this.cacheDir = options.cacheDir;\n this.defaultRevalidate = options.defaultRevalidate;\n\n // Per-request state\n this.params = options.params ?? {};\n this.locals = options.locals ?? {};\n this.cookies = new RequestCookieJar(options.request);\n this.signal = options.signal ?? new AbortController().signal;\n this.requestId = options.requestId ?? randomUUID();\n this.platform = options.platform;\n this.route = options.route;\n this.response = {\n status: undefined,\n headers: new Headers(),\n cookies: new MutableResponseCookieJar(),\n };\n }\n\n /** The pathname without a query string. */\n get pathname(): string {\n return this.url.pathname;\n }\n\n /** The HTTP method, uppercased. */\n get method(): string {\n return (this.request.method ?? \"GET\").toUpperCase();\n }\n\n /** Whether the request accepts JSON. */\n get wantsJson(): boolean {\n return (this.request.headers.get(\"Accept\") ?? \"\").includes(\"application/json\");\n }\n\n /** Search params from the request URL. */\n get searchParams(): URLSearchParams {\n return this.url.searchParams;\n }\n\n /** Render config passed to renderPage/renderErrorPage. */\n get renderConfig(): { lang?: string; clientEntry?: string; renderEndpoint?: boolean } {\n return {\n lang: undefined,\n clientEntry: undefined,\n renderEndpoint: this.renderEndpoint,\n };\n }\n\n /** Applies accumulated response state (headers, cookies, status) to a Response. */\n applyToResponse(response: Response): Response {\n const headers = new Headers(response.headers);\n // Merge accumulated headers\n for (const [key, value] of this.response.headers.entries()) {\n headers.set(key, value);\n }\n // Append Set-Cookie values (multiple allowed)\n for (const cookie of this.response.cookies.getAll()) {\n headers.append(\"Set-Cookie\", cookie);\n }\n const status = this.response.status ?? response.status;\n return new Response(response.body, {\n status,\n statusText: response.statusText,\n headers,\n });\n }\n}\n\n// --- ResponseBuilder: small helpers for consistent Web Responses ---\n\nexport function htmlResponse(body: string, status = 200, headers?: HeadersInit): Response {\n return new Response(body, {\n status,\n headers: { \"Content-Type\": \"text/html; charset=utf-8\", ...headers as Record<string, string> },\n });\n}\n\nexport function jsonResponse(data: unknown, status = 200, headers?: HeadersInit): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: { \"Content-Type\": \"application/json; charset=utf-8\", ...headers as Record<string, string> },\n });\n}\n\nexport function textResponse(body: string, status = 200, headers?: HeadersInit): Response {\n return new Response(body, {\n status,\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\", ...headers as Record<string, string> },\n });\n}\n\nexport function notFound(body = \"Not Found\"): Response {\n return textResponse(body, 404);\n}\n\nexport function methodNotAllowed(method: string): Response {\n return textResponse(`Method not allowed: ${method}`, 405);\n}\n\nexport function serverError(body: string): Response {\n return textResponse(body, 500);\n}\n\n// --- Content-type guessing (shared by all static-serving paths) ---\n\nexport function guessContentType(filePath: string): string {\n switch (filePath.slice(filePath.lastIndexOf(\".\") + 1).toLowerCase()) {\n case \"html\": return \"text/html; charset=utf-8\";\n case \"js\": return \"application/javascript; charset=utf-8\";\n case \"mjs\": return \"application/javascript; charset=utf-8\";\n case \"css\": return \"text/css; charset=utf-8\";\n case \"json\": return \"application/json; charset=utf-8\";\n case \"svg\": return \"image/svg+xml\";\n case \"png\": return \"image/png\";\n case \"jpg\":\n case \"jpeg\": return \"image/jpeg\";\n case \"webp\": return \"image/webp\";\n case \"avif\": return \"image/avif\";\n case \"ico\": return \"image/x-icon\";\n case \"woff\": return \"font/woff\";\n case \"woff2\": return \"font/woff2\";\n case \"wasm\": return \"application/wasm\";\n case \"txt\": return \"text/plain; charset=utf-8\";\n default: return \"application/octet-stream\";\n }\n}\n\n// --- Static file serving as a Web handler (reuses resolveStaticFile) ---\n\nimport { readFile, stat } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport { resolveStaticFile } from \"./static.js\";\n\n/**\n * Serves a static file from the root directory with full conditional and\n * range support:\n *\n * - ETag / Last-Modified with If-None-Match / If-Modified-Since → 304.\n * - `Range` with `If-Range` (ETag or date) → 206 with `Content-Range`.\n * - HEAD → same headers as GET without a body.\n * - Invalid/unsatisfiable ranges → 416 with a `Content-Range: bytes (asterisk)/size` header.\n *\n * Files with content hashes in their names (e.g. `app-abc123.js`) get\n * `Cache-Control: public, max-age=31536000, immutable`.\n *\n * @param root Static file root (absolute path).\n * @param pathname Request pathname.\n * @param request Optional request for conditional/range/HEAD handling.\n */\nexport async function serveStaticFile(\n root: string,\n pathname: string,\n request?: Request,\n): Promise<Response | null> {\n const filePath = await resolveStaticFile(root, pathname);\n if (!filePath) return null;\n try {\n const [data, stats] = await Promise.all([\n readFile(filePath),\n stat(filePath),\n ]);\n\n const contentType = guessContentType(filePath);\n const etag = `\"${createHash(\"sha1\").update(data).digest(\"hex\").slice(0, 16)}\"`;\n const lastModified = stats.mtime.toUTCString();\n const isHead = request?.method === \"HEAD\";\n const size = data.byteLength;\n\n const baseHeaders: Record<string, string> = {\n \"Content-Type\": contentType,\n \"Content-Length\": String(size),\n ETag: etag,\n \"Last-Modified\": lastModified,\n \"Accept-Ranges\": \"bytes\",\n };\n\n // Determine Cache-Control: hashed assets get immutable, others get a\n // short revalidation window.\n const baseName = filePath.split(\"/\").pop() ?? \"\";\n const isHashed = /[a-f0-9]{8,}\\.(js|css|woff2?|wasm|png|jpg|jpeg|webp|avif|svg)$/i.test(baseName);\n baseHeaders[\"Cache-Control\"] = isHashed\n ? \"public, max-age=31536000, immutable\"\n : \"public, max-age=0, must-revalidate\";\n\n // Conditional requests (If-None-Match takes precedence).\n const ifNoneMatch = request?.headers.get(\"If-None-Match\");\n if (ifNoneMatch && etagListMatches(ifNoneMatch, etag)) {\n return new Response(null, { status: 304, headers: baseHeaders });\n }\n const ifModifiedSince = request?.headers.get(\"If-Modified-Since\");\n if (ifModifiedSince) {\n const since = Date.parse(ifModifiedSince);\n if (!isNaN(since) && Math.floor(stats.mtime.getTime() / 1000) <= Math.floor(since / 1000)) {\n return new Response(null, { status: 304, headers: baseHeaders });\n }\n }\n\n // Range support with If-Range validation.\n const rangeHeader = request?.headers.get(\"Range\");\n const ifRange = request?.headers.get(\"If-Range\");\n if (rangeHeader && (!ifRange || ifRangeMatches(ifRange, etag, stats.mtime))) {\n const range = parseRange(rangeHeader, size);\n if (range === null) {\n return new Response(null, {\n status: 416,\n headers: { ...baseHeaders, \"Content-Range\": `bytes */${size}` },\n });\n }\n if (range) {\n const [start, end] = range;\n const chunk = data.subarray(start, end + 1);\n const headers: Record<string, string> = {\n ...baseHeaders,\n \"Content-Length\": String(chunk.byteLength),\n \"Content-Range\": `bytes ${start}-${end}/${size}`,\n };\n if (isHead) return new Response(null, { status: 206, headers });\n return new Response(chunk, { status: 206, headers });\n }\n }\n\n if (isHead) return new Response(null, { status: 200, headers: baseHeaders });\n return new Response(data, { status: 200, headers: baseHeaders });\n } catch {\n return null;\n }\n}\n\nfunction etagListMatches(ifNoneMatch: string, etag: string): boolean {\n return ifNoneMatch\n .split(\",\")\n .map((value) => value.trim())\n .some((value) => value === \"*\" || value === etag);\n}\n\nfunction ifRangeMatches(ifRange: string, etag: string, mtime: Date): boolean {\n if (ifRange.startsWith('\"') || ifRange.startsWith(\"W/\")) return ifRange === etag;\n const date = Date.parse(ifRange);\n return !isNaN(date) && Math.floor(mtime.getTime() / 1000) <= Math.floor(date / 1000);\n}\n\n/**\n * Parses a single `Range: bytes=...` header. Returns:\n * - `[start, end]` for a satisfiable range.\n * - `null` when the header is malformed or unsatisfiable (→ 416).\n * - `undefined` when the header is valid but the whole resource is requested\n * (e.g. `bytes=0-` for an empty file) — serve the full body.\n */\nfunction parseRange(rangeHeader: string, size: number): [number, number] | null | undefined {\n const match = /^bytes=(\\d*)-(\\d*)$/.exec(rangeHeader.trim());\n if (!match) return null;\n const startText = match[1];\n const endText = match[2];\n\n if (startText === \"\" && endText === \"\") return null;\n if (startText === \"\") {\n // Suffix range: last N bytes.\n const suffix = Number(endText);\n if (!Number.isSafeInteger(suffix) || suffix <= 0) return null;\n const start = Math.max(0, size - suffix);\n if (size === 0) return undefined;\n return [start, size - 1];\n }\n\n const start = Number(startText);\n if (!Number.isSafeInteger(start) || start < 0 || start >= size) return null;\n const end = endText === \"\" ? size - 1 : Number(endText);\n if (!Number.isSafeInteger(end) || end < start) return null;\n return [start, Math.min(end, size - 1)];\n}\n","// --- Security response headers (runtime-security §14) ---\n//\n// Applies configurable security headers to responses. Defaults are safe and\n// compatible: X-Content-Type-Options, Referrer-Policy, frame-ancestors.\n// HSTS is only applied under HTTPS or when explicitly configured.\n// CSP supports a \"nonce\" placeholder replaced per-request.\n// User-set headers on the response are never overwritten without explicit\n// merge rules.\n\nimport type { SecurityHeadersConfig } from \"../config/index.js\";\n\n/** Default security headers applied when `security.headers` is not `false`. */\nexport const DEFAULT_SECURITY_HEADERS: Required<\n Omit<SecurityHeadersConfig, \"contentSecurityPolicy\" | \"hsts\" | \"permissionsPolicy\">\n> = {\n noSniff: true,\n referrerPolicy: \"strict-origin-when-cross-origin\",\n frameAncestors: \"SAMEORIGIN\",\n};\n\n/**\n * Builds the security headers map from the resolved config.\n * Returns an empty map if headers are disabled.\n */\nexport function buildSecurityHeaders(\n config: SecurityHeadersConfig | false,\n isHttps: boolean,\n nonce?: string,\n): Record<string, string> {\n if (config === false) return {};\n\n const headers: Record<string, string> = {};\n const merged = { ...DEFAULT_SECURITY_HEADERS, ...config };\n\n if (merged.noSniff) {\n headers[\"X-Content-Type-Options\"] = \"nosniff\";\n }\n\n if (merged.referrerPolicy) {\n headers[\"Referrer-Policy\"] = merged.referrerPolicy;\n }\n\n // Frame policy: prefer CSP frame-ancestors if CSP is set, otherwise\n // X-Frame-Options for broader compatibility.\n if (merged.contentSecurityPolicy) {\n let csp = merged.contentSecurityPolicy;\n if (nonce) {\n csp = csp.replace(/\\bnonce\\b/g, `'nonce-${nonce}'`);\n }\n headers[\"Content-Security-Policy\"] = csp;\n } else if (merged.frameAncestors) {\n // Without CSP, use X-Frame-Options for frame protection.\n const fa = merged.frameAncestors;\n if (fa === \"NONE\") {\n headers[\"X-Frame-Options\"] = \"DENY\";\n } else if (fa === \"SAMEORIGIN\") {\n headers[\"X-Frame-Options\"] = \"SAMEORIGIN\";\n } else {\n headers[\"X-Frame-Options\"] = fa;\n }\n }\n\n // HSTS: only under HTTPS or when explicitly set as a string.\n if (merged.hsts === true && isHttps) {\n headers[\"Strict-Transport-Security\"] = \"max-age=15552000; includeSubDomains\";\n } else if (typeof merged.hsts === \"string\") {\n headers[\"Strict-Transport-Security\"] = merged.hsts;\n }\n\n if (merged.permissionsPolicy) {\n headers[\"Permissions-Policy\"] = merged.permissionsPolicy;\n }\n\n return headers;\n}\n\n/**\n * Applies security headers to an existing Response, preserving any\n * user-set headers unless overridden by security config.\n */\nexport function applySecurityHeaders(\n response: Response,\n headers: Record<string, string>,\n): Response {\n if (Object.keys(headers).length === 0) return response;\n\n const newHeaders = new Headers(response.headers);\n for (const [key, value] of Object.entries(headers)) {\n // Don't overwrite a header the response already set explicitly.\n if (!newHeaders.has(key)) {\n newHeaders.set(key, value);\n }\n }\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers: newHeaders,\n });\n}\n","// --- Redirects, rewrites, and route headers (plan §11.1, §10) ---\n//\n// Authors can declare redirects and rewrites in their config:\n//\n// export default defineConfig({\n// redirects: [\n// { from: \"/old-blog/:slug\", to: \"/blog/:slug\", status: 301 },\n// ],\n// rewrites: [\n// { from: \"/api/legacy/*\", to: \"/api/v2/*\" },\n// ],\n// headers: [\n// { path: \"/admin/*\", headers: { \"X-Robots-Tag\": \"noindex\" } },\n// ],\n// });\n//\n// Redirects return a Response with the appropriate status and Location.\n// Rewrites change the pathname before routing (transparent to the user).\n// Route headers are applied to the response for matching paths.\n\nexport interface RedirectRule {\n /** Source path pattern (supports :param and *). */\n from: string;\n /** Destination path (supports :param interpolation). */\n to: string;\n /** HTTP status code (301, 302, 307, 308). Default: 308. */\n status?: 301 | 302 | 307 | 308;\n}\n\nexport interface RewriteRule {\n /** Source path pattern (supports :param and *). */\n from: string;\n /** Destination path (supports :param interpolation). */\n to: string;\n}\n\nexport interface RouteHeadersRule {\n /** Path pattern to match (supports :param and *). */\n path: string;\n /** Headers to apply to matching responses. */\n headers: Record<string, string>;\n}\n\n/**\n * Checks if a pathname matches a redirect rule and returns the redirect\n * Response if so.\n */\nexport function matchRedirect(\n pathname: string,\n rules: RedirectRule[],\n): Response | undefined {\n for (const rule of rules) {\n const params = matchPattern(pathname, rule.from);\n if (params) {\n const location = interpolatePath(rule.to, params);\n const status = rule.status ?? 308;\n return new Response(null, {\n status,\n headers: { Location: location },\n });\n }\n }\n return undefined;\n}\n\n/**\n * Checks if a pathname matches a rewrite rule and returns the rewritten\n * pathname if so.\n */\nexport function matchRewrite(\n pathname: string,\n rules: RewriteRule[],\n): string | undefined {\n for (const rule of rules) {\n const params = matchPattern(pathname, rule.from);\n if (params) {\n return interpolatePath(rule.to, params);\n }\n }\n return undefined;\n}\n\n/**\n * Returns headers that should be applied to a response for the given pathname.\n */\nexport function matchRouteHeaders(\n pathname: string,\n rules: RouteHeadersRule[],\n): Record<string, string> | undefined {\n for (const rule of rules) {\n if (matchPattern(pathname, rule.path)) {\n return rule.headers;\n }\n }\n return undefined;\n}\n\n/**\n * Matches a pathname against a pattern with :param and * wildcards.\n * Returns the extracted params, or undefined if no match.\n */\nfunction matchPattern(pathname: string, pattern: string): Record<string, string> | undefined {\n const cleanPath = pathname.split(\"?\")[0];\n const requestSegments = cleanPath.split(\"/\").filter(Boolean);\n const patternSegments = pattern.split(\"/\").filter(Boolean);\n const params: Record<string, string> = {};\n\n let i = 0;\n for (let r = 0; r < patternSegments.length; r++) {\n const seg = patternSegments[r];\n\n if (seg === \"*\") {\n // Wildcard matches everything remaining.\n return params;\n }\n\n if (seg.endsWith(\"*\")) {\n // Catch-all: :name* matches the rest as a single string.\n const name = seg.slice(1, -1);\n const rest = requestSegments.slice(i).join(\"/\");\n params[name] = rest;\n return params;\n }\n\n if (seg.startsWith(\":\")) {\n const name = seg.slice(1);\n if (requestSegments[i] === undefined) return undefined;\n params[name] = requestSegments[i];\n i++;\n continue;\n }\n\n if (seg !== requestSegments[i]) return undefined;\n i++;\n }\n\n if (i !== requestSegments.length) return undefined;\n return params;\n}\n\n/**\n * Interpolates :param placeholders in a path with actual values.\n */\nfunction interpolatePath(template: string, params: Record<string, string>): string {\n return template.replace(/:(\\w+)\\*?/g, (_match, name: string) => {\n return params[name] ?? \"\";\n });\n}\n","// --- Stream boundary (per-request, real Suspense streaming) ---\n//\n// `streamBoundary()` wraps a promise in a loading fallback. During SSR runtime,\n// the server emits the fallback HTML immediately, then streams a `<template>`\n// chunk with a replacement script that the browser executes to swap the\n// fallback for the resolved content in-place (real Suspense streaming).\n//\n// In SSG (build time), boundaries are resolved synchronously — the build waits\n// for all promises before writing the HTML, so no streaming occurs.\n//\n// Boundaries are tracked per-request via AsyncLocalStorage to avoid global\n// state leakage between concurrent requests.\n\nimport type { ElurTemplate } from \"@elurjs/core\";\nimport { randomUUID } from \"node:crypto\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport interface StreamBoundaryOptions<T> {\n /** Fallback content shown while the promise resolves. */\n fallback: ElurTemplate;\n /** Promise that resolves to a ElurTemplate. */\n promise: Promise<T>;\n /** Renders the resolved value to a ElurTemplate. */\n children: (value: T) => ElurTemplate;\n}\n\n/** Per-request boundary registry. */\ninterface BoundaryContext {\n boundaries: Map<string, {\n promise: Promise<unknown>;\n children: (value: unknown) => ElurTemplate;\n }>;\n}\n\nconst boundaryALS = new AsyncLocalStorage<BoundaryContext>();\n\n/**\n * Gets the current per-request boundary context, if any.\n * Used by the streaming response to collect boundaries for later resolution.\n */\nexport function getCurrentBoundaryContext(): BoundaryContext | undefined {\n return boundaryALS.getStore();\n}\n\n/**\n * Runs a function within a per-request boundary context.\n * Used by the SSR streaming pipeline to collect boundaries.\n */\nexport function withBoundaryContext<T>(fn: () => T): T {\n const ctx: BoundaryContext = { boundaries: new Map() };\n return boundaryALS.run(ctx, fn);\n}\n\n/**\n * Builds the fallback HTML wrapper for a boundary ID.\n * The fallback content is wrapped in a `<div>` with the boundary ID so the\n * browser can find it and replace it when the resolved content arrives.\n *\n * (v2.1 — Fix #4: real Suspense streaming with `<template>` replacement)\n */\nexport function buildFallbackHtml(boundaryId: string, fallbackHtml: string): string {\n return `<div id=\"${boundaryId}\" style=\"display:contents\" data-elur-boundary=\"${boundaryId}\">${fallbackHtml}</div>`;\n}\n\n/**\n * Builds the resolved content chunk for a boundary ID.\n * Emits a `<template>` element with the resolved content, followed by a\n * `<script>` that replaces the fallback div with the template content\n * in-place. This is real Suspense streaming — the browser swaps the DOM\n * node without a full re-render.\n *\n * (v2.1 — Fix #4: real Suspense streaming with `<template>` replacement)\n */\nexport function buildResolvedChunk(boundaryId: string, resolvedHtml: string): string {\n // Escape the resolved HTML for safe embedding inside a <template> tag.\n // <template> content is inert (not parsed as DOM), so we store the raw\n // HTML and clone it via `content.cloneNode(true)`.\n return `<template id=\"${boundaryId}-tpl\">${resolvedHtml}</template>` +\n `<script>(function(){` +\n `var t=document.getElementById(${JSON.stringify(boundaryId + \"-tpl\")});` +\n `var f=document.getElementById(${JSON.stringify(boundaryId)});` +\n `if(t&&f){f.replaceWith(t.content.cloneNode(true));}` +\n `document.dispatchEvent(new CustomEvent(\"elur:rendered\"));` +\n `})();</script>`;\n}\n\n/**\n * Creates a stream boundary. During SSR, emits the fallback and registers the\n * promise for later resolution by the streaming pipeline. During SSG, the\n * build awaits all boundaries before writing HTML.\n *\n * The boundary ID is deterministic per-request via crypto.randomUUID().\n */\nexport function streamBoundary<T>(options: StreamBoundaryOptions<T>): ElurTemplate {\n const id = `elur-stream-${randomUUID().slice(0, 8)}`;\n const ctx = boundaryALS.getStore();\n\n // In SSR mode with a boundary context, register the promise for later.\n if (ctx) {\n ctx.boundaries.set(id, {\n promise: options.promise,\n children: options.children as (value: unknown) => ElurTemplate,\n });\n }\n\n return {\n __isElurTemplate: true as const,\n mount(container: Element | string) {\n const el = typeof container === \"string\" ? document.querySelector(container) : container;\n if (!el) throw new Error(\"[elur-kit] streamBoundary(): container not found\");\n // Render fallback initially.\n const handle = options.fallback.mount(el);\n // Attempt to resolve and swap (works in both SSR and client).\n options.promise\n .then((value) => {\n const content = options.children(value);\n el.innerHTML = \"\";\n const childHandle = content.mount(el);\n // Store the new handle for cleanup.\n (handle as any).__elurChildHandle = childHandle;\n })\n .catch((err) => {\n console.error(`[elur-kit] streamBoundary ${id} failed:`, err);\n });\n return {\n unmount() {\n const childHandle = (handle as any).__elurChildHandle;\n if (childHandle?.unmount) childHandle.unmount();\n handle.unmount();\n },\n };\n },\n _render(parent: Node, before: Node | null): () => void {\n // For SSR/build: render fallback inline. The promise resolution is\n // handled by the streaming pipeline when available.\n const dispose = options.fallback._render(parent, before);\n\n // Kick off the promise resolution in the background.\n options.promise\n .then((value) => {\n void value;\n })\n .catch((err) => {\n console.error(`[elur-kit] streamBoundary ${id} failed:`, err);\n });\n\n return dispose;\n },\n } as unknown as ElurTemplate;\n}\n","// --- Real streaming with ReadableStream (plan §10) ---\n//\n// Creates a Web Response with a ReadableStream that:\n// 1. Sends the document shell + loading fallback immediately.\n// 2. Runs the full page render (loaders included) in the background.\n// 3. Appends a resolved-content chunk with a deterministic boundary ID.\n// 4. Includes a swap script that replaces the loading boundary in-place.\n// 5. Cancels the stream and the background render when the client\n// disconnects (AbortSignal), cleaning up listeners.\n//\n// Response contract (mirrors what Next.js documents for self-hosted\n// streaming): `Content-Type: text/html` is sent early, the body is chunked\n// (no `Content-Length`), `X-Accel-Buffering: no` asks reverse proxies like\n// nginx not to buffer the stream, and `Cache-Control: no-store` keeps CDNs\n// from caching a half-sent dynamic stream. Streamed responses are never\n// written to the ISR cache — caching a stream mid-flight is unsound, so\n// routes served this way always render live.\n//\n// For adapters without streaming support, `createBufferedResponse()` provides\n// a fallback that buffers the full response and returns it as a single\n// Response (no streaming).\n\nimport type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString } from \"../render/render-to-string.js\";\nimport { documentShell, extractAppBody } from \"../build/document-shell.js\";\nimport type { PageRoute } from \"../router/route-scanner.js\";\nimport type { BuildConfig } from \"../build/build.js\";\nimport { renderPage } from \"./render.js\";\nimport { randomUUID } from \"node:crypto\";\nimport { buildResolvedChunk } from \"../middleware/stream-boundary.js\";\n\nexport interface StreamResponseOptions {\n route: PageRoute;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\" | \"renderEndpoint\" | \"router\" | \"js\">;\n actions?: Record<string, string[]>;\n importer?: (path: string) => Promise<unknown>;\n request?: Request;\n /** AbortSignal from the host (client disconnect). */\n signal?: AbortSignal;\n}\n\n/** Standard headers for a streamed HTML response. */\nconst STREAM_HEADERS: Record<string, string> = {\n \"Content-Type\": \"text/html; charset=utf-8\",\n // Ask reverse proxies (nginx and friends) not to buffer the stream; without\n // this the client receives the whole response at once and streaming is\n // pointless. See https://nextjs.org/docs/app/guides/self-hosting#streaming-and-suspense\n \"X-Accel-Buffering\": \"no\",\n // A streamed dynamic page is rendered live per request: intermediaries and\n // browsers must not cache it.\n \"Cache-Control\": \"no-store\",\n};\n\n/**\n * Mid-stream error notice swapped into the loading boundary when the\n * background render fails after the shell was already sent. Inline styles\n * keep it self-contained (the page's CSS may assume the final layout).\n */\nfunction buildErrorNotice(): string {\n return `<div role=\"alert\" style=\"margin:2rem auto;max-width:32rem;padding:1rem 1.25rem;border:1px solid #e5484d;border-radius:8px;color:#b3373c;font-family:system-ui,sans-serif\">` +\n `<strong style=\"display:block;margin-bottom:.25rem\">No se pudo cargar el contenido.</strong>` +\n `<span>Recarga la página para intentarlo de nuevo.</span></div>`;\n}\n\n/**\n * Creates a streaming Response that sends the shell + loading fallback first,\n * then appends the resolved content.\n *\n * If the route has no loading boundary, falls back to a normal renderPage.\n */\nexport async function createStreamingResponse(\n options: StreamResponseOptions,\n): Promise<Response> {\n const { route, params, searchParams, config, actions, importer = defaultImport, request, signal } = options;\n\n // If no loading boundary, do a normal render (no streaming).\n if (!route.loadingPath) {\n const result = await renderPage({\n route,\n params,\n searchParams,\n config,\n actions,\n importer,\n request,\n });\n if (result.response) return result.response;\n return new Response(result.html, {\n headers: { \"Content-Type\": \"text/html; charset=utf-8\" },\n });\n }\n\n // The client already disconnected before we produced anything.\n if (signal?.aborted) {\n return new Response(\"Client Closed Request\", { status: 499 });\n }\n\n // Load the loading boundary component.\n const loadingMod = (await importer(route.loadingPath)) as { default: () => ElurTemplate };\n const loadingHtml = await renderToString(loadingMod.default);\n\n // Deterministic boundary ID for the swap.\n const boundaryId = `elur-stream-${randomUUID().slice(0, 8)}`;\n\n // Build the shell with the loading fallback. Streaming sends the shell\n // before the body is known, so the 0%-JS island scan cannot run here —\n // streamed routes always emit the client entry (they are few and usually\n // interactive anyway). The split router chunk is emitted when configured.\n const routerCfg = config.router;\n const routerEnabled = routerCfg?.enabled !== false;\n const routerEntry =\n routerCfg?.entry && routerEnabled && config.js !== \"legacy\"\n ? routerCfg.entry\n : undefined;\n const shellHtml = documentShell({\n title: \"Loading...\",\n lang: config.lang,\n body: `<div id=\"${boundaryId}\">${loadingHtml}</div>`,\n data: { __elur_js_streaming: true, page: route.path },\n actions,\n clientEntry: config.clientEntry,\n routerEntry,\n routerEnabled: routerCfg ? routerEnabled : undefined,\n renderEndpoint: config.renderEndpoint,\n });\n\n // Create a ReadableStream that sends the shell, then the resolved content.\n let aborted = false;\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n const encoder = new TextEncoder();\n\n const onAbort = () => {\n aborted = true;\n try {\n controller.close();\n } catch {\n // Already closed/errored — nothing to do.\n }\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n /** Enqueue unless the client went away mid-render. */\n const send = (html: string): void => {\n if (aborted) return;\n controller.enqueue(encoder.encode(html));\n };\n\n try {\n // Send the shell immediately.\n send(shellHtml);\n\n // Run the full page render in the background.\n const result = await renderPage({\n route,\n params,\n searchParams,\n config,\n actions,\n importer,\n request,\n });\n if (aborted) return;\n\n // If a loader threw a Response, send a redirect/error script.\n if (result.response) {\n const status = result.response.status;\n const location = result.response.headers.get(\"Location\");\n if (location && (status === 301 || status === 302 || status === 307 || status === 308)) {\n send(`<script>window.location.href=${JSON.stringify(location)};</script>`);\n } else {\n // A non-redirect thrown response (404, 403, ...): swap the loading\n // boundary for an error notice instead of leaving a spinner.\n send(\n buildResolvedChunk(boundaryId, buildErrorNotice()) +\n `<script>console.error(${JSON.stringify(`Loader responded with status ${status}`)});</script>`,\n );\n }\n return;\n }\n\n // Extract the inner body from the full render. The document shell\n // wraps the page in explicit markers; the regex fallback covers\n // documents assembled without them.\n const innerBody = extractAppBody(result.html)\n ?? result.html.match(/<div id=\"app\">([\\s\\S]*)<\\/div>\\s*(<script|$)/)?.[1]?.trim()\n ?? result.html;\n\n // Send a `<template>` chunk + replacement script that swaps the\n // loading boundary with the real content in-place.\n send(buildResolvedChunk(boundaryId, innerBody));\n } catch (err) {\n // The shell is already on the wire, so the error must arrive as a\n // chunk: swap the loading boundary for an error notice and log the\n // details to the console.\n const errorMsg = err instanceof Error ? err.message : String(err);\n send(\n buildResolvedChunk(boundaryId, buildErrorNotice()) +\n `<script>console.error(${JSON.stringify(errorMsg)});</script>`,\n );\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n if (!aborted) {\n controller.close();\n }\n }\n },\n\n cancel() {\n // Client disconnected (the runtime cancelled the stream): mark aborted\n // so a render completing late never enqueues into a dead stream.\n aborted = true;\n },\n });\n\n return new Response(stream, {\n // No `Content-Length` and no explicit `Transfer-Encoding`: the host\n // runtime (Node, Bun, edge) chunks the body automatically when the\n // length is unknown. Setting Transfer-Encoding by hand produces a\n // duplicated `chunked, chunked` header under Node.\n headers: STREAM_HEADERS,\n });\n}\n\n/**\n * Buffered fallback for adapters without streaming support.\n * Renders the full page and returns it as a single Response.\n */\nexport async function createBufferedResponse(\n options: StreamResponseOptions,\n): Promise<Response> {\n const { route, params, searchParams, config, actions, importer = defaultImport, request } = options;\n\n const result = await renderPage({\n route,\n params,\n searchParams,\n config,\n actions,\n importer,\n request,\n });\n\n if (result.response) return result.response;\n\n return new Response(result.html, {\n headers: { \"Content-Type\": \"text/html; charset=utf-8\" },\n });\n}\n\nconst defaultImport = (path: string) => import(path);\n\n/**\n * Checks if the host runtime supports streaming responses.\n * Node, Bun, and modern edge runtimes do. Some serverless platforms may not.\n */\nexport { supportsStreaming } from \"../runtime/capabilities.js\";\n","import { matchRoute, matchApiRoute } from \"../ssr/match.js\";\nimport { handleActionRequest, type ActionResolver } from \"../action/server.js\";\nimport { renderPage, renderErrorPage } from \"../ssr/render.js\";\nimport { renderPageBody, RouteNotFoundError } from \"../ssr/stream.js\";\nimport { actionNames } from \"../action/scan.js\";\nimport { serveStaticFile, htmlResponse, jsonResponse, notFound, methodNotAllowed } from \"./context.js\";\nimport { publicErrorResponse } from \"../errors.js\";\nimport { cacheKey, createFsCacheAdapter, type CacheAdapter } from \"../cache/adapter.js\";\nimport { connectCacheAdapter } from \"../cache/invalidation.js\";\nimport { shouldCachePublic, type CachePolicy } from \"../cache/policy.js\";\nimport { buildSecurityHeaders, applySecurityHeaders } from \"./security-headers.js\";\nimport { createRequestLogger, type LogLevel, type StructuredLogger } from \"./logger.js\";\nimport { matchRedirect, matchRewrite, matchRouteHeaders, type RedirectRule, type RewriteRule, type RouteHeadersRule } from \"../router/redirects.js\";\nimport { matchesMiddleware, runMiddleware, type LoadedMiddleware } from \"../middleware/index.js\";\nimport { createStreamingResponse } from \"../ssr/stream-response.js\";\nimport { supportsStreaming, DEFAULT_CAPABILITIES, type AdapterCapabilities } from \"./capabilities.js\";\nimport type { SecurityHeadersConfig } from \"../config/index.js\";\n\n// --- Unified Web handler ---\n//\n// A single function that turns a Web Request into a Web Response. Every\n// runtime entry point (Node CLI, Bun adapter, Vercel, Netlify, Vite dev)\n// eventually calls this handler so behavior is identical across platforms.\n//\n// Responsibilities (in order):\n// 0. Redirects and rewrites declared in the config.\n// 1. Server actions endpoint (/__elur-js/actions).\n// 2. SPA render endpoint (/__elur-js/render).\n// 3. API routes.\n// 4. Static files from the output directory.\n// 5. Dynamic SSR rendering for unmatched paths.\n// 6. 404 / 500 error pages.\n//\n// The handler is pure: it does not import Node HTTP types and can be used in\n// Bun, Deno, Cloudflare Workers, Vercel Edge, etc.\n\nexport interface WebHandlerOptions {\n /** Static file root (absolute path). Usually the build output directory. */\n staticRoot: string;\n /** Whether to bypass the ISR cache (dev mode). */\n noCache?: boolean;\n /** ISR cache directory (absolute). */\n cacheDir?: string;\n /** Default ISR revalidate interval in seconds. */\n defaultRevalidate?: number;\n /** Optional module loader for adapter-bundled entries. */\n importer?: (path: string) => Promise<unknown>;\n /** HTML lang attribute. */\n lang?: string;\n /** Client entry path. */\n clientEntry?: string;\n /** Whether the render endpoint exists. */\n renderEndpoint?: boolean;\n /** Security headers config (runtime-security §14). `false` disables. */\n securityHeaders?: SecurityHeadersConfig | false;\n /** Minimum log level for the per-request structured logger. */\n logLevel?: LogLevel;\n /**\n * Pluggable ISR cache adapter. When omitted and `cacheDir` is set, a\n * filesystem adapter is created and shared per `cacheDir` for the process.\n */\n cacheAdapter?: CacheAdapter;\n /** Redirect rules evaluated before any routing (first match wins). */\n redirects?: RedirectRule[];\n /** Rewrite rules: transparently change the pathname used for routing. */\n rewrites?: RewriteRule[];\n /** Extra response headers applied to matching request paths. */\n routeHeaders?: RouteHeadersRule[];\n /**\n * Opt-in streaming SSR (experimental). When `true`, dynamic routes with a\n * `loading` boundary are served as a real stream: the document shell plus\n * the loading fallback go out immediately, and the resolved content arrives\n * as a follow-up chunk that swaps the boundary in-place. Streamed responses\n * bypass the ISR cache (they always render live) and send\n * `Cache-Control: no-store` + `X-Accel-Buffering: no`. Routes without a\n * loading boundary render buffered exactly as before.\n */\n streaming?: boolean;\n /**\n * Host capabilities used to gate streaming. Defaults to\n * `DEFAULT_CAPABILITIES` (a full Node/Bun process). Adapters for hosts\n * without streaming support should pass their own capabilities so\n * `streaming: true` degrades to buffered rendering instead of breaking.\n */\n capabilities?: AdapterCapabilities;\n /**\n * User middleware (the project's `src/middleware.ts`, loaded by the caller\n * with `loadMiddleware`). Runs after redirects/rewrites and the internal\n * endpoints, before API/static/SSR routing. A returned Response\n * short-circuits the pipeline; `next({ headers, locals })` merges headers\n * into the downstream request and exposes `locals` to API routes.\n */\n middleware?: LoadedMiddleware;\n /**\n * Client router options affecting SSR output: `enabled` controls the\n * render-endpoint marker and whether a page without islands ships any JS;\n * `entry` is the public URL of the split router chunk (e.g.\n * `/_elur/router.js`) when the client bundle was built with separate\n * entry/router inputs.\n */\n router?: { enabled?: boolean; entry?: string };\n /**\n * Client JS mode. `\"legacy\"` restores the pre-0%-JS behavior: the combined\n * client entry is emitted unconditionally on every page.\n */\n js?: \"modern\" | \"legacy\";\n}\n\nexport interface WebHandlerRouteTable {\n pages: import(\"../router/route-scanner.js\").PageRoute[];\n api: import(\"../router/route-scanner.js\").ApiRoute[];\n error404?: import(\"../router/route-scanner.js\").PageRoute;\n error500?: import(\"../router/route-scanner.js\").PageRoute;\n}\n\nexport interface WebHandlerActionRegistry {\n [pagePath: string]: Record<string, string>;\n}\n\nexport interface CreateWebHandlerResult {\n (request: Request): Promise<Response>;\n}\n\n/**\n * Create a unified Web handler from scanned routes, actions and options.\n *\n * The returned function is the single entry point for all runtimes.\n */\nexport function createWebHandler(\n routes: WebHandlerRouteTable,\n actions: WebHandlerActionRegistry,\n options: WebHandlerOptions,\n): CreateWebHandlerResult {\n const publicActions = actionNames(actions);\n const lang = options.lang ?? \"es\";\n const clientEntry = options.clientEntry;\n const renderEndpoint = options.renderEndpoint ?? true;\n const noCache = options.noCache ?? false;\n const defaultRevalidate = options.defaultRevalidate;\n\n const renderConfig = {\n lang,\n clientEntry,\n renderEndpoint,\n router: options.router\n ? { enabled: options.router.enabled !== false, entry: options.router.entry }\n : undefined,\n js: options.js,\n };\n const securityHeadersConfig = options.securityHeaders ?? {};\n const redirectRules = options.redirects ?? [];\n const rewriteRules = options.rewrites ?? [];\n const routeHeaderRules = options.routeHeaders ?? [];\n const capabilities = options.capabilities ?? DEFAULT_CAPABILITIES;\n // Streaming is opt-in AND requires a host that can flush chunks as they are\n // produced; when either is missing every route renders buffered.\n const streamingEnabled = options.streaming === true && supportsStreaming(capabilities);\n const cacheAdapter = resolveCacheAdapter(options);\n if (cacheAdapter && !invalidatorConnectedAdapters.has(cacheAdapter)) {\n invalidatorConnectedAdapters.add(cacheAdapter);\n // The subscription lives for the process lifetime: defaultInvalidator is\n // a module-level singleton and dev/preview recreate the handler per\n // request, so connecting per call would leak listeners.\n connectCacheAdapter(cacheAdapter);\n }\n\n function createActionResolver(): ActionResolver {\n return async (name: string, page?: string) => {\n const pageKey = page\n ? routes.pages.some((route) => route.path === page)\n ? page\n : (matchRoute(page, routes.pages)?.route.path ?? page)\n : undefined;\n const pageActions = pageKey ? actions[pageKey] : Object.values(actions).find((p) => p[name]) ?? undefined;\n const actionPath = pageActions ? pageActions[name] : undefined;\n if (!actionPath) return undefined;\n if (options.importer) {\n const mod = (await options.importer(actionPath)) as Record<string, unknown>;\n const action = mod[name];\n if (typeof action === \"function\") return action as (...args: unknown[]) => unknown;\n return undefined;\n }\n const mod = (await import(actionPath)) as Record<string, unknown>;\n const action = mod[name];\n if (typeof action === \"function\") return action as (...args: unknown[]) => unknown;\n return undefined;\n };\n }\n\n const actionResolver = createActionResolver();\n\n async function handleActions(request: Request, logger: StructuredLogger): Promise<Response> {\n const stopTimer = logger.startTimer(\"action\", \"Server action\");\n try {\n return await handleActionRequest(request, actionResolver);\n } catch (err) {\n logger.error(\"[elur-kit] action error\", {\n path: new URL(request.url).pathname,\n method: request.method,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n return publicErrorResponse(err, { includeDetail: noCache });\n } finally {\n stopTimer();\n }\n }\n\n async function handleRenderEndpoint(request: Request, url: URL, logger: StructuredLogger): Promise<Response> {\n const page = url.searchParams.get(\"page\") ?? \"/\";\n const search = url.searchParams.get(\"search\") ?? \"\";\n const wantsJson = (request.headers.get(\"Accept\") ?? \"\").includes(\"application/json\");\n const stopTimer = logger.startTimer(\"render-endpoint\", \"SPA render endpoint\");\n try {\n const result = await renderPageBody({\n routes,\n pathname: page,\n searchParams: new URLSearchParams(search),\n config: renderConfig,\n actions: publicActions,\n request,\n importer: options.importer,\n });\n // A thrown Response from a loader is a first-class response (A-22).\n if (result.response) return result.response;\n const { body, title, head, clearActionErrorCookie, data, actions } = result;\n if (wantsJson) {\n // The full SPA payload: head keeps OG/Twitter metadata fresh on\n // navigation, data/actions keep the inert JSON scripts in sync, and\n // the clear-cookie is also relayed as a header for parity with dev.\n const headers: Record<string, string> = {};\n if (clearActionErrorCookie) {\n headers[\"X-Elur-Action-Clear-Cookie\"] = clearActionErrorCookie;\n }\n // `?? null` keeps every key present in the wire shape — JSON.stringify\n // drops undefined values and the parity contract expects a stable\n // payload across runtimes.\n return jsonResponse(\n {\n title,\n body,\n head: head ?? null,\n data: data ?? null,\n actions: actions ?? null,\n clearActionErrorCookie: clearActionErrorCookie ?? null,\n },\n 200,\n headers,\n );\n }\n return htmlResponse(\n body,\n 200,\n clearActionErrorCookie ? { \"Set-Cookie\": clearActionErrorCookie } : undefined,\n );\n } catch (err) {\n if (err instanceof RouteNotFoundError) return notFound(\"Not Found\");\n // A thrown Response from a loader is a first-class response (A-22).\n if (err instanceof Response) return err;\n logger.error(\"[elur-kit] render endpoint error\", {\n path: url.pathname,\n page,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n return publicErrorResponse(err, { includeDetail: noCache });\n } finally {\n stopTimer();\n }\n }\n\n async function handleApiRoute(\n request: Request,\n pathname: string,\n logger: StructuredLogger,\n middlewareLocals?: Record<string, unknown>,\n ): Promise<Response | null> {\n const apiMatch = matchApiRoute(pathname, routes.api);\n if (!apiMatch) return null;\n const stopTimer = logger.startTimer(\"api\", \"API route\");\n try {\n let mod: Record<string, unknown>;\n if (options.importer) {\n mod = (await options.importer(apiMatch.route.routePath as unknown as string)) as Record<string, unknown>;\n } else {\n mod = (await import(apiMatch.route.routePath)) as Record<string, unknown>;\n }\n const handler = mod[request.method ?? \"GET\"];\n if (typeof handler !== \"function\") return methodNotAllowed(request.method ?? \"GET\");\n // Pass params and a writable locals object to the API handler\n // (runtime-security §4: params derived from the effective route).\n // `locals` carries values published by the user middleware via next().\n const ctx = { params: apiMatch.params, locals: middlewareLocals ?? {} as Record<string, unknown> };\n const response = (await (handler as (req: Request, ctx?: { params: Record<string, string | string[]>; locals: Record<string, unknown> }) => unknown)(request, ctx)) as Response;\n return response;\n } catch (err) {\n logger.error(\"[elur-kit] API route error\", {\n path: pathname,\n method: request.method,\n route: apiMatch.route.path,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n return publicErrorResponse(err, { includeDetail: noCache });\n } finally {\n stopTimer();\n }\n }\n\n async function handleStatic(pathname: string, request: Request): Promise<Response | null> {\n const response = await serveStaticFile(options.staticRoot, pathname, request);\n if (response && noCache) {\n const ct = response.headers.get(\"Content-Type\") ?? \"\";\n if (ct.includes(\"text/html\")) {\n // Dev mode: strip the render-endpoint marker so the client router uses\n // the live /__elur-js/render endpoint for fast SPA navigation.\n const stripped = (await response.text())\n .replace('<meta name=\"elur:render-endpoint\" content=\"off\" />', \"\");\n return new Response(stripped, {\n status: response.status,\n headers: { \"Content-Type\": ct, \"Cache-Control\": \"no-store, must-revalidate\" },\n });\n }\n return new Response(response.body, {\n status: response.status,\n headers: { ...Object.fromEntries(response.headers.entries()), \"Cache-Control\": \"no-store, must-revalidate\" },\n });\n }\n if (response && renderEndpoint) {\n const ct = response.headers.get(\"Content-Type\") ?? \"\";\n if (ct.includes(\"text/html\")) {\n const headers = Object.fromEntries(response.headers.entries());\n delete headers[\"content-length\"];\n const body = await response.text();\n if (body.includes('elur:render-endpoint\" content=\"off\"')) {\n // The SSG build baked `render-endpoint content=\"off\"` so static\n // deployments never probe the endpoint. This server exposes\n // /__elur-js/render, so advertise it: SPA navigations fetch live\n // server-rendered content instead of the stale static file.\n const rewritten = body.replace(\n '<meta name=\"elur:render-endpoint\" content=\"off\" />',\n '<meta name=\"elur:render-endpoint\" content=\"on\" />',\n );\n return new Response(rewritten, { status: response.status, headers });\n }\n return new Response(body, { status: response.status, headers });\n }\n }\n return response;\n }\n\n async function handleDynamicRender(request: Request, pathname: string, logger: StructuredLogger): Promise<Response> {\n const match = matchRoute(pathname, routes.pages);\n if (!match) {\n const errorResult = await renderErrorPage({\n routes,\n status: 404,\n config: renderConfig,\n actions: publicActions,\n importer: options.importer,\n });\n if (errorResult) return htmlResponse(errorResult.html, errorResult.status);\n return notFound(`Not found: ${pathname}`);\n }\n\n // Streaming SSR (opt-in): routes with a loading boundary are served as a\n // real stream — shell + fallback first, resolved content as a later chunk.\n // Streamed responses bypass the ISR cache entirely (a half-sent stream is\n // not cacheable; these pages render live on every request), so the cache\n // gates below only apply to the buffered path.\n if (streamingEnabled && match.route.loadingPath) {\n // The timer measures time-to-shell: the Response is returned once the\n // shell is ready while the background render continues streaming.\n const stopStreamTimer = logger.startTimer(\"ssr\", \"SSR stream shell\");\n try {\n return await createStreamingResponse({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(request.url.split(\"?\")[1] ?? \"\"),\n config: renderConfig,\n actions: publicActions,\n importer: options.importer,\n request,\n signal: request.signal,\n });\n } catch (err) {\n // A thrown Response from a loader is a first-class response (A-22).\n if (err instanceof Response) return err;\n logger.error(\"[elur-kit] SSR stream error\", {\n path: pathname,\n route: match.route.path,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n const errorResult = await renderErrorPage({\n routes,\n status: 500,\n error: err,\n config: renderConfig,\n actions: publicActions,\n importer: options.importer,\n }).catch(() => undefined);\n if (errorResult) return htmlResponse(errorResult.html, errorResult.status);\n return publicErrorResponse(err, { includeDetail: noCache });\n } finally {\n stopStreamTimer();\n }\n }\n\n // ISR cache (only when caching is enabled and the request is cacheable —\n // no cookies, no authorization header). Pages are stored in the cache\n // adapter under cacheKey(pathname); the same key scheme is used by\n // path-based invalidation (connectCacheAdapter).\n const cacheable = !noCache && cacheAdapter && isCacheable(request);\n const pageCacheKey = cacheable ? cacheKey(pathname) : undefined;\n\n const renderAndStore = async (): Promise<Response> => {\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(request.url.split(\"?\")[1] ?? \"\"),\n config: renderConfig,\n actions: publicActions,\n request,\n importer: options.importer,\n });\n\n // If a loader threw a Response (redirect, 404, etc.), return it\n // as a first-class response (A-22).\n if (result.response) {\n return result.response;\n }\n\n if (cacheable && cacheAdapter && pageCacheKey && isResultCacheable(result, request)) {\n const revalidateSeconds = result.revalidate ?? defaultRevalidate ?? 0;\n if (revalidateSeconds > 0) {\n await cacheAdapter.set(\n pageCacheKey,\n { html: result.html, generatedAt: Date.now(), revalidate: revalidateSeconds },\n { revalidate: revalidateSeconds, tags: result.cachePolicy?.tags },\n );\n }\n }\n\n return htmlResponse(result.html);\n };\n\n if (cacheable && cacheAdapter && pageCacheKey) {\n const cached = await cacheAdapter.get(pageCacheKey);\n if (cached) {\n if (Date.now() - cached.generatedAt >= cached.revalidate * 1000) {\n // Stale-while-revalidate: serve the stale entry immediately and\n // refresh it in the background.\n renderAndStore().catch((err) => {\n logger.error(\"[elur-kit] background cache revalidation failed\", {\n path: pathname,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n });\n }\n return htmlResponse(cached.html);\n }\n }\n\n const stopTimer = logger.startTimer(\"ssr\", \"SSR render\");\n try {\n return await renderAndStore();\n } catch (err) {\n // A thrown Response from a loader is a first-class response (A-22).\n if (err instanceof Response) return err;\n logger.error(\"[elur-kit] SSR render error\", {\n path: pathname,\n route: match.route.path,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n const errorResult = await renderErrorPage({\n routes,\n status: 500,\n error: err,\n config: renderConfig,\n actions: publicActions,\n importer: options.importer,\n }).catch(() => undefined);\n if (errorResult) return htmlResponse(errorResult.html, errorResult.status);\n return publicErrorResponse(err, { includeDetail: noCache });\n } finally {\n stopTimer();\n }\n }\n\n // Applies security headers plus the per-request observability headers\n // (Server-Timing when there are metrics, X-Request-ID always) and any\n // configured route headers. Route headers may override security headers;\n // the observability headers are applied last so they always win.\n function finalizeResponse(\n response: Response,\n logger: StructuredLogger,\n secHeaders: Record<string, string>,\n routeHeaders?: Record<string, string>,\n ): Response {\n const secured = applySecurityHeaders(response, secHeaders);\n const headers = new Headers(secured.headers);\n if (routeHeaders) {\n for (const [key, value] of Object.entries(routeHeaders)) {\n headers.set(key, value);\n }\n }\n const timing = logger.getServerTimingHeader();\n if (timing) headers.set(\"Server-Timing\", timing);\n headers.set(\"X-Request-ID\", logger.getRequestId());\n return new Response(secured.body, {\n status: secured.status,\n statusText: secured.statusText,\n headers,\n });\n }\n\n return async function handler(request: Request): Promise<Response> {\n const logger = createRequestLogger(request, options.logLevel);\n const url = new URL(request.url);\n const originalPathname = url.pathname;\n const isHttps = url.protocol === \"https:\";\n\n // Determine security headers (rebuild if nonce is needed).\n // HSTS is only applied under HTTPS; other headers apply always.\n const secHeaders = securityHeadersConfig === false\n ? {}\n : buildSecurityHeaders(securityHeadersConfig, isHttps);\n\n // 0. Redirects, evaluated before any routing.\n if (redirectRules.length > 0) {\n const redirect = matchRedirect(originalPathname, redirectRules);\n if (redirect) {\n return finalizeResponse(redirect, logger, secHeaders, matchRouteHeaders(originalPathname, routeHeaderRules));\n }\n }\n\n // Rewrites change the pathname transparently: everything below (API\n // routes, static files, dynamic SSR and its ISR cache key) routes on the\n // rewritten path, while route headers keep matching the original URL the\n // user configured them for.\n let pathname = originalPathname;\n if (rewriteRules.length > 0) {\n pathname = matchRewrite(originalPathname, rewriteRules) ?? originalPathname;\n }\n const routeHeaders = matchRouteHeaders(originalPathname, routeHeaderRules);\n\n // 1. Server actions endpoint.\n if (pathname === \"/__elur-js/actions\" && request.method === \"POST\") {\n const response = await handleActions(request, logger);\n return finalizeResponse(response, logger, secHeaders, routeHeaders);\n }\n\n // 2. SPA render endpoint.\n if (pathname === \"/__elur-js/render\" && renderEndpoint) {\n const response = await handleRenderEndpoint(request, url, logger);\n return finalizeResponse(response, logger, secHeaders, routeHeaders);\n }\n\n // User middleware (src/middleware.ts) runs after redirects/rewrites and\n // the internal endpoints, before routing — same semantics as the legacy\n // createSsrServer pipeline. A returned Response short-circuits (through\n // finalizeResponse so security/observability headers still apply);\n // next({ headers }) merges into the downstream request and\n // next({ locals }) is exposed to API routes.\n let middlewareLocals: Record<string, unknown> | undefined;\n const middleware = options.middleware;\n if (middleware && matchesMiddleware(pathname, middleware.config)) {\n let mwResult;\n try {\n mwResult = await runMiddleware(middleware, request);\n } catch (err) {\n logger.error(\"[elur-kit] middleware error\", {\n path: pathname,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n return finalizeResponse(\n publicErrorResponse(err, { includeDetail: noCache }),\n logger,\n secHeaders,\n routeHeaders,\n );\n }\n if (mwResult.kind === \"response\") {\n return finalizeResponse(mwResult.response, logger, secHeaders, routeHeaders);\n }\n middlewareLocals = mwResult.locals;\n if (mwResult.headers) {\n const merged = new Headers(request.headers);\n for (const [key, value] of Object.entries(mwResult.headers)) {\n merged.set(key, value);\n }\n request = new Request(request, { headers: merged });\n }\n }\n\n // 3. API routes.\n const apiResponse = await handleApiRoute(request, pathname, logger, middlewareLocals);\n if (apiResponse) return finalizeResponse(apiResponse, logger, secHeaders, routeHeaders);\n\n // 4. Static files.\n const staticResponse = await handleStatic(pathname, request);\n if (staticResponse) return finalizeResponse(staticResponse, logger, secHeaders, routeHeaders);\n\n // 5. Dynamic SSR rendering.\n const dynamicResponse = await handleDynamicRender(request, pathname, logger);\n return finalizeResponse(dynamicResponse, logger, secHeaders, routeHeaders);\n };\n}\n\n// Default filesystem adapters are shared per cacheDir and connected to the\n// invalidator once; both live for the process lifetime (dev/preview recreate\n// the handler per request, so per-call adapters would leak listeners).\nconst defaultCacheAdapters = new Map<string, CacheAdapter>();\nconst invalidatorConnectedAdapters = new WeakSet<CacheAdapter>();\n\nfunction resolveCacheAdapter(options: WebHandlerOptions): CacheAdapter | undefined {\n if (options.cacheAdapter) return options.cacheAdapter;\n if (!options.cacheDir) return undefined;\n let adapter = defaultCacheAdapters.get(options.cacheDir);\n if (!adapter) {\n adapter = createFsCacheAdapter({ cacheDir: options.cacheDir });\n defaultCacheAdapters.set(options.cacheDir, adapter);\n }\n return adapter;\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction errorStack(err: unknown): string | undefined {\n return err instanceof Error ? err.stack : undefined;\n}\n\nfunction isCacheable(request: Request): boolean {\n if (request.method !== \"GET\" && request.method !== \"HEAD\") return false;\n if (request.headers.get(\"Cookie\")) return false;\n if (request.headers.get(\"Authorization\")) return false;\n return true;\n}\n\n/**\n * Checks whether a rendered page result is cacheable as public ISR.\n * Per runtime-security §9.1: uses the route's cache policy and checks\n * for personalized content markers.\n */\nfunction isResultCacheable(\n result: { revalidate?: number; html: string; cachePolicy?: CachePolicy },\n request: Request,\n): boolean {\n // If the HTML contains action error markers, it's personalized.\n if (result.html.includes(\"__elur_js_action_error\")) return false;\n // Use the route's cache policy if declared.\n if (result.cachePolicy) {\n return shouldCachePublic(result.cachePolicy, request);\n }\n // Fallback: cacheable only if revalidate > 0 and request is clean.\n if (!result.revalidate || result.revalidate <= 0) return false;\n if (request.headers.get(\"Cookie\")) return false;\n if (request.headers.get(\"Authorization\")) return false;\n return true;\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readdir, copyFile, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { AdapterOptions } from \"./index.js\";\nimport type { PageRoute } from \"../router/route-scanner.js\";\n\n/**\n * Shared helper: copy a directory recursively.\n */\nexport async function copyStatic(from: string, to: string): Promise<void> {\n await mkdir(to, { recursive: true });\n const entries = await readdir(from, { withFileTypes: true });\n for (const entry of entries) {\n const src = join(from, entry.name);\n const dest = join(to, entry.name);\n if (entry.isDirectory()) {\n await copyStatic(src, dest);\n } else {\n await copyFile(src, dest);\n }\n }\n}\n\n/** Adds every module the SSR runtime may import for a page to the registry. */\nfunction collectPageModules(\n page: PageRoute,\n moduleSet: Set<string>,\n actionPathsByPage: Map<string, Set<string>>,\n): void {\n moduleSet.add(page.pagePath);\n if (page.dataPath) moduleSet.add(page.dataPath);\n if (page.loadingPath) moduleSet.add(page.loadingPath);\n for (const layout of page.layouts) {\n moduleSet.add(layout);\n const layoutDataPath = layout.replace(/layout\\.ts$/, \"layout.data.ts\");\n if (layoutDataPath !== layout && existsSync(layoutDataPath)) {\n moduleSet.add(layoutDataPath);\n }\n }\n if (page.actionPath) {\n moduleSet.add(page.actionPath);\n let set = actionPathsByPage.get(page.path);\n if (!set) {\n set = new Set<string>();\n actionPathsByPage.set(page.path, set);\n }\n set.add(page.actionPath);\n }\n}\n\n/**\n * Build a self-contained SSR entry file for a platform adapter.\n * The generated module exports a default `handler(request: Request): Response`\n * and embeds the full route table plus a registry of all page/layout/data/\n * action modules so the runtime never touches the file system.\n */\nexport async function buildSsrEntry(\n routes: Awaited<ReturnType<typeof scanRoutes>>,\n options: AdapterOptions,\n entryDir: string,\n): Promise<string> {\n // Collect all module paths that the SSR runtime may need to import.\n const moduleSet = new Set<string>();\n const actionPathsByPage = new Map<string, Set<string>>();\n for (const page of routes.pages) {\n collectPageModules(page, moduleSet, actionPathsByPage);\n }\n if (routes.error404) collectPageModules(routes.error404, moduleSet, actionPathsByPage);\n if (routes.error500) collectPageModules(routes.error500, moduleSet, actionPathsByPage);\n for (const api of routes.api) {\n moduleSet.add(api.routePath);\n }\n const modules = Array.from(moduleSet);\n const moduleIndex = new Map(modules.map((path, index) => [path, index]));\n\n const imports = modules\n .map((path, index) => {\n const rel = relativeToPosix(entryDir, path);\n return `import * as m_${index} from ${JSON.stringify(rel)};`;\n })\n .join(\"\\n\");\n\n const renderPageRecord = (page: PageRoute): string => `{\n path: ${JSON.stringify(page.path)},\n pagePath: ${JSON.stringify(page.pagePath)},\n dataPath: ${JSON.stringify(page.dataPath ?? null)},\n actionPath: ${JSON.stringify(page.actionPath ?? null)},\n loadingPath: ${JSON.stringify(page.loadingPath ?? null)},\n layouts: ${JSON.stringify(page.layouts)},\n params: ${JSON.stringify(page.params)},\n }`;\n\n const pages = routes.pages.map(renderPageRecord).join(\",\\n\");\n\n const apiRoutes = routes.api\n .map((api) => {\n const index = moduleIndex.get(api.routePath);\n return ` { path: ${JSON.stringify(api.path)}, routePath: m_${index} },`;\n })\n .join(\"\\n\");\n\n const actionModules = Array.from(actionPathsByPage.entries())\n .map(([pagePath, paths]) => {\n const entries = Array.from(paths)\n .map((path) => {\n const index = moduleIndex.get(path);\n return ` [${JSON.stringify(path)}, m_${index}],`;\n })\n .join(\"\\n\");\n return ` [${JSON.stringify(pagePath)}, new Map([\\n${entries}\\n ])],`;\n })\n .join(\"\\n\");\n\n const actionsRegistry: Record<string, string[]> = {};\n for (const page of routes.pages) {\n if (!page.actionPath) continue;\n const mod = (await import(page.actionPath)) as Record<string, unknown>;\n const names: string[] = [];\n for (const [name, value] of Object.entries(mod)) {\n if (name === \"default\") continue;\n if (typeof value === \"function\") {\n names.push(name);\n }\n }\n if (names.length > 0) {\n actionsRegistry[page.path] = names;\n }\n }\n\n // The render config baked into the generated handler. The split router\n // chunk is advertised only when the bundle actually emitted it (the file\n // exists in the build output), so single-input legacy bundles keep working.\n const routerEnabled = options.router?.enabled !== false;\n const routerEntry =\n routerEnabled && options.js !== \"legacy\" &&\n existsSync(resolve(options.root, options.outDir, \"_elur\", \"router.js\"))\n ? \"/_elur/router.js\"\n : null;\n\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { handleActionRequest, matchApiRoute, matchRoute, renderPage, renderPageBody, renderErrorPage, createStreamingResponse } from \"@elurjs/kit\";\n${imports}\n\nconst registry = new Map<string, unknown>([\n${modules.map((path, index) => ` [${JSON.stringify(path)}, m_${index}],`).join(\"\\n\")}\n]);\n\nconst pages = [\n${pages},\n];\n\nconst apiRoutes = [\n${apiRoutes}\n];\n\nconst actionModules = new Map<string, Map<string, unknown>>([\n${actionModules}\n]);\n\nconst actions = ${JSON.stringify(actionsRegistry)};\n\nconst routes = {\n pages,\n api: apiRoutes,\n error404: ${routes.error404 ? renderPageRecord(routes.error404) : \"undefined\"},\n error500: ${routes.error500 ? renderPageRecord(routes.error500) : \"undefined\"},\n};\n\nconst clientEntry = ${JSON.stringify(options.clientEntry)};\nconst lang = ${JSON.stringify(options.lang)};\n// Client router/JS emission rules baked at adapter build time.\nconst router = ${JSON.stringify({ enabled: routerEnabled, entry: routerEntry })};\nconst jsMode = ${JSON.stringify(options.js === \"legacy\" ? \"legacy\" : \"modern\")};\n// Opt-in streaming SSR (experimental): routes with a loading boundary stream\n// the shell first and swap in the resolved content as a follow-up chunk.\nconst streaming = ${options.streaming === true};\n\nfunction loadModule(path: string) {\n const mod = registry.get(path);\n if (mod) return mod;\n throw new Error(\\`Module not found in registry: \\${path}\\`);\n}\n\nasync function resolveAction(name: string, page?: string) {\n // Match concrete page paths (e.g. /movies/inception) to their route pattern\n // (/movies/:slug) so actions on dynamic routes resolve by scope.\n let pageKey: string | undefined;\n if (page) {\n pageKey = routes.pages.some((route) => route.path === page)\n ? page\n : (matchRoute(page, routes.pages)?.route.path ?? page);\n }\n const pageModules = pageKey ? actionModules.get(pageKey) : undefined;\n const candidates = pageModules ? [...pageModules.values()] : [];\n if (!pageModules) {\n for (const mods of actionModules.values()) {\n for (const mod of mods.values()) {\n const action = (mod as Record<string, unknown>)[name];\n if (typeof action === \"function\") return action;\n }\n }\n }\n for (const mod of candidates) {\n const action = (mod as Record<string, unknown>)[name];\n if (typeof action === \"function\") {\n return action as (...args: unknown[]) => unknown;\n }\n }\n return undefined;\n}\n\nexport default async function handler(request: Request): Promise<Response> {\n const url = new URL(request.url);\n\n if (url.pathname === \"/__elur-js/actions\") {\n return handleActionRequest(request, resolveAction);\n }\n\n // Render endpoint used by the SPA router and streaming boundaries.\n if (url.pathname === \"/__elur-js/render\") {\n const page = url.searchParams.get(\"page\") ?? \"/\";\n const search = url.searchParams.get(\"search\") ?? \"\";\n const wantsJson = (request.headers.get(\"Accept\") ?? \"\").includes(\"application/json\");\n try {\n const result = await renderPageBody({\n routes,\n pathname: page,\n searchParams: new URLSearchParams(search),\n config: { lang, clientEntry, router, js: jsMode },\n importer: loadModule,\n actions,\n request,\n });\n // A thrown Response from a loader is a first-class response (A-22).\n if (result.response) return result.response;\n const { body, title, head, clearActionErrorCookie, data, actions: actionsPayload } = result;\n if (wantsJson) {\n const headers = { \"Content-Type\": \"application/json; charset=utf-8\" };\n if (clearActionErrorCookie) headers[\"X-Elur-Action-Clear-Cookie\"] = clearActionErrorCookie;\n // The ?? null fallbacks keep every key present — JSON.stringify drops\n // undefined and the SPA payload shape must be stable across runtimes.\n return new Response(\n JSON.stringify({\n title,\n body,\n head: head ?? null,\n data: data ?? null,\n actions: actionsPayload ?? null,\n clearActionErrorCookie: clearActionErrorCookie ?? null,\n }),\n { status: 200, headers },\n );\n }\n const headers = { \"Content-Type\": \"text/html; charset=utf-8\" };\n if (clearActionErrorCookie) headers[\"Set-Cookie\"] = clearActionErrorCookie;\n return new Response(body, { status: 200, headers });\n } catch (err) {\n if ((err as { name?: string }).name === \"RouteNotFoundError\") {\n return new Response(\"Not Found\", {\n status: 404,\n headers: { \"Content-Type\": \"text/plain\" },\n });\n }\n console.error(\"[elur-kit] render endpoint error:\", err);\n return new Response(\"Internal Server Error\", {\n status: 500,\n headers: { \"Content-Type\": \"text/plain\" },\n });\n }\n }\n\n const apiMatch = matchApiRoute(url.pathname, apiRoutes);\n if (apiMatch) {\n const mod = apiMatch.route.routePath as Record<\n string,\n (request: Request, context?: { params: Record<string, string | string[]> }) => unknown\n >;\n const handler = mod[request.method ?? \"GET\"];\n if (typeof handler !== \"function\") {\n return new Response(\"Method not allowed: \" + request.method, { status: 405, headers: { \"Content-Type\": \"text/plain\" } });\n }\n return (await handler(request, { params: apiMatch.params })) as Response;\n }\n\n const match = matchRoute(url.pathname, routes.pages);\n if (!match) {\n const errorResult = await renderErrorPage({ routes, status: 404, config: { lang, clientEntry, router, js: jsMode }, actions, importer: loadModule });\n if (errorResult) {\n return new Response(errorResult.html, { status: errorResult.status, headers: { \"Content-Type\": \"text/html; charset=utf-8\" } });\n }\n return new Response(\"Not Found\", { status: 404, headers: { \"Content-Type\": \"text/plain\" } });\n }\n\n try {\n if (streaming && match.route.loadingPath) {\n // Streaming SSR: shell + loading boundary first, resolved content as a\n // follow-up chunk. Streamed pages are rendered live (no cache).\n return createStreamingResponse({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(url.search),\n config: { lang, clientEntry, router, js: jsMode },\n importer: loadModule,\n actions,\n request,\n signal: request.signal,\n });\n }\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(url.search),\n config: { lang, clientEntry, router, js: jsMode },\n importer: loadModule,\n actions,\n request,\n });\n // A thrown Response from a loader is a first-class response (A-22).\n if (result.response) return result.response;\n const headers = { \"Content-Type\": \"text/html; charset=utf-8\" };\n if (result.clearActionErrorCookie) headers[\"Set-Cookie\"] = result.clearActionErrorCookie;\n return new Response(result.html, { status: 200, headers });\n } catch (err) {\n console.error(\"[elur-kit] SSR render error:\", err);\n const errorResult = await renderErrorPage({ routes, status: 500, error: err, config: { lang, clientEntry, router, js: jsMode }, actions, importer: loadModule });\n if (errorResult) {\n return new Response(errorResult.html, { status: errorResult.status, headers: { \"Content-Type\": \"text/html; charset=utf-8\" } });\n }\n return new Response(\"Internal Server Error\", { status: 500, headers: { \"Content-Type\": \"text/plain; charset=utf-8\" } });\n }\n}\n`;\n}\n\nfunction relativeToPosix(from: string, to: string): string {\n return relative(from, to).split(\"\\\\\").join(\"/\");\n}\n\n/**\n * Write a generated SSR entry file for an adapter.\n */\nexport async function writeSsrEntry(\n entryPath: string,\n routes: Awaited<ReturnType<typeof scanRoutes>>,\n options: AdapterOptions,\n): Promise<void> {\n await writeFile(\n entryPath,\n await buildSsrEntry(routes, options, dirname(entryPath)),\n \"utf8\",\n );\n}\n","import { mkdir, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { build } from \"vite\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { copyStatic, writeSsrEntry } from \"./shared.js\";\nimport { SERVERLESS_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Vercel adapter for elur-kit.\n *\n * Produces a `.vercel/output` directory compatible with the Vercel Build Output\n * API (v3). Static files are served from `dist/` and unmatched routes fall back\n * to the SSR function.\n */\nexport const vercelAdapter: Adapter = {\n name: \"vercel\",\n capabilities: SERVERLESS_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const vercelOut = resolve(root, \".vercel/output\");\n const functionsDir = join(vercelOut, \"functions\", \"__elur-js-kit.func\");\n const generatedDir = resolve(root, \".elur\");\n\n // Verify the production build exists.\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n // Clean previous adapter output.\n await rm(vercelOut, { recursive: true, force: true });\n await mkdir(vercelOut, { recursive: true });\n await mkdir(functionsDir, { recursive: true });\n await mkdir(generatedDir, { recursive: true });\n\n // Copy static files.\n await copyStatic(outDir, join(vercelOut, \"static\"));\n\n // Scan routes and generate a self-contained function entry.\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"vercel-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n // Bundle the function entry.\n await build({\n configFile: false,\n root,\n build: {\n outDir: functionsDir,\n emptyOutDir: true,\n ssr: true,\n lib: {\n entry: entryPath,\n formats: [\"es\"],\n fileName: () => \"index.js\",\n },\n rollupOptions: {\n external: [],\n output: {\n inlineDynamicImports: true,\n },\n },\n },\n });\n\n // Vite SSR lib builds may use the entry file name, so force the expected handler name.\n const generatedHandler = join(functionsDir, \"vercel-index.js\");\n const targetHandler = join(functionsDir, \"index.js\");\n try {\n await stat(generatedHandler);\n await rename(generatedHandler, targetHandler);\n } catch {\n // If the file is already named index.js, nothing to do.\n }\n\n // Write Vercel function config.\n await writeFile(\n join(functionsDir, \".vc-config.json\"),\n JSON.stringify(\n {\n runtime: \"nodejs20.x\",\n handler: \"index.js\",\n launcherType: \"Nodejs\",\n shouldAddHelpers: true,\n },\n null,\n 2,\n ),\n \"utf8\",\n );\n\n // Write Vercel root config.\n await writeFile(\n join(vercelOut, \"config.json\"),\n JSON.stringify(\n {\n version: 3,\n routes: [\n { handle: \"filesystem\" },\n { src: \"/(.*)\", \"dest\": \"/__elur-js-kit\" },\n ],\n },\n null,\n 2,\n ),\n \"utf8\",\n );\n },\n};\n","import { mkdir, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { build } from \"vite\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { writeSsrEntry } from \"./shared.js\";\nimport { SERVERLESS_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Netlify adapter for elur-kit.\n *\n * Produces the files expected by Netlify Functions v2:\n * - `netlify/functions/__elur-js-kit.mjs` — bundled SSR function.\n * - `netlify.toml` — redirects unmatched routes to the function.\n *\n * Run this after `elur-kit build`. The static files are left in `dist/` and\n * served directly by Netlify; the function only handles routes that have no\n * matching static file.\n */\nexport const netlifyAdapter: Adapter = {\n name: \"netlify\",\n capabilities: SERVERLESS_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const netlifyDir = resolve(root, \"netlify\");\n const functionsDir = join(netlifyDir, \"functions\");\n const generatedDir = resolve(root, \".elur\");\n\n // Verify the production build exists.\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n // Clean previous adapter output.\n await rm(functionsDir, { recursive: true, force: true });\n await mkdir(functionsDir, { recursive: true });\n await mkdir(generatedDir, { recursive: true });\n\n // Scan routes and generate a self-contained function entry.\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"netlify-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n // Bundle the function entry.\n await build({\n configFile: false,\n root,\n build: {\n outDir: functionsDir,\n emptyOutDir: true,\n ssr: true,\n lib: {\n entry: entryPath,\n formats: [\"es\"],\n fileName: () => \"__elur-js-kit.mjs\",\n },\n rollupOptions: {\n external: [],\n output: {\n inlineDynamicImports: true,\n },\n },\n },\n });\n\n // Vite SSR lib builds may use the entry file name, so force the expected handler name.\n const generatedHandler = join(functionsDir, \"netlify-index.js\");\n const targetHandler = join(functionsDir, \"__elur-js-kit.mjs\");\n try {\n await stat(generatedHandler);\n await rename(generatedHandler, targetHandler);\n } catch {\n // If the file is already named __elur-js-kit.mjs, nothing to do.\n }\n\n // Write Netlify redirects config.\n await writeFile(\n join(root, \"netlify.toml\"),\n `[build]\n command = \"elur-kit build\"\n publish = \"dist\"\n\n[[redirects]]\n from = \"/*\"\n to = \"/.netlify/functions/__elur-js-kit\"\n status = 200\n`,\n \"utf8\",\n );\n },\n};\n","import { mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { writeSsrEntry } from \"./shared.js\";\nimport { DEFAULT_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Bun adapter for elur-kit.\n *\n * Produces a self-contained Bun server entry at `.elur/bun-server.ts`.\n * Run it with:\n *\n * bun run .elur/bun-server.ts\n *\n * The server serves static files from `dist/` and renders pages on demand for\n * unmatched routes.\n */\nexport const bunAdapter: Adapter = {\n name: \"bun\",\n capabilities: DEFAULT_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const generatedDir = resolve(root, \".elur\");\n\n // Verify the production build exists.\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n // Clean previous adapter output.\n await rm(generatedDir, { recursive: true, force: true });\n await mkdir(generatedDir, { recursive: true });\n\n // Scan routes and generate a self-contained SSR handler entry.\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"bun-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n // Write the Bun server entry.\n const serverPath = resolve(generatedDir, \"bun-server.ts\");\n await writeFile(\n serverPath,\n buildBunServerSource(relativeToUrlPath(generatedDir, outDir), options),\n \"utf8\",\n );\n },\n};\n\nfunction buildBunServerSource(\n outDirUrl: string,\n options: {\n clientEntry: string;\n lang: string;\n port?: number;\n logLevel?: string;\n redirects?: import(\"../router/redirects.js\").RedirectRule[];\n rewrites?: import(\"../router/redirects.js\").RewriteRule[];\n routeHeaders?: import(\"../router/redirects.js\").RouteHeadersRule[];\n },\n): string {\n const logLevelOption = options.logLevel ? `, logLevel: ${JSON.stringify(options.logLevel)}` : \"\";\n // Rule arrays are plain data: emit them as JSON literals when defined.\n const routingOptions = ([\"redirects\", \"rewrites\", \"routeHeaders\"] as const)\n .map((key) => {\n const rules = options[key];\n return rules && rules.length > 0 ? `, ${key}: ${JSON.stringify(rules)}` : \"\";\n })\n .join(\"\");\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { fileURLToPath } from \"node:url\";\nimport { createWebHandler } from \"@elurjs/kit/runtime\";\nimport handler from \"./bun-index.ts\";\n\nconst outDir = fileURLToPath(new URL(${JSON.stringify(outDirUrl)}, import.meta.url));\nconst port = Number(process.env.PORT) || ${options.port ?? 3000};\n\nconst webHandler = createWebHandler(\n { pages: [], api: [], error404: undefined, error500: undefined },\n {},\n { staticRoot: outDir, lang: ${JSON.stringify(options.lang)}, clientEntry: ${JSON.stringify(options.clientEntry)}${logLevelOption}${routingOptions} },\n);\n\nBun.serve({\n port,\n async fetch(request) {\n // Try static files first via the unified handler, then fall back to the\n // bundled SSR handler for dynamic routes.\n let response = await webHandler(request);\n if (response.status === 404) {\n response = await handler(request);\n }\n return response;\n },\n});\n\nconsole.log(\\`Bun server running at http://localhost:\\${port}\\`);\n`;\n}\n\nfunction relativeToUrlPath(from: string, to: string): string {\n const path = relative(from, to).split(\"\\\\\").join(\"/\");\n return `${path.startsWith(\".\") ? path : `./${path}`}/`;\n}\n","import { mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { build } from \"vite\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { writeSsrEntry } from \"./shared.js\";\nimport { DEFAULT_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Node adapter for elur-kit.\n *\n * Produces a self-contained Node server entry at `.elur/node-server.mjs`.\n * Run it with:\n *\n * node .elur/node-server.mjs\n *\n * The server serves static files from `dist/` and renders pages on demand for\n * unmatched routes.\n */\nexport const nodeAdapter: Adapter = {\n name: \"node\",\n capabilities: DEFAULT_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const generatedDir = resolve(root, \".elur\");\n\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n await rm(generatedDir, { recursive: true, force: true });\n await mkdir(generatedDir, { recursive: true });\n\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"node-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n const serverPath = resolve(generatedDir, \"node-server.ts\");\n await writeFile(\n serverPath,\n buildNodeServerSource(relativeToUrlPath(generatedDir, outDir), options),\n \"utf8\",\n );\n\n await build({\n configFile: false,\n root,\n build: {\n outDir: generatedDir,\n emptyOutDir: false,\n ssr: true,\n lib: {\n entry: serverPath,\n formats: [\"es\"],\n },\n rollupOptions: {\n external: [/^@elurjs\\/kit(?:\\/.*)?$/, /^@elurjs\\/core(?:\\/.*)?$/, /^node:/],\n output: {\n entryFileNames: \"node-server.mjs\",\n inlineDynamicImports: true,\n },\n },\n },\n });\n },\n};\n\nfunction buildNodeServerSource(\n outDirUrl: string,\n options: {\n clientEntry: string;\n lang: string;\n port?: number;\n logLevel?: string;\n redirects?: import(\"../router/redirects.js\").RedirectRule[];\n rewrites?: import(\"../router/redirects.js\").RewriteRule[];\n routeHeaders?: import(\"../router/redirects.js\").RouteHeadersRule[];\n },\n): string {\n const logLevelOption = options.logLevel ? `, logLevel: ${JSON.stringify(options.logLevel)}` : \"\";\n // Rule arrays are plain data: emit them as JSON literals when defined.\n const routingOptions = ([\"redirects\", \"rewrites\", \"routeHeaders\"] as const)\n .map((key) => {\n const rules = options[key];\n return rules && rules.length > 0 ? `, ${key}: ${JSON.stringify(rules)}` : \"\";\n })\n .join(\"\");\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { createServer } from \"node:http\";\nimport { fileURLToPath } from \"node:url\";\nimport { createWebHandler } from \"@elurjs/kit/runtime\";\nimport { incomingMessageToRequest, sendWebResponse } from \"@elurjs/kit/runtime\";\nimport handler from \"./node-index.ts\";\n\nconst outDir = fileURLToPath(new URL(${JSON.stringify(outDirUrl)}, import.meta.url));\nconst port = Number(process.env.PORT) || ${options.port ?? 3000};\n\n// The adapter-bundled handler already handles actions, API routes, render\n// endpoint and dynamic SSR. We only need to add static file serving from\n// the output directory, then fall through to the bundled handler.\nconst webHandler = createWebHandler(\n { pages: [], api: [], error404: undefined, error500: undefined },\n {},\n { staticRoot: outDir, lang: ${JSON.stringify(options.lang)}, clientEntry: ${JSON.stringify(options.clientEntry)}${logLevelOption}${routingOptions} },\n);\n\ncreateServer(async (req, res) => {\n const body = req.method !== \"GET\" && req.method !== \"HEAD\"\n ? await readBody(req)\n : undefined;\n const request = incomingMessageToRequest(req, body);\n // Try static files first via the unified handler, then fall back to the\n // bundled SSR handler for dynamic routes.\n let response = await webHandler(request);\n if (response.status === 404) {\n response = await handler(request);\n }\n // Streams the body: streaming SSR chunks flush as they are produced.\n await sendWebResponse(res, response);\n}).listen(port, () => {\n console.log(\\`Node server running at http://localhost:\\${port}\\`);\n});\n\nfunction readBody(req: import(\"node:http\").IncomingMessage): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));\n req.on(\"end\", () => resolve(Buffer.concat(chunks)));\n req.on(\"error\", reject);\n });\n}\n`;\n}\n\nfunction relativeToUrlPath(from: string, to: string): string {\n const path = relative(from, to).split(\"\\\\\").join(\"/\");\n return `${path.startsWith(\".\") ? path : `./${path}`}/`;\n}\n","// --- CLI commands: check, routes, doctor (plan §12.1) ---\n//\n// `check` — typechecks the project and validates route/config integrity.\n// `routes` — lists all discovered routes and their metadata.\n// `doctor` — diagnoses common configuration and environment issues.\n//\n// All commands produce actionable error messages with cause/path/suggestion\n// and reliable exit codes.\n\nimport { stat, access } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport { scanActions } from \"../action/scan.js\";\nimport type { CliOptions } from \"../cli.js\";\n\n/** Exit codes used by all CLI commands. */\nexport const ExitCode = {\n Success: 0,\n GenericError: 1,\n ConfigError: 2,\n TypeError: 3,\n RouteConflict: 4,\n MissingDependency: 5,\n} as const;\n\n/** Formats an error with cause, path, and suggestion. */\nexport function formatError(\n cause: string,\n path?: string,\n suggestion?: string,\n): string {\n const parts = [cause];\n if (path) parts.push(` at: ${path}`);\n if (suggestion) parts.push(` fix: ${suggestion}`);\n return parts.join(\"\\n\");\n}\n\n// check — typecheck + route/config integrity\n\nexport async function doCheck(options: CliOptions): Promise<number> {\n console.log(\"Running typecheck...\");\n const typecheckResult = await runTypecheck(options.root);\n if (typecheckResult !== 0) {\n console.error(formatError(\n \"Typecheck failed.\",\n undefined,\n \"Fix TypeScript errors above before building.\",\n ));\n return ExitCode.TypeError;\n }\n console.log(\"✓ Typecheck passed\");\n\n console.log(\"\\nValidating routes...\");\n try {\n const routes = await scanRoutes(options.appDir);\n console.log(`✓ ${routes.pages.length} page route(s), ${routes.api.length} API route(s)`);\n if (routes.error404) console.log(\" - 404 page: configured\");\n if (routes.error500) console.log(\" - 500 page: configured\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(formatError(\n \"Route validation failed.\",\n options.appDir,\n message,\n ));\n return ExitCode.RouteConflict;\n }\n\n console.log(\"\\nValidating actions...\");\n try {\n const actions = await scanActions(options.appDir);\n console.log(`✓ ${actions.size} action(s) discovered`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(formatError(\n \"Action validation failed.\",\n options.appDir,\n message,\n ));\n return ExitCode.GenericError;\n }\n\n console.log(\"\\n✓ All checks passed\");\n return ExitCode.Success;\n}\n\n// routes — list all discovered routes\n\nexport async function doRoutes(options: CliOptions): Promise<number> {\n try {\n const routes = await scanRoutes(options.appDir);\n\n console.log(\"\\nPage routes:\");\n if (routes.pages.length === 0) {\n console.log(\" (none)\");\n } else {\n for (const page of routes.pages) {\n const params = page.params.length > 0 ? ` [${page.params.join(\", \")}]` : \"\";\n const loading = page.loadingPath ? \" +loading\" : \"\";\n const action = page.actionPath ? \" +action\" : \"\";\n const data = page.dataPath ? \" +data\" : \"\";\n const optional = page.optionalCatchAll ? \" (optional)\" : \"\";\n console.log(` ${page.path}${params}${data}${loading}${action}${optional}`);\n console.log(` page: ${relative(options.root, page.pagePath)}`);\n if (page.layouts.length > 0) {\n console.log(` layouts: ${page.layouts.map((l) => relative(options.root, l)).join(\" → \")}`);\n }\n }\n }\n\n console.log(\"\\nAPI routes:\");\n if (routes.api.length === 0) {\n console.log(\" (none)\");\n } else {\n for (const api of routes.api) {\n const params = api.params.length > 0 ? ` [${api.params.join(\", \")}]` : \"\";\n console.log(` ${api.path}${params}`);\n console.log(` route: ${relative(options.root, api.routePath)}`);\n }\n }\n\n if (routes.error404) {\n console.log(`\\n404 page: ${relative(options.root, routes.error404.pagePath)}`);\n } else {\n console.log(\"\\n404 page: (not configured)\");\n }\n if (routes.error500) {\n console.log(`500 page: ${relative(options.root, routes.error500.pagePath)}`);\n } else {\n console.log(\"500 page: (not configured)\");\n }\n\n return ExitCode.Success;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(formatError(\"Failed to scan routes.\", options.appDir, message));\n return ExitCode.RouteConflict;\n }\n}\n\n// doctor — diagnose common issues\n\ninterface DiagnosticResult {\n name: string;\n status: \"ok\" | \"warn\" | \"error\";\n message: string;\n suggestion?: string;\n}\n\nexport async function doDoctor(options: CliOptions): Promise<number> {\n const results: DiagnosticResult[] = [];\n\n // Check 1: app directory exists\n results.push(await checkExists(\"App directory\", options.appDir, \"Create src/app/ with at least a page.ts\"));\n\n // Check 2: islands directory exists (optional)\n if (options.islandsDir) {\n results.push(await checkExists(\"Islands directory\", options.islandsDir, \"Create src/islands/ for client-side islands\", \"warn\"));\n }\n\n // Check 3: public directory exists (optional)\n if (options.publicDir) {\n results.push(await checkExists(\"Public directory\", options.publicDir, \"Create public/ for static assets\", \"warn\"));\n }\n\n // Check 4: elur.config.ts exists (optional)\n const preferredPaths = [\"elur.config.ts\", \"elur.config.js\", \"elur.config.mjs\"];\n const legacyPaths = [\"elur.config.ts\", \"elur.config.js\", \"elur.config.mjs\"];\n let configFound = false;\n let foundName: string | undefined;\n let isLegacy = false;\n for (const p of preferredPaths) {\n try {\n await access(join(options.root, p));\n configFound = true;\n foundName = p;\n break;\n } catch {\n // continue\n }\n }\n if (!configFound) {\n for (const p of legacyPaths) {\n try {\n await access(join(options.root, p));\n configFound = true;\n foundName = p;\n isLegacy = true;\n break;\n } catch {\n // continue\n }\n }\n }\n if (configFound && foundName) {\n results.push({\n name: \"Config file\",\n status: isLegacy ? \"warn\" : \"ok\",\n message: `Found ${foundName}${isLegacy ? \" (legacy, rename to elur.config.* )\" : \"\"}`,\n suggestion: isLegacy\n ? `Rename ${foundName} to elur.config.${foundName.split(\".\").slice(1).join(\".\")} (deprecated name)`\n : undefined,\n });\n } else {\n results.push({\n name: \"Config file\",\n status: \"warn\",\n message: \"No elur.config.ts/js/mjs found\",\n suggestion: \"Create elur.config.ts for custom configuration (optional, defaults work)\",\n });\n }\n\n // Check 5: TypeScript config exists\n results.push(await checkExists(\"tsconfig.json\", join(options.root, \"tsconfig.json\"), \"Create a tsconfig.json for TypeScript support\", \"warn\"));\n\n // Check 6: Node.js version\n const nodeVersion = process.versions.node;\n const major = parseInt(nodeVersion.split(\".\")[0]!, 10);\n if (major >= 18) {\n results.push({ name: \"Node.js version\", status: \"ok\", message: `v${nodeVersion}` });\n } else {\n results.push({\n name: \"Node.js version\",\n status: \"error\",\n message: `v${nodeVersion} (requires >= 18)`,\n suggestion: \"Upgrade Node.js to v18 or later\",\n });\n }\n\n // Check 7: routes scan\n try {\n const routes = await scanRoutes(options.appDir);\n results.push({\n name: \"Route scan\",\n status: routes.pages.length > 0 ? \"ok\" : \"warn\",\n message: `${routes.pages.length} page(s), ${routes.api.length} API route(s)`,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n results.push({\n name: \"Route scan\",\n status: \"error\",\n message: message,\n suggestion: \"Fix route conflicts or file structure issues\",\n });\n }\n\n // Check 8: optional peer dependencies\n const peers = [\n { name: \"marked\", import: \"marked\", purpose: \"Markdown rendering\" },\n { name: \"zod\", import: \"zod\", purpose: \"Schema validation\" },\n { name: \"sharp\", import: \"sharp\", purpose: \"Image optimization\" },\n ];\n for (const peer of peers) {\n try {\n await import(peer.import);\n results.push({ name: `Peer dep: ${peer.name}`, status: \"ok\", message: `available (${peer.purpose})` });\n } catch {\n results.push({\n name: `Peer dep: ${peer.name}`,\n status: \"warn\",\n message: `not installed (${peer.purpose})`,\n suggestion: `Install with: bun add ${peer.name}`,\n });\n }\n }\n\n // Print results\n console.log(\"\\nElur Kit doctor\\n\");\n let hasErrors = false;\n let hasWarnings = false;\n for (const result of results) {\n const icon = result.status === \"ok\" ? \"✓\" : result.status === \"warn\" ? \"⚠\" : \"✗\";\n const color = result.status === \"ok\" ? \"\" : result.status === \"warn\" ? \"\" : \"\";\n console.log(`${icon} ${result.name}: ${color}${result.message}`);\n if (result.suggestion) console.log(` → ${result.suggestion}`);\n if (result.status === \"error\") hasErrors = true;\n if (result.status === \"warn\") hasWarnings = true;\n }\n\n console.log(\"\");\n if (hasErrors) {\n console.log(\"✗ Issues found. Fix errors before building.\");\n return ExitCode.GenericError;\n } else if (hasWarnings) {\n console.log(\"⚠ Warnings found. Project may work but consider fixing them.\");\n return ExitCode.Success;\n } else {\n console.log(\"✓ All checks passed. Project is healthy.\");\n return ExitCode.Success;\n }\n}\n\n// Helpers\n\nasync function checkExists(\n name: string,\n path: string,\n suggestion: string,\n level: \"error\" | \"warn\" = \"error\",\n): Promise<DiagnosticResult> {\n try {\n await stat(path);\n return { name, status: \"ok\", message: path };\n } catch {\n return {\n name,\n status: level,\n message: `not found at ${path}`,\n suggestion,\n };\n }\n}\n\nasync function runTypecheck(root: string): Promise<number> {\n return new Promise((resolve) => {\n const child = spawn(\"npx\", [\"tsc\", \"--noEmit\"], {\n cwd: root,\n stdio: \"inherit\",\n shell: true,\n });\n child.on(\"close\", (code) => resolve(code ?? 1));\n child.on(\"error\", () => resolve(1));\n });\n}\n","import { stat } from \"node:fs/promises\";\nimport { createServer } from \"node:http\";\nimport { dirname, join, resolve, relative } from \"node:path\";\nimport { existsSync, watch } from \"node:fs\";\nimport { spawn } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\nimport { createRequire } from \"node:module\";\nimport { build, type BuildConfig } from \"./build/build.js\";\nimport { transformProjectFiles, transformedAppDir as transformedAppDirOf } from \"./build/transform-source.js\";\nimport { scanActions } from \"./action/scan.js\";\nimport { scanRoutes } from \"./router/route-scanner.js\";\nimport { incomingMessageToRequest, sendWebResponse } from \"./runtime/node-http.js\";\nimport { createRequestLogger, type LogLevel } from \"./runtime/logger.js\";\nimport { loadElurConfig, type ResolvedElurConfig } from \"./config/index.js\";\nimport { createAppManifest, writeAppManifest, writeRouteTypes } from \"./manifest/index.js\";\nimport { validateCapabilities } from \"./runtime/capabilities.js\";\nimport * as out from \"./cli/output.js\";\nimport { listenWithFallback, PORT_UNAVAILABLE_EXIT_CODE } from \"./cli/ports.js\";\n\n// --- CLI ---\n//\n// Minimal command-line interface for Elur Kit. Supports:\n// elur-kit build — run a production static build\n// elur-kit dev — run a dev server that rebuilds on file changes\n// elur-kit preview — serve the static build in production mode\n// elur-kit start — run an SSR server that renders pages on demand\n//\n// This is intentionally small: no generators, no config file parsing, just\n// convention-based defaults overridable via CLI flags.\n\nexport interface CliOptions {\n command: \"build\" | \"dev\" | \"preview\" | \"start\" | \"adapter\" | \"check\" | \"routes\" | \"doctor\";\n adapterName?: \"vercel\" | \"netlify\" | \"bun\" | \"node\";\n root: string;\n appDir: string;\n islandsDir?: string;\n outDir: string;\n publicDir?: string;\n generatedEntry: string;\n clientEntry: string;\n port: number;\n host: string;\n lang: string;\n hydrateImport?: string;\n routerImport?: string;\n /**\n * Path to a Vite config used to build the client hydration bundle.\n * In dev mode it is rebuilt whenever source files change.\n */\n clientConfig?: string;\n /** Absolute path to the ISR cache directory. */\n cacheDir?: string;\n /** Default revalidate interval in seconds for ISR. */\n defaultRevalidate?: number;\n configFile?: string;\n resolvedConfig?: ResolvedElurConfig;\n /**\n * Verbosity override from `--verbose` (\"debug\") / `--quiet` (\"error\").\n * Overrides `logger.level` from the config file.\n */\n logLevel?: LogLevel;\n /**\n * Internal: whether the client bundle emits the router as its own chunk\n * (`router.js`). Computed by `doBuild` from the resolved config and the\n * client bundle inputs — `true` for the kit-generated default config and\n * for user configs that declare the generated router module as an input.\n */\n routerSeparate?: boolean;\n /** Internal: whether the last build found any islands. */\n hasIslands?: boolean;\n /**\n * Internal: public URL of the router chunk when the emitted bundle\n * actually contains it (`/_elur/router.js` exists in the output).\n * Computed once per server start for dev/preview/start.\n */\n routerEntry?: string;\n}\n\nfunction parseArgs(argv: string[]): CliOptions {\n const args = argv.slice(2);\n if (args.includes(\"--help\") || args.includes(\"-?\")) {\n printHelp();\n process.exit(0);\n }\n const command = args[0];\n if (\n command !== \"build\" &&\n command !== \"dev\" &&\n command !== \"preview\" &&\n command !== \"start\" &&\n command !== \"adapter\" &&\n command !== \"check\" &&\n command !== \"routes\" &&\n command !== \"doctor\"\n ) {\n throw new Error(`Usage: elur-kit <build|dev|preview|start|adapter|check|routes|doctor> [options]`);\n }\n const adapterName = command === \"adapter\" ? args[1] : undefined;\n if (\n command === \"adapter\" &&\n adapterName !== \"vercel\" &&\n adapterName !== \"netlify\" &&\n adapterName !== \"bun\" &&\n adapterName !== \"node\"\n ) {\n throw new Error(`Usage: elur-kit adapter <vercel|netlify|bun|node> [options]`);\n }\n const optionStart = command === \"adapter\" ? 2 : 1;\n\n let root = process.cwd();\n let appDir = \"src/app\";\n let islandsDir = \"src/islands\";\n let outDir = \"dist\";\n let publicDir = \"public\";\n let generatedEntry = \".elur/entry-client.ts\";\n let clientEntry = \"/_elur/entry-client.js\";\n let port = 3000;\n let host = \"127.0.0.1\";\n let lang = \"es\";\n let hydrateImport: string | undefined;\n let routerImport: string | undefined;\n let clientConfig: string | undefined;\n let cacheDir: string | undefined;\n let defaultRevalidate: number | undefined;\n let configFile: string | undefined;\n let logLevel: LogLevel | undefined;\n\n for (let i = optionStart; i < args.length; i++) {\n const arg = args[i];\n const next = args[i + 1];\n switch (arg) {\n case \"--root\":\n case \"-r\":\n root = next;\n i++;\n break;\n case \"--app\":\n case \"-a\":\n appDir = next;\n i++;\n break;\n case \"--islands\":\n case \"-i\":\n islandsDir = next;\n i++;\n break;\n case \"--out\":\n case \"-o\":\n outDir = next;\n i++;\n break;\n case \"--public\":\n publicDir = next;\n i++;\n break;\n case \"--port\":\n case \"-p\":\n port = Number(next);\n i++;\n break;\n case \"--host\":\n case \"-h\":\n host = next;\n i++;\n break;\n case \"--lang\":\n case \"-l\":\n lang = next;\n i++;\n break;\n case \"--hydrate-import\":\n hydrateImport = next;\n i++;\n break;\n case \"--router-import\":\n routerImport = next;\n i++;\n break;\n case \"--client-config\":\n clientConfig = next;\n i++;\n break;\n case \"--config\":\n configFile = next;\n i++;\n break;\n case \"--cache-dir\":\n cacheDir = next;\n i++;\n break;\n case \"--default-revalidate\":\n defaultRevalidate = Number(next);\n i++;\n break;\n case \"--verbose\":\n // --quiet wins when both are passed.\n if (logLevel !== \"error\") logLevel = \"debug\";\n break;\n case \"--quiet\":\n logLevel = \"error\";\n break;\n case \"--help\":\n case \"-?\":\n printHelp();\n process.exit(0);\n default:\n throw new Error(`Unknown option: ${arg}`);\n }\n }\n\n return {\n command,\n adapterName: adapterName as CliOptions[\"adapterName\"],\n root: resolve(root),\n appDir: resolve(root, appDir),\n islandsDir: resolve(root, islandsDir),\n outDir: resolve(root, outDir),\n publicDir: resolve(root, publicDir),\n generatedEntry: resolve(root, generatedEntry),\n clientEntry,\n port,\n host,\n lang,\n hydrateImport,\n routerImport,\n clientConfig: clientConfig ? resolve(root, clientConfig) : undefined,\n cacheDir: cacheDir ? resolve(root, cacheDir) : undefined,\n defaultRevalidate,\n configFile: configFile ? resolve(root, configFile) : undefined,\n logLevel,\n };\n}\n\nfunction printHelp(): void {\n console.log(`\nelur-kit <command> [options]\n\nCommands:\n build Run a static site build\n dev Run a development server with rebuild-on-change\n preview Serve the static build in production mode\n start Run an SSR server that renders pages on demand\n adapter <name> Generate deployment output for a platform (vercel|netlify|bun|node)\n check Typecheck the project and validate route/config integrity\n routes List all discovered routes and their metadata\n doctor Diagnose common configuration and environment issues\n\nOptions:\n -r, --root <dir> Project root (default: cwd)\n -a, --app <dir> App directory relative to root (default: src/app)\n -i, --islands <dir> Islands directory relative to root (default: src/islands)\n -o, --out <dir> Output directory relative to root (default: dist)\n --public <dir> Public directory relative to root (default: public)\n -p, --port <number> Server port (default: 3000)\n -h, --host <address> Server host (default: 127.0.0.1)\n -l, --lang <lang> HTML lang attribute (default: es)\n --hydrate-import <spec> Import specifier for hydrateIslands in generated entry\n --router-import <spec> Import specifier for startClientRouter in generated entry\n --client-config <path> Vite config used to build the client hydration bundle\n --config <path> Elur config file (default: elur.config.ts/js/mjs)\n --cache-dir <dir> Directory for ISR cache (only used by start)\n --default-revalidate <s> Default ISR revalidate interval in seconds\n --verbose Debug logging (overrides logger.level)\n --quiet Only errors are printed (overrides logger.level)\n`);\n}\n\n/**\n * Reads the kit's own version from package.json. The CLI runs from two\n * layouts: src/cli.ts in the repo (../package.json) and dist/lib/cli.js when\n * installed (../../package.json).\n */\nfunction getKitVersion(): string {\n const require = createRequire(import.meta.url);\n for (const rel of [\"../package.json\", \"../../package.json\"]) {\n try {\n const pkg = require(rel) as { version?: unknown };\n if (typeof pkg.version === \"string\") return pkg.version;\n } catch {\n // Try the next layout.\n }\n }\n return \"unknown\";\n}\n\nfunction toBuildConfig(options: CliOptions): BuildConfig {\n return {\n root: options.root,\n appDir: options.appDir,\n outDir: options.outDir,\n publicDir: options.publicDir,\n clientEntry: options.clientEntry,\n lang: options.lang,\n islandsDir: options.islandsDir,\n generatedEntry: options.generatedEntry,\n hydrateImport: options.hydrateImport,\n routerImport: options.routerImport,\n imageFormats: options.resolvedConfig?.images.formats,\n integrations: options.resolvedConfig?.integrations,\n site: options.resolvedConfig?.site,\n js: options.resolvedConfig?.js,\n router: options.resolvedConfig\n ? {\n enabled: options.resolvedConfig.router.enabled,\n prefetch: options.resolvedConfig.router.prefetch,\n morph: options.resolvedConfig.router.morph,\n loadingIndicator: options.resolvedConfig.router.loadingIndicator,\n speculation: options.resolvedConfig.router.speculation,\n // Whether the bundle emits the router as its own chunk — computed\n // before pages render so the shell knows to advertise router.js.\n separate: options.routerSeparate,\n entry: \"/_elur/router.js\",\n outFile: join(dirname(options.generatedEntry), \"router.ts\"),\n }\n : undefined,\n };\n}\n\nasync function doBuild(options: CliOptions): Promise<void> {\n const buildStart = Date.now();\n const transformedRoot = join(options.root, \".elur\", \"transformed\");\n const transformedAppDir = transformedAppDirOf(options.root, options.appDir, options.islandsDir, transformedRoot);\n let phaseStart = performance.now();\n await transformProjectFiles({\n root: options.root,\n appDir: options.appDir,\n islandsDir: options.islandsDir,\n outDir: transformedRoot,\n });\n out.phase(\"transform\", performance.now() - phaseStart);\n\n // Atomic output staging: build into a temp directory, then swap to the final\n // outDir so a crashed build never leaves a half-written dist.\n const { beginAtomicStage } = await import(\"./build/vite-build.js\");\n const stage = await beginAtomicStage({ outDir: options.outDir });\n const tempOutDir = stage.tempDir;\n\n // Resolve the client bundle layout BEFORE rendering pages: whether the\n // router is emitted as its own chunk decides both the generated entry\n // (hydrate-only vs combined) and which scripts the shell advertises.\n if (options.islandsDir && !options.clientConfig) {\n const autoConfig = await findClientConfig(options.root);\n if (autoConfig) options.clientConfig = autoConfig;\n }\n options.routerSeparate = await resolveRouterSeparate(options);\n\n try {\n const buildConfig = toBuildConfig(options);\n buildConfig.appDir = transformedAppDir;\n buildConfig.outDir = tempOutDir;\n buildConfig.onPhase = (name, ms) => out.phase(name, ms);\n const result = await build(buildConfig);\n options.hasIslands = result.islands.length > 0;\n\n // Emit the portable application manifest and route types when a resolved\n // config is available. The manifest is the source of truth for adapters,\n // the client island registry and runtime route metadata.\n if (options.resolvedConfig) {\n phaseStart = performance.now();\n try {\n const manifest = await createAppManifest(options.resolvedConfig);\n const manifestPath = join(tempOutDir, \".elur\", \"manifest.json\");\n await writeAppManifest(manifest, manifestPath);\n const typesPath = join(options.root, \".elur\", \"routes.d.ts\");\n await writeRouteTypes(manifest, typesPath);\n out.phase(\"manifest\", performance.now() - phaseStart);\n } catch (err) {\n out.warn(`manifest generation failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n // Build the client bundle when there is something to ship: islands to\n // hydrate, a router to run, or an explicit user config (which may bundle\n // extra client code beyond the generated entry). Without a user config,\n // the kit synthesizes a default one from the generated inputs.\n const routerEnabled = options.resolvedConfig?.router.enabled !== false;\n if (options.clientConfig || options.hasIslands || routerEnabled) {\n // Temporarily redirect the client build to the staging directory.\n const originalOutDir = options.outDir;\n options.outDir = tempOutDir;\n try {\n phaseStart = performance.now();\n await buildClient(options);\n out.phase(\"client bundle\", performance.now() - phaseStart);\n } finally {\n options.outDir = originalOutDir;\n }\n }\n\n // Atomically swap the staged output into the final destination.\n await stage.commit();\n\n const elapsed = ((Date.now() - buildStart) / 1000).toFixed(2);\n out.success(`${out.bold(\"Build completo\")} ${out.dim(`en ${elapsed}s`)}`);\n out.info(`${result.pages} página(s), ${result.islands.length} island(s), ${result.files.length} archivo(s)`);\n const fileEntries: out.FileEntry[] = [];\n for (const file of result.files) {\n // result.files point at the staging directory; display the final path.\n const finalPath = join(options.outDir, relative(tempOutDir, file));\n let bytes = 0;\n try {\n bytes = (await stat(finalPath)).size;\n } catch {\n // File may have been moved by an integration; size stays 0.\n }\n fileEntries.push({ path: relative(options.root, finalPath), bytes });\n }\n out.fileList(fileEntries);\n if (result.islands.length > 0) {\n out.success(`${result.islands.length} island(s) detectada(s):`);\n for (const island of result.islands) {\n out.detail(island.name);\n }\n if (result.generatedEntry) {\n out.detail(`entry: ${relative(options.root, result.generatedEntry)}`);\n }\n }\n if (result.skipped.length > 0) {\n out.warn(\"Rutas dinámicas omitidas (necesitan generateStaticParams):\");\n for (const path of result.skipped) {\n out.detail(path);\n }\n }\n } catch (err) {\n await stage.rollback();\n throw err;\n }\n}\n\nconst DEV_WORKER_ENV = \"ELUR_JS_KIT_DEV_WORKER\";\n\nasync function doDev(options: CliOptions): Promise<void> {\n await doBuild(options);\n\n const transformedRoot = join(options.root, \".elur\", \"transformed\");\n const transformedAppDir = transformedAppDirOf(options.root, options.appDir, options.islandsDir, transformedRoot);\n await transformProjectFiles({\n root: options.root,\n appDir: options.appDir,\n islandsDir: options.islandsDir,\n outDir: transformedRoot,\n });\n\n const actions = await scanActions(transformedAppDir);\n const routes = await scanRoutes(transformedAppDir);\n const middleware = await loadUserMiddleware(options.root);\n options.routerEntry = detectRouterEntry(options);\n const server = createServer((req, res) => handleRequest(req, res, options, actions, routes, true, middleware));\n\n const shutdown = () => {\n server.close(() => process.exit(0));\n setTimeout(() => process.exit(0), 2000).unref();\n };\n process.on(\"SIGTERM\", shutdown);\n process.on(\"SIGINT\", shutdown);\n\n try {\n const usedPort = await listenWithFallback(server, options.host, options.port, {\n onFallback: (busyPort, nextPort) => out.warn(`Puerto ${busyPort} ocupado, usando ${nextPort}`),\n });\n const network = out.getNetworkAddress();\n out.serverBanner({\n name: \"elur-kit\",\n version: `v${getKitVersion()}`,\n command: \"dev\",\n localUrl: `http://${options.host}:${usedPort}/`,\n networkUrl: network ? `http://${network}:${usedPort}/` : undefined,\n });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EADDRINUSE\") {\n out.error(`No hay puerto disponible entre ${options.port} y ${options.port + 20}.`);\n // Distinct exit code so the supervisor does not restart-loop.\n process.exit(PORT_UNAVAILABLE_EXIT_CODE);\n }\n throw err;\n }\n}\n\n/**\n * Dev supervisor: runs the actual dev server in a child process and restarts\n * it whenever app/islands source files change. A fresh process means a fresh\n * module registry, so edits to pages, loaders, layouts and islands are always\n * picked up (no stale ESM cache).\n */\nasync function doDevSupervisor(options: CliOptions): Promise<void> {\n // Re-invoke this bin with the same flags; the worker branch (env var set)\n // runs the actual server in a fresh process.\n const binPath = process.argv[1];\n const spawnPath = binPath && existsSync(binPath)\n ? binPath\n : fileURLToPath(import.meta.url);\n const args = process.argv.slice(2);\n\n let child: import(\"node:child_process\").ChildProcess | null = null;\n let stopping = false;\n let intentional = false;\n let respawnTimer: ReturnType<typeof setTimeout> | null = null;\n\n const startWorker = () => {\n intentional = false;\n console.log();\n out.event(\"dev\", \"Starting dev server...\");\n child = spawn(process.execPath, [spawnPath, ...args], {\n env: { ...process.env, [DEV_WORKER_ENV]: \"1\" },\n stdio: \"inherit\",\n });\n child.on(\"exit\", (code) => {\n child = null;\n if (stopping) return;\n if (intentional) {\n // Restart after a source change.\n respawnTimer = setTimeout(startWorker, 400);\n return;\n }\n if (code !== 0) {\n if (code === PORT_UNAVAILABLE_EXIT_CODE) {\n // The worker already reported that no port is available; restarting\n // would loop forever on the same EADDRINUSE.\n out.error(\"[dev] Stopping: no available port.\");\n process.exit(code);\n }\n out.error(`[dev] Dev server exited with code ${code}; restarting...`);\n respawnTimer = setTimeout(startWorker, 600);\n }\n });\n };\n\n const restart = () => {\n if (!child) return;\n intentional = true;\n child.kill(\"SIGTERM\");\n };\n\n const watchedDirs = [options.appDir, options.islandsDir].filter(Boolean) as string[];\n if (watchedDirs.length > 0) {\n let timer: ReturnType<typeof setTimeout> | null = null;\n const scheduleRestart = () => {\n console.log();\n out.event(\"change\", \"Restarting dev server...\");\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => restart(), 150);\n };\n for (const dir of watchedDirs) {\n try {\n watch(dir, { recursive: true }, (event, filename) => {\n // Editors and sed replace files via atomic rename, which reports the\n // temporary name (e.g. \"blog/sed1234\") instead of the .ts file, so\n // treat every rename as a potential source change. \"change\" events\n // only restart when the reported name looks like a source file.\n if (event === \"rename\") {\n scheduleRestart();\n } else if (filename && /\\.ts$/.test(filename)) {\n scheduleRestart();\n }\n });\n } catch (err) {\n out.error(`[dev] failed to watch ${dir}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n }\n\n const cleanup = () => {\n stopping = true;\n if (respawnTimer) clearTimeout(respawnTimer);\n if (child) child.kill(\"SIGTERM\");\n // Exit after the worker has gone, so a new supervisor can take over the port.\n const deadline = setTimeout(() => process.exit(0), 3000);\n deadline.unref();\n if (!child) process.exit(0);\n };\n process.on(\"SIGINT\", cleanup);\n process.on(\"SIGTERM\", cleanup);\n\n startWorker();\n}\n\n/**\n * Shared production-serving path for `preview` and `start`: serves the build\n * output plus dynamic SSR through the unified Web handler, with middleware,\n * streaming, port fallback and the startup banner. Both commands behave\n * identically; the label only differs in the banner.\n */\nasync function startProductionServer(\n options: CliOptions,\n command: \"preview\" | \"start\",\n): Promise<import(\"node:http\").Server> {\n try {\n const s = await stat(options.outDir);\n if (!s.isDirectory()) {\n throw new Error(`Output path is not a directory: ${options.outDir}`);\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n throw new Error(\n `No build output found at ${options.outDir}. Run \\`elur-kit build\\` first.`,\n );\n }\n throw err;\n }\n\n const transformedRoot = join(options.root, \".elur\", command === \"preview\" ? \"preview-transformed\" : \"transformed\");\n const transformedAppDir = transformedAppDirOf(options.root, options.appDir, options.islandsDir, transformedRoot);\n await transformProjectFiles({\n root: options.root,\n appDir: options.appDir,\n islandsDir: options.islandsDir,\n outDir: transformedRoot,\n });\n\n const actions = await scanActions(transformedAppDir);\n const routes = await scanRoutes(transformedAppDir);\n const middleware = await loadUserMiddleware(options.root);\n options.routerEntry = detectRouterEntry(options);\n const server = createServer((req, res) => handleRequest(req, res, options, actions, routes, false, middleware));\n const usedPort = await listenWithFallback(server, options.host, options.port, {\n onFallback: (busyPort, nextPort) => out.warn(`Puerto ${busyPort} ocupado, usando ${nextPort}`),\n });\n const network = out.getNetworkAddress();\n out.serverBanner({\n name: \"elur-kit\",\n version: `v${getKitVersion()}`,\n command,\n localUrl: `http://${options.host}:${usedPort}/`,\n networkUrl: network ? `http://${network}:${usedPort}/` : undefined,\n });\n return server;\n}\n\nexport async function doPreview(options: CliOptions): Promise<import(\"node:http\").Server> {\n return startProductionServer(options, \"preview\");\n}\n\nasync function doStart(options: CliOptions): Promise<void> {\n // `start` now runs on the unified Web handler like dev/preview (it used to\n // rely on the legacy createSsrServer pipeline).\n await startProductionServer(options, \"start\");\n}\n\nasync function findClientConfig(root: string): Promise<string | undefined> {\n const candidates = [\"vite.client.config.ts\", \"vite.client.config.js\", \"vite.client.config.mjs\"];\n for (const name of candidates) {\n const path = resolve(root, name);\n try {\n if ((await stat(path)).isFile()) return path;\n } catch {\n // ignore\n }\n }\n return undefined;\n}\n\n/**\n * Decides whether the client bundle emits the router as its own chunk.\n *\n * - `js: \"legacy\"` or `router.enabled: false` → never split (the entry is\n * hydrate-only when the router is off; legacy embeds the router).\n * - A user-provided client config splits only when it declares the generated\n * router module (`.elur/router.ts`) as a bundle input — a single input is\n * \"legacy de facto\": the router stays embedded in `entry-client.js`.\n * - Without a user config, the kit synthesizes a default two-input config →\n * split.\n */\nasync function resolveRouterSeparate(options: CliOptions): Promise<boolean> {\n const rc = options.resolvedConfig;\n if (!rc || rc.js === \"legacy\" || rc.router.enabled === false) return false;\n const routerFile = join(dirname(options.generatedEntry), \"router.ts\");\n if (!options.clientConfig) return true;\n try {\n const { resolveClientInputs } = await import(\"./build/vite-build.js\");\n const inputs = await resolveClientInputs(options.clientConfig, options.root);\n return inputs.includes(routerFile);\n } catch {\n return false;\n }\n}\n\n/**\n * Public URL of the router chunk when the built bundle actually contains it.\n * The file check keeps `preview`/`start` consistent with whatever layout the\n * last build produced (split or legacy single-entry).\n */\nfunction detectRouterEntry(options: CliOptions): string | undefined {\n const rc = options.resolvedConfig;\n if (!rc || rc.js === \"legacy\" || rc.router.enabled === false) return undefined;\n return existsSync(join(options.outDir, \"_elur\", \"router.js\"))\n ? \"/_elur/router.js\"\n : undefined;\n}\n\nasync function buildClient(options: CliOptions): Promise<void> {\n // Use the programmatic Vite build API instead of spawnSync(\"npx\", [\"vite\", ...]).\n // This avoids child-process overhead, shares the module cache, and gives us\n // structured errors instead of exit-code parsing.\n const { buildClientBundle } = await import(\"./build/vite-build.js\");\n const clientOutDir = join(options.outDir, \"_elur\");\n // The client bundle is always served from /_elur/ regardless of the\n // project's deployment base. The deployment base is applied to page HTML,\n // not to the internal hydration bundle path.\n const clientBase = \"/_elur/\";\n // Inputs for the kit-synthesized default config (used only when the\n // project does not ship its own vite.client.config.*).\n const defaultInputs: Record<string, string> = {\n \"entry-client\": options.generatedEntry,\n };\n if (options.routerSeparate) {\n defaultInputs.router = join(dirname(options.generatedEntry), \"router.ts\");\n }\n await buildClientBundle({\n root: options.root,\n userConfigPath: options.clientConfig ? resolve(options.clientConfig) : undefined,\n defaultInputs,\n appDir: join(options.root, \"src\", \"app\"),\n islandsDir: join(options.root, \"src\", \"islands\"),\n outDir: clientOutDir,\n base: clientBase,\n logPrefix: \"[client]\",\n quiet: options.logLevel === \"error\",\n });\n}\n\n/**\n * Loads the project's `src/middleware.ts` for dev/preview/start. A missing\n * file is fine; a broken one warns but does not stop the server.\n */\nasync function loadUserMiddleware(\n root: string,\n): Promise<import(\"./middleware/index.js\").LoadedMiddleware | null> {\n const { loadMiddleware } = await import(\"./middleware/index.js\");\n try {\n return await loadMiddleware(root);\n } catch (err) {\n out.warn(err instanceof Error ? err.message : String(err));\n return null;\n }\n}\n\nasync function handleRequest(\n req: import(\"node:http\").IncomingMessage,\n res: import(\"node:http\").ServerResponse,\n options: CliOptions,\n actions: import(\"./action/scan.js\").ActionRegistry,\n routes: import(\"./router/route-scanner.js\").ScannedRoutes,\n noCache = false,\n middleware?: import(\"./middleware/index.js\").LoadedMiddleware | null,\n): Promise<void> {\n // Unified pipeline: actions, render endpoint, API routes, static files and\n // dynamic SSR all run through `createWebHandler`, the same code used by the\n // Node/Bun/Vercel/Netlify adapters. This eliminates the duplicated request\n // handling that previously diverged between dev/preview/start and adapters\n // (audit §8.1, Risk 1).\n const { createWebHandler } = await import(\"./runtime/handler.js\");\n const securityHeaders = (options.resolvedConfig as { security?: { headers?: unknown } } | undefined)?.security?.headers;\n const webHandler = createWebHandler(\n routes,\n actions,\n {\n staticRoot: options.outDir,\n noCache,\n cacheDir: options.cacheDir,\n defaultRevalidate: options.defaultRevalidate,\n lang: options.lang,\n clientEntry: options.clientEntry,\n renderEndpoint: true,\n router: {\n enabled: options.resolvedConfig?.router.enabled ?? true,\n entry: options.routerEntry,\n },\n js: options.resolvedConfig?.js,\n securityHeaders: securityHeaders === undefined ? false : (securityHeaders as never),\n logLevel: options.resolvedConfig?.logger?.level,\n cacheAdapter: options.resolvedConfig?.cache?.adapter,\n redirects: options.resolvedConfig?.redirects,\n rewrites: options.resolvedConfig?.rewrites,\n routeHeaders: options.resolvedConfig?.headers,\n streaming: options.resolvedConfig?.streaming,\n middleware: middleware ?? undefined,\n },\n );\n\n const body = req.method && req.method !== \"GET\" && req.method !== \"HEAD\"\n ? await readRequestBody(req)\n : undefined;\n const request = incomingMessageToRequest(req, body);\n let response: Response;\n try {\n response = await webHandler(request);\n } catch (err) {\n // Last-resort failure outside the unified handler: log through the\n // structured logger at server level (a fresh per-request logger, since\n // the handler's own logger is unreachable here).\n createRequestLogger(request, options.resolvedConfig?.logger?.level).error(\"[elur-kit] request error\", {\n path: new URL(request.url).pathname,\n method: request.method,\n error: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n });\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(\"Internal Server Error\");\n return;\n }\n // Stream the response body to the socket: for streaming SSR responses the\n // chunks are flushed as they are produced instead of being buffered whole.\n await sendWebResponse(res, response);\n}\n\nfunction readRequestBody(req: import(\"node:http\").IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let body = \"\";\n req.setEncoding(\"utf8\");\n req.on(\"data\", (chunk) => {\n body += chunk;\n });\n req.on(\"end\", () => resolve(body));\n req.on(\"error\", reject);\n });\n}\n\nasync function doAdapter(options: CliOptions): Promise<void> {\n const adapterOptions = {\n root: options.root,\n appDir: options.appDir,\n islandsDir: options.islandsDir ?? resolve(options.root, \"src/islands\"),\n outDir: options.outDir,\n publicDir: options.publicDir,\n clientEntry: options.clientEntry,\n lang: options.lang,\n hydrateImport: options.hydrateImport,\n logLevel: options.resolvedConfig?.logger?.level,\n cacheAdapter: options.resolvedConfig?.cache?.adapter,\n redirects: options.resolvedConfig?.redirects,\n rewrites: options.resolvedConfig?.rewrites,\n routeHeaders: options.resolvedConfig?.headers,\n streaming: options.resolvedConfig?.streaming,\n router: { enabled: options.resolvedConfig?.router.enabled ?? true },\n js: options.resolvedConfig?.js,\n };\n const resolvedConfig = options.resolvedConfig as { images?: { strict?: boolean }; cache?: { defaultRevalidate?: number }; streaming?: boolean } | undefined;\n const features = {\n isr: typeof resolvedConfig?.cache?.defaultRevalidate === \"number\" && resolvedConfig.cache.defaultRevalidate > 0,\n images: resolvedConfig?.images?.strict === true,\n streaming: resolvedConfig?.streaming === true,\n };\n let adapterName = options.adapterName;\n if (adapterName === \"vercel\") {\n const { vercelAdapter } = await import(\"./adapters/vercel.js\");\n assertCapabilities(vercelAdapter, features, adapterName);\n await vercelAdapter.build(adapterOptions);\n console.log();\n out.info(\"Vercel output generated at .vercel/output\");\n } else if (adapterName === \"netlify\") {\n const { netlifyAdapter } = await import(\"./adapters/netlify.js\");\n assertCapabilities(netlifyAdapter, features, adapterName);\n await netlifyAdapter.build(adapterOptions);\n console.log();\n out.info(\"Netlify output generated at netlify/functions/__elur-js-kit.mjs\");\n } else if (adapterName === \"bun\") {\n const { bunAdapter } = await import(\"./adapters/bun.js\");\n assertCapabilities(bunAdapter, features, adapterName);\n await bunAdapter.build(adapterOptions);\n console.log();\n out.info(\"Bun server generated at .elur/bun-server.ts\");\n } else if (adapterName === \"node\") {\n const { nodeAdapter } = await import(\"./adapters/node.js\");\n assertCapabilities(nodeAdapter, features, adapterName);\n await nodeAdapter.build(adapterOptions);\n console.log();\n out.info(\"Node server generated at .elur/node-server.mjs\");\n }\n}\n\nfunction assertCapabilities(\n adapter: { capabilities?: import(\"./runtime/capabilities.js\").AdapterCapabilities },\n features: { isr: boolean; images: boolean; streaming?: boolean },\n adapterName: string,\n): void {\n if (!adapter.capabilities) return;\n const diagnostics = validateCapabilities(adapter.capabilities, features);\n if (!diagnostics.ok) {\n throw new Error(\n `[elur-kit] Adapter \"${adapterName}\" cannot satisfy the requested features:\\n - ${diagnostics.problems.join(\"\\n - \")}`,\n );\n }\n}\n\nasync function applyProjectConfig(options: CliOptions, argv: string[]): Promise<void> {\n // Map non-build commands to \"build\" or \"serve\" for config resolution.\n const command = (options.command === \"adapter\" || options.command === \"routes\" || options.command === \"doctor\")\n ? \"build\"\n : options.command;\n const config = await loadElurConfig({\n root: options.root,\n configFile: options.configFile,\n command,\n });\n const args = argv.slice(2);\n const has = (...names: string[]) => names.some((name) => args.includes(name));\n options.root = config.root;\n if (!has(\"--app\", \"-a\")) options.appDir = config.appDir;\n if (!has(\"--islands\", \"-i\")) options.islandsDir = config.islandsDir;\n if (!has(\"--out\", \"-o\")) options.outDir = config.outDir;\n if (!has(\"--public\")) options.publicDir = config.publicDir;\n if (!has(\"--cache-dir\")) options.cacheDir = config.cache.dir;\n if (!has(\"--default-revalidate\")) options.defaultRevalidate = config.cache.defaultRevalidate;\n // --verbose/--quiet override logger.level from the config file.\n if (options.logLevel) config.logger.level = options.logLevel;\n options.generatedEntry = resolve(config.root, \".elur/entry-client.ts\");\n options.resolvedConfig = config;\n}\n\nexport async function run(argv: string[]): Promise<void> {\n const options = parseArgs(argv);\n if (options.logLevel === \"error\") out.setQuiet(true);\n\n // Commands that don't need project config resolution.\n if (options.command === \"doctor\") {\n const { doDoctor } = await import(\"./cli/commands.js\");\n const code = await doDoctor(options);\n process.exit(code);\n }\n\n await applyProjectConfig(options, argv);\n\n if (options.command === \"build\") {\n await doBuild(options);\n } else if (options.command === \"preview\") {\n await doPreview(options);\n } else if (options.command === \"start\") {\n await doStart(options);\n } else if (options.command === \"adapter\") {\n await doAdapter(options);\n } else if (options.command === \"check\") {\n const { doCheck } = await import(\"./cli/commands.js\");\n const code = await doCheck(options);\n process.exit(code);\n } else if (options.command === \"routes\") {\n const { doRoutes } = await import(\"./cli/commands.js\");\n const code = await doRoutes(options);\n process.exit(code);\n } else if (process.env[DEV_WORKER_ENV] === \"1\") {\n await doDev(options);\n } else {\n await doDevSupervisor(options);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.cjs","names":[],"sources":["../../src/router/route-scanner.ts","../../src/island/scan.ts","../../src/island/generate-entry.ts","../../src/render/ssr-flag.ts","../../src/render/render-to-string.ts","../../src/build/document-shell.ts","../../src/island/island.ts","../../src/action/error-store.ts","../../src/cache/policy.ts","../../src/ssr/render.ts","../../src/action/scan.ts","../../src/image/service.ts","../../src/integrations/index.ts","../../src/seo/index.ts","../../src/seo/sitemap-from-routes.ts","../../src/build/build.ts","../../src/vite/interpolation-plugin.ts","../../src/build/transform-source.ts","../../src/runtime/node-http.ts","../../src/runtime/logger.ts","../../src/config/index.ts","../../src/manifest/index.ts","../../src/runtime/capabilities.ts","../../src/cli/output.ts","../../src/cli/ports.ts","../../src/build/vite-build.ts","../../src/ssr/match.ts","../../src/middleware/index.ts","../../src/errors.ts","../../src/action/origin.ts","../../src/cache/adapter.ts","../../src/cache/invalidation.ts","../../src/action/server.ts","../../src/ssr/stream.ts","../../src/runtime/static.ts","../../src/runtime/context.ts","../../src/runtime/security-headers.ts","../../src/router/redirects.ts","../../src/middleware/stream-boundary.ts","../../src/ssr/stream-response.ts","../../src/runtime/handler.ts","../../src/adapters/shared.ts","../../src/adapters/vercel.ts","../../src/adapters/netlify.ts","../../src/adapters/bun.ts","../../src/adapters/node.ts","../../src/cli/commands.ts","../../src/cli.ts"],"sourcesContent":["import { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\n// --- Route scanner ---\n//\n// Walks src/app/ and maps file conventions to URL paths.\n//\n// Supported conventions:\n// - page.ts -> URL path\n// - page.data.ts -> loader for that page\n// - layout.ts -> layout wrapping pages in the same segment\n// - route.ts -> API endpoint (collected separately)\n//\n// Dynamic segments:\n// - [slug] -> :slug\n// - [...slug] -> catch-all (rendered as :slug*)\n// - [[...slug]] -> optional catch-all (rendered as :slug* but matches\n// the base path too)\n//\n// Route conflicts (two routes with the same path pattern) cause an error\n// during scanRoutes (plan §11.1).\n\n/** A page route discovered by the scanner. */\nexport interface PageRoute {\n /** URL path, e.g. \"/blog/:slug\". */\n path: string;\n /** File system path to the page.ts module. */\n pagePath: string;\n /** File system path to the page.data.ts module, if any. */\n dataPath?: string;\n /** File system path to the page.action.ts module, if any. */\n actionPath?: string;\n /** Ordered list of layout.ts modules from root to leaf. */\n layouts: string[];\n /** File system path to the loading.ts module, if any. */\n loadingPath?: string;\n /** Dynamic parameter names extracted from the path. */\n params: string[];\n /** Whether the route has an optional catch-all segment. */\n optionalCatchAll?: boolean;\n /**\n * Named slot modules discovered in the same directory as the page.\n * Keyed by slot name (filename without `.slot.ts` suffix).\n * (v2.1 — Fix #2: Layout Slots)\n */\n slots?: Record<string, string>;\n}\n\n/** An API route discovered by the scanner. */\nexport interface ApiRoute {\n /** URL path, e.g. \"/api/posts\". */\n path: string;\n /** File system path to the route.ts module. */\n routePath: string;\n /** Dynamic parameter names extracted from the path. */\n params: string[];\n}\n\n/** Result of scanning the app directory. */\nexport interface ScannedRoutes {\n pages: PageRoute[];\n api: ApiRoute[];\n /** Optional 404 error page. */\n error404?: PageRoute;\n /** Optional 500 error page. */\n error500?: PageRoute;\n}\n\nfunction isRouteGroup(segment: string): boolean {\n return segment.startsWith(\"(\") && segment.endsWith(\")\");\n}\n\nfunction segmentToUrl(segment: string): string {\n // Optional catch-all: [[...slug]] -> :slug* (matches base path too)\n if (segment.startsWith(\"[[...\") && segment.endsWith(\"]]\")) {\n return `:${segment.slice(5, -2)}*`;\n }\n // Catch-all: [...slug] -> :slug*\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\n return `:${segment.slice(4, -1)}*`;\n }\n // Dynamic: [slug] -> :slug\n if (segment.startsWith(\"[\") && segment.endsWith(\"]\")) {\n return `:${segment.slice(1, -1)}`;\n }\n return segment;\n}\n\nfunction extractParams(segment: string): string[] {\n if (segment.startsWith(\"[[...\") && segment.endsWith(\"]]\")) {\n return [segment.slice(5, -2)];\n }\n if (segment.startsWith(\"[...\") && segment.endsWith(\"]\")) {\n return [segment.slice(4, -1)];\n }\n if (segment.startsWith(\"[\") && segment.endsWith(\"]\")) {\n return [segment.slice(1, -1)];\n }\n return [];\n}\n\nfunction isOptionalCatchAll(segment: string): boolean {\n return segment.startsWith(\"[[...\") && segment.endsWith(\"]]\");\n}\n\nasync function collectFiles(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries\n .filter((e) => e.isFile() && e.name.endsWith(\".ts\"))\n .map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nasync function collectDirs(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nasync function scanRecursive(\n appDir: string,\n currentDir: string,\n urlSegments: string[],\n params: string[],\n layouts: string[],\n result: ScannedRoutes,\n hasOptionalCatchAll = false,\n): Promise<void> {\n const files = await collectFiles(currentDir);\n const dirs = await collectDirs(currentDir);\n\n const pagePath = files.includes(\"page.ts\")\n ? join(currentDir, \"page.ts\")\n : undefined;\n const dataPath = files.includes(\"page.data.ts\")\n ? join(currentDir, \"page.data.ts\")\n : undefined;\n const actionPath = files.includes(\"page.action.ts\")\n ? join(currentDir, \"page.action.ts\")\n : undefined;\n const loadingPath = files.includes(\"loading.ts\")\n ? join(currentDir, \"loading.ts\")\n : undefined;\n const layoutPath = files.includes(\"layout.ts\")\n ? join(currentDir, \"layout.ts\")\n : undefined;\n const routePath = files.includes(\"route.ts\")\n ? join(currentDir, \"route.ts\")\n : undefined;\n\n const currentLayouts = layoutPath\n ? [...layouts, layoutPath]\n : [...layouts];\n\n if (routePath) {\n result.api.push({\n path: urlSegments.length === 0 ? \"/\" : \"/\" + urlSegments.join(\"/\"),\n routePath,\n params: [...params],\n });\n }\n\n if (pagePath) {\n const path = urlSegments.length === 0 ? \"/\" : \"/\" + urlSegments.join(\"/\");\n // Detect named slot files: *.slot.ts (v2.1 — Fix #2: Layout Slots)\n const slots: Record<string, string> = {};\n for (const file of files) {\n const slotMatch = file.match(/^(.+)\\.slot\\.ts$/);\n if (slotMatch) {\n slots[slotMatch[1]] = join(currentDir, file);\n }\n }\n result.pages.push({\n path,\n pagePath,\n dataPath,\n actionPath,\n layouts: currentLayouts,\n loadingPath,\n params: [...params],\n optionalCatchAll: hasOptionalCatchAll,\n slots: Object.keys(slots).length > 0 ? slots : undefined,\n });\n }\n\n for (const dir of dirs) {\n if (isRouteGroup(dir)) {\n // Route groups do not add a URL segment, but they can add a layout.\n const groupDir = join(currentDir, dir);\n const groupFiles = await collectFiles(groupDir);\n const groupLayout = groupFiles.includes(\"layout.ts\")\n ? join(groupDir, \"layout.ts\")\n : undefined;\n await scanRecursive(\n appDir,\n groupDir,\n urlSegments,\n params,\n groupLayout ? [...currentLayouts, groupLayout] : currentLayouts,\n result,\n );\n continue;\n }\n\n const optional = isOptionalCatchAll(dir);\n await scanRecursive(\n appDir,\n join(currentDir, dir),\n [...urlSegments, segmentToUrl(dir)],\n [...params, ...extractParams(dir)],\n currentLayouts,\n result,\n optional,\n );\n }\n}\n\n/**\n * Scans an app directory for Elur Kit file-based routes.\n *\n * @param appDir Absolute path to the app directory (e.g. \"src/app\").\n * @returns Discovered page and API routes.\n */\nexport async function scanRoutes(appDir: string): Promise<ScannedRoutes> {\n const result: ScannedRoutes = { pages: [], api: [] };\n const rootFiles = await collectFiles(appDir);\n const rootLayout = rootFiles.includes(\"layout.ts\")\n ? join(appDir, \"layout.ts\")\n : undefined;\n\n if (rootFiles.includes(\"404.page.ts\")) {\n result.error404 = {\n path: \"/404\",\n pagePath: join(appDir, \"404.page.ts\"),\n dataPath: rootFiles.includes(\"404.page.data.ts\")\n ? join(appDir, \"404.page.data.ts\")\n : undefined,\n layouts: rootLayout ? [rootLayout] : [],\n params: [],\n };\n }\n\n if (rootFiles.includes(\"500.page.ts\")) {\n result.error500 = {\n path: \"/500\",\n pagePath: join(appDir, \"500.page.ts\"),\n dataPath: rootFiles.includes(\"500.page.data.ts\")\n ? join(appDir, \"500.page.data.ts\")\n : undefined,\n layouts: rootLayout ? [rootLayout] : [],\n params: [],\n };\n }\n\n await scanRecursive(appDir, appDir, [], [], [], result);\n\n // Detect route conflicts (plan §11.1): two routes with the same path\n // pattern is an error during manifest generation.\n detectRouteConflicts(result);\n\n return result;\n}\n\n/**\n * Detects and throws on route conflicts (plan §11.1, runtime-security §10).\n * Two routes with the same path pattern cause an error.\n */\nfunction detectRouteConflicts(routes: ScannedRoutes): void {\n const pagePaths = new Map<string, string>();\n for (const page of routes.pages) {\n const existing = pagePaths.get(page.path);\n if (existing) {\n throw new Error(\n `[elur-kit] Route conflict: \"${page.path}\" is defined by both ` +\n `\"${existing}\" and \"${page.pagePath}\". ` +\n `Remove one of the conflicting page.ts files.`,\n );\n }\n pagePaths.set(page.path, page.pagePath);\n }\n\n // Also check API route conflicts.\n const apiPaths = new Map<string, string>();\n for (const api of routes.api) {\n const existing = apiPaths.get(api.path);\n if (existing) {\n throw new Error(\n `[elur-kit] API route conflict: \"${api.path}\" is defined by both ` +\n `\"${existing}\" and \"${api.routePath}\".`,\n );\n }\n apiPaths.set(api.path, api.routePath);\n }\n}\n","import { readdir } from \"node:fs/promises\";\nimport type { Dirent } from \"node:fs\";\nimport { join, relative, sep } from \"node:path\";\n\n// --- Island scanner ---\n//\n// Walks `src/islands/` and lists every island component module. Each `.ts`\n// file (recursively) is treated as one island whose name is derived from its\n// path relative to the islands root:\n//\n// src/islands/LikeButton.ts -> \"LikeButton\"\n// src/islands/nav/MobileMenu.ts -> \"nav/MobileMenu\"\n//\n// The name must match the first argument passed to `island(name, ...)` on the\n// server so the client registry can look the component up during hydration.\n\n/** A single island component discovered by the scanner. */\nexport interface IslandModule {\n /** Registry name, derived from the path relative to the islands dir. */\n name: string;\n /** Absolute file system path to the island module. */\n filePath: string;\n}\n\nasync function walk(dir: string): Promise<string[]> {\n let entries: Dirent<string>[];\n try {\n entries = (await readdir(dir, {\n withFileTypes: true,\n encoding: \"utf8\",\n })) as Dirent<string>[];\n } catch {\n return [];\n }\n\n const files: string[] = [];\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await walk(full)));\n } else if (\n entry.isFile() &&\n entry.name.endsWith(\".ts\") &&\n !entry.name.endsWith(\".d.ts\") &&\n !entry.name.endsWith(\".test.ts\")\n ) {\n files.push(full);\n }\n }\n return files;\n}\n\nfunction toIslandName(islandsDir: string, filePath: string): string {\n return relative(islandsDir, filePath)\n .replace(/\\.ts$/, \"\")\n .split(sep)\n .join(\"/\");\n}\n\n/**\n * Scans an islands directory for island component modules.\n *\n * @param islandsDir Absolute path to the islands directory (e.g. \"src/islands\").\n * @returns Discovered island modules, sorted by name.\n */\nexport async function scanIslands(islandsDir: string): Promise<IslandModule[]> {\n const files = await walk(islandsDir);\n return files\n .map((filePath) => ({ name: toIslandName(islandsDir, filePath), filePath }))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative, sep } from \"node:path\";\nimport type { IslandModule } from \"./scan.js\";\n\n// --- Client entry generator ---\n//\n// Turns a list of scanned islands into a client entry module that imports each\n// island and registers it with `hydrateIslands`. This removes the need to hand-\n// maintain `entry-client.ts` as islands are added or removed.\n//\n// The generated file imports island default exports and passes them to\n// `hydrateIslands` keyed by their registry name.\n\n/**\n * Router options for the generated client entry (Fase 8.3).\n */\nexport interface RouterEntryOptions {\n /**\n * Include SPA navigation code. When `false` the generated entry is\n * hydrate-only and no router file is emitted. Default: `true`.\n */\n enabled?: boolean;\n /** Forwarded to `startClientRouter({ prefetch })`. Default: `true`. */\n prefetch?: boolean;\n /** Forwarded to `startClientRouter({ morph })` (idiomorph swap). */\n morph?: boolean;\n /** Forwarded to `startClientRouter({ loadingIndicator })`. */\n loadingIndicator?: boolean;\n /**\n * Split mode: the entry hydrates islands only and the router lives in a\n * separate generated module (`router.ts` next to the entry, emitted as its\n * own chunk). This is what lets pages without islands load only the router.\n */\n separate?: boolean;\n /** Absolute path of the generated router module when `separate` is set. */\n outFile?: string;\n}\n\n/** Options for generating the client entry module. */\nexport interface GenerateEntryOptions {\n /** Islands to register, from `scanIslands`. */\n islands: IslandModule[];\n /** Absolute path of the entry file to write (e.g. \".elur/entry-client.ts\"). */\n outFile: string;\n /**\n * Import specifier for the kit's client island helpers.\n * Defaults to the published subpath `@elurjs/kit/island`.\n */\n hydrateImport?: string;\n /**\n * Import specifier for the kit's client router.\n * Defaults to the published subpath `@elurjs/kit/router`.\n */\n routerImport?: string;\n /**\n * Router inclusion. Omit for the legacy combined entry (router embedded).\n * With `separate: true`, a standalone router module is also generated at\n * `router.outFile`.\n */\n router?: RouterEntryOptions;\n}\n\n/** Turns a registry name into a safe JS identifier for the import binding. */\nfunction toIdentifier(name: string, index: number): string {\n const cleaned = name.replace(/[^a-zA-Z0-9_$]/g, \"_\");\n return /^[a-zA-Z_$]/.test(cleaned) ? `${cleaned}_${index}` : `_${cleaned}_${index}`;\n}\n\n/**\n * Source for the standalone router module emitted in split builds. Router\n * options are baked in so the public module takes no arguments.\n */\nexport function buildRouterEntrySource(\n routerImport = \"@elurjs/kit/router\",\n options: Omit<RouterEntryOptions, \"enabled\" | \"separate\" | \"outFile\"> = {},\n): string {\n const opts: Record<string, boolean> = {};\n if (options.prefetch === false) opts.prefetch = false;\n if (options.morph === true) opts.morph = true;\n if (options.loadingIndicator === true) opts.loadingIndicator = true;\n const args = Object.keys(opts).length > 0 ? JSON.stringify(opts) : \"\";\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { startClientRouter } from ${JSON.stringify(routerImport)};\n\nstartClientRouter(${args});\n`;\n}\n\n/**\n * Serializes the startClientRouter options embedded in a combined entry.\n * Only non-default flags are emitted to keep the generated code minimal.\n */\nfunction routerCallArgs(router?: RouterEntryOptions): string {\n const opts: Record<string, boolean> = {};\n if (router?.prefetch === false) opts.prefetch = false;\n if (router?.morph === true) opts.morph = true;\n if (router?.loadingIndicator === true) opts.loadingIndicator = true;\n return Object.keys(opts).length > 0 ? JSON.stringify(opts) : \"\";\n}\n\n/** Builds the source code of the client entry module. */\nexport function buildEntrySource(\n islands: IslandModule[],\n outFile: string,\n hydrateImport = \"@elurjs/kit/island\",\n routerImport = \"@elurjs/kit/router\",\n router?: RouterEntryOptions,\n): string {\n const bindings = islands.map((island, i) => ({\n ident: toIdentifier(island.name, i),\n name: island.name,\n // Relative import specifier from the entry file to the island module.\n spec: toImportSpecifier(outFile, island.filePath),\n }));\n\n // Lazy registry: each island is loaded on-demand via dynamic import().\n // This enables code-splitting — islands not on the current page (or not yet\n // triggered by their directive) stay out of the initial bundle.\n //\n // The registry maps island name → discriminated lazy loader `{ load }`.\n // hydrateIslands() awaits `entry.load()` before hydrating, so the first\n // paint only needs the small entry chunk + the islands on the page. The\n // discriminated form lets the hydrator tell eager components from lazy\n // loaders without executing a probe.\n const registryLines = bindings\n .map((b) => ` ${JSON.stringify(b.name)}: { load: () => import(${JSON.stringify(b.spec)}).then(m => m.default) },`)\n .join(\"\\n\");\n\n const islandHydration = registryLines\n ? `const registry = {\n${registryLines}\n};\nconst hydrate = () => hydrateIslands(registry);\n// Islands inside persisted nodes must not be disposed across navigations.\n// The router announces the survivors in the elur:before-render detail; the\n// DOM query fallback covers hosts that dispatch it without detail.\nconst cleanup = (persisted) =>\n cleanupHydratedIslands({\n except: persisted ?? document.querySelectorAll(\"[data-elur-persist]\"),\n });\nlet sawBeforeRender = false;\n\n// Hydrate right after parse: module scripts are deferred, so this already\n// runs once the DOM is ready. Directives schedule themselves inside\n// hydrateIslands — \"load\"/\"only\" run immediately (real Astro semantics),\n// \"idle\"/\"visible\" keep their deferred scheduling.\nhydrate();\n\n// The router dispatches elur:before-render BEFORE swapping #app: islands are\n// disposed while still attached (Fase A2), except persisted subtrees.\ndocument.addEventListener(\"elur:before-render\", (event) => {\n sawBeforeRender = true;\n cleanup(event.detail?.persisted);\n});\n\n// Re-hydrate after SPA navigations.\ndocument.addEventListener(\"elur:rendered\", () => {\n // Compat fallback: hosts that only dispatch elur:rendered (streaming swap\n // script, hand-rolled integrations) still need the cleanup pass.\n if (!sawBeforeRender) cleanup();\n sawBeforeRender = false;\n hydrate();\n});\n\n// Vite HMR: when an island module (or the entry itself) updates, dispose the\n// current islands and re-hydrate from the updated modules — the registry's\n// dynamic import() resolves to the fresh modules, so no full page reload is\n// needed (progressive enhancement, audit §10.2 / §12.2).\nif (import.meta.hot) {\n import.meta.hot.accept(() => {\n cleanupHydratedIslands();\n hydrateIslands(registry);\n });\n}`\n : \"\";\n\n // The router is embedded in the entry unless a separate chunk was\n // requested (split builds) or the router is disabled outright.\n const embedRouter = router ? router.enabled !== false && !router.separate : true;\n\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\n${embedRouter ? `import { startClientRouter } from ${JSON.stringify(routerImport)};\\n` : \"\"}import { hydrateIslands, cleanupHydratedIslands } from ${JSON.stringify(hydrateImport)};\n${embedRouter ? `\\nstartClientRouter(${routerCallArgs(router)});\\n` : \"\"}${islandHydration}\n`;\n}\n\n/** Computes a POSIX-style relative import specifier between two files. */\nfunction toImportSpecifier(fromFile: string, toFile: string): string {\n let spec = relative(dirname(fromFile), toFile).split(sep).join(\"/\");\n if (!spec.startsWith(\".\")) spec = `./${spec}`;\n return spec;\n}\n\n/**\n * Generates and writes the client entry module for the given islands. When\n * `options.router.separate` is set (and the router is enabled), a standalone\n * router module is written alongside it (default: `router.ts` next to the\n * entry — bundle it as a second input to emit `/_elur/router.js`).\n *\n * @param options Generation options.\n * @returns The absolute path of the written entry file.\n */\nexport async function generateClientEntry(\n options: GenerateEntryOptions,\n): Promise<string> {\n const source = buildEntrySource(\n options.islands,\n options.outFile,\n options.hydrateImport,\n options.routerImport,\n options.router,\n );\n await mkdir(dirname(options.outFile), { recursive: true });\n await writeFile(options.outFile, source, \"utf8\");\n\n // Always emit the router module whenever router options were provided —\n // even in combined mode or with the router disabled — so a two-input user\n // config (`.elur/router.ts` as second input) never breaks on a missing\n // file. In combined mode the file is simply never emitted as a page script.\n if (options.router) {\n const routerFile =\n options.router.outFile ?? join(dirname(options.outFile), \"router.ts\");\n const routerSource =\n options.router.enabled === false\n ? `// AUTO-GENERATED by @elurjs/kit. Do not edit.\\n// router.enabled: false — intentionally empty.\\nexport {};\\n`\n : buildRouterEntrySource(options.routerImport ?? \"@elurjs/kit/router\", options.router);\n await writeFile(routerFile, routerSource, \"utf8\");\n }\n return options.outFile;\n}\n","// --- SSR flag utility ---\n//\n// `@elurjs/core` does not export `_setSSR`/`_isSSR`. The reactivity state lives\n// on `globalThis[Symbol.for(\"@elurjs/core/reactivity-state\")]` and the kit owns\n// the `ssr` boolean on it: `renderToString` sets it to `true` while server\n// rendering so `isSSR()` reflects the current render mode for user code\n// (environment reads, client-only guards, ...).\n//\n// This module manipulates that flag directly so the kit does not depend on\n// private exports that may or may not be present in a given elur release.\n\nconst STATE_KEY = Symbol.for(\"@elurjs/core/reactivity-state\");\n\ntype ReactivityState = { ssr?: boolean };\n\nfunction getState(): ReactivityState | undefined {\n return (globalThis as Record<symbol, unknown>)[STATE_KEY] as\n | ReactivityState\n | undefined;\n}\n\n/** Sets the SSR flag on the Elur reactivity state. No-op if state is absent. */\nexport function setSSR(value: boolean): void {\n const state = getState();\n if (state) state.ssr = value;\n}\n\n/** Reads the SSR flag from the Elur reactivity state. Defaults to false. */\nexport function isSSR(): boolean {\n return getState()?.ssr ?? false;\n}\n","import type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString as renderCoreTemplate } from \"@elurjs/core/server\";\nimport { setSSR } from \"./ssr-flag\";\n\n// --- Build-time / server rendering ---\n//\n// The Elur core ships a DOM-free `renderToString` (`@elurjs/core/server`)\n// that streams template output without ever touching a `document`. The kit used\n// to inject a Node-side DOM (happy-dom) as a fallback for legacy compatibility;\n// that fallback has been removed together with the happy-dom dependency.\n\n/**\n * Renders a Elur template to an HTML string in Node.\n *\n * Accepts a *factory* (not a template) because `html`` evaluates at call time.\n *\n * @param factory Thunk that builds the template, e.g. `() => Page({ data })`.\n * @returns Serialized HTML of the rendered template.\n */\nexport async function renderToString(\n factory: () => ElurTemplate,\n options: { markers?: \"none\" | \"hydration\" } = {},\n): Promise<string> {\n setSSR(true);\n try {\n return await renderCoreTemplate(factory(), {\n markers: options.markers ?? \"hydration\",\n });\n } finally {\n setSSR(false);\n }\n}\n","//\n// The <!DOCTYPE>, <head> and <body> wrapper — plus the serialized loader data\n// and the client entry — are injected here at build time.\n\nimport type { PageMetadata } from \"../types.js\";\nexport type SpeculationMode = \"prefetch\" | \"prerender\";\n\nexport interface ShellOptions {\n /** Rendered inner HTML that goes inside `#app`. */\n body: string;\n /** `<title>` text. */\n title?: string;\n /** `<html lang>` attribute. */\n lang?: string;\n /** Additional attributes for the `<html>` element, e.g. `{ \"data-theme\": \"dark\" }`. */\n htmlAttributes?: Record<string, string>;\n /**\n * Inline scripts injected into `<head>`. They run synchronously while the\n * document parses — before the first paint and before the (deferred) client\n * bundle — so they are the right place for no-flash bootstrapping (e.g.\n * applying a stored theme before the page becomes visible).\n */\n headScripts?: string[];\n /**\n * Raw HTML strings injected into `<head>` — e.g. `<link rel=\"icon\">`,\n * `<link rel=\"manifest\">`, `<meta name=\"theme-color\">`. Each string is\n * rendered as-is inside `<head>`.\n */\n headLinks?: string[];\n /** Loader data serialized into `<script id=\"elur-data\">`. */\n data?: unknown;\n /** Per-page action names serialized into `<script id=\"elur-actions\">`. */\n actions?: Record<string, string[]>;\n /**\n * Path to the client entry module, e.g. `/_elur/entry-client.js`. In split\n * builds this is the hydrate-only entry; callers gate it per page so it is\n * only emitted when the rendered body actually contains islands.\n */\n clientEntry?: string;\n /**\n * Path to the standalone client router module, e.g. `/_elur/router.js`\n * (split builds only). Emitted as a second `<script type=\"module\">` so pages\n * without islands still get SPA navigation without paying for the islands\n * entry.\n */\n routerEntry?: string;\n /**\n * Whether the client router is enabled for this page. When `false`, the\n * `elur:render-endpoint` meta is omitted entirely: no client router will run,\n * so there is nothing to advertise endpoint availability to.\n */\n routerEnabled?: boolean;\n /**\n * Speculation Rules API mode emitted as\n * `<script type=\"speculationrules\">` with document rules and\n * `eagerness: \"moderate\"`. Chromium-only progressive enhancement — other\n * browsers ignore the unknown script type. Only set this for static builds;\n * never apply to URLs reachable via server actions.\n */\n speculation?: SpeculationMode;\n /** Page metadata emitted as `<meta>`, `<link>` and OG/Twitter tags in `<head>`. */\n metadata?: PageMetadata;\n /**\n * Whether the SSR render endpoint (`/__elur-js/render`) is available at\n * runtime. Defaults to `true`. When `false` (static deployments), the shell\n * emits `<meta name=\"elur:render-endpoint\" content=\"off\" />` so the client\n * router skips probing the endpoint entirely — preventing a storm of 404\n * requests on fully static sites.\n */\n renderEndpoint?: boolean;\n}\n\nconst HTML_ESCAPES: Record<string, string> = {\n \"&\": \"&\",\n \"<\": \"<\",\n \">\": \">\",\n '\"': \""\",\n \"'\": \"'\",\n};\n\n/**\n * Explicit delimiters around the `#app` content. The streaming pipeline\n * (`createStreamingResponse`) and adapter render endpoints extract the page\n * body with these markers instead of parsing the shell layout by hand, so\n * changes to the shell markup never break extraction. They are HTML comments:\n * invisible, and ignored by hydration and the SPA router.\n */\nexport const APP_START_MARKER = \"<!--elur:app:start-->\";\nexport const APP_END_MARKER = \"<!--elur:app:end-->\";\n\n/**\n * Extracts the inner HTML of `#app` from a full document produced by\n * `documentShell`. Returns `undefined` when the markers are missing (e.g. a\n * hand-written document).\n */\nexport function extractAppBody(html: string): string | undefined {\n const start = html.indexOf(APP_START_MARKER);\n if (start < 0) return undefined;\n const end = html.indexOf(APP_END_MARKER, start + APP_START_MARKER.length);\n if (end < 0) return undefined;\n return html.slice(start + APP_START_MARKER.length, end);\n}\n\nfunction escapeHtml(value: string): string {\n return value.replace(/[&<>\"']/g, (c) => HTML_ESCAPES[c]);\n}\n\n/**\n * Serializes data for embedding inside a `<script>` tag. Escapes `<` so a\n * `</script>` sequence in the data cannot break out of the tag.\n */\nexport function serializeData(data: unknown): string {\n return JSON.stringify(data ?? null).replace(/</g, \"\\\\u003c\");\n}\n\n/**\n * Builds the `<head>` tags for a `PageMetadata` object. Every tag is marked with\n * `data-elur-head` so the client-side router can replace them on navigation\n * without touching charset/viewport or user-supplied `headScripts`.\n */\nexport function buildHeadTags(metadata: PageMetadata, fallbackTitle: string): string {\n const tags: string[] = [];\n const title = metadata.title ?? fallbackTitle;\n if (metadata.title) {\n tags.push(`<title data-elur-head>${escapeHtml(title)}</title>`);\n }\n\n if (metadata.description) {\n tags.push(`<meta data-elur-head name=\"description\" content=\"${escapeHtml(metadata.description)}\" />`);\n }\n\n if (metadata.canonical) {\n tags.push(`<link data-elur-head rel=\"canonical\" href=\"${escapeHtml(metadata.canonical)}\" />`);\n }\n\n if (metadata.robots) {\n tags.push(`<meta data-elur-head name=\"robots\" content=\"${escapeHtml(metadata.robots)}\" />`);\n }\n\n const og = metadata.openGraph;\n if (og) {\n if (og.type) tags.push(`<meta data-elur-head property=\"og:type\" content=\"${escapeHtml(og.type)}\" />`);\n tags.push(`<meta data-elur-head property=\"og:title\" content=\"${escapeHtml(og.title ?? title)}\" />`);\n if (og.description ?? metadata.description) {\n tags.push(`<meta data-elur-head property=\"og:description\" content=\"${escapeHtml(og.description ?? metadata.description!)}\" />`);\n }\n if (og.url ?? metadata.canonical) {\n tags.push(`<meta data-elur-head property=\"og:url\" content=\"${escapeHtml(og.url ?? metadata.canonical!)}\" />`);\n }\n if (og.image) tags.push(`<meta data-elur-head property=\"og:image\" content=\"${escapeHtml(og.image)}\" />`);\n if (og.image && og.imageAlt) tags.push(`<meta data-elur-head property=\"og:image:alt\" content=\"${escapeHtml(og.imageAlt)}\" />`);\n if (og.image && og.imageWidth) tags.push(`<meta data-elur-head property=\"og:image:width\" content=\"${String(og.imageWidth)}\" />`);\n if (og.image && og.imageHeight) tags.push(`<meta data-elur-head property=\"og:image:height\" content=\"${String(og.imageHeight)}\" />`);\n if (og.image && og.imageType) tags.push(`<meta data-elur-head property=\"og:image:type\" content=\"${escapeHtml(og.imageType)}\" />`);\n if (og.siteName) tags.push(`<meta data-elur-head property=\"og:site_name\" content=\"${escapeHtml(og.siteName)}\" />`);\n if (og.locale) tags.push(`<meta data-elur-head property=\"og:locale\" content=\"${escapeHtml(og.locale)}\" />`);\n }\n\n const tw = metadata.twitter;\n if (tw) {\n if (tw.card) tags.push(`<meta data-elur-head name=\"twitter:card\" content=\"${escapeHtml(tw.card)}\" />`);\n if (tw.title ?? title) tags.push(`<meta data-elur-head name=\"twitter:title\" content=\"${escapeHtml(tw.title ?? title)}\" />`);\n if (tw.description ?? metadata.description) {\n tags.push(`<meta data-elur-head name=\"twitter:description\" content=\"${escapeHtml(tw.description ?? metadata.description!)}\" />`);\n }\n if (tw.image) tags.push(`<meta data-elur-head name=\"twitter:image\" content=\"${escapeHtml(tw.image)}\" />`);\n if (tw.image && tw.imageAlt) tags.push(`<meta data-elur-head name=\"twitter:image:alt\" content=\"${escapeHtml(tw.imageAlt)}\" />`);\n }\n\n if (metadata.other) {\n for (const [name, content] of Object.entries(metadata.other)) {\n tags.push(`<meta data-elur-head name=\"${escapeHtml(name)}\" content=\"${escapeHtml(content)}\" />`);\n }\n }\n\n return tags.map((t) => `\\n ${t}`).join(\"\");\n}\n\n/**\n * Document-level Speculation Rules (Chromium-only, ignored elsewhere).\n *\n * `href_matches: \"/*\"` scopes the rule to same-origin path links; the\n * `selector_matches` exclusions keep downloads, new-tab links, router-opt-outs\n * and explicit `data-no-speculation` links out of speculation. Actions are\n * POST endpoints reached through forms/`callAction`, never through document\n * links, so they are not speculated. `eagerness: \"moderate\"` speculates on\n * hover — the same trigger as the client router's prefetch.\n */\nfunction speculationRulesScript(mode: SpeculationMode): string {\n const rules = {\n [mode]: [\n {\n source: \"document\",\n where: {\n and: [\n { href_matches: \"/*\" },\n {\n not: {\n selector_matches:\n \"a[download], a[target], a[data-no-router], a[data-no-speculation]\",\n },\n },\n ],\n },\n eagerness: \"moderate\",\n },\n ],\n };\n return `\\n <script type=\"speculationrules\">${JSON.stringify(rules)}</script>`;\n}\n\n/** Wraps rendered body HTML into a full HTML document. */\nexport function documentShell(opts: ShellOptions): string {\n const { body, title = \"Elur Kit App\", lang = \"es\", data, actions, clientEntry, routerEntry, htmlAttributes, headScripts, headLinks, metadata } = opts;\n\n const dataScript =\n data !== undefined\n ? `\\n <script type=\"application/json\" id=\"elur-data\">${serializeData(data)}</script>`\n : \"\";\n\n const actionsScript = actions && Object.keys(actions).length > 0\n ? `\\n <script type=\"application/json\" id=\"elur-actions\">${serializeData(actions)}</script>`\n : \"\";\n\n // Every emitted module script also gets a <link rel=\"modulepreload\"> so the\n // fetch starts during HTML parsing instead of waiting for the deferred\n // script discovery (Fase 8.5 — paso 1).\n const modulePreload = (src: string) =>\n `\\n <link rel=\"modulepreload\" href=\"${escapeHtml(src)}\" />`;\n\n const preloads =\n (clientEntry ? modulePreload(clientEntry) : \"\") +\n (routerEntry ? modulePreload(routerEntry) : \"\");\n\n const entryScript = clientEntry\n ? `\\n <script type=\"module\" src=\"${escapeHtml(clientEntry)}\"></script>`\n : \"\";\n\n const routerScript = routerEntry\n ? `\\n <script type=\"module\" src=\"${escapeHtml(routerEntry)}\"></script>`\n : \"\";\n\n const speculationScript = opts.speculation\n ? speculationRulesScript(opts.speculation)\n : \"\";\n\n const htmlAttrs = htmlAttributes\n ? Object.entries(htmlAttributes)\n .filter(([, value]) => value !== undefined && value !== null && value !== \"\")\n .map(([key, value]) => ` ${escapeHtml(key)}=\"${escapeHtml(String(value))}\"`)\n .join(\"\")\n : \"\";\n\n const headScriptsHtml = headScripts\n ? headScripts\n .filter((script) => typeof script === \"string\" && script.trim().length > 0)\n .map((script) => {\n // If the script is already a complete <script> tag (e.g. JSON-LD),\n // render it as-is without wrapping.\n if (script.trimStart().startsWith(\"<script\")) {\n return `\\n ${script}`;\n }\n return `\\n <script>${script.replace(/<\\/script>/gi, \"<\\\\/script>\")}</script>`;\n })\n .join(\"\")\n : \"\";\n\n const headTags = metadata ? buildHeadTags(metadata, title) : \"\";\n const titleTag = metadata?.title\n ? \"\" // already emitted by buildHeadTags\n : `\\n <title>${escapeHtml(title)}</title>`;\n\n const headLinksHtml = headLinks\n ? headLinks\n .filter((link) => typeof link === \"string\" && link.trim().length > 0)\n .map((link) => `\\n ${link}`)\n .join(\"\")\n : \"\";\n\n // The render-endpoint marker only exists for the client router; when the\n // router is disabled for the page there is nothing to advertise.\n const renderEndpointMeta =\n opts.renderEndpoint === false && opts.routerEnabled !== false\n ? '\\n <meta name=\"elur:render-endpoint\" content=\"off\" />'\n : \"\";\n\n return `<!DOCTYPE html>\n<html lang=\"${escapeHtml(lang)}\"${htmlAttrs}>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />${renderEndpointMeta}${titleTag}${headTags}${headLinksHtml}${headScriptsHtml}${preloads}${speculationScript}\n </head>\n <body>\n <div id=\"app\">${APP_START_MARKER}${body}${APP_END_MARKER}</div>${dataScript}${actionsScript}${entryScript}${routerScript}\n </body>\n</html>\n`;\n}\n","import { ELUR_RENDER_PROTOCOL, type ElurTemplate, type ServerRenderProtocolContext } from \"@elurjs/core\";\n\n// --- Islands helper ---\n//\n// Marks a component as an island. During server-side rendering it emits a\n// static placeholder with `data-elur-island` attributes. The client entry finds\n// these markers and hydrates them with the real component + reactive signals.\n//\n// SSR strategy\n// ------------\n// By default the component is executed on the server to produce a fallback HTML\n// fragment (better first paint, SEO, less layout shift). Components that access\n// browser-only globals (`document`, `window`, `navigator`, ...) in their body\n// cannot run on the server. Two opt-out mechanisms are provided, mirroring the\n// industry standard (Astro `client:only`, Next.js `dynamic(..., { ssr: false })`):\n//\n// 1. directive: \"only\" — shortcut for client-only with `load` scheduling.\n// 2. options: { ssr: false } — client-only with any directive (load/idle/visible).\n//\n// When SSR is skipped, only `options.fallback` (a ElurTemplate or string) is\n// rendered into the marker. The client hydrates from scratch.\n//\n// When SSR runs and the component throws, the error is NOT swallowed: it is\n// re-thrown wrapped with an actionable message naming the island and suggesting\n// `directive: \"only\"` / `{ ssr: false }` / `isSSR()`. This matches Astro and\n// Next.js, which never try/catch to \"auto-detect\" client-only components.\n\nexport type IslandDirective = \"load\" | \"idle\" | \"visible\" | \"only\";\n\n/**\n * HTML attribute that marks an island marker element. The renderer scans the\n * rendered body for this attribute to decide whether the page needs the\n * hydration entry at all (0% JS gating); the client hydrator queries the DOM\n * with `[data-elur-island]`.\n */\nexport const ISLAND_MARKER_ATTR = \"data-elur-island\";\n\n/**\n * HTML attribute that marks an element whose live DOM node is moved (not\n * re-rendered) across SPA navigations — the Astro `transition:persist` /\n * Turbo `data-turbo-permanent` pattern. The client router matches nodes by\n * the attribute value (`data-elur-persist=\"key\"`) between the old and new\n * page, preserving component state, media playback, scroll position, etc.\n */\nexport const PERSIST_ATTR = \"data-elur-persist\";\n\nexport interface IslandComponent<TProps = unknown> {\n (props: TProps): ElurTemplate | null | false | undefined;\n}\n\n/**\n * Options for {@link island}.\n *\n * - `ssr`: Whether to execute the component on the server. Defaults to `true`\n * unless `directive === \"only\"` (then `false`). When `false`, the component\n * is never called during SSR; only `fallback` is rendered.\n * - `fallback`: HTML to render inside the island marker when SSR is skipped or\n * the component returns null/false. Accepts a `ElurTemplate` (reactive, with\n * signals) or a plain string. Defaults to an empty string.\n */\nexport interface IslandOptions {\n ssr?: boolean;\n fallback?: ElurTemplate | string;\n}\n\n/**\n * Renders a component to a static HTML string with island markers.\n *\n * @param name Unique island name used by the client entry to look up the module.\n * @param component Island component. Executed on the server unless `directive`\n * is `\"only\"` or `options.ssr` is `false`.\n * @param props Props passed to the component and serialized for hydration.\n * @param directive When to hydrate on the client. Use `\"only\"` to skip SSR\n * entirely (client-only island).\n * @param options SSR strategy and fallback content.\n * @returns A ElurTemplate that renders the island placeholder.\n */\nexport function island<TProps>(\n name: string,\n component: IslandComponent<TProps>,\n props: TProps,\n directive: IslandDirective = \"load\",\n options?: IslandOptions,\n): ElurTemplate {\n // `directive: \"only\"` forces ssr off; explicit `options.ssr` wins otherwise.\n const ssr = directive === \"only\" ? false : (options?.ssr ?? true);\n const fallback = options?.fallback;\n\n const markerHtml = (innerHtml: string) =>\n `<div ${ISLAND_MARKER_ATTR}=\"${escapeHtml(name)}\" data-directive=\"${directive}\" data-props='${serializeProps(props)}'>${innerHtml}</div>`;\n\n return {\n __isElurTemplate: true as const,\n [ELUR_RENDER_PROTOCOL]: {\n async renderServer(context: ServerRenderProtocolContext) {\n let innerHtml = \"\";\n if (ssr) {\n try {\n const template = component(props);\n if (template !== null && template !== false && template !== undefined) {\n innerHtml = await context.render(template, { markers: true });\n } else {\n // Component returned null/false/undefined — render fallback if any.\n innerHtml = await renderFallback(fallback, context);\n }\n } catch (error) {\n throw wrapIslandSSRError(name, error);\n }\n } else {\n innerHtml = await renderFallback(fallback, context);\n }\n return markerHtml(innerHtml);\n },\n },\n _render(parent: Node, before: Node | null): () => void {\n const container = document.createElement(\"div\");\n let innerHtml = \"\";\n if (ssr) {\n const template = component(props);\n if (template !== null && template !== false && template !== undefined) {\n const dispose = template._render(container, null);\n innerHtml = container.innerHTML;\n dispose();\n } else {\n // null/false/undefined — render fallback if any.\n innerHtml = renderFallbackSync(fallback, container);\n }\n } else {\n innerHtml = renderFallbackSync(fallback, container);\n }\n const wrapper = document.createElement(\"template\");\n wrapper.innerHTML = markerHtml(innerHtml);\n const fragment = wrapper.content;\n const inserted = fragment.firstChild;\n parent.insertBefore(fragment, before);\n return () => {\n if (inserted?.parentNode) inserted.parentNode.removeChild(inserted);\n };\n },\n } as unknown as ElurTemplate;\n}\n\n/**\n * Wraps an SSR error from an island component with an actionable message.\n *\n * Following the Astro/Next.js convention, SSR errors are never silently\n * swallowed — they propagate so real bugs surface. The wrapper adds the island\n * name and three concrete remediation paths.\n */\nfunction wrapIslandSSRError(name: string, error: unknown): Error {\n const cause = error instanceof Error ? error : new Error(String(error));\n const msg = error instanceof Error ? error.message : String(error);\n return new Error(\n `[elur-kit] Island \"${name}\" threw during SSR: ${msg}\\n` +\n ` If the component accesses browser-only globals (document, window, etc.),\\n` +\n ` use directive: \"only\" or options: { ssr: false } to skip server rendering.\\n` +\n ` For environment reads (matchMedia, localStorage, navigator) you may guard\\n` +\n ` the access with isSSR() from \"@elurjs/kit\".`,\n { cause },\n );\n}\n\n/** Renders the fallback (ElurTemplate or string) to an HTML string on the server. */\nasync function renderFallback(\n fallback: ElurTemplate | string | undefined,\n context: ServerRenderProtocolContext,\n): Promise<string> {\n if (fallback == null || fallback === \"\") return \"\";\n if (typeof fallback === \"string\") return fallback;\n return context.render(fallback, { markers: false });\n}\n\n/** Renders the fallback into a container and returns its innerHTML (client path). */\nfunction renderFallbackSync(fallback: ElurTemplate | string | undefined, container: HTMLElement): string {\n if (fallback == null || fallback === \"\") return \"\";\n if (typeof fallback === \"string\") return fallback;\n const dispose = fallback._render(container, null);\n const html = container.innerHTML;\n dispose();\n return html;\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nfunction serializeProps(props: unknown): string {\n return JSON.stringify(props ?? null)\n .replace(/</g, \"\\\\u003c\")\n .replace(/'/g, \"\\\\u0027\");\n}\n","// --- Ephemeral action error store ---\n//\n// Action failures submitted via plain HTML forms (progressive enhancement)\n// need to be relayed back to the page so the user sees validation errors.\n//\n// Previously the failure data was serialized into a `?__elur_js_action_error=`\n// query param on the redirect. That leaks errors into browser history,\n// server logs and third-party Referer headers.\n//\n// Now we stash the failure in a short-lived in-memory store keyed by a random\n// id, set a small cookie `__elur_js_action_error=<id>` (Max-Age=15s, SameSite=Lax),\n// and the next render reads the cookie, fetches the payload, exposes it as\n// `props.form`, and clears the entry.\n//\n// The store is process-local, which is fine for the single-process SSR server\n// and the dev server. For multi-instance deployments the cookie carries the\n// payload directly when it fits (see `encodeActionErrorCookie`); the store is\n// only the overflow path for large payloads.\n\nimport { createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\n\nconst COOKIE_NAME = \"__elur_js_action_error\";\nconst MAX_COOKIE_SIZE = 3500; // bytes; leaves headroom under the 4KB cookie limit\nconst TTL_MS = 15_000;\n\n// HMAC key for signing action error cookies. In production this should be\n// set via ELUR_JS_ACTION_SECRET env var; otherwise we derive a per-process\n// key (sufficient for single-process dev/preview, but NOT for multi-instance).\nconst ACTION_SECRET =\n process.env.ELUR_JS_ACTION_SECRET ?? randomBytes(32).toString(\"hex\");\n\ninterface StoredError {\n data: unknown;\n status: number;\n expiresAt: number;\n}\n\nconst store = new Map<string, StoredError>();\n\n// Periodically purge expired entries so the map does not grow unbounded.\nlet sweepScheduled = false;\nfunction scheduleSweep(): void {\n if (sweepScheduled) return;\n sweepScheduled = true;\n setTimeout(() => {\n sweepScheduled = false;\n const now = Date.now();\n for (const [key, entry] of store) {\n if (entry.expiresAt <= now) store.delete(key);\n }\n }, TTL_MS).unref?.();\n}\n\n/**\n * Signs a payload with HMAC-SHA256 using the action secret.\n * Returns `signature.payload` (both hex/base64url).\n */\nfunction sign(payload: string): string {\n const sig = createHmac(\"sha256\", ACTION_SECRET).update(payload).digest(\"hex\");\n return `${sig}.${payload}`;\n}\n\n/**\n * Verifies a signed value and returns the payload if valid, or undefined.\n * Uses timingSafeEqual to prevent timing attacks.\n */\nfunction verify(value: string): string | undefined {\n const dotIndex = value.indexOf(\".\");\n if (dotIndex === -1) return undefined;\n const sig = value.slice(0, dotIndex);\n const payload = value.slice(dotIndex + 1);\n const expectedSig = createHmac(\"sha256\", ACTION_SECRET).update(payload).digest(\"hex\");\n if (sig.length !== expectedSig.length) return undefined;\n try {\n if (timingSafeEqual(Buffer.from(sig), Buffer.from(expectedSig))) {\n return payload;\n }\n } catch {\n // Length mismatch — invalid.\n }\n return undefined;\n}\n\n/**\n * Encodes an action failure for the redirect cookie. When the payload fits\n * inside the cookie limit, it is embedded directly as a signed base64url JSON\n * value. When it is too large, it is stored in memory and only a short signed\n * id is written to the cookie.\n *\n * The cookie is signed with HMAC-SHA256 to prevent forgery (A-20).\n *\n * @returns The cookie value to set on the redirect response.\n */\nexport function encodeActionErrorCookie(\n data: unknown,\n status: number,\n): { value: string; storeId?: string } {\n const payload = JSON.stringify({ d: data, s: status });\n const encoded = Buffer.from(payload, \"utf8\").toString(\"base64url\");\n const signed = sign(encoded);\n if (signed.length <= MAX_COOKIE_SIZE) {\n return { value: signed };\n }\n\n // Overflow: stash in memory and reference by signed id.\n const id = randomBytes(12).toString(\"hex\");\n store.set(id, { data, status, expiresAt: Date.now() + TTL_MS });\n scheduleSweep();\n return { value: sign(`id:${id}`), storeId: id };\n}\n\n/**\n * Decodes a cookie value (previously produced by `encodeActionErrorCookie`)\n * into the failure payload. Verifies the HMAC signature first, then resolves\n * in-memory overflow entries and deletes them after reading.\n */\nexport function decodeActionErrorCookie(value: string | undefined | null):\n | { data: unknown; status: number }\n | undefined {\n if (!value) return undefined;\n\n // Verify signature first.\n const verifiedPayload = verify(value);\n if (verifiedPayload === undefined) return undefined;\n\n // Check if it's an in-memory store reference.\n if (verifiedPayload.startsWith(\"id:\")) {\n const id = verifiedPayload.slice(3);\n const entry = store.get(id);\n if (!entry) return undefined;\n store.delete(id);\n if (entry.expiresAt <= Date.now()) return undefined;\n return { data: entry.data, status: entry.status };\n }\n\n try {\n const json = Buffer.from(verifiedPayload, \"base64url\").toString(\"utf8\");\n const parsed = JSON.parse(json) as { d: unknown; s: number };\n return { data: parsed.d, status: parsed.s };\n } catch {\n return undefined;\n }\n}\n\n/** Name of the cookie used to relay action errors. */\nexport const ACTION_ERROR_COOKIE = COOKIE_NAME;\n\n/** Builds the Set-Cookie header value that clears the error cookie. */\nexport function clearActionErrorCookieHeader(): string {\n return `${COOKIE_NAME}=; Path=/; Max-Age=0; SameSite=Lax`;\n}\n\n/** Builds the Set-Cookie header value that sets the error cookie. */\nexport function setActionErrorCookieHeader(value: string): string {\n return `${COOKIE_NAME}=${value}; Path=/; Max-Age=15; SameSite=Lax; HttpOnly`;\n}\n","// --- Cache policy per route (runtime-security §9.1) ---\n//\n// Authors can declare a cache policy in their page.data.ts:\n//\n// export const cache = {\n// mode: \"public\", // \"public\" | \"private\" | \"dynamic\"\n// revalidate: 60, // seconds\n// tags: [\"products\"], // for tag-based invalidation\n// };\n//\n// Default policy: \"dynamic\" (no public ISR caching).\n// Requests with Cookie/Authorization are never cached publicly.\n// Responses with Set-Cookie/private/no-store are never cached publicly.\n\n/** Cache mode for a route. */\nexport type CacheMode = \"public\" | \"private\" | \"dynamic\";\n\n/** Cache policy declared by the route's data module. */\nexport interface CachePolicy {\n mode: CacheMode;\n revalidate: number;\n tags?: string[];\n}\n\n/** Default cache policy when none is declared. */\nexport const DEFAULT_CACHE_POLICY: CachePolicy = {\n mode: \"dynamic\",\n revalidate: 0,\n};\n\n/**\n * Normalizes a raw cache export from a data module into a CachePolicy.\n * Returns the default policy if the input is invalid or missing.\n */\nexport function normalizeCachePolicy(raw: unknown): CachePolicy {\n if (!raw || typeof raw !== \"object\") return DEFAULT_CACHE_POLICY;\n const obj = raw as Record<string, unknown>;\n const mode = obj.mode;\n if (mode !== \"public\" && mode !== \"private\" && mode !== \"dynamic\") {\n return DEFAULT_CACHE_POLICY;\n }\n const revalidate = typeof obj.revalidate === \"number\" ? obj.revalidate : 0;\n const tags = Array.isArray(obj.tags) ? obj.tags.filter((t) => typeof t === \"string\") : undefined;\n return { mode, revalidate, tags };\n}\n\n/**\n * Determines whether a route's cache policy allows public caching for the\n * given request.\n *\n * Per §9.1:\n * - \"dynamic\" → never cache\n * - \"private\" → never cache publicly (requires private adapter)\n * - \"public\" → cache only if request has no Cookie/Authorization\n */\nexport function shouldCachePublic(\n policy: CachePolicy,\n request: Request,\n): boolean {\n if (policy.mode !== \"public\") return false;\n if (policy.revalidate <= 0) return false;\n if (request.headers.get(\"Cookie\")) return false;\n if (request.headers.get(\"Authorization\")) return false;\n return true;\n}\n","import type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString } from \"../render/render-to-string.js\";\nimport { documentShell, buildHeadTags } from \"../build/document-shell.js\";\nimport { ISLAND_MARKER_ATTR } from \"../island/island.js\";\nimport type { PageRoute, ScannedRoutes } from \"../router/route-scanner.js\";\nimport type { BuildConfig } from \"../build/build.js\";\nimport type { PageDataLoad, PageProps, RouteParams, PageMetadata, GenerateMetadata } from \"../types.js\";\nimport { existsSync } from \"node:fs\";\nimport { decodeActionErrorCookie, ACTION_ERROR_COOKIE } from \"../action/error-store.js\";\nimport { normalizeCachePolicy, type CachePolicy } from \"../cache/policy.js\";\n\nexport interface RenderPageOptions {\n route: PageRoute;\n params?: RouteParams;\n searchParams?: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\" | \"renderEndpoint\" | \"router\" | \"js\">;\n /** Custom module loader. Defaults to native dynamic import. */\n importer?: (path: string) => Promise<unknown>;\n /** Per-page action names exposed in the HTML shell. */\n actions?: Record<string, string[]>;\n /** Current request, used to hydrate data loaders that need cookies/headers. */\n request?: Request;\n}\n\nexport interface RenderPageResult {\n html: string;\n revalidate?: number;\n /**\n * `Set-Cookie` header value that clears the action error cookie, when the\n * page consumed a relayed action failure. The SSR server should append it to\n * the outgoing response so the cookie does not persist.\n */\n clearActionErrorCookie?: string;\n /** `<head>` tags (title, meta, OG, twitter) for the SPA router to merge. */\n head?: string;\n /** Resolved page title (from metadata or fallback). */\n resolvedTitle?: string;\n /**\n * Loader data as rendered into `<script id=\"elur-data\">`. Exposed so the\n * SPA render endpoint can ship it in the payload and the client router can\n * keep the serialized data fresh across navigations.\n */\n data?: unknown;\n /**\n * When a loader or layout throws a `Response` (e.g. `throw new Response(...,\n * { status: 404 })`), it is captured here as a first-class response instead\n * of being treated as an internal error (A-22).\n */\n response?: Response;\n /** HTTP status code for the rendered page (e.g. 404 for not-found pages). */\n status?: number;\n /** Cache policy declared by the route (§9.1). */\n cachePolicy?: CachePolicy;\n}\n\nconst defaultImport = (path: string) => import(path);\n\n/**\n * Collects `<html>` attributes and head scripts declared by data loaders\n * (page and layouts) via top-level `htmlAttributes` / `headScripts` fields.\n */\nexport function collectShellExtras(\n pageData: unknown,\n layoutDataList: unknown[],\n): { htmlAttributes: Record<string, string>; headScripts: string[]; headLinks: string[] } {\n const htmlAttributes: Record<string, string> = {};\n const headScripts: string[] = [];\n const headLinks: string[] = [];\n const merge = (value: unknown) => {\n if (!value || typeof value !== \"object\") return;\n const attrs = (value as { htmlAttributes?: Record<string, string> }).htmlAttributes;\n if (attrs) Object.assign(htmlAttributes, attrs);\n const scripts = (value as { headScripts?: string[] }).headScripts;\n if (Array.isArray(scripts)) headScripts.push(...scripts);\n const links = (value as { headLinks?: string[] }).headLinks;\n if (Array.isArray(links)) headLinks.push(...links);\n };\n for (const layoutData of layoutDataList) merge(layoutData);\n merge(pageData);\n // Deduplicate headScripts and headLinks (e.g. from both layout and page data)\n const uniqueScripts = [...new Set(headScripts)];\n const uniqueLinks = [...new Set(headLinks)];\n return { htmlAttributes, headScripts: uniqueScripts, headLinks: uniqueLinks };\n}\n\nexport async function renderPage(options: RenderPageOptions): Promise<RenderPageResult> {\n const { route, params = {}, searchParams = new URLSearchParams(), config, importer = defaultImport, actions, request } = options;\n\n const pageModule = await importer(route.pagePath) as {\n default: (props: PageProps<unknown>) => ElurTemplate;\n generateMetadata?: GenerateMetadata;\n };\n const { default: PageComponent, generateMetadata } = pageModule;\n\n let data: unknown;\n let revalidate: number | undefined;\n let cachePolicy: import(\"../cache/policy.js\").CachePolicy | undefined;\n // Use a mutable container so TypeScript doesn't narrow the type after\n // the first `if (thrownResponse)` check.\n const thrown: { response: Response | undefined } = { response: undefined };\n if (route.dataPath) {\n const mod = await importer(route.dataPath) as {\n load?: PageDataLoad;\n revalidate?: number;\n cache?: unknown;\n };\n if (mod.load) {\n try {\n data = await mod.load({ params, searchParams, request });\n } catch (err) {\n if (err instanceof Response) {\n thrown.response = err;\n } else {\n throw err;\n }\n }\n }\n if (typeof mod.revalidate === \"number\") {\n revalidate = mod.revalidate;\n }\n // Read cache policy from the data module (§9.1).\n if (mod.cache) {\n cachePolicy = normalizeCachePolicy(mod.cache);\n if (cachePolicy.revalidate > 0) {\n revalidate = cachePolicy.revalidate;\n }\n }\n }\n\n // If a loader threw a Response (redirect, 404, etc.), return it as a\n // first-class response instead of rendering the page (A-22).\n if (thrown.response) {\n return { html: \"\", response: thrown.response, status: thrown.response.status };\n }\n\n // Relay an action failure previously stored in the ephemeral cookie so the\n // page can render validation errors via `props.form`. The cookie is cleared\n // on the outgoing response (see `clearActionErrorCookie` in the result).\n let form: unknown;\n let clearActionErrorCookie: string | undefined;\n if (request) {\n const cookieHeader = request.headers.get(\"Cookie\") ?? \"\";\n const match = cookieHeader.match(new RegExp(`(?:^|;\\\\s*)${ACTION_ERROR_COOKIE}=([^;]+)`));\n if (match) {\n const decoded = decodeActionErrorCookie(match[1]);\n if (decoded) {\n form = { __elur_js_action_error: true, status: decoded.status, data: decoded.data };\n clearActionErrorCookie = `${ACTION_ERROR_COOKIE}=; Path=/; Max-Age=0; SameSite=Lax`;\n }\n }\n }\n\n const props: PageProps<unknown> = {\n data: data ?? {},\n params,\n searchParams,\n form,\n };\n\n const layoutModules = await Promise.all(\n route.layouts.map(async (layoutPath) => importer(layoutPath)),\n );\n const layoutDataList = await Promise.all(\n route.layouts.map(async (layoutPath) => {\n const dataPath = layoutPath.replace(/layout\\.ts$/, \"layout.data.ts\");\n if (!existsSync(dataPath)) return undefined;\n const mod = (await importer(dataPath)) as { load?: PageDataLoad };\n if (mod.load) {\n try {\n return await mod.load({ params, searchParams, request });\n } catch (err) {\n if (err instanceof Response) {\n thrown.response = err;\n return undefined;\n }\n throw err;\n }\n }\n return undefined;\n }),\n );\n\n // If a layout loader threw a Response, return it as first-class (A-22).\n const layoutThrown = thrown.response as Response | undefined;\n if (layoutThrown) {\n return { html: \"\", response: layoutThrown, status: layoutThrown.status };\n }\n\n // Load slot modules if the route has them (v2.1 — Fix #2: Layout Slots).\n let slotTemplates: Record<string, ElurTemplate> | undefined;\n if (route.slots) {\n slotTemplates = {};\n for (const [slotName, slotPath] of Object.entries(route.slots)) {\n const slotMod = await importer(slotPath) as { default: (props: PageProps<unknown>) => ElurTemplate };\n slotTemplates[slotName] = slotMod.default(props);\n }\n }\n\n const body = await renderToString(() => {\n let template = PageComponent(props);\n for (let i = layoutModules.length - 1; i >= 0; i--) {\n const { default: Layout } = layoutModules[i] as {\n default: (props: { children: ElurTemplate; data?: unknown; slots?: Record<string, ElurTemplate> }) => ElurTemplate;\n };\n template = Layout({ children: template, data: layoutDataList[i], slots: slotTemplates });\n }\n return template;\n });\n\n const title = typeof data === \"object\" && data && \"title\" in data\n ? String((data as { title?: unknown }).title ?? \"Elur Kit\")\n : \"Elur Kit\";\n\n const { htmlAttributes, headScripts, headLinks } = collectShellExtras(data, layoutDataList);\n\n // Resolve page metadata. Priority: `generateMetadata` from page.ts > `metadata`\n // field in the page loader data > `metadata` field in layout loader data.\n let metadata: PageMetadata | undefined;\n if (typeof generateMetadata === \"function\") {\n metadata = await generateMetadata({ params, searchParams, request, data });\n }\n if (!metadata) {\n metadata = extractMetadata(data) ?? extractMetadataFromList(layoutDataList);\n }\n // The title from metadata takes precedence over the data.title fallback.\n const resolvedTitle = metadata?.title ?? title;\n\n // --- 0% JS gating (Fase 8.2) ---\n // Scan the rendered body for island markers. A false positive (e.g. a\n // `data-elur-island` string inside user markdown) only loads the hydration\n // entry unnecessarily — benign. A false negative would mean dead islands in\n // production, which is why we scan output instead of tracking render context.\n const hasIslands = body.includes(ISLAND_MARKER_ATTR);\n\n // Decide which module scripts the shell emits. Three modes:\n // legacy (`js: \"legacy\"` or no router config at all): the combined\n // entry is emitted unconditionally — the pre-Fase-8 behavior.\n // split (router.entry set): entry-client hydrates islands only, the\n // router lives in its own chunk → emit router.js whenever the\n // router is enabled, and entry-client only when islands exist.\n // combined (router configured, no entry): the entry embeds the router\n // (single-input bundles) → emit it when there are islands or the\n // router is on; a page with neither ships 0 KB of JS.\n const routerCfg = config.router;\n const routerEnabled = routerCfg?.enabled !== false;\n let clientEntry: string | undefined;\n let routerEntry: string | undefined;\n if (!routerCfg || config.js === \"legacy\") {\n clientEntry = config.clientEntry;\n } else if (routerCfg.entry) {\n if (hasIslands) clientEntry = config.clientEntry;\n if (routerEnabled) routerEntry = routerCfg.entry;\n } else if (hasIslands || routerEnabled) {\n clientEntry = config.clientEntry;\n }\n\n const html = documentShell({\n title: resolvedTitle,\n lang: config.lang,\n body,\n data,\n actions,\n htmlAttributes,\n headScripts,\n headLinks,\n metadata,\n clientEntry,\n routerEntry,\n routerEnabled: routerCfg ? routerEnabled : undefined,\n speculation: routerCfg?.speculation,\n renderEndpoint: config.renderEndpoint,\n });\n\n const head = metadata ? buildHeadTags(metadata, resolvedTitle) : \"\";\n return { html, revalidate, clearActionErrorCookie, head, resolvedTitle, cachePolicy, data };\n}\n\n/** Extracts a `metadata` field from a loader data object, if present. */\nfunction extractMetadata(value: unknown): PageMetadata | undefined {\n if (value && typeof value === \"object\" && \"metadata\" in value) {\n const meta = (value as { metadata?: unknown }).metadata;\n if (meta && typeof meta === \"object\") return meta as PageMetadata;\n }\n return undefined;\n}\n\n/** Extracts metadata from the first layout data object that has one. */\nfunction extractMetadataFromList(list: unknown[]): PageMetadata | undefined {\n for (const item of list) {\n const meta = extractMetadata(item);\n if (meta) return meta;\n }\n return undefined;\n}\n\nexport interface RenderErrorPageOptions {\n routes: ScannedRoutes;\n status: 404 | 500;\n error?: unknown;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\" | \"renderEndpoint\" | \"router\" | \"js\">;\n actions?: Record<string, string[]>;\n importer?: (path: string) => Promise<unknown>;\n}\n\nexport async function renderErrorPage(\n options: RenderErrorPageOptions,\n): Promise<{ html: string; status: number } | undefined> {\n const route = options.status === 404 ? options.routes.error404 : options.routes.error500;\n if (!route) return undefined;\n\n try {\n const { html } = await renderPage({\n route,\n params: {},\n searchParams: new URLSearchParams(),\n config: options.config,\n actions: options.actions,\n importer: options.importer,\n });\n return { html, status: options.status };\n } catch (err) {\n console.error(`[render] error ${options.status} page failed`, err);\n return undefined;\n }\n}\n","import { resolve, relative } from \"node:path\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\n\n/**\n * Registry of server actions grouped by page path.\n *\n * The outer key is the page URL path (e.g. \"/contact\"). The inner object maps\n * each exported action name to the absolute file path of the `page.action.ts`\n * module that defines it.\n */\nexport type ActionRegistry = Record<string, Record<string, string>>;\n\n/**\n * Scans `page.action.ts` modules and returns a per-page registry of server actions.\n *\n * Only named function exports are collected; default exports are ignored. The\n * registry is keyed by page URL path so the client can resolve actions scoped\n * to a specific page and avoid name collisions between different routes.\n */\nexport async function scanActions(appDir: string): Promise<ActionRegistry> {\n const routes = await scanRoutes(appDir);\n const actions: ActionRegistry = {};\n\n for (const page of routes.pages) {\n if (!page.actionPath) continue;\n const actionPath = resolve(page.actionPath);\n const mod = (await import(actionPath)) as Record<string, unknown>;\n const pageActions: Record<string, string> = {};\n for (const [name, value] of Object.entries(mod)) {\n if (name === \"default\") continue;\n if (typeof value === \"function\") {\n pageActions[name] = actionPath;\n }\n }\n if (Object.keys(pageActions).length > 0) {\n actions[page.path] = pageActions;\n }\n }\n\n return actions;\n}\n\n/**\n * Return a copy of the action registry where every file path is made relative to\n * the given project root. Useful for serializing actions into the HTML shell\n * without exposing absolute server paths.\n */\nexport function relativeActions(actions: ActionRegistry, root: string): ActionRegistry {\n const result: ActionRegistry = {};\n for (const [page, pageActions] of Object.entries(actions)) {\n const entries: Record<string, string> = {};\n for (const [name, actionPath] of Object.entries(pageActions)) {\n entries[name] = relative(root, actionPath);\n }\n result[page] = entries;\n }\n return result;\n}\n\n/**\n * Return only the names of available actions per page, without file paths.\n * This is the safe format to serialize into the HTML shell: the client only\n * needs to know which actions exist, never where they are implemented.\n */\nexport function actionNames(actions: ActionRegistry): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n for (const [page, pageActions] of Object.entries(actions)) {\n result[page] = Object.keys(pageActions);\n }\n return result;\n}\n","import { readFile, mkdir, writeFile, rename, rm, stat } from \"node:fs/promises\";\nimport { join, dirname, extname, basename, resolve, sep } from \"node:path\";\nimport { createHash, randomBytes } from \"node:crypto\";\nimport type { ImageFormat } from \"./index.js\";\n\n// --- ImageService: metadata-driven image processing and manifest ---\n//\n// * Reads real image dimensions from the source file (sharp metadata).\n// * Generates hashed variant filenames from a SHA-256 transform key that\n// incorporates: content digest + normalized transform options +\n// encoder/service version + output naming version (§4.2).\n// * Applies path containment for sources and outputs (no traversal, no NUL,\n// no symlink escape, no Unicode/separator tricks).\n// * Writes outputs atomically (temp + rename) with single-flight per\n// transform key and a bounded concurrency pool.\n// * Supports `strict` mode: fails the build on missing sources or failed\n// transforms instead of emitting a partially-written variant.\n// * Falls back gracefully when sharp is not installed.\n\nconst ENCODER_VERSION = \"sharp-1\";\nconst NAMING_VERSION = \"v1\";\nconst HASH_LENGTH = 12;\nconst DEFAULT_QUALITY = 80;\nconst DEFAULT_CONCURRENCY = 4;\n\nexport interface ImageVariant {\n /** URL path relative to the site root, e.g. \"/images/hero.abc123def456.800w.webp\". */\n url: string;\n /** Width in pixels. */\n width: number;\n /** Height in pixels (preserves aspect ratio). */\n height: number;\n /** Format of the variant. */\n format: ImageFormat;\n /** File size in bytes. */\n size: number;\n}\n\nexport interface ImageEntry {\n /** Original source URL, e.g. \"/images/hero.jpg\". */\n src: string;\n /** Intrinsic width of the source. */\n width: number;\n /** Intrinsic height of the source. */\n height: number;\n /** All generated variants. */\n variants: ImageVariant[];\n /** Content hash of the source file. */\n hash: string;\n}\n\nexport interface ImageManifest {\n version: 1;\n entries: Record<string, ImageEntry>;\n}\n\nexport interface ProcessOptions {\n /** Absolute path to the public directory (source images). */\n publicDir: string;\n /** Absolute path to the output directory. */\n outDir: string;\n /** Formats to generate. Defaults to [\"webp\", \"avif\"]. */\n formats?: ImageFormat[];\n /** Quality (1-100). Defaults to 80. */\n quality?: number;\n /** Path to write the manifest JSON. */\n manifestPath?: string;\n /** When true, missing sources or failed transforms fail the build. */\n strict?: boolean;\n /** Max concurrent sharp transforms. Defaults to 4. */\n concurrency?: number;\n /** Optional URL base prefix applied to variant URLs. */\n base?: string;\n}\n\nexport interface ProcessResult {\n manifest: ImageManifest;\n /** Number of variants generated. */\n count: number;\n /** Whether sharp was available. */\n optimized: boolean;\n}\n\nlet sharpLoader: (() => Promise<any>) | null | undefined;\n\nasync function loadSharp(): Promise<any | null> {\n if (sharpLoader === null) return null;\n if (sharpLoader) return sharpLoader();\n try {\n // @ts-ignore — `sharp` is an optional peer dependency.\n const mod = await import(\"sharp\");\n const sharp = mod.default;\n if (typeof sharp !== \"function\") {\n sharpLoader = null;\n return null;\n }\n sharpLoader = async () => sharp;\n return sharp;\n } catch {\n sharpLoader = null;\n return null;\n }\n}\n\nexport async function isSharpAvailable(): Promise<boolean> {\n const sharp = await loadSharp();\n return sharp !== null;\n}\n\n// --- Transform identity (§4.2) ---\n\n/**\n * SHA-256 transform key. Stable for identical content+options and invalidated\n * whenever the source bytes, the effective transform options, the encoder\n * version or the naming scheme change.\n */\nexport function transformHash(sourceBuffer: Buffer, width: number, format: ImageFormat, quality: number): string {\n const contentDigest = createHash(\"sha256\").update(sourceBuffer).digest(\"hex\");\n const normalizedOptions = JSON.stringify({\n width,\n format,\n quality,\n withoutEnlargement: true,\n });\n return createHash(\"sha256\")\n .update(`${contentDigest}|${normalizedOptions}|${ENCODER_VERSION}|${NAMING_VERSION}`)\n .digest(\"hex\")\n .slice(0, HASH_LENGTH);\n}\n\n// --- Path containment (§9.5) ---\n\nfunction isSafeRelativePath(value: string): boolean {\n if (value.includes(\"\\0\") || value.includes(\"\\\\\")) return false;\n if (/%[0-9a-f]{2}/i.test(value)) return false;\n const segments = value.replace(/^\\/+/, \"\").split(\"/\");\n return !segments.some((segment) => segment === \"..\" || segment === \".\" || segment === \"\");\n}\n\nfunction isInside(root: string, candidate: string): boolean {\n return candidate === root || candidate.startsWith(`${root}${sep}`);\n}\n\nfunction assertInside(root: string, candidate: string, label: string): void {\n const resolvedRoot = resolve(root);\n const resolvedCandidate = resolve(candidate);\n if (!isInside(resolvedRoot, resolvedCandidate)) {\n throw new Error(`[elur-kit] Image ${label} escapes its allowed root (${resolvedCandidate}).`);\n }\n}\n\n// --- Concurrency: bounded pool + single-flight ---\n\nfunction createPool(limit: number) {\n let active = 0;\n const waiters: Array<() => void> = [];\n const acquire = () =>\n new Promise<void>((resolve) => {\n if (active < limit) {\n active++;\n resolve();\n } else {\n waiters.push(() => {\n active++;\n resolve();\n });\n }\n });\n const release = () => {\n active--;\n const next = waiters.shift();\n if (next) next();\n else if (active < 0) active = 0;\n };\n return {\n async run<T>(fn: () => Promise<T>): Promise<T> {\n await acquire();\n try {\n return await fn();\n } finally {\n release();\n }\n },\n };\n}\n\n// --- Atomic writes (§9.6) ---\n\nasync function atomicWriteFile(path: string, data: Buffer | string): Promise<void> {\n const temp = `${path}.${process.pid}.${randomBytes(6).toString(\"hex\")}.tmp`;\n try {\n await writeFile(temp, data);\n await rename(temp, path);\n } catch (error) {\n await rm(temp, { force: true }).catch(() => { });\n throw error;\n }\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\n// --- Public programmatic API (§3.1 / §3.3) ---\n\nexport interface ImageRequest {\n src: string;\n alt: string;\n widths?: readonly number[];\n formats?: readonly ImageFormat[];\n sizes?: string;\n width?: number;\n height?: number;\n priority?: boolean;\n loading?: \"lazy\" | \"eager\";\n decoding?: \"async\" | \"sync\" | \"auto\";\n quality?: number;\n fit?: string;\n class?: string;\n attributes?: Record<string, unknown>;\n}\n\nexport interface GeneratedImage {\n url: string;\n width: number;\n height: number;\n format: ImageFormat;\n size: number;\n}\n\nexport interface ImageMetadata {\n src: string;\n width?: number;\n height?: number;\n sources: Array<{ type: string; srcset: string }>;\n attributes: Record<string, string | number | boolean | undefined>;\n generated: readonly GeneratedImage[];\n}\n\nexport interface ImageServiceContext {\n publicDir: string;\n outDir: string;\n manifest: ImageManifest;\n}\n\nexport interface ImageServiceCapabilities {\n /** Whether the encoder (sharp) is available. */\n encoding: boolean;\n /** Whether remote images can be fetched. */\n remote: boolean;\n /** Whether a runtime image endpoint exists. */\n runtimeEndpoint: boolean;\n /** Whether the host exposes a writable filesystem. */\n filesystem: boolean;\n}\n\nexport interface ImageService {\n resolve(request: ImageRequest, context: ImageServiceContext): Promise<ImageMetadata>;\n capabilities: ImageServiceCapabilities;\n}\n\n/**\n * Creates a build-time ImageService bound to a public/output directory pair.\n */\nexport function createImageService(options: ProcessOptions): ImageService {\n return {\n capabilities: {\n encoding: false,\n remote: false,\n runtimeEndpoint: false,\n filesystem: true,\n },\n async resolve(request, context) {\n return getImage(request, { ...options, publicDir: context.publicDir, outDir: context.outDir });\n },\n };\n}\n\n/**\n * Programmatic async image API (§3.1). Ensures the requested variants exist on\n * disk (build-time), then returns deterministic metadata (not opaque markup).\n */\nexport async function getImage(\n request: ImageRequest,\n options: ProcessOptions,\n): Promise<ImageMetadata> {\n const { src, alt, widths, formats, quality, priority, loading, decoding, class: className, attributes = {} } = request;\n const targetWidths = widths?.length ? [...widths] : [request.width ?? 0];\n const targetFormats = formats?.length ? [...formats] : options.formats ?? [\"webp\", \"avif\"];\n const result = await processImageBatch(\n [{ src, widths: targetWidths, formats: targetFormats }],\n { ...options, quality: quality ?? options.quality },\n );\n const entry = result.manifest.entries[src];\n const generated: GeneratedImage[] = entry\n ? entry.variants.map((v) => ({ url: v.url, width: v.width, height: v.height, format: v.format, size: v.size }))\n : [];\n\n const sources: ImageMetadata[\"sources\"] = [];\n for (const format of targetFormats) {\n const srcset = entry ? buildSrcset(entry, format) : \"\";\n if (srcset) sources.push({ type: format === \"jpeg\" ? \"image/jpeg\" : `image/${format}`, srcset });\n }\n\n return {\n src,\n width: entry?.width,\n height: entry?.height,\n sources,\n attributes: {\n alt,\n width: entry?.width ?? request.width,\n height: entry?.height ?? request.height,\n loading: priority ? \"eager\" : (loading ?? \"lazy\"),\n decoding: decoding ?? \"async\",\n ...(priority ? { fetchpriority: \"high\" } : {}),\n ...(className ? { class: className } : {}),\n ...attributes,\n },\n generated,\n };\n}\n\n// --- Batch processing ---\n\nexport async function processImageBatch(\n images: { src: string; widths: number[]; formats?: ImageFormat[] }[],\n options: ProcessOptions,\n): Promise<ProcessResult> {\n const sharp = await loadSharp();\n const {\n publicDir,\n outDir,\n formats = [\"webp\", \"avif\"],\n quality = DEFAULT_QUALITY,\n strict = false,\n concurrency = DEFAULT_CONCURRENCY,\n base = \"\",\n } = options;\n const entries: Record<string, ImageEntry> = {};\n let count = 0;\n const pool = createPool(concurrency);\n const inFlight = new Map<string, Promise<void>>();\n\n const warned = new Set<string>();\n const warnOnce = (key: string, message: string): void => {\n if (warned.has(key)) return;\n warned.add(key);\n console.warn(`[elur-kit] ${message}`);\n };\n\n if (!sharp) {\n // Without sharp, build a manifest with only the original source entries.\n for (const { src } of images) {\n if (entries[src]) continue;\n if (!isSafeRelativePath(src)) {\n if (strict) throw new Error(`[elur-kit] Invalid image source path: ${src}`);\n warnOnce(`path:${src}`, `Skipping invalid image source path: ${src}`);\n continue;\n }\n const sourcePath = join(publicDir, src.replace(/^\\//, \"\"));\n assertInside(publicDir, sourcePath, `source \"${src}\"`);\n try {\n const buffer = await readFile(sourcePath);\n entries[src] = {\n src,\n width: 0,\n height: 0,\n variants: [],\n hash: createHash(\"sha256\").update(buffer).digest(\"hex\").slice(0, 8),\n };\n } catch (error) {\n if (strict) throw new Error(`[elur-kit] Image source not found: ${src}`);\n warnOnce(`missing:${src}`, `Image source not found: ${src}. Skipping.`);\n }\n }\n const manifest: ImageManifest = { version: 1, entries };\n if (options.manifestPath) await writeManifest(options.manifestPath, manifest);\n return { manifest, count: 0, optimized: false };\n }\n\n for (const { src, widths, formats: imgFormats } of images) {\n if (entries[src]) continue;\n\n if (!isSafeRelativePath(src)) {\n if (strict) throw new Error(`[elur-kit] Invalid image source path: ${src}`);\n warnOnce(`path:${src}`, `Skipping invalid image source path: ${src}`);\n continue;\n }\n\n const sourcePath = join(publicDir, src.replace(/^\\//, \"\"));\n assertInside(publicDir, sourcePath, `source \"${src}\"`);\n\n let sourceBuffer: Buffer;\n try {\n sourceBuffer = await readFile(sourcePath);\n } catch (error) {\n if (strict) throw new Error(`[elur-kit] Image source not found: ${src}`);\n warnOnce(`missing:${src}`, `Image not found: ${src}. Skipping.`);\n continue;\n }\n\n const ext = extname(src);\n const safeBase = basename(src, ext).replace(/[^a-zA-Z0-9._-]+/g, \"-\");\n const dir = dirname(src);\n const targetFormats = imgFormats?.length ? imgFormats : formats;\n\n // Read real metadata from the source.\n let sourceWidth = 0;\n let sourceHeight = 0;\n try {\n const meta = await sharp(sourceBuffer).metadata();\n sourceWidth = meta.width ?? 0;\n sourceHeight = meta.height ?? 0;\n } catch {\n // Fallback: no metadata.\n }\n\n const variants: ImageVariant[] = [];\n\n const processVariant = async (width: number, format: ImageFormat): Promise<void> => {\n // Never upscale: skip widths larger than the source.\n if (sourceWidth > 0 && width > sourceWidth) return;\n\n const hash = transformHash(sourceBuffer, width, format, quality);\n const variantName = `${safeBase}.${hash}.${width}w.${format}`;\n const variantRelPath = join(dir, variantName);\n const variantAbsPath = join(outDir, variantRelPath.replace(/^\\//, \"\"));\n assertInside(outDir, variantAbsPath, `variant \"${variantRelPath}\"`);\n const variantUrl = `${base.replace(/\\/$/, \"\")}/${variantRelPath.replace(/\\\\/g, \"/\").replace(/^\\//, \"\")}`;\n\n // Reuse an existing, valid output file (validated, not guessed).\n if (await fileExists(variantAbsPath)) {\n try {\n const info = await sharp(variantAbsPath).metadata();\n variants.push({\n url: variantUrl,\n width: info.width ?? width,\n height: info.height ?? Math.round((info.height ?? 0) || (sourceHeight && sourceWidth ? (width * sourceHeight) / sourceWidth : 0)),\n format,\n size: (await stat(variantAbsPath)).size,\n });\n count++;\n return;\n } catch {\n // Existing file invalid — regenerate below.\n }\n }\n\n const key = variantAbsPath;\n if (inFlight.has(key)) {\n await inFlight.get(key);\n variants.push({\n url: variantUrl,\n width,\n height: Math.round(sourceHeight && sourceWidth ? (width * sourceHeight) / sourceWidth : 0),\n format,\n size: (await stat(variantAbsPath)).size,\n });\n count++;\n return;\n }\n\n const task = (async () => {\n try {\n const buffer = await sharp(sourceBuffer)\n .resize({ width, withoutEnlargement: true })\n .toFormat(format, { quality })\n .toBuffer();\n await mkdir(dirname(variantAbsPath), { recursive: true });\n await atomicWriteFile(variantAbsPath, buffer);\n } catch (error) {\n if (strict) throw new Error(`[elur-kit] Failed to generate ${variantName}: ${error instanceof Error ? error.message : String(error)}`);\n warnOnce(`fail:${variantName}`, `Failed to generate ${variantName}.`);\n return;\n }\n variants.push({\n url: variantUrl,\n width,\n height: Math.round(sourceHeight && sourceWidth ? (width * sourceHeight) / sourceWidth : 0),\n format,\n size: (await stat(variantAbsPath)).size,\n });\n count++;\n })().finally(() => inFlight.delete(key));\n\n inFlight.set(key, task);\n await pool.run(() => task);\n };\n\n const tasks: Promise<void>[] = [];\n for (const width of widths) {\n for (const format of targetFormats) {\n tasks.push(processVariant(width, format));\n }\n }\n await Promise.all(tasks);\n\n entries[src] = {\n src,\n width: sourceWidth,\n height: sourceHeight,\n variants,\n hash: createHash(\"sha256\").update(sourceBuffer).digest(\"hex\").slice(0, 8),\n };\n }\n\n const manifest: ImageManifest = { version: 1, entries };\n if (options.manifestPath) await writeManifest(options.manifestPath, manifest);\n return { manifest, count, optimized: true };\n}\n\n/**\n * Read a manifest from disk, or return an empty one if it doesn't exist.\n */\nexport async function readManifest(path: string): Promise<ImageManifest> {\n try {\n const data = await readFile(path, \"utf8\");\n return JSON.parse(data) as ImageManifest;\n } catch {\n return { version: 1, entries: {} };\n }\n}\n\n/**\n * Write a manifest to disk atomically.\n */\nexport async function writeManifest(path: string, manifest: ImageManifest): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await atomicWriteFile(path, JSON.stringify(manifest, null, 2));\n}\n\n/**\n * Look up an image entry in the manifest by its source URL.\n */\nexport function getManifestEntry(manifest: ImageManifest, src: string): ImageEntry | undefined {\n return manifest.entries[src];\n}\n\n/**\n * Build a srcset string from manifest variants of a given format.\n * Returns e.g. \"/images/hero.abc.400w.webp 400w, /images/hero.abc.800w.webp 800w\".\n */\nexport function buildSrcset(entry: ImageEntry, format: ImageFormat): string {\n return entry.variants\n .filter((v) => v.format === format)\n .map((v) => `${v.url} ${v.width}w`)\n .join(\", \");\n}\n\n/**\n * Build the full <picture> markup for an image entry, with <source> per format\n * and a fallback <img>.\n */\nexport function buildPictureMarkup(entry: ImageEntry, opts: {\n alt: string;\n sizes?: string;\n priority?: boolean;\n class?: string;\n attributes?: Record<string, string>;\n fallbackSrc?: string;\n fallbackWidth?: number;\n fallbackHeight?: number;\n}): string {\n const {\n alt,\n sizes,\n priority = false,\n class: className,\n attributes = {},\n fallbackSrc = entry.src,\n fallbackWidth = entry.width,\n fallbackHeight = entry.height,\n } = opts;\n\n const formats = [...new Set(entry.variants.map((v) => v.format))];\n const loadingAttr = priority ? \"\" : ' loading=\"lazy\"';\n const fetchPriorityAttr = priority ? ' fetchpriority=\"high\"' : \"\";\n const sizesAttr = sizes ? ` sizes=\"${escapeAttr(sizes)}\"` : \"\";\n const classAttr = className ? ` class=\"${escapeAttr(className)}\"` : \"\";\n const extraAttrs = Object.entries(attributes)\n .map(([key, value]) => ` ${escapeAttr(key)}=\"${escapeAttr(String(value))}\"`)\n .join(\"\");\n\n const sources = formats\n .map((format) => {\n const srcset = buildSrcset(entry, format);\n if (!srcset) return \"\";\n const type = format === \"jpeg\" ? \"image/jpeg\" : `image/${format}`;\n return `<source srcset=\"${srcset}\"${sizesAttr} type=\"${type}\" />`;\n })\n .filter(Boolean)\n .join(\"\");\n\n const img = `<img src=\"${escapeAttr(fallbackSrc)}\" alt=\"${escapeAttr(alt)}\" width=\"${fallbackWidth}\" height=\"${fallbackHeight}\"${loadingAttr} decoding=\"async\"${fetchPriorityAttr}${classAttr}${extraAttrs} />`;\n\n return sources ? `<picture>${sources}${img}</picture>` : img;\n}\n\n/**\n * Validate that every variant URL in the manifest corresponds to a real file\n * in the output directory. Returns a list of missing URLs.\n */\nexport async function validateManifestUrls(\n manifest: ImageManifest,\n outDir: string,\n): Promise<string[]> {\n const missing: string[] = [];\n for (const entry of Object.values(manifest.entries)) {\n for (const variant of entry.variants) {\n const relative = variant.url.replace(/^\\/+/, \"\");\n const resolved = resolve(outDir, relative);\n if (!isInside(resolve(outDir), resolved)) {\n missing.push(variant.url);\n continue;\n }\n try {\n await stat(resolved);\n } catch {\n missing.push(variant.url);\n }\n }\n }\n return missing;\n}\n\nfunction escapeAttr(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n","export interface ElurKitIntegrationContext {\n root: string;\n command: \"dev\" | \"build\" | \"preview\" | \"start\" | \"check\" | \"routes\" | \"doctor\";\n}\n\nexport interface ElurKitIntegration {\n name: string;\n config?(config: Record<string, unknown>, context: ElurKitIntegrationContext): void | Promise<void>;\n routes?(manifest: unknown, context: ElurKitIntegrationContext): void | Promise<void>;\n request?(request: Request, context: ElurKitIntegrationContext): void | Response | Promise<void | Response>;\n render?(result: { html: string }, context: ElurKitIntegrationContext): void | Promise<void>;\n build?(result: unknown, context: ElurKitIntegrationContext): void | Promise<void>;\n clientEntry?(source: string, context: ElurKitIntegrationContext): string | void | Promise<string | void>;\n error?(error: unknown, context: ElurKitIntegrationContext): void | Promise<void>;\n}\n\nexport async function runIntegrationHook<K extends keyof Omit<ElurKitIntegration, \"name\">>(\n integrations: readonly ElurKitIntegration[],\n hook: K,\n args: Parameters<NonNullable<ElurKitIntegration[K]>>,\n): Promise<void> {\n for (const integration of integrations) {\n const handler = integration[hook];\n if (typeof handler === \"function\") await (handler as (...values: unknown[]) => unknown)(...args);\n }\n}\n\n// Typed integration hooks for optional packages (plan §11.6).\nexport {\n type I18nIntegration,\n type AuthIntegration,\n type QueryIntegration,\n type TestingIntegration,\n registerIntegration,\n getI18nIntegration,\n getAuthIntegration,\n getQueryIntegration,\n getTestingIntegration,\n getCustomIntegrations,\n clearIntegrations,\n} from \"./hooks.js\";\n","/**\n * SEO utilities — sitemap.xml and robots.txt generation.\n *\n * @module\n */\n\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\n\n// Sitemap generation from the scanned route manifest (wired into `build`).\nexport { generateSitemapFromRoutes, type SitemapFromRoutesOptions } from \"./sitemap-from-routes.js\";\n\n// Types\n\nexport interface SitemapEntry {\n /** URL path, e.g. \"/docs/getting-started/introduction\". */\n url: string;\n /** Last modification date (ISO 8601 or YYYY-MM-DD). */\n lastmod?: string;\n /** Change frequency: always, hourly, daily, weekly, monthly, yearly, never. */\n changefreq?: \"always\" | \"hourly\" | \"daily\" | \"weekly\" | \"monthly\" | \"yearly\" | \"never\";\n /** Priority 0.0–1.0. */\n priority?: number;\n}\n\nexport interface SitemapConfig {\n /** Base URL of the site, e.g. \"https://example.com\". */\n siteUrl: string;\n /** List of URL entries to include in the sitemap. */\n urls: (SitemapEntry | string)[];\n /** Output directory where sitemap.xml will be written. */\n outDir: string;\n}\n\nexport interface RobotsConfig {\n /** Base URL of the site, e.g. \"https://example.com\". */\n siteUrl: string;\n /** Output directory where robots.txt will be written. */\n outDir: string;\n /** Rules for specific user agents. */\n rules?: RobotsRule[];\n /** Paths to disallow for all crawlers (shorthand for rules). */\n disallow?: string[];\n /** Sitemap URL override. If not set, defaults to `${siteUrl}/sitemap.xml`. */\n sitemapUrl?: string;\n}\n\nexport interface RobotsRule {\n /** User-agent, e.g. \"Googlebot\" or \"*\" for all. */\n userAgent: string;\n /** Paths to disallow. */\n disallow?: string[];\n /** Paths to allow. */\n allow?: string[];\n /** Crawl delay in seconds. */\n crawlDelay?: number;\n}\n\n// Sitemap generation\n\n/**\n * Generates a `sitemap.xml` file from a list of URLs.\n *\n * @example\n * ```ts\n * import { generateSitemap } from \"@elurjs/kit/seo\";\n *\n * await generateSitemap({\n * siteUrl: \"https://elur-kit.dev\",\n * outDir: \"./dist\",\n * urls: [\n * \"/\",\n * \"/docs/introduction\",\n * { url: \"/docs/routing\", changefreq: \"weekly\", priority: 0.8 },\n * ],\n * });\n * ```\n */\nexport async function generateSitemap(config: SitemapConfig): Promise<string> {\n const { siteUrl, urls, outDir } = config;\n const base = siteUrl.replace(/\\/$/, \"\");\n\n const entries: string[] = urls.map((entry) => {\n const e = typeof entry === \"string\" ? { url: entry } : entry;\n const loc = `${base}${e.url.startsWith(\"/\") ? \"\" : \"/\"}${e.url}`;\n const lines = [` <url>`, ` <loc>${escapeXml(loc)}</loc>`];\n if (e.lastmod) lines.push(` <lastmod>${e.lastmod}</lastmod>`);\n if (e.changefreq) lines.push(` <changefreq>${e.changefreq}</changefreq>`);\n if (e.priority !== undefined) lines.push(` <priority>${e.priority.toFixed(1)}</priority>`);\n lines.push(` </url>`);\n return lines.join(\"\\n\");\n });\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${entries.join(\"\\n\")}\n</urlset>\n`;\n\n const filePath = join(outDir, \"sitemap.xml\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, xml, \"utf8\");\n return filePath;\n}\n\n// Robots.txt generation\n\n/**\n * Generates a `robots.txt` file.\n *\n * @example\n * ```ts\n * import { generateRobots } from \"@elurjs/kit/seo\";\n *\n * await generateRobots({\n * siteUrl: \"https://elur-kit.dev\",\n * outDir: \"./dist\",\n * disallow: [\"/api/\", \"/_elur/\"],\n * });\n * ```\n */\nexport async function generateRobots(config: RobotsConfig): Promise<string> {\n const { siteUrl, outDir, rules, disallow, sitemapUrl } = config;\n const base = siteUrl.replace(/\\/$/, \"\");\n const lines: string[] = [];\n\n if (rules && rules.length > 0) {\n for (const rule of rules) {\n lines.push(`User-agent: ${rule.userAgent}`);\n if (rule.allow) {\n for (const path of rule.allow) lines.push(`Allow: ${path}`);\n }\n if (rule.disallow) {\n for (const path of rule.disallow) lines.push(`Disallow: ${path}`);\n }\n if (rule.crawlDelay !== undefined) {\n lines.push(`Crawl-delay: ${rule.crawlDelay}`);\n }\n lines.push(\"\");\n }\n } else {\n lines.push(\"User-agent: *\");\n if (disallow && disallow.length > 0) {\n for (const path of disallow) lines.push(`Disallow: ${path}`);\n } else {\n lines.push(\"Disallow:\");\n }\n lines.push(\"\");\n }\n\n const sitemap = sitemapUrl ?? `${base}/sitemap.xml`;\n lines.push(`Sitemap: ${sitemap}`);\n\n const content = lines.join(\"\\n\") + \"\\n\";\n const filePath = join(outDir, \"robots.txt\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, content, \"utf8\");\n return filePath;\n}\n\n// JSON-LD / Structured data\n\nexport interface JsonLdSchema {\n [key: string]: unknown;\n}\n\n/**\n * Serializes a JSON-LD structured data object into a `<script type=\"application/ld+json\">` tag.\n *\n * @example\n * ```ts\n * import { jsonLd } from \"@elurjs/kit/seo\";\n *\n * const schema = jsonLd({\n * \"@context\": \"https://schema.org\",\n * \"@type\": \"TechArticle\",\n * headline: \"Routing\",\n * author: { \"@type\": \"Person\", name: \"Deiver Vasquez\" },\n * });\n * // Returns: <script type=\"application/ld+json\">{...}</script>\n * ```\n */\nexport function jsonLd(schema: JsonLdSchema | JsonLdSchema[]): string {\n const data = JSON.stringify(Array.isArray(schema) ? schema : schema);\n // Escape sequences that could close the <script> tag or introduce markup.\n // Per the HTML spec, inside a <script> block the only dangerous sequence\n // is \"</script\" (case-insensitive). We also escape \"<\" more broadly to\n // prevent any interpreter from seeing markup-like content, and escape\n // \"<!--\" to prevent HTML comment-based escapes.\n const safe = data\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/&/g, \"\\\\u0026\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n return `<script type=\"application/ld+json\">${safe}</script>`;\n}\n\n// Helpers\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n","// --- Sitemap generation from route manifest (plan §11.3) ---\n//\n// Generates a sitemap.xml from the scanned routes, excluding:\n// - API routes\n// - Dynamic routes (they require data to generate URLs)\n// - Error pages (404, 500)\n// - Routes with noindex metadata\n//\n// For dynamic routes, the author should provide a `generateSitemapUrls()`\n// function in their page.data.ts that returns concrete URLs.\n//\n// Supports large sitemaps via sitemap index files (split at 50,000 URLs).\n\nimport type { ScannedRoutes } from \"../router/route-scanner.js\";\nimport { generateSitemap, type SitemapEntry } from \"./index.js\";\n\nexport interface SitemapFromRoutesOptions {\n siteUrl: string;\n outDir: string;\n routes: ScannedRoutes;\n /** Additional URLs to include (e.g. from dynamic routes). */\n extraUrls?: (SitemapEntry | string)[];\n /** Max URLs per sitemap file. Default: 50000. */\n maxUrlsPerSitemap?: number;\n /** Default changefreq for routes. */\n defaultChangefreq?: SitemapEntry[\"changefreq\"];\n /** Default priority for routes. */\n defaultPriority?: number;\n}\n\n/**\n * Generates a sitemap.xml from the route manifest.\n *\n * Static routes are included automatically. Dynamic routes require the author\n * to provide URLs via `extraUrls` or a `generateSitemapUrls()` export.\n *\n * For large sites (>50,000 URLs), a sitemap index is generated.\n */\nexport async function generateSitemapFromRoutes(\n options: SitemapFromRoutesOptions,\n): Promise<string[]> {\n const { siteUrl, outDir, routes, extraUrls = [], maxUrlsPerSitemap = 50000 } = options;\n\n // Collect static route URLs.\n const routeUrls: SitemapEntry[] = [];\n for (const page of routes.pages) {\n // Skip dynamic routes (they have params).\n if (page.params.length > 0) continue;\n // Skip error pages.\n if (page.path === \"/404\" || page.path === \"/500\") continue;\n // Skip internal namespaces.\n if (page.path.startsWith(\"/_elur\") || page.path.startsWith(\"/__elur-js\")) continue;\n\n routeUrls.push({\n url: page.path,\n changefreq: options.defaultChangefreq,\n priority: options.defaultPriority,\n });\n }\n\n // Merge with extra URLs.\n const allUrls = [...routeUrls, ...extraUrls];\n\n // If under the limit, generate a single sitemap.\n if (allUrls.length <= maxUrlsPerSitemap) {\n const path = await generateSitemap({ siteUrl, outDir, urls: allUrls });\n return [path];\n }\n\n // For large sitemaps, split into multiple files with an index.\n return generateSitemapIndex({ siteUrl, outDir, urls: allUrls, maxUrlsPerSitemap });\n}\n\n/**\n * Generates a sitemap index file that references multiple sitemap files.\n * Used for large sites (>50,000 URLs).\n */\nasync function generateSitemapIndex(\n options: { siteUrl: string; outDir: string; urls: (SitemapEntry | string)[]; maxUrlsPerSitemap: number },\n): Promise<string[]> {\n const { siteUrl, outDir, urls, maxUrlsPerSitemap } = options;\n const base = siteUrl.replace(/\\/$/, \"\");\n const files: string[] = [];\n const sitemapUrls: string[] = [];\n\n // Split URLs into chunks.\n for (let i = 0; i < urls.length; i += maxUrlsPerSitemap) {\n const chunk = urls.slice(i, i + maxUrlsPerSitemap);\n const filename = `sitemap-${Math.floor(i / maxUrlsPerSitemap) + 1}.xml`;\n const { writeFile, mkdir } = await import(\"node:fs/promises\");\n const { join, dirname } = await import(\"node:path\");\n\n // Generate the chunk sitemap.\n const entries = chunk.map((entry) => {\n const e = typeof entry === \"string\" ? { url: entry } : entry;\n const loc = `${base}${e.url.startsWith(\"/\") ? \"\" : \"/\"}${e.url}`;\n const lines = [` <url>`, ` <loc>${escapeXml(loc)}</loc>`];\n if (e.lastmod) lines.push(` <lastmod>${e.lastmod}</lastmod>`);\n if (e.changefreq) lines.push(` <changefreq>${e.changefreq}</changefreq>`);\n if (e.priority !== undefined) lines.push(` <priority>${e.priority.toFixed(1)}</priority>`);\n lines.push(` </url>`);\n return lines.join(\"\\n\");\n });\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${entries.join(\"\\n\")}\\n</urlset>\\n`;\n const filePath = join(outDir, filename);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, xml, \"utf8\");\n files.push(filePath);\n sitemapUrls.push(`${base}/${filename}`);\n }\n\n // Generate the index file.\n const { writeFile, mkdir } = await import(\"node:fs/promises\");\n const { join, dirname } = await import(\"node:path\");\n\n const indexEntries = sitemapUrls.map((url) => ` <sitemap>\\n <loc>${escapeXml(url)}</loc>\\n </sitemap>`).join(\"\\n\");\n const indexXml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${indexEntries}\\n</sitemapindex>\\n`;\n const indexPath = join(outDir, \"sitemap.xml\");\n await mkdir(dirname(indexPath), { recursive: true });\n await writeFile(indexPath, indexXml, \"utf8\");\n files.push(indexPath);\n\n return files;\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n","import { cp, mkdir, stat, writeFile } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { scanRoutes, type PageRoute, type ScannedRoutes } from \"../router/route-scanner.js\";\nimport { scanIslands, type IslandModule } from \"../island/scan.js\";\nimport { generateClientEntry } from \"../island/generate-entry.js\";\nimport { renderPage, renderErrorPage } from \"../ssr/render.js\";\nimport { scanActions, actionNames } from \"../action/scan.js\";\nimport { consumeImageRegistry, setImageManifest, type ImageFormat } from \"../image/index.js\";\nimport { processImageBatch, type ImageManifest } from \"../image/service.js\";\nimport { runIntegrationHook, type ElurKitIntegration } from \"../integrations/index.js\";\nimport { generateSitemapFromRoutes } from \"../seo/sitemap-from-routes.js\";\nimport type { RouteParams, GenerateStaticParams } from \"../types.js\";\n\nexport interface BuildConfig {\n /** Absolute path to the app directory (e.g. /project/src/app). */\n appDir: string;\n /** Absolute path to the output directory (e.g. /project/dist). */\n outDir: string;\n /** Absolute path to the project root (e.g. /project). When provided, action\n * paths in the serialized HTML shell are made relative to this root. */\n root?: string;\n /** Base path for the client entry module, e.g. \"/_elur/entry-client.js\". */\n clientEntry?: string;\n /** Default language for the HTML shell. */\n lang?: string;\n /**\n * Absolute path to the islands directory (e.g. /project/src/islands).\n * When set, `build` scans it and generates a client entry module listing\n * every island so you don't have to maintain `entry-client.ts` by hand.\n */\n islandsDir?: string;\n /**\n * Absolute path where the generated client entry module is written\n * (e.g. /project/.elur/entry-client.ts). Required when `islandsDir` is set.\n */\n generatedEntry?: string;\n /**\n * Import specifier the generated entry uses for `hydrateIslands`.\n * Defaults to the published subpath `@elurjs/kit/island`.\n */\n hydrateImport?: string;\n /**\n * Import specifier the generated entry uses for `startClientRouter`.\n * Defaults to the published subpath `@elurjs/kit/router`.\n */\n routerImport?: string;\n /** Absolute path to the public directory for static assets (optional). */\n publicDir?: string;\n /** Image formats to generate when sharp is available. Defaults to [\"webp\", \"avif\"]. */\n imageFormats?: ImageFormat[];\n /**\n * Whether the SSR render endpoint (`/__elur-js/render`) exists at runtime.\n * Defaults to `true` (dev, preview and SSR deployments). Set to `false` for\n * fully static outputs so the emitted HTML tells the client router to skip\n * the endpoint (no 404 storms on static hosts like Vercel).\n */\n renderEndpoint?: boolean;\n /**\n * Client router options (Fase 8.3 + §9). `enabled`/`prefetch`/`morph`/\n * `loadingIndicator` are baked into the generated entry; `separate` makes\n * the router its own generated module (emitted as its own chunk when the\n * client bundle declares it as an input) so pages without islands only\n * load `router.js`; `entry` is that chunk's public URL; `speculation`\n * emits a Speculation Rules block on static pages.\n */\n router?: {\n enabled?: boolean;\n prefetch?: boolean;\n morph?: boolean;\n loadingIndicator?: boolean;\n speculation?: \"prefetch\" | \"prerender\";\n /** Generate a standalone router module next to the client entry. */\n separate?: boolean;\n /** Public URL of the router chunk (default: \"/_elur/router.js\"). */\n entry?: string;\n /** Path of the generated router module (default: sibling \"router.ts\"). */\n outFile?: string;\n };\n /**\n * Client JS emission mode: `\"modern\"` gates the entry per page (0% JS);\n * `\"legacy\"` emits the combined entry unconditionally on every page.\n */\n js?: \"modern\" | \"legacy\";\n /**\n * Public site URL (e.g. \"https://example.com\"). When set, the build\n * generates `sitemap.xml` from the scanned routes automatically, unless\n * one already exists in the output (from `public/` or an integration).\n */\n site?: string;\n /**\n * Integrations to invoke during the build lifecycle. When provided, the\n * `build` hook fires after all pages and image variants are generated,\n * giving integrations a chance to write post-build artifacts (sitemaps,\n * robots.txt, search indexes, etc.) into the output directory.\n */\n integrations?: ElurKitIntegration[];\n /**\n * Optional observer invoked once per build phase with its duration in\n * milliseconds (\"scan\", \"pages\", \"images\", \"integrations\", \"sitemap\").\n * Phases that don't run (no images, no integrations, no site URL) are not\n * reported. Used by the CLI to render progress; the build itself stays\n * silent.\n */\n onPhase?: (name: string, durationMs: number) => void;\n}\n\nexport interface BuildResult {\n /** Number of static HTML pages generated. */\n pages: number;\n /** Paths that were skipped because they are dynamic without a static param list. */\n skipped: string[];\n /** Absolute paths to the generated HTML files. */\n files: string[];\n /** Islands discovered when `islandsDir` is set. */\n islands: IslandModule[];\n /** Absolute path to the generated client entry, if one was written. */\n generatedEntry?: string;\n /** Number of image variants generated (0 if sharp is not installed). */\n imagesProcessed: number;\n /** Absolute path to the output directory where build artifacts were written.\n * When called via the CLI, this is the atomic staging directory (not the\n * final `dist/`). Integration `build` hooks should write post-build\n * artifacts here so they survive the atomic swap. */\n outDir: string;\n}\n\nfunction urlToFilePath(outDir: string, urlPath: string): string {\n if (urlPath === \"/\") {\n return join(outDir, \"index.html\");\n }\n\n const segments = urlPath.slice(1).split(\"/\");\n return join(outDir, ...segments, \"index.html\");\n}\n\nfunction isDynamic(path: string): boolean {\n return path.includes(\":\");\n}\n\nfunction buildConcreteUrl(path: string, params: RouteParams): string {\n return path.replace(/:([a-zA-Z0-9_]+)(\\*)?/g, (_, name, catchAll) => {\n const value = params[name];\n if (value === undefined || value === null) {\n throw new Error(\n `Missing value for dynamic segment \"${name}\" in path \"${path}\"`,\n );\n }\n if (catchAll) {\n return Array.isArray(value) ? value.join(\"/\") : String(value);\n }\n return String(value);\n });\n}\n\n/**\n * Builds a static site from a scanned route tree.\n *\n * @param config Build configuration.\n * @returns Summary of generated files.\n */\nexport async function build(config: BuildConfig): Promise<BuildResult> {\n if (config.publicDir) {\n try {\n if ((await stat(config.publicDir)).isDirectory()) {\n await mkdir(config.outDir, { recursive: true });\n await cp(config.publicDir, config.outDir, { recursive: true, force: true });\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n }\n\n const reportPhase = (name: string, start: number): void => {\n config.onPhase?.(name, performance.now() - start);\n };\n\n let phaseStart = performance.now();\n const routes = await scanRoutes(config.appDir);\n const actions = await scanActions(config.appDir);\n reportPhase(\"scan\", phaseStart);\n // Only action names are serialized into the HTML shell; full paths stay on the server.\n const publicActions = actionNames(actions);\n const result: BuildResult = { pages: 0, skipped: [], files: [], islands: [], imagesProcessed: 0, outDir: config.outDir };\n\n // Scan islands and generate the client entry before rendering pages, so the\n // hydration bundle stays in sync with what the app actually uses.\n if (config.islandsDir) {\n result.islands = await scanIslands(config.islandsDir);\n }\n\n if (config.generatedEntry) {\n result.generatedEntry = await generateClientEntry({\n islands: result.islands,\n outFile: config.generatedEntry,\n hydrateImport: config.hydrateImport,\n routerImport: config.routerImport,\n router: config.router\n ? {\n enabled: config.router.enabled !== false,\n prefetch: config.router.prefetch,\n morph: config.router.morph,\n loadingIndicator: config.router.loadingIndicator,\n separate: config.router.separate === true && config.js !== \"legacy\",\n outFile: config.router.outFile,\n }\n : undefined,\n });\n }\n\n phaseStart = performance.now();\n for (const route of routes.pages) {\n if (!isDynamic(route.path)) {\n const filePath = await buildPage(config, route, publicActions);\n result.pages++;\n result.files.push(filePath);\n continue;\n }\n\n const dynamicFiles = await buildDynamicPages(config, route, publicActions);\n if (dynamicFiles.length === 0) {\n result.skipped.push(route.path);\n } else {\n result.pages += dynamicFiles.length;\n result.files.push(...dynamicFiles);\n }\n }\n\n // Generate static 404 and 500 error pages when they exist.\n const errorConfig = {\n lang: config.lang,\n clientEntry: config.clientEntry,\n renderEndpoint: false,\n router: pageRouterConfig(config),\n js: config.js,\n };\n if (routes.error404) {\n const result404 = await renderErrorPage({\n routes,\n status: 404,\n config: errorConfig,\n actions: publicActions,\n });\n if (result404) {\n const filePath = join(config.outDir, \"404.html\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, result404.html, \"utf8\");\n result.files.push(filePath);\n }\n }\n\n if (routes.error500) {\n const result500 = await renderErrorPage({\n routes,\n status: 500,\n config: errorConfig,\n actions: publicActions,\n });\n if (result500) {\n const filePath = join(config.outDir, \"500.html\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, result500.html, \"utf8\");\n result.files.push(filePath);\n }\n }\n reportPhase(\"pages\", phaseStart);\n\n // Process registered images with the ImageService (if sharp is installed).\n // This is a two-pass process:\n // 1. First render pass registers all images (already done above).\n // 2. Process registered images → produce manifest.\n // 3. If variants were generated, set the manifest and re-render pages\n // so the markup uses real <picture>/<source> with hashed URLs.\n const registeredImages = consumeImageRegistry();\n let manifest: ImageManifest | null = null;\n if (registeredImages.length > 0 && config.publicDir) {\n phaseStart = performance.now();\n const manifestPath = join(config.outDir, \".elur\", \"image-manifest.json\");\n const processResult = await processImageBatch(registeredImages, {\n publicDir: config.publicDir,\n outDir: config.outDir,\n formats: config.imageFormats,\n manifestPath,\n });\n result.imagesProcessed = processResult.count;\n\n if (processResult.optimized && processResult.count > 0) {\n manifest = processResult.manifest;\n setImageManifest(manifest);\n\n // Re-render all pages with the manifest so image() emits <picture>.\n result.pages = 0;\n result.files = [];\n for (const route of routes.pages) {\n if (!isDynamic(route.path)) {\n const filePath = await buildPage(config, route, publicActions);\n result.pages++;\n result.files.push(filePath);\n continue;\n }\n const dynamicFiles = await buildDynamicPages(config, route, publicActions);\n if (dynamicFiles.length === 0) {\n result.skipped.push(route.path);\n } else {\n result.pages += dynamicFiles.length;\n result.files.push(...dynamicFiles);\n }\n }\n\n // Re-render error pages too.\n if (routes.error404) {\n const result404 = await renderErrorPage({\n routes,\n status: 404,\n config: errorConfig,\n actions: publicActions,\n });\n if (result404) {\n const filePath = join(config.outDir, \"404.html\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, result404.html, \"utf8\");\n result.files.push(filePath);\n }\n }\n if (routes.error500) {\n const result500 = await renderErrorPage({\n routes,\n status: 500,\n config: errorConfig,\n actions: publicActions,\n });\n if (result500) {\n const filePath = join(config.outDir, \"500.html\");\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, result500.html, \"utf8\");\n result.files.push(filePath);\n }\n }\n }\n reportPhase(\"images\", phaseStart);\n }\n\n // Clear the manifest so subsequent builds start fresh.\n setImageManifest(null);\n\n // Fire the `build` integration hook so integrations can write\n // post-build artifacts (sitemaps, robots.txt, search indexes, etc.)\n // into the output directory. This runs after all pages, image variants,\n // and the manifest are written, but before the atomic staging commit\n // (when called via the CLI), so integration artifacts survive the swap.\n if (config.integrations && config.integrations.length > 0) {\n phaseStart = performance.now();\n await runIntegrationHook(config.integrations, \"build\", [\n result,\n { root: config.root ?? config.outDir, command: \"build\" },\n ]);\n reportPhase(\"integrations\", phaseStart);\n }\n\n // Automatic sitemap from the scanned routes when the site URL is known.\n // Runs after the integration hook; an existing sitemap.xml (copied from\n // public/ or written by an integration) always takes precedence.\n if (config.site) {\n phaseStart = performance.now();\n let sitemapExists = false;\n try {\n sitemapExists = (await stat(join(config.outDir, \"sitemap.xml\"))).isFile();\n } catch {\n // No sitemap yet.\n }\n if (!sitemapExists) {\n const sitemapFiles = await generateSitemapFromRoutes({\n siteUrl: config.site,\n outDir: config.outDir,\n routes,\n });\n result.files.push(...sitemapFiles);\n }\n reportPhase(\"sitemap\", phaseStart);\n }\n\n return result;\n}\n\nasync function buildPage(\n config: BuildConfig,\n route: PageRoute,\n actions: Record<string, string[]>,\n): Promise<string> {\n return buildConcretePage(config, route, {}, actions);\n}\n\nasync function buildDynamicPages(\n config: BuildConfig,\n route: PageRoute,\n actions: Record<string, string[]>,\n): Promise<string[]> {\n const { generateStaticParams } = (await import(\n route.pagePath\n )) as { generateStaticParams?: GenerateStaticParams };\n\n if (!generateStaticParams) {\n return [];\n }\n\n const paramList = await generateStaticParams();\n if (!Array.isArray(paramList) || paramList.length === 0) {\n return [];\n }\n\n const files: string[] = [];\n for (const params of paramList) {\n files.push(await buildConcretePage(config, route, params, actions));\n }\n return files;\n}\n\nasync function buildConcretePage(\n config: BuildConfig,\n route: PageRoute,\n params: RouteParams,\n actions: Record<string, string[]>,\n): Promise<string> {\n const { html: htmlOut } = await renderPage({\n route,\n params,\n searchParams: new URLSearchParams(),\n config: {\n lang: config.lang,\n clientEntry: config.clientEntry,\n renderEndpoint: false,\n router: pageRouterConfig(config),\n js: config.js,\n },\n actions,\n });\n\n const urlPath = isDynamic(route.path) ? buildConcreteUrl(route.path, params) : route.path;\n const filePath = urlToFilePath(config.outDir, urlPath);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, htmlOut, \"utf8\");\n\n return filePath;\n}\n\n/**\n * The router slice of the per-page render config: `enabled` gates script/meta\n * emission, `entry` is advertised only for split bundles, and `speculation`\n * produces the Speculation Rules block on static pages.\n */\nfunction pageRouterConfig(config: BuildConfig) {\n if (!config.router) return undefined;\n const separate = config.router.separate === true && config.js !== \"legacy\";\n return {\n enabled: config.router.enabled !== false,\n entry: separate ? config.router.entry ?? \"/_elur/router.js\" : undefined,\n speculation: config.router.speculation,\n };\n}\n\nexport { scanRoutes, type PageRoute, type ScannedRoutes };\n","import { createRequire } from \"node:module\";\nimport type { Plugin } from \"vite\";\n\n/**\n * How the legacy interpolation transform is handled relative to the installed\n * Elur core and Vite plugin:\n *\n * - `\"auto\"` (default): the kit's legacy transform is only applied when the\n * Vite plugin (`@elurjs/vite-plugin-elur` >= 1.1.0) is NOT installed.\n * The plugin has a more powerful state-machine lexer and takes precedence.\n * - `\"legacy\"`: always apply the kit's transform (for migrations), with a\n * one-time deprecation warning.\n * - `\"off\"`: never apply the kit's transform. Recommended when the Vite\n * plugin is installed.\n */\nexport type InterpolationMode = \"auto\" | \"legacy\" | \"off\";\n\nconst require = createRequire(import.meta.url);\n\nlet _warnedLegacy = false;\n\nfunction warnLegacyOnce(): void {\n if (_warnedLegacy) return;\n _warnedLegacy = true;\n console.warn(\n \"[elur-kit] The legacy interpolation transform is deprecated. \" +\n \"Install @elurjs/vite-plugin-elur >= 1.1.0 for compile-time \" +\n \"partial attribute interpolation. Remove `interpolation: \\\"legacy\\\"` \" +\n \"once migration is complete.\",\n );\n}\n\n/**\n * Detects whether the Vite plugin (`@elurjs/vite-plugin-elur`) is\n * installed and provides compile-time partial attribute interpolation.\n */\nexport function pluginSupportsPartialInterpolation(): boolean {\n try {\n const pkg = require(\"@elurjs/vite-plugin-elur/package.json\") as {\n version?: string;\n };\n // >= 1.1.0 has the interpolation lexer\n const [major, minor] = (pkg.version ?? \"0.0.0\").split(\".\").map(Number);\n return major > 1 || (major === 1 && minor >= 1);\n } catch {\n return false;\n }\n}\n\n/**\n * Detects whether the installed Elur core supports partial attribute\n * interpolation natively (via the public `templateFeatures` capability).\n * Note: as of core v3.4.0, this is always false — the lexer moved to the\n * Vite plugin.\n */\nexport function coreSupportsPartialInterpolation(): boolean {\n try {\n const core = require(\"@elurjs/core\") as {\n templateFeatures?: { partialAttributeInterpolation?: boolean };\n };\n return core?.templateFeatures?.partialAttributeInterpolation === true;\n } catch {\n return false;\n }\n}\n\n/**\n * Resolves whether the kit's legacy transform should be applied.\n *\n * In `\"auto\"` mode, the kit's transform runs only when neither the Vite\n * plugin nor the core provides partial interpolation. When the Vite plugin\n * is installed (>= 1.1.0), it takes precedence and the kit's transform is\n * skipped to avoid double-processing.\n */\nexport function shouldUseLegacyInterpolation(mode: InterpolationMode): boolean {\n if (mode === \"off\") return false;\n if (mode === \"legacy\") {\n warnLegacyOnce();\n return true;\n }\n // auto: skip if the Vite plugin handles it\n if (pluginSupportsPartialInterpolation()) return false;\n // fallback: use legacy if core doesn't support it natively\n return !coreSupportsPartialInterpolation();\n}\n\n/**\n * Transforms Elur `html\\`\\`` templates so that attributes with partial\n * interpolation become a single interpolation expression.\n *\n * Elur requires every dynamic attribute to be a single interpolation covering\n * the whole value. This plugin rewrites patterns such as:\n *\n * html\\`<a href=\"/blog/${slug}\">...</a>\\`\n *\n * into:\n *\n * html\\`<a href=${\"/blog/\" + slug}>...</a>\\`\n *\n * Only files inside the app and islands directories are processed.\n *\n * @deprecated Elur core supports partial attribute interpolation natively.\n * Keep this transform only for migrations against older cores\n * (`interpolation: \"legacy\"`).\n */\nexport interface InterpolationPluginOptions {\n appDir?: string;\n islandsDir?: string;\n}\n\nconst HTML_TAG = \"html\";\nconst TEMPLATE_START = \"`\";\n\n/**\n * Scans a `${...}` interpolation starting at `start` (where content[start] is\n * `$` and content[start + 1] is `{`), honoring nested braces, strings and\n * escape sequences. Returns the index just past the closing `}`.\n */\nfunction scanInterpolation(content: string, start: number): number {\n let depth = 1;\n let i = start + 2;\n while (i < content.length && depth > 0) {\n const c = content[i];\n if (c === \"\\\\\") {\n i += 2;\n continue;\n }\n if (c === '\"' || c === \"'\" || c === \"`\") {\n const q = c;\n i++;\n while (i < content.length) {\n if (content[i] === \"\\\\\") {\n i += 2;\n continue;\n }\n if (content[i] === q) break;\n i++;\n }\n i++;\n continue;\n }\n if (c === \"{\") depth++;\n else if (c === \"}\") depth--;\n i++;\n }\n return i;\n}\n\n/**\n * Scans a quoted attribute value starting at `start` (where content[start] is\n * the quote character). Handles escapes, `${...}` interpolations with nested\n * braces, and nested quotes. Returns the index just past the closing quote,\n * the raw inner text (escapes preserved as in the source) and whether the\n * value contains at least one interpolation.\n */\nfunction scanQuotedValue(\n content: string,\n start: number,\n quote: string,\n): { end: number; inside: string; hasInterp: boolean } {\n let i = start + 1;\n let inside = \"\";\n let hasInterp = false;\n while (i < content.length) {\n const c = content[i];\n if (c === \"\\\\\") {\n inside += c + (content[i + 1] ?? \"\");\n i += 2;\n continue;\n }\n if (c === quote) {\n i++;\n break;\n }\n if (c === \"$\" && content[i + 1] === \"{\") {\n const end = scanInterpolation(content, i);\n inside += content.slice(i, end);\n i = end;\n hasInterp = true;\n continue;\n }\n inside += c;\n i++;\n }\n return { end: i, inside, hasInterp };\n}\n\n/**\n * Converts the inner text of a quoted attribute value (which may contain\n * `${...}` interpolations) into a JS expression. Literal parts are JSON\n * encoded; interpolations keep their raw expression text.\n *\n * Examples:\n * /blog/${slug} -> \"/blog/\" + (slug)\n * ${slug} -> (slug)\n * tag ${cls({a:1})} -> \"tag \" + (cls({a:1}))\n */\nfunction valueToExpression(value: string): string {\n const parts: string[] = [];\n let i = 0;\n let literal = \"\";\n const flush = () => {\n if (literal) {\n parts.push(JSON.stringify(unescapeAttributeLiteral(literal)));\n literal = \"\";\n }\n };\n\n while (i < value.length) {\n if (value[i] === \"\\\\\") {\n literal += value[i] + (value[i + 1] ?? \"\");\n i += 2;\n continue;\n }\n if (value[i] === \"$\" && value[i + 1] === \"{\") {\n flush();\n const end = scanInterpolation(value, i);\n const expr = value.slice(i + 2, end - 1).trim();\n if (expr) parts.push(`(${expr})`);\n i = end;\n continue;\n }\n literal += value[i];\n i++;\n }\n flush();\n\n if (parts.length === 0) return '\"\"';\n if (parts.length === 1) return parts[0] as string;\n return parts.join(\" + \");\n}\n\n/**\n * Unescapes escape sequences that appear inside a JS template literal so the\n * JSON.stringify output matches the runtime string value.\n */\nfunction unescapeAttributeLiteral(literal: string): string {\n const escapes: Record<string, string> = {\n n: \"\\n\",\n t: \"\\t\",\n r: \"\\r\",\n };\n let out = \"\";\n let i = 0;\n while (i < literal.length) {\n const c = literal[i];\n if (c === \"\\\\\" && i + 1 < literal.length) {\n const next = literal[i + 1];\n if (next in escapes) {\n out += escapes[next];\n i += 2;\n continue;\n }\n out += next;\n i += 2;\n continue;\n }\n out += c;\n i++;\n }\n return out;\n}\n\n/**\n * Rewrites quoted attribute values that contain interpolations inside html``\n * templates, leaving everything else untouched.\n */\nfunction transformTemplateContent(content: string): string {\n let out = \"\";\n let i = 0;\n const n = content.length;\n\n while (i < n) {\n const lt = content.indexOf(\"<\", i);\n if (lt === -1) {\n out += content.slice(i);\n break;\n }\n out += content.slice(i, lt);\n i = lt;\n\n // HTML comments: copy verbatim.\n if (content.startsWith(\"<!--\", i)) {\n const end = content.indexOf(\"-->\", i + 4);\n if (end === -1) {\n out += content.slice(i);\n break;\n }\n out += content.slice(i, end + 3);\n i = end + 3;\n continue;\n }\n\n // Closing tags, doctype, CDATA, processing instructions: copy verbatim.\n if (content[i + 1] === \"/\" || content[i + 1] === \"!\" || content[i + 1] === \"?\") {\n const gt = content.indexOf(\">\", i + 1);\n if (gt === -1) {\n out += content.slice(i);\n break;\n }\n out += content.slice(i, gt + 1);\n i = gt + 1;\n continue;\n }\n\n // Opening tag. Copy the tag name, then walk its attributes.\n let j = i + 1;\n while (j < n && /[a-zA-Z0-9-]/.test(content[j])) j++;\n out += content.slice(i, j);\n i = j;\n\n while (i < n) {\n let ws = \"\";\n while (i < n && /\\s/.test(content[i])) {\n ws += content[i];\n i++;\n }\n if (i >= n) {\n out += ws;\n break;\n }\n if (content[i] === \">\") {\n out += ws + \">\";\n i++;\n break;\n }\n if (content[i] === \"/\" && content[i + 1] === \">\") {\n out += ws + \"/>\";\n i += 2;\n break;\n }\n // Interpolation in the tag body (dynamic attrs/spread): copy verbatim.\n if (content[i] === \"$\" && content[i + 1] === \"{\") {\n const end = scanInterpolation(content, i);\n out += ws + content.slice(i, end);\n i = end;\n continue;\n }\n\n // Attribute name.\n let nameStart = i;\n while (i < n && !/[\\s=/>\"'$]/.test(content[i])) i++;\n const name = content.slice(nameStart, i);\n if (!name) {\n out += ws + content[i];\n i++;\n continue;\n }\n\n let eqWs = \"\";\n while (i < n && /\\s/.test(content[i])) {\n eqWs += content[i];\n i++;\n }\n\n if (content[i] !== \"=\") {\n out += ws + name + eqWs;\n continue;\n }\n\n i++; // consume \"=\"\n let valWs = \"\";\n while (i < n && /\\s/.test(content[i])) {\n valWs += content[i];\n i++;\n }\n\n const quote = content[i];\n if (quote === '\"' || quote === \"'\") {\n const { end, inside, hasInterp } = scanQuotedValue(content, i, quote);\n if (hasInterp) {\n // Skip values that are a single full interpolation: Elur handles\n // `attr=\"${expr}\"` natively, so only partial interpolations need the\n // rewrite.\n const first = scanInterpolation(inside, 0);\n const fullValue =\n inside.startsWith(\"${\") &&\n first === inside.length &&\n !inside.slice(2, first - 1).includes(\"${\");\n if (!fullValue) {\n // Elur needs the interpolation to start right after \"=\" (no space),\n // so the whitespace before the original value is dropped.\n out += ws + name + eqWs + \"=\" + \"${\" + valueToExpression(inside) + \"}\";\n i = end;\n continue;\n }\n out += ws + name + eqWs + \"=\" + valWs + content.slice(i, end);\n } else {\n out += ws + name + eqWs + \"=\" + valWs + content.slice(i, end);\n }\n i = end;\n continue;\n }\n\n // Unquoted value: copy up to whitespace, \">\" or \"/>\".\n let v = \"\";\n while (\n i < n &&\n !/\\s/.test(content[i]) &&\n content[i] !== \">\" &&\n !(content[i] === \"/\" && content[i + 1] === \">\")\n ) {\n v += content[i];\n i++;\n }\n out += ws + name + eqWs + \"=\" + valWs + v;\n }\n }\n\n return out;\n}\n\n/**\n * @deprecated Use the native partial attribute interpolation of Elur core\n * (core >= 3.3). Kept for legacy migrations and direct consumers.\n */\nexport function transformPartialInterpolations(source: string): string {\n let result = \"\";\n let i = 0;\n while (i < source.length) {\n // Find the next html` sequence.\n const htmlIndex = source.indexOf(HTML_TAG, i);\n if (htmlIndex === -1) {\n result += source.slice(i);\n break;\n }\n result += source.slice(i, htmlIndex + HTML_TAG.length);\n i = htmlIndex + HTML_TAG.length;\n\n // Skip whitespace before the backtick.\n while (i < source.length && /\\s/.test(source[i])) {\n result += source[i];\n i++;\n }\n if (i >= source.length || source[i] !== TEMPLATE_START) {\n continue;\n }\n result += source[i];\n i++;\n\n // Parse the template literal until the matching backtick.\n let depth = 1;\n let templateContent = \"\";\n while (i < source.length && depth > 0) {\n const char = source[i];\n if (char === \"\\\\\") {\n templateContent += char + source[i + 1];\n i += 2;\n continue;\n }\n if (char === TEMPLATE_START) {\n depth--;\n if (depth === 0) {\n i++;\n break;\n }\n }\n if (char === \"$\") {\n // Look ahead for ${...}\n if (source[i + 1] === \"{\") {\n const end = scanInterpolation(source, i);\n templateContent += source.slice(i, end);\n i = end;\n continue;\n }\n }\n templateContent += char;\n i++;\n }\n\n const transformed = transformTemplateContent(templateContent);\n result += transformed;\n result += TEMPLATE_START;\n }\n return result;\n}\n\nexport function elurJsInterpolationPlugin(options: InterpolationPluginOptions = {}): Plugin {\n const appDir = options.appDir ?? \"src/app\";\n const islandsDir = options.islandsDir ?? \"src/islands\";\n return {\n name: \"elur-kit-interpolation\",\n enforce: \"pre\",\n transform(code, id) {\n if (!id.endsWith(\".ts\") && !id.endsWith(\".js\")) return;\n if (!id.includes(appDir) && !id.includes(islandsDir)) return;\n if (!code.includes(\"html`\")) return;\n const transformed = transformPartialInterpolations(code);\n if (transformed === code) return;\n return { code: transformed, map: null };\n },\n };\n}\n","import { mkdir, readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { dirname, extname, relative, resolve, sep } from \"node:path\";\nimport { shouldUseLegacyInterpolation, transformPartialInterpolations, type InterpolationMode } from \"../vite/interpolation-plugin.js\";\n\nexport interface TransformProjectOptions {\n root: string;\n appDir: string;\n islandsDir?: string;\n /**\n * Absolute path to the transformed tree root. The tree mirrors the project\n * layout relative to the common ancestor of `appDir`/`islandsDir`, so\n * relative imports between app and islands keep resolving. Relative imports\n * that escape that ancestor are compensated for the added directory depth.\n */\n outDir: string;\n /**\n * How the legacy interpolation transform is handled (default: \"auto\").\n * With a Elur core that supports partial attribute interpolation natively\n * the transform is not applied; use \"legacy\" for migrations against older\n * cores and \"off\" to never transform.\n */\n interpolation?: InterpolationMode;\n}\n\n/**\n * Copy app (and optionally islands) source files to a transformed directory,\n * rewriting partial Elur attribute interpolations so they can be imported\n * by the SSG/SSR build without requiring manual syntax changes.\n */\nasync function collectTsFiles(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n const files: string[] = [];\n for (const entry of entries) {\n const path = resolve(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await collectTsFiles(path)));\n } else if (entry.isFile() && extname(path) === \".ts\") {\n files.push(path);\n }\n }\n return files;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") return [];\n throw err;\n }\n}\n\nfunction segments(rel: string): string[] {\n return rel.split(/[\\\\/]+/).filter(Boolean);\n}\n\n/** Number of path segments in `rel`. */\nfunction depth(rel: string): number {\n return segments(rel).length;\n}\n\n/** Common ancestor directory of two paths (both absolute). */\nfunction commonBase(a: string, b: string): string {\n const sa = segments(a);\n const sb = segments(b);\n const prefix: string[] = [];\n for (let i = 0; i < Math.min(sa.length, sb.length); i++) {\n if (sa[i] === sb[i]) prefix.push(sa[i]);\n else break;\n }\n return resolve(\"/\" + prefix.join(sep));\n}\n\n/**\n * Absolute path of the transformed app directory inside the mirror tree,\n * matching where `transformProjectFiles` copies the app files.\n */\nexport function transformedAppDir(\n root: string,\n appDir: string,\n islandsDir: string | undefined,\n outDir: string,\n): string {\n const absAppDir = resolve(root, appDir);\n const absIslandsDir = islandsDir ? resolve(root, islandsDir) : absAppDir;\n return resolve(outDir, relative(commonBase(absAppDir, absIslandsDir), absAppDir));\n}\n\n/**\n * Rewrites relative import specifiers in non-template regions so they resolve\n * to the same targets from the transformed location.\n *\n * Imports that stay inside the mirrored subtree need no changes. Imports that\n * escape it are moved `delta` levels: a positive delta prepends that many\n * `../`, a negative one strips leading `../` segments.\n */\nfunction compensateRelativeImports(source: string, delta: number, maxUps: number): string {\n if (delta === 0) return source;\n const prepend = \"..\".repeat(delta) + \"/\";\n const strip = -delta;\n return source.replace(\n /(?:(\\bfrom\\s*)|(\\bimport\\s*\\()|(\\bimport\\s+)|(\\bexport\\s*\\*\\s*from\\s*))([\"'])(\\.[^\"']*)\\5/g,\n (_match, fromKw, importCall, importKw, exportStar, quote, specifier) => {\n let ups = 0;\n let idx = 0;\n while (specifier.startsWith(\"../\", idx)) {\n ups++;\n idx += 3;\n }\n // Imports crossing the mirrored subtree boundary (more `..` than the\n // file's depth below the mirror base) point outside the tree.\n const crosses = ups > maxUps;\n let spec = specifier;\n if (crosses && delta > 0) {\n spec = prepend + spec;\n } else if (crosses && delta < 0) {\n let removed = 0;\n while (removed < strip && spec.startsWith(\"../\")) {\n spec = spec.slice(3);\n removed++;\n }\n if (removed < strip && spec === \"..\") {\n spec = spec.slice(0, -2);\n removed++;\n }\n if (!spec.startsWith(\".\")) spec = \"./\" + spec;\n }\n return (fromKw || importCall || importKw || exportStar) + quote + spec + quote;\n },\n );\n}\n\n/**\n * Applies import compensation to every region of `source` that is not inside\n * an `html` template literal, so attribute strings like `from \"./x.js\"` are\n * never rewritten.\n */\nfunction rewriteImportsOutsideTemplates(source: string, delta: number, maxUps: number): string {\n if (delta === 0) return source;\n let result = \"\";\n let i = 0;\n while (i < source.length) {\n const htmlIndex = source.indexOf(\"html\", i);\n if (htmlIndex === -1) {\n result += compensateRelativeImports(source.slice(i), delta, maxUps);\n break;\n }\n let j = htmlIndex + 4;\n while (j < source.length && /\\s/.test(source[j])) j++;\n if (source[j] !== \"`\") {\n result += compensateRelativeImports(source.slice(i, htmlIndex + 4), delta, maxUps);\n i = htmlIndex + 4;\n continue;\n }\n result += compensateRelativeImports(source.slice(i, htmlIndex + 4), delta, maxUps);\n // Copy the template literal verbatim (interpolations included).\n let depth = 1;\n let k = j + 1;\n while (k < source.length && depth > 0) {\n const c = source[k];\n if (c === \"\\\\\") {\n k += 2;\n continue;\n }\n if (c === \"`\") {\n depth--;\n if (depth === 0) break;\n }\n if (c === \"$\" && source[k + 1] === \"{\") {\n // Jump over the interpolation, honoring nested braces.\n let braceDepth = 1;\n let l = k + 2;\n while (l < source.length && braceDepth > 0) {\n if (source[l] === \"{\") braceDepth++;\n else if (source[l] === \"}\") braceDepth--;\n l++;\n }\n k = l;\n continue;\n }\n k++;\n }\n if (k >= source.length) {\n result += source.slice(j);\n break;\n }\n result += source.slice(j, k + 1);\n i = k + 1;\n }\n return result;\n}\n\nexport async function transformProjectFiles(options: TransformProjectOptions): Promise<void> {\n const { root, appDir, islandsDir, outDir } = options;\n const dirs = islandsDir ? [appDir, islandsDir] : [appDir];\n const files: string[] = [];\n for (const dir of dirs) {\n files.push(...(await collectTsFiles(resolve(root, dir))));\n }\n\n const absAppDir = resolve(root, appDir);\n const absIslandsDir = islandsDir ? resolve(root, islandsDir) : absAppDir;\n const base = commonBase(absAppDir, absIslandsDir);\n\n // Transformed files sit `delta` levels further from root than originals.\n const delta = depth(relative(root, outDir)) - depth(relative(root, base));\n\n for (const file of files) {\n const source = await readFile(file, \"utf8\");\n let output = source;\n if (source.includes(\"html`\") && shouldUseLegacyInterpolation(options.interpolation ?? \"auto\")) {\n const transformed = transformPartialInterpolations(source);\n if (transformed !== source) {\n output = transformed;\n }\n }\n const rel = relative(root, file);\n if (rel.startsWith(\"..\")) {\n continue;\n }\n const baseDepth = depth(relative(base, dirname(file)));\n output = rewriteImportsOutsideTemplates(output, delta, baseDepth);\n const outFile = resolve(outDir, relative(base, file));\n await mkdir(dirname(outFile), { recursive: true });\n await writeFile(outFile, output, \"utf8\");\n }\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\n// Capture the global AbortController at module load time so it's immune to\n// test frameworks that replace or delete globalThis.AbortController.\nconst GlobalAbortController =\n (globalThis as { AbortController?: typeof AbortController }).AbortController ?? AbortController;\n\nexport function incomingMessageToRequest(req: IncomingMessage, body?: BodyInit | null): Request {\n const headers = new Headers();\n for (let index = 0; index < req.rawHeaders.length; index += 2) {\n headers.append(req.rawHeaders[index], req.rawHeaders[index + 1]);\n }\n\n const controller = new GlobalAbortController();\n req.once(\"aborted\", () => controller.abort());\n req.once(\"close\", () => {\n if (!req.complete) controller.abort();\n });\n\n const protocol = (req.socket as typeof req.socket & { encrypted?: boolean }).encrypted ? \"https\" : \"http\";\n const init: RequestInit = {\n method: req.method ?? \"GET\",\n headers,\n signal: controller.signal,\n };\n if (body !== undefined && body !== null && init.method !== \"GET\" && init.method !== \"HEAD\") init.body = body;\n\n return new Request(`${protocol}://${headers.get(\"host\") ?? \"localhost\"}${req.url ?? \"/\"}`, init);\n}\n\n/**\n * Writes a Web `Response` to a Node `ServerResponse`, streaming the body.\n *\n * Unlike `res.end(Buffer.from(await response.arrayBuffer()))`, this forwards\n * chunks as they are produced — required for streaming SSR responses to reach\n * the client progressively. Buffered (non-stream) bodies behave exactly as\n * before. Honors backpressure (`drain`) and cancels the upstream stream when\n * the client disconnects (`close` before `finish`).\n */\nexport async function sendWebResponse(res: ServerResponse, response: Response): Promise<void> {\n const headers = Object.fromEntries(response.headers.entries());\n if (response.body !== null) {\n // Chunk boundaries are decided as the body is read; a Content-Length\n // captured earlier would be wrong for streams. Transfer-Encoding is\n // managed by Node itself (it chunks when no length is set) — forwarding\n // it would duplicate the header (`chunked, chunked`).\n delete headers[\"content-length\"];\n delete headers[\"transfer-encoding\"];\n }\n res.writeHead(response.status, headers);\n\n const body = response.body;\n if (!body) {\n res.end();\n return;\n }\n\n const reader = body.getReader();\n let done = false;\n const onClose = () => {\n if (!done) void reader.cancel().catch(() => {});\n };\n res.once(\"close\", onClose);\n\n try {\n for (;;) {\n const { done: readDone, value } = await reader.read();\n if (readDone) break;\n if (value && value.byteLength > 0 && !res.write(value)) {\n // Socket buffer is full: wait for it to drain before reading more.\n await new Promise<void>((resolveDrain) => res.once(\"drain\", resolveDrain));\n }\n }\n done = true;\n res.end();\n } catch {\n done = true;\n // The client went away or the upstream stream failed: tear the socket\n // down instead of leaving a half-written response hanging.\n res.destroy();\n } finally {\n res.removeListener(\"close\", onClose);\n }\n}\n","// --- Structured logger with request ID and Server-Timing (plan §12.3) ---\n//\n// Provides a structured logger that:\n// - Generates a unique request ID per request.\n// - Attaches the request ID to all log entries.\n// - Supports structured fields (not just string messages).\n// - Redacts sensitive data (cookies, auth headers, tokens).\n// - Supports Server-Timing header accumulation.\n//\n// OpenTelemetry/analytics are external integrations — no automatic telemetry.\n\nimport { randomUUID } from \"node:crypto\";\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\nconst SENSITIVE_HEADERS = new Set([\n \"cookie\",\n \"authorization\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-auth-token\",\n]);\n\nexport interface LogEntry {\n level: LogLevel;\n message: string;\n requestId?: string;\n timestamp: string;\n fields?: Record<string, unknown>;\n}\n\nexport interface ServerTimingMetric {\n name: string;\n description?: string;\n durationMs: number;\n}\n\nexport class StructuredLogger {\n private minLevel: LogLevel;\n private requestId: string;\n private timings: ServerTimingMetric[] = [];\n private entries: LogEntry[] = [];\n\n constructor(options: { minLevel?: LogLevel; requestId?: string } = {}) {\n this.minLevel = options.minLevel ?? (process.env.NODE_ENV === \"production\" ? \"info\" : \"debug\");\n this.requestId = options.requestId ?? randomUUID();\n }\n\n /** Returns the request ID for this logger instance. */\n getRequestId(): string {\n return this.requestId;\n }\n\n /** Logs a debug message. */\n debug(message: string, fields?: Record<string, unknown>): void {\n this.log(\"debug\", message, fields);\n }\n\n /** Logs an info message. */\n info(message: string, fields?: Record<string, unknown>): void {\n this.log(\"info\", message, fields);\n }\n\n /** Logs a warning. */\n warn(message: string, fields?: Record<string, unknown>): void {\n this.log(\"warn\", message, fields);\n }\n\n /** Logs an error. */\n error(message: string, fields?: Record<string, unknown>): void {\n this.log(\"error\", message, fields);\n }\n\n /** Records a Server-Timing metric. */\n timing(name: string, durationMs: number, description?: string): void {\n this.timings.push({ name, durationMs, description });\n }\n\n /** Starts a timer and returns a function to stop it and record the timing. */\n startTimer(name: string, description?: string): () => void {\n const start = performance.now();\n return () => {\n this.timing(name, performance.now() - start, description);\n };\n }\n\n /** Returns the Server-Timing header value. */\n getServerTimingHeader(): string {\n return this.timings\n .map((t) => {\n const desc = t.description ? `;desc=\"${t.description}\"` : \"\";\n return `${t.name};dur=${t.durationMs.toFixed(1)}${desc}`;\n })\n .join(\", \");\n }\n\n /** Returns all log entries collected so far. */\n getEntries(): readonly LogEntry[] {\n return this.entries;\n }\n\n private log(level: LogLevel, message: string, fields?: Record<string, unknown>): void {\n if (LEVEL_PRIORITY[level] < LEVEL_PRIORITY[this.minLevel]) return;\n\n const entry: LogEntry = {\n level,\n message,\n requestId: this.requestId,\n timestamp: new Date().toISOString(),\n fields: fields ? redactSensitive(fields) : undefined,\n };\n\n this.entries.push(entry);\n\n // Output to console in development, structured JSON in production.\n if (process.env.NODE_ENV === \"production\") {\n const output = JSON.stringify(entry);\n if (level === \"error\") console.error(output);\n else if (level === \"warn\") console.warn(output);\n else console.log(output);\n } else {\n const prefix = `[${level.toUpperCase()}]`;\n const fieldsStr = entry.fields ? \" \" + JSON.stringify(entry.fields) : \"\";\n const output = `${prefix} ${message}${fieldsStr}`;\n if (level === \"error\") console.error(output);\n else if (level === \"warn\") console.warn(output);\n else console.log(output);\n }\n }\n}\n\n/**\n * Redacts sensitive fields from a log fields object.\n * Recursively redacts keys that match sensitive header names.\n */\nfunction redactSensitive(fields: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(fields)) {\n const lowerKey = key.toLowerCase();\n if (SENSITIVE_HEADERS.has(lowerKey)) {\n result[key] = \"[REDACTED]\";\n } else if (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n result[key] = redactSensitive(value as Record<string, unknown>);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Creates a logger for a request, optionally using the request's\n * X-Request-ID header if present.\n */\nexport function createRequestLogger(request?: Request, minLevel?: LogLevel): StructuredLogger {\n const requestId = request?.headers.get(\"X-Request-ID\") ?? undefined;\n return new StructuredLogger({ minLevel, requestId });\n}\n","import { access } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { loadConfigFromFile } from \"vite\";\nimport type { Adapter } from \"../adapters/index.js\";\nimport type { ImageFormat } from \"../image/index.js\";\nimport type { ElurKitIntegration } from \"../integrations/index.js\";\nimport { runIntegrationHook } from \"../integrations/index.js\";\nimport type { LogLevel } from \"../runtime/logger.js\";\nimport type { CacheAdapter } from \"../cache/adapter.js\";\nimport type { RedirectRule, RewriteRule, RouteHeadersRule } from \"../router/redirects.js\";\n\nexport type ElurOutputMode = \"static\" | \"server\" | \"hybrid\";\nexport type TrailingSlashMode = \"always\" | \"never\" | \"ignore\";\n\nexport interface ElurConfig {\n root?: string;\n appDir?: string;\n islandsDir?: string;\n contentDir?: string;\n publicDir?: string;\n outDir?: string;\n site?: string;\n base?: string;\n trailingSlash?: TrailingSlashMode;\n output?: ElurOutputMode;\n adapter?: Adapter;\n images?: {\n formats?: ImageFormat[];\n quality?: number;\n strict?: boolean;\n };\n cache?: {\n dir?: string;\n defaultRevalidate?: number;\n /**\n * Pluggable ISR cache adapter (programmatic only — not serializable).\n * Default: filesystem adapter rooted at `cache.dir`.\n */\n adapter?: CacheAdapter;\n };\n security?: {\n allowedOrigins?: string[];\n strictOrigin?: boolean;\n bodyLimit?: number;\n /** Security response headers. Set to `false` to disable defaults. */\n headers?: SecurityHeadersConfig | false;\n };\n /**\n * Client-side router options.\n */\n router?: {\n /**\n * Enable the SPA router on the client (default: `true`). When `false`,\n * no router code is generated and pages without islands ship 0 KB of\n * client JavaScript.\n */\n enabled?: boolean;\n /**\n * Enable link prefetching on hover/focus/pointerdown (default: `true`).\n * Prefetch already opts out on Save-Data and 2g-class connections.\n */\n prefetch?: boolean;\n /**\n * Swap `#app` via idiomorph DOM morphing instead of replacing children\n * (default: `false`, experimental). Hydrated islands and\n * `data-elur-persist` nodes are treated as opaque.\n */\n morph?: boolean;\n /**\n * Emit a `<script type=\"speculationrules\">` block on statically built\n * pages (default: off). Chromium-only progressive enhancement; other\n * browsers ignore it.\n */\n speculation?: \"prefetch\" | \"prerender\";\n /**\n * Show a minimal top progress bar on SPA navigations slower than\n * ~200 ms (default: `false`).\n */\n loadingIndicator?: boolean;\n };\n /**\n * Client JavaScript emission mode (default: `\"modern\"`).\n *\n * - `\"modern\"`: per-page gating — pages without islands emit only the\n * router chunk (or nothing when `router.enabled: false`), and split\n * client builds emit `entry-client.js` + `router.js` separately.\n * - `\"legacy\"`: escape hatch restoring the pre-0%-JS behavior — the\n * combined client entry (hydration + router) is emitted unconditionally\n * on every page.\n */\n js?: \"modern\" | \"legacy\";\n logger?: {\n /** Minimum log level. Default: \"info\" in production, \"debug\" otherwise. */\n level?: LogLevel;\n };\n /** Redirect rules (first match wins; default status 308). */\n redirects?: RedirectRule[];\n /**\n * Opt-in streaming SSR (experimental). When `true`, dynamic routes with a\n * `loading` boundary stream the document shell immediately and swap in the\n * resolved content as a follow-up chunk. Streamed pages bypass the ISR\n * cache. Default: `false` (fully buffered rendering).\n */\n streaming?: boolean;\n /** Rewrite rules: transparently change the pathname before routing. */\n rewrites?: RewriteRule[];\n /** Extra response headers applied to matching request paths. */\n headers?: RouteHeadersRule[];\n integrations?: ElurKitIntegration[];\n}\n\n/** Security headers configuration (runtime-security §14). */\nexport interface SecurityHeadersConfig {\n /** X-Content-Type-Options: nosniff. Default: true. */\n noSniff?: boolean;\n /** Referrer-Policy. Default: \"strict-origin-when-cross-origin\". */\n referrerPolicy?: string;\n /**\n * Content-Security-Policy. Set to a string to enable.\n * Use \"nonce\" placeholder to inject per-request nonces.\n */\n contentSecurityPolicy?: string;\n /** Strict-Transport-Security. Only applied under HTTPS. Default: unset. */\n hsts?: string | true;\n /** X-Frame-Options or CSP frame-ancestors. Default: \"SAMEORIGIN\". */\n frameAncestors?: string;\n /** Permissions-Policy. Default: unset. */\n permissionsPolicy?: string;\n}\n\nexport interface ResolvedElurConfig {\n root: string;\n appDir: string;\n islandsDir: string;\n contentDir: string;\n publicDir: string;\n outDir: string;\n site?: string;\n base: string;\n trailingSlash: TrailingSlashMode;\n output: ElurOutputMode;\n adapter?: Adapter;\n images: {\n formats: ImageFormat[];\n quality: number;\n strict: boolean;\n };\n cache: {\n dir: string;\n defaultRevalidate?: number;\n adapter?: CacheAdapter;\n };\n security: {\n allowedOrigins: string[];\n strictOrigin: boolean;\n bodyLimit: number;\n headers: SecurityHeadersConfig | false;\n };\n router: {\n enabled: boolean;\n prefetch: boolean;\n morph: boolean;\n speculation?: \"prefetch\" | \"prerender\";\n loadingIndicator: boolean;\n };\n /** Client JS emission mode: \"modern\" (0% JS gating) or \"legacy\". */\n js: \"modern\" | \"legacy\";\n logger: {\n level?: LogLevel;\n };\n redirects: RedirectRule[];\n rewrites: RewriteRule[];\n /** Opt-in streaming SSR (experimental). Default: `false`. */\n streaming: boolean;\n headers: RouteHeadersRule[];\n integrations: ElurKitIntegration[];\n configFile?: string;\n}\n\nexport interface LoadElurConfigOptions {\n root?: string;\n configFile?: string;\n command?: \"dev\" | \"build\" | \"preview\" | \"start\" | \"check\" | \"routes\" | \"doctor\";\n mode?: string;\n overrides?: ElurConfig;\n}\n\nexport function defineConfig(config: ElurConfig): ElurConfig {\n return config;\n}\n\nexport async function loadElurConfig(options: LoadElurConfigOptions = {}): Promise<ResolvedElurConfig> {\n const initialRoot = resolve(options.root ?? process.cwd());\n const configFile = options.configFile\n ? resolve(initialRoot, options.configFile)\n : await findConfigFile(initialRoot);\n let loaded: ElurConfig = {};\n\n if (configFile) {\n const result = await loadConfigFromFile(\n { command: options.command === \"build\" ? \"build\" : \"serve\", mode: options.mode ?? \"development\" },\n configFile,\n initialRoot,\n );\n if (!result) throw new Error(`[elur-kit] Could not load config: ${configFile}`);\n loaded = result.config as ElurConfig;\n }\n\n const merged = mergeConfig(loaded, options.overrides ?? {});\n const root = resolve(initialRoot, merged.root ?? \".\");\n const resolved = resolveConfig(root, merged, configFile);\n await runIntegrationHook(resolved.integrations, \"config\", [\n resolved as unknown as Record<string, unknown>,\n { root, command: options.command ?? \"dev\" },\n ]);\n return resolved;\n}\n\nfunction resolveConfig(root: string, config: ElurConfig, configFile?: string): ResolvedElurConfig {\n if (config.site) new URL(config.site);\n const base = normalizeBase(config.base ?? \"/\");\n const imageQuality = config.images?.quality ?? 80;\n if (!Number.isFinite(imageQuality) || imageQuality < 1 || imageQuality > 100) {\n throw new Error(\"[elur-kit] images.quality must be between 1 and 100\");\n }\n\n return {\n root,\n appDir: resolveInside(root, config.appDir ?? \"src/app\", \"appDir\"),\n islandsDir: resolveInside(root, config.islandsDir ?? \"src/islands\", \"islandsDir\"),\n contentDir: resolveInside(root, config.contentDir ?? \"src/content\", \"contentDir\"),\n publicDir: resolveInside(root, config.publicDir ?? \"public\", \"publicDir\"),\n outDir: resolveInside(root, config.outDir ?? \"dist\", \"outDir\"),\n site: config.site,\n base,\n trailingSlash: config.trailingSlash ?? \"ignore\",\n output: config.output ?? \"static\",\n adapter: config.adapter,\n images: {\n formats: config.images?.formats ?? [\"webp\", \"avif\"],\n quality: imageQuality,\n strict: config.images?.strict ?? false,\n },\n cache: {\n dir: resolveInside(root, config.cache?.dir ?? \".elur/cache\", \"cache.dir\"),\n defaultRevalidate: config.cache?.defaultRevalidate,\n adapter: config.cache?.adapter,\n },\n security: {\n allowedOrigins: config.security?.allowedOrigins ?? [],\n strictOrigin: config.security?.strictOrigin ?? false,\n bodyLimit: config.security?.bodyLimit ?? 1_048_576,\n headers: config.security?.headers === false\n ? false\n : config.security?.headers ?? {},\n },\n router: {\n enabled: config.router?.enabled ?? true,\n prefetch: config.router?.prefetch ?? true,\n morph: config.router?.morph ?? false,\n speculation: config.router?.speculation,\n loadingIndicator: config.router?.loadingIndicator ?? false,\n },\n js: config.js ?? \"modern\",\n // No forced level: the StructuredLogger defaults to \"info\" in production\n // and \"debug\" in development when `level` is undefined.\n logger: {\n level: config.logger?.level,\n },\n redirects: config.redirects ?? [],\n rewrites: config.rewrites ?? [],\n streaming: config.streaming ?? false,\n headers: config.headers ?? [],\n integrations: config.integrations ?? [],\n configFile,\n };\n}\n\nfunction mergeConfig(base: ElurConfig, override: ElurConfig): ElurConfig {\n return {\n ...base,\n ...override,\n images: { ...base.images, ...override.images },\n cache: { ...base.cache, ...override.cache },\n security: { ...base.security, ...override.security },\n router: { ...base.router, ...override.router },\n logger: { ...base.logger, ...override.logger },\n // Rule arrays match first-match-wins, so override rules go first: they\n // win over base rules for the same path while base keeps the rest.\n redirects: [...(override.redirects ?? []), ...(base.redirects ?? [])],\n rewrites: [...(override.rewrites ?? []), ...(base.rewrites ?? [])],\n headers: [...(override.headers ?? []), ...(base.headers ?? [])],\n integrations: override.integrations ?? base.integrations,\n };\n}\n\nfunction resolveInside(root: string, path: string, name: string): string {\n const resolved = isAbsolute(path) ? resolve(path) : resolve(root, path);\n const rel = relative(root, resolved);\n if (rel === \"..\" || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {\n throw new Error(`[elur-kit] ${name} must stay inside root: ${resolved}`);\n }\n return resolved;\n}\n\nfunction normalizeBase(base: string): string {\n if (!base.startsWith(\"/\")) throw new Error(\"[elur-kit] base must start with /\");\n return base === \"/\" ? base : `${base.replace(/\\/+$/, \"\")}/`;\n}\n\nconst PREFERRED_CONFIG_FILES = [\"elur.config.ts\", \"elur.config.js\", \"elur.config.mjs\"];\n\nasync function findConfigFile(root: string): Promise<string | undefined> {\n for (const name of PREFERRED_CONFIG_FILES) {\n const path = resolve(root, name);\n try {\n await access(path);\n return path;\n } catch {\n }\n }\n return undefined;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, relative } from \"node:path\";\nimport { scanActions, type ActionRegistry } from \"../action/scan.js\";\nimport type { ResolvedElurConfig } from \"../config/index.js\";\nimport { runIntegrationHook } from \"../integrations/index.js\";\nimport { scanIslands, type IslandModule } from \"../island/scan.js\";\nimport { scanRoutes, type ScannedRoutes } from \"../router/route-scanner.js\";\n\nexport interface AppManifest {\n version: 1;\n root: string;\n routes: ScannedRoutes;\n actions: ActionRegistry;\n islands: IslandModule[];\n base: string;\n output: ResolvedElurConfig[\"output\"];\n}\n\nexport async function createAppManifest(config: ResolvedElurConfig): Promise<AppManifest> {\n const [routes, actions, islands] = await Promise.all([\n scanRoutes(config.appDir),\n scanActions(config.appDir),\n scanIslands(config.islandsDir),\n ]);\n validateManifestRoutes(routes);\n validateIslands(islands);\n const manifest: AppManifest = {\n version: 1,\n root: config.root,\n routes,\n actions,\n islands,\n base: config.base,\n output: config.output,\n };\n await runIntegrationHook(config.integrations, \"routes\", [\n manifest,\n { root: config.root, command: \"build\" },\n ]);\n return manifest;\n}\n\nexport async function writeAppManifest(manifest: AppManifest, path: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, JSON.stringify(toPortableManifest(manifest), null, 2), \"utf8\");\n}\n\nexport async function writeRouteTypes(manifest: AppManifest, path: string): Promise<void> {\n const routePaths = manifest.routes.pages.map((route) => JSON.stringify(route.path));\n const actionNames = Object.values(manifest.actions)\n .flatMap((actions) => Object.keys(actions))\n .filter((name, index, names) => names.indexOf(name) === index)\n .map((name) => JSON.stringify(name));\n const source = [\n `export type ElurRoutePath = ${routePaths.length ? routePaths.join(\" | \") : \"never\"};`,\n `export type ElurActionName = ${actionNames.length ? actionNames.join(\" | \") : \"never\"};`,\n \"export interface ElurRouteParams { [name: string]: string | string[] | undefined }\",\n \"\",\n ].join(\"\\n\");\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, source, \"utf8\");\n}\n\nexport function validateManifestRoutes(routes: ScannedRoutes): void {\n const seen = new Map<string, string>();\n for (const route of routes.pages) {\n registerRoute(seen, route.path, route.pagePath, \"page\");\n assertNotReserved(route.path, route.pagePath);\n }\n for (const route of routes.api) {\n registerRoute(seen, route.path, route.routePath, \"API\");\n assertNotReserved(route.path, route.routePath);\n }\n}\n\nexport function assertClientImportAllowed(id: string, importer?: string): void {\n if (/\\.server\\.[cm]?[jt]sx?$/.test(id)) {\n throw new Error(`[elur-kit] Server-only module imported by client${importer ? ` from ${importer}` : \"\"}: ${id}`);\n }\n}\n\nfunction registerRoute(seen: Map<string, string>, path: string, file: string, kind: string): void {\n const existing = seen.get(path);\n if (existing) {\n throw new Error(`[elur-kit] Duplicate ${kind} route \"${path}\": ${existing} and ${file}`);\n }\n seen.set(path, file);\n}\n\nfunction assertNotReserved(path: string, file: string): void {\n if (path === \"/__elur-js\" || path.startsWith(\"/__elur-js/\") || path === \"/_elur\" || path.startsWith(\"/_elur/\")) {\n throw new Error(`[elur-kit] Reserved route \"${path}\" declared by ${file}`);\n }\n}\n\nfunction validateIslands(islands: readonly IslandModule[]): void {\n const names = new Set<string>();\n for (const island of islands) {\n if (names.has(island.name)) throw new Error(`[elur-kit] Duplicate island name: ${island.name}`);\n names.add(island.name);\n }\n}\n\nfunction toPortableManifest(manifest: AppManifest): AppManifest {\n const relativePath = (path: string | undefined) => path ? relative(manifest.root, path).split(\"\\\\\").join(\"/\") : undefined;\n const routes: ScannedRoutes = {\n pages: manifest.routes.pages.map((route) => ({\n ...route,\n pagePath: relativePath(route.pagePath)!,\n dataPath: relativePath(route.dataPath),\n actionPath: relativePath(route.actionPath),\n loadingPath: relativePath(route.loadingPath),\n layouts: route.layouts.map((layout) => relativePath(layout)!),\n })),\n api: manifest.routes.api.map((route) => ({ ...route, routePath: relativePath(route.routePath)! })),\n error404: manifest.routes.error404 ? {\n ...manifest.routes.error404,\n pagePath: relativePath(manifest.routes.error404.pagePath)!,\n dataPath: relativePath(manifest.routes.error404.dataPath),\n actionPath: relativePath(manifest.routes.error404.actionPath),\n loadingPath: relativePath(manifest.routes.error404.loadingPath),\n layouts: manifest.routes.error404.layouts.map((layout) => relativePath(layout)!),\n } : undefined,\n error500: manifest.routes.error500 ? {\n ...manifest.routes.error500,\n pagePath: relativePath(manifest.routes.error500.pagePath)!,\n dataPath: relativePath(manifest.routes.error500.dataPath),\n actionPath: relativePath(manifest.routes.error500.actionPath),\n loadingPath: relativePath(manifest.routes.error500.loadingPath),\n layouts: manifest.routes.error500.layouts.map((layout) => relativePath(layout)!),\n } : undefined,\n };\n const actions: ActionRegistry = {};\n for (const [page, pageActions] of Object.entries(manifest.actions)) {\n actions[page] = Object.fromEntries(\n Object.entries(pageActions).map(([name, path]) => [name, relativePath(path)!]),\n );\n }\n return {\n ...manifest,\n root: \".\",\n routes,\n actions,\n islands: manifest.islands.map((island) => ({ ...island, filePath: relativePath(island.filePath)! })),\n };\n}\n","// --- Adapter capabilities contract (§8.5) ---\n//\n// Every runtime host (Node CLI, Vite dev, Node/Bun adapters, Vercel, Netlify)\n// declares an explicit `AdapterCapabilities` object. The framework uses it to\n// decide which features are safe to enable: streaming, filesystem access,\n// runtime image transforms, background work, body size limits, ISR persistence.\n//\n// Invalid or incompatible capability combinations fail fast during build.\n\nexport type FilesystemCapability = \"none\" | \"readonly\" | \"persistent\" | \"ephemeral\";\n\nexport interface AdapterCapabilities {\n /** Whether the host supports streaming responses (ReadableStream bodies). */\n streaming: boolean;\n /** Filesystem access model of the host. */\n filesystem: FilesystemCapability;\n /** Whether the host can run image transforms at request time. */\n imageRuntime: boolean;\n /** Whether the host allows background work after the response completes. */\n backgroundWork: boolean;\n /** Maximum request body size in bytes accepted by the host (if any). */\n maxBodySize?: number;\n}\n\nexport interface CapabilityOptions {\n streaming?: boolean;\n filesystem?: FilesystemCapability;\n imageRuntime?: boolean;\n backgroundWork?: boolean;\n maxBodySize?: number;\n}\n\n/** Default capabilities for a full-featured long-lived Node/Bun process. */\nexport const DEFAULT_CAPABILITIES: AdapterCapabilities = {\n streaming: true,\n filesystem: \"persistent\",\n imageRuntime: true,\n backgroundWork: true,\n};\n\n/** Default capabilities for a stateless serverless function (Vercel/Netlify). */\nexport const SERVERLESS_CAPABILITIES: AdapterCapabilities = {\n streaming: true,\n filesystem: \"ephemeral\",\n imageRuntime: false,\n backgroundWork: false,\n maxBodySize: 1_048_576,\n};\n\n/** Default capabilities for an edge runtime (read-only filesystem). */\nexport const EDGE_CAPABILITIES: AdapterCapabilities = {\n streaming: true,\n filesystem: \"readonly\",\n imageRuntime: false,\n backgroundWork: false,\n maxBodySize: 1_048_576,\n};\n\nexport function createCapabilities(options: CapabilityOptions = {}): AdapterCapabilities {\n return {\n ...DEFAULT_CAPABILITIES,\n ...options,\n };\n}\n\n/** True when the host supports streaming responses (streaming !== false). */\nexport function supportsStreaming(capabilities: Pick<AdapterCapabilities, \"streaming\"> = { streaming: true }): boolean {\n return capabilities.streaming !== false;\n}\n\n/** True when the host can write to persistent storage (for ISR/cache/image writes). */\nexport function supportsPersistentStorage(capabilities: Pick<AdapterCapabilities, \"filesystem\">): boolean {\n return capabilities.filesystem === \"persistent\";\n}\n\n/** True when the host exposes a writable filesystem at build/runtime. */\nexport function supportsWritableFilesystem(capabilities: Pick<AdapterCapabilities, \"filesystem\">): boolean {\n return capabilities.filesystem === \"persistent\" || capabilities.filesystem === \"ephemeral\";\n}\n\nexport interface CapabilityDiagnostics {\n ok: boolean;\n problems: string[];\n}\n\n/**\n * Validates a capability declaration and reports incompatible combinations.\n * Used by the build pipeline so invalid hosts fail at build time instead of\n * producing a broken runtime.\n */\nexport function validateCapabilities(\n capabilities: AdapterCapabilities,\n features: { isr?: boolean; images?: boolean; streaming?: boolean } = {},\n): CapabilityDiagnostics {\n const problems: string[] = [];\n\n if (features.isr && !supportsPersistentStorage(capabilities)) {\n problems.push(\n `ISR requires a persistent filesystem; the host declares filesystem=\"${capabilities.filesystem}\".`,\n );\n }\n if (features.images && capabilities.imageRuntime === false && capabilities.filesystem === \"none\") {\n problems.push(\n \"On-demand image transforms require either imageRuntime=true or a readable filesystem; the host has neither.\",\n );\n }\n if (features.streaming && capabilities.streaming === false) {\n problems.push(\"Streaming was requested but the host declares streaming=false.\");\n }\n\n return { ok: problems.length === 0, problems };\n}\n","// --- CLI output formatting ---\n//\n// Lightweight colored output without extra dependencies. Colors are enabled\n// only when stdout is a TTY and NO_COLOR is not set (https://no-color.org).\n//\n// Message shape (sober, Vite/Astro style):\n// ✓ message success\n// → message info / pointer\n// ! message warning\n// ✗ message error\n// [tag] message lifecycle events (dev supervisor)\n//\n// `--quiet` suppresses everything except errors.\n\nimport { networkInterfaces } from \"node:os\";\n\nconst useColor = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;\n\nfunction paint(code: number, text: string): string {\n return useColor ? `\\x1b[${code}m${text}\\x1b[0m` : text;\n}\n\nexport const bold = (text: string): string => paint(1, text);\nexport const dim = (text: string): string => paint(2, text);\nexport const red = (text: string): string => paint(31, text);\nexport const green = (text: string): string => paint(32, text);\nexport const yellow = (text: string): string => paint(33, text);\nexport const cyan = (text: string): string => paint(36, text);\n\nlet quiet = false;\n\n/** Enables quiet mode: only errors are printed. */\nexport function setQuiet(value: boolean): void {\n quiet = value;\n}\n\n/** Success message with a green check. */\nexport function success(message: string): void {\n if (quiet) return;\n console.log(`${green(\"✓\")} ${message}`);\n}\n\n/** Indented info line with a cyan arrow. */\nexport function info(message: string): void {\n if (quiet) return;\n console.log(` ${cyan(\"→\")} ${message}`);\n}\n\n/** Indented detail line (file lists, sub-items). */\nexport function detail(message: string): void {\n if (quiet) return;\n console.log(dim(` - ${message}`));\n}\n\n/** Lifecycle event with a dim bracket tag, e.g. [dev], [change]. */\nexport function event(tag: string, message: string): void {\n if (quiet) return;\n console.log(`${dim(`[${tag}]`)} ${message}`);\n}\n\n/** Warning; suppressed in quiet mode. */\nexport function warn(message: string): void {\n if (quiet) return;\n console.warn(`${yellow(\"!\")} ${message}`);\n}\n\n/** Error; always printed, even in quiet mode. */\nexport function error(message: string): void {\n console.error(`${red(\"✗\")} ${message}`);\n}\n\n/** Formats a byte count as \"640 B\", \"1.5 kB\", \"2.3 MB\". */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} kB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/** Formats a duration as \"45ms\" or \"1.23s\". */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) return `${Math.round(ms)}ms`;\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\n/** Build phase line: checkmark + label + dim duration. */\nexport function phase(label: string, durationMs: number): void {\n if (quiet) return;\n console.log(` ${green(\"✓\")} ${label} ${dim(formatDuration(durationMs))}`);\n}\n\nexport interface FileEntry {\n path: string;\n bytes: number;\n}\n\nconst MAX_FILE_ROWS = 20;\nconst SHOWN_FILE_ROWS = 10;\n\n/**\n * Renders the generated-file list as aligned \"path size\" rows (plain text,\n * no color). With more than MAX_FILE_ROWS entries, shows the SHOWN_FILE_ROWS\n * largest plus a \"… and N more\" line.\n */\nexport function fileRows(files: FileEntry[], max = MAX_FILE_ROWS, shown = SHOWN_FILE_ROWS): string[] {\n const sorted = files.length > max\n ? [...files].sort((a, b) => b.bytes - a.bytes)\n : files;\n const visible = sorted.slice(0, files.length > max ? shown : sorted.length);\n const pathWidth = Math.max(...visible.map((f) => f.path.length), 0);\n const sizeWidth = Math.max(...visible.map((f) => formatBytes(f.bytes).length), 0);\n const rows = visible.map(\n (f) => `${f.path.padEnd(pathWidth)} ${formatBytes(f.bytes).padStart(sizeWidth)}`,\n );\n const hidden = files.length - visible.length;\n if (hidden > 0) rows.push(`… and ${hidden} more`);\n return rows;\n}\n\n/** Prints the generated-file list: dim paths, aligned sizes. */\nexport function fileList(files: FileEntry[]): void {\n if (quiet || files.length === 0) return;\n for (const row of fileRows(files)) {\n const sizeMatch = /^(.*?)( \\S+)$/.exec(row);\n if (sizeMatch) {\n console.log(` ${dim(sizeMatch[1])} ${dim(sizeMatch[2])}`);\n } else {\n console.log(` ${dim(row)}`);\n }\n }\n}\n\nexport interface ServerBannerOptions {\n name: string;\n version: string;\n /** Command label, e.g. \"dev\" or \"preview\". */\n command: string;\n localUrl: string;\n networkUrl?: string;\n}\n\n/**\n * Plain-text lines of the server startup banner (Astro-style, no box):\n *\n * elur-kit v2.4.10 dev server running at:\n * → Local: http://localhost:3000/\n * → Network: http://192.168.1.20:3000/\n */\nexport function serverBannerLines(options: ServerBannerOptions): string[] {\n const lines = [\n `${options.name} ${options.version} ${options.command} server running at:`,\n \"\",\n ];\n const labelWidth = options.networkUrl ? \"Network:\".length : \"Local:\".length;\n lines.push(` → ${\"Local:\".padEnd(labelWidth)} ${options.localUrl}`);\n if (options.networkUrl) {\n lines.push(` → ${\"Network:\".padEnd(labelWidth)} ${options.networkUrl}`);\n }\n return lines;\n}\n\n/** Prints the server startup banner with brand colors. */\nexport function serverBanner(options: ServerBannerOptions): void {\n if (quiet) return;\n const [title, blank, ...urls] = serverBannerLines(options);\n console.log();\n console.log(` ${bold(cyan(title))}`);\n console.log(blank);\n for (const line of urls) {\n const arrowEnd = line.indexOf(\"→\") + 1;\n console.log(` ${cyan(\"→\")}${dim(line.slice(arrowEnd))}`);\n }\n}\n\n/** First external (LAN) IPv4 address, for the Network URL. */\nexport function getNetworkAddress(): string | undefined {\n for (const infos of Object.values(networkInterfaces())) {\n for (const info of infos ?? []) {\n if (info.family === \"IPv4\" && !info.internal) return info.address;\n }\n }\n return undefined;\n}\n","// --- Port fallback for dev/preview servers ---\n//\n// When the requested port is busy (EADDRINUSE), the server retries on\n// port+1, port+2, ... up to MAX_PORT_FALLBACK_TRIES times. Detection is\n// error-driven (the listen itself fails) rather than a bind/close probe, so\n// there is no TOCTOU race between checking and binding.\n//\n// When every candidate port is busy the caller should exit with\n// PORT_UNAVAILABLE_EXIT_CODE so the dev supervisor does not restart-loop.\n\nimport type { Server } from \"node:http\";\n\n/** Max ports tried after the requested one before giving up. */\nexport const MAX_PORT_FALLBACK_TRIES = 20;\n\n/**\n * Exit code used when no port in the fallback range is available. The dev\n * supervisor treats it as fatal and does not restart the worker.\n */\nexport const PORT_UNAVAILABLE_EXIT_CODE = 78;\n\nexport interface ListenFallbackOptions {\n /** Max fallbacks after the requested port. Default: MAX_PORT_FALLBACK_TRIES. */\n maxTries?: number;\n /** Called when a busy port is skipped: (busyPort, nextPort). */\n onFallback?: (busyPort: number, nextPort: number) => void;\n}\n\n/**\n * Listens on host:port, falling back to the next port while the failure is\n * EADDRINUSE. Resolves with the port actually bound. Rejects with the\n * original error for non-port failures or when the range is exhausted.\n */\nexport function listenWithFallback(\n server: Server,\n host: string,\n port: number,\n options: ListenFallbackOptions = {},\n): Promise<number> {\n const maxTries = options.maxTries ?? MAX_PORT_FALLBACK_TRIES;\n return new Promise((resolvePromise, reject) => {\n let attempt = 0;\n let candidate = port;\n // Shared listeners: the per-listen callback style would leave stale\n // \"listening\" handlers behind after a failed attempt, resolving with the\n // original (busy) port when the fallback succeeds.\n const onListening = () => {\n server.removeListener(\"error\", onError);\n resolvePromise(candidate);\n };\n const onError = (err: NodeJS.ErrnoException) => {\n server.removeListener(\"listening\", onListening);\n if (err.code === \"EADDRINUSE\" && attempt < maxTries) {\n attempt++;\n const nextPort = port + attempt;\n options.onFallback?.(nextPort - 1, nextPort);\n tryListen(nextPort);\n return;\n }\n reject(err);\n };\n const tryListen = (next: number) => {\n candidate = next;\n server.once(\"error\", onError);\n server.once(\"listening\", onListening);\n server.listen(candidate, host);\n };\n tryListen(port);\n });\n}\n","import { mkdir, rm, rename, stat, cp, access } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join, resolve, dirname, relative } from \"node:path\";\nimport { build as viteBuild, type InlineConfig, type PluginOption } from \"vite\";\nimport { elurJsInterpolationPlugin, shouldUseLegacyInterpolation, type InterpolationMode } from \"../vite/interpolation-plugin.js\";\n\n// --- Programmatic Vite build orchestration ---\n//\n// Replaces the previous `spawnSync(\"npx\", [\"vite\", \"build\", ...])` approach\n// with direct use of the Vite JavaScript API. Benefits:\n//\n// * No child-process overhead or `npx` resolution latency.\n// * Shared module cache across build phases (faster large builds).\n// * Structured errors instead of exit-code parsing.\n// * Atomic output staging: build into a temp directory, then rename to the\n// final destination so a crashed build never leaves a half-written dist.\n\nexport interface ClientBuildOptions {\n /** Project root (absolute). */\n root: string;\n /**\n * Absolute path to the user's Vite client config (e.g.\n * vite.client.config.ts). When omitted, a default config is generated\n * from `defaultInputs` — the generated entry plus, in split builds, the\n * generated router module — so projects get a working bundle with zero\n * client config.\n */\n userConfigPath?: string;\n /**\n * Default bundle inputs (name → absolute entry path) used when no user\n * config is present. With `entry-client` + `router` keys the output is\n * `entry-client.js` + `router.js`.\n */\n defaultInputs?: Record<string, string>;\n /** Absolute path to the app directory (used by the interpolation plugin). */\n appDir: string;\n /** Absolute path to the islands directory (used by the interpolation plugin). */\n islandsDir: string;\n /** Output directory for the client bundle (absolute). */\n outDir: string;\n /** Optional base path. */\n base?: string;\n /** Optional log prefix. */\n logPrefix?: string;\n /** Suppress bundle logs (kit's and Vite's); errors still surface. */\n quiet?: boolean;\n /**\n * How the legacy interpolation transform is handled (default: \"auto\").\n * With a Elur core that supports partial attribute interpolation natively\n * the transform is not applied; use \"legacy\" for migrations against older\n * cores and \"off\" to never transform.\n */\n interpolation?: InterpolationMode;\n}\n\nexport interface ClientBuildResult {\n /** Output directory (same as `outDir` input). */\n outDir: string;\n /** Number of chunks/assets emitted, if reported by Vite. */\n outputCount: number;\n}\n\n/**\n * Build the client hydration bundle using the Vite JavaScript API.\n *\n * The user's config is loaded programmatically and the elur interpolation\n * plugin is injected so partial attribute interpolations inside islands are\n * transformed before reaching the browser.\n */\nexport async function buildClientBundle(options: ClientBuildOptions): Promise<ClientBuildResult> {\n const log = options.logPrefix ?? \"[client]\";\n const quiet = options.quiet ?? false;\n if (!quiet) console.log(`${log} Building hydration bundle...`);\n\n const userConfig = options.userConfigPath\n ? await loadUserConfig(options.userConfigPath, options.root)\n : defaultClientConfig(options.defaultInputs);\n const pluginOptions: PluginOption = shouldUseLegacyInterpolation(options.interpolation ?? \"auto\")\n ? elurJsInterpolationPlugin({\n appDir: options.appDir,\n islandsDir: options.islandsDir,\n })\n : [];\n\n const config: InlineConfig = {\n ...userConfig,\n root: options.root,\n base: options.base ?? userConfig.base ?? \"/\",\n logLevel: quiet ? \"silent\" : userConfig.logLevel,\n build: {\n ...(userConfig.build ?? {}),\n outDir: options.outDir,\n emptyOutDir: true,\n },\n plugins: [...(userConfig.plugins ?? []), pluginOptions],\n configFile: false,\n };\n\n const result = await viteBuild(config);\n const outputs = Array.isArray(result) ? result : [result];\n const outputCount = outputs.reduce(\n (n, r) => n + (\"output\" in r ? (r.output?.length ?? 0) : 0),\n 0,\n );\n if (!quiet) console.log(`${log} ✓ ${outputCount} asset(s) emitted → ${relative(options.root, options.outDir)}`);\n return { outDir: options.outDir, outputCount };\n}\n\nexport async function loadUserConfig(path: string, _root: string): Promise<InlineConfig> {\n const mod = await import(path);\n const raw = mod.default ?? mod;\n const resolved = typeof raw === \"function\" ? await raw({ command: \"build\", mode: \"production\" }) : raw;\n return (resolved && typeof resolved.then === \"function\" ? await resolved : resolved) ?? {};\n}\n\n/**\n * Resolves a user Vite config's `build.rollupOptions.input` to a list of\n * absolute entry paths. Used to detect whether the bundle will emit the\n * generated router module as its own chunk (split build) or not (legacy\n * single-entry bundle — the router stays embedded in the entry).\n */\nexport async function resolveClientInputs(userConfigPath: string, root: string): Promise<string[]> {\n const config = await loadUserConfig(userConfigPath, root);\n const input = config.build?.rollupOptions?.input;\n if (!input || typeof input === \"string\") {\n return input ? [resolve(root, input)] : [];\n }\n const list = Array.isArray(input) ? input : Object.values(input);\n return list\n .filter((v): v is string => typeof v === \"string\")\n .map((v) => resolve(root, v));\n}\n\n/**\n * The synthesized client bundle config used when the project does not ship\n * its own `vite.client.config.*`: named inputs with `[name].js` filenames in\n * ES format — the same contract the docs give to hand-written client\n * configs, so `entry-client` → `entry-client.js` and `router` → `router.js`.\n */\nfunction defaultClientConfig(defaultInputs?: Record<string, string>): InlineConfig {\n return {\n build: {\n rollupOptions: {\n input: defaultInputs ?? {},\n output: { entryFileNames: \"[name].js\", format: \"es\" },\n },\n },\n };\n}\n\n// --- Atomic output staging ---\n\nexport interface AtomicStageOptions {\n /** Final destination directory (absolute). */\n outDir: string;\n /** Build into this temp directory first, then rename to `outDir`. */\n tempDir?: string;\n /** Whether to preserve existing content in `outDir` during the swap. */\n keepExisting?: boolean;\n}\n\nexport interface AtomicStage {\n tempDir: string;\n /** Call after the build succeeds to atomically swap temp → outDir. */\n commit: () => Promise<void>;\n /** Call on failure to clean up the temp directory. */\n rollback: () => Promise<void>;\n}\n\n/**\n * Prepare an atomic staging directory for build output.\n *\n * Usage:\n * const stage = await beginAtomicStage({ outDir });\n * try {\n * await buildInto(stage.tempDir);\n * await stage.commit();\n * } catch (err) {\n * await stage.rollback();\n * throw err;\n * }\n */\nexport async function beginAtomicStage(options: AtomicStageOptions): Promise<AtomicStage> {\n const outDir = resolve(options.outDir);\n const tempDir = resolve(options.tempDir ?? join(dirname(outDir), `.${basename(outDir)}.tmp-${process.pid}`));\n\n // Start from a clean temp directory.\n await rm(tempDir, { recursive: true, force: true });\n await mkdir(tempDir, { recursive: true });\n\n const commit = async () => {\n // Backup the existing output if requested, then swap.\n const backup = options.keepExisting && existsSync(outDir) ? `${outDir}.bak-${process.pid}` : undefined;\n if (backup) {\n await rm(backup, { recursive: true, force: true });\n await safeRename(outDir, backup);\n }\n try {\n await safeRename(tempDir, outDir);\n } catch (err) {\n // On some platforms, renaming across mount points fails. Fall back to a\n // recursive copy + clean, which is not atomic but still correct.\n if (isCrossDevice(err)) {\n await cp(tempDir, outDir, { recursive: true, force: true });\n await rm(tempDir, { recursive: true, force: true });\n } else {\n if (backup) await safeRename(backup, outDir);\n throw err;\n }\n }\n if (backup) await rm(backup, { recursive: true, force: true });\n };\n\n const rollback = async () => {\n await rm(tempDir, { recursive: true, force: true });\n };\n\n return { tempDir, commit, rollback };\n}\n\nfunction basename(path: string): string {\n const parts = path.split(/[\\\\/]+/).filter(Boolean);\n return parts[parts.length - 1] ?? \"output\";\n}\n\nasync function safeRename(src: string, dest: string): Promise<void> {\n await rm(dest, { recursive: true, force: true });\n try {\n await rename(src, dest);\n } catch (err) {\n if (isCrossDevice(err)) {\n await cp(src, dest, { recursive: true, force: true });\n await rm(src, { recursive: true, force: true });\n } else {\n throw err;\n }\n }\n}\n\nfunction isCrossDevice(err: unknown): boolean {\n const code = (err as NodeJS.ErrnoException)?.code;\n return code === \"EXDEV\";\n}\n\n// --- Public asset copy ---\n\nexport interface CopyPublicAssetsOptions {\n /** Absolute path to the public directory. */\n publicDir: string;\n /** Absolute path to the output directory. */\n outDir: string;\n}\n\n/**\n * Copy the public directory into the output directory.\n * Returns the number of files copied.\n */\nexport async function copyPublicAssets(options: CopyPublicAssetsOptions): Promise<number> {\n try {\n await access(options.publicDir);\n const s = await stat(options.publicDir);\n if (!s.isDirectory()) return 0;\n } catch {\n return 0;\n }\n await mkdir(options.outDir, { recursive: true });\n await cp(options.publicDir, options.outDir, { recursive: true, force: true });\n return countFiles(options.outDir);\n}\n\nasync function countFiles(dir: string): Promise<number> {\n const { readdir } = await import(\"node:fs/promises\");\n let count = 0;\n async function walk(d: string): Promise<void> {\n const entries = await readdir(d, { withFileTypes: true });\n for (const entry of entries) {\n const path = join(d, entry.name);\n if (entry.isDirectory()) await walk(path);\n else count++;\n }\n }\n await walk(dir);\n return count;\n}\n","import type { ApiRoute, PageRoute } from \"../router/route-scanner.js\";\n\nexport interface MatchResult {\n route: PageRoute;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n}\n\n/**\n * Match a request pathname against a list of page routes.\n *\n * Routes are sorted by specificity (static > dynamic > catch-all) before\n * matching, so `/about` wins over `/:slug` even if the catch-all appears first.\n *\n * URL segments are safely decoded (plan §11.1, runtime-security §10).\n */\nexport function matchRoute(\n pathname: string,\n routes: PageRoute[],\n): MatchResult | undefined {\n const cleanPath = pathname.split(\"?\")[0];\n const requestSegments = cleanPath.split(\"/\").filter(Boolean).map(safeDecodeURIComponent);\n\n const sorted = [...routes].sort((a, b) => specificity(b.path) - specificity(a.path));\n\n for (const route of sorted) {\n const routeSegments = route.path.split(\"/\").filter(Boolean);\n const match = tryMatch(requestSegments, routeSegments, route.optionalCatchAll);\n if (match) {\n return { route, params: match, searchParams: new URLSearchParams() };\n }\n }\n\n return undefined;\n}\n\nexport interface ApiMatchResult<T = ApiRoute> {\n route: T;\n params: Record<string, string | string[]>;\n}\n\n/**\n * Match a request pathname against a list of API routes.\n */\nexport function matchApiRoute<T extends { path: string }>(pathname: string, routes: T[]): ApiMatchResult<T> | undefined {\n const cleanPath = pathname.split(\"?\")[0];\n const requestSegments = cleanPath.split(\"/\").filter(Boolean).map(safeDecodeURIComponent);\n\n const sorted = [...routes].sort((a, b) => specificity(b.path) - specificity(a.path));\n\n for (const route of sorted) {\n const routeSegments = route.path.split(\"/\").filter(Boolean);\n const match = tryMatch(requestSegments, routeSegments);\n if (match) {\n return { route, params: match };\n }\n }\n\n return undefined;\n}\n\n/**\n * Safely decodes a URI component. If decoding fails (malformed % sequences),\n * returns the original string rather than throwing (runtime-security §10).\n */\nfunction safeDecodeURIComponent(segment: string): string {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n}\n\nfunction specificity(path: string): number {\n return path.split(\"/\").filter(Boolean).reduce((score, segment) => {\n if (segment.endsWith(\"*\")) return score;\n if (segment.startsWith(\":\")) return score + 1;\n return score + 2;\n }, 0);\n}\n\nfunction tryMatch(\n requestSegments: string[],\n routeSegments: string[],\n optionalCatchAll = false,\n): Record<string, string | string[]> | undefined {\n const params: Record<string, string | string[]> = {};\n\n let i = 0;\n for (let r = 0; r < routeSegments.length; r++) {\n const routeSeg = routeSegments[r];\n\n if (routeSeg.endsWith(\"*\")) {\n // Catch-all consumes the rest of the request segments.\n const name = routeSeg.slice(1, -1);\n const rest = requestSegments.slice(i);\n // For optional catch-all, empty rest is OK.\n if (rest.length === 0 && !optionalCatchAll) return undefined;\n params[name] = rest.length > 0 ? rest : [];\n return params;\n }\n\n if (routeSeg.startsWith(\":\")) {\n const requestSeg = requestSegments[i];\n if (requestSeg === undefined) return undefined;\n params[routeSeg.slice(1)] = requestSeg;\n i++;\n continue;\n }\n\n if (routeSeg !== requestSegments[i]) {\n return undefined;\n }\n i++;\n }\n\n if (i !== requestSegments.length) return undefined;\n return params;\n}\n","// --- Middleware ---\n//\n// Convention: `src/middleware.ts` in the project root exports a default\n// function and an optional `config` with a `matcher` array.\n//\n// import type { Middleware } from \"@elurjs/kit\";\n//\n// export default function middleware(request: Request) {\n// if (!request.headers.get(\"Cookie\")?.includes(\"session=\")) {\n// return Response.redirect(new URL(\"/login\", request.url), 307);\n// }\n// }\n//\n// export const config = { matcher: [\"/dashboard/:path*\", \"/admin/:path*\"] };\n//\n// The middleware runs before routing. Return a `Response` to short-circuit\n// (redirect, rewrite, 401, etc.). Return `undefined` or nothing to continue.\n// Use `next()` to pass headers to the loader.\n\nimport { matchRoute } from \"../ssr/match.js\";\nimport type { PageRoute } from \"../router/route-scanner.js\";\n\n/** The middleware function signature. */\nexport type Middleware = (request: Request, context: MiddlewareContext) =>\n | Response\n | void\n | Promise<Response | void>;\n\n/** Context passed to the middleware function. */\nexport interface MiddlewareContext {\n /** Helper to continue to the next handler. Can attach headers, params, and locals. */\n next(options?: {\n headers?: Record<string, string>;\n params?: Record<string, string | string[]>;\n locals?: Record<string, unknown>;\n }): void;\n /** Matched route params (only available if the path matches a page route). */\n params?: Record<string, string | string[]>;\n /** Per-request locals (populated by middleware, available to loaders/actions). */\n locals?: Record<string, unknown>;\n}\n\n/** Configuration for the middleware module. */\nexport interface MiddlewareConfig {\n /** Path patterns that trigger the middleware. Supports `:param` and `:param*`. */\n matcher?: string[];\n}\n\nexport interface LoadedMiddleware {\n handler: Middleware;\n config: MiddlewareConfig;\n}\n\n/** Result of running middleware: either a response to short-circuit with, or continue. */\nexport type MiddlewareResult =\n | { kind: \"response\"; response: Response }\n | {\n kind: \"continue\";\n headers?: Record<string, string>;\n params?: Record<string, string | string[]>;\n locals?: Record<string, unknown>;\n };\n\n/**\n * Loads the user's `src/middleware.ts` module. Returns `null` if no middleware\n * file exists. Distinguishes \"file not found\" from \"file has errors\" (§6):\n * an import error is not silently treated as \"no middleware\".\n */\nexport async function loadMiddleware(root: string): Promise<LoadedMiddleware | null> {\n const candidates = [\n `${root}/src/middleware.ts`,\n `${root}/middleware.ts`,\n ];\n\n for (const path of candidates) {\n try {\n const mod = await import(path);\n const handler = (mod.default ?? mod.middleware) as Middleware | undefined;\n if (typeof handler !== \"function\") continue;\n const config = (mod.config ?? {}) as MiddlewareConfig;\n return { handler, config };\n } catch (err) {\n // Distinguish \"module not found\" from actual errors.\n // If the error is a module resolution error for this specific file,\n // it means the file doesn't exist — try the next candidate.\n // If it's a syntax/runtime error, rethrow so the user sees it.\n // Note: Bun's ResolveMessage is not `instanceof Error`, so match on the\n // message property instead of relying on the class hierarchy.\n const msg =\n typeof err === \"object\" && err !== null && \"message\" in err\n ? String((err as { message: unknown }).message)\n : String(err);\n if (\n msg.includes(\"Cannot find module\") ||\n msg.includes(\"Cannot find package\") ||\n msg.includes(\"ENOENT\") ||\n msg.includes(\"Module not found\")\n ) {\n // File doesn't exist — try next candidate.\n continue;\n }\n // Actual error in the middleware file — rethrow (§6).\n throw new Error(`[elur-kit] Error loading middleware: ${msg}`, { cause: err });\n }\n }\n\n return null;\n}\n\n/**\n * Checks if a pathname matches any of the middleware's matcher patterns.\n * If no matcher is configured, the middleware runs for every request.\n *\n * Catch-all patterns (`:param*`) match both the base path and any sub-paths,\n * e.g. `/dashboard/:path*` matches `/dashboard` and `/dashboard/settings/users`.\n */\nexport function matchesMiddleware(pathname: string, config: MiddlewareConfig): boolean {\n if (!config.matcher || config.matcher.length === 0) return true;\n\n const cleanPath = pathname.split(\"?\")[0];\n\n for (const pattern of config.matcher) {\n // Exact match.\n if (pattern === cleanPath) return true;\n\n // Check for catch-all: `/foo/:bar*` should also match `/foo`.\n const catchAllMatch = pattern.match(/^(.*)\\/:[\\w]+\\*$/);\n if (catchAllMatch) {\n const base = catchAllMatch[1];\n if (cleanPath === base) return true;\n }\n\n // Use matchRoute for param matching.\n const pseudoRoutes: PageRoute[] = [{\n path: pattern,\n pagePath: \"\",\n params: [],\n layouts: [],\n }];\n if (matchRoute(cleanPath, pseudoRoutes)) return true;\n }\n\n return false;\n}\n\n/**\n * Runs the middleware for a request. Returns the result indicating whether to\n * short-circuit with a response or continue with propagated headers/params/locals.\n *\n * Per §6: cleanup runs in `finally`, response short-circuits the pipeline,\n * headers/params/locals are propagated to downstream handlers.\n */\nexport async function runMiddleware(\n middleware: LoadedMiddleware,\n request: Request,\n params?: Record<string, string | string[]>,\n): Promise<MiddlewareResult> {\n let nextHeaders: Record<string, string> | undefined;\n let nextParams: Record<string, string | string[]> | undefined;\n let nextLocals: Record<string, unknown> | undefined;\n const cleanups: Array<() => void | Promise<void>> = [];\n\n const context: MiddlewareContext = {\n next(options) {\n if (options?.headers) nextHeaders = options.headers;\n if (options?.params) nextParams = options.params;\n if (options?.locals) nextLocals = options.locals;\n },\n params,\n locals: {},\n };\n\n try {\n const result = await middleware.handler(request, context);\n\n if (result instanceof Response) {\n return { kind: \"response\", response: result };\n }\n\n return {\n kind: \"continue\",\n headers: nextHeaders,\n params: nextParams ?? params,\n locals: nextLocals,\n };\n } finally {\n // Run any cleanup functions (§6). Errors in cleanup are logged but\n // do not propagate to the caller.\n for (const cleanup of cleanups) {\n try {\n await cleanup();\n } catch (err) {\n console.error(\"[elur-kit] middleware cleanup error:\", err);\n }\n }\n }\n}\n","/**\n * Represents a failed action result. Returned by `fail()` from server actions.\n *\n * The `__elur_js_action_failure` marker is set on the instance so the server can\n * detect it even when the value crosses a bundling boundary (e.g. the CLI is\n * bundled separately from the user's action modules).\n */\nexport class ActionFailure<TData = unknown> {\n readonly __elur_js_action_failure = true;\n constructor(\n public status: number,\n public data: TData,\n ) {}\n}\n\n/**\n * Represents a redirect returned by a server action. Returned by `redirect()`.\n */\nexport class RedirectResponse {\n readonly __elur_js_action_redirect = true;\n constructor(\n public status: number,\n public location: string,\n ) {}\n}\n\n/**\n * Helper to return a validation/error response from a server action.\n *\n * Both argument orders are accepted:\n *\n * ```ts\n * return fail(400, { email: \"Invalid email\" });\n * return fail({ email: \"Invalid email\" }, 400);\n * return fail({ email: \"Invalid email\" }); // defaults to status 400\n * ```\n */\nexport function fail<TData>(\n statusOrData: number | TData,\n dataOrStatus?: TData | number,\n): ActionFailure<unknown> {\n if (typeof statusOrData === \"number\") {\n return new ActionFailure(statusOrData, dataOrStatus as TData);\n }\n return new ActionFailure((dataOrStatus as number) ?? 400, statusOrData);\n}\n\n/**\n * Helper to return a redirect from a server action.\n *\n * Both argument orders are accepted:\n *\n * ```ts\n * return redirect(303, \"/login\");\n * return redirect(\"/login\"); // defaults to status 303\n * ```\n */\nexport function redirect(\n statusOrLocation: number | string,\n locationOrStatus?: string | number,\n): RedirectResponse {\n if (typeof statusOrLocation === \"number\") {\n return new RedirectResponse(statusOrLocation, locationOrStatus as string);\n }\n return new RedirectResponse((locationOrStatus as number) ?? 303, statusOrLocation);\n}\n\n/**\n * Type guard for action failures. Uses the marker field so it works across\n * bundling boundaries where `instanceof` fails.\n */\nexport function isActionFailure(value: unknown): value is ActionFailure {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as { __elur_js_action_failure?: unknown }).__elur_js_action_failure === true\n );\n}\n\n/**\n * Type guard for redirects. Uses the marker field so it works across bundling\n * boundaries where `instanceof` fails.\n */\nexport function isRedirectResponse(value: unknown): value is RedirectResponse {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as { __elur_js_action_redirect?: unknown }).__elur_js_action_redirect === true\n );\n}\n\n// --- Public error sanitization (production-safe 500 responses) ---\n\n/**\n * A stable, publicly safe error description. Never includes stacks, internal\n * paths or messages that could leak secrets or filesystem details.\n */\nexport interface PublicErrorInfo {\n /** Stable machine-readable code for the response body. */\n code: string;\n /** Stable public message. In non-production this may include the raw message. */\n message: string;\n status: number;\n}\n\n/**\n * Maps an arbitrary thrown value to a public-safe error info. By default the\n * public message is generic; `includeDetail` (dev/verbose mode) appends the\n * original `Error.message` for local debugging.\n */\nexport function toPublicErrorInfo(error: unknown, options: { includeDetail?: boolean } = {}): PublicErrorInfo {\n const code = \"INTERNAL_SERVER_ERROR\";\n const status = 500;\n if (options.includeDetail && error instanceof Error && error.message) {\n return { code, status, message: error.message };\n }\n return { code, status, message: \"Internal Server Error\" };\n}\n\n/**\n * Builds a production-safe JSON error Response. Logs the raw error separately\n * (never reflected in the response body) and keeps the request id header.\n */\nexport function publicErrorResponse(\n error: unknown,\n options: { includeDetail?: boolean; requestId?: string } = {},\n): Response {\n const info = toPublicErrorInfo(error, options);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n };\n if (options.requestId) headers[\"X-Request-Id\"] = options.requestId;\n return new Response(JSON.stringify({ error: info }), {\n status: info.status,\n headers,\n });\n}\n\n/** True when the error should be re-thrown as control flow instead of a 500. */\nexport function isFirstClassResponse(error: unknown): error is Response {\n return typeof Response !== \"undefined\" && error instanceof Response;\n}\n","// --- Origin verification (CSRF protection for server actions) ---\n//\n// Server actions accept POST requests from the browser. Without origin\n// verification, any third-party site could submit forged requests to\n// `/__elur-js/actions` on behalf of a logged-in user (CSRF).\n//\n// Strategy: compare the request's `Origin` (or `Referer` fallback) host against\n// the target `Host` header. Same-origin requests pass; cross-origin requests\n// are rejected with 403 unless the origin is explicitly allow-listed.\n//\n// Requests without `Origin` AND without `Referer` (e.g. curl, server-to-server)\n// are accepted by default for DX, unless `strictOrigin: true` is configured.\n\nexport interface OriginCheckOptions {\n /** Extra origins allowed to call actions (e.g. preview deployments). */\n allowedOrigins?: string[];\n /**\n * When true, requests missing both `Origin` and `Referer` are rejected.\n * Defaults to false so curl/server-to-server calls keep working.\n */\n strictOrigin?: boolean;\n}\n\n/**\n * Returns the host:port of a URL string, or undefined if it cannot be parsed.\n */\nfunction originOf(urlString: string | null | undefined): string | undefined {\n if (!urlString) return undefined;\n try {\n const url = new URL(urlString);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") return undefined;\n return url.origin;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Verifies that a request originates from the same host (or an allow-listed\n * origin). Returns an error message when the request must be rejected, or\n * undefined when it is allowed.\n *\n * @param request The incoming Request to actions.\n * @param options Origin check configuration.\n */\nexport function verifyOrigin(\n request: Request,\n options: OriginCheckOptions = {},\n): string | undefined {\n const targetOrigin = originOf(request.url);\n if (!targetOrigin) return \"Invalid target URL\";\n\n const origin = request.headers.get(\"Origin\");\n const referer = request.headers.get(\"Referer\");\n if (!origin && !referer) {\n return options.strictOrigin\n ? \"Missing Origin and Referer headers\"\n : undefined;\n }\n\n const sourceOrigin = origin ? originOf(origin) : originOf(referer);\n if (!sourceOrigin) return origin ? \"Invalid Origin header\" : \"Invalid Referer header\";\n if (sourceOrigin === targetOrigin) return undefined;\n\n if (options.allowedOrigins?.some((allowed) => originOf(allowed) === sourceOrigin)) return undefined;\n\n return `Cross-origin request blocked: source \"${sourceOrigin}\" != target \"${targetOrigin}\"`;\n}\n\n/** Builds a 403 Response for a rejected origin. */\nexport function originForbidden(message: string): Response {\n return new Response(message, {\n status: 403,\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\" },\n });\n}\n","// --- CacheAdapter: pluggable cache with single-flight, SWR, tags (§9.2) ---\n//\n// Implements the CacheAdapter interface from the runtime-security design:\n// - SHA-256 keys for normalized identity\n// - temp + atomic rename writes\n// - single-flight per process (deduplicates concurrent gets for same key)\n// - stale-while-revalidate (serves stale, refreshes in background)\n// - tag-based invalidation\n// - size limits and periodic cleanup\n//\n// The filesystem adapter is the default. External adapters (Redis, KV, etc.)\n// can implement the same interface and be plugged in via config.\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, writeFile, readdir, stat } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\n// Types\n\nexport interface CacheEntry {\n html: string;\n generatedAt: number;\n revalidate: number;\n tags?: string[];\n version?: string;\n}\n\nexport interface CacheWriteOptions {\n revalidate: number;\n tags?: string[];\n version?: string;\n}\n\nexport interface CacheAdapter {\n get(key: string): Promise<CacheEntry | null>;\n set(key: string, value: CacheEntry, options: CacheWriteOptions): Promise<void>;\n delete(key: string): Promise<void>;\n invalidateTags(tags: readonly string[]): Promise<void>;\n}\n\n// Helpers\n\n/** Computes a SHA-256 key from a normalized identity string. */\nexport function cacheKey(...parts: string[]): string {\n return createHash(\"sha256\").update(parts.join(\"\\n\")).digest(\"hex\");\n}\n\n// Filesystem CacheAdapter\n\nexport interface FsCacheAdapterOptions {\n cacheDir: string;\n /** Max entries before cleanup runs. Default: 1000. */\n maxEntries?: number;\n /** Max age in ms for entries. Default: 24h. */\n maxAgeMs?: number;\n}\n\nexport function createFsCacheAdapter(options: FsCacheAdapterOptions): CacheAdapter {\n const { cacheDir } = options;\n const maxEntries = options.maxEntries ?? 1000;\n const maxAgeMs = options.maxAgeMs ?? 24 * 60 * 60 * 1000;\n\n // Single-flight: deduplicates concurrent gets for the same key.\n const inFlight = new Map<string, Promise<CacheEntry | null>>();\n\n // Tag index: maps tag -> set of cache keys.\n // Persisted to a JSON file for cross-process visibility.\n const tagIndexPath = join(cacheDir, \"_tag-index.json\");\n\n async function loadTagIndex(): Promise<Record<string, string[]>> {\n try {\n const raw = await readFile(tagIndexPath, \"utf8\");\n return JSON.parse(raw) as Record<string, string[]>;\n } catch {\n return {};\n }\n }\n\n async function saveTagIndex(index: Record<string, string[]>): Promise<void> {\n await mkdir(dirname(tagIndexPath), { recursive: true });\n const tmp = `${tagIndexPath}.${process.pid}.${randomUUID()}.tmp`;\n try {\n await writeFile(tmp, JSON.stringify(index), \"utf8\");\n await rename(tmp, tagIndexPath);\n } finally {\n await rm(tmp, { force: true });\n }\n }\n\n function entryPath(key: string): string {\n return join(cacheDir, `${key}.html.json`);\n }\n\n async function get(key: string): Promise<CacheEntry | null> {\n // Single-flight: if a get is already in progress for this key, wait for it.\n const existing = inFlight.get(key);\n if (existing) return existing;\n\n const promise = (async () => {\n try {\n const raw = await readFile(entryPath(key), \"utf8\");\n const entry = JSON.parse(raw) as CacheEntry;\n return entry;\n } catch {\n return null;\n }\n })();\n\n inFlight.set(key, promise);\n try {\n return await promise;\n } finally {\n inFlight.delete(key);\n }\n }\n\n async function set(key: string, value: CacheEntry, opts: CacheWriteOptions): Promise<void> {\n const path = entryPath(key);\n await mkdir(dirname(path), { recursive: true });\n\n const entry: CacheEntry = {\n html: value.html,\n generatedAt: value.generatedAt ?? Date.now(),\n revalidate: opts.revalidate,\n tags: opts.tags,\n version: opts.version,\n };\n\n // Atomic write: temp + rename.\n const tmp = `${path}.${process.pid}.${randomUUID()}.tmp`;\n try {\n await writeFile(tmp, JSON.stringify(entry), \"utf8\");\n await rename(tmp, path);\n } finally {\n await rm(tmp, { force: true });\n }\n\n // Update tag index.\n if (opts.tags && opts.tags.length > 0) {\n const index = await loadTagIndex();\n for (const tag of opts.tags) {\n if (!index[tag]) index[tag] = [];\n if (!index[tag].includes(key)) index[tag].push(key);\n }\n await saveTagIndex(index);\n }\n\n // Periodic cleanup.\n await maybeCleanup();\n }\n\n async function del(key: string): Promise<void> {\n await rm(entryPath(key), { force: true });\n }\n\n async function invalidateTags(tags: readonly string[]): Promise<void> {\n if (tags.length === 0) return;\n const index = await loadTagIndex();\n const keysToDelete = new Set<string>();\n for (const tag of tags) {\n const keys = index[tag];\n if (keys) {\n for (const key of keys) keysToDelete.add(key);\n delete index[tag];\n }\n }\n await Promise.all([...keysToDelete].map((key) => del(key)));\n await saveTagIndex(index);\n }\n\n let lastCleanup = 0;\n async function maybeCleanup(): Promise<void> {\n const now = Date.now();\n if (now - lastCleanup < 60_000) return; // at most once per minute\n lastCleanup = now;\n try {\n const files = await readdir(cacheDir);\n let entryCount = 0;\n const toDelete: string[] = [];\n for (const file of files) {\n if (!file.endsWith(\".html.json\")) continue;\n entryCount++;\n const filePath = join(cacheDir, file);\n try {\n const stats = await stat(filePath);\n if (now - stats.mtimeMs > maxAgeMs) {\n toDelete.push(filePath);\n }\n } catch {\n // stat failed, skip\n }\n }\n // If over limit, delete oldest (by mtime).\n if (entryCount - toDelete.length > maxEntries) {\n const candidates: Array<{ path: string; mtime: number }> = [];\n for (const file of files) {\n if (!file.endsWith(\".html.json\")) continue;\n const filePath = join(cacheDir, file);\n if (toDelete.includes(filePath)) continue;\n try {\n const stats = await stat(filePath);\n candidates.push({ path: filePath, mtime: stats.mtimeMs });\n } catch {\n // skip\n }\n }\n candidates.sort((a, b) => a.mtime - b.mtime);\n const excess = entryCount - toDelete.length - maxEntries;\n for (let i = 0; i < excess && i < candidates.length; i++) {\n toDelete.push(candidates[i].path);\n }\n }\n await Promise.all(toDelete.map((p) => rm(p, { force: true })));\n } catch {\n // cleanup is best-effort\n }\n }\n\n return { get, set, delete: del, invalidateTags };\n}\n\n// Stale-while-revalidate wrapper\n\n/**\n * Gets a cached entry. If the entry is stale (past revalidate), serves it\n * immediately and triggers a background revalidation.\n *\n * @param adapter The cache adapter.\n * @param key The cache key.\n * @param revalidate The revalidation function (called if stale or missing).\n * @returns The cache entry (fresh or stale), or null if missing.\n */\nexport async function getWithSWR(\n adapter: CacheAdapter,\n key: string,\n revalidate: () => Promise<CacheEntry | null>,\n): Promise<{ entry: CacheEntry | null; stale: boolean }> {\n const entry = await adapter.get(key);\n if (!entry) {\n // Cache miss: revalidate synchronously.\n const fresh = await revalidate();\n return { entry: fresh, stale: false };\n }\n\n const ageMs = Date.now() - entry.generatedAt;\n const isStale = ageMs >= entry.revalidate * 1000;\n\n if (isStale) {\n // Serve stale, revalidate in background (fire-and-forget).\n revalidate().then(\n (fresh) => {\n if (fresh) {\n adapter.set(key, fresh, {\n revalidate: entry.revalidate,\n tags: entry.tags,\n version: entry.version,\n }).catch((err) => {\n console.error(\"[elur-kit] background cache write failed:\", err);\n });\n }\n },\n (err) => {\n console.error(\"[elur-kit] background revalidation failed:\", err);\n },\n );\n return { entry, stale: true };\n }\n\n return { entry, stale: false };\n}\n","// --- Cache invalidation hooks (runtime-security §9.4) ---\n//\n// Actions can emit tags/paths to invalidate via a generic context. The cache\n// server listens to these hooks and invalidates the appropriate entries.\n// Integrations like elur-query can also listen, but they are NOT a dependency\n// of the cache server.\n//\n// Design:\n// - `CacheInvalidator` is a simple pub/sub for invalidation events.\n// - The runtime registers an invalidator with the cache adapter.\n// - Actions call `invalidateTags()` / `invalidatePaths()` from their context.\n// - The invalidator dispatches to all registered listeners.\n\nexport interface InvalidationEvent {\n tags?: readonly string[];\n paths?: readonly string[];\n /** Source of the invalidation (e.g. action name). */\n source?: string;\n}\n\nexport type InvalidationListener = (event: InvalidationEvent) => void | Promise<void>;\n\n/**\n * A pub/sub hub for cache invalidation events. Actions emit events;\n * the cache adapter (and optionally elur-query or other integrations) listen.\n */\nexport class CacheInvalidator {\n private listeners = new Set<InvalidationListener>();\n\n /** Registers a listener for invalidation events. Returns an unsubscribe function. */\n on(listener: InvalidationListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /** Emits an invalidation event to all listeners. */\n async emit(event: InvalidationEvent): Promise<void> {\n const promises: Array<Promise<void>> = [];\n for (const listener of this.listeners) {\n try {\n const result = listener(event);\n if (result instanceof Promise) {\n // Wrap to prevent unhandled rejection from failing the whole emit.\n promises.push(result.catch((err) => {\n console.error(\"[elur-kit] invalidation listener error:\", err);\n }));\n }\n } catch (err) {\n console.error(\"[elur-kit] invalidation listener error:\", err);\n }\n }\n await Promise.all(promises);\n }\n\n /** Convenience: invalidate by tags. */\n async invalidateTags(tags: readonly string[], source?: string): Promise<void> {\n if (tags.length === 0) return;\n await this.emit({ tags, source });\n }\n\n /** Convenience: invalidate by paths. */\n async invalidatePaths(paths: readonly string[], source?: string): Promise<void> {\n if (paths.length === 0) return;\n await this.emit({ paths, source });\n }\n\n /** Removes all listeners. */\n clear(): void {\n this.listeners.clear();\n }\n}\n\n/** Global default invalidator. The runtime registers the cache adapter here. */\nexport const defaultInvalidator = new CacheInvalidator();\n\n/**\n * Connects a CacheAdapter to the default invalidator so that tag/path\n * invalidation events from actions are dispatched to the cache.\n *\n * Returns an unsubscribe function.\n */\nexport function connectCacheAdapter(\n adapter: {\n invalidateTags: (tags: readonly string[]) => Promise<void>;\n delete?: (key: string) => Promise<void>;\n },\n invalidator: CacheInvalidator = defaultInvalidator,\n): () => void {\n return invalidator.on(async (event) => {\n if (event.tags && event.tags.length > 0) {\n await adapter.invalidateTags(event.tags);\n }\n // Path-based invalidation: the adapter needs to know which cache keys\n // correspond to which paths. This is handled by the runtime mapping\n // paths to cache keys before calling delete().\n if (event.paths && event.paths.length > 0 && adapter.delete) {\n // The runtime should register a path-to-key mapper.\n // For now, we use the path as the cache key directly (SHA-256 of path).\n const { cacheKey } = await import(\"./adapter.js\");\n await Promise.all(event.paths.map((p) => adapter.delete!(cacheKey(p))));\n }\n });\n}\n","import type { ActionRequest } from \"./index.js\";\nimport { isActionFailure, isRedirectResponse, publicErrorResponse } from \"../errors.js\";\nimport { verifyOrigin, originForbidden, type OriginCheckOptions } from \"./origin.js\";\nimport type { ActionContext } from \"./define.js\";\nimport { defaultInvalidator } from \"../cache/invalidation.js\";\nimport {\n encodeActionErrorCookie,\n setActionErrorCookieHeader,\n} from \"./error-store.js\";\n\n/**\n * Resolves a server action by name and optional page scope.\n */\nexport type ActionResolver = (\n name: string,\n page?: string,\n) => Promise<((...args: unknown[]) => unknown) | undefined>;\n\n/** Options shared by `handleActionRequest` callers for CSRF protection. */\nexport interface ActionSecurityOptions extends OriginCheckOptions {\n /** Maximum body size in bytes. Defaults to 1MB (1_048_576). */\n bodyLimit?: number;\n}\n\n/** Default body size limit: 1MB. */\nconst DEFAULT_BODY_LIMIT = 1_048_576;\n\n/**\n * Reads the request body as text, enforcing a maximum size.\n * Returns a 413 response if the body exceeds the limit.\n */\nasync function readBodyWithLimit(\n request: Request,\n limit: number,\n): Promise<{ ok: true; text: string } | { ok: false; response: Response }> {\n const contentLength = request.headers.get(\"Content-Length\");\n if (contentLength && parseInt(contentLength, 10) > limit) {\n return {\n ok: false,\n response: new Response(\"Request body too large\", {\n status: 413,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n // Read the body as a stream with a size cap to prevent memory exhaustion\n // from chunked transfer encoding without Content-Length.\n const reader = request.body?.getReader();\n if (!reader) {\n return { ok: true, text: \"\" };\n }\n const chunks: Uint8Array[] = [];\n let totalSize = 0;\n try {\n for (; ;) {\n const { done, value } = await reader.read();\n if (done) break;\n totalSize += value.byteLength;\n if (totalSize > limit) {\n try { reader.cancel(); } catch { /* ignore */ }\n return {\n ok: false,\n response: new Response(\"Request body too large\", {\n status: 413,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n chunks.push(value);\n }\n } finally {\n try { reader.releaseLock(); } catch { /* ignore */ }\n }\n const total = new Uint8Array(totalSize);\n let offset = 0;\n for (const chunk of chunks) {\n total.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return { ok: true, text: new TextDecoder().decode(total) };\n}\n\nfunction parseFormBody(body: string): Record<string, unknown> {\n const params = new URLSearchParams(body);\n const result: Record<string, unknown> = {};\n for (const [key, value] of params) {\n if (result[key] === undefined) {\n result[key] = value;\n } else if (Array.isArray(result[key])) {\n (result[key] as unknown[]).push(value);\n } else {\n result[key] = [result[key], value];\n }\n }\n return result;\n}\n\nasync function parseActionRequest(\n request: Request,\n bodyLimit: number = DEFAULT_BODY_LIMIT,\n): Promise<\n | { ok: true; name: string; page?: string; args: unknown[]; wantsJson: boolean }\n | { ok: false; response: Response }\n> {\n if (request.method !== \"POST\") {\n return {\n ok: false,\n response: new Response(\"Method not allowed\", {\n status: 405,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n\n const contentType = request.headers.get(\"Content-Type\") ?? \"\";\n const wantsJson = (request.headers.get(\"Accept\") ?? \"\").includes(\"application/json\");\n\n let name: string | undefined;\n let page: string | undefined;\n let args: unknown[] = [];\n\n if (contentType.includes(\"application/json\")) {\n const bodyResult = await readBodyWithLimit(request, bodyLimit);\n if (!bodyResult.ok) return { ok: false, response: bodyResult.response };\n let body: ActionRequest;\n try {\n body = JSON.parse(bodyResult.text) as ActionRequest;\n } catch {\n return {\n ok: false,\n response: new Response(\"Invalid JSON body\", {\n status: 400,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n name = body.name;\n page = body.page;\n args = Array.isArray(body.args) ? body.args : [];\n } else if (\n contentType.includes(\"application/x-www-form-urlencoded\") ||\n contentType.includes(\"multipart/form-data\")\n ) {\n // For multipart, use the native formData() parser after checking\n // Content-Length against the limit. For urlencoded, use our size-capped\n // reader to handle chunked encoding without Content-Length.\n if (contentType.includes(\"multipart/form-data\")) {\n const contentLength = request.headers.get(\"Content-Length\");\n if (contentLength && parseInt(contentLength, 10) > bodyLimit) {\n return {\n ok: false,\n response: new Response(\"Request body too large\", {\n status: 413,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n let form: FormData;\n try {\n form = await request.formData();\n } catch {\n return {\n ok: false,\n response: new Response(\"Invalid form body\", {\n status: 400,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n name = form.get(\"__elur_js_action_name\") as string | null ?? undefined;\n page = form.get(\"__elur_js_action_page\") as string | null ?? undefined;\n const input: Record<string, unknown> = {};\n for (const [key, value] of form) {\n if (key === \"__elur_js_action_name\" || key === \"__elur_js_action_page\") continue;\n input[key] = value;\n }\n args = [input];\n } else {\n const bodyResult = await readBodyWithLimit(request, bodyLimit);\n if (!bodyResult.ok) return { ok: false, response: bodyResult.response };\n const form = parseFormBody(bodyResult.text);\n name = form.__elur_js_action_name as string | undefined;\n page = form.__elur_js_action_page as string | undefined;\n const input: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(form)) {\n if (key === \"__elur_js_action_name\" || key === \"__elur_js_action_page\") continue;\n input[key] = value;\n }\n args = [input];\n }\n } else {\n // Try to parse a plain form body as a fallback for progressive enhancement.\n const bodyResult = await readBodyWithLimit(request, bodyLimit);\n if (!bodyResult.ok) return { ok: false, response: bodyResult.response };\n const form = parseFormBody(bodyResult.text);\n name = form.__elur_js_action_name as string | undefined;\n page = form.__elur_js_action_page as string | undefined;\n const input: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(form)) {\n if (key === \"__elur_js_action_name\" || key === \"__elur_js_action_page\") continue;\n input[key] = value;\n }\n args = [input];\n }\n\n if (!name || typeof name !== \"string\") {\n return {\n ok: false,\n response: new Response(\"Missing action name\", {\n status: 400,\n headers: { \"Content-Type\": \"text/plain\" },\n }),\n };\n }\n\n return { ok: true, name, page, args, wantsJson };\n}\n\n/**\n * Handles a POST request to the server action endpoint.\n *\n * Accepts both JSON requests (`{ name, page?, args }`) and HTML form submissions\n * for progressive enhancement. The provided resolver looks up the action\n * implementation, invokes it with the supplied arguments and returns the result\n * as JSON or redirects back to the request origin for form submissions.\n *\n * Origin verification (CSRF protection) runs before parsing the body: any\n * cross-origin POST is rejected with 403 unless its origin is allow-listed via\n * `security.allowedOrigins`.\n *\n * For progressive-enhancement form submissions that fail, the failure payload\n * is relayed back via a short-lived `__elur_js_action_error` cookie (SameSite=Lax,\n * Max-Age=15s) instead of a query param, so errors do not leak into browser\n * history, server logs or third-party Referer headers.\n */\nexport async function handleActionRequest(\n request: Request,\n resolveAction: ActionResolver,\n security: ActionSecurityOptions = {},\n): Promise<Response> {\n // CSRF: verify same-origin (or allow-listed) before doing any work.\n const originError = verifyOrigin(request, security);\n if (originError) return originForbidden(originError);\n\n const parsed = await parseActionRequest(request, security.bodyLimit ?? DEFAULT_BODY_LIMIT);\n if (!parsed.ok) return parsed.response;\n\n const { name, page, args, wantsJson } = parsed;\n\n try {\n const action = await resolveAction(name, page);\n if (!action) {\n const message = page ? `Action not found: ${name} (page: ${page})` : `Action not found: ${name}`;\n return new Response(message, {\n status: 404,\n headers: { \"Content-Type\": \"text/plain\" },\n });\n }\n\n // defineAction() functions take (input, ctx) and carry __elurAction\n // metadata; legacy plain actions take (...args). Route params are not\n // known at this endpoint (actions resolve by page path), so params and\n // locals start empty — middleware/page context can fill them elsewhere.\n const actionMeta = (action as { __elurAction?: { invalidateTags?: readonly string[]; invalidatePaths?: readonly string[] } }).__elurAction;\n let result: unknown;\n if (actionMeta) {\n const ctx: ActionContext = {\n request,\n signal: request.signal,\n idempotencyKey: request.headers.get(\"Idempotency-Key\") ?? undefined,\n params: {},\n locals: {},\n };\n result = await action(args[0], ctx);\n } else {\n result = await action(...args);\n }\n\n // Cache invalidation (§9.4): actions defined with defineAction() declare\n // invalidateTags/invalidatePaths metadata; dispatch them to connected\n // cache adapters after a successful run (not on ActionFailure).\n if (!isActionFailure(result) && actionMeta) {\n const tags = actionMeta.invalidateTags ?? [];\n const paths = actionMeta.invalidatePaths ?? [];\n if (tags.length > 0 || paths.length > 0) {\n await defaultInvalidator.emit({ tags, paths, source: name });\n }\n }\n\n if (isActionFailure(result)) {\n if (wantsJson) {\n return new Response(JSON.stringify({ __elur_js_action_failure: true, status: result.status, data: result.data }), {\n status: result.status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n // Progressive enhancement: redirect back with the failure in a cookie.\n const referer = request.headers.get(\"Referer\") ?? \"/\";\n const url = new URL(referer, \"http://localhost\");\n const { value } = encodeActionErrorCookie(result.data, result.status);\n return new Response(null, {\n status: 303,\n headers: {\n Location: url.pathname + url.search,\n \"Content-Type\": \"text/plain\",\n \"Set-Cookie\": setActionErrorCookieHeader(value),\n },\n });\n }\n\n if (isRedirectResponse(result)) {\n if (wantsJson) {\n return new Response(\n JSON.stringify({ __elur_js_action_redirect: true, status: result.status, location: result.location }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n }\n return new Response(null, {\n status: result.status,\n headers: { Location: result.location, \"Content-Type\": \"text/plain\" },\n });\n }\n\n if (wantsJson) {\n return new Response(JSON.stringify(result ?? null), {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n // For progressive enhancement (plain form POST), redirect back.\n const referer = request.headers.get(\"Referer\") ?? \"/\";\n return new Response(null, {\n status: 303,\n headers: {\n Location: typeof result === \"string\" ? result : referer,\n \"Content-Type\": \"text/plain\",\n },\n });\n } catch (err) {\n console.error(\"[elur-kit] Action error:\", err);\n return publicErrorResponse(err, { includeDetail: false });\n }\n}\n\nexport { verifyOrigin, originForbidden, type OriginCheckOptions } from \"./origin.js\";\nexport {\n decodeActionErrorCookie,\n clearActionErrorCookieHeader,\n setActionErrorCookieHeader,\n ACTION_ERROR_COOKIE,\n} from \"./error-store.js\";\n","import type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString } from \"../render/render-to-string.js\";\nimport { documentShell, extractAppBody, serializeData } from \"../build/document-shell.js\";\nimport type { PageRoute, ScannedRoutes } from \"../router/route-scanner.js\";\nimport type { BuildConfig } from \"../build/build.js\";\nimport type { PageDataLoad } from \"../types.js\";\nimport { matchRoute } from \"./match.js\";\nimport { renderPage } from \"./render.js\";\n\nexport interface StreamingPageOptions {\n route: PageRoute;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\">;\n importer?: (path: string) => Promise<unknown>;\n actions?: Record<string, string[]>;\n request?: Request;\n}\n\nconst defaultImport = (path: string) => import(path);\n\n/** Builds the concrete URL path for a route pattern given matched params. */\nfunction buildConcretePath(\n routePath: string,\n params: Record<string, string | string[]>,\n): string {\n return routePath.replace(/:([a-zA-Z0-9_]+)(\\*)?/g, (_m, name: string, catchAll?: string) => {\n const value = params[name];\n if (value === undefined || value === null) return \"\";\n return catchAll ? (Array.isArray(value) ? value.join(\"/\") : String(value)) : String(value);\n });\n}\n\nfunction streamingScript(page: string, search: string): string {\n const src = `\n async function __elurJsStreamRender() {\n try {\n const url = \"/__elur-js/render?page=\" + encodeURIComponent(${JSON.stringify(page)}) + \"&search=\" + encodeURIComponent(${JSON.stringify(search)});\n const res = await fetch(url);\n if (!res.ok) throw new Error(\"Streaming render failed: \" + res.status);\n const html = await res.text();\n const app = document.getElementById(\"app\");\n if (app) app.innerHTML = html;\n document.dispatchEvent(new CustomEvent(\"elur:rendered\"));\n } catch (err) {\n console.error(\"[elur-kit] streaming render failed\", err);\n }\n }\n __elurJsStreamRender();\n `;\n return `<script type=\"module\">${src}</script>`;\n}\n\n/**\n * Render a page shell that shows the loading boundary while the real content\n * is fetched and injected by the client.\n *\n * @deprecated Legacy shell + client-fetch approach, only used by the\n * deprecated `createSsrServer`. Real streaming SSR (shell first, resolved\n * content streamed as a swap chunk) lives in `createStreamingResponse`\n * (`src/ssr/stream-response.ts`, exported from the package root).\n */\nexport async function renderStreamingPage(options: StreamingPageOptions): Promise<string> {\n const { route, params, searchParams, config, importer = defaultImport, actions } = options;\n if (!route.loadingPath) {\n throw new Error(\"Cannot stream a page without a loading.ts boundary\");\n }\n\n const { default: Loading } = (await importer(route.loadingPath)) as {\n default: () => ElurTemplate;\n };\n\n const loadingBody = await renderToString(() => Loading());\n const concretePath = buildConcretePath(route.path, params);\n const body = `<div id=\"elur-loading\">${loadingBody}</div>${streamingScript(concretePath, searchParams.toString())}`;\n\n // Apply <html> attributes and head scripts (e.g. data-theme and the no-flash\n // theme script) from the root layout loader so the shell paints correctly\n // before the real content arrives.\n const htmlAttributes: Record<string, string> = {};\n const headScripts: string[] = [];\n const headLinks: string[] = [];\n if (route.layouts.length > 0) {\n const rootLayout = route.layouts[0];\n const dataPath = rootLayout.replace(/layout\\.ts$/, \"layout.data.ts\");\n if (dataPath !== rootLayout) {\n try {\n const mod = (await importer(dataPath)) as { load?: PageDataLoad };\n const layoutData = mod.load ? await mod.load({ params, searchParams, request: options.request }) : undefined;\n if (layoutData && typeof layoutData === \"object\") {\n const attrs = (layoutData as { htmlAttributes?: Record<string, string> }).htmlAttributes;\n if (attrs) Object.assign(htmlAttributes, attrs);\n const scripts = (layoutData as { headScripts?: string[] }).headScripts;\n if (Array.isArray(scripts)) headScripts.push(...scripts);\n const links = (layoutData as { headLinks?: string[] }).headLinks;\n if (Array.isArray(links)) headLinks.push(...links);\n }\n } catch {\n // The root layout loader is optional; ignore failures here.\n }\n }\n }\n\n return documentShell({\n title: \"Loading...\",\n lang: config.lang,\n body,\n data: { __elur_js_streaming: true, page: route.path },\n actions,\n htmlAttributes,\n headScripts,\n headLinks,\n clientEntry: config.clientEntry,\n });\n}\n\nexport interface RenderPageBodyOptions {\n routes: ScannedRoutes;\n pathname: string;\n searchParams: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\" | \"router\" | \"js\">;\n actions?: Record<string, string[]>;\n importer?: (path: string) => Promise<unknown>;\n request?: Request;\n}\n\nexport interface RenderPageBodyResult {\n /** Inner HTML body for the page (without the document shell). */\n body: string;\n /** Page title extracted from the rendered shell. */\n title: string;\n /** Full rendered document shell (used for ISR caching). */\n fullHtml?: string;\n /** `Set-Cookie` value that clears a consumed action error cookie. */\n clearActionErrorCookie?: string;\n /** `<head>` tags (title, meta, OG, twitter) for the SPA router to merge. */\n head?: string;\n /**\n * Serialized contents of `<script id=\"elur-data\">` for this page, when the\n * shell emitted it. Lets the SPA router refresh the inert data script after\n * navigation instead of leaving the initial page's data frozen.\n */\n data?: string;\n /**\n * Serialized contents of `<script id=\"elur-actions\">`, when emitted.\n */\n actions?: string;\n /** First-class Response when a loader threw one (A-22). */\n response?: Response;\n}\n\n/** Thrown by `renderPageBody` when the requested path has no matching route. */\nexport class RouteNotFoundError extends Error {\n constructor(pathname: string) {\n super(`No route found for ${pathname}`);\n this.name = \"RouteNotFoundError\";\n }\n}\n\n/**\n * Render only the inner HTML body for a page. Used by the streaming endpoint\n * to inject the real content into the shell.\n */\nexport async function renderPageBody(options: RenderPageBodyOptions): Promise<RenderPageBodyResult> {\n const { routes, pathname, searchParams, config, actions, importer = defaultImport, request } = options;\n const match = matchRoute(pathname, routes.pages);\n if (!match) {\n throw new RouteNotFoundError(pathname);\n }\n\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams,\n config,\n actions,\n importer,\n request,\n });\n\n // If a loader threw a Response (redirect, 404, etc.), propagate it (A-22).\n if (result.response) {\n return {\n body: \"\",\n title: \"\",\n response: result.response,\n };\n }\n\n const body = extractAppBody(result.html)?.trim()\n ?? result.html.match(/<div id=\"app\">([\\s\\S]*)<\\/div>\\s*(<script|$)/)?.[1]?.trim()\n ?? result.html;\n const titleMatch = result.html.match(/<title[^>]*>([^<]*)<\\/title>/);\n return {\n body,\n title: titleMatch ? titleMatch[1] : result.resolvedTitle ?? \"\",\n fullHtml: result.html,\n clearActionErrorCookie: result.clearActionErrorCookie,\n head: result.head,\n data: result.data !== undefined ? serializeData(result.data) : undefined,\n actions: actions && Object.keys(actions).length > 0 ? serializeData(actions) : undefined,\n };\n}\n","import { realpath, stat } from \"node:fs/promises\";\nimport { extname, resolve, sep } from \"node:path\";\n\nfunction isInside(root: string, candidate: string): boolean {\n return candidate === root || candidate.startsWith(`${root}${sep}`);\n}\n\nfunction decodePathname(pathname: string): string | null {\n try {\n const decoded = decodeURIComponent(pathname);\n if (decoded.includes(\"\\0\") || decoded.includes(\"\\\\\") || /%(?:00|2e|2f|5c)/i.test(decoded)) return null;\n if (decoded.split(\"/\").some((segment) => segment === \"..\")) return null;\n return decoded;\n } catch {\n return null;\n }\n}\n\nexport async function resolveStaticFile(root: string, pathname: string): Promise<string | null> {\n const decoded = decodePathname(pathname);\n if (decoded === null) return null;\n\n const resolvedRoot = resolve(root);\n const relativePath = decoded.replace(/^\\/+/, \"\");\n let candidate = resolve(resolvedRoot, relativePath);\n if (!isInside(resolvedRoot, candidate)) return null;\n\n try {\n const candidateStat = await stat(candidate);\n if (candidateStat.isDirectory()) candidate = resolve(candidate, \"index.html\");\n } catch {\n if (decoded.endsWith(\"/\") || extname(decoded) === \"\") candidate = resolve(candidate, \"index.html\");\n }\n\n if (!isInside(resolvedRoot, candidate)) return null;\n\n try {\n const [canonicalRoot, canonicalCandidate, candidateStat] = await Promise.all([\n realpath(resolvedRoot),\n realpath(candidate),\n stat(candidate),\n ]);\n if (!candidateStat.isFile() || !isInside(canonicalRoot, canonicalCandidate)) return null;\n return canonicalCandidate;\n } catch {\n return null;\n }\n}\n","import type { ResolvedElurConfig } from \"../config/index.js\";\nimport { randomUUID } from \"node:crypto\";\n\n// --- RequestContext: unified per-request runtime context ---\n//\n// Every runtime path (SSR server, CLI preview/dev, adapters, Vite plugin)\n// eventually funnels through a single Web handler that receives a Web Request\n// and returns a Web Response. RequestContext carries the resolved config,\n// route tables, action registry and request-scoped state so handlers do not\n// re-derive this information on every request.\n//\n// Design goals (runtime-security §4):\n// * One type used by every runtime entry point.\n// * No Node-specific APIs on the type — only Web standards.\n// * Carries per-request state: params, locals, cookies, signal, requestId.\n// * response.headers supports multiple Set-Cookie without collapsing them.\n// * signal aborts when the host disconnects (when the platform allows it).\n// * Middleware/loaders/actions share the same context or readonly views.\n\nexport interface RouteTable {\n pages: import(\"../router/route-scanner.js\").PageRoute[];\n api: import(\"../router/route-scanner.js\").ApiRoute[];\n error404?: import(\"../router/route-scanner.js\").PageRoute;\n error500?: import(\"../router/route-scanner.js\").PageRoute;\n}\n\n// --- CookieJar: read cookies from request, write to response ---\n\n/** Read-only access to request cookies. */\nexport interface CookieJar {\n /** Gets a cookie value by name, or undefined if not present. */\n get(name: string): string | undefined;\n /** Returns all cookie name-value pairs. */\n getAll(): Record<string, string>;\n /** Checks if a cookie exists. */\n has(name: string): boolean;\n}\n\n/** Write access to response cookies (Set-Cookie headers). */\nexport interface ResponseCookieJar {\n /** Sets a Set-Cookie header. */\n set(name: string, value: string, options?: CookieOptions): void;\n /** Removes a cookie by setting it expired. */\n clear(name: string, options?: CookieOptions): void;\n /** Returns all Set-Cookie header values accumulated so far. */\n getAll(): string[];\n}\n\nexport interface CookieOptions {\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n maxAge?: number;\n expires?: Date;\n path?: string;\n domain?: string;\n}\n\n/** Mutable response state accumulated during the request lifecycle. */\nexport interface ResponseState {\n status?: number;\n headers: Headers;\n cookies: ResponseCookieJar;\n}\n\n// --- Cookie implementation ---\n\nclass RequestCookieJar implements CookieJar {\n private cookies: Record<string, string>;\n\n constructor(request: Request) {\n this.cookies = parseCookies(request.headers.get(\"Cookie\") ?? \"\");\n }\n\n get(name: string): string | undefined {\n return this.cookies[name];\n }\n\n getAll(): Record<string, string> {\n return { ...this.cookies };\n }\n\n has(name: string): boolean {\n return name in this.cookies;\n }\n}\n\nclass MutableResponseCookieJar implements ResponseCookieJar {\n private entries: string[] = [];\n\n set(name: string, value: string, options: CookieOptions = {}): void {\n this.entries.push(serializeCookie(name, value, options));\n }\n\n clear(name: string, options: CookieOptions = {}): void {\n this.entries.push(serializeCookie(name, \"\", { ...options, maxAge: 0, expires: new Date(0) }));\n }\n\n getAll(): string[] {\n return [...this.entries];\n }\n}\n\nfunction parseCookies(header: string): Record<string, string> {\n const result: Record<string, string> = {};\n if (!header) return result;\n for (const pair of header.split(\";\")) {\n const idx = pair.indexOf(\"=\");\n if (idx === -1) continue;\n const name = pair.slice(0, idx).trim();\n const value = pair.slice(idx + 1).trim();\n result[name] = value;\n }\n return result;\n}\n\nfunction serializeCookie(name: string, value: string, options: CookieOptions): string {\n const parts = [`${name}=${value}`];\n if (options.httpOnly) parts.push(\"HttpOnly\");\n if (options.secure) parts.push(\"Secure\");\n if (options.sameSite) parts.push(`SameSite=${options.sameSite}`);\n if (options.maxAge !== undefined) parts.push(`Max-Age=${options.maxAge}`);\n if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);\n if (options.path) parts.push(`Path=${options.path}`);\n if (options.domain) parts.push(`Domain=${options.domain}`);\n return parts.join(\"; \");\n}\n\nexport interface RequestContextOptions {\n request: Request;\n config: ResolvedElurConfig;\n routes: RouteTable;\n actions: import(\"../action/scan.js\").ActionRegistry;\n /** Public action names serialized into the HTML shell. */\n publicActions: Record<string, string[]>;\n /** Optional module loader for adapter-bundled entries. */\n importer?: (path: string) => unknown | Promise<unknown>;\n /** Whether the render endpoint (/__elur-js/render) is available. */\n renderEndpoint?: boolean;\n /** Whether to bypass the ISR cache (dev mode). */\n noCache?: boolean;\n /** ISR cache directory (absolute). */\n cacheDir?: string;\n /** Default ISR revalidate interval in seconds. */\n defaultRevalidate?: number;\n /** Route params (populated after route matching). */\n params?: Record<string, string | string[] | undefined>;\n /** Per-request locals (populated by middleware). */\n locals?: Record<string, unknown>;\n /** Abort signal for the request (from host disconnect). */\n signal?: AbortSignal;\n /** Request ID (auto-generated if not provided). */\n requestId?: string;\n /** Platform-specific context (e.g. Vercel, Netlify). */\n platform?: unknown;\n /** Matched route (populated after route matching). */\n route?: import(\"../router/route-scanner.js\").PageRoute | import(\"../router/route-scanner.js\").ApiRoute;\n}\n\nexport class RequestContext {\n readonly request: Request;\n readonly url: URL;\n readonly config: ResolvedElurConfig;\n readonly routes: RouteTable;\n readonly actions: import(\"../action/scan.js\").ActionRegistry;\n readonly publicActions: Record<string, string[]>;\n readonly importer?: (path: string) => unknown | Promise<unknown>;\n readonly renderEndpoint: boolean;\n readonly noCache: boolean;\n readonly cacheDir?: string;\n readonly defaultRevalidate?: number;\n\n // Per-request state (runtime-security §4)\n /** Route params derived from the matched route. */\n params: Readonly<Record<string, string | string[] | undefined>>;\n /** Per-request locals, populated by middleware. Not global. */\n locals: Record<string, unknown>;\n /** Read-only access to request cookies. */\n readonly cookies: CookieJar;\n /** Abort signal (from host disconnect when platform allows). */\n readonly signal: AbortSignal;\n /** Unique request ID for logging/correlation. */\n readonly requestId: string;\n /** Platform-specific context (Vercel, Netlify, etc.). */\n readonly platform: unknown;\n /** Matched route after route matching. */\n route?: import(\"../router/route-scanner.js\").PageRoute | import(\"../router/route-scanner.js\").ApiRoute;\n /** Mutable response state accumulated during the request. */\n readonly response: ResponseState;\n\n constructor(options: RequestContextOptions) {\n this.request = options.request;\n this.url = new URL(options.request.url);\n this.config = options.config;\n this.routes = options.routes;\n this.actions = options.actions;\n this.publicActions = options.publicActions;\n this.importer = options.importer;\n this.renderEndpoint = options.renderEndpoint ?? true;\n this.noCache = options.noCache ?? false;\n this.cacheDir = options.cacheDir;\n this.defaultRevalidate = options.defaultRevalidate;\n\n // Per-request state\n this.params = options.params ?? {};\n this.locals = options.locals ?? {};\n this.cookies = new RequestCookieJar(options.request);\n this.signal = options.signal ?? new AbortController().signal;\n this.requestId = options.requestId ?? randomUUID();\n this.platform = options.platform;\n this.route = options.route;\n this.response = {\n status: undefined,\n headers: new Headers(),\n cookies: new MutableResponseCookieJar(),\n };\n }\n\n /** The pathname without a query string. */\n get pathname(): string {\n return this.url.pathname;\n }\n\n /** The HTTP method, uppercased. */\n get method(): string {\n return (this.request.method ?? \"GET\").toUpperCase();\n }\n\n /** Whether the request accepts JSON. */\n get wantsJson(): boolean {\n return (this.request.headers.get(\"Accept\") ?? \"\").includes(\"application/json\");\n }\n\n /** Search params from the request URL. */\n get searchParams(): URLSearchParams {\n return this.url.searchParams;\n }\n\n /** Render config passed to renderPage/renderErrorPage. */\n get renderConfig(): { lang?: string; clientEntry?: string; renderEndpoint?: boolean } {\n return {\n lang: undefined,\n clientEntry: undefined,\n renderEndpoint: this.renderEndpoint,\n };\n }\n\n /** Applies accumulated response state (headers, cookies, status) to a Response. */\n applyToResponse(response: Response): Response {\n const headers = new Headers(response.headers);\n // Merge accumulated headers\n for (const [key, value] of this.response.headers.entries()) {\n headers.set(key, value);\n }\n // Append Set-Cookie values (multiple allowed)\n for (const cookie of this.response.cookies.getAll()) {\n headers.append(\"Set-Cookie\", cookie);\n }\n const status = this.response.status ?? response.status;\n return new Response(response.body, {\n status,\n statusText: response.statusText,\n headers,\n });\n }\n}\n\n// --- ResponseBuilder: small helpers for consistent Web Responses ---\n\nexport function htmlResponse(body: string, status = 200, headers?: HeadersInit): Response {\n return new Response(body, {\n status,\n headers: { \"Content-Type\": \"text/html; charset=utf-8\", ...headers as Record<string, string> },\n });\n}\n\nexport function jsonResponse(data: unknown, status = 200, headers?: HeadersInit): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: { \"Content-Type\": \"application/json; charset=utf-8\", ...headers as Record<string, string> },\n });\n}\n\nexport function textResponse(body: string, status = 200, headers?: HeadersInit): Response {\n return new Response(body, {\n status,\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\", ...headers as Record<string, string> },\n });\n}\n\nexport function notFound(body = \"Not Found\"): Response {\n return textResponse(body, 404);\n}\n\nexport function methodNotAllowed(method: string): Response {\n return textResponse(`Method not allowed: ${method}`, 405);\n}\n\nexport function serverError(body: string): Response {\n return textResponse(body, 500);\n}\n\n// --- Content-type guessing (shared by all static-serving paths) ---\n\nexport function guessContentType(filePath: string): string {\n switch (filePath.slice(filePath.lastIndexOf(\".\") + 1).toLowerCase()) {\n case \"html\": return \"text/html; charset=utf-8\";\n case \"js\": return \"application/javascript; charset=utf-8\";\n case \"mjs\": return \"application/javascript; charset=utf-8\";\n case \"css\": return \"text/css; charset=utf-8\";\n case \"json\": return \"application/json; charset=utf-8\";\n case \"svg\": return \"image/svg+xml\";\n case \"png\": return \"image/png\";\n case \"jpg\":\n case \"jpeg\": return \"image/jpeg\";\n case \"webp\": return \"image/webp\";\n case \"avif\": return \"image/avif\";\n case \"ico\": return \"image/x-icon\";\n case \"woff\": return \"font/woff\";\n case \"woff2\": return \"font/woff2\";\n case \"wasm\": return \"application/wasm\";\n case \"txt\": return \"text/plain; charset=utf-8\";\n default: return \"application/octet-stream\";\n }\n}\n\n// --- Static file serving as a Web handler (reuses resolveStaticFile) ---\n\nimport { readFile, stat } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport { resolveStaticFile } from \"./static.js\";\n\n/**\n * Serves a static file from the root directory with full conditional and\n * range support:\n *\n * - ETag / Last-Modified with If-None-Match / If-Modified-Since → 304.\n * - `Range` with `If-Range` (ETag or date) → 206 with `Content-Range`.\n * - HEAD → same headers as GET without a body.\n * - Invalid/unsatisfiable ranges → 416 with a `Content-Range: bytes (asterisk)/size` header.\n *\n * Files with content hashes in their names (e.g. `app-abc123.js`) get\n * `Cache-Control: public, max-age=31536000, immutable`.\n *\n * @param root Static file root (absolute path).\n * @param pathname Request pathname.\n * @param request Optional request for conditional/range/HEAD handling.\n */\nexport async function serveStaticFile(\n root: string,\n pathname: string,\n request?: Request,\n): Promise<Response | null> {\n const filePath = await resolveStaticFile(root, pathname);\n if (!filePath) return null;\n try {\n const [data, stats] = await Promise.all([\n readFile(filePath),\n stat(filePath),\n ]);\n\n const contentType = guessContentType(filePath);\n const etag = `\"${createHash(\"sha1\").update(data).digest(\"hex\").slice(0, 16)}\"`;\n const lastModified = stats.mtime.toUTCString();\n const isHead = request?.method === \"HEAD\";\n const size = data.byteLength;\n\n const baseHeaders: Record<string, string> = {\n \"Content-Type\": contentType,\n \"Content-Length\": String(size),\n ETag: etag,\n \"Last-Modified\": lastModified,\n \"Accept-Ranges\": \"bytes\",\n };\n\n // Determine Cache-Control: hashed assets get immutable, others get a\n // short revalidation window.\n const baseName = filePath.split(\"/\").pop() ?? \"\";\n const isHashed = /[a-f0-9]{8,}\\.(js|css|woff2?|wasm|png|jpg|jpeg|webp|avif|svg)$/i.test(baseName);\n baseHeaders[\"Cache-Control\"] = isHashed\n ? \"public, max-age=31536000, immutable\"\n : \"public, max-age=0, must-revalidate\";\n\n // Conditional requests (If-None-Match takes precedence).\n const ifNoneMatch = request?.headers.get(\"If-None-Match\");\n if (ifNoneMatch && etagListMatches(ifNoneMatch, etag)) {\n return new Response(null, { status: 304, headers: baseHeaders });\n }\n const ifModifiedSince = request?.headers.get(\"If-Modified-Since\");\n if (ifModifiedSince) {\n const since = Date.parse(ifModifiedSince);\n if (!isNaN(since) && Math.floor(stats.mtime.getTime() / 1000) <= Math.floor(since / 1000)) {\n return new Response(null, { status: 304, headers: baseHeaders });\n }\n }\n\n // Range support with If-Range validation.\n const rangeHeader = request?.headers.get(\"Range\");\n const ifRange = request?.headers.get(\"If-Range\");\n if (rangeHeader && (!ifRange || ifRangeMatches(ifRange, etag, stats.mtime))) {\n const range = parseRange(rangeHeader, size);\n if (range === null) {\n return new Response(null, {\n status: 416,\n headers: { ...baseHeaders, \"Content-Range\": `bytes */${size}` },\n });\n }\n if (range) {\n const [start, end] = range;\n const chunk = data.subarray(start, end + 1);\n const headers: Record<string, string> = {\n ...baseHeaders,\n \"Content-Length\": String(chunk.byteLength),\n \"Content-Range\": `bytes ${start}-${end}/${size}`,\n };\n if (isHead) return new Response(null, { status: 206, headers });\n return new Response(chunk, { status: 206, headers });\n }\n }\n\n if (isHead) return new Response(null, { status: 200, headers: baseHeaders });\n return new Response(data, { status: 200, headers: baseHeaders });\n } catch {\n return null;\n }\n}\n\nfunction etagListMatches(ifNoneMatch: string, etag: string): boolean {\n return ifNoneMatch\n .split(\",\")\n .map((value) => value.trim())\n .some((value) => value === \"*\" || value === etag);\n}\n\nfunction ifRangeMatches(ifRange: string, etag: string, mtime: Date): boolean {\n if (ifRange.startsWith('\"') || ifRange.startsWith(\"W/\")) return ifRange === etag;\n const date = Date.parse(ifRange);\n return !isNaN(date) && Math.floor(mtime.getTime() / 1000) <= Math.floor(date / 1000);\n}\n\n/**\n * Parses a single `Range: bytes=...` header. Returns:\n * - `[start, end]` for a satisfiable range.\n * - `null` when the header is malformed or unsatisfiable (→ 416).\n * - `undefined` when the header is valid but the whole resource is requested\n * (e.g. `bytes=0-` for an empty file) — serve the full body.\n */\nfunction parseRange(rangeHeader: string, size: number): [number, number] | null | undefined {\n const match = /^bytes=(\\d*)-(\\d*)$/.exec(rangeHeader.trim());\n if (!match) return null;\n const startText = match[1];\n const endText = match[2];\n\n if (startText === \"\" && endText === \"\") return null;\n if (startText === \"\") {\n // Suffix range: last N bytes.\n const suffix = Number(endText);\n if (!Number.isSafeInteger(suffix) || suffix <= 0) return null;\n const start = Math.max(0, size - suffix);\n if (size === 0) return undefined;\n return [start, size - 1];\n }\n\n const start = Number(startText);\n if (!Number.isSafeInteger(start) || start < 0 || start >= size) return null;\n const end = endText === \"\" ? size - 1 : Number(endText);\n if (!Number.isSafeInteger(end) || end < start) return null;\n return [start, Math.min(end, size - 1)];\n}\n","// --- Security response headers (runtime-security §14) ---\n//\n// Applies configurable security headers to responses. Defaults are safe and\n// compatible: X-Content-Type-Options, Referrer-Policy, frame-ancestors.\n// HSTS is only applied under HTTPS or when explicitly configured.\n// CSP supports a \"nonce\" placeholder replaced per-request.\n// User-set headers on the response are never overwritten without explicit\n// merge rules.\n\nimport type { SecurityHeadersConfig } from \"../config/index.js\";\n\n/** Default security headers applied when `security.headers` is not `false`. */\nexport const DEFAULT_SECURITY_HEADERS: Required<\n Omit<SecurityHeadersConfig, \"contentSecurityPolicy\" | \"hsts\" | \"permissionsPolicy\">\n> = {\n noSniff: true,\n referrerPolicy: \"strict-origin-when-cross-origin\",\n frameAncestors: \"SAMEORIGIN\",\n};\n\n/**\n * Builds the security headers map from the resolved config.\n * Returns an empty map if headers are disabled.\n */\nexport function buildSecurityHeaders(\n config: SecurityHeadersConfig | false,\n isHttps: boolean,\n nonce?: string,\n): Record<string, string> {\n if (config === false) return {};\n\n const headers: Record<string, string> = {};\n const merged = { ...DEFAULT_SECURITY_HEADERS, ...config };\n\n if (merged.noSniff) {\n headers[\"X-Content-Type-Options\"] = \"nosniff\";\n }\n\n if (merged.referrerPolicy) {\n headers[\"Referrer-Policy\"] = merged.referrerPolicy;\n }\n\n // Frame policy: prefer CSP frame-ancestors if CSP is set, otherwise\n // X-Frame-Options for broader compatibility.\n if (merged.contentSecurityPolicy) {\n let csp = merged.contentSecurityPolicy;\n if (nonce) {\n csp = csp.replace(/\\bnonce\\b/g, `'nonce-${nonce}'`);\n }\n headers[\"Content-Security-Policy\"] = csp;\n } else if (merged.frameAncestors) {\n // Without CSP, use X-Frame-Options for frame protection.\n const fa = merged.frameAncestors;\n if (fa === \"NONE\") {\n headers[\"X-Frame-Options\"] = \"DENY\";\n } else if (fa === \"SAMEORIGIN\") {\n headers[\"X-Frame-Options\"] = \"SAMEORIGIN\";\n } else {\n headers[\"X-Frame-Options\"] = fa;\n }\n }\n\n // HSTS: only under HTTPS or when explicitly set as a string.\n if (merged.hsts === true && isHttps) {\n headers[\"Strict-Transport-Security\"] = \"max-age=15552000; includeSubDomains\";\n } else if (typeof merged.hsts === \"string\") {\n headers[\"Strict-Transport-Security\"] = merged.hsts;\n }\n\n if (merged.permissionsPolicy) {\n headers[\"Permissions-Policy\"] = merged.permissionsPolicy;\n }\n\n return headers;\n}\n\n/**\n * Applies security headers to an existing Response, preserving any\n * user-set headers unless overridden by security config.\n */\nexport function applySecurityHeaders(\n response: Response,\n headers: Record<string, string>,\n): Response {\n if (Object.keys(headers).length === 0) return response;\n\n const newHeaders = new Headers(response.headers);\n for (const [key, value] of Object.entries(headers)) {\n // Don't overwrite a header the response already set explicitly.\n if (!newHeaders.has(key)) {\n newHeaders.set(key, value);\n }\n }\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers: newHeaders,\n });\n}\n","// --- Redirects, rewrites, and route headers (plan §11.1, §10) ---\n//\n// Authors can declare redirects and rewrites in their config:\n//\n// export default defineConfig({\n// redirects: [\n// { from: \"/old-blog/:slug\", to: \"/blog/:slug\", status: 301 },\n// ],\n// rewrites: [\n// { from: \"/api/legacy/*\", to: \"/api/v2/*\" },\n// ],\n// headers: [\n// { path: \"/admin/*\", headers: { \"X-Robots-Tag\": \"noindex\" } },\n// ],\n// });\n//\n// Redirects return a Response with the appropriate status and Location.\n// Rewrites change the pathname before routing (transparent to the user).\n// Route headers are applied to the response for matching paths.\n\nexport interface RedirectRule {\n /** Source path pattern (supports :param and *). */\n from: string;\n /** Destination path (supports :param interpolation). */\n to: string;\n /** HTTP status code (301, 302, 307, 308). Default: 308. */\n status?: 301 | 302 | 307 | 308;\n}\n\nexport interface RewriteRule {\n /** Source path pattern (supports :param and *). */\n from: string;\n /** Destination path (supports :param interpolation). */\n to: string;\n}\n\nexport interface RouteHeadersRule {\n /** Path pattern to match (supports :param and *). */\n path: string;\n /** Headers to apply to matching responses. */\n headers: Record<string, string>;\n}\n\n/**\n * Checks if a pathname matches a redirect rule and returns the redirect\n * Response if so.\n */\nexport function matchRedirect(\n pathname: string,\n rules: RedirectRule[],\n): Response | undefined {\n for (const rule of rules) {\n const params = matchPattern(pathname, rule.from);\n if (params) {\n const location = interpolatePath(rule.to, params);\n const status = rule.status ?? 308;\n return new Response(null, {\n status,\n headers: { Location: location },\n });\n }\n }\n return undefined;\n}\n\n/**\n * Checks if a pathname matches a rewrite rule and returns the rewritten\n * pathname if so.\n */\nexport function matchRewrite(\n pathname: string,\n rules: RewriteRule[],\n): string | undefined {\n for (const rule of rules) {\n const params = matchPattern(pathname, rule.from);\n if (params) {\n return interpolatePath(rule.to, params);\n }\n }\n return undefined;\n}\n\n/**\n * Returns headers that should be applied to a response for the given pathname.\n */\nexport function matchRouteHeaders(\n pathname: string,\n rules: RouteHeadersRule[],\n): Record<string, string> | undefined {\n for (const rule of rules) {\n if (matchPattern(pathname, rule.path)) {\n return rule.headers;\n }\n }\n return undefined;\n}\n\n/**\n * Matches a pathname against a pattern with :param and * wildcards.\n * Returns the extracted params, or undefined if no match.\n */\nfunction matchPattern(pathname: string, pattern: string): Record<string, string> | undefined {\n const cleanPath = pathname.split(\"?\")[0];\n const requestSegments = cleanPath.split(\"/\").filter(Boolean);\n const patternSegments = pattern.split(\"/\").filter(Boolean);\n const params: Record<string, string> = {};\n\n let i = 0;\n for (let r = 0; r < patternSegments.length; r++) {\n const seg = patternSegments[r];\n\n if (seg === \"*\") {\n // Wildcard matches everything remaining.\n return params;\n }\n\n if (seg.endsWith(\"*\")) {\n // Catch-all: :name* matches the rest as a single string.\n const name = seg.slice(1, -1);\n const rest = requestSegments.slice(i).join(\"/\");\n params[name] = rest;\n return params;\n }\n\n if (seg.startsWith(\":\")) {\n const name = seg.slice(1);\n if (requestSegments[i] === undefined) return undefined;\n params[name] = requestSegments[i];\n i++;\n continue;\n }\n\n if (seg !== requestSegments[i]) return undefined;\n i++;\n }\n\n if (i !== requestSegments.length) return undefined;\n return params;\n}\n\n/**\n * Interpolates :param placeholders in a path with actual values.\n */\nfunction interpolatePath(template: string, params: Record<string, string>): string {\n return template.replace(/:(\\w+)\\*?/g, (_match, name: string) => {\n return params[name] ?? \"\";\n });\n}\n","// --- Stream boundary (per-request, real Suspense streaming) ---\n//\n// `streamBoundary()` wraps a promise in a loading fallback. During SSR runtime,\n// the server emits the fallback HTML immediately, then streams a `<template>`\n// chunk with a replacement script that the browser executes to swap the\n// fallback for the resolved content in-place (real Suspense streaming).\n//\n// In SSG (build time), boundaries are resolved synchronously — the build waits\n// for all promises before writing the HTML, so no streaming occurs.\n//\n// Boundaries are tracked per-request via AsyncLocalStorage to avoid global\n// state leakage between concurrent requests.\n\nimport type { ElurTemplate } from \"@elurjs/core\";\nimport { randomUUID } from \"node:crypto\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport interface StreamBoundaryOptions<T> {\n /** Fallback content shown while the promise resolves. */\n fallback: ElurTemplate;\n /** Promise that resolves to a ElurTemplate. */\n promise: Promise<T>;\n /** Renders the resolved value to a ElurTemplate. */\n children: (value: T) => ElurTemplate;\n}\n\n/** Per-request boundary registry. */\ninterface BoundaryContext {\n boundaries: Map<string, {\n promise: Promise<unknown>;\n children: (value: unknown) => ElurTemplate;\n }>;\n}\n\nconst boundaryALS = new AsyncLocalStorage<BoundaryContext>();\n\n/**\n * Gets the current per-request boundary context, if any.\n * Used by the streaming response to collect boundaries for later resolution.\n */\nexport function getCurrentBoundaryContext(): BoundaryContext | undefined {\n return boundaryALS.getStore();\n}\n\n/**\n * Runs a function within a per-request boundary context.\n * Used by the SSR streaming pipeline to collect boundaries.\n */\nexport function withBoundaryContext<T>(fn: () => T): T {\n const ctx: BoundaryContext = { boundaries: new Map() };\n return boundaryALS.run(ctx, fn);\n}\n\n/**\n * Builds the fallback HTML wrapper for a boundary ID.\n * The fallback content is wrapped in a `<div>` with the boundary ID so the\n * browser can find it and replace it when the resolved content arrives.\n *\n * (v2.1 — Fix #4: real Suspense streaming with `<template>` replacement)\n */\nexport function buildFallbackHtml(boundaryId: string, fallbackHtml: string): string {\n return `<div id=\"${boundaryId}\" style=\"display:contents\" data-elur-boundary=\"${boundaryId}\">${fallbackHtml}</div>`;\n}\n\n/**\n * Builds the resolved content chunk for a boundary ID.\n * Emits a `<template>` element with the resolved content, followed by a\n * `<script>` that replaces the fallback div with the template content\n * in-place. This is real Suspense streaming — the browser swaps the DOM\n * node without a full re-render.\n *\n * (v2.1 — Fix #4: real Suspense streaming with `<template>` replacement)\n */\nexport function buildResolvedChunk(boundaryId: string, resolvedHtml: string): string {\n // Escape the resolved HTML for safe embedding inside a <template> tag.\n // <template> content is inert (not parsed as DOM), so we store the raw\n // HTML and clone it via `content.cloneNode(true)`.\n return `<template id=\"${boundaryId}-tpl\">${resolvedHtml}</template>` +\n `<script>(function(){` +\n `var t=document.getElementById(${JSON.stringify(boundaryId + \"-tpl\")});` +\n `var f=document.getElementById(${JSON.stringify(boundaryId)});` +\n `if(t&&f){f.replaceWith(t.content.cloneNode(true));}` +\n `document.dispatchEvent(new CustomEvent(\"elur:rendered\"));` +\n `})();</script>`;\n}\n\n/**\n * Creates a stream boundary. During SSR, emits the fallback and registers the\n * promise for later resolution by the streaming pipeline. During SSG, the\n * build awaits all boundaries before writing HTML.\n *\n * The boundary ID is deterministic per-request via crypto.randomUUID().\n */\nexport function streamBoundary<T>(options: StreamBoundaryOptions<T>): ElurTemplate {\n const id = `elur-stream-${randomUUID().slice(0, 8)}`;\n const ctx = boundaryALS.getStore();\n\n // In SSR mode with a boundary context, register the promise for later.\n if (ctx) {\n ctx.boundaries.set(id, {\n promise: options.promise,\n children: options.children as (value: unknown) => ElurTemplate,\n });\n }\n\n return {\n __isElurTemplate: true as const,\n mount(container: Element | string) {\n const el = typeof container === \"string\" ? document.querySelector(container) : container;\n if (!el) throw new Error(\"[elur-kit] streamBoundary(): container not found\");\n // Render fallback initially.\n const handle = options.fallback.mount(el);\n // Attempt to resolve and swap (works in both SSR and client).\n options.promise\n .then((value) => {\n const content = options.children(value);\n el.innerHTML = \"\";\n const childHandle = content.mount(el);\n // Store the new handle for cleanup.\n (handle as any).__elurChildHandle = childHandle;\n })\n .catch((err) => {\n console.error(`[elur-kit] streamBoundary ${id} failed:`, err);\n });\n return {\n unmount() {\n const childHandle = (handle as any).__elurChildHandle;\n if (childHandle?.unmount) childHandle.unmount();\n handle.unmount();\n },\n };\n },\n _render(parent: Node, before: Node | null): () => void {\n // For SSR/build: render fallback inline. The promise resolution is\n // handled by the streaming pipeline when available.\n const dispose = options.fallback._render(parent, before);\n\n // Kick off the promise resolution in the background.\n options.promise\n .then((value) => {\n void value;\n })\n .catch((err) => {\n console.error(`[elur-kit] streamBoundary ${id} failed:`, err);\n });\n\n return dispose;\n },\n } as unknown as ElurTemplate;\n}\n","// --- Real streaming with ReadableStream (plan §10) ---\n//\n// Creates a Web Response with a ReadableStream that:\n// 1. Sends the document shell + loading fallback immediately.\n// 2. Runs the full page render (loaders included) in the background.\n// 3. Appends a resolved-content chunk with a deterministic boundary ID.\n// 4. Includes a swap script that replaces the loading boundary in-place.\n// 5. Cancels the stream and the background render when the client\n// disconnects (AbortSignal), cleaning up listeners.\n//\n// Response contract (mirrors what Next.js documents for self-hosted\n// streaming): `Content-Type: text/html` is sent early, the body is chunked\n// (no `Content-Length`), `X-Accel-Buffering: no` asks reverse proxies like\n// nginx not to buffer the stream, and `Cache-Control: no-store` keeps CDNs\n// from caching a half-sent dynamic stream. Streamed responses are never\n// written to the ISR cache — caching a stream mid-flight is unsound, so\n// routes served this way always render live.\n//\n// For adapters without streaming support, `createBufferedResponse()` provides\n// a fallback that buffers the full response and returns it as a single\n// Response (no streaming).\n\nimport type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString } from \"../render/render-to-string.js\";\nimport { documentShell, extractAppBody } from \"../build/document-shell.js\";\nimport type { PageRoute } from \"../router/route-scanner.js\";\nimport type { BuildConfig } from \"../build/build.js\";\nimport { renderPage } from \"./render.js\";\nimport { randomUUID } from \"node:crypto\";\nimport { buildResolvedChunk } from \"../middleware/stream-boundary.js\";\n\nexport interface StreamResponseOptions {\n route: PageRoute;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\" | \"renderEndpoint\" | \"router\" | \"js\">;\n actions?: Record<string, string[]>;\n importer?: (path: string) => Promise<unknown>;\n request?: Request;\n /** AbortSignal from the host (client disconnect). */\n signal?: AbortSignal;\n}\n\n/** Standard headers for a streamed HTML response. */\nconst STREAM_HEADERS: Record<string, string> = {\n \"Content-Type\": \"text/html; charset=utf-8\",\n // Ask reverse proxies (nginx and friends) not to buffer the stream; without\n // this the client receives the whole response at once and streaming is\n // pointless. See https://nextjs.org/docs/app/guides/self-hosting#streaming-and-suspense\n \"X-Accel-Buffering\": \"no\",\n // A streamed dynamic page is rendered live per request: intermediaries and\n // browsers must not cache it.\n \"Cache-Control\": \"no-store\",\n};\n\n/**\n * Mid-stream error notice swapped into the loading boundary when the\n * background render fails after the shell was already sent. Inline styles\n * keep it self-contained (the page's CSS may assume the final layout).\n */\nfunction buildErrorNotice(): string {\n return `<div role=\"alert\" style=\"margin:2rem auto;max-width:32rem;padding:1rem 1.25rem;border:1px solid #e5484d;border-radius:8px;color:#b3373c;font-family:system-ui,sans-serif\">` +\n `<strong style=\"display:block;margin-bottom:.25rem\">No se pudo cargar el contenido.</strong>` +\n `<span>Recarga la página para intentarlo de nuevo.</span></div>`;\n}\n\n/**\n * Creates a streaming Response that sends the shell + loading fallback first,\n * then appends the resolved content.\n *\n * If the route has no loading boundary, falls back to a normal renderPage.\n */\nexport async function createStreamingResponse(\n options: StreamResponseOptions,\n): Promise<Response> {\n const { route, params, searchParams, config, actions, importer = defaultImport, request, signal } = options;\n\n // If no loading boundary, do a normal render (no streaming).\n if (!route.loadingPath) {\n const result = await renderPage({\n route,\n params,\n searchParams,\n config,\n actions,\n importer,\n request,\n });\n if (result.response) return result.response;\n return new Response(result.html, {\n headers: { \"Content-Type\": \"text/html; charset=utf-8\" },\n });\n }\n\n // The client already disconnected before we produced anything.\n if (signal?.aborted) {\n return new Response(\"Client Closed Request\", { status: 499 });\n }\n\n // Load the loading boundary component.\n const loadingMod = (await importer(route.loadingPath)) as { default: () => ElurTemplate };\n const loadingHtml = await renderToString(loadingMod.default);\n\n // Deterministic boundary ID for the swap.\n const boundaryId = `elur-stream-${randomUUID().slice(0, 8)}`;\n\n // Build the shell with the loading fallback. Streaming sends the shell\n // before the body is known, so the 0%-JS island scan cannot run here —\n // streamed routes always emit the client entry (they are few and usually\n // interactive anyway). The split router chunk is emitted when configured.\n const routerCfg = config.router;\n const routerEnabled = routerCfg?.enabled !== false;\n const routerEntry =\n routerCfg?.entry && routerEnabled && config.js !== \"legacy\"\n ? routerCfg.entry\n : undefined;\n const shellHtml = documentShell({\n title: \"Loading...\",\n lang: config.lang,\n body: `<div id=\"${boundaryId}\">${loadingHtml}</div>`,\n data: { __elur_js_streaming: true, page: route.path },\n actions,\n clientEntry: config.clientEntry,\n routerEntry,\n routerEnabled: routerCfg ? routerEnabled : undefined,\n renderEndpoint: config.renderEndpoint,\n });\n\n // Create a ReadableStream that sends the shell, then the resolved content.\n let aborted = false;\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n const encoder = new TextEncoder();\n\n const onAbort = () => {\n aborted = true;\n try {\n controller.close();\n } catch {\n // Already closed/errored — nothing to do.\n }\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n /** Enqueue unless the client went away mid-render. */\n const send = (html: string): void => {\n if (aborted) return;\n controller.enqueue(encoder.encode(html));\n };\n\n try {\n // Send the shell immediately.\n send(shellHtml);\n\n // Run the full page render in the background.\n const result = await renderPage({\n route,\n params,\n searchParams,\n config,\n actions,\n importer,\n request,\n });\n if (aborted) return;\n\n // If a loader threw a Response, send a redirect/error script.\n if (result.response) {\n const status = result.response.status;\n const location = result.response.headers.get(\"Location\");\n if (location && (status === 301 || status === 302 || status === 307 || status === 308)) {\n send(`<script>window.location.href=${JSON.stringify(location)};</script>`);\n } else {\n // A non-redirect thrown response (404, 403, ...): swap the loading\n // boundary for an error notice instead of leaving a spinner.\n send(\n buildResolvedChunk(boundaryId, buildErrorNotice()) +\n `<script>console.error(${JSON.stringify(`Loader responded with status ${status}`)});</script>`,\n );\n }\n return;\n }\n\n // Extract the inner body from the full render. The document shell\n // wraps the page in explicit markers; the regex fallback covers\n // documents assembled without them.\n const innerBody = extractAppBody(result.html)\n ?? result.html.match(/<div id=\"app\">([\\s\\S]*)<\\/div>\\s*(<script|$)/)?.[1]?.trim()\n ?? result.html;\n\n // Send a `<template>` chunk + replacement script that swaps the\n // loading boundary with the real content in-place.\n send(buildResolvedChunk(boundaryId, innerBody));\n } catch (err) {\n // The shell is already on the wire, so the error must arrive as a\n // chunk: swap the loading boundary for an error notice and log the\n // details to the console.\n const errorMsg = err instanceof Error ? err.message : String(err);\n send(\n buildResolvedChunk(boundaryId, buildErrorNotice()) +\n `<script>console.error(${JSON.stringify(errorMsg)});</script>`,\n );\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n if (!aborted) {\n controller.close();\n }\n }\n },\n\n cancel() {\n // Client disconnected (the runtime cancelled the stream): mark aborted\n // so a render completing late never enqueues into a dead stream.\n aborted = true;\n },\n });\n\n return new Response(stream, {\n // No `Content-Length` and no explicit `Transfer-Encoding`: the host\n // runtime (Node, Bun, edge) chunks the body automatically when the\n // length is unknown. Setting Transfer-Encoding by hand produces a\n // duplicated `chunked, chunked` header under Node.\n headers: STREAM_HEADERS,\n });\n}\n\n/**\n * Buffered fallback for adapters without streaming support.\n * Renders the full page and returns it as a single Response.\n */\nexport async function createBufferedResponse(\n options: StreamResponseOptions,\n): Promise<Response> {\n const { route, params, searchParams, config, actions, importer = defaultImport, request } = options;\n\n const result = await renderPage({\n route,\n params,\n searchParams,\n config,\n actions,\n importer,\n request,\n });\n\n if (result.response) return result.response;\n\n return new Response(result.html, {\n headers: { \"Content-Type\": \"text/html; charset=utf-8\" },\n });\n}\n\nconst defaultImport = (path: string) => import(path);\n\n/**\n * Checks if the host runtime supports streaming responses.\n * Node, Bun, and modern edge runtimes do. Some serverless platforms may not.\n */\nexport { supportsStreaming } from \"../runtime/capabilities.js\";\n","import { matchRoute, matchApiRoute } from \"../ssr/match.js\";\nimport { handleActionRequest, type ActionResolver } from \"../action/server.js\";\nimport { renderPage, renderErrorPage } from \"../ssr/render.js\";\nimport { renderPageBody, RouteNotFoundError } from \"../ssr/stream.js\";\nimport { actionNames } from \"../action/scan.js\";\nimport { serveStaticFile, htmlResponse, jsonResponse, notFound, methodNotAllowed } from \"./context.js\";\nimport { publicErrorResponse } from \"../errors.js\";\nimport { cacheKey, createFsCacheAdapter, type CacheAdapter } from \"../cache/adapter.js\";\nimport { connectCacheAdapter } from \"../cache/invalidation.js\";\nimport { shouldCachePublic, type CachePolicy } from \"../cache/policy.js\";\nimport { buildSecurityHeaders, applySecurityHeaders } from \"./security-headers.js\";\nimport { createRequestLogger, type LogLevel, type StructuredLogger } from \"./logger.js\";\nimport { matchRedirect, matchRewrite, matchRouteHeaders, type RedirectRule, type RewriteRule, type RouteHeadersRule } from \"../router/redirects.js\";\nimport { matchesMiddleware, runMiddleware, type LoadedMiddleware } from \"../middleware/index.js\";\nimport { createStreamingResponse } from \"../ssr/stream-response.js\";\nimport { supportsStreaming, DEFAULT_CAPABILITIES, type AdapterCapabilities } from \"./capabilities.js\";\nimport type { SecurityHeadersConfig } from \"../config/index.js\";\n\n// --- Unified Web handler ---\n//\n// A single function that turns a Web Request into a Web Response. Every\n// runtime entry point (Node CLI, Bun adapter, Vercel, Netlify, Vite dev)\n// eventually calls this handler so behavior is identical across platforms.\n//\n// Responsibilities (in order):\n// 0. Redirects and rewrites declared in the config.\n// 1. Server actions endpoint (/__elur-js/actions).\n// 2. SPA render endpoint (/__elur-js/render).\n// 3. API routes.\n// 4. Static files from the output directory.\n// 5. Dynamic SSR rendering for unmatched paths.\n// 6. 404 / 500 error pages.\n//\n// The handler is pure: it does not import Node HTTP types and can be used in\n// Bun, Deno, Cloudflare Workers, Vercel Edge, etc.\n\nexport interface WebHandlerOptions {\n /** Static file root (absolute path). Usually the build output directory. */\n staticRoot: string;\n /** Whether to bypass the ISR cache (dev mode). */\n noCache?: boolean;\n /** ISR cache directory (absolute). */\n cacheDir?: string;\n /** Default ISR revalidate interval in seconds. */\n defaultRevalidate?: number;\n /** Optional module loader for adapter-bundled entries. */\n importer?: (path: string) => Promise<unknown>;\n /** HTML lang attribute. */\n lang?: string;\n /** Client entry path. */\n clientEntry?: string;\n /** Whether the render endpoint exists. */\n renderEndpoint?: boolean;\n /** Security headers config (runtime-security §14). `false` disables. */\n securityHeaders?: SecurityHeadersConfig | false;\n /** Minimum log level for the per-request structured logger. */\n logLevel?: LogLevel;\n /**\n * Pluggable ISR cache adapter. When omitted and `cacheDir` is set, a\n * filesystem adapter is created and shared per `cacheDir` for the process.\n */\n cacheAdapter?: CacheAdapter;\n /** Redirect rules evaluated before any routing (first match wins). */\n redirects?: RedirectRule[];\n /** Rewrite rules: transparently change the pathname used for routing. */\n rewrites?: RewriteRule[];\n /** Extra response headers applied to matching request paths. */\n routeHeaders?: RouteHeadersRule[];\n /**\n * Opt-in streaming SSR (experimental). When `true`, dynamic routes with a\n * `loading` boundary are served as a real stream: the document shell plus\n * the loading fallback go out immediately, and the resolved content arrives\n * as a follow-up chunk that swaps the boundary in-place. Streamed responses\n * bypass the ISR cache (they always render live) and send\n * `Cache-Control: no-store` + `X-Accel-Buffering: no`. Routes without a\n * loading boundary render buffered exactly as before.\n */\n streaming?: boolean;\n /**\n * Host capabilities used to gate streaming. Defaults to\n * `DEFAULT_CAPABILITIES` (a full Node/Bun process). Adapters for hosts\n * without streaming support should pass their own capabilities so\n * `streaming: true` degrades to buffered rendering instead of breaking.\n */\n capabilities?: AdapterCapabilities;\n /**\n * User middleware (the project's `src/middleware.ts`, loaded by the caller\n * with `loadMiddleware`). Runs after redirects/rewrites and the internal\n * endpoints, before API/static/SSR routing. A returned Response\n * short-circuits the pipeline; `next({ headers, locals })` merges headers\n * into the downstream request and exposes `locals` to API routes.\n */\n middleware?: LoadedMiddleware;\n /**\n * Client router options affecting SSR output: `enabled` controls the\n * render-endpoint marker and whether a page without islands ships any JS;\n * `entry` is the public URL of the split router chunk (e.g.\n * `/_elur/router.js`) when the client bundle was built with separate\n * entry/router inputs.\n */\n router?: { enabled?: boolean; entry?: string };\n /**\n * Client JS mode. `\"legacy\"` restores the pre-0%-JS behavior: the combined\n * client entry is emitted unconditionally on every page.\n */\n js?: \"modern\" | \"legacy\";\n}\n\nexport interface WebHandlerRouteTable {\n pages: import(\"../router/route-scanner.js\").PageRoute[];\n api: import(\"../router/route-scanner.js\").ApiRoute[];\n error404?: import(\"../router/route-scanner.js\").PageRoute;\n error500?: import(\"../router/route-scanner.js\").PageRoute;\n}\n\nexport interface WebHandlerActionRegistry {\n [pagePath: string]: Record<string, string>;\n}\n\nexport interface CreateWebHandlerResult {\n (request: Request): Promise<Response>;\n}\n\n/**\n * Create a unified Web handler from scanned routes, actions and options.\n *\n * The returned function is the single entry point for all runtimes.\n */\nexport function createWebHandler(\n routes: WebHandlerRouteTable,\n actions: WebHandlerActionRegistry,\n options: WebHandlerOptions,\n): CreateWebHandlerResult {\n const publicActions = actionNames(actions);\n const lang = options.lang ?? \"es\";\n const clientEntry = options.clientEntry;\n const renderEndpoint = options.renderEndpoint ?? true;\n const noCache = options.noCache ?? false;\n const defaultRevalidate = options.defaultRevalidate;\n\n const renderConfig = {\n lang,\n clientEntry,\n renderEndpoint,\n router: options.router\n ? { enabled: options.router.enabled !== false, entry: options.router.entry }\n : undefined,\n js: options.js,\n };\n const securityHeadersConfig = options.securityHeaders ?? {};\n const redirectRules = options.redirects ?? [];\n const rewriteRules = options.rewrites ?? [];\n const routeHeaderRules = options.routeHeaders ?? [];\n const capabilities = options.capabilities ?? DEFAULT_CAPABILITIES;\n // Streaming is opt-in AND requires a host that can flush chunks as they are\n // produced; when either is missing every route renders buffered.\n const streamingEnabled = options.streaming === true && supportsStreaming(capabilities);\n const cacheAdapter = resolveCacheAdapter(options);\n if (cacheAdapter && !invalidatorConnectedAdapters.has(cacheAdapter)) {\n invalidatorConnectedAdapters.add(cacheAdapter);\n // The subscription lives for the process lifetime: defaultInvalidator is\n // a module-level singleton and dev/preview recreate the handler per\n // request, so connecting per call would leak listeners.\n connectCacheAdapter(cacheAdapter);\n }\n\n function createActionResolver(): ActionResolver {\n return async (name: string, page?: string) => {\n const pageKey = page\n ? routes.pages.some((route) => route.path === page)\n ? page\n : (matchRoute(page, routes.pages)?.route.path ?? page)\n : undefined;\n const pageActions = pageKey ? actions[pageKey] : Object.values(actions).find((p) => p[name]) ?? undefined;\n const actionPath = pageActions ? pageActions[name] : undefined;\n if (!actionPath) return undefined;\n if (options.importer) {\n const mod = (await options.importer(actionPath)) as Record<string, unknown>;\n const action = mod[name];\n if (typeof action === \"function\") return action as (...args: unknown[]) => unknown;\n return undefined;\n }\n const mod = (await import(actionPath)) as Record<string, unknown>;\n const action = mod[name];\n if (typeof action === \"function\") return action as (...args: unknown[]) => unknown;\n return undefined;\n };\n }\n\n const actionResolver = createActionResolver();\n\n async function handleActions(request: Request, logger: StructuredLogger): Promise<Response> {\n const stopTimer = logger.startTimer(\"action\", \"Server action\");\n try {\n return await handleActionRequest(request, actionResolver);\n } catch (err) {\n logger.error(\"[elur-kit] action error\", {\n path: new URL(request.url).pathname,\n method: request.method,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n return publicErrorResponse(err, { includeDetail: noCache });\n } finally {\n stopTimer();\n }\n }\n\n async function handleRenderEndpoint(request: Request, url: URL, logger: StructuredLogger): Promise<Response> {\n const page = url.searchParams.get(\"page\") ?? \"/\";\n const search = url.searchParams.get(\"search\") ?? \"\";\n const wantsJson = (request.headers.get(\"Accept\") ?? \"\").includes(\"application/json\");\n const stopTimer = logger.startTimer(\"render-endpoint\", \"SPA render endpoint\");\n try {\n const result = await renderPageBody({\n routes,\n pathname: page,\n searchParams: new URLSearchParams(search),\n config: renderConfig,\n actions: publicActions,\n request,\n importer: options.importer,\n });\n // A thrown Response from a loader is a first-class response (A-22).\n if (result.response) return result.response;\n const { body, title, head, clearActionErrorCookie, data, actions } = result;\n if (wantsJson) {\n // The full SPA payload: head keeps OG/Twitter metadata fresh on\n // navigation, data/actions keep the inert JSON scripts in sync, and\n // the clear-cookie is also relayed as a header for parity with dev.\n const headers: Record<string, string> = {};\n if (clearActionErrorCookie) {\n headers[\"X-Elur-Action-Clear-Cookie\"] = clearActionErrorCookie;\n }\n // `?? null` keeps every key present in the wire shape — JSON.stringify\n // drops undefined values and the parity contract expects a stable\n // payload across runtimes.\n return jsonResponse(\n {\n title,\n body,\n head: head ?? null,\n data: data ?? null,\n actions: actions ?? null,\n clearActionErrorCookie: clearActionErrorCookie ?? null,\n },\n 200,\n headers,\n );\n }\n return htmlResponse(\n body,\n 200,\n clearActionErrorCookie ? { \"Set-Cookie\": clearActionErrorCookie } : undefined,\n );\n } catch (err) {\n if (err instanceof RouteNotFoundError) return notFound(\"Not Found\");\n // A thrown Response from a loader is a first-class response (A-22).\n if (err instanceof Response) return err;\n logger.error(\"[elur-kit] render endpoint error\", {\n path: url.pathname,\n page,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n return publicErrorResponse(err, { includeDetail: noCache });\n } finally {\n stopTimer();\n }\n }\n\n async function handleApiRoute(\n request: Request,\n pathname: string,\n logger: StructuredLogger,\n middlewareLocals?: Record<string, unknown>,\n ): Promise<Response | null> {\n const apiMatch = matchApiRoute(pathname, routes.api);\n if (!apiMatch) return null;\n const stopTimer = logger.startTimer(\"api\", \"API route\");\n try {\n let mod: Record<string, unknown>;\n if (options.importer) {\n mod = (await options.importer(apiMatch.route.routePath as unknown as string)) as Record<string, unknown>;\n } else {\n mod = (await import(apiMatch.route.routePath)) as Record<string, unknown>;\n }\n const handler = mod[request.method ?? \"GET\"];\n if (typeof handler !== \"function\") return methodNotAllowed(request.method ?? \"GET\");\n // Pass params and a writable locals object to the API handler\n // (runtime-security §4: params derived from the effective route).\n // `locals` carries values published by the user middleware via next().\n const ctx = { params: apiMatch.params, locals: middlewareLocals ?? {} as Record<string, unknown> };\n const response = (await (handler as (req: Request, ctx?: { params: Record<string, string | string[]>; locals: Record<string, unknown> }) => unknown)(request, ctx)) as Response;\n return response;\n } catch (err) {\n logger.error(\"[elur-kit] API route error\", {\n path: pathname,\n method: request.method,\n route: apiMatch.route.path,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n return publicErrorResponse(err, { includeDetail: noCache });\n } finally {\n stopTimer();\n }\n }\n\n async function handleStatic(pathname: string, request: Request): Promise<Response | null> {\n const response = await serveStaticFile(options.staticRoot, pathname, request);\n if (response && noCache) {\n const ct = response.headers.get(\"Content-Type\") ?? \"\";\n if (ct.includes(\"text/html\")) {\n // Dev mode: strip the render-endpoint marker so the client router uses\n // the live /__elur-js/render endpoint for fast SPA navigation.\n const stripped = (await response.text())\n .replace('<meta name=\"elur:render-endpoint\" content=\"off\" />', \"\");\n return new Response(stripped, {\n status: response.status,\n headers: { \"Content-Type\": ct, \"Cache-Control\": \"no-store, must-revalidate\" },\n });\n }\n return new Response(response.body, {\n status: response.status,\n headers: { ...Object.fromEntries(response.headers.entries()), \"Cache-Control\": \"no-store, must-revalidate\" },\n });\n }\n if (response && renderEndpoint) {\n const ct = response.headers.get(\"Content-Type\") ?? \"\";\n if (ct.includes(\"text/html\")) {\n const headers = Object.fromEntries(response.headers.entries());\n delete headers[\"content-length\"];\n const body = await response.text();\n if (body.includes('elur:render-endpoint\" content=\"off\"')) {\n // The SSG build baked `render-endpoint content=\"off\"` so static\n // deployments never probe the endpoint. This server exposes\n // /__elur-js/render, so advertise it: SPA navigations fetch live\n // server-rendered content instead of the stale static file.\n const rewritten = body.replace(\n '<meta name=\"elur:render-endpoint\" content=\"off\" />',\n '<meta name=\"elur:render-endpoint\" content=\"on\" />',\n );\n return new Response(rewritten, { status: response.status, headers });\n }\n return new Response(body, { status: response.status, headers });\n }\n }\n return response;\n }\n\n async function handleDynamicRender(request: Request, pathname: string, logger: StructuredLogger): Promise<Response> {\n const match = matchRoute(pathname, routes.pages);\n if (!match) {\n const errorResult = await renderErrorPage({\n routes,\n status: 404,\n config: renderConfig,\n actions: publicActions,\n importer: options.importer,\n });\n if (errorResult) return htmlResponse(errorResult.html, errorResult.status);\n return notFound(`Not found: ${pathname}`);\n }\n\n // Streaming SSR (opt-in): routes with a loading boundary are served as a\n // real stream — shell + fallback first, resolved content as a later chunk.\n // Streamed responses bypass the ISR cache entirely (a half-sent stream is\n // not cacheable; these pages render live on every request), so the cache\n // gates below only apply to the buffered path.\n if (streamingEnabled && match.route.loadingPath) {\n // The timer measures time-to-shell: the Response is returned once the\n // shell is ready while the background render continues streaming.\n const stopStreamTimer = logger.startTimer(\"ssr\", \"SSR stream shell\");\n try {\n return await createStreamingResponse({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(request.url.split(\"?\")[1] ?? \"\"),\n config: renderConfig,\n actions: publicActions,\n importer: options.importer,\n request,\n signal: request.signal,\n });\n } catch (err) {\n // A thrown Response from a loader is a first-class response (A-22).\n if (err instanceof Response) return err;\n logger.error(\"[elur-kit] SSR stream error\", {\n path: pathname,\n route: match.route.path,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n const errorResult = await renderErrorPage({\n routes,\n status: 500,\n error: err,\n config: renderConfig,\n actions: publicActions,\n importer: options.importer,\n }).catch(() => undefined);\n if (errorResult) return htmlResponse(errorResult.html, errorResult.status);\n return publicErrorResponse(err, { includeDetail: noCache });\n } finally {\n stopStreamTimer();\n }\n }\n\n // ISR cache (only when caching is enabled and the request is cacheable —\n // no cookies, no authorization header). Pages are stored in the cache\n // adapter under cacheKey(pathname); the same key scheme is used by\n // path-based invalidation (connectCacheAdapter).\n const cacheable = !noCache && cacheAdapter && isCacheable(request);\n const pageCacheKey = cacheable ? cacheKey(pathname) : undefined;\n\n const renderAndStore = async (): Promise<Response> => {\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(request.url.split(\"?\")[1] ?? \"\"),\n config: renderConfig,\n actions: publicActions,\n request,\n importer: options.importer,\n });\n\n // If a loader threw a Response (redirect, 404, etc.), return it\n // as a first-class response (A-22).\n if (result.response) {\n return result.response;\n }\n\n if (cacheable && cacheAdapter && pageCacheKey && isResultCacheable(result, request)) {\n const revalidateSeconds = result.revalidate ?? defaultRevalidate ?? 0;\n if (revalidateSeconds > 0) {\n await cacheAdapter.set(\n pageCacheKey,\n { html: result.html, generatedAt: Date.now(), revalidate: revalidateSeconds },\n { revalidate: revalidateSeconds, tags: result.cachePolicy?.tags },\n );\n }\n }\n\n return htmlResponse(result.html);\n };\n\n if (cacheable && cacheAdapter && pageCacheKey) {\n const cached = await cacheAdapter.get(pageCacheKey);\n if (cached) {\n if (Date.now() - cached.generatedAt >= cached.revalidate * 1000) {\n // Stale-while-revalidate: serve the stale entry immediately and\n // refresh it in the background.\n renderAndStore().catch((err) => {\n logger.error(\"[elur-kit] background cache revalidation failed\", {\n path: pathname,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n });\n }\n return htmlResponse(cached.html);\n }\n }\n\n const stopTimer = logger.startTimer(\"ssr\", \"SSR render\");\n try {\n return await renderAndStore();\n } catch (err) {\n // A thrown Response from a loader is a first-class response (A-22).\n if (err instanceof Response) return err;\n logger.error(\"[elur-kit] SSR render error\", {\n path: pathname,\n route: match.route.path,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n const errorResult = await renderErrorPage({\n routes,\n status: 500,\n error: err,\n config: renderConfig,\n actions: publicActions,\n importer: options.importer,\n }).catch(() => undefined);\n if (errorResult) return htmlResponse(errorResult.html, errorResult.status);\n return publicErrorResponse(err, { includeDetail: noCache });\n } finally {\n stopTimer();\n }\n }\n\n // Applies security headers plus the per-request observability headers\n // (Server-Timing when there are metrics, X-Request-ID always) and any\n // configured route headers. Route headers may override security headers;\n // the observability headers are applied last so they always win.\n function finalizeResponse(\n response: Response,\n logger: StructuredLogger,\n secHeaders: Record<string, string>,\n routeHeaders?: Record<string, string>,\n ): Response {\n const secured = applySecurityHeaders(response, secHeaders);\n const headers = new Headers(secured.headers);\n if (routeHeaders) {\n for (const [key, value] of Object.entries(routeHeaders)) {\n headers.set(key, value);\n }\n }\n const timing = logger.getServerTimingHeader();\n if (timing) headers.set(\"Server-Timing\", timing);\n headers.set(\"X-Request-ID\", logger.getRequestId());\n return new Response(secured.body, {\n status: secured.status,\n statusText: secured.statusText,\n headers,\n });\n }\n\n return async function handler(request: Request): Promise<Response> {\n const logger = createRequestLogger(request, options.logLevel);\n const url = new URL(request.url);\n const originalPathname = url.pathname;\n const isHttps = url.protocol === \"https:\";\n\n // Determine security headers (rebuild if nonce is needed).\n // HSTS is only applied under HTTPS; other headers apply always.\n const secHeaders = securityHeadersConfig === false\n ? {}\n : buildSecurityHeaders(securityHeadersConfig, isHttps);\n\n // 0. Redirects, evaluated before any routing.\n if (redirectRules.length > 0) {\n const redirect = matchRedirect(originalPathname, redirectRules);\n if (redirect) {\n return finalizeResponse(redirect, logger, secHeaders, matchRouteHeaders(originalPathname, routeHeaderRules));\n }\n }\n\n // Rewrites change the pathname transparently: everything below (API\n // routes, static files, dynamic SSR and its ISR cache key) routes on the\n // rewritten path, while route headers keep matching the original URL the\n // user configured them for.\n let pathname = originalPathname;\n if (rewriteRules.length > 0) {\n pathname = matchRewrite(originalPathname, rewriteRules) ?? originalPathname;\n }\n const routeHeaders = matchRouteHeaders(originalPathname, routeHeaderRules);\n\n // 1. Server actions endpoint.\n if (pathname === \"/__elur-js/actions\" && request.method === \"POST\") {\n const response = await handleActions(request, logger);\n return finalizeResponse(response, logger, secHeaders, routeHeaders);\n }\n\n // 2. SPA render endpoint.\n if (pathname === \"/__elur-js/render\" && renderEndpoint) {\n const response = await handleRenderEndpoint(request, url, logger);\n return finalizeResponse(response, logger, secHeaders, routeHeaders);\n }\n\n // User middleware (src/middleware.ts) runs after redirects/rewrites and\n // the internal endpoints, before routing — same semantics as the legacy\n // createSsrServer pipeline. A returned Response short-circuits (through\n // finalizeResponse so security/observability headers still apply);\n // next({ headers }) merges into the downstream request and\n // next({ locals }) is exposed to API routes.\n let middlewareLocals: Record<string, unknown> | undefined;\n const middleware = options.middleware;\n if (middleware && matchesMiddleware(pathname, middleware.config)) {\n let mwResult;\n try {\n mwResult = await runMiddleware(middleware, request);\n } catch (err) {\n logger.error(\"[elur-kit] middleware error\", {\n path: pathname,\n error: errorMessage(err),\n stack: errorStack(err),\n });\n return finalizeResponse(\n publicErrorResponse(err, { includeDetail: noCache }),\n logger,\n secHeaders,\n routeHeaders,\n );\n }\n if (mwResult.kind === \"response\") {\n return finalizeResponse(mwResult.response, logger, secHeaders, routeHeaders);\n }\n middlewareLocals = mwResult.locals;\n if (mwResult.headers) {\n const merged = new Headers(request.headers);\n for (const [key, value] of Object.entries(mwResult.headers)) {\n merged.set(key, value);\n }\n request = new Request(request, { headers: merged });\n }\n }\n\n // 3. API routes.\n const apiResponse = await handleApiRoute(request, pathname, logger, middlewareLocals);\n if (apiResponse) return finalizeResponse(apiResponse, logger, secHeaders, routeHeaders);\n\n // 4. Static files.\n const staticResponse = await handleStatic(pathname, request);\n if (staticResponse) return finalizeResponse(staticResponse, logger, secHeaders, routeHeaders);\n\n // 5. Dynamic SSR rendering.\n const dynamicResponse = await handleDynamicRender(request, pathname, logger);\n return finalizeResponse(dynamicResponse, logger, secHeaders, routeHeaders);\n };\n}\n\n// Default filesystem adapters are shared per cacheDir and connected to the\n// invalidator once; both live for the process lifetime (dev/preview recreate\n// the handler per request, so per-call adapters would leak listeners).\nconst defaultCacheAdapters = new Map<string, CacheAdapter>();\nconst invalidatorConnectedAdapters = new WeakSet<CacheAdapter>();\n\nfunction resolveCacheAdapter(options: WebHandlerOptions): CacheAdapter | undefined {\n if (options.cacheAdapter) return options.cacheAdapter;\n if (!options.cacheDir) return undefined;\n let adapter = defaultCacheAdapters.get(options.cacheDir);\n if (!adapter) {\n adapter = createFsCacheAdapter({ cacheDir: options.cacheDir });\n defaultCacheAdapters.set(options.cacheDir, adapter);\n }\n return adapter;\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction errorStack(err: unknown): string | undefined {\n return err instanceof Error ? err.stack : undefined;\n}\n\nfunction isCacheable(request: Request): boolean {\n if (request.method !== \"GET\" && request.method !== \"HEAD\") return false;\n if (request.headers.get(\"Cookie\")) return false;\n if (request.headers.get(\"Authorization\")) return false;\n return true;\n}\n\n/**\n * Checks whether a rendered page result is cacheable as public ISR.\n * Per runtime-security §9.1: uses the route's cache policy and checks\n * for personalized content markers.\n */\nfunction isResultCacheable(\n result: { revalidate?: number; html: string; cachePolicy?: CachePolicy },\n request: Request,\n): boolean {\n // If the HTML contains action error markers, it's personalized.\n if (result.html.includes(\"__elur_js_action_error\")) return false;\n // Use the route's cache policy if declared.\n if (result.cachePolicy) {\n return shouldCachePublic(result.cachePolicy, request);\n }\n // Fallback: cacheable only if revalidate > 0 and request is clean.\n if (!result.revalidate || result.revalidate <= 0) return false;\n if (request.headers.get(\"Cookie\")) return false;\n if (request.headers.get(\"Authorization\")) return false;\n return true;\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readdir, copyFile, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { AdapterOptions } from \"./index.js\";\nimport type { PageRoute } from \"../router/route-scanner.js\";\n\n/**\n * Shared helper: copy a directory recursively.\n */\nexport async function copyStatic(from: string, to: string): Promise<void> {\n await mkdir(to, { recursive: true });\n const entries = await readdir(from, { withFileTypes: true });\n for (const entry of entries) {\n const src = join(from, entry.name);\n const dest = join(to, entry.name);\n if (entry.isDirectory()) {\n await copyStatic(src, dest);\n } else {\n await copyFile(src, dest);\n }\n }\n}\n\n/** Adds every module the SSR runtime may import for a page to the registry. */\nfunction collectPageModules(\n page: PageRoute,\n moduleSet: Set<string>,\n actionPathsByPage: Map<string, Set<string>>,\n): void {\n moduleSet.add(page.pagePath);\n if (page.dataPath) moduleSet.add(page.dataPath);\n if (page.loadingPath) moduleSet.add(page.loadingPath);\n for (const layout of page.layouts) {\n moduleSet.add(layout);\n const layoutDataPath = layout.replace(/layout\\.ts$/, \"layout.data.ts\");\n if (layoutDataPath !== layout && existsSync(layoutDataPath)) {\n moduleSet.add(layoutDataPath);\n }\n }\n if (page.actionPath) {\n moduleSet.add(page.actionPath);\n let set = actionPathsByPage.get(page.path);\n if (!set) {\n set = new Set<string>();\n actionPathsByPage.set(page.path, set);\n }\n set.add(page.actionPath);\n }\n}\n\n/**\n * Build a self-contained SSR entry file for a platform adapter.\n * The generated module exports a default `handler(request: Request): Response`\n * and embeds the full route table plus a registry of all page/layout/data/\n * action modules so the runtime never touches the file system.\n */\nexport async function buildSsrEntry(\n routes: Awaited<ReturnType<typeof scanRoutes>>,\n options: AdapterOptions,\n entryDir: string,\n): Promise<string> {\n // Collect all module paths that the SSR runtime may need to import.\n const moduleSet = new Set<string>();\n const actionPathsByPage = new Map<string, Set<string>>();\n for (const page of routes.pages) {\n collectPageModules(page, moduleSet, actionPathsByPage);\n }\n if (routes.error404) collectPageModules(routes.error404, moduleSet, actionPathsByPage);\n if (routes.error500) collectPageModules(routes.error500, moduleSet, actionPathsByPage);\n for (const api of routes.api) {\n moduleSet.add(api.routePath);\n }\n const modules = Array.from(moduleSet);\n const moduleIndex = new Map(modules.map((path, index) => [path, index]));\n\n const imports = modules\n .map((path, index) => {\n const rel = relativeToPosix(entryDir, path);\n return `import * as m_${index} from ${JSON.stringify(rel)};`;\n })\n .join(\"\\n\");\n\n const renderPageRecord = (page: PageRoute): string => `{\n path: ${JSON.stringify(page.path)},\n pagePath: ${JSON.stringify(page.pagePath)},\n dataPath: ${JSON.stringify(page.dataPath ?? null)},\n actionPath: ${JSON.stringify(page.actionPath ?? null)},\n loadingPath: ${JSON.stringify(page.loadingPath ?? null)},\n layouts: ${JSON.stringify(page.layouts)},\n params: ${JSON.stringify(page.params)},\n }`;\n\n const pages = routes.pages.map(renderPageRecord).join(\",\\n\");\n\n const apiRoutes = routes.api\n .map((api) => {\n const index = moduleIndex.get(api.routePath);\n return ` { path: ${JSON.stringify(api.path)}, routePath: m_${index} },`;\n })\n .join(\"\\n\");\n\n const actionModules = Array.from(actionPathsByPage.entries())\n .map(([pagePath, paths]) => {\n const entries = Array.from(paths)\n .map((path) => {\n const index = moduleIndex.get(path);\n return ` [${JSON.stringify(path)}, m_${index}],`;\n })\n .join(\"\\n\");\n return ` [${JSON.stringify(pagePath)}, new Map([\\n${entries}\\n ])],`;\n })\n .join(\"\\n\");\n\n const actionsRegistry: Record<string, string[]> = {};\n for (const page of routes.pages) {\n if (!page.actionPath) continue;\n const mod = (await import(page.actionPath)) as Record<string, unknown>;\n const names: string[] = [];\n for (const [name, value] of Object.entries(mod)) {\n if (name === \"default\") continue;\n if (typeof value === \"function\") {\n names.push(name);\n }\n }\n if (names.length > 0) {\n actionsRegistry[page.path] = names;\n }\n }\n\n // The render config baked into the generated handler. The split router\n // chunk is advertised only when the bundle actually emitted it (the file\n // exists in the build output), so single-input legacy bundles keep working.\n const routerEnabled = options.router?.enabled !== false;\n const routerEntry =\n routerEnabled && options.js !== \"legacy\" &&\n existsSync(resolve(options.root, options.outDir, \"_elur\", \"router.js\"))\n ? \"/_elur/router.js\"\n : null;\n\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { handleActionRequest, matchApiRoute, matchRoute, renderPage, renderPageBody, renderErrorPage, createStreamingResponse } from \"@elurjs/kit\";\n${imports}\n\nconst registry = new Map<string, unknown>([\n${modules.map((path, index) => ` [${JSON.stringify(path)}, m_${index}],`).join(\"\\n\")}\n]);\n\nconst pages = [\n${pages},\n];\n\nconst apiRoutes = [\n${apiRoutes}\n];\n\nconst actionModules = new Map<string, Map<string, unknown>>([\n${actionModules}\n]);\n\nconst actions = ${JSON.stringify(actionsRegistry)};\n\nconst routes = {\n pages,\n api: apiRoutes,\n error404: ${routes.error404 ? renderPageRecord(routes.error404) : \"undefined\"},\n error500: ${routes.error500 ? renderPageRecord(routes.error500) : \"undefined\"},\n};\n\nconst clientEntry = ${JSON.stringify(options.clientEntry)};\nconst lang = ${JSON.stringify(options.lang)};\n// Client router/JS emission rules baked at adapter build time.\nconst router = ${JSON.stringify({ enabled: routerEnabled, entry: routerEntry })};\nconst jsMode = ${JSON.stringify(options.js === \"legacy\" ? \"legacy\" : \"modern\")};\n// Opt-in streaming SSR (experimental): routes with a loading boundary stream\n// the shell first and swap in the resolved content as a follow-up chunk.\nconst streaming = ${options.streaming === true};\n\nfunction loadModule(path: string) {\n const mod = registry.get(path);\n if (mod) return mod;\n throw new Error(\\`Module not found in registry: \\${path}\\`);\n}\n\nasync function resolveAction(name: string, page?: string) {\n // Match concrete page paths (e.g. /movies/inception) to their route pattern\n // (/movies/:slug) so actions on dynamic routes resolve by scope.\n let pageKey: string | undefined;\n if (page) {\n pageKey = routes.pages.some((route) => route.path === page)\n ? page\n : (matchRoute(page, routes.pages)?.route.path ?? page);\n }\n const pageModules = pageKey ? actionModules.get(pageKey) : undefined;\n const candidates = pageModules ? [...pageModules.values()] : [];\n if (!pageModules) {\n for (const mods of actionModules.values()) {\n for (const mod of mods.values()) {\n const action = (mod as Record<string, unknown>)[name];\n if (typeof action === \"function\") return action;\n }\n }\n }\n for (const mod of candidates) {\n const action = (mod as Record<string, unknown>)[name];\n if (typeof action === \"function\") {\n return action as (...args: unknown[]) => unknown;\n }\n }\n return undefined;\n}\n\nexport default async function handler(request: Request): Promise<Response> {\n const url = new URL(request.url);\n\n if (url.pathname === \"/__elur-js/actions\") {\n return handleActionRequest(request, resolveAction);\n }\n\n // Render endpoint used by the SPA router and streaming boundaries.\n if (url.pathname === \"/__elur-js/render\") {\n const page = url.searchParams.get(\"page\") ?? \"/\";\n const search = url.searchParams.get(\"search\") ?? \"\";\n const wantsJson = (request.headers.get(\"Accept\") ?? \"\").includes(\"application/json\");\n try {\n const result = await renderPageBody({\n routes,\n pathname: page,\n searchParams: new URLSearchParams(search),\n config: { lang, clientEntry, router, js: jsMode },\n importer: loadModule,\n actions,\n request,\n });\n // A thrown Response from a loader is a first-class response (A-22).\n if (result.response) return result.response;\n const { body, title, head, clearActionErrorCookie, data, actions: actionsPayload } = result;\n if (wantsJson) {\n const headers = { \"Content-Type\": \"application/json; charset=utf-8\" };\n if (clearActionErrorCookie) headers[\"X-Elur-Action-Clear-Cookie\"] = clearActionErrorCookie;\n // The ?? null fallbacks keep every key present — JSON.stringify drops\n // undefined and the SPA payload shape must be stable across runtimes.\n return new Response(\n JSON.stringify({\n title,\n body,\n head: head ?? null,\n data: data ?? null,\n actions: actionsPayload ?? null,\n clearActionErrorCookie: clearActionErrorCookie ?? null,\n }),\n { status: 200, headers },\n );\n }\n const headers = { \"Content-Type\": \"text/html; charset=utf-8\" };\n if (clearActionErrorCookie) headers[\"Set-Cookie\"] = clearActionErrorCookie;\n return new Response(body, { status: 200, headers });\n } catch (err) {\n if ((err as { name?: string }).name === \"RouteNotFoundError\") {\n return new Response(\"Not Found\", {\n status: 404,\n headers: { \"Content-Type\": \"text/plain\" },\n });\n }\n console.error(\"[elur-kit] render endpoint error:\", err);\n return new Response(\"Internal Server Error\", {\n status: 500,\n headers: { \"Content-Type\": \"text/plain\" },\n });\n }\n }\n\n const apiMatch = matchApiRoute(url.pathname, apiRoutes);\n if (apiMatch) {\n const mod = apiMatch.route.routePath as Record<\n string,\n (request: Request, context?: { params: Record<string, string | string[]> }) => unknown\n >;\n const handler = mod[request.method ?? \"GET\"];\n if (typeof handler !== \"function\") {\n return new Response(\"Method not allowed: \" + request.method, { status: 405, headers: { \"Content-Type\": \"text/plain\" } });\n }\n return (await handler(request, { params: apiMatch.params })) as Response;\n }\n\n const match = matchRoute(url.pathname, routes.pages);\n if (!match) {\n const errorResult = await renderErrorPage({ routes, status: 404, config: { lang, clientEntry, router, js: jsMode }, actions, importer: loadModule });\n if (errorResult) {\n return new Response(errorResult.html, { status: errorResult.status, headers: { \"Content-Type\": \"text/html; charset=utf-8\" } });\n }\n return new Response(\"Not Found\", { status: 404, headers: { \"Content-Type\": \"text/plain\" } });\n }\n\n try {\n if (streaming && match.route.loadingPath) {\n // Streaming SSR: shell + loading boundary first, resolved content as a\n // follow-up chunk. Streamed pages are rendered live (no cache).\n return createStreamingResponse({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(url.search),\n config: { lang, clientEntry, router, js: jsMode },\n importer: loadModule,\n actions,\n request,\n signal: request.signal,\n });\n }\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(url.search),\n config: { lang, clientEntry, router, js: jsMode },\n importer: loadModule,\n actions,\n request,\n });\n // A thrown Response from a loader is a first-class response (A-22).\n if (result.response) return result.response;\n const headers = { \"Content-Type\": \"text/html; charset=utf-8\" };\n if (result.clearActionErrorCookie) headers[\"Set-Cookie\"] = result.clearActionErrorCookie;\n return new Response(result.html, { status: 200, headers });\n } catch (err) {\n console.error(\"[elur-kit] SSR render error:\", err);\n const errorResult = await renderErrorPage({ routes, status: 500, error: err, config: { lang, clientEntry, router, js: jsMode }, actions, importer: loadModule });\n if (errorResult) {\n return new Response(errorResult.html, { status: errorResult.status, headers: { \"Content-Type\": \"text/html; charset=utf-8\" } });\n }\n return new Response(\"Internal Server Error\", { status: 500, headers: { \"Content-Type\": \"text/plain; charset=utf-8\" } });\n }\n}\n`;\n}\n\nfunction relativeToPosix(from: string, to: string): string {\n return relative(from, to).split(\"\\\\\").join(\"/\");\n}\n\n/**\n * Write a generated SSR entry file for an adapter.\n */\nexport async function writeSsrEntry(\n entryPath: string,\n routes: Awaited<ReturnType<typeof scanRoutes>>,\n options: AdapterOptions,\n): Promise<void> {\n await writeFile(\n entryPath,\n await buildSsrEntry(routes, options, dirname(entryPath)),\n \"utf8\",\n );\n}\n","import { mkdir, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { build } from \"vite\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { copyStatic, writeSsrEntry } from \"./shared.js\";\nimport { SERVERLESS_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Vercel adapter for elur-kit.\n *\n * Produces a `.vercel/output` directory compatible with the Vercel Build Output\n * API (v3). Static files are served from `dist/` and unmatched routes fall back\n * to the SSR function.\n */\nexport const vercelAdapter: Adapter = {\n name: \"vercel\",\n capabilities: SERVERLESS_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const vercelOut = resolve(root, \".vercel/output\");\n const functionsDir = join(vercelOut, \"functions\", \"__elur-js-kit.func\");\n const generatedDir = resolve(root, \".elur\");\n\n // Verify the production build exists.\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n // Clean previous adapter output.\n await rm(vercelOut, { recursive: true, force: true });\n await mkdir(vercelOut, { recursive: true });\n await mkdir(functionsDir, { recursive: true });\n await mkdir(generatedDir, { recursive: true });\n\n // Copy static files.\n await copyStatic(outDir, join(vercelOut, \"static\"));\n\n // Scan routes and generate a self-contained function entry.\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"vercel-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n // Bundle the function entry.\n await build({\n configFile: false,\n root,\n build: {\n outDir: functionsDir,\n emptyOutDir: true,\n ssr: true,\n lib: {\n entry: entryPath,\n formats: [\"es\"],\n fileName: () => \"index.js\",\n },\n rollupOptions: {\n external: [],\n output: {\n inlineDynamicImports: true,\n },\n },\n },\n });\n\n // Vite SSR lib builds may use the entry file name, so force the expected handler name.\n const generatedHandler = join(functionsDir, \"vercel-index.js\");\n const targetHandler = join(functionsDir, \"index.js\");\n try {\n await stat(generatedHandler);\n await rename(generatedHandler, targetHandler);\n } catch {\n // If the file is already named index.js, nothing to do.\n }\n\n // Write Vercel function config.\n await writeFile(\n join(functionsDir, \".vc-config.json\"),\n JSON.stringify(\n {\n runtime: \"nodejs20.x\",\n handler: \"index.js\",\n launcherType: \"Nodejs\",\n shouldAddHelpers: true,\n },\n null,\n 2,\n ),\n \"utf8\",\n );\n\n // Write Vercel root config.\n await writeFile(\n join(vercelOut, \"config.json\"),\n JSON.stringify(\n {\n version: 3,\n routes: [\n { handle: \"filesystem\" },\n { src: \"/(.*)\", \"dest\": \"/__elur-js-kit\" },\n ],\n },\n null,\n 2,\n ),\n \"utf8\",\n );\n },\n};\n","import { mkdir, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { build } from \"vite\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { writeSsrEntry } from \"./shared.js\";\nimport { SERVERLESS_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Netlify adapter for elur-kit.\n *\n * Produces the files expected by Netlify Functions v2:\n * - `netlify/functions/__elur-js-kit.mjs` — bundled SSR function.\n * - `netlify.toml` — redirects unmatched routes to the function.\n *\n * Run this after `elur-kit build`. The static files are left in `dist/` and\n * served directly by Netlify; the function only handles routes that have no\n * matching static file.\n */\nexport const netlifyAdapter: Adapter = {\n name: \"netlify\",\n capabilities: SERVERLESS_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const netlifyDir = resolve(root, \"netlify\");\n const functionsDir = join(netlifyDir, \"functions\");\n const generatedDir = resolve(root, \".elur\");\n\n // Verify the production build exists.\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n // Clean previous adapter output.\n await rm(functionsDir, { recursive: true, force: true });\n await mkdir(functionsDir, { recursive: true });\n await mkdir(generatedDir, { recursive: true });\n\n // Scan routes and generate a self-contained function entry.\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"netlify-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n // Bundle the function entry.\n await build({\n configFile: false,\n root,\n build: {\n outDir: functionsDir,\n emptyOutDir: true,\n ssr: true,\n lib: {\n entry: entryPath,\n formats: [\"es\"],\n fileName: () => \"__elur-js-kit.mjs\",\n },\n rollupOptions: {\n external: [],\n output: {\n inlineDynamicImports: true,\n },\n },\n },\n });\n\n // Vite SSR lib builds may use the entry file name, so force the expected handler name.\n const generatedHandler = join(functionsDir, \"netlify-index.js\");\n const targetHandler = join(functionsDir, \"__elur-js-kit.mjs\");\n try {\n await stat(generatedHandler);\n await rename(generatedHandler, targetHandler);\n } catch {\n // If the file is already named __elur-js-kit.mjs, nothing to do.\n }\n\n // Write Netlify redirects config.\n await writeFile(\n join(root, \"netlify.toml\"),\n `[build]\n command = \"elur-kit build\"\n publish = \"dist\"\n\n[[redirects]]\n from = \"/*\"\n to = \"/.netlify/functions/__elur-js-kit\"\n status = 200\n`,\n \"utf8\",\n );\n },\n};\n","import { mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { writeSsrEntry } from \"./shared.js\";\nimport { DEFAULT_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Bun adapter for elur-kit.\n *\n * Produces a self-contained Bun server entry at `.elur/bun-server.ts`.\n * Run it with:\n *\n * bun run .elur/bun-server.ts\n *\n * The server serves static files from `dist/` and renders pages on demand for\n * unmatched routes.\n */\nexport const bunAdapter: Adapter = {\n name: \"bun\",\n capabilities: DEFAULT_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const generatedDir = resolve(root, \".elur\");\n\n // Verify the production build exists.\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n // Clean previous adapter output.\n await rm(generatedDir, { recursive: true, force: true });\n await mkdir(generatedDir, { recursive: true });\n\n // Scan routes and generate a self-contained SSR handler entry.\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"bun-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n // Write the Bun server entry.\n const serverPath = resolve(generatedDir, \"bun-server.ts\");\n await writeFile(\n serverPath,\n buildBunServerSource(relativeToUrlPath(generatedDir, outDir), options),\n \"utf8\",\n );\n },\n};\n\nfunction buildBunServerSource(\n outDirUrl: string,\n options: {\n clientEntry: string;\n lang: string;\n port?: number;\n logLevel?: string;\n redirects?: import(\"../router/redirects.js\").RedirectRule[];\n rewrites?: import(\"../router/redirects.js\").RewriteRule[];\n routeHeaders?: import(\"../router/redirects.js\").RouteHeadersRule[];\n },\n): string {\n const logLevelOption = options.logLevel ? `, logLevel: ${JSON.stringify(options.logLevel)}` : \"\";\n // Rule arrays are plain data: emit them as JSON literals when defined.\n const routingOptions = ([\"redirects\", \"rewrites\", \"routeHeaders\"] as const)\n .map((key) => {\n const rules = options[key];\n return rules && rules.length > 0 ? `, ${key}: ${JSON.stringify(rules)}` : \"\";\n })\n .join(\"\");\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { fileURLToPath } from \"node:url\";\nimport { createWebHandler } from \"@elurjs/kit/runtime\";\nimport handler from \"./bun-index.ts\";\n\nconst outDir = fileURLToPath(new URL(${JSON.stringify(outDirUrl)}, import.meta.url));\nconst port = Number(process.env.PORT) || ${options.port ?? 3000};\n\nconst webHandler = createWebHandler(\n { pages: [], api: [], error404: undefined, error500: undefined },\n {},\n { staticRoot: outDir, lang: ${JSON.stringify(options.lang)}, clientEntry: ${JSON.stringify(options.clientEntry)}${logLevelOption}${routingOptions} },\n);\n\nBun.serve({\n port,\n async fetch(request) {\n // Try static files first via the unified handler, then fall back to the\n // bundled SSR handler for dynamic routes.\n let response = await webHandler(request);\n if (response.status === 404) {\n response = await handler(request);\n }\n return response;\n },\n});\n\nconsole.log(\\`Bun server running at http://localhost:\\${port}\\`);\n`;\n}\n\nfunction relativeToUrlPath(from: string, to: string): string {\n const path = relative(from, to).split(\"\\\\\").join(\"/\");\n return `${path.startsWith(\".\") ? path : `./${path}`}/`;\n}\n","import { mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { build } from \"vite\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { writeSsrEntry } from \"./shared.js\";\nimport { DEFAULT_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Node adapter for elur-kit.\n *\n * Produces a self-contained Node server entry at `.elur/node-server.mjs`.\n * Run it with:\n *\n * node .elur/node-server.mjs\n *\n * The server serves static files from `dist/` and renders pages on demand for\n * unmatched routes.\n */\nexport const nodeAdapter: Adapter = {\n name: \"node\",\n capabilities: DEFAULT_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const generatedDir = resolve(root, \".elur\");\n\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n await rm(generatedDir, { recursive: true, force: true });\n await mkdir(generatedDir, { recursive: true });\n\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"node-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n const serverPath = resolve(generatedDir, \"node-server.ts\");\n await writeFile(\n serverPath,\n buildNodeServerSource(relativeToUrlPath(generatedDir, outDir), options),\n \"utf8\",\n );\n\n await build({\n configFile: false,\n root,\n build: {\n outDir: generatedDir,\n emptyOutDir: false,\n ssr: true,\n lib: {\n entry: serverPath,\n formats: [\"es\"],\n },\n rollupOptions: {\n external: [/^@elurjs\\/kit(?:\\/.*)?$/, /^@elurjs\\/core(?:\\/.*)?$/, /^node:/],\n output: {\n entryFileNames: \"node-server.mjs\",\n inlineDynamicImports: true,\n },\n },\n },\n });\n },\n};\n\nfunction buildNodeServerSource(\n outDirUrl: string,\n options: {\n clientEntry: string;\n lang: string;\n port?: number;\n logLevel?: string;\n redirects?: import(\"../router/redirects.js\").RedirectRule[];\n rewrites?: import(\"../router/redirects.js\").RewriteRule[];\n routeHeaders?: import(\"../router/redirects.js\").RouteHeadersRule[];\n },\n): string {\n const logLevelOption = options.logLevel ? `, logLevel: ${JSON.stringify(options.logLevel)}` : \"\";\n // Rule arrays are plain data: emit them as JSON literals when defined.\n const routingOptions = ([\"redirects\", \"rewrites\", \"routeHeaders\"] as const)\n .map((key) => {\n const rules = options[key];\n return rules && rules.length > 0 ? `, ${key}: ${JSON.stringify(rules)}` : \"\";\n })\n .join(\"\");\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { createServer } from \"node:http\";\nimport { fileURLToPath } from \"node:url\";\nimport { createWebHandler } from \"@elurjs/kit/runtime\";\nimport { incomingMessageToRequest, sendWebResponse } from \"@elurjs/kit/runtime\";\nimport handler from \"./node-index.ts\";\n\nconst outDir = fileURLToPath(new URL(${JSON.stringify(outDirUrl)}, import.meta.url));\nconst port = Number(process.env.PORT) || ${options.port ?? 3000};\n\n// The adapter-bundled handler already handles actions, API routes, render\n// endpoint and dynamic SSR. We only need to add static file serving from\n// the output directory, then fall through to the bundled handler.\nconst webHandler = createWebHandler(\n { pages: [], api: [], error404: undefined, error500: undefined },\n {},\n { staticRoot: outDir, lang: ${JSON.stringify(options.lang)}, clientEntry: ${JSON.stringify(options.clientEntry)}${logLevelOption}${routingOptions} },\n);\n\ncreateServer(async (req, res) => {\n const body = req.method !== \"GET\" && req.method !== \"HEAD\"\n ? await readBody(req)\n : undefined;\n const request = incomingMessageToRequest(req, body);\n // Try static files first via the unified handler, then fall back to the\n // bundled SSR handler for dynamic routes.\n let response = await webHandler(request);\n if (response.status === 404) {\n response = await handler(request);\n }\n // Streams the body: streaming SSR chunks flush as they are produced.\n await sendWebResponse(res, response);\n}).listen(port, () => {\n console.log(\\`Node server running at http://localhost:\\${port}\\`);\n});\n\nfunction readBody(req: import(\"node:http\").IncomingMessage): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));\n req.on(\"end\", () => resolve(Buffer.concat(chunks)));\n req.on(\"error\", reject);\n });\n}\n`;\n}\n\nfunction relativeToUrlPath(from: string, to: string): string {\n const path = relative(from, to).split(\"\\\\\").join(\"/\");\n return `${path.startsWith(\".\") ? path : `./${path}`}/`;\n}\n","// --- CLI commands: check, routes, doctor (plan §12.1) ---\n//\n// `check` — typechecks the project and validates route/config integrity.\n// `routes` — lists all discovered routes and their metadata.\n// `doctor` — diagnoses common configuration and environment issues.\n//\n// All commands produce actionable error messages with cause/path/suggestion\n// and reliable exit codes.\n\nimport { stat, access } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport { scanActions } from \"../action/scan.js\";\nimport type { CliOptions } from \"../cli.js\";\n\n/** Exit codes used by all CLI commands. */\nexport const ExitCode = {\n Success: 0,\n GenericError: 1,\n ConfigError: 2,\n TypeError: 3,\n RouteConflict: 4,\n MissingDependency: 5,\n} as const;\n\n/** Formats an error with cause, path, and suggestion. */\nexport function formatError(\n cause: string,\n path?: string,\n suggestion?: string,\n): string {\n const parts = [cause];\n if (path) parts.push(` at: ${path}`);\n if (suggestion) parts.push(` fix: ${suggestion}`);\n return parts.join(\"\\n\");\n}\n\n// check — typecheck + route/config integrity\n\nexport async function doCheck(options: CliOptions): Promise<number> {\n console.log(\"Running typecheck...\");\n const typecheckResult = await runTypecheck(options.root);\n if (typecheckResult !== 0) {\n console.error(formatError(\n \"Typecheck failed.\",\n undefined,\n \"Fix TypeScript errors above before building.\",\n ));\n return ExitCode.TypeError;\n }\n console.log(\"✓ Typecheck passed\");\n\n console.log(\"\\nValidating routes...\");\n try {\n const routes = await scanRoutes(options.appDir);\n console.log(`✓ ${routes.pages.length} page route(s), ${routes.api.length} API route(s)`);\n if (routes.error404) console.log(\" - 404 page: configured\");\n if (routes.error500) console.log(\" - 500 page: configured\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(formatError(\n \"Route validation failed.\",\n options.appDir,\n message,\n ));\n return ExitCode.RouteConflict;\n }\n\n console.log(\"\\nValidating actions...\");\n try {\n const actions = await scanActions(options.appDir);\n console.log(`✓ ${actions.size} action(s) discovered`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(formatError(\n \"Action validation failed.\",\n options.appDir,\n message,\n ));\n return ExitCode.GenericError;\n }\n\n console.log(\"\\n✓ All checks passed\");\n return ExitCode.Success;\n}\n\n// routes — list all discovered routes\n\nexport async function doRoutes(options: CliOptions): Promise<number> {\n try {\n const routes = await scanRoutes(options.appDir);\n\n console.log(\"\\nPage routes:\");\n if (routes.pages.length === 0) {\n console.log(\" (none)\");\n } else {\n for (const page of routes.pages) {\n const params = page.params.length > 0 ? ` [${page.params.join(\", \")}]` : \"\";\n const loading = page.loadingPath ? \" +loading\" : \"\";\n const action = page.actionPath ? \" +action\" : \"\";\n const data = page.dataPath ? \" +data\" : \"\";\n const optional = page.optionalCatchAll ? \" (optional)\" : \"\";\n console.log(` ${page.path}${params}${data}${loading}${action}${optional}`);\n console.log(` page: ${relative(options.root, page.pagePath)}`);\n if (page.layouts.length > 0) {\n console.log(` layouts: ${page.layouts.map((l) => relative(options.root, l)).join(\" → \")}`);\n }\n }\n }\n\n console.log(\"\\nAPI routes:\");\n if (routes.api.length === 0) {\n console.log(\" (none)\");\n } else {\n for (const api of routes.api) {\n const params = api.params.length > 0 ? ` [${api.params.join(\", \")}]` : \"\";\n console.log(` ${api.path}${params}`);\n console.log(` route: ${relative(options.root, api.routePath)}`);\n }\n }\n\n if (routes.error404) {\n console.log(`\\n404 page: ${relative(options.root, routes.error404.pagePath)}`);\n } else {\n console.log(\"\\n404 page: (not configured)\");\n }\n if (routes.error500) {\n console.log(`500 page: ${relative(options.root, routes.error500.pagePath)}`);\n } else {\n console.log(\"500 page: (not configured)\");\n }\n\n return ExitCode.Success;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(formatError(\"Failed to scan routes.\", options.appDir, message));\n return ExitCode.RouteConflict;\n }\n}\n\n// doctor — diagnose common issues\n\ninterface DiagnosticResult {\n name: string;\n status: \"ok\" | \"warn\" | \"error\";\n message: string;\n suggestion?: string;\n}\n\nexport async function doDoctor(options: CliOptions): Promise<number> {\n const results: DiagnosticResult[] = [];\n\n // Check 1: app directory exists\n results.push(await checkExists(\"App directory\", options.appDir, \"Create src/app/ with at least a page.ts\"));\n\n // Check 2: islands directory exists (optional)\n if (options.islandsDir) {\n results.push(await checkExists(\"Islands directory\", options.islandsDir, \"Create src/islands/ for client-side islands\", \"warn\"));\n }\n\n // Check 3: public directory exists (optional)\n if (options.publicDir) {\n results.push(await checkExists(\"Public directory\", options.publicDir, \"Create public/ for static assets\", \"warn\"));\n }\n\n // Check 4: elur.config.ts exists (optional)\n const preferredPaths = [\"elur.config.ts\", \"elur.config.js\", \"elur.config.mjs\"];\n const legacyPaths = [\"elur.config.ts\", \"elur.config.js\", \"elur.config.mjs\"];\n let configFound = false;\n let foundName: string | undefined;\n let isLegacy = false;\n for (const p of preferredPaths) {\n try {\n await access(join(options.root, p));\n configFound = true;\n foundName = p;\n break;\n } catch {\n // continue\n }\n }\n if (!configFound) {\n for (const p of legacyPaths) {\n try {\n await access(join(options.root, p));\n configFound = true;\n foundName = p;\n isLegacy = true;\n break;\n } catch {\n // continue\n }\n }\n }\n if (configFound && foundName) {\n results.push({\n name: \"Config file\",\n status: isLegacy ? \"warn\" : \"ok\",\n message: `Found ${foundName}${isLegacy ? \" (legacy, rename to elur.config.* )\" : \"\"}`,\n suggestion: isLegacy\n ? `Rename ${foundName} to elur.config.${foundName.split(\".\").slice(1).join(\".\")} (deprecated name)`\n : undefined,\n });\n } else {\n results.push({\n name: \"Config file\",\n status: \"warn\",\n message: \"No elur.config.ts/js/mjs found\",\n suggestion: \"Create elur.config.ts for custom configuration (optional, defaults work)\",\n });\n }\n\n // Check 5: TypeScript config exists\n results.push(await checkExists(\"tsconfig.json\", join(options.root, \"tsconfig.json\"), \"Create a tsconfig.json for TypeScript support\", \"warn\"));\n\n // Check 6: Node.js version\n const nodeVersion = process.versions.node;\n const major = parseInt(nodeVersion.split(\".\")[0]!, 10);\n if (major >= 18) {\n results.push({ name: \"Node.js version\", status: \"ok\", message: `v${nodeVersion}` });\n } else {\n results.push({\n name: \"Node.js version\",\n status: \"error\",\n message: `v${nodeVersion} (requires >= 18)`,\n suggestion: \"Upgrade Node.js to v18 or later\",\n });\n }\n\n // Check 7: routes scan\n try {\n const routes = await scanRoutes(options.appDir);\n results.push({\n name: \"Route scan\",\n status: routes.pages.length > 0 ? \"ok\" : \"warn\",\n message: `${routes.pages.length} page(s), ${routes.api.length} API route(s)`,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n results.push({\n name: \"Route scan\",\n status: \"error\",\n message: message,\n suggestion: \"Fix route conflicts or file structure issues\",\n });\n }\n\n // Check 8: optional peer dependencies\n const peers = [\n { name: \"marked\", import: \"marked\", purpose: \"Markdown rendering\" },\n { name: \"zod\", import: \"zod\", purpose: \"Schema validation\" },\n { name: \"sharp\", import: \"sharp\", purpose: \"Image optimization\" },\n ];\n for (const peer of peers) {\n try {\n await import(peer.import);\n results.push({ name: `Peer dep: ${peer.name}`, status: \"ok\", message: `available (${peer.purpose})` });\n } catch {\n results.push({\n name: `Peer dep: ${peer.name}`,\n status: \"warn\",\n message: `not installed (${peer.purpose})`,\n suggestion: `Install with: bun add ${peer.name}`,\n });\n }\n }\n\n // Print results\n console.log(\"\\nElur Kit doctor\\n\");\n let hasErrors = false;\n let hasWarnings = false;\n for (const result of results) {\n const icon = result.status === \"ok\" ? \"✓\" : result.status === \"warn\" ? \"⚠\" : \"✗\";\n const color = result.status === \"ok\" ? \"\" : result.status === \"warn\" ? \"\" : \"\";\n console.log(`${icon} ${result.name}: ${color}${result.message}`);\n if (result.suggestion) console.log(` → ${result.suggestion}`);\n if (result.status === \"error\") hasErrors = true;\n if (result.status === \"warn\") hasWarnings = true;\n }\n\n console.log(\"\");\n if (hasErrors) {\n console.log(\"✗ Issues found. Fix errors before building.\");\n return ExitCode.GenericError;\n } else if (hasWarnings) {\n console.log(\"⚠ Warnings found. Project may work but consider fixing them.\");\n return ExitCode.Success;\n } else {\n console.log(\"✓ All checks passed. Project is healthy.\");\n return ExitCode.Success;\n }\n}\n\n// Helpers\n\nasync function checkExists(\n name: string,\n path: string,\n suggestion: string,\n level: \"error\" | \"warn\" = \"error\",\n): Promise<DiagnosticResult> {\n try {\n await stat(path);\n return { name, status: \"ok\", message: path };\n } catch {\n return {\n name,\n status: level,\n message: `not found at ${path}`,\n suggestion,\n };\n }\n}\n\nasync function runTypecheck(root: string): Promise<number> {\n return new Promise((resolve) => {\n const child = spawn(\"npx\", [\"tsc\", \"--noEmit\"], {\n cwd: root,\n stdio: \"inherit\",\n shell: true,\n });\n child.on(\"close\", (code) => resolve(code ?? 1));\n child.on(\"error\", () => resolve(1));\n });\n}\n","import { stat } from \"node:fs/promises\";\nimport { createServer } from \"node:http\";\nimport { dirname, join, resolve, relative } from \"node:path\";\nimport { existsSync, watch } from \"node:fs\";\nimport { spawn } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\nimport { createRequire } from \"node:module\";\nimport { build, type BuildConfig } from \"./build/build.js\";\nimport { transformProjectFiles, transformedAppDir as transformedAppDirOf } from \"./build/transform-source.js\";\nimport { scanActions } from \"./action/scan.js\";\nimport { scanRoutes } from \"./router/route-scanner.js\";\nimport { incomingMessageToRequest, sendWebResponse } from \"./runtime/node-http.js\";\nimport { createRequestLogger, type LogLevel } from \"./runtime/logger.js\";\nimport { loadElurConfig, type ResolvedElurConfig } from \"./config/index.js\";\nimport { createAppManifest, writeAppManifest, writeRouteTypes } from \"./manifest/index.js\";\nimport { validateCapabilities } from \"./runtime/capabilities.js\";\nimport * as out from \"./cli/output.js\";\nimport { listenWithFallback, PORT_UNAVAILABLE_EXIT_CODE } from \"./cli/ports.js\";\n\n// --- CLI ---\n//\n// Minimal command-line interface for Elur Kit. Supports:\n// elur-kit build — run a production static build\n// elur-kit dev — run a dev server that rebuilds on file changes\n// elur-kit preview — serve the static build in production mode\n// elur-kit start — run an SSR server that renders pages on demand\n//\n// This is intentionally small: no generators, no config file parsing, just\n// convention-based defaults overridable via CLI flags.\n\nexport interface CliOptions {\n command: \"build\" | \"dev\" | \"preview\" | \"start\" | \"adapter\" | \"check\" | \"routes\" | \"doctor\";\n adapterName?: \"vercel\" | \"netlify\" | \"bun\" | \"node\";\n root: string;\n appDir: string;\n islandsDir?: string;\n outDir: string;\n publicDir?: string;\n generatedEntry: string;\n clientEntry: string;\n port: number;\n host: string;\n lang: string;\n hydrateImport?: string;\n routerImport?: string;\n /**\n * Path to a Vite config used to build the client hydration bundle.\n * In dev mode it is rebuilt whenever source files change.\n */\n clientConfig?: string;\n /** Absolute path to the ISR cache directory. */\n cacheDir?: string;\n /** Default revalidate interval in seconds for ISR. */\n defaultRevalidate?: number;\n configFile?: string;\n resolvedConfig?: ResolvedElurConfig;\n /**\n * Verbosity override from `--verbose` (\"debug\") / `--quiet` (\"error\").\n * Overrides `logger.level` from the config file.\n */\n logLevel?: LogLevel;\n /**\n * Internal: whether the client bundle emits the router as its own chunk\n * (`router.js`). Computed by `doBuild` from the resolved config and the\n * client bundle inputs — `true` for the kit-generated default config and\n * for user configs that declare the generated router module as an input.\n */\n routerSeparate?: boolean;\n /** Internal: whether the last build found any islands. */\n hasIslands?: boolean;\n /**\n * Internal: public URL of the router chunk when the emitted bundle\n * actually contains it (`/_elur/router.js` exists in the output).\n * Computed once per server start for dev/preview/start.\n */\n routerEntry?: string;\n}\n\nfunction parseArgs(argv: string[]): CliOptions {\n const args = argv.slice(2);\n if (args.includes(\"--help\") || args.includes(\"-?\")) {\n printHelp();\n process.exit(0);\n }\n const command = args[0];\n if (\n command !== \"build\" &&\n command !== \"dev\" &&\n command !== \"preview\" &&\n command !== \"start\" &&\n command !== \"adapter\" &&\n command !== \"check\" &&\n command !== \"routes\" &&\n command !== \"doctor\"\n ) {\n throw new Error(`Usage: elur-kit <build|dev|preview|start|adapter|check|routes|doctor> [options]`);\n }\n const adapterName = command === \"adapter\" ? args[1] : undefined;\n if (\n command === \"adapter\" &&\n adapterName !== \"vercel\" &&\n adapterName !== \"netlify\" &&\n adapterName !== \"bun\" &&\n adapterName !== \"node\"\n ) {\n throw new Error(`Usage: elur-kit adapter <vercel|netlify|bun|node> [options]`);\n }\n const optionStart = command === \"adapter\" ? 2 : 1;\n\n let root = process.cwd();\n let appDir = \"src/app\";\n let islandsDir = \"src/islands\";\n let outDir = \"dist\";\n let publicDir = \"public\";\n let generatedEntry = \".elur/entry-client.ts\";\n let clientEntry = \"/_elur/entry-client.js\";\n let port = 3000;\n let host = \"127.0.0.1\";\n let lang = \"es\";\n let hydrateImport: string | undefined;\n let routerImport: string | undefined;\n let clientConfig: string | undefined;\n let cacheDir: string | undefined;\n let defaultRevalidate: number | undefined;\n let configFile: string | undefined;\n let logLevel: LogLevel | undefined;\n\n for (let i = optionStart; i < args.length; i++) {\n const arg = args[i];\n const next = args[i + 1];\n switch (arg) {\n case \"--root\":\n case \"-r\":\n root = next;\n i++;\n break;\n case \"--app\":\n case \"-a\":\n appDir = next;\n i++;\n break;\n case \"--islands\":\n case \"-i\":\n islandsDir = next;\n i++;\n break;\n case \"--out\":\n case \"-o\":\n outDir = next;\n i++;\n break;\n case \"--public\":\n publicDir = next;\n i++;\n break;\n case \"--port\":\n case \"-p\":\n port = Number(next);\n i++;\n break;\n case \"--host\":\n case \"-h\":\n host = next;\n i++;\n break;\n case \"--lang\":\n case \"-l\":\n lang = next;\n i++;\n break;\n case \"--hydrate-import\":\n hydrateImport = next;\n i++;\n break;\n case \"--router-import\":\n routerImport = next;\n i++;\n break;\n case \"--client-config\":\n clientConfig = next;\n i++;\n break;\n case \"--config\":\n configFile = next;\n i++;\n break;\n case \"--cache-dir\":\n cacheDir = next;\n i++;\n break;\n case \"--default-revalidate\":\n defaultRevalidate = Number(next);\n i++;\n break;\n case \"--verbose\":\n // --quiet wins when both are passed.\n if (logLevel !== \"error\") logLevel = \"debug\";\n break;\n case \"--quiet\":\n logLevel = \"error\";\n break;\n case \"--help\":\n case \"-?\":\n printHelp();\n process.exit(0);\n default:\n throw new Error(`Unknown option: ${arg}`);\n }\n }\n\n return {\n command,\n adapterName: adapterName as CliOptions[\"adapterName\"],\n root: resolve(root),\n appDir: resolve(root, appDir),\n islandsDir: resolve(root, islandsDir),\n outDir: resolve(root, outDir),\n publicDir: resolve(root, publicDir),\n generatedEntry: resolve(root, generatedEntry),\n clientEntry,\n port,\n host,\n lang,\n hydrateImport,\n routerImport,\n clientConfig: clientConfig ? resolve(root, clientConfig) : undefined,\n cacheDir: cacheDir ? resolve(root, cacheDir) : undefined,\n defaultRevalidate,\n configFile: configFile ? resolve(root, configFile) : undefined,\n logLevel,\n };\n}\n\nfunction printHelp(): void {\n console.log(`\nelur-kit <command> [options]\n\nCommands:\n build Run a static site build\n dev Run a development server with rebuild-on-change\n preview Serve the static build in production mode\n start Run an SSR server that renders pages on demand\n adapter <name> Generate deployment output for a platform (vercel|netlify|bun|node)\n check Typecheck the project and validate route/config integrity\n routes List all discovered routes and their metadata\n doctor Diagnose common configuration and environment issues\n\nOptions:\n -r, --root <dir> Project root (default: cwd)\n -a, --app <dir> App directory relative to root (default: src/app)\n -i, --islands <dir> Islands directory relative to root (default: src/islands)\n -o, --out <dir> Output directory relative to root (default: dist)\n --public <dir> Public directory relative to root (default: public)\n -p, --port <number> Server port (default: 3000)\n -h, --host <address> Server host (default: 127.0.0.1)\n -l, --lang <lang> HTML lang attribute (default: es)\n --hydrate-import <spec> Import specifier for hydrateIslands in generated entry\n --router-import <spec> Import specifier for startClientRouter in generated entry\n --client-config <path> Vite config used to build the client hydration bundle\n --config <path> Elur config file (default: elur.config.ts/js/mjs)\n --cache-dir <dir> Directory for ISR cache (only used by start)\n --default-revalidate <s> Default ISR revalidate interval in seconds\n --verbose Debug logging (overrides logger.level)\n --quiet Only errors are printed (overrides logger.level)\n`);\n}\n\n/**\n * Reads the kit's own version from package.json. The CLI runs from two\n * layouts: src/cli.ts in the repo (../package.json) and dist/lib/cli.js when\n * installed (../../package.json).\n */\nfunction getKitVersion(): string {\n const require = createRequire(import.meta.url);\n for (const rel of [\"../package.json\", \"../../package.json\"]) {\n try {\n const pkg = require(rel) as { version?: unknown };\n if (typeof pkg.version === \"string\") return pkg.version;\n } catch {\n // Try the next layout.\n }\n }\n return \"unknown\";\n}\n\nfunction toBuildConfig(options: CliOptions): BuildConfig {\n return {\n root: options.root,\n appDir: options.appDir,\n outDir: options.outDir,\n publicDir: options.publicDir,\n clientEntry: options.clientEntry,\n lang: options.lang,\n islandsDir: options.islandsDir,\n generatedEntry: options.generatedEntry,\n hydrateImport: options.hydrateImport,\n routerImport: options.routerImport,\n imageFormats: options.resolvedConfig?.images.formats,\n integrations: options.resolvedConfig?.integrations,\n site: options.resolvedConfig?.site,\n js: options.resolvedConfig?.js,\n router: options.resolvedConfig\n ? {\n enabled: options.resolvedConfig.router.enabled,\n prefetch: options.resolvedConfig.router.prefetch,\n morph: options.resolvedConfig.router.morph,\n loadingIndicator: options.resolvedConfig.router.loadingIndicator,\n speculation: options.resolvedConfig.router.speculation,\n // Whether the bundle emits the router as its own chunk — computed\n // before pages render so the shell knows to advertise router.js.\n separate: options.routerSeparate,\n entry: \"/_elur/router.js\",\n outFile: join(dirname(options.generatedEntry), \"router.ts\"),\n }\n : undefined,\n };\n}\n\nasync function doBuild(options: CliOptions): Promise<void> {\n const buildStart = Date.now();\n const transformedRoot = join(options.root, \".elur\", \"transformed\");\n const transformedAppDir = transformedAppDirOf(options.root, options.appDir, options.islandsDir, transformedRoot);\n let phaseStart = performance.now();\n await transformProjectFiles({\n root: options.root,\n appDir: options.appDir,\n islandsDir: options.islandsDir,\n outDir: transformedRoot,\n });\n out.phase(\"transform\", performance.now() - phaseStart);\n\n // Atomic output staging: build into a temp directory, then swap to the final\n // outDir so a crashed build never leaves a half-written dist.\n const { beginAtomicStage } = await import(\"./build/vite-build.js\");\n const stage = await beginAtomicStage({ outDir: options.outDir });\n const tempOutDir = stage.tempDir;\n\n // Resolve the client bundle layout BEFORE rendering pages: whether the\n // router is emitted as its own chunk decides both the generated entry\n // (hydrate-only vs combined) and which scripts the shell advertises.\n if (options.islandsDir && !options.clientConfig) {\n const autoConfig = await findClientConfig(options.root);\n if (autoConfig) options.clientConfig = autoConfig;\n }\n options.routerSeparate = await resolveRouterSeparate(options);\n\n try {\n const buildConfig = toBuildConfig(options);\n buildConfig.appDir = transformedAppDir;\n buildConfig.outDir = tempOutDir;\n buildConfig.onPhase = (name, ms) => out.phase(name, ms);\n const result = await build(buildConfig);\n options.hasIslands = result.islands.length > 0;\n\n // Emit the portable application manifest and route types when a resolved\n // config is available. The manifest is the source of truth for adapters,\n // the client island registry and runtime route metadata.\n if (options.resolvedConfig) {\n phaseStart = performance.now();\n try {\n const manifest = await createAppManifest(options.resolvedConfig);\n const manifestPath = join(tempOutDir, \".elur\", \"manifest.json\");\n await writeAppManifest(manifest, manifestPath);\n const typesPath = join(options.root, \".elur\", \"routes.d.ts\");\n await writeRouteTypes(manifest, typesPath);\n out.phase(\"manifest\", performance.now() - phaseStart);\n } catch (err) {\n out.warn(`manifest generation failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n // Build the client bundle when there is something to ship: islands to\n // hydrate, a router to run, or an explicit user config (which may bundle\n // extra client code beyond the generated entry). Without a user config,\n // the kit synthesizes a default one from the generated inputs.\n const routerEnabled = options.resolvedConfig?.router.enabled !== false;\n if (options.clientConfig || options.hasIslands || routerEnabled) {\n // Temporarily redirect the client build to the staging directory.\n const originalOutDir = options.outDir;\n options.outDir = tempOutDir;\n try {\n phaseStart = performance.now();\n await buildClient(options);\n out.phase(\"client bundle\", performance.now() - phaseStart);\n } finally {\n options.outDir = originalOutDir;\n }\n }\n\n // Atomically swap the staged output into the final destination.\n await stage.commit();\n\n const elapsed = ((Date.now() - buildStart) / 1000).toFixed(2);\n out.success(`${out.bold(\"Build completo\")} ${out.dim(`en ${elapsed}s`)}`);\n out.info(`${result.pages} página(s), ${result.islands.length} island(s), ${result.files.length} archivo(s)`);\n const fileEntries: out.FileEntry[] = [];\n for (const file of result.files) {\n // result.files point at the staging directory; display the final path.\n const finalPath = join(options.outDir, relative(tempOutDir, file));\n let bytes = 0;\n try {\n bytes = (await stat(finalPath)).size;\n } catch {\n // File may have been moved by an integration; size stays 0.\n }\n fileEntries.push({ path: relative(options.root, finalPath), bytes });\n }\n out.fileList(fileEntries);\n if (result.islands.length > 0) {\n out.success(`${result.islands.length} island(s) detectada(s):`);\n for (const island of result.islands) {\n out.detail(island.name);\n }\n if (result.generatedEntry) {\n out.detail(`entry: ${relative(options.root, result.generatedEntry)}`);\n }\n }\n if (result.skipped.length > 0) {\n out.warn(\"Rutas dinámicas omitidas (necesitan generateStaticParams):\");\n for (const path of result.skipped) {\n out.detail(path);\n }\n }\n } catch (err) {\n await stage.rollback();\n throw err;\n }\n}\n\nconst DEV_WORKER_ENV = \"ELUR_JS_KIT_DEV_WORKER\";\n\nasync function doDev(options: CliOptions): Promise<void> {\n await doBuild(options);\n\n const transformedRoot = join(options.root, \".elur\", \"transformed\");\n const transformedAppDir = transformedAppDirOf(options.root, options.appDir, options.islandsDir, transformedRoot);\n await transformProjectFiles({\n root: options.root,\n appDir: options.appDir,\n islandsDir: options.islandsDir,\n outDir: transformedRoot,\n });\n\n const actions = await scanActions(transformedAppDir);\n const routes = await scanRoutes(transformedAppDir);\n const middleware = await loadUserMiddleware(options.root);\n options.routerEntry = detectRouterEntry(options);\n const server = createServer((req, res) => handleRequest(req, res, options, actions, routes, true, middleware));\n\n const shutdown = () => {\n server.close(() => process.exit(0));\n setTimeout(() => process.exit(0), 2000).unref();\n };\n process.on(\"SIGTERM\", shutdown);\n process.on(\"SIGINT\", shutdown);\n\n try {\n const usedPort = await listenWithFallback(server, options.host, options.port, {\n onFallback: (busyPort, nextPort) => out.warn(`Puerto ${busyPort} ocupado, usando ${nextPort}`),\n });\n const network = out.getNetworkAddress();\n out.serverBanner({\n name: \"elur-kit\",\n version: `v${getKitVersion()}`,\n command: \"dev\",\n localUrl: `http://${options.host}:${usedPort}/`,\n networkUrl: network ? `http://${network}:${usedPort}/` : undefined,\n });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EADDRINUSE\") {\n out.error(`No hay puerto disponible entre ${options.port} y ${options.port + 20}.`);\n // Distinct exit code so the supervisor does not restart-loop.\n process.exit(PORT_UNAVAILABLE_EXIT_CODE);\n }\n throw err;\n }\n}\n\n/**\n * Dev supervisor: runs the actual dev server in a child process and restarts\n * it whenever app/islands source files change. A fresh process means a fresh\n * module registry, so edits to pages, loaders, layouts and islands are always\n * picked up (no stale ESM cache).\n */\nasync function doDevSupervisor(options: CliOptions): Promise<void> {\n // Re-invoke this bin with the same flags; the worker branch (env var set)\n // runs the actual server in a fresh process.\n const binPath = process.argv[1];\n const spawnPath = binPath && existsSync(binPath)\n ? binPath\n : fileURLToPath(import.meta.url);\n const args = process.argv.slice(2);\n\n let child: import(\"node:child_process\").ChildProcess | null = null;\n let stopping = false;\n let intentional = false;\n let respawnTimer: ReturnType<typeof setTimeout> | null = null;\n\n const startWorker = () => {\n intentional = false;\n console.log();\n out.event(\"dev\", \"Starting dev server...\");\n child = spawn(process.execPath, [spawnPath, ...args], {\n env: { ...process.env, [DEV_WORKER_ENV]: \"1\" },\n stdio: \"inherit\",\n });\n child.on(\"exit\", (code) => {\n child = null;\n if (stopping) return;\n if (intentional) {\n // Restart after a source change.\n respawnTimer = setTimeout(startWorker, 400);\n return;\n }\n if (code !== 0) {\n if (code === PORT_UNAVAILABLE_EXIT_CODE) {\n // The worker already reported that no port is available; restarting\n // would loop forever on the same EADDRINUSE.\n out.error(\"[dev] Stopping: no available port.\");\n process.exit(code);\n }\n out.error(`[dev] Dev server exited with code ${code}; restarting...`);\n respawnTimer = setTimeout(startWorker, 600);\n }\n });\n };\n\n const restart = () => {\n if (!child) return;\n intentional = true;\n child.kill(\"SIGTERM\");\n };\n\n const watchedDirs = [options.appDir, options.islandsDir].filter(Boolean) as string[];\n if (watchedDirs.length > 0) {\n let timer: ReturnType<typeof setTimeout> | null = null;\n const scheduleRestart = () => {\n console.log();\n out.event(\"change\", \"Restarting dev server...\");\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => restart(), 150);\n };\n for (const dir of watchedDirs) {\n try {\n watch(dir, { recursive: true }, (event, filename) => {\n // Editors and sed replace files via atomic rename, which reports the\n // temporary name (e.g. \"blog/sed1234\") instead of the .ts file, so\n // treat every rename as a potential source change. \"change\" events\n // only restart when the reported name looks like a source file.\n if (event === \"rename\") {\n scheduleRestart();\n } else if (filename && /\\.ts$/.test(filename)) {\n scheduleRestart();\n }\n });\n } catch (err) {\n out.error(`[dev] failed to watch ${dir}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n }\n\n const cleanup = () => {\n stopping = true;\n if (respawnTimer) clearTimeout(respawnTimer);\n if (child) child.kill(\"SIGTERM\");\n // Exit after the worker has gone, so a new supervisor can take over the port.\n const deadline = setTimeout(() => process.exit(0), 3000);\n deadline.unref();\n if (!child) process.exit(0);\n };\n process.on(\"SIGINT\", cleanup);\n process.on(\"SIGTERM\", cleanup);\n\n startWorker();\n}\n\n/**\n * Shared production-serving path for `preview` and `start`: serves the build\n * output plus dynamic SSR through the unified Web handler, with middleware,\n * streaming, port fallback and the startup banner. Both commands behave\n * identically; the label only differs in the banner.\n */\nasync function startProductionServer(\n options: CliOptions,\n command: \"preview\" | \"start\",\n): Promise<import(\"node:http\").Server> {\n try {\n const s = await stat(options.outDir);\n if (!s.isDirectory()) {\n throw new Error(`Output path is not a directory: ${options.outDir}`);\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n throw new Error(\n `No build output found at ${options.outDir}. Run \\`elur-kit build\\` first.`,\n );\n }\n throw err;\n }\n\n const transformedRoot = join(options.root, \".elur\", command === \"preview\" ? \"preview-transformed\" : \"transformed\");\n const transformedAppDir = transformedAppDirOf(options.root, options.appDir, options.islandsDir, transformedRoot);\n await transformProjectFiles({\n root: options.root,\n appDir: options.appDir,\n islandsDir: options.islandsDir,\n outDir: transformedRoot,\n });\n\n const actions = await scanActions(transformedAppDir);\n const routes = await scanRoutes(transformedAppDir);\n const middleware = await loadUserMiddleware(options.root);\n options.routerEntry = detectRouterEntry(options);\n const server = createServer((req, res) => handleRequest(req, res, options, actions, routes, false, middleware));\n const usedPort = await listenWithFallback(server, options.host, options.port, {\n onFallback: (busyPort, nextPort) => out.warn(`Puerto ${busyPort} ocupado, usando ${nextPort}`),\n });\n const network = out.getNetworkAddress();\n out.serverBanner({\n name: \"elur-kit\",\n version: `v${getKitVersion()}`,\n command,\n localUrl: `http://${options.host}:${usedPort}/`,\n networkUrl: network ? `http://${network}:${usedPort}/` : undefined,\n });\n return server;\n}\n\nexport async function doPreview(options: CliOptions): Promise<import(\"node:http\").Server> {\n return startProductionServer(options, \"preview\");\n}\n\nasync function doStart(options: CliOptions): Promise<void> {\n // `start` now runs on the unified Web handler like dev/preview (it used to\n // rely on the legacy createSsrServer pipeline).\n await startProductionServer(options, \"start\");\n}\n\nasync function findClientConfig(root: string): Promise<string | undefined> {\n const candidates = [\"vite.client.config.ts\", \"vite.client.config.js\", \"vite.client.config.mjs\"];\n for (const name of candidates) {\n const path = resolve(root, name);\n try {\n if ((await stat(path)).isFile()) return path;\n } catch {\n // ignore\n }\n }\n return undefined;\n}\n\n/**\n * Decides whether the client bundle emits the router as its own chunk.\n *\n * - `js: \"legacy\"` or `router.enabled: false` → never split (the entry is\n * hydrate-only when the router is off; legacy embeds the router).\n * - A user-provided client config splits only when it declares the generated\n * router module (`.elur/router.ts`) as a bundle input — a single input is\n * \"legacy de facto\": the router stays embedded in `entry-client.js`.\n * - Without a user config, the kit synthesizes a default two-input config →\n * split.\n */\nasync function resolveRouterSeparate(options: CliOptions): Promise<boolean> {\n const rc = options.resolvedConfig;\n if (!rc || rc.js === \"legacy\" || rc.router.enabled === false) return false;\n const routerFile = join(dirname(options.generatedEntry), \"router.ts\");\n if (!options.clientConfig) return true;\n try {\n const { resolveClientInputs } = await import(\"./build/vite-build.js\");\n const inputs = await resolveClientInputs(options.clientConfig, options.root);\n return inputs.includes(routerFile);\n } catch {\n return false;\n }\n}\n\n/**\n * Public URL of the router chunk when the built bundle actually contains it.\n * The file check keeps `preview`/`start` consistent with whatever layout the\n * last build produced (split or legacy single-entry).\n */\nfunction detectRouterEntry(options: CliOptions): string | undefined {\n const rc = options.resolvedConfig;\n if (!rc || rc.js === \"legacy\" || rc.router.enabled === false) return undefined;\n return existsSync(join(options.outDir, \"_elur\", \"router.js\"))\n ? \"/_elur/router.js\"\n : undefined;\n}\n\nasync function buildClient(options: CliOptions): Promise<void> {\n // Use the programmatic Vite build API instead of spawnSync(\"npx\", [\"vite\", ...]).\n // This avoids child-process overhead, shares the module cache, and gives us\n // structured errors instead of exit-code parsing.\n const { buildClientBundle } = await import(\"./build/vite-build.js\");\n const clientOutDir = join(options.outDir, \"_elur\");\n // The client bundle is always served from /_elur/ regardless of the\n // project's deployment base. The deployment base is applied to page HTML,\n // not to the internal hydration bundle path.\n const clientBase = \"/_elur/\";\n // Inputs for the kit-synthesized default config (used only when the\n // project does not ship its own vite.client.config.*).\n const defaultInputs: Record<string, string> = {\n \"entry-client\": options.generatedEntry,\n };\n if (options.routerSeparate) {\n defaultInputs.router = join(dirname(options.generatedEntry), \"router.ts\");\n }\n await buildClientBundle({\n root: options.root,\n userConfigPath: options.clientConfig ? resolve(options.clientConfig) : undefined,\n defaultInputs,\n appDir: join(options.root, \"src\", \"app\"),\n islandsDir: join(options.root, \"src\", \"islands\"),\n outDir: clientOutDir,\n base: clientBase,\n logPrefix: \"[client]\",\n quiet: options.logLevel === \"error\",\n });\n}\n\n/**\n * Loads the project's `src/middleware.ts` for dev/preview/start. A missing\n * file is fine; a broken one warns but does not stop the server.\n */\nasync function loadUserMiddleware(\n root: string,\n): Promise<import(\"./middleware/index.js\").LoadedMiddleware | null> {\n const { loadMiddleware } = await import(\"./middleware/index.js\");\n try {\n return await loadMiddleware(root);\n } catch (err) {\n out.warn(err instanceof Error ? err.message : String(err));\n return null;\n }\n}\n\nasync function handleRequest(\n req: import(\"node:http\").IncomingMessage,\n res: import(\"node:http\").ServerResponse,\n options: CliOptions,\n actions: import(\"./action/scan.js\").ActionRegistry,\n routes: import(\"./router/route-scanner.js\").ScannedRoutes,\n noCache = false,\n middleware?: import(\"./middleware/index.js\").LoadedMiddleware | null,\n): Promise<void> {\n // Unified pipeline: actions, render endpoint, API routes, static files and\n // dynamic SSR all run through `createWebHandler`, the same code used by the\n // Node/Bun/Vercel/Netlify adapters. This eliminates the duplicated request\n // handling that previously diverged between dev/preview/start and adapters\n // (audit §8.1, Risk 1).\n const { createWebHandler } = await import(\"./runtime/handler.js\");\n const securityHeaders = (options.resolvedConfig as { security?: { headers?: unknown } } | undefined)?.security?.headers;\n const webHandler = createWebHandler(\n routes,\n actions,\n {\n staticRoot: options.outDir,\n noCache,\n cacheDir: options.cacheDir,\n defaultRevalidate: options.defaultRevalidate,\n lang: options.lang,\n clientEntry: options.clientEntry,\n renderEndpoint: true,\n router: {\n enabled: options.resolvedConfig?.router.enabled ?? true,\n entry: options.routerEntry,\n },\n js: options.resolvedConfig?.js,\n securityHeaders: securityHeaders === undefined ? false : (securityHeaders as never),\n logLevel: options.resolvedConfig?.logger?.level,\n cacheAdapter: options.resolvedConfig?.cache?.adapter,\n redirects: options.resolvedConfig?.redirects,\n rewrites: options.resolvedConfig?.rewrites,\n routeHeaders: options.resolvedConfig?.headers,\n streaming: options.resolvedConfig?.streaming,\n middleware: middleware ?? undefined,\n },\n );\n\n const body = req.method && req.method !== \"GET\" && req.method !== \"HEAD\"\n ? await readRequestBody(req)\n : undefined;\n const request = incomingMessageToRequest(req, body);\n let response: Response;\n try {\n response = await webHandler(request);\n } catch (err) {\n // Last-resort failure outside the unified handler: log through the\n // structured logger at server level (a fresh per-request logger, since\n // the handler's own logger is unreachable here).\n createRequestLogger(request, options.resolvedConfig?.logger?.level).error(\"[elur-kit] request error\", {\n path: new URL(request.url).pathname,\n method: request.method,\n error: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n });\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(\"Internal Server Error\");\n return;\n }\n // Stream the response body to the socket: for streaming SSR responses the\n // chunks are flushed as they are produced instead of being buffered whole.\n await sendWebResponse(res, response);\n}\n\nfunction readRequestBody(req: import(\"node:http\").IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let body = \"\";\n req.setEncoding(\"utf8\");\n req.on(\"data\", (chunk) => {\n body += chunk;\n });\n req.on(\"end\", () => resolve(body));\n req.on(\"error\", reject);\n });\n}\n\nasync function doAdapter(options: CliOptions): Promise<void> {\n const adapterOptions = {\n root: options.root,\n appDir: options.appDir,\n islandsDir: options.islandsDir ?? resolve(options.root, \"src/islands\"),\n outDir: options.outDir,\n publicDir: options.publicDir,\n clientEntry: options.clientEntry,\n lang: options.lang,\n hydrateImport: options.hydrateImport,\n logLevel: options.resolvedConfig?.logger?.level,\n cacheAdapter: options.resolvedConfig?.cache?.adapter,\n redirects: options.resolvedConfig?.redirects,\n rewrites: options.resolvedConfig?.rewrites,\n routeHeaders: options.resolvedConfig?.headers,\n streaming: options.resolvedConfig?.streaming,\n router: { enabled: options.resolvedConfig?.router.enabled ?? true },\n js: options.resolvedConfig?.js,\n };\n const resolvedConfig = options.resolvedConfig as { images?: { strict?: boolean }; cache?: { defaultRevalidate?: number }; streaming?: boolean } | undefined;\n const features = {\n isr: typeof resolvedConfig?.cache?.defaultRevalidate === \"number\" && resolvedConfig.cache.defaultRevalidate > 0,\n images: resolvedConfig?.images?.strict === true,\n streaming: resolvedConfig?.streaming === true,\n };\n let adapterName = options.adapterName;\n if (adapterName === \"vercel\") {\n const { vercelAdapter } = await import(\"./adapters/vercel.js\");\n assertCapabilities(vercelAdapter, features, adapterName);\n await vercelAdapter.build(adapterOptions);\n console.log();\n out.info(\"Vercel output generated at .vercel/output\");\n } else if (adapterName === \"netlify\") {\n const { netlifyAdapter } = await import(\"./adapters/netlify.js\");\n assertCapabilities(netlifyAdapter, features, adapterName);\n await netlifyAdapter.build(adapterOptions);\n console.log();\n out.info(\"Netlify output generated at netlify/functions/__elur-js-kit.mjs\");\n } else if (adapterName === \"bun\") {\n const { bunAdapter } = await import(\"./adapters/bun.js\");\n assertCapabilities(bunAdapter, features, adapterName);\n await bunAdapter.build(adapterOptions);\n console.log();\n out.info(\"Bun server generated at .elur/bun-server.ts\");\n } else if (adapterName === \"node\") {\n const { nodeAdapter } = await import(\"./adapters/node.js\");\n assertCapabilities(nodeAdapter, features, adapterName);\n await nodeAdapter.build(adapterOptions);\n console.log();\n out.info(\"Node server generated at .elur/node-server.mjs\");\n }\n}\n\nfunction assertCapabilities(\n adapter: { capabilities?: import(\"./runtime/capabilities.js\").AdapterCapabilities },\n features: { isr: boolean; images: boolean; streaming?: boolean },\n adapterName: string,\n): void {\n if (!adapter.capabilities) return;\n const diagnostics = validateCapabilities(adapter.capabilities, features);\n if (!diagnostics.ok) {\n throw new Error(\n `[elur-kit] Adapter \"${adapterName}\" cannot satisfy the requested features:\\n - ${diagnostics.problems.join(\"\\n - \")}`,\n );\n }\n}\n\nasync function applyProjectConfig(options: CliOptions, argv: string[]): Promise<void> {\n // Map non-build commands to \"build\" or \"serve\" for config resolution.\n const command = (options.command === \"adapter\" || options.command === \"routes\" || options.command === \"doctor\")\n ? \"build\"\n : options.command;\n const config = await loadElurConfig({\n root: options.root,\n configFile: options.configFile,\n command,\n });\n const args = argv.slice(2);\n const has = (...names: string[]) => names.some((name) => args.includes(name));\n options.root = config.root;\n if (!has(\"--app\", \"-a\")) options.appDir = config.appDir;\n if (!has(\"--islands\", \"-i\")) options.islandsDir = config.islandsDir;\n if (!has(\"--out\", \"-o\")) options.outDir = config.outDir;\n if (!has(\"--public\")) options.publicDir = config.publicDir;\n if (!has(\"--cache-dir\")) options.cacheDir = config.cache.dir;\n if (!has(\"--default-revalidate\")) options.defaultRevalidate = config.cache.defaultRevalidate;\n // --verbose/--quiet override logger.level from the config file.\n if (options.logLevel) config.logger.level = options.logLevel;\n options.generatedEntry = resolve(config.root, \".elur/entry-client.ts\");\n options.resolvedConfig = config;\n}\n\nexport async function run(argv: string[]): Promise<void> {\n const options = parseArgs(argv);\n if (options.logLevel === \"error\") out.setQuiet(true);\n\n // Commands that don't need project config resolution.\n if (options.command === \"doctor\") {\n const { doDoctor } = await import(\"./cli/commands.js\");\n const code = await doDoctor(options);\n process.exit(code);\n }\n\n await applyProjectConfig(options, argv);\n\n if (options.command === \"build\") {\n await doBuild(options);\n } else if (options.command === \"preview\") {\n await doPreview(options);\n } else if (options.command === \"start\") {\n await doStart(options);\n } else if (options.command === \"adapter\") {\n await doAdapter(options);\n } else if (options.command === \"check\") {\n const { doCheck } = await import(\"./cli/commands.js\");\n const code = await doCheck(options);\n process.exit(code);\n } else if (options.command === \"routes\") {\n const { doRoutes } = await import(\"./cli/commands.js\");\n const code = await doRoutes(options);\n process.exit(code);\n } else if (process.env[DEV_WORKER_ENV] === \"1\") {\n await doDev(options);\n } else {\n await doDevSupervisor(options);\n }\n}\n"],"mappings":"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"}
|