@elurjs/kit 2.4.4 → 2.4.6
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 +24 -0
- package/README.md +9 -3
- package/dist/lib/cli.cjs.map +1 -1
- package/dist/lib/cli.js.map +1 -1
- package/dist/lib/{hydrate-CgZGrTxF.js → hydrate-CJbUWdXu.js} +2 -2
- package/dist/lib/hydrate-CJbUWdXu.js.map +1 -0
- package/dist/lib/hydrate-D6MR24mz.cjs +2 -0
- package/dist/lib/hydrate-D6MR24mz.cjs.map +1 -0
- package/dist/lib/index.cjs +1 -1
- package/dist/lib/index.js +1 -1
- package/dist/lib/island/index.cjs +1 -1
- package/dist/lib/island/index.js +1 -1
- package/dist/lib/node-http-DRAUhO0c.js.map +1 -1
- package/dist/lib/node-http-DhxguYyz.cjs.map +1 -1
- package/package.json +5 -4
- package/dist/lib/hydrate-8a3TbQbs.cjs +0 -2
- package/dist/lib/hydrate-8a3TbQbs.cjs.map +0 -1
- package/dist/lib/hydrate-CgZGrTxF.js.map +0 -1
package/dist/lib/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","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/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/build/build.ts","../../src/vite/interpolation-plugin.ts","../../src/build/transform-source.ts","../../src/errors.ts","../../src/action/origin.ts","../../src/action/server.ts","../../src/cache.ts","../../src/ssr/match.ts","../../src/ssr/stream.ts","../../src/middleware/index.ts","../../src/runtime/node-http.ts","../../src/runtime/static.ts","../../src/ssr/server.ts","../../src/config/index.ts","../../src/manifest/index.ts","../../src/runtime/capabilities.ts","../../src/build/vite-build.ts","../../src/runtime/context.ts","../../src/runtime/security-headers.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, 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/** 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\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/** 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): 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};\nhydrateIslands(registry);\ndocument.addEventListener(\"elur:rendered\", () => {\n cleanupHydratedIslands();\n hydrateIslands(registry);\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((newModule) => {\n cleanupHydratedIslands();\n hydrateIslands(registry);\n if (newModule) {\n // Re-run the module so its side effects (router, listeners) apply.\n }\n });\n}`\n : \"\";\n\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { startClientRouter } from ${JSON.stringify(routerImport)};\nimport { hydrateIslands, cleanupHydratedIslands } from ${JSON.stringify(hydrateImport)};\n\nstartClientRouter();\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.\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 );\n await mkdir(dirname(options.outFile), { recursive: true });\n await writeFile(options.outFile, source, \"utf8\");\n return options.outFile;\n}\n","// --- SSR flag utility ---\n//\n// Elur 2.6.0 (published on npm) does not export `_setSSR`/`_isSSR`. The\n// reactivity state lives on `globalThis[Symbol.for(\"@elurjs/core/reactivity-state\")]`\n// and exposes an `ssr` boolean that, when true, makes effects run a single\n// pass without subscribing — exactly what we need during server rendering.\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 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 /** Path to the client entry module, e.g. `/_elur/entry-client.js`. */\n clientEntry?: string;\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\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 */\nfunction 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/** 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, 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 const entryScript = clientEntry\n ? `\\n <script type=\"module\" src=\"${escapeHtml(clientEntry)}\"></script>`\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 const renderEndpointMeta =\n opts.renderEndpoint === 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}\n </head>\n <body>\n <div id=\"app\">${body}</div>${dataScript}${actionsScript}${entryScript}\n </body>\n</html>\n`;\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 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\">;\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 * 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 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: config.clientEntry,\n renderEndpoint: config.renderEndpoint,\n });\n\n const head = metadata ? buildHeadTags(metadata, resolvedTitle) : \"\";\n return { html, revalidate, clearActionErrorCookie, head, resolvedTitle, cachePolicy };\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\">;\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","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 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 * 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\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 routes = await scanRoutes(config.appDir);\n const actions = await scanActions(config.appDir);\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 });\n }\n\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 = { lang: config.lang, clientEntry: config.clientEntry, renderEndpoint: false };\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\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 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 }\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 await runIntegrationHook(config.integrations, \"build\", [\n result,\n { root: config.root ?? config.outDir, command: \"build\" },\n ]);\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: { lang: config.lang, clientEntry: config.clientEntry, renderEndpoint: false },\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\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","/**\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","import type { ActionRequest } from \"./index.js\";\nimport { isActionFailure, isRedirectResponse, publicErrorResponse } from \"../errors.js\";\nimport { verifyOrigin, originForbidden, type OriginCheckOptions } from \"./origin.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 const result = await action(...args);\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 { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\n\nexport interface CacheEntry {\n html: string;\n generatedAt: number;\n revalidate: number;\n}\n\nexport interface CacheOptions {\n cacheDir: string;\n defaultRevalidate?: number;\n}\n\nfunction cachePath(cacheDir: string, pathname: string): string {\n const key = createHash(\"sha256\").update(pathname).digest(\"hex\");\n return join(cacheDir, `${key}.html.json`);\n}\n\nexport async function getCachedHtml(\n cacheDir: string,\n pathname: string,\n): Promise<CacheEntry | undefined> {\n const path = cachePath(cacheDir, pathname);\n try {\n const raw = await readFile(path, \"utf8\");\n const entry = JSON.parse(raw) as CacheEntry;\n if (Date.now() - entry.generatedAt < entry.revalidate * 1000) {\n return entry;\n }\n } catch {\n // cache miss or invalid\n }\n return undefined;\n}\n\nexport async function setCachedHtml(\n cacheDir: string,\n pathname: string,\n html: string,\n revalidate: number,\n): Promise<void> {\n const path = cachePath(cacheDir, pathname);\n await mkdir(dirname(path), { recursive: true });\n const entry: CacheEntry = { html, generatedAt: Date.now(), revalidate };\n const temporaryPath = `${path}.${process.pid}.${randomUUID()}.tmp`;\n try {\n await writeFile(temporaryPath, JSON.stringify(entry), \"utf8\");\n await rename(temporaryPath, path);\n } finally {\n await rm(temporaryPath, { force: true });\n }\n}\n\nexport async function isStale(cacheDir: string, pathname: string): Promise<boolean> {\n const path = cachePath(cacheDir, pathname);\n try {\n const raw = await readFile(path, \"utf8\");\n const entry = JSON.parse(raw) as CacheEntry;\n return Date.now() - entry.generatedAt >= entry.revalidate * 1000;\n } catch {\n return true;\n }\n}\n\nexport async function clearCache(cacheDir: string): Promise<void> {\n try {\n await rm(cacheDir, { recursive: true, force: true });\n } catch {\n // ignore\n }\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","import type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString } from \"../render/render-to-string.js\";\nimport { documentShell } 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 */\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\">;\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 /** 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 bodyMatch = result.html.match(/<div id=\"app\">([\\s\\S]*)<\\/div>\\s*(<script|$)/);\n const body = bodyMatch ? bodyMatch[1].trim() : 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 };\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","import type { IncomingMessage } 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","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 { createServer, type IncomingMessage, type Server } from \"node:http\";\nimport { readFile } from \"node:fs/promises\";\nimport { extname } from \"node:path\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport { scanActions, actionNames } from \"../action/scan.js\";\nimport { handleActionRequest, type ActionSecurityOptions } from \"../action/server.js\";\nimport { getCachedHtml, setCachedHtml } from \"../cache.js\";\nimport { matchApiRoute, matchRoute } from \"./match.js\";\nimport { renderPage, renderErrorPage } from \"./render.js\";\nimport { renderPageBody, renderStreamingPage, RouteNotFoundError } from \"./stream.js\";\nimport { loadMiddleware, matchesMiddleware, runMiddleware } from \"../middleware/index.js\";\nimport { incomingMessageToRequest } from \"../runtime/node-http.js\";\nimport { resolveStaticFile } from \"../runtime/static.js\";\nimport { toPublicErrorInfo } from \"../errors.js\";\n\nexport interface SsrServerOptions {\n /** Absolute path to the app directory (e.g. /project/src/app). */\n appDir: string;\n /** Absolute path to the project root. When provided, action paths in the\n * serialized HTML shell are made relative to this root. */\n root?: string;\n /** Absolute path to the public directory for static files (optional). */\n publicDir?: 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 port?: number;\n host?: string;\n /** Absolute path to the ISR cache directory (optional). */\n cacheDir?: string;\n /** Default revalidate interval in seconds when a page does not export one. */\n defaultRevalidate?: number;\n /** If true, render pages with loading.ts boundaries using streaming. */\n streaming?: boolean;\n /** CSRF / origin policy applied to the server actions endpoint. */\n actionSecurity?: ActionSecurityOptions;\n}\n\nexport interface SsrServer {\n server: Server;\n listen(): Promise<void>;\n close(): Promise<void>;\n}\n\n/**\n * Create an SSR server that renders pages on demand and serves static files.\n */\nexport async function createSsrServer(options: SsrServerOptions): Promise<SsrServer> {\n const routes = await scanRoutes(options.appDir);\n const actions = await scanActions(options.appDir);\n const publicActions = actionNames(actions);\n\n // Load user middleware (src/middleware.ts) if it exists.\n const middleware = options.root ? await loadMiddleware(options.root) : null;\n\n const resolveAction = async (name: string, page?: string) => {\n const pageKey = resolveActionPageKey(page, routes);\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 const mod = (await import(actionPath)) as Record<string, unknown>;\n const action = mod[name];\n if (typeof action === \"function\") {\n return action as (...args: unknown[]) => unknown;\n }\n return undefined;\n };\n\n const server = createServer(async (req, res) => {\n let urlPath = req.url ?? \"/\";\n if (urlPath.includes(\"?\")) urlPath = urlPath.split(\"?\")[0];\n\n // Server actions endpoint.\n if (urlPath === \"/__elur-js/actions\" && req.method === \"POST\") {\n try {\n const body = await readRequestBody(req);\n const request = incomingMessageToRequest(req, body);\n const response = await handleActionRequest(request, resolveAction, options.actionSecurity);\n res.writeHead(response.status, Object.fromEntries(response.headers.entries()));\n res.end(await response.text());\n } catch (err) {\n console.error(\"[action] error handling\", err);\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(toPublicErrorInfo(err).message);\n }\n return;\n }\n\n if (urlPath === \"/__elur-js/render\") {\n const renderUrl = new URL(req.url ?? \"/\", \"http://localhost\");\n const page = renderUrl.searchParams.get(\"page\") ?? \"/\";\n const search = renderUrl.searchParams.get(\"search\") ?? \"\";\n const wantsJson = (req.headers[\"accept\"] ?? \"\").includes(\"application/json\");\n try {\n const request = incomingMessageToRequest(req);\n\n // ISR: cache the real content served by this endpoint when a cache\n // directory is configured, so streamed pages regenerate on a TTL.\n let body: string;\n let title: string;\n let lastRenderedCookie: string | undefined;\n let lastRenderedHead: string | undefined;\n const ttl = await resolveTtl(options, page, routes);\n const cacheKey = `/__elur-js/render${page}?${search}`;\n if (options.cacheDir && typeof ttl === \"number\" && canUsePublicCache(request)) {\n const cached = await getCachedHtml(options.cacheDir, cacheKey);\n if (cached) {\n body = extractBody(cached.html);\n title = extractTitle(cached.html);\n } else {\n const rendered = await renderPageBody({\n routes,\n pathname: page,\n searchParams: new URLSearchParams(search),\n config: { lang: options.lang ?? \"es\", clientEntry: options.clientEntry },\n actions: publicActions,\n request,\n });\n body = rendered.body;\n title = rendered.title;\n lastRenderedCookie = rendered.clearActionErrorCookie;\n lastRenderedHead = rendered.head;\n await setCachedHtml(options.cacheDir, cacheKey, rendered.fullHtml ?? \"\", ttl);\n }\n } else {\n const rendered = await renderPageBody({\n routes,\n pathname: page,\n searchParams: new URLSearchParams(search),\n config: { lang: options.lang ?? \"es\", clientEntry: options.clientEntry },\n actions: publicActions,\n request,\n });\n body = rendered.body;\n title = rendered.title;\n lastRenderedCookie = rendered.clearActionErrorCookie;\n lastRenderedHead = rendered.head;\n }\n\n if (wantsJson) {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json; charset=utf-8\" };\n // The SPA router applies the cookie via document.cookie so the next\n // full reload does not re-feed stale errors to the page.\n const setCookie = lastRenderedCookie;\n if (setCookie) headers[\"X-Elur-Action-Clear-Cookie\"] = setCookie;\n res.writeHead(200, headers);\n res.end(JSON.stringify({ title, body, head: lastRenderedHead, clearActionErrorCookie: setCookie }));\n } else {\n const headers: Record<string, string> = { \"Content-Type\": \"text/html; charset=utf-8\" };\n if (lastRenderedCookie) headers[\"Set-Cookie\"] = lastRenderedCookie;\n res.writeHead(200, headers);\n res.end(body);\n }\n } catch (err) {\n if (err instanceof RouteNotFoundError) {\n console.log(`[ssr] render endpoint: no route for ${page}`);\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not Found\");\n return;\n }\n console.error(\"[ssr] streaming render error\", err);\n res.writeHead(500, { \"Content-Type\": \"text/plain\" });\n res.end(\"Internal Server Error\");\n }\n return;\n }\n\n // Run middleware before routing (skip for internal endpoints handled above).\n let middlewareHeaders: Record<string, string> | undefined;\n if (middleware && matchesMiddleware(urlPath, middleware.config)) {\n const mwResult = await runMiddleware(middleware, incomingMessageToRequest(req));\n if (mwResult.kind === \"response\") {\n res.writeHead(mwResult.response.status, Object.fromEntries(mwResult.response.headers.entries()));\n res.end(Buffer.from(await mwResult.response.arrayBuffer()));\n return;\n }\n middlewareHeaders = mwResult.headers;\n }\n\n // Try API routes first.\n const apiMatch = matchApiRoute(urlPath, routes.api);\n if (apiMatch) {\n try {\n const mod = (await import(apiMatch.route.routePath)) as Record<\n string,\n (request: Request, context?: { params: Record<string, string | string[]> }) => unknown\n >;\n const handler = mod[req.method ?? \"GET\"];\n if (typeof handler !== \"function\") {\n res.writeHead(405, { \"Content-Type\": \"text/plain\" });\n res.end(`Method not allowed: ${req.method}`);\n return;\n }\n const body = req.method && req.method !== \"GET\" && req.method !== \"HEAD\" ? await readRequestBody(req) : undefined;\n const request = incomingMessageToRequest(req, body);\n applyHeaders(request.headers, middlewareHeaders);\n const response = (await handler(request, { params: apiMatch.params })) as Response;\n res.writeHead(response.status, Object.fromEntries(response.headers.entries()));\n res.end(Buffer.from(await response.arrayBuffer()));\n } catch (err) {\n console.error(\"[api] error handling\", urlPath, err);\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(toPublicErrorInfo(err).message);\n }\n return;\n }\n\n // Try static files first.\n if (options.publicDir) {\n try {\n const served = await tryServeStatic(res, options.publicDir, urlPath);\n if (served) return;\n } catch (err) {\n console.error(\"[static] error serving\", urlPath, err);\n }\n }\n\n // Try SSR page rendering.\n const match = matchRoute(urlPath, routes.pages);\n const config = { lang: options.lang ?? \"es\", clientEntry: options.clientEntry };\n if (match) {\n try {\n const request = incomingMessageToRequest(req);\n applyHeaders(request.headers, middlewareHeaders);\n\n let html: string;\n let clearActionErrorCookie: string | undefined;\n const revalidate = match.route.dataPath\n ? ((await import(match.route.dataPath)) as { revalidate?: number }).revalidate\n : undefined;\n const ttl = revalidate ?? options.defaultRevalidate;\n const useStreaming = options.streaming !== false && match.route.loadingPath;\n if (useStreaming) {\n html = await renderStreamingPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(req.url?.split(\"?\")[1] ?? \"\"),\n config,\n actions: publicActions,\n request,\n });\n } else if (options.cacheDir && typeof ttl === \"number\" && canUsePublicCache(request)) {\n const cacheKey = new URL(request.url).pathname + new URL(request.url).search;\n const cached = await getCachedHtml(options.cacheDir, cacheKey);\n if (cached) {\n html = cached.html;\n } else {\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(req.url?.split(\"?\")[1] ?? \"\"),\n config,\n actions: publicActions,\n request,\n });\n html = result.html;\n clearActionErrorCookie = result.clearActionErrorCookie;\n await setCachedHtml(options.cacheDir, cacheKey, html, ttl);\n }\n } else {\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(req.url?.split(\"?\")[1] ?? \"\"),\n config,\n actions: publicActions,\n request,\n });\n html = result.html;\n clearActionErrorCookie = result.clearActionErrorCookie;\n }\n const responseHeaders: Record<string, string> = { \"Content-Type\": \"text/html; charset=utf-8\" };\n if (clearActionErrorCookie) responseHeaders[\"Set-Cookie\"] = clearActionErrorCookie;\n res.writeHead(200, responseHeaders);\n res.end(html);\n return;\n } catch (err) {\n console.error(\"[ssr] error rendering\", urlPath, err);\n const errorResult = await renderErrorPage({\n routes,\n status: 500,\n error: err,\n config,\n actions: publicActions,\n });\n if (errorResult) {\n res.writeHead(errorResult.status, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(errorResult.html);\n } else {\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(toPublicErrorInfo(err).message);\n }\n return;\n }\n }\n\n const errorResult = await renderErrorPage({\n routes,\n status: 404,\n config,\n actions: publicActions,\n });\n if (errorResult) {\n res.writeHead(errorResult.status, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(errorResult.html);\n return;\n }\n\n res.writeHead(404, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(`Not found: ${req.url}`);\n });\n\n return {\n server,\n listen() {\n return new Promise((resolve) => {\n server.listen(options.port ?? 3000, options.host ?? \"127.0.0.1\", () => {\n console.log(\n `\\n → SSR server http://${options.host ?? \"127.0.0.1\"}:${options.port ?? 3000}`,\n );\n resolve();\n });\n });\n },\n close() {\n return new Promise((resolve, reject) => {\n server.close((err) => (err ? reject(err) : resolve()));\n });\n },\n };\n}\n\nasync function tryServeStatic(\n res: import(\"node:http\").ServerResponse,\n publicDir: string,\n urlPath: string,\n): Promise<boolean> {\n const filePath = await resolveStaticFile(publicDir, urlPath);\n if (!filePath) return false;\n const contentType = guessContentType(filePath);\n let data: Buffer | string = await readFile(filePath);\n if (contentType.includes(\"text/html\")) {\n // The SSG build bakes `render-endpoint content=\"off\"` into the static\n // HTML so purely static deployments never probe the endpoint. This server\n // (SSR `start`) DOES expose /__elur-js/render, so advertise it: SPA\n // navigations then fetch live server-rendered content instead of the\n // stale static file (e.g. after a mutating server action).\n data = data\n .toString(\"utf8\")\n .replace(\n '<meta name=\"elur:render-endpoint\" content=\"off\" />',\n '<meta name=\"elur:render-endpoint\" content=\"on\" />',\n );\n }\n res.writeHead(200, { \"Content-Type\": contentType, \"Content-Length\": Buffer.byteLength(data) });\n res.end(data);\n return true;\n}\n\nfunction canUsePublicCache(request: Request): boolean {\n return !request.headers.has(\"cookie\") && !request.headers.has(\"authorization\");\n}\n\nfunction applyHeaders(headers: Headers, values: Record<string, string> | undefined): void {\n if (!values) return;\n for (const [name, value] of Object.entries(values)) headers.set(name, value);\n}\n\nfunction readRequestBody(req: 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\nfunction guessContentType(filePath: string): string {\n switch (extname(filePath)) {\n case \".html\":\n return \"text/html; charset=utf-8\";\n case \".js\":\n case \".mjs\":\n return \"application/javascript; charset=utf-8\";\n case \".css\":\n return \"text/css; charset=utf-8\";\n case \".json\":\n return \"application/json; charset=utf-8\";\n case \".svg\":\n return \"image/svg+xml\";\n case \".png\":\n return \"image/png\";\n case \".jpg\":\n case \".jpeg\":\n return \"image/jpeg\";\n case \".webp\":\n return \"image/webp\";\n case \".avif\":\n return \"image/avif\";\n case \".ico\":\n return \"image/x-icon\";\n case \".woff\":\n return \"font/woff\";\n case \".woff2\":\n return \"font/woff2\";\n case \".wasm\":\n return \"application/wasm\";\n default:\n return \"application/octet-stream\";\n }\n}\n\n/**\n * Maps a concrete page path (e.g. `/movies/inception`) to the route pattern\n * key used by the action registry (e.g. `/movies/:slug`). Falls back to the\n * path itself when it matches an exact registry key.\n */\nexport function resolveActionPageKey(\n page: string | undefined,\n routes: Awaited<ReturnType<typeof scanRoutes>>,\n): string | undefined {\n if (!page) return undefined;\n if (routes.pages.some((route) => route.path === page)) return page;\n const match = matchRoute(page, routes.pages);\n return match ? match.route.path : page;\n}\n\n/** Resolves the ISR TTL for a page: route `revalidate` or the default. */\nasync function resolveTtl(\n options: SsrServerOptions,\n pathname: string,\n routes: Awaited<ReturnType<typeof scanRoutes>>,\n): Promise<number | undefined> {\n const match = matchRoute(pathname, routes.pages);\n if (!match) return undefined;\n const revalidate = match.route.dataPath\n ? ((await import(match.route.dataPath)) as { revalidate?: number }).revalidate\n : undefined;\n return revalidate ?? options.defaultRevalidate;\n}\n\nfunction extractBody(fullHtml: string): string {\n const match = fullHtml.match(/<div id=\"app\">([\\s\\S]*)<\\/div>\\s*(<script|$)/);\n return match ? match[1].trim() : fullHtml;\n}\n\nfunction extractTitle(fullHtml: string): string {\n const match = fullHtml.match(/<title>([^<]*)<\\/title>/);\n return match ? match[1] : \"\";\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\";\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 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 router?: {\n enabled?: boolean;\n prefetch?: boolean;\n };\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 };\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 };\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 },\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 },\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 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// Legacy names kept for backward compatibility. Emit a deprecation warning\n// when a project still uses them so authors migrate to `elur.config.*`.\nconst LEGACY_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 for (const name of LEGACY_CONFIG_FILES) {\n const path = resolve(root, name);\n try {\n await access(path);\n console.warn(\n `[elur-kit] \"${name}\" is deprecated and will be removed in a future release. ` +\n `Rename it to \"elur.config.${name.split(\".\").slice(1).join(\".\")}\" to keep your config working.`,\n );\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","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 /** Absolute path to the user's Vite client config (e.g. vite.client.config.ts). */\n userConfigPath: 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 /**\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 console.log(`${log} Building hydration bundle...`);\n\n const userConfig = await loadUserConfig(options.userConfigPath, options.root);\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 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 console.log(`${log} ✓ ${outputCount} asset(s) emitted → ${relative(options.root, options.outDir)}`);\n return { outDir: options.outDir, outputCount };\n}\n\nasync 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// --- 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 { 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","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 { getCachedHtml, setCachedHtml } from \"../cache.js\";\nimport { shouldCachePublic, type CachePolicy } from \"../cache/policy.js\";\nimport { buildSecurityHeaders, applySecurityHeaders } from \"./security-headers.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// 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}\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 cacheDir = options.cacheDir;\n const defaultRevalidate = options.defaultRevalidate;\n\n const renderConfig = { lang, clientEntry, renderEndpoint };\n const securityHeadersConfig = options.securityHeaders ?? {};\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): Promise<Response> {\n try {\n return await handleActionRequest(request, actionResolver);\n } catch (err) {\n console.error(\"[elur-kit] action error:\", err);\n return publicErrorResponse(err, { includeDetail: noCache });\n }\n }\n\n async function handleRenderEndpoint(request: Request, url: URL): 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 try {\n const { body, title } = 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 if (wantsJson) return jsonResponse({ title, body });\n return htmlResponse(body);\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 console.error(\"[elur-kit] render endpoint error:\", err);\n return publicErrorResponse(err, { includeDetail: noCache });\n }\n }\n\n async function handleApiRoute(\n request: Request,\n pathname: string,\n ): Promise<Response | null> {\n const apiMatch = matchApiRoute(pathname, routes.api);\n if (!apiMatch) return null;\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 const ctx = { params: apiMatch.params, locals: {} 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 console.error(\"[elur-kit] API route error:\", err);\n return publicErrorResponse(err, { includeDetail: noCache });\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): 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 // ISR cache check (only when caching is enabled and the request is\n // cacheable — no cookies, no authorization header).\n const cacheable = !noCache && cacheDir && isCacheable(request);\n if (cacheable && cacheDir) {\n const cached = await getCachedHtml(cacheDir, pathname);\n if (cached) return htmlResponse(cached.html);\n }\n\n try {\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 && cacheDir && isResultCacheable(result, request)) {\n const revalidateSeconds = result.revalidate ?? defaultRevalidate ?? 0;\n if (revalidateSeconds > 0) {\n await setCachedHtml(cacheDir, pathname, result.html, revalidateSeconds);\n }\n }\n\n return htmlResponse(result.html);\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 console.error(\"[elur-kit] SSR render error:\", err);\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 }\n }\n\n return async function handler(request: Request): Promise<Response> {\n const url = new URL(request.url);\n const pathname = 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 // 1. Server actions endpoint.\n if (pathname === \"/__elur-js/actions\" && request.method === \"POST\") {\n const response = await handleActions(request);\n return applySecurityHeaders(response, secHeaders);\n }\n\n // 2. SPA render endpoint.\n if (pathname === \"/__elur-js/render\" && renderEndpoint) {\n const response = await handleRenderEndpoint(request, url);\n return applySecurityHeaders(response, secHeaders);\n }\n\n // 3. API routes.\n const apiResponse = await handleApiRoute(request, pathname);\n if (apiResponse) return applySecurityHeaders(apiResponse, secHeaders);\n\n // 4. Static files.\n const staticResponse = await handleStatic(pathname, request);\n if (staticResponse) return applySecurityHeaders(staticResponse, secHeaders);\n\n // 5. Dynamic SSR rendering.\n const dynamicResponse = await handleDynamicRender(request, pathname);\n return applySecurityHeaders(dynamicResponse, secHeaders);\n };\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 } 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 return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { handleActionRequest, matchApiRoute, matchRoute, renderPage, renderErrorPage } 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\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 match = matchRoute(page, routes.pages);\n if (!match) throw new Error(\\`No route found for \\${page}\\`);\n const { html } = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(search),\n config: { lang, clientEntry },\n importer: loadModule,\n actions,\n request,\n });\n const bodyStart = html.indexOf('<div id=\"app\">');\n const bodyEnd = html.lastIndexOf(\"</div>\");\n const body = bodyStart >= 0 && bodyEnd > bodyStart\n ? html.slice(bodyStart + 13, bodyEnd).trim()\n : html;\n const titleStart = html.indexOf(\"<title>\");\n const titleEnd = html.indexOf(\"</title>\");\n const title = titleStart >= 0 && titleEnd > titleStart\n ? html.slice(titleStart + 7, titleEnd)\n : \"\";\n if (wantsJson) {\n return new Response(JSON.stringify({ title, body }), {\n status: 200,\n headers: { \"Content-Type\": \"application/json; charset=utf-8\" },\n });\n }\n return new Response(body, {\n status: 200,\n headers: { \"Content-Type\": \"text/html; charset=utf-8\" },\n });\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 }, 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 const { html } = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(url.search),\n config: { lang, clientEntry },\n importer: loadModule,\n actions,\n request,\n });\n return new Response(html, { status: 200, headers: { \"Content-Type\": \"text/html; charset=utf-8\" } });\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 }, 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 },\n): string {\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)} },\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 },\n): string {\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 } 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)} },\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 res.writeHead(response.status, Object.fromEntries(response.headers.entries()));\n res.end(Buffer.from(await response.arrayBuffer()));\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 { join, resolve, relative } from \"node:path\";\nimport { existsSync, watch } from \"node:fs\";\nimport { spawn } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\nimport { build, type BuildConfig } from \"./build/build.js\";\nimport { transformProjectFiles, transformedAppDir as transformedAppDirOf } from \"./build/transform-source.js\";\nimport { createSsrServer } from \"./ssr/server.js\";\nimport { scanActions } from \"./action/scan.js\";\nimport { scanRoutes } from \"./router/route-scanner.js\";\nimport { incomingMessageToRequest } from \"./runtime/node-http.js\";\nimport { loadElurConfig, type ResolvedElurConfig } from \"./config/index.js\";\nimport { createAppManifest, writeAppManifest, writeRouteTypes } from \"./manifest/index.js\";\nimport { validateCapabilities } from \"./runtime/capabilities.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\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\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 \"--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 };\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`);\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 };\n}\n\nasync function doBuild(options: CliOptions): Promise<void> {\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 // 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 try {\n const buildConfig = toBuildConfig(options);\n buildConfig.appDir = transformedAppDir;\n buildConfig.outDir = tempOutDir;\n const result = await build(buildConfig);\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 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 console.log(` - manifest: ${relative(options.root, join(options.outDir, \".elur\", \"manifest.json\"))}`);\n } catch (err) {\n console.warn(\"[elur-kit] manifest generation failed:\", err);\n }\n }\n\n if (options.islandsDir && !options.clientConfig) {\n const autoConfig = await findClientConfig(options.root);\n if (autoConfig) {\n options.clientConfig = autoConfig;\n }\n }\n if (options.clientConfig) {\n // Temporarily redirect the client build to the staging directory.\n const originalOutDir = options.outDir;\n options.outDir = tempOutDir;\n try {\n await buildClient(options);\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 console.log(`✓ Build completo: ${result.pages} páginas generadas`);\n for (const file of result.files) {\n console.log(\" -\", relative(options.root, file));\n }\n if (result.islands.length > 0) {\n console.log(`\\n✓ ${result.islands.length} island(s) detectada(s):`);\n for (const island of result.islands) {\n console.log(\" -\", island.name);\n }\n if (result.generatedEntry) {\n console.log(\" entry:\", relative(options.root, result.generatedEntry));\n }\n }\n if (result.skipped.length > 0) {\n console.log(\"\\nRutas dinámicas omitidas (necesitan generateStaticParams):\");\n for (const path of result.skipped) {\n console.log(\" -\", 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 server = createServer((req, res) => handleRequest(req, res, options, actions, routes, true));\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 server.listen(options.port, options.host, () => {\n console.log(`\\n → Dev server http://${options.host}:${options.port}`);\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[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 console.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[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 console.error(`[dev] failed to watch ${dir}:`, 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\nexport async function doPreview(options: CliOptions): 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\", \"preview-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 server = createServer((req, res) => handleRequest(req, res, options, actions, routes));\n server.listen(options.port, options.host, () => {\n console.log(`\\n → Preview server http://${options.host}:${options.port}`);\n });\n return server;\n}\n\nasync function doStart(options: CliOptions): Promise<void> {\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 ssr = await createSsrServer({\n root: options.root,\n appDir: transformedAppDir,\n publicDir: options.outDir,\n clientEntry: options.clientEntry,\n lang: options.lang,\n port: options.port,\n host: options.host,\n cacheDir: options.cacheDir,\n defaultRevalidate: options.defaultRevalidate,\n });\n await ssr.listen();\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\nasync function buildClient(options: CliOptions): Promise<void> {\n if (!options.clientConfig) return;\n\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 await buildClientBundle({\n root: options.root,\n userConfigPath: resolve(options.clientConfig),\n appDir: join(options.root, \"src\", \"app\"),\n islandsDir: join(options.root, \"src\", \"islands\"),\n outDir: clientOutDir,\n base: clientBase,\n logPrefix: \"[client]\",\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): 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 securityHeaders: securityHeaders === undefined ? false : (securityHeaders as never),\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 console.error(\"[elur-kit] request error:\", err);\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(\"Internal Server Error\");\n return;\n }\n res.writeHead(response.status, Object.fromEntries(response.headers.entries()));\n res.end(Buffer.from(await response.arrayBuffer()));\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 };\n const resolvedConfig = options.resolvedConfig as { images?: { strict?: boolean }; cache?: { defaultRevalidate?: number } } | undefined;\n const features = {\n isr: typeof resolvedConfig?.cache?.defaultRevalidate === \"number\" && resolvedConfig.cache.defaultRevalidate > 0,\n images: resolvedConfig?.images?.strict === 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 → 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 → 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 → 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 → 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 },\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 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\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.js","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/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/build/build.ts","../../src/vite/interpolation-plugin.ts","../../src/build/transform-source.ts","../../src/errors.ts","../../src/action/origin.ts","../../src/action/server.ts","../../src/cache.ts","../../src/ssr/match.ts","../../src/ssr/stream.ts","../../src/middleware/index.ts","../../src/runtime/node-http.ts","../../src/runtime/static.ts","../../src/ssr/server.ts","../../src/config/index.ts","../../src/manifest/index.ts","../../src/runtime/capabilities.ts","../../src/build/vite-build.ts","../../src/runtime/context.ts","../../src/runtime/security-headers.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, 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/** 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\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/** 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): 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};\nhydrateIslands(registry);\ndocument.addEventListener(\"elur:rendered\", () => {\n cleanupHydratedIslands();\n hydrateIslands(registry);\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((newModule) => {\n cleanupHydratedIslands();\n hydrateIslands(registry);\n if (newModule) {\n // Re-run the module so its side effects (router, listeners) apply.\n }\n });\n}`\n : \"\";\n\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { startClientRouter } from ${JSON.stringify(routerImport)};\nimport { hydrateIslands, cleanupHydratedIslands } from ${JSON.stringify(hydrateImport)};\n\nstartClientRouter();\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.\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 );\n await mkdir(dirname(options.outFile), { recursive: true });\n await writeFile(options.outFile, source, \"utf8\");\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 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 /** Path to the client entry module, e.g. `/_elur/entry-client.js`. */\n clientEntry?: string;\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\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 */\nfunction 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/** 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, 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 const entryScript = clientEntry\n ? `\\n <script type=\"module\" src=\"${escapeHtml(clientEntry)}\"></script>`\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 const renderEndpointMeta =\n opts.renderEndpoint === 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}\n </head>\n <body>\n <div id=\"app\">${body}</div>${dataScript}${actionsScript}${entryScript}\n </body>\n</html>\n`;\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 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\">;\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 * 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 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: config.clientEntry,\n renderEndpoint: config.renderEndpoint,\n });\n\n const head = metadata ? buildHeadTags(metadata, resolvedTitle) : \"\";\n return { html, revalidate, clearActionErrorCookie, head, resolvedTitle, cachePolicy };\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\">;\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","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 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 * 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\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 routes = await scanRoutes(config.appDir);\n const actions = await scanActions(config.appDir);\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 });\n }\n\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 = { lang: config.lang, clientEntry: config.clientEntry, renderEndpoint: false };\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\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 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 }\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 await runIntegrationHook(config.integrations, \"build\", [\n result,\n { root: config.root ?? config.outDir, command: \"build\" },\n ]);\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: { lang: config.lang, clientEntry: config.clientEntry, renderEndpoint: false },\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\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","/**\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","import type { ActionRequest } from \"./index.js\";\nimport { isActionFailure, isRedirectResponse, publicErrorResponse } from \"../errors.js\";\nimport { verifyOrigin, originForbidden, type OriginCheckOptions } from \"./origin.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 const result = await action(...args);\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 { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\n\nexport interface CacheEntry {\n html: string;\n generatedAt: number;\n revalidate: number;\n}\n\nexport interface CacheOptions {\n cacheDir: string;\n defaultRevalidate?: number;\n}\n\nfunction cachePath(cacheDir: string, pathname: string): string {\n const key = createHash(\"sha256\").update(pathname).digest(\"hex\");\n return join(cacheDir, `${key}.html.json`);\n}\n\nexport async function getCachedHtml(\n cacheDir: string,\n pathname: string,\n): Promise<CacheEntry | undefined> {\n const path = cachePath(cacheDir, pathname);\n try {\n const raw = await readFile(path, \"utf8\");\n const entry = JSON.parse(raw) as CacheEntry;\n if (Date.now() - entry.generatedAt < entry.revalidate * 1000) {\n return entry;\n }\n } catch {\n // cache miss or invalid\n }\n return undefined;\n}\n\nexport async function setCachedHtml(\n cacheDir: string,\n pathname: string,\n html: string,\n revalidate: number,\n): Promise<void> {\n const path = cachePath(cacheDir, pathname);\n await mkdir(dirname(path), { recursive: true });\n const entry: CacheEntry = { html, generatedAt: Date.now(), revalidate };\n const temporaryPath = `${path}.${process.pid}.${randomUUID()}.tmp`;\n try {\n await writeFile(temporaryPath, JSON.stringify(entry), \"utf8\");\n await rename(temporaryPath, path);\n } finally {\n await rm(temporaryPath, { force: true });\n }\n}\n\nexport async function isStale(cacheDir: string, pathname: string): Promise<boolean> {\n const path = cachePath(cacheDir, pathname);\n try {\n const raw = await readFile(path, \"utf8\");\n const entry = JSON.parse(raw) as CacheEntry;\n return Date.now() - entry.generatedAt >= entry.revalidate * 1000;\n } catch {\n return true;\n }\n}\n\nexport async function clearCache(cacheDir: string): Promise<void> {\n try {\n await rm(cacheDir, { recursive: true, force: true });\n } catch {\n // ignore\n }\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","import type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString } from \"../render/render-to-string.js\";\nimport { documentShell } 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 */\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\">;\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 /** 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 bodyMatch = result.html.match(/<div id=\"app\">([\\s\\S]*)<\\/div>\\s*(<script|$)/);\n const body = bodyMatch ? bodyMatch[1].trim() : 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 };\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","import type { IncomingMessage } 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","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 { createServer, type IncomingMessage, type Server } from \"node:http\";\nimport { readFile } from \"node:fs/promises\";\nimport { extname } from \"node:path\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport { scanActions, actionNames } from \"../action/scan.js\";\nimport { handleActionRequest, type ActionSecurityOptions } from \"../action/server.js\";\nimport { getCachedHtml, setCachedHtml } from \"../cache.js\";\nimport { matchApiRoute, matchRoute } from \"./match.js\";\nimport { renderPage, renderErrorPage } from \"./render.js\";\nimport { renderPageBody, renderStreamingPage, RouteNotFoundError } from \"./stream.js\";\nimport { loadMiddleware, matchesMiddleware, runMiddleware } from \"../middleware/index.js\";\nimport { incomingMessageToRequest } from \"../runtime/node-http.js\";\nimport { resolveStaticFile } from \"../runtime/static.js\";\nimport { toPublicErrorInfo } from \"../errors.js\";\n\nexport interface SsrServerOptions {\n /** Absolute path to the app directory (e.g. /project/src/app). */\n appDir: string;\n /** Absolute path to the project root. When provided, action paths in the\n * serialized HTML shell are made relative to this root. */\n root?: string;\n /** Absolute path to the public directory for static files (optional). */\n publicDir?: 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 port?: number;\n host?: string;\n /** Absolute path to the ISR cache directory (optional). */\n cacheDir?: string;\n /** Default revalidate interval in seconds when a page does not export one. */\n defaultRevalidate?: number;\n /** If true, render pages with loading.ts boundaries using streaming. */\n streaming?: boolean;\n /** CSRF / origin policy applied to the server actions endpoint. */\n actionSecurity?: ActionSecurityOptions;\n}\n\nexport interface SsrServer {\n server: Server;\n listen(): Promise<void>;\n close(): Promise<void>;\n}\n\n/**\n * Create an SSR server that renders pages on demand and serves static files.\n */\nexport async function createSsrServer(options: SsrServerOptions): Promise<SsrServer> {\n const routes = await scanRoutes(options.appDir);\n const actions = await scanActions(options.appDir);\n const publicActions = actionNames(actions);\n\n // Load user middleware (src/middleware.ts) if it exists.\n const middleware = options.root ? await loadMiddleware(options.root) : null;\n\n const resolveAction = async (name: string, page?: string) => {\n const pageKey = resolveActionPageKey(page, routes);\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 const mod = (await import(actionPath)) as Record<string, unknown>;\n const action = mod[name];\n if (typeof action === \"function\") {\n return action as (...args: unknown[]) => unknown;\n }\n return undefined;\n };\n\n const server = createServer(async (req, res) => {\n let urlPath = req.url ?? \"/\";\n if (urlPath.includes(\"?\")) urlPath = urlPath.split(\"?\")[0];\n\n // Server actions endpoint.\n if (urlPath === \"/__elur-js/actions\" && req.method === \"POST\") {\n try {\n const body = await readRequestBody(req);\n const request = incomingMessageToRequest(req, body);\n const response = await handleActionRequest(request, resolveAction, options.actionSecurity);\n res.writeHead(response.status, Object.fromEntries(response.headers.entries()));\n res.end(await response.text());\n } catch (err) {\n console.error(\"[action] error handling\", err);\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(toPublicErrorInfo(err).message);\n }\n return;\n }\n\n if (urlPath === \"/__elur-js/render\") {\n const renderUrl = new URL(req.url ?? \"/\", \"http://localhost\");\n const page = renderUrl.searchParams.get(\"page\") ?? \"/\";\n const search = renderUrl.searchParams.get(\"search\") ?? \"\";\n const wantsJson = (req.headers[\"accept\"] ?? \"\").includes(\"application/json\");\n try {\n const request = incomingMessageToRequest(req);\n\n // ISR: cache the real content served by this endpoint when a cache\n // directory is configured, so streamed pages regenerate on a TTL.\n let body: string;\n let title: string;\n let lastRenderedCookie: string | undefined;\n let lastRenderedHead: string | undefined;\n const ttl = await resolveTtl(options, page, routes);\n const cacheKey = `/__elur-js/render${page}?${search}`;\n if (options.cacheDir && typeof ttl === \"number\" && canUsePublicCache(request)) {\n const cached = await getCachedHtml(options.cacheDir, cacheKey);\n if (cached) {\n body = extractBody(cached.html);\n title = extractTitle(cached.html);\n } else {\n const rendered = await renderPageBody({\n routes,\n pathname: page,\n searchParams: new URLSearchParams(search),\n config: { lang: options.lang ?? \"es\", clientEntry: options.clientEntry },\n actions: publicActions,\n request,\n });\n body = rendered.body;\n title = rendered.title;\n lastRenderedCookie = rendered.clearActionErrorCookie;\n lastRenderedHead = rendered.head;\n await setCachedHtml(options.cacheDir, cacheKey, rendered.fullHtml ?? \"\", ttl);\n }\n } else {\n const rendered = await renderPageBody({\n routes,\n pathname: page,\n searchParams: new URLSearchParams(search),\n config: { lang: options.lang ?? \"es\", clientEntry: options.clientEntry },\n actions: publicActions,\n request,\n });\n body = rendered.body;\n title = rendered.title;\n lastRenderedCookie = rendered.clearActionErrorCookie;\n lastRenderedHead = rendered.head;\n }\n\n if (wantsJson) {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json; charset=utf-8\" };\n // The SPA router applies the cookie via document.cookie so the next\n // full reload does not re-feed stale errors to the page.\n const setCookie = lastRenderedCookie;\n if (setCookie) headers[\"X-Elur-Action-Clear-Cookie\"] = setCookie;\n res.writeHead(200, headers);\n res.end(JSON.stringify({ title, body, head: lastRenderedHead, clearActionErrorCookie: setCookie }));\n } else {\n const headers: Record<string, string> = { \"Content-Type\": \"text/html; charset=utf-8\" };\n if (lastRenderedCookie) headers[\"Set-Cookie\"] = lastRenderedCookie;\n res.writeHead(200, headers);\n res.end(body);\n }\n } catch (err) {\n if (err instanceof RouteNotFoundError) {\n console.log(`[ssr] render endpoint: no route for ${page}`);\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not Found\");\n return;\n }\n console.error(\"[ssr] streaming render error\", err);\n res.writeHead(500, { \"Content-Type\": \"text/plain\" });\n res.end(\"Internal Server Error\");\n }\n return;\n }\n\n // Run middleware before routing (skip for internal endpoints handled above).\n let middlewareHeaders: Record<string, string> | undefined;\n if (middleware && matchesMiddleware(urlPath, middleware.config)) {\n const mwResult = await runMiddleware(middleware, incomingMessageToRequest(req));\n if (mwResult.kind === \"response\") {\n res.writeHead(mwResult.response.status, Object.fromEntries(mwResult.response.headers.entries()));\n res.end(Buffer.from(await mwResult.response.arrayBuffer()));\n return;\n }\n middlewareHeaders = mwResult.headers;\n }\n\n // Try API routes first.\n const apiMatch = matchApiRoute(urlPath, routes.api);\n if (apiMatch) {\n try {\n const mod = (await import(apiMatch.route.routePath)) as Record<\n string,\n (request: Request, context?: { params: Record<string, string | string[]> }) => unknown\n >;\n const handler = mod[req.method ?? \"GET\"];\n if (typeof handler !== \"function\") {\n res.writeHead(405, { \"Content-Type\": \"text/plain\" });\n res.end(`Method not allowed: ${req.method}`);\n return;\n }\n const body = req.method && req.method !== \"GET\" && req.method !== \"HEAD\" ? await readRequestBody(req) : undefined;\n const request = incomingMessageToRequest(req, body);\n applyHeaders(request.headers, middlewareHeaders);\n const response = (await handler(request, { params: apiMatch.params })) as Response;\n res.writeHead(response.status, Object.fromEntries(response.headers.entries()));\n res.end(Buffer.from(await response.arrayBuffer()));\n } catch (err) {\n console.error(\"[api] error handling\", urlPath, err);\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(toPublicErrorInfo(err).message);\n }\n return;\n }\n\n // Try static files first.\n if (options.publicDir) {\n try {\n const served = await tryServeStatic(res, options.publicDir, urlPath);\n if (served) return;\n } catch (err) {\n console.error(\"[static] error serving\", urlPath, err);\n }\n }\n\n // Try SSR page rendering.\n const match = matchRoute(urlPath, routes.pages);\n const config = { lang: options.lang ?? \"es\", clientEntry: options.clientEntry };\n if (match) {\n try {\n const request = incomingMessageToRequest(req);\n applyHeaders(request.headers, middlewareHeaders);\n\n let html: string;\n let clearActionErrorCookie: string | undefined;\n const revalidate = match.route.dataPath\n ? ((await import(match.route.dataPath)) as { revalidate?: number }).revalidate\n : undefined;\n const ttl = revalidate ?? options.defaultRevalidate;\n const useStreaming = options.streaming !== false && match.route.loadingPath;\n if (useStreaming) {\n html = await renderStreamingPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(req.url?.split(\"?\")[1] ?? \"\"),\n config,\n actions: publicActions,\n request,\n });\n } else if (options.cacheDir && typeof ttl === \"number\" && canUsePublicCache(request)) {\n const cacheKey = new URL(request.url).pathname + new URL(request.url).search;\n const cached = await getCachedHtml(options.cacheDir, cacheKey);\n if (cached) {\n html = cached.html;\n } else {\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(req.url?.split(\"?\")[1] ?? \"\"),\n config,\n actions: publicActions,\n request,\n });\n html = result.html;\n clearActionErrorCookie = result.clearActionErrorCookie;\n await setCachedHtml(options.cacheDir, cacheKey, html, ttl);\n }\n } else {\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(req.url?.split(\"?\")[1] ?? \"\"),\n config,\n actions: publicActions,\n request,\n });\n html = result.html;\n clearActionErrorCookie = result.clearActionErrorCookie;\n }\n const responseHeaders: Record<string, string> = { \"Content-Type\": \"text/html; charset=utf-8\" };\n if (clearActionErrorCookie) responseHeaders[\"Set-Cookie\"] = clearActionErrorCookie;\n res.writeHead(200, responseHeaders);\n res.end(html);\n return;\n } catch (err) {\n console.error(\"[ssr] error rendering\", urlPath, err);\n const errorResult = await renderErrorPage({\n routes,\n status: 500,\n error: err,\n config,\n actions: publicActions,\n });\n if (errorResult) {\n res.writeHead(errorResult.status, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(errorResult.html);\n } else {\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(toPublicErrorInfo(err).message);\n }\n return;\n }\n }\n\n const errorResult = await renderErrorPage({\n routes,\n status: 404,\n config,\n actions: publicActions,\n });\n if (errorResult) {\n res.writeHead(errorResult.status, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(errorResult.html);\n return;\n }\n\n res.writeHead(404, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(`Not found: ${req.url}`);\n });\n\n return {\n server,\n listen() {\n return new Promise((resolve) => {\n server.listen(options.port ?? 3000, options.host ?? \"127.0.0.1\", () => {\n console.log(\n `\\n → SSR server http://${options.host ?? \"127.0.0.1\"}:${options.port ?? 3000}`,\n );\n resolve();\n });\n });\n },\n close() {\n return new Promise((resolve, reject) => {\n server.close((err) => (err ? reject(err) : resolve()));\n });\n },\n };\n}\n\nasync function tryServeStatic(\n res: import(\"node:http\").ServerResponse,\n publicDir: string,\n urlPath: string,\n): Promise<boolean> {\n const filePath = await resolveStaticFile(publicDir, urlPath);\n if (!filePath) return false;\n const contentType = guessContentType(filePath);\n let data: Buffer | string = await readFile(filePath);\n if (contentType.includes(\"text/html\")) {\n // The SSG build bakes `render-endpoint content=\"off\"` into the static\n // HTML so purely static deployments never probe the endpoint. This server\n // (SSR `start`) DOES expose /__elur-js/render, so advertise it: SPA\n // navigations then fetch live server-rendered content instead of the\n // stale static file (e.g. after a mutating server action).\n data = data\n .toString(\"utf8\")\n .replace(\n '<meta name=\"elur:render-endpoint\" content=\"off\" />',\n '<meta name=\"elur:render-endpoint\" content=\"on\" />',\n );\n }\n res.writeHead(200, { \"Content-Type\": contentType, \"Content-Length\": Buffer.byteLength(data) });\n res.end(data);\n return true;\n}\n\nfunction canUsePublicCache(request: Request): boolean {\n return !request.headers.has(\"cookie\") && !request.headers.has(\"authorization\");\n}\n\nfunction applyHeaders(headers: Headers, values: Record<string, string> | undefined): void {\n if (!values) return;\n for (const [name, value] of Object.entries(values)) headers.set(name, value);\n}\n\nfunction readRequestBody(req: 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\nfunction guessContentType(filePath: string): string {\n switch (extname(filePath)) {\n case \".html\":\n return \"text/html; charset=utf-8\";\n case \".js\":\n case \".mjs\":\n return \"application/javascript; charset=utf-8\";\n case \".css\":\n return \"text/css; charset=utf-8\";\n case \".json\":\n return \"application/json; charset=utf-8\";\n case \".svg\":\n return \"image/svg+xml\";\n case \".png\":\n return \"image/png\";\n case \".jpg\":\n case \".jpeg\":\n return \"image/jpeg\";\n case \".webp\":\n return \"image/webp\";\n case \".avif\":\n return \"image/avif\";\n case \".ico\":\n return \"image/x-icon\";\n case \".woff\":\n return \"font/woff\";\n case \".woff2\":\n return \"font/woff2\";\n case \".wasm\":\n return \"application/wasm\";\n default:\n return \"application/octet-stream\";\n }\n}\n\n/**\n * Maps a concrete page path (e.g. `/movies/inception`) to the route pattern\n * key used by the action registry (e.g. `/movies/:slug`). Falls back to the\n * path itself when it matches an exact registry key.\n */\nexport function resolveActionPageKey(\n page: string | undefined,\n routes: Awaited<ReturnType<typeof scanRoutes>>,\n): string | undefined {\n if (!page) return undefined;\n if (routes.pages.some((route) => route.path === page)) return page;\n const match = matchRoute(page, routes.pages);\n return match ? match.route.path : page;\n}\n\n/** Resolves the ISR TTL for a page: route `revalidate` or the default. */\nasync function resolveTtl(\n options: SsrServerOptions,\n pathname: string,\n routes: Awaited<ReturnType<typeof scanRoutes>>,\n): Promise<number | undefined> {\n const match = matchRoute(pathname, routes.pages);\n if (!match) return undefined;\n const revalidate = match.route.dataPath\n ? ((await import(match.route.dataPath)) as { revalidate?: number }).revalidate\n : undefined;\n return revalidate ?? options.defaultRevalidate;\n}\n\nfunction extractBody(fullHtml: string): string {\n const match = fullHtml.match(/<div id=\"app\">([\\s\\S]*)<\\/div>\\s*(<script|$)/);\n return match ? match[1].trim() : fullHtml;\n}\n\nfunction extractTitle(fullHtml: string): string {\n const match = fullHtml.match(/<title>([^<]*)<\\/title>/);\n return match ? match[1] : \"\";\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\";\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 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 router?: {\n enabled?: boolean;\n prefetch?: boolean;\n };\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 };\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 };\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 },\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 },\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 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// Legacy names kept for backward compatibility. Emit a deprecation warning\n// when a project still uses them so authors migrate to `elur.config.*`.\nconst LEGACY_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 for (const name of LEGACY_CONFIG_FILES) {\n const path = resolve(root, name);\n try {\n await access(path);\n console.warn(\n `[elur-kit] \"${name}\" is deprecated and will be removed in a future release. ` +\n `Rename it to \"elur.config.${name.split(\".\").slice(1).join(\".\")}\" to keep your config working.`,\n );\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","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 /** Absolute path to the user's Vite client config (e.g. vite.client.config.ts). */\n userConfigPath: 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 /**\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 console.log(`${log} Building hydration bundle...`);\n\n const userConfig = await loadUserConfig(options.userConfigPath, options.root);\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 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 console.log(`${log} ✓ ${outputCount} asset(s) emitted → ${relative(options.root, options.outDir)}`);\n return { outDir: options.outDir, outputCount };\n}\n\nasync 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// --- 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 { 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","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 { getCachedHtml, setCachedHtml } from \"../cache.js\";\nimport { shouldCachePublic, type CachePolicy } from \"../cache/policy.js\";\nimport { buildSecurityHeaders, applySecurityHeaders } from \"./security-headers.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// 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}\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 cacheDir = options.cacheDir;\n const defaultRevalidate = options.defaultRevalidate;\n\n const renderConfig = { lang, clientEntry, renderEndpoint };\n const securityHeadersConfig = options.securityHeaders ?? {};\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): Promise<Response> {\n try {\n return await handleActionRequest(request, actionResolver);\n } catch (err) {\n console.error(\"[elur-kit] action error:\", err);\n return publicErrorResponse(err, { includeDetail: noCache });\n }\n }\n\n async function handleRenderEndpoint(request: Request, url: URL): 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 try {\n const { body, title } = 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 if (wantsJson) return jsonResponse({ title, body });\n return htmlResponse(body);\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 console.error(\"[elur-kit] render endpoint error:\", err);\n return publicErrorResponse(err, { includeDetail: noCache });\n }\n }\n\n async function handleApiRoute(\n request: Request,\n pathname: string,\n ): Promise<Response | null> {\n const apiMatch = matchApiRoute(pathname, routes.api);\n if (!apiMatch) return null;\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 const ctx = { params: apiMatch.params, locals: {} 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 console.error(\"[elur-kit] API route error:\", err);\n return publicErrorResponse(err, { includeDetail: noCache });\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): 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 // ISR cache check (only when caching is enabled and the request is\n // cacheable — no cookies, no authorization header).\n const cacheable = !noCache && cacheDir && isCacheable(request);\n if (cacheable && cacheDir) {\n const cached = await getCachedHtml(cacheDir, pathname);\n if (cached) return htmlResponse(cached.html);\n }\n\n try {\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 && cacheDir && isResultCacheable(result, request)) {\n const revalidateSeconds = result.revalidate ?? defaultRevalidate ?? 0;\n if (revalidateSeconds > 0) {\n await setCachedHtml(cacheDir, pathname, result.html, revalidateSeconds);\n }\n }\n\n return htmlResponse(result.html);\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 console.error(\"[elur-kit] SSR render error:\", err);\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 }\n }\n\n return async function handler(request: Request): Promise<Response> {\n const url = new URL(request.url);\n const pathname = 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 // 1. Server actions endpoint.\n if (pathname === \"/__elur-js/actions\" && request.method === \"POST\") {\n const response = await handleActions(request);\n return applySecurityHeaders(response, secHeaders);\n }\n\n // 2. SPA render endpoint.\n if (pathname === \"/__elur-js/render\" && renderEndpoint) {\n const response = await handleRenderEndpoint(request, url);\n return applySecurityHeaders(response, secHeaders);\n }\n\n // 3. API routes.\n const apiResponse = await handleApiRoute(request, pathname);\n if (apiResponse) return applySecurityHeaders(apiResponse, secHeaders);\n\n // 4. Static files.\n const staticResponse = await handleStatic(pathname, request);\n if (staticResponse) return applySecurityHeaders(staticResponse, secHeaders);\n\n // 5. Dynamic SSR rendering.\n const dynamicResponse = await handleDynamicRender(request, pathname);\n return applySecurityHeaders(dynamicResponse, secHeaders);\n };\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 } 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 return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { handleActionRequest, matchApiRoute, matchRoute, renderPage, renderErrorPage } 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\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 match = matchRoute(page, routes.pages);\n if (!match) throw new Error(\\`No route found for \\${page}\\`);\n const { html } = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(search),\n config: { lang, clientEntry },\n importer: loadModule,\n actions,\n request,\n });\n const bodyStart = html.indexOf('<div id=\"app\">');\n const bodyEnd = html.lastIndexOf(\"</div>\");\n const body = bodyStart >= 0 && bodyEnd > bodyStart\n ? html.slice(bodyStart + 13, bodyEnd).trim()\n : html;\n const titleStart = html.indexOf(\"<title>\");\n const titleEnd = html.indexOf(\"</title>\");\n const title = titleStart >= 0 && titleEnd > titleStart\n ? html.slice(titleStart + 7, titleEnd)\n : \"\";\n if (wantsJson) {\n return new Response(JSON.stringify({ title, body }), {\n status: 200,\n headers: { \"Content-Type\": \"application/json; charset=utf-8\" },\n });\n }\n return new Response(body, {\n status: 200,\n headers: { \"Content-Type\": \"text/html; charset=utf-8\" },\n });\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 }, 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 const { html } = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(url.search),\n config: { lang, clientEntry },\n importer: loadModule,\n actions,\n request,\n });\n return new Response(html, { status: 200, headers: { \"Content-Type\": \"text/html; charset=utf-8\" } });\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 }, 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 },\n): string {\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)} },\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 },\n): string {\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 } 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)} },\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 res.writeHead(response.status, Object.fromEntries(response.headers.entries()));\n res.end(Buffer.from(await response.arrayBuffer()));\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 { join, resolve, relative } from \"node:path\";\nimport { existsSync, watch } from \"node:fs\";\nimport { spawn } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\nimport { build, type BuildConfig } from \"./build/build.js\";\nimport { transformProjectFiles, transformedAppDir as transformedAppDirOf } from \"./build/transform-source.js\";\nimport { createSsrServer } from \"./ssr/server.js\";\nimport { scanActions } from \"./action/scan.js\";\nimport { scanRoutes } from \"./router/route-scanner.js\";\nimport { incomingMessageToRequest } from \"./runtime/node-http.js\";\nimport { loadElurConfig, type ResolvedElurConfig } from \"./config/index.js\";\nimport { createAppManifest, writeAppManifest, writeRouteTypes } from \"./manifest/index.js\";\nimport { validateCapabilities } from \"./runtime/capabilities.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\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\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 \"--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 };\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`);\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 };\n}\n\nasync function doBuild(options: CliOptions): Promise<void> {\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 // 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 try {\n const buildConfig = toBuildConfig(options);\n buildConfig.appDir = transformedAppDir;\n buildConfig.outDir = tempOutDir;\n const result = await build(buildConfig);\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 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 console.log(` - manifest: ${relative(options.root, join(options.outDir, \".elur\", \"manifest.json\"))}`);\n } catch (err) {\n console.warn(\"[elur-kit] manifest generation failed:\", err);\n }\n }\n\n if (options.islandsDir && !options.clientConfig) {\n const autoConfig = await findClientConfig(options.root);\n if (autoConfig) {\n options.clientConfig = autoConfig;\n }\n }\n if (options.clientConfig) {\n // Temporarily redirect the client build to the staging directory.\n const originalOutDir = options.outDir;\n options.outDir = tempOutDir;\n try {\n await buildClient(options);\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 console.log(`✓ Build completo: ${result.pages} páginas generadas`);\n for (const file of result.files) {\n console.log(\" -\", relative(options.root, file));\n }\n if (result.islands.length > 0) {\n console.log(`\\n✓ ${result.islands.length} island(s) detectada(s):`);\n for (const island of result.islands) {\n console.log(\" -\", island.name);\n }\n if (result.generatedEntry) {\n console.log(\" entry:\", relative(options.root, result.generatedEntry));\n }\n }\n if (result.skipped.length > 0) {\n console.log(\"\\nRutas dinámicas omitidas (necesitan generateStaticParams):\");\n for (const path of result.skipped) {\n console.log(\" -\", 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 server = createServer((req, res) => handleRequest(req, res, options, actions, routes, true));\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 server.listen(options.port, options.host, () => {\n console.log(`\\n → Dev server http://${options.host}:${options.port}`);\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[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 console.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[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 console.error(`[dev] failed to watch ${dir}:`, 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\nexport async function doPreview(options: CliOptions): 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\", \"preview-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 server = createServer((req, res) => handleRequest(req, res, options, actions, routes));\n server.listen(options.port, options.host, () => {\n console.log(`\\n → Preview server http://${options.host}:${options.port}`);\n });\n return server;\n}\n\nasync function doStart(options: CliOptions): Promise<void> {\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 ssr = await createSsrServer({\n root: options.root,\n appDir: transformedAppDir,\n publicDir: options.outDir,\n clientEntry: options.clientEntry,\n lang: options.lang,\n port: options.port,\n host: options.host,\n cacheDir: options.cacheDir,\n defaultRevalidate: options.defaultRevalidate,\n });\n await ssr.listen();\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\nasync function buildClient(options: CliOptions): Promise<void> {\n if (!options.clientConfig) return;\n\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 await buildClientBundle({\n root: options.root,\n userConfigPath: resolve(options.clientConfig),\n appDir: join(options.root, \"src\", \"app\"),\n islandsDir: join(options.root, \"src\", \"islands\"),\n outDir: clientOutDir,\n base: clientBase,\n logPrefix: \"[client]\",\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): 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 securityHeaders: securityHeaders === undefined ? false : (securityHeaders as never),\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 console.error(\"[elur-kit] request error:\", err);\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(\"Internal Server Error\");\n return;\n }\n res.writeHead(response.status, Object.fromEntries(response.headers.entries()));\n res.end(Buffer.from(await response.arrayBuffer()));\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 };\n const resolvedConfig = options.resolvedConfig as { images?: { strict?: boolean }; cache?: { defaultRevalidate?: number } } | undefined;\n const features = {\n isr: typeof resolvedConfig?.cache?.defaultRevalidate === \"number\" && resolvedConfig.cache.defaultRevalidate > 0,\n images: resolvedConfig?.images?.strict === 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 → 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 → 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 → 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 → 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 },\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 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\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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"}
|