@lolyjs/core 0.2.0-alpha.3 → 0.2.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{bootstrap-BiCQmSkx.d.mts → bootstrap-DgvWWDim.d.mts} +7 -0
- package/dist/{bootstrap-BiCQmSkx.d.ts → bootstrap-DgvWWDim.d.ts} +7 -0
- package/dist/cli.cjs +29 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +29 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +86 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +86 -1
- package/dist/index.js.map +1 -1
- package/dist/react/hooks.cjs +98 -22
- package/dist/react/hooks.cjs.map +1 -1
- package/dist/react/hooks.d.mts +5 -0
- package/dist/react/hooks.d.ts +5 -0
- package/dist/react/hooks.js +99 -23
- package/dist/react/hooks.js.map +1 -1
- package/dist/runtime.cjs +57 -0
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +57 -0
- package/dist/runtime.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../constants/globals.ts","../modules/cli/index.ts","../modules/router/loader-pages.ts","../modules/router/constants/index.ts","../modules/router/path.ts","../modules/router/layout.ts","../modules/router/loader.ts","../modules/router/loader-api.ts","../modules/router/helpers/routes/index.ts","../modules/router/matcher.ts","../modules/router/manifest.ts","../modules/router/loader-routes.ts","../modules/router/route-loader.ts","../modules/router/loader-wss.ts","../modules/build/bundler/client.ts","../modules/build/config/client.ts","../modules/build/utils/index.ts","../modules/build/ssg/builder.ts","../modules/build/ssg/path.ts","../modules/build/ssg/renderer.ts","../modules/rendering/createDocumentTree/index.ts","../modules/rendering/initialData/index.ts","../modules/build/bundler/server.ts","../modules/server/utils/server-dir.ts","../modules/server/init.ts","../modules/server/config.ts","../modules/build/index.ts","../src/config.ts","../src/server.ts","../modules/server/setup.ts","../../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js","../../../node_modules/.pnpm/readdirp@4.1.2/node_modules/readdirp/esm/index.js","../../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/handler.js","../modules/dev/hot-reload-client/index.ts","../modules/dev/hot-reload-server/index.ts","../modules/security/sanitize.ts","../modules/server/middleware/rate-limit.ts","../modules/server/middleware/auto-rate-limit.ts","../modules/logger/index.ts","../modules/server/handlers/api.ts","../modules/server/handlers/pages.ts","../modules/server/handlers/middleware.ts","../modules/server/handlers/loader.ts","../modules/server/handlers/response.ts","../modules/server/handlers/ssg.ts","../modules/server/routes.ts","../modules/server/wss.ts","../modules/server/application.ts","../modules/runtime/client/bootstrap.tsx","../modules/runtime/client/AppShell.tsx","../modules/runtime/client/RouterView.tsx","../modules/react/cache/client-data-cache/index.ts","../modules/runtime/client/RouterContext.tsx","../modules/validation/index.ts"],"sourcesContent":["export const BUILD_FOLDER_NAME = '.loly';\r\nexport const STYLE_FILE_NAME = 'styles.css';\r\n\r\n// Framework runtime constants\r\nexport const WINDOW_DATA_KEY = '__FW_DATA__';\r\nexport const APP_CONTAINER_ID = '__app';\r\nexport const STATIC_PATH = '/static';\r\nexport const NOT_FOUND_PATTERN = '/not-found';\r\nexport const ERROR_PATTERN = '/error';\r\nexport const NOT_FOUND_CHUNK_KEY = '__fw_not_found__';\r\nexport const ERROR_CHUNK_KEY = '__fw_error__';\r\n\r\n// Special page file names\r\nexport const NOT_FOUND_FILE_PREFIX = '_not-found';\r\nexport const ERROR_FILE_PREFIX = '_error';\r\nexport const PAGE_FILE_NAME = 'page';\r\nexport const LAYOUT_FILE_NAME = 'layout';\r\n\r\n// Static asset paths\r\nexport const FAVICON_PATH = '/static/favicon.png';\r\nexport const CLIENT_CSS_PATH = '/static/client.css';\r\nexport const CLIENT_JS_PATH = '/static/client.js';\r\nexport const ASSETS_BASE_DIR = '/static/assets';","// src/cli/index.ts\r\n\r\n\r\n// Register tsx so Node can require/import TypeScript config files\r\n// like `loly.config.ts` from CJS entrypoints.\r\ndeclare const require: any;\r\n\r\ntry {\r\n if (typeof require !== \"undefined\") {\r\n require(\"tsx/cjs\");\r\n }\r\n} catch {\r\n // If tsx is not installed for some reason, we just skip it.\r\n // The framework will then only work with plain JS configs.\r\n}\r\n\r\n\r\nimport path from \"path\";\r\nimport process from \"process\";\r\nimport type {\r\n StartDevServerOptions,\r\n StartProdServerOptions,\r\n} from \"../../src/server\";\r\nimport type { BuildAppOptions } from \"../build\";\r\nimport { buildApp } from\"../build\";\r\nimport { startDevServer, startProdServer } from \"../../src/index\";\r\n\r\n/**\r\n * Shape of parsed CLI flags.\r\n *\r\n * Example:\r\n * --port 3000 -> { port: \"3000\" }\r\n * --appDir=app -> { appDir: \"app\" }\r\n * --flag -> { flag: true }\r\n */\r\ntype CliFlags = Record<string, string | boolean>;\r\n\r\n/**\r\n * Very small flag parser for patterns like:\r\n * --port 3000\r\n * --appDir=app\r\n * --flag\r\n */\r\nfunction parseArgs(argv: string[]): CliFlags {\r\n const args: CliFlags = {};\r\n\r\n for (let i = 0; i < argv.length; i++) {\r\n let arg = argv[i];\r\n if (!arg.startsWith(\"--\")) continue;\r\n\r\n // Strip leading \"--\"\r\n arg = arg.slice(2);\r\n\r\n // Handle \"--key=value\"\r\n if (arg.includes(\"=\")) {\r\n const [key, ...rest] = arg.split(\"=\");\r\n args[key] = rest.join(\"=\");\r\n continue;\r\n }\r\n\r\n // Handle \"--key value\" or boolean flag\r\n const next = argv[i + 1];\r\n if (next && !next.startsWith(\"--\")) {\r\n args[arg] = next;\r\n i++; // skip value\r\n } else {\r\n args[arg] = true;\r\n }\r\n }\r\n\r\n return args;\r\n}\r\n\r\n/**\r\n * Print high-level usage and options.\r\n */\r\nfunction printHelp(): void {\r\n console.log(`\r\nloly - CLI for the framework\r\n\r\nUsage:\r\n loly dev [--port 3000] [--appDir app]\r\n loly build [--appDir app]\r\n loly start [--port 3000] [--appDir app]\r\n\r\nOptions:\r\n --port HTTP port for the dev/prod server (default: 3000)\r\n --appDir App directory relative to project root (default: \"app\")\r\n`);\r\n}\r\n\r\n/**\r\n * Main CLI entrypoint.\r\n *\r\n * Supported commands:\r\n * - dev\r\n * - build\r\n * - start\r\n */\r\nasync function run(): Promise<void> {\r\n const argv = process.argv.slice(2);\r\n const command = argv[0];\r\n\r\n if (\r\n !command ||\r\n command === \"help\" ||\r\n command === \"--help\" ||\r\n command === \"-h\"\r\n ) {\r\n printHelp();\r\n return;\r\n }\r\n\r\n const args = parseArgs(argv.slice(1));\r\n\r\n const projectRoot = process.cwd();\r\n const appDir = path.resolve(projectRoot, (args.appDir as string) || \"app\");\r\n const port =\r\n typeof args.port === \"string\" && args.port.trim().length > 0\r\n ? Number(args.port)\r\n : 3000;\r\n\r\n switch (command) {\r\n case \"dev\": {\r\n // Set a sensible default environment\r\n process.env.NODE_ENV ||= \"development\";\r\n\r\n const options: StartDevServerOptions = {\r\n rootDir: projectRoot,\r\n appDir,\r\n port,\r\n };\r\n\r\n startDevServer(options);\r\n break;\r\n }\r\n\r\n case \"build\": {\r\n process.env.NODE_ENV ||= \"production\";\r\n\r\n const options: BuildAppOptions = {\r\n rootDir: projectRoot,\r\n appDir,\r\n };\r\n\r\n await buildApp(options);\r\n \r\n // Force exit to ensure process terminates after build\r\n // This prevents hanging due to open handles from loaded modules\r\n process.exit(0);\r\n break;\r\n }\r\n\r\n case \"start\": {\r\n process.env.NODE_ENV ||= \"production\";\r\n\r\n const options: StartProdServerOptions = {\r\n rootDir: projectRoot,\r\n appDir,\r\n port,\r\n };\r\n\r\n await startProdServer(options);\r\n break;\r\n }\r\n\r\n default: {\r\n console.error(`Unknown command: \"${command}\"\\n`);\r\n printHelp();\r\n process.exit(1);\r\n }\r\n }\r\n}\r\n\r\nrun().catch((err) => {\r\n console.error(\"[loly] CLI error:\", err);\r\n process.exit(1);\r\n});\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { LoadedRoute, PageComponent } from \"./index.types\";\r\nimport { PAGE_FILE_REGEX } from \"./constants\";\r\nimport { buildRoutePathFromDir, buildRegexFromRoutePath } from \"./path\";\r\nimport { loadLayoutsForDir } from \"./layout\";\r\nimport { loadLoaderForDir } from \"./loader\";\r\n\r\n/**\r\n * Scans the app directory and loads all page routes.\r\n * \r\n * Recursively walks through the app directory, finding all `page.tsx`, `page.ts`,\r\n * `page.jsx`, or `page.js` files and creating route definitions.\r\n * \r\n * @param appDir - Root directory of the app (e.g., 'app')\r\n * @returns Array of loaded routes with components, layouts, loaders, etc.\r\n * \r\n * @example\r\n * const routes = loadRoutes('app');\r\n * // [\r\n * // { pattern: '/', component: HomePage, layouts: [], ... },\r\n * // { pattern: '/blog/[slug]', component: BlogPage, layouts: [RootLayout], ... },\r\n * // ]\r\n */\r\nexport function loadRoutes(appDir: string): LoadedRoute[] {\r\n if (!fs.existsSync(appDir)) {\r\n return [];\r\n }\r\n\r\n const routes: LoadedRoute[] = [];\r\n\r\n function walk(currentDir: string) {\r\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(currentDir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n walk(fullPath);\r\n continue;\r\n }\r\n\r\n if (!PAGE_FILE_REGEX.test(entry.name)) continue;\r\n\r\n // Skip special error pages - they're handled separately\r\n if (entry.name.startsWith(\"_not-found.\") || entry.name.startsWith(\"_error.\")) {\r\n continue;\r\n }\r\n\r\n const relDir = path.relative(appDir, currentDir);\r\n const routePath = buildRoutePathFromDir(relDir);\r\n const { regex, paramNames } = buildRegexFromRoutePath(routePath);\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n const mod = require(fullPath);\r\n const component: PageComponent = mod.default;\r\n\r\n if (!component) {\r\n continue;\r\n }\r\n\r\n const { components: layouts, files: layoutFiles } = loadLayoutsForDir(\r\n currentDir,\r\n appDir\r\n );\r\n\r\n const { middlewares, loader, dynamic, generateStaticParams } =\r\n loadLoaderForDir(currentDir);\r\n\r\n routes.push({\r\n pattern: routePath,\r\n regex,\r\n paramNames,\r\n component,\r\n layouts,\r\n pageFile: fullPath,\r\n layoutFiles,\r\n middlewares,\r\n loader,\r\n dynamic,\r\n generateStaticParams,\r\n });\r\n }\r\n }\r\n\r\n walk(appDir);\r\n\r\n return routes;\r\n}\r\n\r\n","import type { FrameworkConfig } from \"@src/config\";\r\n\r\nexport const PAGE_FILE_REGEX = /^page\\.(tsx|ts|jsx|js)$/;\r\nexport const LAYOUT_FILE_BASENAME = \"layout\";\r\n\r\n/**\r\n * Creates a regex pattern for page files based on configuration.\r\n * \r\n * @param config - Framework configuration\r\n * @returns Regex pattern for matching page files\r\n */\r\nexport function createPageFileRegex(config: FrameworkConfig): RegExp {\r\n const pageName = config.conventions.page;\r\n return new RegExp(`^${pageName}\\\\.(tsx|ts|jsx|js)$`);\r\n}\r\n\r\n/**\r\n * Gets the layout file basename from configuration.\r\n * \r\n * @param config - Framework configuration\r\n * @returns Layout file basename\r\n */\r\nexport function getLayoutFileBasename(config: FrameworkConfig): string {\r\n return config.conventions.layout;\r\n}","/**\r\n * Path utilities for building route paths and regex patterns.\r\n */\r\n\r\n/**\r\n * Builds a route path from a relative directory path.\r\n * \r\n * @param relDir - Relative directory path (e.g., '', 'about', 'blog\\\\[slug]')\r\n * @returns Route path (e.g., '/', '/about', '/blog/[slug]')\r\n * \r\n * @example\r\n * buildRoutePathFromDir('') // '/'\r\n * buildRoutePathFromDir('about') // '/about'\r\n * buildRoutePathFromDir('blog\\\\[slug]') // '/blog/[slug]'\r\n */\r\nexport function buildRoutePathFromDir(relDir: string): string {\r\n if (!relDir || relDir === \".\") return \"/\";\r\n const clean = relDir.replace(/\\\\/g, \"/\");\r\n return \"/\" + clean;\r\n}\r\n\r\n/**\r\n * Builds a regex pattern and parameter names from a route path.\r\n * \r\n * Supports:\r\n * - Static segments: `/about` → `/^\\/about\\/?$/`\r\n * - Dynamic segments: `[slug]` → captures single segment\r\n * - Catch-all segments: `[...path]` → captures remaining path (must be last)\r\n * \r\n * @param routePath - Route path pattern (e.g., '/blog/[slug]', '/post/[...path]')\r\n * @returns Object with regex pattern and parameter names\r\n * \r\n * @example\r\n * buildRegexFromRoutePath('/blog/[slug]')\r\n * // { regex: /^\\/blog\\/([^\\/]+)\\/?$/, paramNames: ['slug'] }\r\n * \r\n * buildRegexFromRoutePath('/post/[...path]')\r\n * // { regex: /^\\/post\\/(.+)\\/?$/, paramNames: ['path'] }\r\n * \r\n * @throws Error if catch-all segment is not the last segment\r\n */\r\nexport function buildRegexFromRoutePath(routePath: string): {\r\n regex: RegExp;\r\n paramNames: string[];\r\n} {\r\n const segments = routePath.split(\"/\").filter(Boolean);\r\n const paramNames: string[] = [];\r\n const regexParts: string[] = [];\r\n\r\n for (let i = 0; i < segments.length; i++) {\r\n const seg = segments[i];\r\n\r\n // 1) Catch-all: [...slug]\r\n if (seg.startsWith(\"[...\") && seg.endsWith(\"]\")) {\r\n const paramName = seg.slice(4, -1); // \"[...slug]\" -> \"slug\"\r\n paramNames.push(paramName);\r\n\r\n // Catch-all must be the last segment\r\n if (i !== segments.length - 1) {\r\n throw new Error(\r\n `Catch-all segment \"${seg}\" in \"${routePath}\" must be the last segment.`\r\n );\r\n }\r\n\r\n // (.+) = one or more characters (non-empty), allows \"/\" inside\r\n regexParts.push(\"(.+)\");\r\n continue;\r\n }\r\n\r\n // 2) Normal param: [slug]\r\n if (seg.startsWith(\"[\") && seg.endsWith(\"]\")) {\r\n const paramName = seg.slice(1, -1);\r\n paramNames.push(paramName);\r\n regexParts.push(\"([^/]+)\");\r\n continue;\r\n }\r\n\r\n // 3) Static segment - escape special regex characters\r\n const escaped = seg.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\r\n regexParts.push(escaped);\r\n }\r\n\r\n const regexSource = \"^/\" + regexParts.join(\"/\") + \"/?$\";\r\n const regex = new RegExp(regexSource);\r\n\r\n return { regex, paramNames };\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { LayoutComponent } from \"./index.types\";\r\nimport { LAYOUT_FILE_BASENAME } from \"./constants\";\r\n\r\n/**\r\n * Finds a layout file in the given directory.\r\n * \r\n * Checks for layout files in this order:\r\n * 1. layout.tsx\r\n * 2. layout.ts\r\n * 3. layout.jsx\r\n * 4. layout.js\r\n * \r\n * @param dir - Directory to search for layout file\r\n * @returns Full path to layout file, or null if not found\r\n */\r\nexport function findLayoutFileInDir(dir: string): string | null {\r\n const candidates = [\r\n `${LAYOUT_FILE_BASENAME}.tsx`,\r\n `${LAYOUT_FILE_BASENAME}.ts`,\r\n `${LAYOUT_FILE_BASENAME}.jsx`,\r\n `${LAYOUT_FILE_BASENAME}.js`,\r\n ];\r\n\r\n for (const file of candidates) {\r\n const fullPath = path.join(dir, file);\r\n if (fs.existsSync(fullPath)) return fullPath;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Loads all layout components for a page directory.\r\n * \r\n * Walks up from the page directory to the app root, collecting layouts\r\n * at each level. Returns layouts in order from root to most specific.\r\n * \r\n * @param pageDir - Directory containing the page file\r\n * @param appDir - Root app directory\r\n * @returns Object with layout components and their file paths\r\n * \r\n * @example\r\n * // app/layout.tsx (root)\r\n * // app/blog/layout.tsx (blog)\r\n * // app/blog/[slug]/page.tsx (page)\r\n * \r\n * loadLayoutsForDir('app/blog/[slug]', 'app')\r\n * // Returns: [RootLayout, BlogLayout] (in that order)\r\n */\r\nexport function loadLayoutsForDir(\r\n pageDir: string,\r\n appDir: string\r\n): { components: LayoutComponent[]; files: string[] } {\r\n const componentsBottomUp: LayoutComponent[] = [];\r\n const filesBottomUp: string[] = [];\r\n\r\n let currentDir = pageDir;\r\n const appDirResolved = path.resolve(appDir);\r\n\r\n while (true) {\r\n const layoutFile = findLayoutFileInDir(currentDir);\r\n if (layoutFile) {\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n const mod = require(layoutFile);\r\n const LayoutComp: LayoutComponent = mod.default;\r\n if (LayoutComp) {\r\n componentsBottomUp.push(LayoutComp);\r\n filesBottomUp.push(layoutFile);\r\n }\r\n }\r\n\r\n const currentResolved = path.resolve(currentDir);\r\n if (currentResolved === appDirResolved) break;\r\n\r\n const parent = path.dirname(currentDir);\r\n if (parent === currentDir) break; // Reached filesystem root\r\n currentDir = parent;\r\n }\r\n\r\n // Reverse to get root → most specific order\r\n return {\r\n components: componentsBottomUp.reverse(),\r\n files: filesBottomUp.reverse(),\r\n };\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport {\r\n DynamicMode,\r\n GenerateStaticParams,\r\n RouteMiddleware,\r\n ServerLoader,\r\n} from \"./index.types\";\r\n\r\nconst NAMING = {\r\n // Constants & Fns\r\n BEFORE_MIDDLEWARES: \"beforeServerData\",\r\n GET_SERVER_DATA_FN: \"getServerSideProps\",\r\n GENERATE_SSG_PARAMS: \"generateStaticParams\",\r\n RENDER_TYPE_CONST: \"dynamic\",\r\n\r\n // Files\r\n SERVER_HOOK: 'server.hook',\r\n};\r\n\r\n/**\r\n * Loads server-side hooks (loader, middlewares, SSG config) from a directory.\r\n *\r\n * Looks for `server.hook.ts` or `server.hook.js` in the given directory.\r\n *\r\n * @param currentDir - Directory to search for server hook file\r\n * @returns Object containing middlewares, loader, dynamic mode, and generateStaticParams\r\n *\r\n * @example\r\n * // app/blog/[slug]/server.hook.ts\r\n * export const beforeServerData = [authMiddleware];\r\n * export const getServerSideProps = async (ctx) => ({ props: {} });\r\n * export const dynamic = \"force-static\";\r\n * export const generateStaticParams = async () => [{ slug: \"post-1\" }];\r\n */\r\nexport function loadLoaderForDir(currentDir: string): {\r\n middlewares: RouteMiddleware[];\r\n loader: ServerLoader | null;\r\n dynamic: DynamicMode;\r\n generateStaticParams: GenerateStaticParams | null;\r\n} {\r\n const loaderTs = path.join(currentDir, `${NAMING.SERVER_HOOK}.ts`);\r\n const loaderJs = path.join(currentDir, `${NAMING.SERVER_HOOK}.js`);\r\n\r\n const file = fs.existsSync(loaderTs)\r\n ? loaderTs\r\n : fs.existsSync(loaderJs)\r\n ? loaderJs\r\n : null;\r\n\r\n if (!file) {\r\n return {\r\n middlewares: [],\r\n loader: null,\r\n dynamic: \"auto\",\r\n generateStaticParams: null,\r\n };\r\n }\r\n\r\n // Ensure tsx is loaded for TypeScript files during build\r\n // tsx automatically reads tsconfig.json from the project root to resolve path aliases\r\n if (file.endsWith('.ts') || file.endsWith('.tsx')) {\r\n try {\r\n // Load tsx if not already loaded - it will handle TypeScript compilation and path resolution\r\n require('tsx/cjs');\r\n } catch (e) {\r\n // tsx might already be loaded, ignore error\r\n }\r\n }\r\n\r\n let mod;\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n mod = require(file);\r\n } catch (error) {\r\n console.error(\r\n `[framework][loader] Error loading server hook from ${file}:`,\r\n error\r\n );\r\n // Return defaults if module fails to load\r\n return {\r\n middlewares: [],\r\n loader: null,\r\n dynamic: \"auto\",\r\n generateStaticParams: null,\r\n };\r\n }\r\n\r\n const middlewares: RouteMiddleware[] = Array.isArray(\r\n mod?.[NAMING.BEFORE_MIDDLEWARES]\r\n )\r\n ? mod[NAMING.BEFORE_MIDDLEWARES]\r\n : [];\r\n\r\n const loader: ServerLoader | null =\r\n typeof mod?.[NAMING.GET_SERVER_DATA_FN] === \"function\"\r\n ? mod[NAMING.GET_SERVER_DATA_FN]\r\n : null;\r\n\r\n const dynamic: DynamicMode =\r\n mod?.[NAMING.RENDER_TYPE_CONST] === \"force-static\" ||\r\n mod?.[NAMING.RENDER_TYPE_CONST] === \"force-dynamic\"\r\n ? mod.dynamic\r\n : \"auto\";\r\n\r\n const generateStaticParams: GenerateStaticParams | null =\r\n typeof mod?.[NAMING.GENERATE_SSG_PARAMS] === \"function\"\r\n ? mod[NAMING.GENERATE_SSG_PARAMS]\r\n : null;\r\n\r\n return {\r\n middlewares,\r\n loader,\r\n dynamic,\r\n generateStaticParams,\r\n };\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { ApiRoute } from \"./index.types\";\r\nimport {\r\n extractApiHandlers,\r\n extractApiMiddlewares,\r\n extractRouteRegex,\r\n loadModuleSafely,\r\n} from \"./helpers/routes\";\r\n\r\nconst ROUTE_FILE_REGEX = /route\\.(ts|tsx|js|jsx)$/;\r\nconst HTTP_METHODS = [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"];\r\n\r\n/**\r\n * Scans the app/api directory and loads all API routes.\r\n * \r\n * Recursively walks through the app/api directory, finding all `route.ts`, `route.tsx`,\r\n * `route.js`, or `route.jsx` files and creating API route definitions.\r\n * \r\n * @param appDir - Root directory of the app (e.g., 'app')\r\n * @returns Array of loaded API routes with handlers and middlewares\r\n * \r\n * @example\r\n * const apiRoutes = loadApiRoutes('app');\r\n * // [\r\n * // {\r\n * // pattern: '/api/posts/[id]',\r\n * // handlers: { GET: getPost, POST: updatePost },\r\n * // middlewares: [authMiddleware],\r\n * // methodMiddlewares: { GET: [logMiddleware] },\r\n * // },\r\n * // ]\r\n */\r\nexport function loadApiRoutes(appDir: string): ApiRoute[] {\r\n const apiRoot = path.join(appDir, \"api\");\r\n const routes: ApiRoute[] = [];\r\n\r\n if (!fs.existsSync(apiRoot)) return routes;\r\n\r\n function walk(currentDir: string) {\r\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(currentDir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n walk(fullPath);\r\n continue;\r\n }\r\n\r\n // Only process route files\r\n if (!ROUTE_FILE_REGEX.test(entry.name)) continue;\r\n\r\n const relToApp = path.relative(appDir, fullPath).replace(/\\\\/g, \"/\");\r\n const withoutRoute = relToApp.replace(/\\/route\\.(ts|tsx|js|jsx)$/, \"\");\r\n const pattern = \"/\" + withoutRoute;\r\n\r\n const { regex, paramNames } = extractRouteRegex(pattern);\r\n\r\n const mod = loadModuleSafely(fullPath);\r\n if (!mod) {\r\n continue;\r\n }\r\n\r\n const handlers = extractApiHandlers(mod, HTTP_METHODS);\r\n const { global: globalMiddlewares, methodSpecific: methodMiddlewares } =\r\n extractApiMiddlewares(mod, HTTP_METHODS);\r\n\r\n routes.push({\r\n pattern,\r\n regex,\r\n paramNames,\r\n handlers,\r\n middlewares: globalMiddlewares,\r\n methodMiddlewares,\r\n filePath: fullPath,\r\n });\r\n }\r\n }\r\n\r\n walk(apiRoot);\r\n\r\n return routes;\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport {\r\n ApiHandler,\r\n ApiMiddleware,\r\n LayoutComponent,\r\n PageComponent,\r\n RoutesManifest,\r\n} from \"../../index.types\";\r\nimport { buildRegexFromRoutePath } from \"../../path\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\n/**\r\n * Reads and parses the routes manifest file.\r\n */\r\nexport function readManifest(projectRoot: string): RoutesManifest | null {\r\n const manifestPath = path.join(\r\n projectRoot,\r\n BUILD_FOLDER_NAME,\r\n \"routes-manifest.json\"\r\n );\r\n\r\n if (!fs.existsSync(manifestPath)) {\r\n return null;\r\n }\r\n\r\n const raw = fs.readFileSync(manifestPath, \"utf-8\");\r\n return JSON.parse(raw) as RoutesManifest;\r\n}\r\n\r\n/**\r\n * Safely loads a module with error handling.\r\n */\r\nexport function loadModuleSafely(filePath: string): any | null {\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n return require(filePath);\r\n } catch (err) {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Loads and processes layout components from layout file paths.\r\n */\r\nexport function loadLayouts(\r\n layoutFiles: string[],\r\n projectRoot: string\r\n): LayoutComponent[] {\r\n const layoutMods = layoutFiles.map((lf) => {\r\n const fullPath = path.join(projectRoot, lf);\r\n return loadModuleSafely(fullPath);\r\n });\r\n\r\n return layoutMods\r\n .filter((m): m is { default: LayoutComponent } => !!m?.default)\r\n .map((m) => m.default);\r\n}\r\n\r\n/**\r\n * Builds regex and extracts param names from a route pattern.\r\n */\r\nexport function extractRouteRegex(pattern: string, paramNames?: string[]) {\r\n const { regex, paramNames: extractedParamNames } =\r\n buildRegexFromRoutePath(pattern);\r\n return {\r\n regex,\r\n paramNames: paramNames ?? extractedParamNames,\r\n };\r\n}\r\n\r\n/**\r\n * Extracts HTTP method handlers from a module.\r\n */\r\nexport function extractApiHandlers(\r\n mod: any,\r\n methods: string[]\r\n): Record<string, ApiHandler> {\r\n const handlers: Record<string, ApiHandler> = {};\r\n\r\n for (const method of methods) {\r\n if (typeof mod[method] === \"function\") {\r\n handlers[method] = mod[method] as ApiHandler;\r\n }\r\n }\r\n\r\n return handlers;\r\n}\r\n\r\n/**\r\n * Extracts global and method-specific middlewares from a module.\r\n */\r\nexport function extractApiMiddlewares(\r\n mod: any,\r\n methods: string[]\r\n): {\r\n global: ApiMiddleware[];\r\n methodSpecific: Record<string, ApiMiddleware[]>;\r\n} {\r\n const globalMiddlewares: ApiMiddleware[] = Array.isArray(mod.beforeApi)\r\n ? mod.beforeApi\r\n : [];\r\n\r\n const methodMiddlewares: Record<string, ApiMiddleware[]> = {};\r\n\r\n for (const method of methods) {\r\n const key = `before${method}`;\r\n const mws = mod[key];\r\n if (Array.isArray(mws)) {\r\n methodMiddlewares[method] = mws as ApiMiddleware[];\r\n }\r\n }\r\n\r\n return {\r\n global: globalMiddlewares,\r\n methodSpecific: methodMiddlewares,\r\n };\r\n}\r\n\r\n/**\r\n * Extracts WebSocket event handlers from a module.\r\n */\r\nexport function extractWssHandlers(\r\n mod: any,\r\n events: string[]\r\n): Record<string, ApiHandler> {\r\n const handlers: Record<string, ApiHandler> = {};\r\n\r\n if (!Array.isArray(mod.events)) {\r\n return handlers;\r\n }\r\n\r\n for (const eventName of events) {\r\n if (typeof eventName === \"string\") {\r\n const event = mod.events.find(\r\n (e: { name: string }) => e.name?.toLowerCase() === eventName.toLowerCase()\r\n );\r\n if (event?.handler) {\r\n handlers[eventName] = event.handler as ApiHandler;\r\n }\r\n }\r\n }\r\n\r\n return handlers;\r\n}\r\n\r\n/**\r\n * Extracts all WebSocket event handlers directly from a module's events array.\r\n * This is used when scanning filesystem routes where we iterate over all events.\r\n */\r\nexport function extractWssHandlersFromModule(mod: any): Record<string, ApiHandler> {\r\n const handlers: Record<string, ApiHandler> = {};\r\n\r\n if (!Array.isArray(mod?.events)) {\r\n return handlers;\r\n }\r\n\r\n for (const event of mod.events) {\r\n if (typeof event.handler === \"function\" && typeof event.name === \"string\") {\r\n handlers[event.name.toLowerCase()] = event.handler as ApiHandler;\r\n }\r\n }\r\n\r\n return handlers;\r\n}\r\n\r\n/**\r\n * Loads a page component from a file path.\r\n */\r\nexport function loadPageComponent(\r\n pageFile: string,\r\n projectRoot: string\r\n): PageComponent | null {\r\n const fullPath = path.join(projectRoot, pageFile);\r\n const pageMod = loadModuleSafely(fullPath);\r\n return pageMod?.default || null;\r\n}\r\n\r\n","import { ApiRoute, LoadedRoute } from \"./index.types\";\r\n\r\n/**\r\n * Matches a URL path against loaded routes and returns the matched route with params.\r\n * \r\n * @param routes - Array of loaded routes to match against\r\n * @param urlPath - URL path to match (e.g., '/blog/my-post')\r\n * @returns Matched route with extracted parameters, or null if no match\r\n * \r\n * @example\r\n * const routes = loadRoutes('app');\r\n * const match = matchRoute(routes, '/blog/my-post');\r\n * // { route: LoadedRoute, params: { slug: 'my-post' } }\r\n */\r\nexport function matchRoute(\r\n routes: LoadedRoute[],\r\n urlPath: string\r\n): { route: LoadedRoute; params: Record<string, string> } | null {\r\n for (const route of routes) {\r\n const match = route.regex.exec(urlPath);\r\n if (!match) continue;\r\n\r\n const params: Record<string, string> = {};\r\n route.paramNames.forEach((name, idx) => {\r\n params[name] = match[idx + 1];\r\n });\r\n\r\n return { route, params };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Matches a URL path against API routes and returns the matched route with params.\r\n * \r\n * @param routes - Array of API routes to match against\r\n * @param pathname - URL path to match (e.g., '/api/posts/123')\r\n * @returns Matched API route with extracted parameters, or null if no match\r\n * \r\n * @example\r\n * const apiRoutes = loadApiRoutes('app');\r\n * const match = matchApiRoute(apiRoutes, '/api/posts/123');\r\n * // { route: ApiRoute, params: { id: '123' } }\r\n */\r\nexport function matchApiRoute(\r\n routes: ApiRoute[],\r\n pathname: string\r\n): { route: ApiRoute; params: Record<string, string> } | null {\r\n for (const r of routes) {\r\n const match = r.regex.exec(pathname);\r\n if (!match) continue;\r\n\r\n const params: Record<string, string> = {};\r\n r.paramNames.forEach((name, idx) => {\r\n params[name] = match[idx + 1];\r\n });\r\n\r\n return { route: r, params };\r\n }\r\n return null;\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport {\r\n ApiRoute,\r\n ApiRouteManifestEntry,\r\n LoadedRoute,\r\n PageRouteManifestEntry,\r\n RoutesManifest,\r\n WssRoute,\r\n WssRouteManifestEntry,\r\n} from \"./index.types\";\r\nimport {\r\n BUILD_FOLDER_NAME,\r\n STYLE_FILE_NAME,\r\n NOT_FOUND_FILE_PREFIX,\r\n ERROR_FILE_PREFIX,\r\n NOT_FOUND_CHUNK_KEY,\r\n ERROR_CHUNK_KEY,\r\n NOT_FOUND_PATTERN,\r\n ERROR_PATTERN,\r\n} from \"@constants/globals\";\r\n\r\n/**\r\n * Writes the client-side routes manifest file.\r\n *\r\n * Generates a TypeScript file that exports route definitions with lazy-loaded\r\n * components for code splitting. The manifest is used by the client runtime\r\n * to handle client-side navigation.\r\n *\r\n * @param routes - Array of loaded routes\r\n * @param projectRoot - Root directory of the project\r\n * @param errorRoute - Optional error route for client-side error handling\r\n */\r\nexport function writeClientRoutesManifest(\r\n routes: LoadedRoute[],\r\n projectRoot: string\r\n): void {\r\n const fwDir = path.join(projectRoot, BUILD_FOLDER_NAME);\r\n if (!fs.existsSync(fwDir)) {\r\n fs.mkdirSync(fwDir, { recursive: true });\r\n }\r\n\r\n const manifestPath = path.join(fwDir, \"routes-client.ts\");\r\n const manifestDir = path.dirname(manifestPath);\r\n\r\n function toImportPath(filePath: string): string {\r\n const relRaw = path.relative(manifestDir, filePath).replace(/\\\\/g, \"/\");\r\n const rel = relRaw.startsWith(\".\") ? relRaw : \"./\" + relRaw;\r\n // Remove extension so bundler can resolve .tsx, .ts, .jsx, .js\r\n return rel.replace(/\\.(tsx|ts|jsx|js)$/, \"\");\r\n }\r\n\r\n function findUserNotFound(): string | null {\r\n const candidates = [\r\n `app/${NOT_FOUND_FILE_PREFIX}.tsx`,\r\n `app/${NOT_FOUND_FILE_PREFIX}.ts`,\r\n `app/${NOT_FOUND_FILE_PREFIX}.jsx`,\r\n `app/${NOT_FOUND_FILE_PREFIX}.js`,\r\n // Fallback to old style for backward compatibility\r\n \"app/not-found/page.tsx\",\r\n \"app/not-found/page.ts\",\r\n \"app/not-found/page.jsx\",\r\n \"app/not-found/page.js\",\r\n ];\r\n\r\n for (const rel of candidates) {\r\n const full = path.join(projectRoot, rel);\r\n if (fs.existsSync(full)) return full;\r\n }\r\n return null;\r\n }\r\n\r\n function findUserError(): string | null {\r\n const candidates = [\r\n `app/${ERROR_FILE_PREFIX}.tsx`,\r\n `app/${ERROR_FILE_PREFIX}.ts`,\r\n `app/${ERROR_FILE_PREFIX}.jsx`,\r\n `app/${ERROR_FILE_PREFIX}.js`,\r\n ];\r\n\r\n for (const rel of candidates) {\r\n const full = path.join(projectRoot, rel);\r\n if (fs.existsSync(full)) return full;\r\n }\r\n return null;\r\n }\r\n\r\n function findRootLayout(): string | null {\r\n const candidates = [\r\n \"app/layout.tsx\",\r\n \"app/layout.ts\",\r\n \"app/layout.jsx\",\r\n \"app/layout.js\",\r\n ];\r\n\r\n for (const rel of candidates) {\r\n const full = path.join(projectRoot, rel);\r\n if (fs.existsSync(full)) return full;\r\n }\r\n return null;\r\n }\r\n\r\n const lines: string[] = [];\r\n const chunkMap: Record<string, string> = {};\r\n\r\n lines.push(`import React from \"react\";`);\r\n lines.push(\"\");\r\n\r\n lines.push(`export interface ClientLoadedComponents {`);\r\n lines.push(` Page: React.ComponentType<any>;`);\r\n lines.push(` layouts: React.ComponentType<any>[];`);\r\n lines.push(`}`);\r\n lines.push(\"\");\r\n\r\n lines.push(`export interface ClientRouteLoaded {`);\r\n lines.push(` pattern: string;`);\r\n lines.push(` paramNames: string[];`);\r\n lines.push(` load: () => Promise<ClientLoadedComponents>;`);\r\n lines.push(`}`);\r\n lines.push(\"\");\r\n\r\n // --- rutas normales ---\r\n lines.push(`export const routes: ClientRouteLoaded[] = [`);\r\n\r\n for (const route of routes) {\r\n const pattern = route.pattern;\r\n const paramNames = route.paramNames;\r\n\r\n const modulePaths = [route.pageFile, ...route.layoutFiles].map(\r\n toImportPath\r\n );\r\n\r\n const safeName =\r\n pattern.replace(/^\\//, \"\").replace(/\\//g, \"_\").replace(/\\[|\\]/g, \"\") ||\r\n \"root\";\r\n\r\n const chunkName = `route-${safeName}`;\r\n chunkMap[pattern] = chunkName;\r\n\r\n lines.push(\" {\");\r\n lines.push(` pattern: ${JSON.stringify(pattern)},`);\r\n lines.push(` paramNames: ${JSON.stringify(paramNames)},`);\r\n lines.push(` load: async () => {`);\r\n lines.push(` const mods = await Promise.all([`);\r\n\r\n for (const p of modulePaths) {\r\n lines.push(\r\n ` import(/* webpackChunkName: \"${chunkName}\" */ \"${p}\"),`\r\n );\r\n }\r\n\r\n lines.push(\" ]);\");\r\n lines.push(\" const [pageMod, ...layoutMods] = mods;\");\r\n lines.push(\" return {\");\r\n lines.push(\" Page: pageMod.default,\");\r\n lines.push(\" layouts: layoutMods.map((m) => m.default),\");\r\n lines.push(\" };\");\r\n lines.push(\" },\");\r\n lines.push(\" },\");\r\n }\r\n\r\n lines.push(\"];\");\r\n lines.push(\"\");\r\n\r\n const notFoundPath = findUserNotFound();\r\n const errorPath = findUserError();\r\n const rootLayoutPath = findRootLayout();\r\n\r\n if (notFoundPath) {\r\n const notFoundImportPath = toImportPath(notFoundPath);\r\n const chunkName = \"route-not-found\";\r\n\r\n lines.push(`export const notFoundRoute: ClientRouteLoaded = {`);\r\n lines.push(` pattern: \"${NOT_FOUND_CHUNK_KEY}\",`);\r\n lines.push(` paramNames: [],`);\r\n lines.push(` load: async () => {`);\r\n lines.push(` const mods = await Promise.all([`);\r\n lines.push(\r\n ` import(/* webpackChunkName: \"${chunkName}\" */ \"${notFoundImportPath}\"),`\r\n );\r\n\r\n if (rootLayoutPath) {\r\n const rootLayoutImportPath = toImportPath(rootLayoutPath);\r\n lines.push(\r\n ` import(/* webpackChunkName: \"${chunkName}\" */ \"${rootLayoutImportPath}\"),`\r\n );\r\n }\r\n\r\n lines.push(` ]);`);\r\n lines.push(` const [pageMod, ...layoutMods] = mods;`);\r\n lines.push(` return {`);\r\n lines.push(` Page: pageMod.default,`);\r\n lines.push(` layouts: layoutMods.map((m) => m.default),`);\r\n lines.push(` };`);\r\n lines.push(` },`);\r\n lines.push(`};`);\r\n lines.push(\"\");\r\n\r\n chunkMap[NOT_FOUND_CHUNK_KEY] = chunkName;\r\n } else {\r\n lines.push(`export const notFoundRoute: ClientRouteLoaded | null = null;`);\r\n lines.push(\"\");\r\n }\r\n\r\n if (errorPath) {\r\n const errorImportPath = toImportPath(errorPath);\r\n const chunkName = \"route-error\";\r\n\r\n lines.push(`export const errorRoute: ClientRouteLoaded = {`);\r\n lines.push(` pattern: \"${ERROR_CHUNK_KEY}\",`);\r\n lines.push(` paramNames: [],`);\r\n lines.push(` load: async () => {`);\r\n lines.push(` const mods = await Promise.all([`);\r\n lines.push(\r\n ` import(/* webpackChunkName: \"${chunkName}\" */ \"${errorImportPath}\"),`\r\n );\r\n\r\n if (rootLayoutPath) {\r\n const rootLayoutImportPath = toImportPath(rootLayoutPath);\r\n lines.push(\r\n ` import(/* webpackChunkName: \"${chunkName}\" */ \"${rootLayoutImportPath}\"),`\r\n );\r\n }\r\n\r\n lines.push(` ]);`);\r\n lines.push(` const [pageMod, ...layoutMods] = mods;`);\r\n lines.push(` return {`);\r\n lines.push(` Page: pageMod.default,`);\r\n lines.push(` layouts: layoutMods.map((m) => m.default),`);\r\n lines.push(` };`);\r\n lines.push(` },`);\r\n lines.push(`};`);\r\n lines.push(\"\");\r\n\r\n chunkMap[ERROR_CHUNK_KEY] = chunkName;\r\n } else {\r\n lines.push(`export const errorRoute: ClientRouteLoaded | null = null;`);\r\n lines.push(\"\");\r\n }\r\n\r\n fs.writeFileSync(manifestPath, lines.join(\"\\n\"), \"utf-8\");\r\n\r\n const chunksJsonPath = path.join(fwDir, \"route-chunks.json\");\r\n fs.writeFileSync(chunksJsonPath, JSON.stringify(chunkMap, null, 2), \"utf-8\");\r\n}\r\n\r\n/**\r\n * Writes the client bootstrap manifest file.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n */\r\nexport function writeClientBoostrapManifest(projectRoot: string): void {\r\n const buildDir = path.join(projectRoot, BUILD_FOLDER_NAME);\r\n if (!fs.existsSync(buildDir)) {\r\n fs.mkdirSync(buildDir, { recursive: true });\r\n }\r\n\r\n const manifestPath = path.join(buildDir, \"boostrap.ts\");\r\n\r\n const lines: string[] = [];\r\n\r\n lines.push(`import \"../app/${STYLE_FILE_NAME}\";`);\r\n lines.push(\"\");\r\n\r\n lines.push(`import {`);\r\n lines.push(` routes,`);\r\n lines.push(` type ClientRouteLoaded,`);\r\n lines.push(` notFoundRoute,`);\r\n lines.push(` errorRoute,`);\r\n lines.push(`} from \"./routes-client\";`);\r\n lines.push(\"\");\r\n\r\n lines.push(`import { bootstrapClient } from \"@lolyjs/core/runtime\"`);\r\n lines.push(\"\");\r\n lines.push(\r\n \"bootstrapClient(routes as ClientRouteLoaded[], notFoundRoute, errorRoute);\"\r\n );\r\n\r\n fs.writeFileSync(manifestPath, lines.join(\"\\n\"), \"utf-8\");\r\n}\r\n\r\n/**\r\n * Writes the routes manifest JSON file.\r\n *\r\n * This manifest contains only data (no functions) and is:\r\n * - Readable by Node without compiling TypeScript\r\n * - Usable by the production server\r\n * - Usable by build/SSG processes\r\n *\r\n * @param routes - Array of loaded page routes\r\n * @param apiRoutes - Array of loaded API routes\r\n * @param notFoundRoute - Not-found route definition\r\n * @param errorRoute - Error route definition (optional)\r\n * @param projectRoot - Root directory of the project\r\n * @param serverOutDir - Server output directory from buildServerApp\r\n * @param appDir - Absolute path to the app directory\r\n */\r\nexport function writeRoutesManifest({\r\n routes,\r\n apiRoutes,\r\n wssRoutes,\r\n notFoundRoute,\r\n errorRoute,\r\n projectRoot,\r\n serverOutDir,\r\n appDir,\r\n}: {\r\n routes: LoadedRoute[];\r\n apiRoutes: ApiRoute[];\r\n wssRoutes: WssRoute[];\r\n notFoundRoute: LoadedRoute;\r\n errorRoute: LoadedRoute | null;\r\n projectRoot: string;\r\n serverOutDir: string;\r\n appDir: string;\r\n}) {\r\n const fwDir = path.join(projectRoot, BUILD_FOLDER_NAME);\r\n if (!fs.existsSync(fwDir)) {\r\n fs.mkdirSync(fwDir, { recursive: true });\r\n }\r\n\r\n const manifestPath = path.join(fwDir, \"routes-manifest.json\");\r\n\r\n const toRelative = (abs: string) =>\r\n path.relative(projectRoot, abs).replace(/\\\\/g, \"/\");\r\n\r\n const convertToJs = (file: string) =>\r\n file.replace(/\\.(ts|tsx|jsx|mjs|cjs)$/i, \".js\");\r\n\r\n const pageEntries: PageRouteManifestEntry[] = routes.map((r) => {\r\n const relativeSource = path.relative(appDir, r.pageFile);\r\n\r\n const jsPageFile = path.join(serverOutDir, convertToJs(relativeSource));\r\n\r\n const jsLayoutFiles = r.layoutFiles.map((lf) => {\r\n const rel = path.relative(appDir, lf);\r\n return path.join(serverOutDir, convertToJs(rel));\r\n });\r\n\r\n return {\r\n type: \"page\",\r\n pattern: r.pattern,\r\n paramNames: r.paramNames,\r\n pageFile: toRelative(jsPageFile),\r\n layoutFiles: jsLayoutFiles.map(toRelative),\r\n dynamic: r.dynamic,\r\n };\r\n });\r\n\r\n const apiEntries: ApiRouteManifestEntry[] = apiRoutes\r\n .map((r) => {\r\n const anyRoute = r as any;\r\n const filePath: string | undefined = anyRoute.filePath;\r\n\r\n if (!filePath) {\r\n return undefined;\r\n }\r\n\r\n const relSource = path.relative(appDir, filePath);\r\n\r\n const jsApiFile = path.join(serverOutDir, convertToJs(relSource));\r\n\r\n const methods = Object.keys(r.handlers || {});\r\n\r\n const entry: ApiRouteManifestEntry = {\r\n type: \"api\",\r\n pattern: r.pattern,\r\n paramNames: r.paramNames,\r\n file: toRelative(jsApiFile),\r\n methods,\r\n };\r\n\r\n return entry;\r\n })\r\n .filter((e): e is ApiRouteManifestEntry => !!e);\r\n\r\n const wssEntries: WssRouteManifestEntry[] = wssRoutes\r\n .map((r) => {\r\n const anyRoute = r as any;\r\n const filePath: string | undefined = anyRoute.filePath;\r\n\r\n if (!filePath) {\r\n return undefined;\r\n }\r\n\r\n const relSource = path.relative(appDir, filePath);\r\n\r\n const jsApiFile = path.join(serverOutDir, convertToJs(relSource));\r\n\r\n const events = Object.keys(r.handlers || {});\r\n\r\n const entry: WssRouteManifestEntry = {\r\n type: \"wss\",\r\n pattern: r.pattern,\r\n paramNames: r.paramNames,\r\n file: toRelative(jsApiFile),\r\n events,\r\n };\r\n\r\n return entry;\r\n })\r\n .filter((e): e is WssRouteManifestEntry => !!e);\r\n\r\n // Build not-found page entry\r\n const notFoundLayoutFiles = notFoundRoute.layoutFiles || [];\r\n const notFoundJsLayoutFiles = notFoundLayoutFiles.map((lf) => {\r\n const rel = path.relative(appDir, lf);\r\n return path.join(serverOutDir, convertToJs(rel));\r\n });\r\n\r\n const notFoundRelativeSource = notFoundRoute.pageFile\r\n ? path.relative(appDir, notFoundRoute.pageFile)\r\n : `${NOT_FOUND_FILE_PREFIX}.tsx`;\r\n const notFoundJsPageFile = notFoundRoute.pageFile\r\n ? path.join(serverOutDir, convertToJs(notFoundRelativeSource))\r\n : path.join(serverOutDir, convertToJs(`${NOT_FOUND_FILE_PREFIX}.tsx`));\r\n\r\n const notFoundPage: PageRouteManifestEntry = {\r\n type: \"page\",\r\n pageFile: toRelative(notFoundJsPageFile),\r\n layoutFiles: notFoundJsLayoutFiles.map(toRelative),\r\n dynamic: \"force-static\",\r\n paramNames: [],\r\n pattern: NOT_FOUND_PATTERN,\r\n };\r\n\r\n // Build error page entry (if exists)\r\n let errorPageEntry: PageRouteManifestEntry | undefined;\r\n if (errorRoute && errorRoute.pageFile) {\r\n const errorLayoutFiles = errorRoute.layoutFiles || [];\r\n const errorJsLayoutFiles = errorLayoutFiles.map((lf) => {\r\n const rel = path.relative(appDir, lf);\r\n return path.join(serverOutDir, convertToJs(rel));\r\n });\r\n\r\n const errorRelativeSource = path.relative(appDir, errorRoute.pageFile);\r\n const errorJsPageFile = path.join(\r\n serverOutDir,\r\n convertToJs(errorRelativeSource)\r\n );\r\n\r\n errorPageEntry = {\r\n type: \"page\",\r\n pageFile: toRelative(errorJsPageFile),\r\n layoutFiles: errorJsLayoutFiles.map(toRelative),\r\n dynamic: \"force-static\",\r\n paramNames: [],\r\n pattern: ERROR_PATTERN,\r\n };\r\n }\r\n\r\n const manifest: RoutesManifest = {\r\n version: 1,\r\n basePath: \"\",\r\n caseSensitive: false,\r\n pages404: true,\r\n routes: pageEntries,\r\n apiRoutes: apiEntries,\r\n notFound: notFoundPage,\r\n wssRoutes: wssEntries,\r\n ...(errorPageEntry && { error: errorPageEntry }),\r\n };\r\n\r\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), \"utf-8\");\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport {\r\n ApiRoute,\r\n LoadedRoute,\r\n WssRoute,\r\n} from \"./index.types\";\r\nimport { loadLoaderForDir } from \"./loader\";\r\nimport { BUILD_FOLDER_NAME, ERROR_PATTERN } from \"@constants/globals\";\r\nimport {\r\n extractApiHandlers,\r\n extractApiMiddlewares,\r\n extractRouteRegex,\r\n extractWssHandlers,\r\n loadLayouts,\r\n loadModuleSafely,\r\n loadPageComponent,\r\n readManifest,\r\n} from \"./helpers/routes\";\r\n\r\n/**\r\n * Loads page and API routes from the routes manifest file.\r\n * Used in production to avoid filesystem scanning.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @returns Object containing loaded routes and API routes\r\n */\r\nexport function loadRoutesFromManifest(projectRoot: string): {\r\n routes: LoadedRoute[];\r\n apiRoutes: ApiRoute[];\r\n wssRoutes: WssRoute[];\r\n} {\r\n const manifest = readManifest(projectRoot);\r\n if (!manifest) {\r\n return { routes: [], apiRoutes: [], wssRoutes: [] };\r\n }\r\n\r\n const pageRoutes: LoadedRoute[] = [];\r\n\r\n for (const entry of manifest.routes) {\r\n const { regex, paramNames } = extractRouteRegex(\r\n entry.pattern,\r\n entry.paramNames\r\n );\r\n\r\n const component = loadPageComponent(entry.pageFile, projectRoot);\r\n if (!component) {\r\n continue;\r\n }\r\n\r\n const layouts = loadLayouts(entry.layoutFiles, projectRoot);\r\n const pageFile = path.join(projectRoot, entry.pageFile);\r\n const layoutFiles = entry.layoutFiles.map((f) =>\r\n path.join(projectRoot, f)\r\n );\r\n const pageDir = path.dirname(pageFile);\r\n const { middlewares, loader, dynamic, generateStaticParams } =\r\n loadLoaderForDir(pageDir);\r\n\r\n pageRoutes.push({\r\n pattern: entry.pattern,\r\n regex,\r\n paramNames,\r\n component,\r\n layouts,\r\n pageFile,\r\n layoutFiles,\r\n middlewares,\r\n loader,\r\n dynamic: entry.dynamic ?? dynamic,\r\n generateStaticParams,\r\n });\r\n }\r\n\r\n const apiRoutes: ApiRoute[] = [];\r\n const httpMethods = [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"];\r\n\r\n for (const entry of manifest.apiRoutes) {\r\n const { regex, paramNames } = extractRouteRegex(\r\n entry.pattern,\r\n entry.paramNames\r\n );\r\n const filePath = path.join(projectRoot, entry.file);\r\n const mod = loadModuleSafely(filePath);\r\n\r\n if (!mod) {\r\n continue;\r\n }\r\n\r\n const handlers = extractApiHandlers(mod, httpMethods);\r\n const { global: globalMiddlewares, methodSpecific: methodMiddlewares } =\r\n extractApiMiddlewares(mod, httpMethods);\r\n\r\n apiRoutes.push({\r\n pattern: entry.pattern,\r\n regex,\r\n paramNames,\r\n handlers,\r\n middlewares: globalMiddlewares,\r\n methodMiddlewares,\r\n filePath,\r\n });\r\n }\r\n\r\n const wssRoutes: WssRoute[] = [];\r\n\r\n for (const entry of manifest.wssRoutes) {\r\n const { regex, paramNames } = extractRouteRegex(\r\n entry.pattern,\r\n entry.paramNames\r\n );\r\n const filePath = path.join(projectRoot, entry.file);\r\n const mod = loadModuleSafely(filePath);\r\n\r\n if (!mod) {\r\n continue;\r\n }\r\n\r\n const handlers = extractWssHandlers(mod, entry.events || []);\r\n const { global: globalMiddlewares, methodSpecific: methodMiddlewares } =\r\n extractApiMiddlewares(mod, []);\r\n\r\n wssRoutes.push({\r\n pattern: entry.pattern,\r\n regex,\r\n paramNames,\r\n handlers,\r\n middlewares: globalMiddlewares,\r\n methodMiddlewares,\r\n filePath,\r\n });\r\n }\r\n\r\n return { routes: pageRoutes, apiRoutes, wssRoutes };\r\n}\r\n\r\n/**\r\n * Loads route chunks mapping from the manifest file.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @returns Record mapping route patterns to chunk names\r\n */\r\nexport function loadChunksFromManifest(projectRoot: string): Record<string, string> {\r\n const chunksPath = path.join(\r\n projectRoot,\r\n BUILD_FOLDER_NAME,\r\n \"route-chunks.json\"\r\n );\r\n let routeChunks: Record<string, string> = {};\r\n if (fs.existsSync(chunksPath)) {\r\n try {\r\n routeChunks = JSON.parse(fs.readFileSync(chunksPath, \"utf-8\"));\r\n } catch (err) {\r\n // Silently fail if chunks file is invalid\r\n }\r\n }\r\n\r\n return routeChunks;\r\n}\r\n\r\n/**\r\n * Loads the not-found route from the routes manifest.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @returns LoadedRoute for the not-found page, or null if not found\r\n */\r\nexport function loadNotFoundFromManifest(\r\n projectRoot: string\r\n): LoadedRoute | null {\r\n const manifest = readManifest(projectRoot);\r\n if (!manifest) {\r\n return null;\r\n }\r\n\r\n const component = loadPageComponent(manifest.notFound.pageFile, projectRoot);\r\n if (!component) {\r\n return null;\r\n }\r\n\r\n const layouts = loadLayouts(manifest.notFound.layoutFiles, projectRoot);\r\n const pageFile = path.join(projectRoot, manifest.notFound.pageFile);\r\n\r\n return {\r\n pattern: \"\",\r\n regex: new RegExp(\"\"),\r\n paramNames: [],\r\n component,\r\n layouts,\r\n pageFile,\r\n layoutFiles: [],\r\n middlewares: [],\r\n loader: null,\r\n dynamic: \"force-static\",\r\n generateStaticParams: null,\r\n };\r\n}\r\n\r\n/**\r\n * Loads the error route from the routes manifest.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @returns LoadedRoute for the error page, or null if not found\r\n */\r\nexport function loadErrorFromManifest(\r\n projectRoot: string\r\n): LoadedRoute | null {\r\n const manifest = readManifest(projectRoot);\r\n if (!manifest) {\r\n return null;\r\n }\r\n\r\n // Check if error page exists in manifest\r\n const errorEntry = (manifest as any).error;\r\n if (!errorEntry) {\r\n return null;\r\n }\r\n\r\n const component = loadPageComponent(errorEntry.pageFile, projectRoot);\r\n if (!component) {\r\n return null;\r\n }\r\n\r\n const layoutFiles = (errorEntry.layoutFiles || []) as string[];\r\n const layouts = loadLayouts(layoutFiles, projectRoot);\r\n const pageFile = path.join(projectRoot, errorEntry.pageFile);\r\n\r\n return {\r\n pattern: ERROR_PATTERN,\r\n regex: new RegExp(`^${ERROR_PATTERN}/?$`),\r\n paramNames: [],\r\n component,\r\n layouts,\r\n pageFile,\r\n layoutFiles: [],\r\n middlewares: [],\r\n loader: null,\r\n dynamic: \"force-static\",\r\n generateStaticParams: null,\r\n };\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { ApiRoute, LoadedRoute, PageComponent, WssRoute } from \"./index.types\";\r\n\r\nimport { loadLayoutsForDir } from \"./layout\";\r\nimport { loadLoaderForDir } from \"./loader\";\r\nimport {\r\n loadRoutesFromManifest,\r\n loadNotFoundFromManifest,\r\n loadErrorFromManifest,\r\n loadChunksFromManifest,\r\n} from \"./loader-routes\";\r\nimport { loadRoutes } from \"./loader-pages\";\r\nimport { loadApiRoutes } from \"./loader-api\";\r\nimport {\r\n NOT_FOUND_PATTERN,\r\n ERROR_PATTERN,\r\n NOT_FOUND_FILE_PREFIX,\r\n ERROR_FILE_PREFIX,\r\n} from \"@constants/globals\";\r\nimport { loadWssRoutes } from \"./loader-wss\";\r\n\r\n/**\r\n * Unified interface for loading routes from different sources.\r\n * Abstracts the difference between filesystem (dev) and manifest (prod) loading.\r\n */\r\nexport interface RouteLoader {\r\n loadRoutes(): LoadedRoute[];\r\n loadApiRoutes(): ApiRoute[];\r\n loadWssRoutes(): WssRoute[];\r\n loadNotFoundRoute(): LoadedRoute | null;\r\n loadErrorRoute(): LoadedRoute | null;\r\n loadRouteChunks(): Record<string, string>;\r\n}\r\n\r\n/**\r\n * Loads routes directly from the filesystem.\r\n * Used in development mode.\r\n */\r\nexport class FilesystemRouteLoader implements RouteLoader {\r\n constructor(private appDir: string) {}\r\n\r\n loadRoutes(): LoadedRoute[] {\r\n return loadRoutes(this.appDir);\r\n }\r\n\r\n loadApiRoutes(): ApiRoute[] {\r\n return loadApiRoutes(this.appDir);\r\n }\r\n\r\n loadWssRoutes(): WssRoute[] {\r\n return loadWssRoutes(this.appDir);\r\n }\r\n\r\n loadNotFoundRoute(): LoadedRoute | null {\r\n return loadNotFoundRouteFromFilesystem(this.appDir);\r\n }\r\n\r\n loadErrorRoute(): LoadedRoute | null {\r\n return loadErrorRouteFromFilesystem(this.appDir);\r\n }\r\n\r\n loadRouteChunks(): Record<string, string> {\r\n // In dev, route chunks are not critical, return empty\r\n return {};\r\n }\r\n}\r\n\r\n/**\r\n * Loads routes from the compiled manifest file.\r\n * Used in production mode.\r\n */\r\nexport class ManifestRouteLoader implements RouteLoader {\r\n constructor(private projectRoot: string) {}\r\n\r\n loadRoutes(): LoadedRoute[] {\r\n const { routes } = loadRoutesFromManifest(this.projectRoot);\r\n return routes;\r\n }\r\n\r\n loadApiRoutes(): ApiRoute[] {\r\n const { apiRoutes } = loadRoutesFromManifest(this.projectRoot);\r\n return apiRoutes;\r\n }\r\n\r\n loadWssRoutes(): WssRoute[] {\r\n const { wssRoutes } = loadRoutesFromManifest(this.projectRoot);\r\n return wssRoutes;\r\n }\r\n\r\n loadNotFoundRoute(): LoadedRoute | null {\r\n return loadNotFoundFromManifest(this.projectRoot);\r\n }\r\n\r\n loadErrorRoute(): LoadedRoute | null {\r\n return loadErrorFromManifest(this.projectRoot);\r\n }\r\n\r\n loadRouteChunks(): Record<string, string> {\r\n return loadChunksFromManifest(this.projectRoot);\r\n }\r\n}\r\n\r\n/**\r\n * Loads the not-found route from the filesystem.\r\n * Looks for `_not-found.tsx` in the app root (Next.js style).\r\n *\r\n * @param appDir - Root directory of the app\r\n * @returns LoadedRoute for the not-found page, or null if not found\r\n */\r\nexport function loadNotFoundRouteFromFilesystem(\r\n appDir: string\r\n): LoadedRoute | null {\r\n const notFoundCandidates = [\r\n path.join(appDir, `${NOT_FOUND_FILE_PREFIX}.tsx`),\r\n path.join(appDir, `${NOT_FOUND_FILE_PREFIX}.ts`),\r\n path.join(appDir, `${NOT_FOUND_FILE_PREFIX}.jsx`),\r\n path.join(appDir, `${NOT_FOUND_FILE_PREFIX}.js`),\r\n // Fallback to old style for backward compatibility\r\n path.join(appDir, \"not-found\", \"page.tsx\"),\r\n path.join(appDir, \"not-found\", \"page.ts\"),\r\n path.join(appDir, \"not-found\", \"page.jsx\"),\r\n path.join(appDir, \"not-found\", \"page.js\"),\r\n ];\r\n\r\n let notFoundFile: string | null = null;\r\n for (const candidate of notFoundCandidates) {\r\n if (fs.existsSync(candidate)) {\r\n notFoundFile = candidate;\r\n break;\r\n }\r\n }\r\n\r\n if (!notFoundFile) {\r\n return null;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n const mod = require(notFoundFile);\r\n const component: PageComponent = mod.default;\r\n\r\n if (!component) {\r\n return null;\r\n }\r\n\r\n // For _not-found.tsx in root, use appDir as the directory\r\n const notFoundDir = notFoundFile.includes(NOT_FOUND_FILE_PREFIX)\r\n ? appDir\r\n : path.dirname(notFoundFile);\r\n\r\n const { components: layouts, files: layoutFiles } = loadLayoutsForDir(\r\n notFoundDir,\r\n appDir\r\n );\r\n\r\n const { middlewares, loader, dynamic, generateStaticParams } =\r\n loadLoaderForDir(notFoundDir);\r\n\r\n return {\r\n pattern: NOT_FOUND_PATTERN,\r\n regex: new RegExp(`^${NOT_FOUND_PATTERN}/?$`),\r\n paramNames: [],\r\n component,\r\n layouts,\r\n pageFile: notFoundFile,\r\n layoutFiles,\r\n middlewares,\r\n loader,\r\n dynamic,\r\n generateStaticParams,\r\n };\r\n}\r\n\r\n/**\r\n * Loads the error route from the filesystem.\r\n * Looks for `_error.tsx` in the app root (Next.js style).\r\n *\r\n * @param appDir - Root directory of the app\r\n * @returns LoadedRoute for the error page, or null if not found\r\n */\r\nexport function loadErrorRouteFromFilesystem(\r\n appDir: string\r\n): LoadedRoute | null {\r\n const errorCandidates = [\r\n path.join(appDir, `${ERROR_FILE_PREFIX}.tsx`),\r\n path.join(appDir, `${ERROR_FILE_PREFIX}.ts`),\r\n path.join(appDir, `${ERROR_FILE_PREFIX}.jsx`),\r\n path.join(appDir, `${ERROR_FILE_PREFIX}.js`),\r\n ];\r\n\r\n let errorFile: string | null = null;\r\n for (const candidate of errorCandidates) {\r\n if (fs.existsSync(candidate)) {\r\n errorFile = candidate;\r\n break;\r\n }\r\n }\r\n\r\n if (!errorFile) {\r\n return null;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n const mod = require(errorFile);\r\n const component: PageComponent = mod.default;\r\n\r\n if (!component) {\r\n return null;\r\n }\r\n\r\n const { components: layouts, files: layoutFiles } = loadLayoutsForDir(\r\n appDir,\r\n appDir\r\n );\r\n\r\n const { middlewares, loader, dynamic, generateStaticParams } =\r\n loadLoaderForDir(appDir);\r\n\r\n return {\r\n pattern: ERROR_PATTERN,\r\n regex: new RegExp(`^${ERROR_PATTERN}/?$`),\r\n paramNames: [],\r\n component,\r\n layouts,\r\n pageFile: errorFile,\r\n layoutFiles,\r\n middlewares,\r\n loader,\r\n dynamic,\r\n generateStaticParams,\r\n };\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { WssRoute } from \"./index.types\";\r\nimport {\r\n extractApiMiddlewares,\r\n extractRouteRegex,\r\n extractWssHandlersFromModule,\r\n loadModuleSafely,\r\n} from \"./helpers/routes\";\r\n\r\nconst ROUTE_FILE_REGEX = /events\\.(ts|tsx|js|jsx)$/;\r\n\r\nexport function loadWssRoutes(appDir: string): WssRoute[] {\r\n const apiRoot = path.join(appDir, \"wss\");\r\n const routes: WssRoute[] = [];\r\n\r\n if (!fs.existsSync(apiRoot)) return routes;\r\n\r\n function walk(currentDir: string) {\r\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(currentDir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n walk(fullPath);\r\n continue;\r\n }\r\n\r\n // Only process route files\r\n if (!ROUTE_FILE_REGEX.test(entry.name)) continue;\r\n\r\n const relToApp = path.relative(appDir, fullPath).replace(/\\\\/g, \"/\");\r\n const withoutRoute = relToApp.replace(/\\/events\\.(ts|tsx|js|jsx)$/, \"\");\r\n const pattern = \"/\" + withoutRoute;\r\n\r\n const { regex, paramNames } = extractRouteRegex(pattern);\r\n\r\n const mod = loadModuleSafely(fullPath);\r\n if (!mod) {\r\n continue;\r\n }\r\n\r\n const handlers = extractWssHandlersFromModule(mod);\r\n const { global: globalMiddlewares, methodSpecific: methodMiddlewares } =\r\n extractApiMiddlewares(mod, []);\r\n\r\n routes.push({\r\n pattern,\r\n regex,\r\n paramNames,\r\n handlers,\r\n middlewares: globalMiddlewares,\r\n methodMiddlewares,\r\n filePath: fullPath,\r\n });\r\n }\r\n }\r\n\r\n walk(apiRoot);\r\n\r\n return routes;\r\n}\r\n\r\n","import { rspack, type Compiler } from \"@rspack/core\";\r\nimport { createClientConfig } from \"../config/client\";\r\nimport { copyStaticAssets, generateAssetManifest } from \"../utils\";\r\nimport path from \"path\";\r\nimport fs from \"fs\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\nexport interface ClientBundlerResult {\r\n outDir: string;\r\n waitForBuild?: () => Promise<void>;\r\n}\r\n\r\n/**\r\n * Starts the client bundler in watch mode for development.\r\n * \r\n * Automatically rebuilds when files change and copies static assets.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param mode - Build mode ('development' or 'production'), defaults to 'development'\r\n * @returns Output directory path\r\n * \r\n * @example\r\n * const { outDir } = startClientBundler('/path/to/project', 'development');\r\n * // Bundler is now watching for changes\r\n */\r\nexport function startClientBundler(\r\n projectRoot: string,\r\n mode: \"development\" | \"production\" = \"development\"\r\n): ClientBundlerResult {\r\n const { config, outDir } = createClientConfig(projectRoot, mode);\r\n\r\n copyStaticAssets(projectRoot, outDir);\r\n\r\n const compiler = rspack(config);\r\n \r\n // Track build state\r\n let isBuilding = false;\r\n let buildResolve: (() => void) | null = null;\r\n let buildPromise: Promise<void> | null = null;\r\n let lastBuildTime = Date.now();\r\n\r\n // Mark as building when compilation starts\r\n compiler.hooks.compile.tap(\"HotReload\", () => {\r\n isBuilding = true;\r\n // Create new promise for this build\r\n buildPromise = new Promise<void>((resolve) => {\r\n buildResolve = resolve;\r\n });\r\n });\r\n\r\n compiler.watch({}, (err, stats) => {\r\n if (err) {\r\n console.error(\"[framework][client] Rspack error:\", err);\r\n isBuilding = false;\r\n lastBuildTime = Date.now();\r\n // Resolve any waiting promises even on error\r\n if (buildResolve) {\r\n buildResolve();\r\n buildResolve = null;\r\n buildPromise = null;\r\n }\r\n return;\r\n }\r\n if (!stats) {\r\n isBuilding = false;\r\n lastBuildTime = Date.now();\r\n return;\r\n }\r\n\r\n if (stats.hasErrors()) {\r\n console.error(\r\n \"[framework][client] Build with errors:\\n\",\r\n stats.toString(\"errors-only\")\r\n );\r\n } else {\r\n console.log(\"[framework][client] ✓ Client bundle rebuilt successfully\");\r\n }\r\n \r\n isBuilding = false;\r\n lastBuildTime = Date.now();\r\n \r\n // Resolve waiting promise\r\n if (buildResolve) {\r\n buildResolve();\r\n buildResolve = null;\r\n buildPromise = null;\r\n }\r\n });\r\n\r\n return {\r\n outDir,\r\n waitForBuild: async () => {\r\n // If currently building, wait for it to finish\r\n if (isBuilding && buildPromise) {\r\n await buildPromise;\r\n // Give it a small delay to ensure files are written to disk\r\n await new Promise(resolve => setTimeout(resolve, 100));\r\n return;\r\n }\r\n \r\n // If not building, check if a build just finished recently\r\n // (within last 500ms) - this handles the case where the build\r\n // finished just before we checked\r\n const timeSinceLastBuild = Date.now() - lastBuildTime;\r\n if (timeSinceLastBuild < 500) {\r\n // Build just finished, wait a bit for files to be written\r\n await new Promise(resolve => setTimeout(resolve, 200));\r\n return;\r\n }\r\n \r\n // No build in progress and none recently finished, return immediately\r\n return Promise.resolve();\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Builds the client bundle for production.\r\n * \r\n * Creates an optimized production bundle and copies static assets.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Promise that resolves with output directory path\r\n * \r\n * @example\r\n * const { outDir } = await buildClientBundle('/path/to/project');\r\n * // Production bundle created at {BUILD_FOLDER_NAME}/client\r\n */\r\nexport function buildClientBundle(\r\n projectRoot: string\r\n): Promise<ClientBundlerResult> {\r\n const { config, outDir } = createClientConfig(projectRoot, \"production\");\r\n const compiler = rspack(config);\r\n\r\n return new Promise<ClientBundlerResult>((resolve, reject) => {\r\n compiler.run((err, stats) => {\r\n compiler.close(() => {});\r\n\r\n if (err) {\r\n console.error(\"[framework][client] Build error:\", err);\r\n return reject(err);\r\n }\r\n if (!stats) {\r\n const error = new Error(\"No stats from Rspack\");\r\n console.error(\"[framework][client] Build error:\", error);\r\n return reject(error);\r\n }\r\n if (stats.hasErrors()) {\r\n console.error(\r\n \"[framework][client] Build with errors:\\n\",\r\n stats.toString(\"errors-only\")\r\n );\r\n return reject(new Error(\"Client build failed\"));\r\n }\r\n\r\n copyStaticAssets(projectRoot, outDir);\r\n\r\n // Generate asset manifest with hashed filenames\r\n const assetManifest = generateAssetManifest(outDir);\r\n \r\n // Save asset manifest\r\n const manifestPath = path.join(projectRoot, BUILD_FOLDER_NAME, \"asset-manifest.json\");\r\n fs.writeFileSync(manifestPath, JSON.stringify(assetManifest, null, 2), \"utf-8\");\r\n\r\n resolve({ outDir });\r\n });\r\n });\r\n}\r\n\r\n","import path from \"path\";\r\nimport fs from \"fs\";\r\nimport { rspack, type Configuration } from \"@rspack/core\";\r\nimport { loadAliasesFromTsconfig } from \"../utils\";\r\nimport dotenv from 'dotenv';\r\nimport { BUILD_FOLDER_NAME, STATIC_PATH } from \"@constants/globals\";\r\n\r\n/**\r\n * Creates Rspack configuration for client bundle.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @param mode - Build mode ('development' or 'production')\r\n * @returns Rspack configuration and output directory\r\n *\r\n * @example\r\n * const { config, outDir } = createClientConfig('/path/to/project', 'production');\r\n */\r\nexport function createClientConfig(\r\n projectRoot: string,\r\n mode: \"development\" | \"production\"\r\n): { config: Configuration; outDir: string } {\r\n const buildDir = path.join(projectRoot, BUILD_FOLDER_NAME);\r\n const clientEntry = path.join(buildDir, \"boostrap.ts\");\r\n const outDir = path.join(buildDir, \"client\");\r\n\r\n dotenv.config({\r\n path: projectRoot,\r\n });\r\n\r\n const publicEnv: Record<string, string> = {};\r\n\r\n for (const [key, value] of Object.entries(process.env)) {\r\n if (key.startsWith(\"PUBLIC_\")) {\r\n publicEnv[`process.env.${key}`] = JSON.stringify(value ?? \"\");\r\n }\r\n }\r\n\r\n const config: Configuration = {\r\n mode,\r\n entry: {\r\n client: clientEntry,\r\n },\r\n output: {\r\n path: outDir,\r\n filename: mode === \"production\" ? \"client.[contenthash].js\" : \"client.js\", // Main entry\r\n chunkFilename: mode === \"production\" ? \"[name].[contenthash].js\" : \"[name].js\", // Code-split chunks (route-..., 0.js, etc.)\r\n publicPath: `${STATIC_PATH}/`,\r\n },\r\n context: projectRoot,\r\n resolve: {\r\n extensions: [\".tsx\", \".ts\", \".jsx\", \".js\"],\r\n alias: loadAliasesFromTsconfig(projectRoot),\r\n },\r\n module: {\r\n rules: [\r\n {\r\n test: /\\.[jt]sx?$/,\r\n loader: \"builtin:swc-loader\",\r\n options: {\r\n jsc: {\r\n parser: { syntax: \"typescript\", tsx: true },\r\n transform: {\r\n react: {\r\n runtime: \"automatic\",\r\n development: mode === \"development\",\r\n refresh: false,\r\n },\r\n },\r\n },\r\n },\r\n },\r\n {\r\n test: /\\.css$/,\r\n use: [\r\n rspack.CssExtractRspackPlugin.loader,\r\n \"css-loader\",\r\n \"postcss-loader\",\r\n ],\r\n },\r\n ],\r\n },\r\n plugins: [\r\n new rspack.DefinePlugin({\r\n \"process.env.NODE_ENV\": JSON.stringify(process.env.NODE_ENV),\r\n ...publicEnv,\r\n }),\r\n new rspack.CssExtractRspackPlugin({\r\n filename: mode === \"production\" ? \"client.[contenthash].css\" : \"client.css\",\r\n }),\r\n ],\r\n infrastructureLogging: {\r\n level: \"error\",\r\n },\r\n stats: \"minimal\",\r\n };\r\n\r\n return { config, outDir };\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\n\r\n/**\r\n * Ensures a directory exists, creating it recursively if needed.\r\n * \r\n * This is a convenience wrapper around `fs.mkdirSync` with `recursive: true`.\r\n * \r\n * @param dir - Directory path to ensure exists\r\n * \r\n * @example\r\n * ensureDir('/path/to/directory');\r\n * // Directory is created if it doesn't exist\r\n */\r\nexport function ensureDir(dir: string): void {\r\n fs.mkdirSync(dir, { recursive: true });\r\n}\r\n\r\n/**\r\n * Loads path aliases from tsconfig.json.\r\n * \r\n * Reads the tsconfig.json file and extracts path mappings from the `paths` option.\r\n * Falls back to a default `@app` alias if tsconfig.json is not found or invalid.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Record of alias keys to resolved paths\r\n * \r\n * @example\r\n * // tsconfig.json\r\n * // {\r\n * // \"compilerOptions\": {\r\n * // \"paths\": {\r\n * // \"@components/*\": [\"components/*\"]\r\n * // }\r\n * // }\r\n * // }\r\n * \r\n * loadAliasesFromTsconfig('/project')\r\n * // { '@components': '/project/components', '@app': '/project/app' }\r\n */\r\nexport function loadAliasesFromTsconfig(\r\n projectRoot: string\r\n): Record<string, string> {\r\n const tsconfigPath = path.join(projectRoot, \"tsconfig.json\");\r\n const aliases: Record<string, string> = {};\r\n\r\n if (!fs.existsSync(tsconfigPath)) {\r\n // Fallback: default @app alias\r\n aliases[\"@app\"] = path.resolve(projectRoot, \"app\");\r\n return aliases;\r\n }\r\n\r\n let tsconfig: any;\r\n try {\r\n tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, \"utf-8\"));\r\n } catch (err) {\r\n console.warn(\"[framework] Could not read tsconfig.json:\", err);\r\n aliases[\"@app\"] = path.resolve(projectRoot, \"app\");\r\n return aliases;\r\n }\r\n\r\n const compilerOptions = tsconfig.compilerOptions ?? {};\r\n const paths = compilerOptions.paths ?? {};\r\n const baseUrl = compilerOptions.baseUrl ?? \".\";\r\n\r\n for (const [aliasPattern, targets] of Object.entries(paths) as [\r\n string,\r\n string[]\r\n ][]) {\r\n if (!Array.isArray(targets) || targets.length === 0) continue;\r\n\r\n // aliasPattern like \"@components/*\" -> \"@components\"\r\n const aliasKey = aliasPattern.replace(/\\/\\*$/, \"\");\r\n const firstTarget = targets[0]; // \"components/*\"\r\n const targetPath = firstTarget.replace(/\\/\\*$/, \"\");\r\n\r\n const resolved = path.resolve(projectRoot, baseUrl, targetPath);\r\n aliases[aliasKey] = resolved;\r\n }\r\n\r\n // Fallback: ensure @app alias exists\r\n if (!aliases[\"@app\"]) {\r\n aliases[\"@app\"] = path.resolve(projectRoot, \"app\");\r\n }\r\n\r\n return aliases;\r\n}\r\n\r\n/**\r\n * Recursively copies a directory and all its contents.\r\n * \r\n * @param srcDir - Source directory to copy from\r\n * @param destDir - Destination directory to copy to\r\n */\r\nexport function copyDirRecursive(srcDir: string, destDir: string): void {\r\n if (!fs.existsSync(srcDir)) return;\r\n ensureDir(destDir);\r\n\r\n const entries = fs.readdirSync(srcDir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const srcPath = path.join(srcDir, entry.name);\r\n const destPath = path.join(destDir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n copyDirRecursive(srcPath, destPath);\r\n } else if (entry.isFile()) {\r\n fs.copyFileSync(srcPath, destPath);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Copies static assets to the output directory.\r\n * \r\n * Copies:\r\n * 1. `assets/` directory (if exists) → `outDir/assets/`\r\n * 2. Favicon files (`favicon.ico` or `favicon.png`) from `app/` or project root\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param outDir - Output directory to copy assets to\r\n * \r\n * @example\r\n * copyStaticAssets('/project', '/project/{BUILD_FOLDER_NAME}/client');\r\n * // Copies assets/ and favicon.* to {BUILD_FOLDER_NAME}/client/\r\n */\r\nexport function copyStaticAssets(projectRoot: string, outDir: string): void {\r\n // 1) Copy assets/ directory (if exists) → {BUILD_FOLDER_NAME}/client/assets/\r\n const assetsSrc = path.join(projectRoot, \"assets\");\r\n const assetsDest = path.join(outDir, \"assets\");\r\n copyDirRecursive(assetsSrc, assetsDest);\r\n\r\n // 2) Find and copy favicon from app/ or project root\r\n const appDir = path.join(projectRoot, \"app\");\r\n const candidates = [\"favicon.ico\", \"favicon.png\"];\r\n\r\n for (const name of candidates) {\r\n const fromApp = path.join(appDir, name);\r\n const fromRoot = path.join(projectRoot, name);\r\n\r\n let src: string | null = null;\r\n if (fs.existsSync(fromApp)) src = fromApp;\r\n else if (fs.existsSync(fromRoot)) src = fromRoot;\r\n\r\n if (src) {\r\n const dest = path.join(outDir, name); // Will be served as ${STATIC_PATH}/favicon.*\r\n ensureDir(path.dirname(dest));\r\n fs.copyFileSync(src, dest);\r\n break; // Use the first one found\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Asset manifest interface for tracking hashed filenames.\r\n */\r\nexport interface AssetManifest {\r\n client: {\r\n js: string; // e.g., \"client.abc123.js\"\r\n css: string; // e.g., \"client.def456.css\"\r\n };\r\n chunks: Record<string, string>; // chunk name -> hashed filename, e.g., \"route-root\" -> \"route-root.xyz789.js\"\r\n}\r\n\r\n/**\r\n * Generates an asset manifest by scanning the build output directory.\r\n * \r\n * Finds files with content hashes and maps them to their logical names.\r\n * \r\n * @param outDir - Output directory to scan\r\n * @returns Asset manifest with hashed filenames\r\n * \r\n * @example\r\n * const manifest = generateAssetManifest('/project/.loly/client');\r\n * // { client: { js: 'client.abc123.js', css: 'client.def456.css' }, chunks: {...} }\r\n */\r\nexport function generateAssetManifest(outDir: string): AssetManifest {\r\n const manifest: AssetManifest = {\r\n client: {\r\n js: \"client.js\",\r\n css: \"client.css\",\r\n },\r\n chunks: {},\r\n };\r\n\r\n if (!fs.existsSync(outDir)) {\r\n return manifest;\r\n }\r\n\r\n const files = fs.readdirSync(outDir);\r\n \r\n // Find client.js (with or without hash)\r\n const clientJsMatch = files.find((f) => /^client\\.[\\w-]+\\.js$/.test(f) || f === \"client.js\");\r\n if (clientJsMatch) {\r\n manifest.client.js = clientJsMatch;\r\n }\r\n\r\n // Find client.css (with or without hash)\r\n const clientCssMatch = files.find((f) => /^client\\.[\\w-]+\\.css$/.test(f) || f === \"client.css\");\r\n if (clientCssMatch) {\r\n manifest.client.css = clientCssMatch;\r\n }\r\n\r\n // Find all chunk files (route-*.js, 0.js, 1.js, etc. with or without hash)\r\n // Pattern: route-*.js or numeric chunks like 0.js, 1.js, etc.\r\n for (const file of files) {\r\n if (!file.endsWith(\".js\")) continue;\r\n \r\n // Skip the main client.js file\r\n if (file === manifest.client.js) continue;\r\n \r\n // Match route chunks: route-*.js or route-*.[hash].js\r\n const routeMatch = file.match(/^(route-[^.]+)(\\.[\\w-]+)?\\.js$/);\r\n if (routeMatch) {\r\n const chunkName = routeMatch[1]; // e.g., \"route-root\"\r\n manifest.chunks[chunkName] = file;\r\n continue;\r\n }\r\n \r\n // Match numeric chunks: 0.js, 1.js, etc. or 0.[hash].js\r\n const numericMatch = file.match(/^(\\d+)(\\.[\\w-]+)?\\.js$/);\r\n if (numericMatch) {\r\n const chunkName = numericMatch[1]; // e.g., \"0\"\r\n manifest.chunks[chunkName] = file;\r\n }\r\n }\r\n\r\n return manifest;\r\n}\r\n\r\n/**\r\n * Loads the asset manifest from the build directory.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Asset manifest or null if not found\r\n */\r\nexport function loadAssetManifest(projectRoot: string): AssetManifest | null {\r\n const { BUILD_FOLDER_NAME } = require(\"@constants/globals\");\r\n const manifestPath = path.join(projectRoot, BUILD_FOLDER_NAME, \"asset-manifest.json\");\r\n \r\n if (!fs.existsSync(manifestPath)) {\r\n return null;\r\n }\r\n\r\n try {\r\n const manifest: AssetManifest = JSON.parse(fs.readFileSync(manifestPath, \"utf-8\"));\r\n return manifest;\r\n } catch (err) {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Gets the client JS path with hash from the asset manifest.\r\n * Falls back to default path if manifest is not available.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Path to client JS file (e.g., \"/static/client.abc123.js\")\r\n */\r\nexport function getClientJsPath(projectRoot: string): string {\r\n const { STATIC_PATH } = require(\"@constants/globals\");\r\n const manifest = loadAssetManifest(projectRoot);\r\n const filename = manifest?.client.js || \"client.js\";\r\n return `${STATIC_PATH}/${filename}`;\r\n}\r\n\r\n/**\r\n * Gets the client CSS path with hash from the asset manifest.\r\n * Falls back to default path if manifest is not available.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Path to client CSS file (e.g., \"/static/client.def456.css\")\r\n */\r\nexport function getClientCssPath(projectRoot: string): string {\r\n const { STATIC_PATH } = require(\"@constants/globals\");\r\n const manifest = loadAssetManifest(projectRoot);\r\n const filename = manifest?.client.css || \"client.css\";\r\n return `${STATIC_PATH}/${filename}`;\r\n}","import path from \"path\";\r\nimport type { LoadedRoute } from \"@router/index\";\r\nimport { buildPathFromPattern } from \"./path\";\r\nimport { renderStaticRoute } from \"./renderer\";\r\nimport { ensureDir } from \"../utils\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\n/**\r\n * Builds static pages for routes marked with `dynamic: \"force-static\"`.\r\n * \r\n * For each static route:\r\n * 1. Calls `generateStaticParams()` to get all parameter combinations\r\n * 2. Renders each combination to HTML and data.json\r\n * 3. Writes files to `{BUILD_FOLDER_NAME}/ssg/{path}/index.html` and `data.json`\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param routes - Array of loaded routes\r\n * \r\n * @example\r\n * await buildStaticPages('/path/to/project', routes);\r\n *\r\n */\r\nexport async function buildStaticPages(\r\n projectRoot: string,\r\n routes: LoadedRoute[]\r\n): Promise<void> {\r\n const ssgOutDir = path.join(projectRoot, BUILD_FOLDER_NAME, \"ssg\");\r\n ensureDir(ssgOutDir);\r\n\r\n for (const route of routes) {\r\n // Only process routes marked as static\r\n if (route.dynamic !== \"force-static\") continue;\r\n\r\n let allParams: Array<Record<string, string>> = [];\r\n\r\n if (route.paramNames.length === 0) {\r\n allParams = [{}];\r\n } else {\r\n if (!route.generateStaticParams) {\r\n console.warn(\r\n `[framework][ssg] Route ${route.pattern} is marked as force-static but has no generateStaticParams function. Skipping.`\r\n );\r\n continue;\r\n }\r\n \r\n try {\r\n console.log(`[framework][ssg] Generating static params for route: ${route.pattern}`);\r\n \r\n // Add timeout to detect hanging\r\n let timeoutId: NodeJS.Timeout | null = null;\r\n const timeoutPromise = new Promise((_, reject) => {\r\n timeoutId = setTimeout(() => {\r\n reject(new Error(`generateStaticParams for route ${route.pattern} timed out after 30 seconds`));\r\n }, 30000);\r\n });\r\n \r\n const sp = await Promise.race([\r\n route.generateStaticParams(),\r\n timeoutPromise\r\n ]) as Array<Record<string, string>>;\r\n \r\n // Clear timeout if it's still pending\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n }\r\n \r\n allParams = sp;\r\n console.log(`[framework][ssg] Generated ${sp.length} static params for route: ${route.pattern}`);\r\n } catch (error) {\r\n console.error(\r\n `[framework][ssg] Error generating static params for route ${route.pattern}:`,\r\n error\r\n );\r\n throw error;\r\n }\r\n }\r\n for (const params of allParams) {\r\n const urlPath = buildPathFromPattern(route.pattern, params);\r\n await renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params);\r\n }\r\n }\r\n \r\n console.log(`[framework][ssg] Finished building all static pages`);\r\n}\r\n\r\n","import path from \"path\";\r\n\r\n/**\r\n * Builds a URL path from a route pattern and parameters.\r\n * \r\n * Replaces dynamic segments ([slug], [...path]) with actual parameter values.\r\n * \r\n * @param pattern - Route pattern (e.g., '/blog/[slug]', '/post/[...path]')\r\n * @param params - Parameter values to substitute\r\n * @returns Actual URL path\r\n * \r\n * @example\r\n * buildPathFromPattern('/blog/[slug]', { slug: 'my-post' })\r\n * // '/blog/my-post'\r\n * \r\n * buildPathFromPattern('/post/[...path]', { path: 'a/b/c' })\r\n * // '/post/a/b/c'\r\n * \r\n * @throws Error if required parameters are missing\r\n */\r\nexport function buildPathFromPattern(\r\n pattern: string,\r\n params: Record<string, string>\r\n): string {\r\n const segments = pattern.split(\"/\").filter(Boolean);\r\n const parts: string[] = [];\r\n\r\n for (const seg of segments) {\r\n // Catch-all parameter: [...path]\r\n if (seg.startsWith(\"[...\") && seg.endsWith(\"]\")) {\r\n const name = seg.slice(4, -1);\r\n const value = params[name];\r\n if (!value) {\r\n throw new Error(\r\n `Missing parameter \"${name}\" for catch-all pattern \"${pattern}\"`\r\n );\r\n }\r\n parts.push(value);\r\n }\r\n // Normal parameter: [slug]\r\n else if (seg.startsWith(\"[\") && seg.endsWith(\"]\")) {\r\n const name = seg.slice(1, -1);\r\n const value = params[name];\r\n if (!value) {\r\n throw new Error(`Missing parameter \"${name}\" for pattern \"${pattern}\"`);\r\n }\r\n parts.push(encodeURIComponent(value));\r\n }\r\n // Static segment\r\n else {\r\n parts.push(seg);\r\n }\r\n }\r\n\r\n return \"/\" + parts.join(\"/\");\r\n}\r\n\r\n/**\r\n * Converts a URL path to an output directory path.\r\n * \r\n * @param baseDir - Base output directory\r\n * @param urlPath - URL path (e.g., '/blog/my-post' or '/')\r\n * @returns Directory path relative to baseDir\r\n * \r\n * @example\r\n * pathToOutDir('/output/ssg', '/blog/my-post')\r\n * // '/output/ssg/blog/my-post'\r\n * \r\n * pathToOutDir('/output/ssg', '/')\r\n * // '/output/ssg'\r\n */\r\nexport function pathToOutDir(baseDir: string, urlPath: string): string {\r\n const clean = urlPath === \"/\" ? \"\" : urlPath.replace(/^\\/+/, \"\");\r\n return path.join(baseDir, clean);\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { renderToString } from \"react-dom/server\";\r\nimport { loadChunksFromManifest, type LoadedRoute, type LoaderResult, type ServerContext } from \"@router/index\";\r\nimport {\r\n buildAppTree,\r\n buildInitialData,\r\n createDocumentTree,\r\n} from \"@rendering/index\";\r\nimport { pathToOutDir } from \"./path\";\r\nimport { ensureDir, getClientJsPath, getClientCssPath, loadAssetManifest } from \"../utils\";\r\nimport { STATIC_PATH } from \"@constants/globals\";\r\n\r\n/**\r\n * Renders a static page for SSG.\r\n * \r\n * Executes middlewares and loader, then renders the React component tree\r\n * to HTML. Writes both the HTML file and the data JSON file.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param ssgOutDir - SSG output directory\r\n * @param route - Route definition\r\n * @param urlPath - URL path for this page\r\n * @param params - Route parameters\r\n * \r\n * @example\r\n * await renderStaticRoute(\r\n * '/project',\r\n * '/project/{BUILD_FOLDER_NAME}/ssg',\r\n * route,\r\n * '/blog/my-post',\r\n * { slug: 'my-post' }\r\n * );\r\n */\r\nexport async function renderStaticRoute(\r\n projectRoot: string,\r\n ssgOutDir: string,\r\n route: LoadedRoute,\r\n urlPath: string,\r\n params: Record<string, string>\r\n): Promise<void> {\r\n const routeChunks = loadChunksFromManifest(projectRoot);\r\n const assetManifest = loadAssetManifest(projectRoot);\r\n const clientJsPath = getClientJsPath(projectRoot);\r\n const clientCssPath = getClientCssPath(projectRoot);\r\n \r\n // Get chunk href with hash if available\r\n const chunkName = routeChunks[route.pattern];\r\n let chunkHref: string | null = null;\r\n if (chunkName != null) {\r\n if (assetManifest && assetManifest.chunks[chunkName]) {\r\n chunkHref = `${STATIC_PATH}/${assetManifest.chunks[chunkName]}`;\r\n } else {\r\n chunkHref = `${STATIC_PATH}/${chunkName}.js`;\r\n }\r\n }\r\n\r\n // Mock request/response objects for SSG\r\n const req: any = {\r\n method: \"GET\",\r\n headers: {},\r\n query: {},\r\n path: urlPath,\r\n };\r\n\r\n const res: any = {\r\n statusCode: 200,\r\n headers: {} as Record<string, string>,\r\n setHeader(name: string, value: string) {\r\n this.headers[name.toLowerCase()] = value;\r\n },\r\n get headersSent() {\r\n return false;\r\n },\r\n };\r\n\r\n const ctx: ServerContext = {\r\n req,\r\n res,\r\n params,\r\n pathname: urlPath,\r\n locals: {},\r\n };\r\n\r\n // Execute middlewares\r\n for (const mw of route.middlewares) {\r\n await Promise.resolve(\r\n mw(ctx, async () => {\r\n /* no-op */\r\n })\r\n );\r\n }\r\n\r\n // Execute loader\r\n let loaderResult: LoaderResult = { props: {} };\r\n\r\n if (route.loader) {\r\n loaderResult = await route.loader(ctx);\r\n }\r\n\r\n if (loaderResult.redirect || loaderResult.notFound) {\r\n return;\r\n }\r\n\r\n // Build React component tree\r\n const initialData = buildInitialData(urlPath, params, loaderResult);\r\n const appTree = buildAppTree(route, params, initialData.props);\r\n const documentTree = createDocumentTree({\r\n appTree,\r\n initialData,\r\n meta: loaderResult.metadata,\r\n titleFallback: \"My Framework Dev\",\r\n descriptionFallback: \"Static page generated by @lolyjs/core.\",\r\n chunkHref,\r\n clientJsPath,\r\n clientCssPath,\r\n });\r\n\r\n // Render to HTML (hydratable, same as SSR)\r\n const html = \"<!DOCTYPE html>\" + renderToString(documentTree);\r\n\r\n // Write files\r\n const dir = pathToOutDir(ssgOutDir, urlPath);\r\n ensureDir(dir);\r\n\r\n const htmlFile = path.join(dir, \"index.html\");\r\n const dataFile = path.join(dir, \"data.json\");\r\n\r\n fs.writeFileSync(htmlFile, html, \"utf-8\");\r\n fs.writeFileSync(dataFile, JSON.stringify(initialData, null, 2), \"utf-8\");\r\n}\r\n\r\n","import React, { ReactElement } from \"react\";\r\nimport type { LoaderResult, PageComponent, LoadedRoute } from \"@router/index\";\r\nimport { InitialData } from \"../index.types\";\r\nimport {\r\n WINDOW_DATA_KEY,\r\n APP_CONTAINER_ID,\r\n FAVICON_PATH,\r\n} from \"@constants/globals\";\r\n\r\n/**\r\n * Builds the app tree (Page + layouts) in the same way for SSR and SSG.\r\n *\r\n * @param route - Route definition\r\n * @param params - Route parameters\r\n * @param props - Props from loader\r\n * @returns React element tree\r\n */\r\nexport function buildAppTree(\r\n route: LoadedRoute,\r\n params: Record<string, string>,\r\n props: any\r\n): ReactElement {\r\n const Page = route.component as PageComponent;\r\n\r\n let appTree: ReactElement = React.createElement(Page, {\r\n params,\r\n ...props,\r\n });\r\n\r\n const layoutChain = route.layouts.slice().reverse();\r\n\r\n for (const Layout of layoutChain) {\r\n appTree = React.createElement(Layout as PageComponent, {\r\n params,\r\n ...props,\r\n children: appTree,\r\n });\r\n }\r\n\r\n return appTree;\r\n}\r\n\r\n/**\r\n * Builds the complete HTML document tree. Used by both SSR and SSG.\r\n *\r\n * @param options - Document tree options\r\n * @returns React element representing the HTML document\r\n */\r\nexport function createDocumentTree(options: {\r\n appTree: ReactElement;\r\n initialData: InitialData;\r\n meta: LoaderResult[\"metadata\"];\r\n titleFallback?: string;\r\n descriptionFallback?: string;\r\n chunkHref?: string | null;\r\n theme?: string;\r\n clientJsPath?: string;\r\n clientCssPath?: string;\r\n nonce?: string;\r\n}): ReactElement {\r\n const {\r\n appTree,\r\n initialData,\r\n meta,\r\n titleFallback,\r\n descriptionFallback,\r\n chunkHref,\r\n theme,\r\n clientJsPath = \"/static/client.js\",\r\n clientCssPath = \"/static/client.css\",\r\n nonce,\r\n } = options;\r\n\r\n const metaObj = meta ?? {};\r\n const title = (metaObj as any).title ?? titleFallback ?? \"My Framework Dev\";\r\n const lang = (metaObj as any).lang ?? \"en\";\r\n const description =\r\n (metaObj as any).description ??\r\n descriptionFallback ??\r\n \"Demo Loly framework\";\r\n\r\n const extraMetaTags: ReactElement[] = [];\r\n\r\n if (description) {\r\n extraMetaTags.push(\r\n React.createElement(\"meta\", {\r\n name: \"description\",\r\n content: description,\r\n })\r\n );\r\n }\r\n\r\n if (Array.isArray((metaObj as any).metaTags)) {\r\n for (const tag of (metaObj as any).metaTags) {\r\n extraMetaTags.push(\r\n React.createElement(\"meta\", {\r\n name: tag.name,\r\n property: tag.property,\r\n content: tag.content,\r\n })\r\n );\r\n }\r\n }\r\n\r\n const serialized = JSON.stringify({\r\n ...initialData,\r\n theme,\r\n });\r\n\r\n const documentTree = React.createElement(\r\n \"html\",\r\n { lang },\r\n React.createElement(\r\n \"head\",\r\n null,\r\n React.createElement(\"meta\", { charSet: \"utf-8\" }),\r\n React.createElement(\"title\", null, title),\r\n React.createElement(\"meta\", {\r\n name: \"viewport\",\r\n content: \"width=device-width, initial-scale=1\",\r\n }),\r\n ...extraMetaTags,\r\n chunkHref &&\r\n React.createElement(\"link\", {\r\n rel: \"modulepreload\",\r\n href: chunkHref,\r\n as: \"script\",\r\n }),\r\n React.createElement(\"link\", {\r\n rel: \"icon\",\r\n href: FAVICON_PATH,\r\n type: \"image/png\",\r\n }),\r\n React.createElement(\"link\", {\r\n rel: \"stylesheet\",\r\n href: clientCssPath,\r\n }),\r\n React.createElement(\"script\", {\r\n src: clientJsPath,\r\n defer: true,\r\n })\r\n ),\r\n React.createElement(\r\n \"body\",\r\n { \r\n style: { margin: 0 }, \r\n className: [initialData.className, theme].filter(Boolean).join(\" \"),\r\n suppressHydrationWarning: true // Allow theme class to differ between server and client initially\r\n },\r\n React.createElement(\"div\", { id: APP_CONTAINER_ID }, appTree)\r\n ),\r\n React.createElement(\"script\", {\r\n nonce: nonce,\r\n dangerouslySetInnerHTML: {\r\n __html: `window.${WINDOW_DATA_KEY} = ${serialized};`,\r\n },\r\n })\r\n );\r\n\r\n return documentTree;\r\n}\r\n","import { InitialData } from \"../index.types\";\nimport type { LoaderResult } from \"@router/index\";\n\n/**\n * Builds InitialData in a consistent way.\n *\n * @param urlPath - URL path\n * @param params - Route parameters\n * @param loaderResult - Loader result\n * @returns Initial data object\n */\nexport function buildInitialData(\n urlPath: string,\n params: Record<string, string>,\n loaderResult: LoaderResult,\n): InitialData {\n // Include theme in props so it's available to layouts and pages\n const props = {\n ...(loaderResult.props ?? {}),\n ...(loaderResult.theme ? { theme: loaderResult.theme } : {}),\n };\n \n return {\n pathname: urlPath,\n params,\n props,\n metadata: loaderResult.metadata ?? null,\n className: loaderResult.className ?? \"\",\n error: false,\n notFound: false,\n };\n}\n","import path from \"path\";\r\nimport fs from \"fs\";\r\nimport esbuild from \"esbuild\";\r\nimport { ensureDir } from \"../utils\";\r\nimport { INIT_FILE_NAME } from \"@server/init\";\r\nimport { CONFIG_FILE_NAME } from \"@server/config\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\nconst SERVER_FILES = [INIT_FILE_NAME, CONFIG_FILE_NAME];\r\n\r\nexport interface BuildServerResult {\r\n outDir: string;\r\n}\r\n\r\nfunction collectAppSources(appDir: string): string[] {\r\n const entries: string[] = [];\r\n\r\n function walk(dir: string) {\r\n const items = fs.readdirSync(dir, { withFileTypes: true });\r\n\r\n for (const item of items) {\r\n const full = path.join(dir, item.name);\r\n\r\n if (item.isDirectory()) {\r\n walk(full);\r\n continue;\r\n }\r\n\r\n if (item.isFile()) {\r\n if (full.endsWith(\".d.ts\")) continue;\r\n\r\n if (\r\n full.endsWith(\".ts\") ||\r\n full.endsWith(\".tsx\") ||\r\n full.endsWith(\".js\") ||\r\n full.endsWith(\".jsx\")\r\n ) {\r\n entries.push(full);\r\n }\r\n }\r\n }\r\n }\r\n\r\n walk(appDir);\r\n return entries;\r\n}\r\n\r\n/**\r\n * Builds the server application.\r\n *\r\n * Compiles app directory with bundling enabled, and server files (init/config)\r\n * without bundling for direct require access.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @param appDir - App directory to build\r\n * @returns Promise resolving to build result with output directory\r\n */\r\nexport async function buildServerApp(\r\n projectRoot: string,\r\n appDir: string\r\n): Promise<BuildServerResult> {\r\n const outDir = path.join(projectRoot, BUILD_FOLDER_NAME, \"server\");\r\n\r\n const entryPoints = collectAppSources(appDir);\r\n ensureDir(outDir);\r\n\r\n if (entryPoints.length === 0) {\r\n return { outDir };\r\n }\r\n\r\n await esbuild.build({\r\n entryPoints,\r\n outdir: outDir,\r\n outbase: appDir,\r\n platform: \"node\",\r\n format: \"cjs\",\r\n target: \"node18\",\r\n jsx: \"automatic\",\r\n sourcemap: true,\r\n bundle: true,\r\n splitting: false,\r\n logLevel: \"info\",\r\n tsconfig: path.join(projectRoot, \"tsconfig.json\"),\r\n packages: \"external\",\r\n });\r\n\r\n for (const fileName of SERVER_FILES) {\r\n const initTS = path.join(projectRoot, `${fileName}.ts`);\r\n const initJS = path.join(outDir, `${fileName}.js`);\r\n\r\n if (fs.existsSync(initTS)) {\r\n await esbuild.build({\r\n entryPoints: [initTS],\r\n outfile: initJS,\r\n platform: \"node\",\r\n format: \"cjs\",\r\n target: \"node18\",\r\n jsx: \"automatic\",\r\n sourcemap: true,\r\n bundle: false,\r\n logLevel: \"info\",\r\n tsconfig: path.join(projectRoot, \"tsconfig.json\"),\r\n });\r\n }\r\n }\r\n\r\n return { outDir };\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\nexport const getServerFile = async (projectRoot: string, fileName: string) => {\r\n const fileTS = path.join(projectRoot, `${fileName}.ts`);\r\n const fileJS = path.join(projectRoot, BUILD_FOLDER_NAME, \"server\", `${fileName}.js`);\r\n\r\n const isDev = process.env.NODE_ENV === \"development\";\r\n let mod: any = null;\r\n\r\n if (isDev) {\r\n if (!fs.existsSync(fileTS)) {\r\n return null;\r\n }\r\n\r\n require(\"tsx/cjs\");\r\n mod = require(fileTS);\r\n } else {\r\n if (!fs.existsSync(fileJS)) {\r\n return null;\r\n }\r\n\r\n mod = require(fileJS);\r\n }\r\n\r\n return mod;\r\n};\r\n","import http from \"http\";\r\nimport { getServerFile } from \"./utils/server-dir\";\r\n\r\nexport const INIT_FILE_NAME = 'init.server';\r\n\r\nexport interface InitServerData {\r\n server: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;\r\n}\r\n\r\nexport async function runInitIfExists(\r\n projectRoot: string,\r\n serverData: InitServerData\r\n): Promise<Record<string, any>> {\r\n let mod: any = await getServerFile(projectRoot, INIT_FILE_NAME);\r\n\r\n if (typeof mod?.init === \"function\") {\r\n const serverContext: any = { ...serverData };\r\n await mod.init({ serverContext });\r\n\r\n return serverContext;\r\n }\r\n\r\n return {};\r\n}\r\n","import { getServerFile } from \"./utils/server-dir\";\r\n\r\nexport const CONFIG_FILE_NAME = \"loly.config\";\r\n\r\nexport interface ServerConfig {\r\n bodyLimit?: string;\r\n corsOrigin?: string | string[] | boolean | ((origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) => void);\r\n rateLimit?: {\r\n windowMs?: number;\r\n max?: number;\r\n apiMax?: number;\r\n strictMax?: number;\r\n // Auto-apply strict rate limiting to routes matching these patterns\r\n strictPatterns?: string[];\r\n };\r\n security?: {\r\n contentSecurityPolicy?: boolean | Record<string, any>;\r\n hsts?: boolean | { maxAge?: number; includeSubDomains?: boolean };\r\n };\r\n}\r\n\r\nconst DEFAULT_CONFIG: ServerConfig = {\r\n bodyLimit: '1mb',\r\n corsOrigin: process.env.CORS_ORIGIN \r\n ? (process.env.CORS_ORIGIN.includes(',') \r\n ? process.env.CORS_ORIGIN.split(',').map(s => s.trim())\r\n : process.env.CORS_ORIGIN)\r\n : (process.env.NODE_ENV === 'production' ? [] : true),\r\n rateLimit: {\r\n windowMs: 15 * 60 * 1000, // 15 minutes\r\n max: 100, // General requests\r\n apiMax: 100, // API requests\r\n strictMax: 5, // Strict endpoints (auth, etc.)\r\n // Auto-apply strict rate limiting to these route patterns\r\n strictPatterns: [\r\n '/api/auth/**',\r\n '/api/login/**',\r\n '/api/register/**',\r\n '/api/password/**',\r\n '/api/reset/**',\r\n '/api/verify/**',\r\n ],\r\n },\r\n security: {\r\n contentSecurityPolicy: {\r\n directives: {\r\n defaultSrc: [\"'self'\"],\r\n styleSrc: [\"'self'\", \"'unsafe-inline'\"],\r\n scriptSrc: [\"'self'\", \"'unsafe-inline'\", \"'unsafe-eval'\"], // Needed for dev\r\n imgSrc: [\"'self'\", \"data:\", \"https:\"],\r\n connectSrc: [\"'self'\"],\r\n fontSrc: [\"'self'\", \"data:\"],\r\n objectSrc: [\"'none'\"],\r\n mediaSrc: [\"'self'\"],\r\n frameSrc: [\"'none'\"],\r\n },\r\n },\r\n hsts: {\r\n maxAge: 31536000, // 1 year\r\n includeSubDomains: true,\r\n },\r\n },\r\n}\r\n\r\nexport async function getServerConfig(\r\n projectRoot: string,\r\n): Promise<ServerConfig> {\r\n let mod: any = await getServerFile(projectRoot, CONFIG_FILE_NAME);\r\n\r\n if (typeof mod?.config === \"function\") {\r\n const options = mod?.config(process.env.NODE_ENV) as ServerConfig;\r\n\r\n // Deep merge for nested objects\r\n const merged: ServerConfig = {\r\n ...DEFAULT_CONFIG,\r\n ...options,\r\n rateLimit: {\r\n ...DEFAULT_CONFIG.rateLimit,\r\n ...options.rateLimit,\r\n },\r\n security: {\r\n ...DEFAULT_CONFIG.security,\r\n ...options.security,\r\n },\r\n };\r\n\r\n return merged;\r\n }\r\n\r\n return DEFAULT_CONFIG;\r\n}\r\n","import path from \"path\";\r\nimport {\r\n loadApiRoutes,\r\n LoadedRoute,\r\n loadRoutes,\r\n writeClientBoostrapManifest,\r\n writeClientRoutesManifest,\r\n writeRoutesManifest,\r\n loadNotFoundRouteFromFilesystem,\r\n loadErrorRouteFromFilesystem,\r\n} from \"@router/index\";\r\nimport { buildClientBundle } from \"./bundler/client\";\r\nimport { buildStaticPages } from \"./ssg\";\r\nimport { buildServerApp } from \"./bundler/server\";\r\nimport { NOT_FOUND_PATTERN } from \"@constants/globals\";\r\nimport { loadConfig, getAppDir, type FrameworkConfig } from \"@src/config\";\r\nimport { loadWssRoutes } from \"@router/loader-wss\";\r\n\r\nexport interface BuildAppOptions {\r\n rootDir?: string;\r\n appDir?: string;\r\n config?: FrameworkConfig;\r\n}\r\n\r\nexport async function buildApp(options: BuildAppOptions = {}): Promise<void> {\r\n const projectRoot = options.rootDir ?? process.cwd();\r\n const config = options.config ?? loadConfig(projectRoot);\r\n const appDir = options.appDir ?? getAppDir(projectRoot, config);\r\n\r\n process.env.LOLY_BUILD = \"1\";\r\n\r\n const routes = loadRoutes(appDir);\r\n const apiRoutes = loadApiRoutes(appDir);\r\n const wssRoutes = loadWssRoutes(appDir);\r\n\r\n const { outDir: serverOutDir } = await buildServerApp(projectRoot, appDir);\r\n\r\n // Load special error pages (_not-found.tsx, _error.tsx)\r\n const notFoundRoute = loadNotFoundRouteFromFilesystem(appDir);\r\n const errorRoute = loadErrorRouteFromFilesystem(appDir);\r\n\r\n if (!notFoundRoute) {\r\n console.warn(\r\n `[framework][build] No not-found route found. Consider creating ${config.directories.app}/${config.conventions.notFound}.tsx`\r\n );\r\n }\r\n\r\n // Create a minimal not-found route if none exists\r\n const fallbackNotFound: LoadedRoute = notFoundRoute || {\r\n pattern: NOT_FOUND_PATTERN,\r\n regex: new RegExp(`^${NOT_FOUND_PATTERN}/?$`),\r\n paramNames: [],\r\n component: () => null,\r\n layouts: [],\r\n pageFile: \"\",\r\n layoutFiles: [],\r\n middlewares: [],\r\n loader: null,\r\n dynamic: \"force-static\",\r\n generateStaticParams: null,\r\n };\r\n\r\n writeRoutesManifest({\r\n routes,\r\n apiRoutes,\r\n wssRoutes,\r\n notFoundRoute: fallbackNotFound,\r\n errorRoute,\r\n projectRoot,\r\n serverOutDir,\r\n appDir,\r\n });\r\n\r\n writeClientBoostrapManifest(projectRoot);\r\n\r\n writeClientRoutesManifest(routes, projectRoot);\r\n\r\n await buildClientBundle(projectRoot);\r\n\r\n await buildStaticPages(projectRoot, routes);\r\n\r\n delete process.env.LOLY_BUILD;\r\n\r\n console.log(`[framework][build] Build completed successfully`);\r\n}\r\n\r\nexport { startClientBundler, buildClientBundle } from \"./bundler/client\";\r\nexport { buildServerApp } from \"./bundler/server\";\r\nexport { buildStaticPages } from \"./ssg\";\r\n","import path from \"path\";\r\nimport fs from \"fs\";\r\nimport { BUILD_FOLDER_NAME } from \"../constants/globals\";\r\n\r\n/**\r\n * Framework configuration interface.\r\n * \r\n * Allows customization of framework behavior without code changes.\r\n */\r\nexport interface FrameworkConfig {\r\n // Directory structure\r\n directories: {\r\n app: string; // Default: 'app'\r\n build: string; // Default: '.loly'\r\n static: string; // Default: 'public'\r\n };\r\n \r\n // File naming conventions\r\n conventions: {\r\n page: string; // Default: 'page'\r\n layout: string; // Default: 'layout'\r\n notFound: string; // Default: '_not-found'\r\n error: string; // Default: '_error'\r\n api: string; // Default: 'route'\r\n };\r\n \r\n // Routing\r\n routing: {\r\n trailingSlash: 'always' | 'never' | 'ignore';\r\n caseSensitive: boolean;\r\n basePath: string; // Default: ''\r\n };\r\n \r\n // Build\r\n build: {\r\n clientBundler: 'rspack' | 'webpack' | 'vite';\r\n serverBundler: 'esbuild' | 'tsup' | 'swc';\r\n outputFormat: 'cjs' | 'esm';\r\n };\r\n \r\n // Server\r\n server: {\r\n adapter: 'express' | 'fastify' | 'koa';\r\n port: number;\r\n host: string;\r\n };\r\n \r\n // Rendering\r\n rendering: {\r\n framework: 'react' | 'preact' | 'vue' | 'svelte';\r\n streaming: boolean;\r\n ssr: boolean;\r\n ssg: boolean;\r\n };\r\n \r\n // Plugins (to be implemented in Phase 2)\r\n plugins?: any[];\r\n}\r\n\r\n/**\r\n * Default framework configuration.\r\n */\r\nexport const DEFAULT_CONFIG: FrameworkConfig = {\r\n directories: {\r\n app: 'app',\r\n build: BUILD_FOLDER_NAME,\r\n static: 'public',\r\n },\r\n conventions: {\r\n page: 'page',\r\n layout: 'layout',\r\n notFound: '_not-found',\r\n error: '_error',\r\n api: 'route',\r\n },\r\n routing: {\r\n trailingSlash: 'ignore',\r\n caseSensitive: false,\r\n basePath: '',\r\n },\r\n build: {\r\n clientBundler: 'rspack',\r\n serverBundler: 'esbuild',\r\n outputFormat: 'cjs',\r\n },\r\n server: {\r\n adapter: 'express',\r\n port: 3000,\r\n host: 'localhost',\r\n },\r\n rendering: {\r\n framework: 'react',\r\n streaming: true,\r\n ssr: true,\r\n ssg: true,\r\n },\r\n plugins: [],\r\n};\r\n\r\n/**\r\n * Deep merge utility for configuration objects.\r\n */\r\nfunction deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {\r\n const result = { ...target };\r\n \r\n for (const key in source) {\r\n const sourceValue = source[key];\r\n if (sourceValue && typeof sourceValue === 'object' && !Array.isArray(sourceValue)) {\r\n const targetValue = result[key];\r\n if (targetValue && typeof targetValue === 'object' && !Array.isArray(targetValue)) {\r\n result[key] = deepMerge(targetValue, sourceValue as any);\r\n } else {\r\n result[key] = sourceValue as T[Extract<keyof T, string>];\r\n }\r\n } else if (sourceValue !== undefined) {\r\n result[key] = sourceValue as T[Extract<keyof T, string>];\r\n }\r\n }\r\n \r\n return result;\r\n}\r\n\r\n/**\r\n * Loads framework configuration from project root.\r\n * \r\n * Looks for configuration in the following order:\r\n * 1. loly.config.ts (TypeScript)\r\n * 2. loly.config.js (JavaScript)\r\n * 3. loly.config.json (JSON)\r\n * \r\n * Merges user config with defaults and validates.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Framework configuration\r\n */\r\nexport function loadConfig(projectRoot: string): FrameworkConfig {\r\n const configFiles = [\r\n path.join(projectRoot, 'loly.config.ts'),\r\n path.join(projectRoot, 'loly.config.js'),\r\n path.join(projectRoot, 'loly.config.json'),\r\n ];\r\n\r\n let userConfig: Partial<FrameworkConfig> = {};\r\n\r\n // Try to load config file\r\n for (const configFile of configFiles) {\r\n if (fs.existsSync(configFile)) {\r\n try {\r\n if (configFile.endsWith('.json')) {\r\n // Load JSON config\r\n const content = fs.readFileSync(configFile, 'utf-8');\r\n userConfig = JSON.parse(content);\r\n } else {\r\n // Load TS/JS config (requires require/import)\r\n // In production, these should be compiled\r\n // For now, we'll use require with tsx in dev\r\n if (process.env.NODE_ENV === 'development') {\r\n require('tsx/cjs');\r\n }\r\n const mod = require(configFile);\r\n userConfig = typeof mod.default === 'function' \r\n ? mod.default(process.env.NODE_ENV)\r\n : (mod.default || mod.config || mod);\r\n }\r\n break;\r\n } catch (error) {\r\n console.warn(`[framework] Failed to load config from ${configFile}:`, error);\r\n }\r\n }\r\n }\r\n\r\n // Merge with defaults\r\n const config = deepMerge(DEFAULT_CONFIG, userConfig);\r\n\r\n // Validate critical paths\r\n const appDir = path.join(projectRoot, config.directories.app);\r\n if (!fs.existsSync(appDir) && process.env.NODE_ENV !== 'test') {\r\n console.warn(`[framework] App directory not found: ${appDir}`);\r\n }\r\n\r\n return config;\r\n}\r\n\r\n/**\r\n * Gets the resolved app directory path.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param config - Framework configuration\r\n * @returns Resolved app directory path\r\n */\r\nexport function getAppDir(projectRoot: string, config: FrameworkConfig): string {\r\n return path.resolve(projectRoot, config.directories.app);\r\n}\r\n\r\n/**\r\n * Gets the resolved build directory path.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param config - Framework configuration\r\n * @returns Resolved build directory path\r\n */\r\nexport function getBuildDir(projectRoot: string, config: FrameworkConfig): string {\r\n return path.join(projectRoot, config.directories.build);\r\n}\r\n\r\n/**\r\n * Gets the resolved static directory path.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param config - Framework configuration\r\n * @returns Resolved static directory path\r\n */\r\nexport function getStaticDir(projectRoot: string, config: FrameworkConfig): string {\r\n return path.resolve(projectRoot, config.directories.static);\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { runInitIfExists } from \"@server/init\";\r\nimport { setupServer, setupRoutes, setupWssEvents } from \"@server/index\";\r\nimport { setupApplication } from \"@server/application\";\r\nimport { FilesystemRouteLoader, ManifestRouteLoader } from \"@router/index\";\r\nimport {\r\n loadConfig,\r\n getAppDir,\r\n getBuildDir,\r\n type FrameworkConfig,\r\n} from \"./config\";\r\nimport { createModuleLogger } from \"@logger/index\";\r\nimport dotenv from \"dotenv\";\r\n\r\ndotenv.config();\r\n\r\nconst logger = createModuleLogger(\"server\");\r\n\r\nexport interface StartServerOptions {\r\n port?: number;\r\n rootDir?: string;\r\n appDir?: string;\r\n isDev?: boolean;\r\n config?: FrameworkConfig;\r\n}\r\n\r\n/**\r\n * Unified server startup function.\r\n * Handles both development and production modes.\r\n *\r\n * @param options - Server startup options\r\n */\r\nexport async function startServer(options: StartServerOptions = {}) {\r\n const isDev = options.isDev ?? process.env.NODE_ENV === \"development\";\r\n const projectRoot = options.rootDir ?? process.cwd();\r\n\r\n // Load configuration\r\n const config = options.config ?? loadConfig(projectRoot);\r\n\r\n // Use config values, but allow overrides from options and environment variables\r\n // PORT and HOST are standard environment variables in hosting platforms (Render, Heroku, etc.)\r\n const port =\r\n options.port ??\r\n (process.env.PORT ? parseInt(process.env.PORT, 10) : undefined) ??\r\n config.server.port;\r\n\r\n // In production, default to 0.0.0.0 to be accessible from outside\r\n // This is required for platforms like Render.com, Heroku, etc.\r\n const host =\r\n process.env.HOST ?? (!isDev ? \"0.0.0.0\" : undefined) ?? config.server.host;\r\n\r\n const appDir =\r\n options.appDir ??\r\n (isDev\r\n ? getAppDir(projectRoot, config)\r\n : path.join(getBuildDir(projectRoot, config), \"server\"));\r\n\r\n if (!isDev && !fs.existsSync(appDir)) {\r\n logger.error(\"Compiled directory not found\", undefined, {\r\n buildDir: config.directories.build,\r\n appDir,\r\n environment: \"production\",\r\n });\r\n process.exit(1);\r\n }\r\n\r\n const { app, httpServer } = await setupApplication({\r\n projectRoot,\r\n });\r\n\r\n // @TODO: Remove or validate if send the server is needed\r\n await runInitIfExists(projectRoot, { server: httpServer });\r\n\r\n const { routes, apiRoutes, wssRoutes, notFoundPage, errorPage, getRoutes } =\r\n setupServer(app, {\r\n projectRoot,\r\n appDir,\r\n isDev,\r\n config,\r\n });\r\n\r\n const routeLoader = isDev\r\n ? new FilesystemRouteLoader(appDir)\r\n : new ManifestRouteLoader(projectRoot);\r\n\r\n // Set up Socket.IO server and WebSocket event handlers\r\n setupWssEvents({\r\n httpServer,\r\n wssRoutes,\r\n });\r\n\r\n setupRoutes({\r\n app,\r\n routes,\r\n apiRoutes,\r\n notFoundPage,\r\n errorPage,\r\n isDev,\r\n projectRoot,\r\n routeLoader,\r\n getRoutes,\r\n config,\r\n });\r\n\r\n httpServer.listen(port, host, () => {\r\n if (isDev) {\r\n logger.info(\"🚀 Dev server running\", {\r\n url: `http://${host}:${port}`,\r\n appDir,\r\n });\r\n logger.info(\"🧭 Reading routes from\", { appDir });\r\n logger.info(\"📦 Client served from /static/client.js\");\r\n } else {\r\n const buildDir = config.directories.build;\r\n logger.info(\"🚀 Prod server running\", {\r\n url: `http://${host}:${port}`,\r\n appDir,\r\n buildDir,\r\n });\r\n logger.info(\"🧭 Reading compiled routes from\", { appDir });\r\n logger.info(\"📦 Client served from\", {\r\n path: `/static (${buildDir}/client)`,\r\n });\r\n logger.info(\"📄 SSG served from\", {\r\n path: `${buildDir}/ssg (if exists)`,\r\n });\r\n }\r\n });\r\n}\r\n\r\nexport interface StartDevServerOptions {\r\n port?: number;\r\n rootDir?: string;\r\n appDir?: string;\r\n}\r\n\r\n/**\r\n * Development server startup.\r\n * Wrapper around startServer for backward compatibility.\r\n *\r\n * @param options - Server options\r\n */\r\nexport async function startDevServer(options: StartDevServerOptions = {}) {\r\n return startServer({\r\n ...options,\r\n isDev: true,\r\n });\r\n}\r\n\r\nexport interface StartProdServerOptions {\r\n port?: number;\r\n rootDir?: string;\r\n appDir?: string;\r\n}\r\n\r\n/**\r\n * Production server startup.\r\n * Wrapper around startServer for backward compatibility.\r\n *\r\n * @param options - Server options\r\n */\r\nexport async function startProdServer(options: StartProdServerOptions = {}) {\r\n return startServer({\r\n ...options,\r\n isDev: false,\r\n });\r\n}\r\n","import express from \"express\";\r\nimport path from \"path\";\r\nimport {\r\n FilesystemRouteLoader,\r\n ManifestRouteLoader,\r\n RouteLoader,\r\n writeClientRoutesManifest,\r\n} from \"@router/index\";\r\nimport { startClientBundler } from \"@build/bundler/client\";\r\nimport { setupHotReload } from \"@dev/hot-reload-client\";\r\nimport { clearAppRequireCache } from \"@dev/hot-reload-server\";\r\nimport { LoadedRoute, ApiRoute, WssRoute } from \"@router/index.types\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\nimport { getBuildDir } from \"@src/config\";\r\n\r\nexport { RouteLoader };\r\n\r\nimport type { FrameworkConfig } from \"@src/config\";\r\n\r\nexport interface ServerSetupOptions {\r\n projectRoot: string;\r\n appDir: string;\r\n isDev: boolean;\r\n config?: FrameworkConfig;\r\n}\r\n\r\nexport interface ServerSetupResult {\r\n routes: LoadedRoute[];\r\n wssRoutes: WssRoute[];\r\n notFoundPage: LoadedRoute | null;\r\n errorPage: LoadedRoute | null;\r\n apiRoutes: ApiRoute[];\r\n getRoutes?: () => {\r\n routes: LoadedRoute[];\r\n apiRoutes: ApiRoute[];\r\n };\r\n}\r\n\r\n/**\r\n * Sets up routes and bundler based on environment (dev/prod).\r\n *\r\n * @param app - Express application instance\r\n * @param options - Setup options\r\n * @returns Server setup result with routes and handlers\r\n */\r\nexport function setupServer(\r\n app: express.Application,\r\n options: ServerSetupOptions\r\n): ServerSetupResult {\r\n const { projectRoot, appDir, isDev, config } = options;\r\n\r\n const routeLoader: RouteLoader = isDev\r\n ? new FilesystemRouteLoader(appDir)\r\n : new ManifestRouteLoader(projectRoot);\r\n\r\n if (isDev) {\r\n const { outDir, waitForBuild } = startClientBundler(projectRoot, \"development\");\r\n \r\n // Callback to reload routes manifest and clear cache when files change\r\n const onFileChange = async (filePath: string) => {\r\n const rel = path.relative(appDir, filePath);\r\n const isPageFile = filePath.includes(\"page.tsx\") || filePath.includes(\"page.ts\") || \r\n filePath.includes(\"layout.tsx\") || filePath.includes(\"layout.ts\") ||\r\n filePath.includes(\"_not-found\") || filePath.includes(\"_error\");\r\n const isTsFile = filePath.endsWith(\".ts\") || filePath.endsWith(\".tsx\");\r\n \r\n // Clear require cache for ANY TypeScript/TSX file change\r\n // This ensures components, utilities, hooks, etc. are reloaded correctly\r\n if (isTsFile) {\r\n clearAppRequireCache(appDir);\r\n console.log(`[hot-reload] Cleared require cache for: ${rel}`);\r\n }\r\n \r\n // Reload client routes manifest for page files (affects client-side routing)\r\n // This is needed when routes are added/removed/changed\r\n if (isPageFile) {\r\n const loader = new FilesystemRouteLoader(appDir);\r\n const newRoutes = loader.loadRoutes();\r\n writeClientRoutesManifest(newRoutes, projectRoot);\r\n console.log(\"[hot-reload] Client routes manifest reloaded\");\r\n }\r\n \r\n // Note: \r\n // - API routes are already reloaded on each request via getRoutes().apiRoutes\r\n // - WSS routes require server restart to take effect (Socket.IO setup is one-time)\r\n // - Components and other files are handled by the bundler (Rspack watch mode)\r\n // and the require cache is cleared above to ensure server-side code reloads\r\n };\r\n \r\n setupHotReload({ app, appDir, waitForBuild, onFileChange });\r\n \r\n app.use(\"/static\", express.static(outDir));\r\n\r\n const routes = routeLoader.loadRoutes();\r\n const wssRoutes = routeLoader.loadWssRoutes();\r\n const notFoundPage = routeLoader.loadNotFoundRoute();\r\n const errorPage = routeLoader.loadErrorRoute();\r\n writeClientRoutesManifest(routes, projectRoot);\r\n\r\n function getRoutes() {\r\n clearAppRequireCache(appDir);\r\n const loader = new FilesystemRouteLoader(appDir);\r\n return {\r\n routes: loader.loadRoutes(),\r\n apiRoutes: loader.loadApiRoutes(),\r\n };\r\n }\r\n\r\n return {\r\n routes,\r\n wssRoutes,\r\n notFoundPage,\r\n errorPage,\r\n apiRoutes: routeLoader.loadApiRoutes(),\r\n getRoutes,\r\n };\r\n } else {\r\n const routes = routeLoader.loadRoutes();\r\n const apiRoutes = routeLoader.loadApiRoutes();\r\n const wssRoutes = routeLoader.loadWssRoutes();\r\n const notFoundPage = routeLoader.loadNotFoundRoute();\r\n const errorPage = routeLoader.loadErrorRoute();\r\n\r\n const buildDir = config ? getBuildDir(projectRoot, config) : path.join(projectRoot, BUILD_FOLDER_NAME);\r\n const clientOutDir = path.join(buildDir, \"client\");\r\n app.use(\r\n \"/static\",\r\n express.static(clientOutDir, {\r\n maxAge: \"1y\",\r\n immutable: true,\r\n })\r\n );\r\n\r\n return {\r\n routes,\r\n apiRoutes,\r\n wssRoutes,\r\n notFoundPage,\r\n errorPage,\r\n };\r\n }\r\n}\r\n","/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */\nimport { stat as statcb } from 'fs';\nimport { stat, readdir } from 'fs/promises';\nimport { EventEmitter } from 'events';\nimport * as sysPath from 'path';\nimport { readdirp } from 'readdirp';\nimport { NodeFsHandler, EVENTS as EV, isWindows, isIBMi, EMPTY_FN, STR_CLOSE, STR_END, } from './handler.js';\nconst SLASH = '/';\nconst SLASH_SLASH = '//';\nconst ONE_DOT = '.';\nconst TWO_DOTS = '..';\nconst STRING_TYPE = 'string';\nconst BACK_SLASH_RE = /\\\\/g;\nconst DOUBLE_SLASH_RE = /\\/\\//;\nconst DOT_RE = /\\..*\\.(sw[px])$|~$|\\.subl.*\\.tmp/;\nconst REPLACER_RE = /^\\.[/\\\\]/;\nfunction arrify(item) {\n return Array.isArray(item) ? item : [item];\n}\nconst isMatcherObject = (matcher) => typeof matcher === 'object' && matcher !== null && !(matcher instanceof RegExp);\nfunction createPattern(matcher) {\n if (typeof matcher === 'function')\n return matcher;\n if (typeof matcher === 'string')\n return (string) => matcher === string;\n if (matcher instanceof RegExp)\n return (string) => matcher.test(string);\n if (typeof matcher === 'object' && matcher !== null) {\n return (string) => {\n if (matcher.path === string)\n return true;\n if (matcher.recursive) {\n const relative = sysPath.relative(matcher.path, string);\n if (!relative) {\n return false;\n }\n return !relative.startsWith('..') && !sysPath.isAbsolute(relative);\n }\n return false;\n };\n }\n return () => false;\n}\nfunction normalizePath(path) {\n if (typeof path !== 'string')\n throw new Error('string expected');\n path = sysPath.normalize(path);\n path = path.replace(/\\\\/g, '/');\n let prepend = false;\n if (path.startsWith('//'))\n prepend = true;\n const DOUBLE_SLASH_RE = /\\/\\//;\n while (path.match(DOUBLE_SLASH_RE))\n path = path.replace(DOUBLE_SLASH_RE, '/');\n if (prepend)\n path = '/' + path;\n return path;\n}\nfunction matchPatterns(patterns, testString, stats) {\n const path = normalizePath(testString);\n for (let index = 0; index < patterns.length; index++) {\n const pattern = patterns[index];\n if (pattern(path, stats)) {\n return true;\n }\n }\n return false;\n}\nfunction anymatch(matchers, testString) {\n if (matchers == null) {\n throw new TypeError('anymatch: specify first argument');\n }\n // Early cache for matchers.\n const matchersArray = arrify(matchers);\n const patterns = matchersArray.map((matcher) => createPattern(matcher));\n if (testString == null) {\n return (testString, stats) => {\n return matchPatterns(patterns, testString, stats);\n };\n }\n return matchPatterns(patterns, testString);\n}\nconst unifyPaths = (paths_) => {\n const paths = arrify(paths_).flat();\n if (!paths.every((p) => typeof p === STRING_TYPE)) {\n throw new TypeError(`Non-string provided as watch path: ${paths}`);\n }\n return paths.map(normalizePathToUnix);\n};\n// If SLASH_SLASH occurs at the beginning of path, it is not replaced\n// because \"//StoragePC/DrivePool/Movies\" is a valid network path\nconst toUnix = (string) => {\n let str = string.replace(BACK_SLASH_RE, SLASH);\n let prepend = false;\n if (str.startsWith(SLASH_SLASH)) {\n prepend = true;\n }\n while (str.match(DOUBLE_SLASH_RE)) {\n str = str.replace(DOUBLE_SLASH_RE, SLASH);\n }\n if (prepend) {\n str = SLASH + str;\n }\n return str;\n};\n// Our version of upath.normalize\n// TODO: this is not equal to path-normalize module - investigate why\nconst normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path)));\n// TODO: refactor\nconst normalizeIgnored = (cwd = '') => (path) => {\n if (typeof path === 'string') {\n return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path));\n }\n else {\n return path;\n }\n};\nconst getAbsolutePath = (path, cwd) => {\n if (sysPath.isAbsolute(path)) {\n return path;\n }\n return sysPath.join(cwd, path);\n};\nconst EMPTY_SET = Object.freeze(new Set());\n/**\n * Directory entry.\n */\nclass DirEntry {\n constructor(dir, removeWatcher) {\n this.path = dir;\n this._removeWatcher = removeWatcher;\n this.items = new Set();\n }\n add(item) {\n const { items } = this;\n if (!items)\n return;\n if (item !== ONE_DOT && item !== TWO_DOTS)\n items.add(item);\n }\n async remove(item) {\n const { items } = this;\n if (!items)\n return;\n items.delete(item);\n if (items.size > 0)\n return;\n const dir = this.path;\n try {\n await readdir(dir);\n }\n catch (err) {\n if (this._removeWatcher) {\n this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir));\n }\n }\n }\n has(item) {\n const { items } = this;\n if (!items)\n return;\n return items.has(item);\n }\n getChildren() {\n const { items } = this;\n if (!items)\n return [];\n return [...items.values()];\n }\n dispose() {\n this.items.clear();\n this.path = '';\n this._removeWatcher = EMPTY_FN;\n this.items = EMPTY_SET;\n Object.freeze(this);\n }\n}\nconst STAT_METHOD_F = 'stat';\nconst STAT_METHOD_L = 'lstat';\nexport class WatchHelper {\n constructor(path, follow, fsw) {\n this.fsw = fsw;\n const watchPath = path;\n this.path = path = path.replace(REPLACER_RE, '');\n this.watchPath = watchPath;\n this.fullWatchPath = sysPath.resolve(watchPath);\n this.dirParts = [];\n this.dirParts.forEach((parts) => {\n if (parts.length > 1)\n parts.pop();\n });\n this.followSymlinks = follow;\n this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;\n }\n entryPath(entry) {\n return sysPath.join(this.watchPath, sysPath.relative(this.watchPath, entry.fullPath));\n }\n filterPath(entry) {\n const { stats } = entry;\n if (stats && stats.isSymbolicLink())\n return this.filterDir(entry);\n const resolvedPath = this.entryPath(entry);\n // TODO: what if stats is undefined? remove !\n return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);\n }\n filterDir(entry) {\n return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);\n }\n}\n/**\n * Watches files & directories for changes. Emitted events:\n * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`\n *\n * new FSWatcher()\n * .add(directories)\n * .on('add', path => log('File', path, 'was added'))\n */\nexport class FSWatcher extends EventEmitter {\n // Not indenting methods for history sake; for now.\n constructor(_opts = {}) {\n super();\n this.closed = false;\n this._closers = new Map();\n this._ignoredPaths = new Set();\n this._throttled = new Map();\n this._streams = new Set();\n this._symlinkPaths = new Map();\n this._watched = new Map();\n this._pendingWrites = new Map();\n this._pendingUnlinks = new Map();\n this._readyCount = 0;\n this._readyEmitted = false;\n const awf = _opts.awaitWriteFinish;\n const DEF_AWF = { stabilityThreshold: 2000, pollInterval: 100 };\n const opts = {\n // Defaults\n persistent: true,\n ignoreInitial: false,\n ignorePermissionErrors: false,\n interval: 100,\n binaryInterval: 300,\n followSymlinks: true,\n usePolling: false,\n // useAsync: false,\n atomic: true, // NOTE: overwritten later (depends on usePolling)\n ..._opts,\n // Change format\n ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),\n awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === 'object' ? { ...DEF_AWF, ...awf } : false,\n };\n // Always default to polling on IBM i because fs.watch() is not available on IBM i.\n if (isIBMi)\n opts.usePolling = true;\n // Editor atomic write normalization enabled by default with fs.watch\n if (opts.atomic === undefined)\n opts.atomic = !opts.usePolling;\n // opts.atomic = typeof _opts.atomic === 'number' ? _opts.atomic : 100;\n // Global override. Useful for developers, who need to force polling for all\n // instances of chokidar, regardless of usage / dependency depth\n const envPoll = process.env.CHOKIDAR_USEPOLLING;\n if (envPoll !== undefined) {\n const envLower = envPoll.toLowerCase();\n if (envLower === 'false' || envLower === '0')\n opts.usePolling = false;\n else if (envLower === 'true' || envLower === '1')\n opts.usePolling = true;\n else\n opts.usePolling = !!envLower;\n }\n const envInterval = process.env.CHOKIDAR_INTERVAL;\n if (envInterval)\n opts.interval = Number.parseInt(envInterval, 10);\n // This is done to emit ready only once, but each 'add' will increase that?\n let readyCalls = 0;\n this._emitReady = () => {\n readyCalls++;\n if (readyCalls >= this._readyCount) {\n this._emitReady = EMPTY_FN;\n this._readyEmitted = true;\n // use process.nextTick to allow time for listener to be bound\n process.nextTick(() => this.emit(EV.READY));\n }\n };\n this._emitRaw = (...args) => this.emit(EV.RAW, ...args);\n this._boundRemove = this._remove.bind(this);\n this.options = opts;\n this._nodeFsHandler = new NodeFsHandler(this);\n // You’re frozen when your heart’s not open.\n Object.freeze(opts);\n }\n _addIgnoredPath(matcher) {\n if (isMatcherObject(matcher)) {\n // return early if we already have a deeply equal matcher object\n for (const ignored of this._ignoredPaths) {\n if (isMatcherObject(ignored) &&\n ignored.path === matcher.path &&\n ignored.recursive === matcher.recursive) {\n return;\n }\n }\n }\n this._ignoredPaths.add(matcher);\n }\n _removeIgnoredPath(matcher) {\n this._ignoredPaths.delete(matcher);\n // now find any matcher objects with the matcher as path\n if (typeof matcher === 'string') {\n for (const ignored of this._ignoredPaths) {\n // TODO (43081j): make this more efficient.\n // probably just make a `this._ignoredDirectories` or some\n // such thing.\n if (isMatcherObject(ignored) && ignored.path === matcher) {\n this._ignoredPaths.delete(ignored);\n }\n }\n }\n }\n // Public methods\n /**\n * Adds paths to be watched on an existing FSWatcher instance.\n * @param paths_ file or file list. Other arguments are unused\n */\n add(paths_, _origAdd, _internal) {\n const { cwd } = this.options;\n this.closed = false;\n this._closePromise = undefined;\n let paths = unifyPaths(paths_);\n if (cwd) {\n paths = paths.map((path) => {\n const absPath = getAbsolutePath(path, cwd);\n // Check `path` instead of `absPath` because the cwd portion can't be a glob\n return absPath;\n });\n }\n paths.forEach((path) => {\n this._removeIgnoredPath(path);\n });\n this._userIgnored = undefined;\n if (!this._readyCount)\n this._readyCount = 0;\n this._readyCount += paths.length;\n Promise.all(paths.map(async (path) => {\n const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, undefined, 0, _origAdd);\n if (res)\n this._emitReady();\n return res;\n })).then((results) => {\n if (this.closed)\n return;\n results.forEach((item) => {\n if (item)\n this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item));\n });\n });\n return this;\n }\n /**\n * Close watchers or start ignoring events from specified paths.\n */\n unwatch(paths_) {\n if (this.closed)\n return this;\n const paths = unifyPaths(paths_);\n const { cwd } = this.options;\n paths.forEach((path) => {\n // convert to absolute path unless relative path already matches\n if (!sysPath.isAbsolute(path) && !this._closers.has(path)) {\n if (cwd)\n path = sysPath.join(cwd, path);\n path = sysPath.resolve(path);\n }\n this._closePath(path);\n this._addIgnoredPath(path);\n if (this._watched.has(path)) {\n this._addIgnoredPath({\n path,\n recursive: true,\n });\n }\n // reset the cached userIgnored anymatch fn\n // to make ignoredPaths changes effective\n this._userIgnored = undefined;\n });\n return this;\n }\n /**\n * Close watchers and remove all listeners from watched paths.\n */\n close() {\n if (this._closePromise) {\n return this._closePromise;\n }\n this.closed = true;\n // Memory management.\n this.removeAllListeners();\n const closers = [];\n this._closers.forEach((closerList) => closerList.forEach((closer) => {\n const promise = closer();\n if (promise instanceof Promise)\n closers.push(promise);\n }));\n this._streams.forEach((stream) => stream.destroy());\n this._userIgnored = undefined;\n this._readyCount = 0;\n this._readyEmitted = false;\n this._watched.forEach((dirent) => dirent.dispose());\n this._closers.clear();\n this._watched.clear();\n this._streams.clear();\n this._symlinkPaths.clear();\n this._throttled.clear();\n this._closePromise = closers.length\n ? Promise.all(closers).then(() => undefined)\n : Promise.resolve();\n return this._closePromise;\n }\n /**\n * Expose list of watched paths\n * @returns for chaining\n */\n getWatched() {\n const watchList = {};\n this._watched.forEach((entry, dir) => {\n const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir;\n const index = key || ONE_DOT;\n watchList[index] = entry.getChildren().sort();\n });\n return watchList;\n }\n emitWithAll(event, args) {\n this.emit(event, ...args);\n if (event !== EV.ERROR)\n this.emit(EV.ALL, event, ...args);\n }\n // Common helpers\n // --------------\n /**\n * Normalize and emit events.\n * Calling _emit DOES NOT MEAN emit() would be called!\n * @param event Type of event\n * @param path File or directory path\n * @param stats arguments to be passed with event\n * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n async _emit(event, path, stats) {\n if (this.closed)\n return;\n const opts = this.options;\n if (isWindows)\n path = sysPath.normalize(path);\n if (opts.cwd)\n path = sysPath.relative(opts.cwd, path);\n const args = [path];\n if (stats != null)\n args.push(stats);\n const awf = opts.awaitWriteFinish;\n let pw;\n if (awf && (pw = this._pendingWrites.get(path))) {\n pw.lastChange = new Date();\n return this;\n }\n if (opts.atomic) {\n if (event === EV.UNLINK) {\n this._pendingUnlinks.set(path, [event, ...args]);\n setTimeout(() => {\n this._pendingUnlinks.forEach((entry, path) => {\n this.emit(...entry);\n this.emit(EV.ALL, ...entry);\n this._pendingUnlinks.delete(path);\n });\n }, typeof opts.atomic === 'number' ? opts.atomic : 100);\n return this;\n }\n if (event === EV.ADD && this._pendingUnlinks.has(path)) {\n event = EV.CHANGE;\n this._pendingUnlinks.delete(path);\n }\n }\n if (awf && (event === EV.ADD || event === EV.CHANGE) && this._readyEmitted) {\n const awfEmit = (err, stats) => {\n if (err) {\n event = EV.ERROR;\n args[0] = err;\n this.emitWithAll(event, args);\n }\n else if (stats) {\n // if stats doesn't exist the file must have been deleted\n if (args.length > 1) {\n args[1] = stats;\n }\n else {\n args.push(stats);\n }\n this.emitWithAll(event, args);\n }\n };\n this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);\n return this;\n }\n if (event === EV.CHANGE) {\n const isThrottled = !this._throttle(EV.CHANGE, path, 50);\n if (isThrottled)\n return this;\n }\n if (opts.alwaysStat &&\n stats === undefined &&\n (event === EV.ADD || event === EV.ADD_DIR || event === EV.CHANGE)) {\n const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path;\n let stats;\n try {\n stats = await stat(fullPath);\n }\n catch (err) {\n // do nothing\n }\n // Suppress event when fs_stat fails, to avoid sending undefined 'stat'\n if (!stats || this.closed)\n return;\n args.push(stats);\n }\n this.emitWithAll(event, args);\n return this;\n }\n /**\n * Common handler for errors\n * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n _handleError(error) {\n const code = error && error.code;\n if (error &&\n code !== 'ENOENT' &&\n code !== 'ENOTDIR' &&\n (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))) {\n this.emit(EV.ERROR, error);\n }\n return error || this.closed;\n }\n /**\n * Helper utility for throttling\n * @param actionType type being throttled\n * @param path being acted upon\n * @param timeout duration of time to suppress duplicate actions\n * @returns tracking object or false if action should be suppressed\n */\n _throttle(actionType, path, timeout) {\n if (!this._throttled.has(actionType)) {\n this._throttled.set(actionType, new Map());\n }\n const action = this._throttled.get(actionType);\n if (!action)\n throw new Error('invalid throttle');\n const actionPath = action.get(path);\n if (actionPath) {\n actionPath.count++;\n return false;\n }\n // eslint-disable-next-line prefer-const\n let timeoutObject;\n const clear = () => {\n const item = action.get(path);\n const count = item ? item.count : 0;\n action.delete(path);\n clearTimeout(timeoutObject);\n if (item)\n clearTimeout(item.timeoutObject);\n return count;\n };\n timeoutObject = setTimeout(clear, timeout);\n const thr = { timeoutObject, clear, count: 0 };\n action.set(path, thr);\n return thr;\n }\n _incrReadyCount() {\n return this._readyCount++;\n }\n /**\n * Awaits write operation to finish.\n * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.\n * @param path being acted upon\n * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished\n * @param event\n * @param awfEmit Callback to be called when ready for event to be emitted.\n */\n _awaitWriteFinish(path, threshold, event, awfEmit) {\n const awf = this.options.awaitWriteFinish;\n if (typeof awf !== 'object')\n return;\n const pollInterval = awf.pollInterval;\n let timeoutHandler;\n let fullPath = path;\n if (this.options.cwd && !sysPath.isAbsolute(path)) {\n fullPath = sysPath.join(this.options.cwd, path);\n }\n const now = new Date();\n const writes = this._pendingWrites;\n function awaitWriteFinishFn(prevStat) {\n statcb(fullPath, (err, curStat) => {\n if (err || !writes.has(path)) {\n if (err && err.code !== 'ENOENT')\n awfEmit(err);\n return;\n }\n const now = Number(new Date());\n if (prevStat && curStat.size !== prevStat.size) {\n writes.get(path).lastChange = now;\n }\n const pw = writes.get(path);\n const df = now - pw.lastChange;\n if (df >= threshold) {\n writes.delete(path);\n awfEmit(undefined, curStat);\n }\n else {\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);\n }\n });\n }\n if (!writes.has(path)) {\n writes.set(path, {\n lastChange: now,\n cancelWait: () => {\n writes.delete(path);\n clearTimeout(timeoutHandler);\n return event;\n },\n });\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);\n }\n }\n /**\n * Determines whether user has asked to ignore this path.\n */\n _isIgnored(path, stats) {\n if (this.options.atomic && DOT_RE.test(path))\n return true;\n if (!this._userIgnored) {\n const { cwd } = this.options;\n const ign = this.options.ignored;\n const ignored = (ign || []).map(normalizeIgnored(cwd));\n const ignoredPaths = [...this._ignoredPaths];\n const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];\n this._userIgnored = anymatch(list, undefined);\n }\n return this._userIgnored(path, stats);\n }\n _isntIgnored(path, stat) {\n return !this._isIgnored(path, stat);\n }\n /**\n * Provides a set of common helpers and properties relating to symlink handling.\n * @param path file or directory pattern being watched\n */\n _getWatchHelpers(path) {\n return new WatchHelper(path, this.options.followSymlinks, this);\n }\n // Directory helpers\n // -----------------\n /**\n * Provides directory tracking objects\n * @param directory path of the directory\n */\n _getWatchedDir(directory) {\n const dir = sysPath.resolve(directory);\n if (!this._watched.has(dir))\n this._watched.set(dir, new DirEntry(dir, this._boundRemove));\n return this._watched.get(dir);\n }\n // File helpers\n // ------------\n /**\n * Check for read permissions: https://stackoverflow.com/a/11781404/1358405\n */\n _hasReadPermissions(stats) {\n if (this.options.ignorePermissionErrors)\n return true;\n return Boolean(Number(stats.mode) & 0o400);\n }\n /**\n * Handles emitting unlink events for\n * files and directories, and via recursion, for\n * files and directories within directories that are unlinked\n * @param directory within which the following item is located\n * @param item base path of item/directory\n */\n _remove(directory, item, isDirectory) {\n // if what is being deleted is a directory, get that directory's paths\n // for recursive deleting and cleaning of watched object\n // if it is not a directory, nestedDirectoryChildren will be empty array\n const path = sysPath.join(directory, item);\n const fullPath = sysPath.resolve(path);\n isDirectory =\n isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);\n // prevent duplicate handling in case of arriving here nearly simultaneously\n // via multiple paths (such as _handleFile and _handleDir)\n if (!this._throttle('remove', path, 100))\n return;\n // if the only watched file is removed, watch for its return\n if (!isDirectory && this._watched.size === 1) {\n this.add(directory, item, true);\n }\n // This will create a new entry in the watched object in either case\n // so we got to do the directory check beforehand\n const wp = this._getWatchedDir(path);\n const nestedDirectoryChildren = wp.getChildren();\n // Recursively remove children directories / files.\n nestedDirectoryChildren.forEach((nested) => this._remove(path, nested));\n // Check if item was on the watched list and remove it\n const parent = this._getWatchedDir(directory);\n const wasTracked = parent.has(item);\n parent.remove(item);\n // Fixes issue #1042 -> Relative paths were detected and added as symlinks\n // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),\n // but never removed from the map in case the path was deleted.\n // This leads to an incorrect state if the path was recreated:\n // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553\n if (this._symlinkPaths.has(fullPath)) {\n this._symlinkPaths.delete(fullPath);\n }\n // If we wait for this file to be fully written, cancel the wait.\n let relPath = path;\n if (this.options.cwd)\n relPath = sysPath.relative(this.options.cwd, path);\n if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {\n const event = this._pendingWrites.get(relPath).cancelWait();\n if (event === EV.ADD)\n return;\n }\n // The Entry will either be a directory that just got removed\n // or a bogus entry to a file, in either case we have to remove it\n this._watched.delete(path);\n this._watched.delete(fullPath);\n const eventName = isDirectory ? EV.UNLINK_DIR : EV.UNLINK;\n if (wasTracked && !this._isIgnored(path))\n this._emit(eventName, path);\n // Avoid conflicts if we later create another file with the same name\n this._closePath(path);\n }\n /**\n * Closes all watchers for a path\n */\n _closePath(path) {\n this._closeFile(path);\n const dir = sysPath.dirname(path);\n this._getWatchedDir(dir).remove(sysPath.basename(path));\n }\n /**\n * Closes only file-specific watchers\n */\n _closeFile(path) {\n const closers = this._closers.get(path);\n if (!closers)\n return;\n closers.forEach((closer) => closer());\n this._closers.delete(path);\n }\n _addPathCloser(path, closer) {\n if (!closer)\n return;\n let list = this._closers.get(path);\n if (!list) {\n list = [];\n this._closers.set(path, list);\n }\n list.push(closer);\n }\n _readdirp(root, opts) {\n if (this.closed)\n return;\n const options = { type: EV.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };\n let stream = readdirp(root, options);\n this._streams.add(stream);\n stream.once(STR_CLOSE, () => {\n stream = undefined;\n });\n stream.once(STR_END, () => {\n if (stream) {\n this._streams.delete(stream);\n stream = undefined;\n }\n });\n return stream;\n }\n}\n/**\n * Instantiates watcher with paths to be tracked.\n * @param paths file / directory paths\n * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others\n * @returns an instance of FSWatcher for chaining.\n * @example\n * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });\n * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })\n */\nexport function watch(paths, options = {}) {\n const watcher = new FSWatcher(options);\n watcher.add(paths);\n return watcher;\n}\nexport default { watch, FSWatcher };\n","import { stat, lstat, readdir, realpath } from 'node:fs/promises';\nimport { Readable } from 'node:stream';\nimport { resolve as presolve, relative as prelative, join as pjoin, sep as psep } from 'node:path';\nexport const EntryTypes = {\n FILE_TYPE: 'files',\n DIR_TYPE: 'directories',\n FILE_DIR_TYPE: 'files_directories',\n EVERYTHING_TYPE: 'all',\n};\nconst defaultOptions = {\n root: '.',\n fileFilter: (_entryInfo) => true,\n directoryFilter: (_entryInfo) => true,\n type: EntryTypes.FILE_TYPE,\n lstat: false,\n depth: 2147483648,\n alwaysStat: false,\n highWaterMark: 4096,\n};\nObject.freeze(defaultOptions);\nconst RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';\nconst NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);\nconst ALL_TYPES = [\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n];\nconst DIR_TYPES = new Set([\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n]);\nconst FILE_TYPES = new Set([\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n]);\nconst isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);\nconst wantBigintFsStats = process.platform === 'win32';\nconst emptyFn = (_entryInfo) => true;\nconst normalizeFilter = (filter) => {\n if (filter === undefined)\n return emptyFn;\n if (typeof filter === 'function')\n return filter;\n if (typeof filter === 'string') {\n const fl = filter.trim();\n return (entry) => entry.basename === fl;\n }\n if (Array.isArray(filter)) {\n const trItems = filter.map((item) => item.trim());\n return (entry) => trItems.some((f) => entry.basename === f);\n }\n return emptyFn;\n};\n/** Readable readdir stream, emitting new files as they're being listed. */\nexport class ReaddirpStream extends Readable {\n constructor(options = {}) {\n super({\n objectMode: true,\n autoDestroy: true,\n highWaterMark: options.highWaterMark,\n });\n const opts = { ...defaultOptions, ...options };\n const { root, type } = opts;\n this._fileFilter = normalizeFilter(opts.fileFilter);\n this._directoryFilter = normalizeFilter(opts.directoryFilter);\n const statMethod = opts.lstat ? lstat : stat;\n // Use bigint stats if it's windows and stat() supports options (node 10+).\n if (wantBigintFsStats) {\n this._stat = (path) => statMethod(path, { bigint: true });\n }\n else {\n this._stat = statMethod;\n }\n this._maxDepth = opts.depth ?? defaultOptions.depth;\n this._wantsDir = type ? DIR_TYPES.has(type) : false;\n this._wantsFile = type ? FILE_TYPES.has(type) : false;\n this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;\n this._root = presolve(root);\n this._isDirent = !opts.alwaysStat;\n this._statsProp = this._isDirent ? 'dirent' : 'stats';\n this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };\n // Launch stream with one parent, the root dir.\n this.parents = [this._exploreDir(root, 1)];\n this.reading = false;\n this.parent = undefined;\n }\n async _read(batch) {\n if (this.reading)\n return;\n this.reading = true;\n try {\n while (!this.destroyed && batch > 0) {\n const par = this.parent;\n const fil = par && par.files;\n if (fil && fil.length > 0) {\n const { path, depth } = par;\n const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path));\n const awaited = await Promise.all(slice);\n for (const entry of awaited) {\n if (!entry)\n continue;\n if (this.destroyed)\n return;\n const entryType = await this._getEntryType(entry);\n if (entryType === 'directory' && this._directoryFilter(entry)) {\n if (depth <= this._maxDepth) {\n this.parents.push(this._exploreDir(entry.fullPath, depth + 1));\n }\n if (this._wantsDir) {\n this.push(entry);\n batch--;\n }\n }\n else if ((entryType === 'file' || this._includeAsFile(entry)) &&\n this._fileFilter(entry)) {\n if (this._wantsFile) {\n this.push(entry);\n batch--;\n }\n }\n }\n }\n else {\n const parent = this.parents.pop();\n if (!parent) {\n this.push(null);\n break;\n }\n this.parent = await parent;\n if (this.destroyed)\n return;\n }\n }\n }\n catch (error) {\n this.destroy(error);\n }\n finally {\n this.reading = false;\n }\n }\n async _exploreDir(path, depth) {\n let files;\n try {\n files = await readdir(path, this._rdOptions);\n }\n catch (error) {\n this._onError(error);\n }\n return { files, depth, path };\n }\n async _formatEntry(dirent, path) {\n let entry;\n const basename = this._isDirent ? dirent.name : dirent;\n try {\n const fullPath = presolve(pjoin(path, basename));\n entry = { path: prelative(this._root, fullPath), fullPath, basename };\n entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);\n }\n catch (err) {\n this._onError(err);\n return;\n }\n return entry;\n }\n _onError(err) {\n if (isNormalFlowError(err) && !this.destroyed) {\n this.emit('warn', err);\n }\n else {\n this.destroy(err);\n }\n }\n async _getEntryType(entry) {\n // entry may be undefined, because a warning or an error were emitted\n // and the statsProp is undefined\n if (!entry && this._statsProp in entry) {\n return '';\n }\n const stats = entry[this._statsProp];\n if (stats.isFile())\n return 'file';\n if (stats.isDirectory())\n return 'directory';\n if (stats && stats.isSymbolicLink()) {\n const full = entry.fullPath;\n try {\n const entryRealPath = await realpath(full);\n const entryRealPathStats = await lstat(entryRealPath);\n if (entryRealPathStats.isFile()) {\n return 'file';\n }\n if (entryRealPathStats.isDirectory()) {\n const len = entryRealPath.length;\n if (full.startsWith(entryRealPath) && full.substr(len, 1) === psep) {\n const recursiveError = new Error(`Circular symlink detected: \"${full}\" points to \"${entryRealPath}\"`);\n // @ts-ignore\n recursiveError.code = RECURSIVE_ERROR_CODE;\n return this._onError(recursiveError);\n }\n return 'directory';\n }\n }\n catch (error) {\n this._onError(error);\n return '';\n }\n }\n }\n _includeAsFile(entry) {\n const stats = entry && entry[this._statsProp];\n return stats && this._wantsEverything && !stats.isDirectory();\n }\n}\n/**\n * Streaming version: Reads all files and directories in given root recursively.\n * Consumes ~constant small amount of RAM.\n * @param root Root directory\n * @param options Options to specify root (start directory), filters and recursion depth\n */\nexport function readdirp(root, options = {}) {\n // @ts-ignore\n let type = options.entryType || options.type;\n if (type === 'both')\n type = EntryTypes.FILE_DIR_TYPE; // backwards-compatibility\n if (type)\n options.type = type;\n if (!root) {\n throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');\n }\n else if (typeof root !== 'string') {\n throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');\n }\n else if (type && !ALL_TYPES.includes(type)) {\n throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);\n }\n options.root = root;\n return new ReaddirpStream(options);\n}\n/**\n * Promise version: Reads all files and directories in given root recursively.\n * Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.\n * @returns array of paths and their entry infos\n */\nexport function readdirpPromise(root, options = {}) {\n return new Promise((resolve, reject) => {\n const files = [];\n readdirp(root, options)\n .on('data', (entry) => files.push(entry))\n .on('end', () => resolve(files))\n .on('error', (error) => reject(error));\n });\n}\nexport default readdirp;\n","import { watchFile, unwatchFile, watch as fs_watch } from 'fs';\nimport { open, stat, lstat, realpath as fsrealpath } from 'fs/promises';\nimport * as sysPath from 'path';\nimport { type as osType } from 'os';\nexport const STR_DATA = 'data';\nexport const STR_END = 'end';\nexport const STR_CLOSE = 'close';\nexport const EMPTY_FN = () => { };\nexport const IDENTITY_FN = (val) => val;\nconst pl = process.platform;\nexport const isWindows = pl === 'win32';\nexport const isMacos = pl === 'darwin';\nexport const isLinux = pl === 'linux';\nexport const isFreeBSD = pl === 'freebsd';\nexport const isIBMi = osType() === 'OS400';\nexport const EVENTS = {\n ALL: 'all',\n READY: 'ready',\n ADD: 'add',\n CHANGE: 'change',\n ADD_DIR: 'addDir',\n UNLINK: 'unlink',\n UNLINK_DIR: 'unlinkDir',\n RAW: 'raw',\n ERROR: 'error',\n};\nconst EV = EVENTS;\nconst THROTTLE_MODE_WATCH = 'watch';\nconst statMethods = { lstat, stat };\nconst KEY_LISTENERS = 'listeners';\nconst KEY_ERR = 'errHandlers';\nconst KEY_RAW = 'rawEmitters';\nconst HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];\n// prettier-ignore\nconst binaryExtensions = new Set([\n '3dm', '3ds', '3g2', '3gp', '7z', 'a', 'aac', 'adp', 'afdesign', 'afphoto', 'afpub', 'ai',\n 'aif', 'aiff', 'alz', 'ape', 'apk', 'appimage', 'ar', 'arj', 'asf', 'au', 'avi',\n 'bak', 'baml', 'bh', 'bin', 'bk', 'bmp', 'btif', 'bz2', 'bzip2',\n 'cab', 'caf', 'cgm', 'class', 'cmx', 'cpio', 'cr2', 'cur', 'dat', 'dcm', 'deb', 'dex', 'djvu',\n 'dll', 'dmg', 'dng', 'doc', 'docm', 'docx', 'dot', 'dotm', 'dra', 'DS_Store', 'dsk', 'dts',\n 'dtshd', 'dvb', 'dwg', 'dxf',\n 'ecelp4800', 'ecelp7470', 'ecelp9600', 'egg', 'eol', 'eot', 'epub', 'exe',\n 'f4v', 'fbs', 'fh', 'fla', 'flac', 'flatpak', 'fli', 'flv', 'fpx', 'fst', 'fvt',\n 'g3', 'gh', 'gif', 'graffle', 'gz', 'gzip',\n 'h261', 'h263', 'h264', 'icns', 'ico', 'ief', 'img', 'ipa', 'iso',\n 'jar', 'jpeg', 'jpg', 'jpgv', 'jpm', 'jxr', 'key', 'ktx',\n 'lha', 'lib', 'lvp', 'lz', 'lzh', 'lzma', 'lzo',\n 'm3u', 'm4a', 'm4v', 'mar', 'mdi', 'mht', 'mid', 'midi', 'mj2', 'mka', 'mkv', 'mmr', 'mng',\n 'mobi', 'mov', 'movie', 'mp3',\n 'mp4', 'mp4a', 'mpeg', 'mpg', 'mpga', 'mxu',\n 'nef', 'npx', 'numbers', 'nupkg',\n 'o', 'odp', 'ods', 'odt', 'oga', 'ogg', 'ogv', 'otf', 'ott',\n 'pages', 'pbm', 'pcx', 'pdb', 'pdf', 'pea', 'pgm', 'pic', 'png', 'pnm', 'pot', 'potm',\n 'potx', 'ppa', 'ppam',\n 'ppm', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx', 'psd', 'pya', 'pyc', 'pyo', 'pyv',\n 'qt',\n 'rar', 'ras', 'raw', 'resources', 'rgb', 'rip', 'rlc', 'rmf', 'rmvb', 'rpm', 'rtf', 'rz',\n 's3m', 's7z', 'scpt', 'sgi', 'shar', 'snap', 'sil', 'sketch', 'slk', 'smv', 'snk', 'so',\n 'stl', 'suo', 'sub', 'swf',\n 'tar', 'tbz', 'tbz2', 'tga', 'tgz', 'thmx', 'tif', 'tiff', 'tlz', 'ttc', 'ttf', 'txz',\n 'udf', 'uvh', 'uvi', 'uvm', 'uvp', 'uvs', 'uvu',\n 'viv', 'vob',\n 'war', 'wav', 'wax', 'wbmp', 'wdp', 'weba', 'webm', 'webp', 'whl', 'wim', 'wm', 'wma',\n 'wmv', 'wmx', 'woff', 'woff2', 'wrm', 'wvx',\n 'xbm', 'xif', 'xla', 'xlam', 'xls', 'xlsb', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx', 'xm',\n 'xmind', 'xpi', 'xpm', 'xwd', 'xz',\n 'z', 'zip', 'zipx',\n]);\nconst isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());\n// TODO: emit errors properly. Example: EMFILE on Macos.\nconst foreach = (val, fn) => {\n if (val instanceof Set) {\n val.forEach(fn);\n }\n else {\n fn(val);\n }\n};\nconst addAndConvert = (main, prop, item) => {\n let container = main[prop];\n if (!(container instanceof Set)) {\n main[prop] = container = new Set([container]);\n }\n container.add(item);\n};\nconst clearItem = (cont) => (key) => {\n const set = cont[key];\n if (set instanceof Set) {\n set.clear();\n }\n else {\n delete cont[key];\n }\n};\nconst delFromSet = (main, prop, item) => {\n const container = main[prop];\n if (container instanceof Set) {\n container.delete(item);\n }\n else if (container === item) {\n delete main[prop];\n }\n};\nconst isEmptySet = (val) => (val instanceof Set ? val.size === 0 : !val);\nconst FsWatchInstances = new Map();\n/**\n * Instantiates the fs_watch interface\n * @param path to be watched\n * @param options to be passed to fs_watch\n * @param listener main event handler\n * @param errHandler emits info about errors\n * @param emitRaw emits raw event data\n * @returns {NativeFsWatcher}\n */\nfunction createFsWatchInstance(path, options, listener, errHandler, emitRaw) {\n const handleEvent = (rawEvent, evPath) => {\n listener(path);\n emitRaw(rawEvent, evPath, { watchedPath: path });\n // emit based on events occurring for files from a directory's watcher in\n // case the file's watcher misses it (and rely on throttling to de-dupe)\n if (evPath && path !== evPath) {\n fsWatchBroadcast(sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath));\n }\n };\n try {\n return fs_watch(path, {\n persistent: options.persistent,\n }, handleEvent);\n }\n catch (error) {\n errHandler(error);\n return undefined;\n }\n}\n/**\n * Helper for passing fs_watch event data to a collection of listeners\n * @param fullPath absolute path bound to fs_watch instance\n */\nconst fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {\n const cont = FsWatchInstances.get(fullPath);\n if (!cont)\n return;\n foreach(cont[listenerType], (listener) => {\n listener(val1, val2, val3);\n });\n};\n/**\n * Instantiates the fs_watch interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path\n * @param fullPath absolute path\n * @param options to be passed to fs_watch\n * @param handlers container for event listener functions\n */\nconst setFsWatchListener = (path, fullPath, options, handlers) => {\n const { listener, errHandler, rawEmitter } = handlers;\n let cont = FsWatchInstances.get(fullPath);\n let watcher;\n if (!options.persistent) {\n watcher = createFsWatchInstance(path, options, listener, errHandler, rawEmitter);\n if (!watcher)\n return;\n return watcher.close.bind(watcher);\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_ERR, errHandler);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n watcher = createFsWatchInstance(path, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, // no need to use broadcast here\n fsWatchBroadcast.bind(null, fullPath, KEY_RAW));\n if (!watcher)\n return;\n watcher.on(EV.ERROR, async (error) => {\n const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);\n if (cont)\n cont.watcherUnusable = true; // documented since Node 10.4.1\n // Workaround for https://github.com/joyent/node/issues/4337\n if (isWindows && error.code === 'EPERM') {\n try {\n const fd = await open(path, 'r');\n await fd.close();\n broadcastErr(error);\n }\n catch (err) {\n // do nothing\n }\n }\n else {\n broadcastErr(error);\n }\n });\n cont = {\n listeners: listener,\n errHandlers: errHandler,\n rawEmitters: rawEmitter,\n watcher,\n };\n FsWatchInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // removes this instance's listeners and closes the underlying fs_watch\n // instance if there are no more listeners left\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_ERR, errHandler);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n // Check to protect against issue gh-730.\n // if (cont.watcherUnusable) {\n cont.watcher.close();\n // }\n FsWatchInstances.delete(fullPath);\n HANDLER_KEYS.forEach(clearItem(cont));\n // @ts-ignore\n cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n// fs_watchFile helpers\n// object to hold per-process fs_watchFile instances\n// (may be shared across chokidar FSWatcher instances)\nconst FsWatchFileInstances = new Map();\n/**\n * Instantiates the fs_watchFile interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path to be watched\n * @param fullPath absolute path\n * @param options options to be passed to fs_watchFile\n * @param handlers container for event listener functions\n * @returns closer\n */\nconst setFsWatchFileListener = (path, fullPath, options, handlers) => {\n const { listener, rawEmitter } = handlers;\n let cont = FsWatchFileInstances.get(fullPath);\n // let listeners = new Set();\n // let rawEmitters = new Set();\n const copts = cont && cont.options;\n if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {\n // \"Upgrade\" the watcher to persistence or a quicker interval.\n // This creates some unlikely edge case issues if the user mixes\n // settings in a very weird way, but solving for those cases\n // doesn't seem worthwhile for the added complexity.\n // listeners = cont.listeners;\n // rawEmitters = cont.rawEmitters;\n unwatchFile(fullPath);\n cont = undefined;\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n // TODO\n // listeners.add(listener);\n // rawEmitters.add(rawEmitter);\n cont = {\n listeners: listener,\n rawEmitters: rawEmitter,\n options,\n watcher: watchFile(fullPath, options, (curr, prev) => {\n foreach(cont.rawEmitters, (rawEmitter) => {\n rawEmitter(EV.CHANGE, fullPath, { curr, prev });\n });\n const currmtime = curr.mtimeMs;\n if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {\n foreach(cont.listeners, (listener) => listener(path, curr));\n }\n }),\n };\n FsWatchFileInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // Removes this instance's listeners and closes the underlying fs_watchFile\n // instance if there are no more listeners left.\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n FsWatchFileInstances.delete(fullPath);\n unwatchFile(fullPath);\n cont.options = cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n/**\n * @mixin\n */\nexport class NodeFsHandler {\n constructor(fsW) {\n this.fsw = fsW;\n this._boundHandleError = (error) => fsW._handleError(error);\n }\n /**\n * Watch file for changes with fs_watchFile or fs_watch.\n * @param path to file or dir\n * @param listener on fs change\n * @returns closer for the watcher instance\n */\n _watchWithNodeFs(path, listener) {\n const opts = this.fsw.options;\n const directory = sysPath.dirname(path);\n const basename = sysPath.basename(path);\n const parent = this.fsw._getWatchedDir(directory);\n parent.add(basename);\n const absolutePath = sysPath.resolve(path);\n const options = {\n persistent: opts.persistent,\n };\n if (!listener)\n listener = EMPTY_FN;\n let closer;\n if (opts.usePolling) {\n const enableBin = opts.interval !== opts.binaryInterval;\n options.interval = enableBin && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;\n closer = setFsWatchFileListener(path, absolutePath, options, {\n listener,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n else {\n closer = setFsWatchListener(path, absolutePath, options, {\n listener,\n errHandler: this._boundHandleError,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n return closer;\n }\n /**\n * Watch a file and emit add event if warranted.\n * @returns closer for the watcher instance\n */\n _handleFile(file, stats, initialAdd) {\n if (this.fsw.closed) {\n return;\n }\n const dirname = sysPath.dirname(file);\n const basename = sysPath.basename(file);\n const parent = this.fsw._getWatchedDir(dirname);\n // stats is always present\n let prevStats = stats;\n // if the file is already being watched, do nothing\n if (parent.has(basename))\n return;\n const listener = async (path, newStats) => {\n if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))\n return;\n if (!newStats || newStats.mtimeMs === 0) {\n try {\n const newStats = await stat(file);\n if (this.fsw.closed)\n return;\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats.ino) {\n this.fsw._closeFile(path);\n prevStats = newStats;\n const closer = this._watchWithNodeFs(file, listener);\n if (closer)\n this.fsw._addPathCloser(path, closer);\n }\n else {\n prevStats = newStats;\n }\n }\n catch (error) {\n // Fix issues where mtime is null but file is still present\n this.fsw._remove(dirname, basename);\n }\n // add is about to be emitted if file not already tracked in parent\n }\n else if (parent.has(basename)) {\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n prevStats = newStats;\n }\n };\n // kick off the watcher\n const closer = this._watchWithNodeFs(file, listener);\n // emit an add event if we're supposed to\n if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {\n if (!this.fsw._throttle(EV.ADD, file, 0))\n return;\n this.fsw._emit(EV.ADD, file, stats);\n }\n return closer;\n }\n /**\n * Handle symlinks encountered while reading a dir.\n * @param entry returned by readdirp\n * @param directory path of dir being read\n * @param path of this item\n * @param item basename of this item\n * @returns true if no more processing is needed for this entry.\n */\n async _handleSymlink(entry, directory, path, item) {\n if (this.fsw.closed) {\n return;\n }\n const full = entry.fullPath;\n const dir = this.fsw._getWatchedDir(directory);\n if (!this.fsw.options.followSymlinks) {\n // watch symlink directly (don't follow) and detect changes\n this.fsw._incrReadyCount();\n let linkPath;\n try {\n linkPath = await fsrealpath(path);\n }\n catch (e) {\n this.fsw._emitReady();\n return true;\n }\n if (this.fsw.closed)\n return;\n if (dir.has(item)) {\n if (this.fsw._symlinkPaths.get(full) !== linkPath) {\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.CHANGE, path, entry.stats);\n }\n }\n else {\n dir.add(item);\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.ADD, path, entry.stats);\n }\n this.fsw._emitReady();\n return true;\n }\n // don't follow the same symlink more than once\n if (this.fsw._symlinkPaths.has(full)) {\n return true;\n }\n this.fsw._symlinkPaths.set(full, true);\n }\n _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {\n // Normalize the directory name on Windows\n directory = sysPath.join(directory, '');\n throttler = this.fsw._throttle('readdir', directory, 1000);\n if (!throttler)\n return;\n const previous = this.fsw._getWatchedDir(wh.path);\n const current = new Set();\n let stream = this.fsw._readdirp(directory, {\n fileFilter: (entry) => wh.filterPath(entry),\n directoryFilter: (entry) => wh.filterDir(entry),\n });\n if (!stream)\n return;\n stream\n .on(STR_DATA, async (entry) => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const item = entry.path;\n let path = sysPath.join(directory, item);\n current.add(item);\n if (entry.stats.isSymbolicLink() &&\n (await this._handleSymlink(entry, directory, path, item))) {\n return;\n }\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n // Files that present in current directory snapshot\n // but absent in previous are added to watch list and\n // emit `add` event.\n if (item === target || (!target && !previous.has(item))) {\n this.fsw._incrReadyCount();\n // ensure relativeness of path is preserved in case of watcher reuse\n path = sysPath.join(dir, sysPath.relative(dir, path));\n this._addToNodeFs(path, initialAdd, wh, depth + 1);\n }\n })\n .on(EV.ERROR, this._boundHandleError);\n return new Promise((resolve, reject) => {\n if (!stream)\n return reject();\n stream.once(STR_END, () => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const wasThrottled = throttler ? throttler.clear() : false;\n resolve(undefined);\n // Files that absent in current directory snapshot\n // but present in previous emit `remove` event\n // and are removed from @watched[directory].\n previous\n .getChildren()\n .filter((item) => {\n return item !== directory && !current.has(item);\n })\n .forEach((item) => {\n this.fsw._remove(directory, item);\n });\n stream = undefined;\n // one more time for any missed in case changes came in extremely quickly\n if (wasThrottled)\n this._handleRead(directory, false, wh, target, dir, depth, throttler);\n });\n });\n }\n /**\n * Read directory to add / remove files from `@watched` list and re-read it on change.\n * @param dir fs path\n * @param stats\n * @param initialAdd\n * @param depth relative to user-supplied path\n * @param target child path targeted for watch\n * @param wh Common watch helpers for this path\n * @param realpath\n * @returns closer for the watcher instance.\n */\n async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {\n const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));\n const tracked = parentDir.has(sysPath.basename(dir));\n if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {\n this.fsw._emit(EV.ADD_DIR, dir, stats);\n }\n // ensure dir is tracked (harmless if redundant)\n parentDir.add(sysPath.basename(dir));\n this.fsw._getWatchedDir(dir);\n let throttler;\n let closer;\n const oDepth = this.fsw.options.depth;\n if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {\n if (!target) {\n await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);\n if (this.fsw.closed)\n return;\n }\n closer = this._watchWithNodeFs(dir, (dirPath, stats) => {\n // if current directory is removed, do nothing\n if (stats && stats.mtimeMs === 0)\n return;\n this._handleRead(dirPath, false, wh, target, dir, depth, throttler);\n });\n }\n return closer;\n }\n /**\n * Handle added file, directory, or glob pattern.\n * Delegates call to _handleFile / _handleDir after checks.\n * @param path to file or ir\n * @param initialAdd was the file added at watch instantiation?\n * @param priorWh depth relative to user-supplied path\n * @param depth Child path actually targeted for watch\n * @param target Child path actually targeted for watch\n */\n async _addToNodeFs(path, initialAdd, priorWh, depth, target) {\n const ready = this.fsw._emitReady;\n if (this.fsw._isIgnored(path) || this.fsw.closed) {\n ready();\n return false;\n }\n const wh = this.fsw._getWatchHelpers(path);\n if (priorWh) {\n wh.filterPath = (entry) => priorWh.filterPath(entry);\n wh.filterDir = (entry) => priorWh.filterDir(entry);\n }\n // evaluate what is at the path we're being asked to watch\n try {\n const stats = await statMethods[wh.statMethod](wh.watchPath);\n if (this.fsw.closed)\n return;\n if (this.fsw._isIgnored(wh.watchPath, stats)) {\n ready();\n return false;\n }\n const follow = this.fsw.options.followSymlinks;\n let closer;\n if (stats.isDirectory()) {\n const absPath = sysPath.resolve(path);\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (absPath !== targetPath && targetPath !== undefined) {\n this.fsw._symlinkPaths.set(absPath, targetPath);\n }\n }\n else if (stats.isSymbolicLink()) {\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n const parent = sysPath.dirname(wh.watchPath);\n this.fsw._getWatchedDir(parent).add(wh.watchPath);\n this.fsw._emit(EV.ADD, wh.watchPath, stats);\n closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (targetPath !== undefined) {\n this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);\n }\n }\n else {\n closer = this._handleFile(wh.watchPath, stats, initialAdd);\n }\n ready();\n if (closer)\n this.fsw._addPathCloser(path, closer);\n return false;\n }\n catch (error) {\n if (this.fsw._handleError(error)) {\n ready();\n return path;\n }\n }\n }\n}\n","import type { Application, Request, Response } from \"express\";\r\nimport chokidar from \"chokidar\";\r\nimport path from \"path\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\nexport interface HotReloadOptions {\r\n app: Application;\r\n appDir: string; // carpeta de la app (ej: apps/example/app)\r\n route?: string; // endpoint SSE, default: \"/__fw/hot\"\r\n waitForBuild?: () => Promise<void>; // Function to wait for client bundle to finish building\r\n onFileChange?: (filePath: string) => void | Promise<void>; // Callback when file changes\r\n}\r\n\r\n/**\r\n * Sets up an SSE endpoint and file watcher on appDir.\r\n * Each change triggers a reload to connected clients.\r\n *\r\n * @param options - Hot reload options\r\n */\r\nexport function setupHotReload({\r\n app,\r\n appDir,\r\n route = \"/__fw/hot\",\r\n waitForBuild,\r\n onFileChange,\r\n}: HotReloadOptions) {\r\n const clients = new Set<Response>();\r\n\r\n app.get(route, (req: Request, res: Response) => {\r\n res.setHeader(\"Content-Type\", \"text/event-stream\");\r\n res.setHeader(\"Cache-Control\", \"no-cache\");\r\n res.setHeader(\"Connection\", \"keep-alive\");\r\n res.flushHeaders?.();\r\n\r\n res.write(`event: ping\\ndata: connected\\n\\n`);\r\n clients.add(res);\r\n\r\n req.on(\"close\", () => {\r\n clients.delete(res);\r\n });\r\n });\r\n\r\n const watcher = chokidar.watch(appDir, {\r\n ignoreInitial: true,\r\n ignored: [\"**/node_modules/**\", `**/${BUILD_FOLDER_NAME}/**`, \"**/.git/**\"],\r\n });\r\n\r\n async function broadcastReload(reason: string, filePath: string) {\r\n const rel = path.relative(appDir, filePath);\r\n console.log(`[hot-reload] ${reason}: ${rel}`);\r\n\r\n // Call onFileChange callback if provided (e.g., to reload routes manifest)\r\n if (onFileChange) {\r\n try {\r\n await onFileChange(filePath);\r\n } catch (error) {\r\n console.warn(\"[hot-reload] Error in onFileChange callback:\", error);\r\n }\r\n }\r\n\r\n // Wait for client bundle to finish building before sending reload event\r\n if (waitForBuild) {\r\n try {\r\n console.log(\"[hot-reload] Waiting for client bundle to finish...\");\r\n await waitForBuild();\r\n console.log(\"[hot-reload] Client bundle ready, sending reload event\");\r\n } catch (error) {\r\n console.warn(\"[hot-reload] Error waiting for build:\", error);\r\n // Continue anyway, don't block reload\r\n }\r\n }\r\n\r\n for (const res of clients) {\r\n res.write(`event: message\\ndata: reload:${rel}\\n\\n`);\r\n }\r\n }\r\n\r\n watcher\r\n .on(\"add\", (filePath) => broadcastReload(\"add\", filePath))\r\n .on(\"change\", (filePath) => broadcastReload(\"change\", filePath))\r\n .on(\"unlink\", (filePath) => broadcastReload(\"unlink\", filePath));\r\n}\r\n","import path from \"path\";\r\n\r\n/**\r\n * Clears the require cache for files in the app directory.\r\n *\r\n * @param appDir - App directory path\r\n */\r\nexport function clearAppRequireCache(appDir: string) {\r\n const appDirNormalized = path.resolve(appDir);\r\n\r\n for (const id of Object.keys(require.cache)) {\r\n if (id.startsWith(appDirNormalized)) {\r\n delete require.cache[id];\r\n }\r\n }\r\n}\r\n","/**\r\n * Security utilities for input sanitization.\r\n */\r\n\r\n/**\r\n * Sanitizes a string by removing potentially dangerous characters.\r\n * Basic sanitization - for production, consider using a library like DOMPurify.\r\n * \r\n * @param input - String to sanitize\r\n * @returns Sanitized string\r\n */\r\nexport function sanitizeString(input: string): string {\r\n if (typeof input !== \"string\") {\r\n return String(input);\r\n }\r\n\r\n // Remove null bytes\r\n let sanitized = input.replace(/\\0/g, \"\");\r\n\r\n // Remove control characters except newlines and tabs\r\n sanitized = sanitized.replace(/[\\x00-\\x08\\x0B-\\x0C\\x0E-\\x1F\\x7F]/g, \"\");\r\n\r\n return sanitized;\r\n}\r\n\r\n/**\r\n * Sanitizes an object by recursively sanitizing all string values.\r\n * \r\n * @param obj - Object to sanitize\r\n * @returns Sanitized object\r\n */\r\nexport function sanitizeObject<T extends Record<string, any>>(obj: T): T {\r\n if (obj === null || obj === undefined) {\r\n return obj;\r\n }\r\n\r\n if (typeof obj !== \"object\") {\r\n return typeof obj === \"string\" ? (sanitizeString(obj) as any) : obj;\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map((item) => sanitizeObject(item)) as any;\r\n }\r\n\r\n const sanitized: any = {};\r\n for (const key in obj) {\r\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\r\n const value = obj[key];\r\n if (typeof value === \"string\") {\r\n sanitized[key] = sanitizeString(value);\r\n } else if (typeof value === \"object\" && value !== null) {\r\n sanitized[key] = sanitizeObject(value);\r\n } else {\r\n sanitized[key] = value;\r\n }\r\n }\r\n }\r\n\r\n return sanitized;\r\n}\r\n\r\n/**\r\n * Sanitizes route parameters.\r\n * \r\n * @param params - Route parameters object\r\n * @returns Sanitized parameters\r\n */\r\nexport function sanitizeParams<T extends Record<string, string | string[]>>(\r\n params: T\r\n): T {\r\n const sanitized: any = {};\r\n for (const key in params) {\r\n if (Object.prototype.hasOwnProperty.call(params, key)) {\r\n const value = params[key];\r\n if (Array.isArray(value)) {\r\n sanitized[key] = value.map((v) => sanitizeString(String(v)));\r\n } else {\r\n sanitized[key] = sanitizeString(String(value));\r\n }\r\n }\r\n }\r\n return sanitized;\r\n}\r\n\r\n/**\r\n * Sanitizes query parameters.\r\n * \r\n * @param query - Query parameters object\r\n * @returns Sanitized query parameters\r\n */\r\nexport function sanitizeQuery<T extends Record<string, any>>(query: T): T {\r\n return sanitizeObject(query);\r\n}\r\n\r\n","import rateLimit from \"express-rate-limit\";\r\n\r\nexport interface RateLimitConfig {\r\n windowMs?: number;\r\n max?: number;\r\n message?: string;\r\n standardHeaders?: boolean;\r\n legacyHeaders?: boolean;\r\n skipSuccessfulRequests?: boolean;\r\n skipFailedRequests?: boolean;\r\n}\r\n\r\n/**\r\n * Creates a rate limiter middleware with configurable options.\r\n * \r\n * @param config - Rate limiting configuration\r\n * @returns Express rate limit middleware\r\n */\r\nexport function createRateLimiter(config: RateLimitConfig = {}) {\r\n const {\r\n windowMs = 15 * 60 * 1000, // 15 minutes\r\n max = 100, // limit each IP to 100 requests per windowMs\r\n message = \"Too many requests from this IP, please try again later.\",\r\n standardHeaders = true,\r\n legacyHeaders = false,\r\n skipSuccessfulRequests = false,\r\n skipFailedRequests = false,\r\n } = config;\r\n\r\n return rateLimit({\r\n windowMs,\r\n max,\r\n message: {\r\n error: message,\r\n },\r\n standardHeaders,\r\n legacyHeaders,\r\n skipSuccessfulRequests,\r\n skipFailedRequests,\r\n });\r\n}\r\n\r\n/**\r\n * Default rate limiter for general API routes.\r\n * Limits: 100 requests per 15 minutes per IP\r\n */\r\nexport const defaultRateLimiter = createRateLimiter({\r\n windowMs: 15 * 60 * 1000, // 15 minutes\r\n max: 100,\r\n message: \"Too many requests from this IP, please try again later.\",\r\n});\r\n\r\n/**\r\n * Strict rate limiter for authentication and sensitive endpoints.\r\n * Limits: 5 requests per 15 minutes per IP\r\n */\r\nexport const strictRateLimiter = createRateLimiter({\r\n windowMs: 15 * 60 * 1000, // 15 minutes\r\n max: 5,\r\n message: \"Too many authentication attempts, please try again later.\",\r\n});\r\n\r\n/**\r\n * Lenient rate limiter for public pages.\r\n * Limits: 200 requests per 15 minutes per IP\r\n */\r\nexport const lenientRateLimiter = createRateLimiter({\r\n windowMs: 15 * 60 * 1000, // 15 minutes\r\n max: 200,\r\n message: \"Too many requests from this IP, please try again later.\",\r\n});\r\n\r\n","import { ApiRoute } from \"@router/index.types\";\nimport { strictRateLimiter, defaultRateLimiter, lenientRateLimiter } from \"./rate-limit\";\n\n/**\n * Determines if a route path matches any of the strict patterns.\n * \n * @param path - Route path to check\n * @param patterns - Array of patterns to match against\n * @returns True if path matches any pattern\n */\nexport function matchesStrictPattern(\n path: string,\n patterns: string[]\n): boolean {\n for (const pattern of patterns) {\n // Convert pattern to regex\n // ** matches any path segment\n // * matches single path segment\n const regexPattern = pattern\n .replace(/\\*\\*/g, \".*\") // ** -> .*\n .replace(/\\*/g, \"[^/]*\") // * -> [^/]*\n .replace(/\\//g, \"\\\\/\"); // / -> \\/\n\n const regex = new RegExp(`^${regexPattern}$`);\n if (regex.test(path)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Checks if a middleware is a rate limiter.\n * \n * @param mw - Middleware to check\n * @returns True if middleware is a rate limiter\n */\nfunction isRateLimiter(mw: any): boolean {\n if (!mw) return false;\n \n // Check if it's one of our known rate limiters\n if (mw === strictRateLimiter || mw === defaultRateLimiter || mw === lenientRateLimiter) {\n return true;\n }\n \n // Check for express-rate-limit signature\n // Rate limiters from express-rate-limit have specific properties\n if (typeof mw === 'function' && mw.name && mw.name.includes('rateLimit')) {\n return true;\n }\n \n // Check if middleware function has rate limit properties\n if (mw && typeof mw === 'function' && (mw as any).skip || (mw as any).resetKey) {\n return true;\n }\n \n return false;\n}\n\n/**\n * Gets the appropriate rate limiter for a route based on configuration.\n * \n * @param route - API route\n * @param strictPatterns - Patterns that should use strict rate limiting\n * @returns Rate limiter middleware or null if route already has rate limiting\n */\nexport function getAutoRateLimiter(\n route: ApiRoute,\n strictPatterns: string[] = []\n): any | null {\n // If route already has rate limiting middleware, don't add another\n const hasRateLimiter = route.middlewares?.some(isRateLimiter) ||\n Object.values(route.methodMiddlewares || {}).some((mws: any[]) => \n mws?.some(isRateLimiter)\n );\n\n if (hasRateLimiter) {\n return null; // Route already has rate limiting\n }\n\n // Check if route matches strict patterns\n if (strictPatterns.length > 0 && matchesStrictPattern(route.pattern, strictPatterns)) {\n console.log(`[rate-limit] Applying strict rate limiter to route: ${route.pattern}`);\n return strictRateLimiter;\n }\n\n // Default: no auto rate limiting (global rate limiter already applied)\n return null;\n}\n\n","import pino from \"pino\";\r\nimport type { Logger as PinoLogger } from \"pino\";\r\nimport type { Request, Response } from \"express\";\r\n\r\nexport type LogLevel = \"fatal\" | \"error\" | \"warn\" | \"info\" | \"debug\" | \"trace\";\r\n\r\nexport interface LoggerContext {\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface LoggerOptions {\r\n level?: LogLevel;\r\n enabled?: boolean;\r\n pretty?: boolean;\r\n destination?: pino.DestinationStream;\r\n}\r\n\r\n/**\r\n * Creates a Pino logger instance with appropriate configuration for dev/prod.\r\n * \r\n * - Development: Pretty printed with colors via pino-pretty\r\n * - Production: JSON structured output for log aggregation\r\n */\r\nfunction createLogger(options: LoggerOptions = {}): PinoLogger {\r\n const {\r\n level = (process.env.LOG_LEVEL as LogLevel) || (process.env.NODE_ENV === \"development\" ? \"debug\" : \"info\"),\r\n enabled = process.env.LOG_ENABLED !== \"false\",\r\n pretty = process.env.NODE_ENV === \"development\",\r\n destination,\r\n } = options;\r\n\r\n if (!enabled) {\r\n // Return a no-op logger\r\n return pino({ enabled: false });\r\n }\r\n\r\n const baseConfig: pino.LoggerOptions = {\r\n level,\r\n base: {\r\n name: \"@lolyjs/core\",\r\n env: process.env.NODE_ENV || \"development\",\r\n },\r\n timestamp: pino.stdTimeFunctions.isoTime,\r\n formatters: {\r\n level: (label) => {\r\n return { level: label };\r\n },\r\n },\r\n };\r\n\r\n // In development, use pino-pretty for colored, human-readable output\r\n if (pretty && !destination) {\r\n try {\r\n // Dynamic import to avoid bundling pino-pretty in production\r\n const pinoPretty = require(\"pino-pretty\");\r\n return pino(\r\n baseConfig,\r\n pinoPretty({\r\n colorize: true,\r\n translateTime: \"HH:MM:ss Z\",\r\n ignore: \"pid,hostname\",\r\n singleLine: false,\r\n messageFormat: \"[{module}] {msg}\",\r\n })\r\n );\r\n } catch (e) {\r\n // Fallback if pino-pretty is not available\r\n console.warn(\"[logger] pino-pretty not available, using default formatter\");\r\n }\r\n }\r\n\r\n // Production: structured JSON logging\r\n return destination ? pino(baseConfig, destination) : pino(baseConfig);\r\n}\r\n\r\n// Singleton logger instance\r\nlet loggerInstance: PinoLogger | null = null;\r\n\r\n/**\r\n * Gets or creates the singleton logger instance.\r\n */\r\nexport function getLogger(options?: LoggerOptions): PinoLogger {\r\n if (!loggerInstance) {\r\n loggerInstance = createLogger(options);\r\n }\r\n return loggerInstance;\r\n}\r\n\r\n/**\r\n * Sets a custom logger instance (useful for testing or custom configuration).\r\n */\r\nexport function setLogger(customLogger: PinoLogger): void {\r\n loggerInstance = customLogger;\r\n}\r\n\r\n/**\r\n * Resets the logger instance (useful for testing).\r\n */\r\nexport function resetLogger(): void {\r\n loggerInstance = null;\r\n}\r\n\r\n/**\r\n * Logger class wrapper for easier usage with context.\r\n */\r\nexport class Logger {\r\n private pino: PinoLogger;\r\n private context: LoggerContext;\r\n\r\n constructor(logger?: PinoLogger, context: LoggerContext = {}) {\r\n this.pino = logger || getLogger();\r\n this.context = context;\r\n }\r\n\r\n /**\r\n * Creates a child logger with additional context.\r\n */\r\n child(context: LoggerContext): Logger {\r\n return new Logger(this.pino.child(context), { ...this.context, ...context });\r\n }\r\n\r\n /**\r\n * Logs a fatal error (application should terminate).\r\n */\r\n fatal(message: string, context?: LoggerContext): void {\r\n this.pino.fatal({ ...this.context, ...context }, message);\r\n }\r\n\r\n /**\r\n * Logs an error.\r\n */\r\n error(message: string, error?: Error | unknown, context?: LoggerContext): void {\r\n const errorContext: LoggerContext = { ...this.context, ...context };\r\n \r\n if (error instanceof Error) {\r\n errorContext.error = {\r\n name: error.name,\r\n message: error.message,\r\n stack: error.stack,\r\n };\r\n } else if (error) {\r\n errorContext.error = error;\r\n }\r\n\r\n this.pino.error(errorContext, message);\r\n }\r\n\r\n /**\r\n * Logs a warning.\r\n */\r\n warn(message: string, context?: LoggerContext): void {\r\n this.pino.warn({ ...this.context, ...context }, message);\r\n }\r\n\r\n /**\r\n * Logs informational message.\r\n */\r\n info(message: string, context?: LoggerContext): void {\r\n this.pino.info({ ...this.context, ...context }, message);\r\n }\r\n\r\n /**\r\n * Logs a debug message (only in development or when level is debug).\r\n */\r\n debug(message: string, context?: LoggerContext): void {\r\n this.pino.debug({ ...this.context, ...context }, message);\r\n }\r\n\r\n /**\r\n * Logs a trace message (most verbose).\r\n */\r\n trace(message: string, context?: LoggerContext): void {\r\n this.pino.trace({ ...this.context, ...context }, message);\r\n }\r\n}\r\n\r\n/**\r\n * Default logger instance.\r\n */\r\nexport const logger = new Logger();\r\n\r\n/**\r\n * Creates a logger for a specific module/component.\r\n */\r\nexport function createModuleLogger(module: string, context?: LoggerContext): Logger {\r\n return logger.child({ module, ...context });\r\n}\r\n\r\n/**\r\n * Generates a unique request ID for request tracking.\r\n */\r\nexport function generateRequestId(): string {\r\n return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\r\n}\r\n\r\n/**\r\n * Default paths to ignore from request logging (static assets, favicon, etc.)\r\n */\r\nconst DEFAULT_IGNORED_PATHS = [\r\n /^\\/static\\//, // Static assets\r\n /^\\/favicon\\.ico$/i, // Favicon\r\n /^\\/_next\\//, // Next.js internals (if used)\r\n /^\\/\\.well-known\\//, // Well-known paths\r\n /^\\/__webpack/, // Webpack dev server\r\n /^\\/sockjs-node/, // Hot reload websocket\r\n];\r\n\r\n/**\r\n * Checks if a path should be ignored from logging.\r\n */\r\nfunction shouldIgnorePath(path: string, ignoredPaths: (string | RegExp)[]): boolean {\r\n return ignoredPaths.some(pattern => {\r\n if (typeof pattern === \"string\") {\r\n return path === pattern || path.startsWith(pattern);\r\n }\r\n return pattern.test(path);\r\n });\r\n}\r\n\r\n/**\r\n * Express middleware for request logging.\r\n * Adds request ID to res.locals and logs incoming requests.\r\n */\r\nexport function requestLoggerMiddleware(options: {\r\n logger?: Logger;\r\n logRequests?: boolean;\r\n logResponses?: boolean;\r\n ignorePaths?: (string | RegExp)[];\r\n logStaticAssets?: boolean;\r\n} = {}) {\r\n const {\r\n logger: customLogger = logger,\r\n logRequests = true,\r\n logResponses = true,\r\n ignorePaths = DEFAULT_IGNORED_PATHS,\r\n logStaticAssets = false,\r\n } = options;\r\n\r\n return (req: Request, res: Response, next: () => void): void => {\r\n // Generate or use existing request ID\r\n const requestId = (req.headers[\"x-request-id\"] as string) || generateRequestId();\r\n (res.locals as any).requestId = requestId;\r\n\r\n // Add request ID to response headers\r\n res.setHeader(\"X-Request-ID\", requestId);\r\n\r\n // Check if we should ignore this path\r\n const shouldIgnore = !logStaticAssets && shouldIgnorePath(req.path, ignorePaths);\r\n\r\n // Create request-scoped logger (always available for handlers, minimal context to avoid duplication)\r\n const reqLogger = customLogger.child({\r\n requestId,\r\n method: req.method,\r\n path: req.path,\r\n });\r\n\r\n // Store logger in request for use in handlers (always available)\r\n (req as any).logger = reqLogger;\r\n\r\n // Log incoming request (only if not ignored and enabled)\r\n if (logRequests && !shouldIgnore) {\r\n reqLogger.debug(`${req.method} ${req.path}`, {\r\n query: Object.keys(req.query).length > 0 ? req.query : undefined,\r\n });\r\n }\r\n\r\n // Log response when finished (only if not ignored)\r\n if (logResponses && !shouldIgnore) {\r\n const startTime = Date.now();\r\n \r\n res.on(\"finish\", () => {\r\n const duration = Date.now() - startTime;\r\n // Only log errors and warnings by default, or successful requests if explicitly enabled\r\n const shouldLogSuccess = logRequests === true; // Only if logRequests is explicitly true\r\n \r\n if (res.statusCode >= 500) {\r\n reqLogger.error(`${req.method} ${req.path} ${res.statusCode}`, {\r\n statusCode: res.statusCode,\r\n duration: `${duration}ms`,\r\n });\r\n } else if (res.statusCode >= 400) {\r\n reqLogger.warn(`${req.method} ${req.path} ${res.statusCode}`, {\r\n statusCode: res.statusCode,\r\n duration: `${duration}ms`,\r\n });\r\n } else if (shouldLogSuccess) {\r\n // Only log successful requests if explicitly enabled\r\n reqLogger.debug(`${req.method} ${req.path} ${res.statusCode}`, {\r\n statusCode: res.statusCode,\r\n duration: `${duration}ms`,\r\n });\r\n }\r\n });\r\n }\r\n\r\n next();\r\n };\r\n}\r\n\r\n/**\r\n * Gets the logger from the request object (set by requestLoggerMiddleware).\r\n */\r\nexport function getRequestLogger(req: Request): Logger {\r\n return (req as any).logger || logger.child({ requestId: \"unknown\" });\r\n}\r\n\r\n","import { Request, Response } from \"express\";\r\nimport { ApiContext, ApiRoute, matchApiRoute } from \"@router/index\";\r\nimport { sanitizeParams, sanitizeQuery } from \"@security/sanitize\";\r\nimport { getAutoRateLimiter } from \"@server/middleware/auto-rate-limit\";\r\nimport { getRequestLogger, createModuleLogger } from \"@logger/index\";\r\n\r\nexport interface HandleApiRequestOptions {\r\n apiRoutes: ApiRoute[];\r\n urlPath: string;\r\n req: Request;\r\n res: Response;\r\n env?: \"dev\" | \"prod\";\r\n strictRateLimitPatterns?: string[];\r\n}\r\n\r\n/**\r\n * Handles an API route request.\r\n * Unifies logic between dev and prod.\r\n *\r\n * @param options - Request handling options\r\n */\r\nexport async function handleApiRequest(\r\n options: HandleApiRequestOptions\r\n): Promise<void> {\r\n const { apiRoutes, urlPath, req, res, env = \"dev\" } = options;\r\n\r\n const matched = matchApiRoute(apiRoutes, urlPath);\r\n\r\n if (!matched) {\r\n res.status(404).json({ error: \"Not Found\" });\r\n return;\r\n }\r\n\r\n const { route, params } = matched;\r\n const method = req.method.toUpperCase();\r\n const handler = route.handlers[method];\r\n\r\n if (!handler) {\r\n res.setHeader(\"Allow\", Object.keys(route.handlers).join(\", \"));\r\n res.status(405).json({ error: \"Method Not Allowed\" });\r\n return;\r\n }\r\n\r\n // Security: Sanitize route parameters and query parameters\r\n const sanitizedParams = sanitizeParams(params);\r\n const sanitizedQuery = sanitizeQuery(req.query as Record<string, any>);\r\n\r\n const ctx: ApiContext = {\r\n req,\r\n res,\r\n Response: (body: any = {}, status = 200) => res.status(status).json(body),\r\n NotFound: (body: any = {}) => res.status(404).json(body),\r\n params: sanitizedParams,\r\n pathname: urlPath,\r\n locals: {},\r\n };\r\n\r\n // Update req.query with sanitized values\r\n req.query = sanitizedQuery as any;\r\n\r\n try {\r\n // Auto-apply rate limiting if route matches strict patterns and doesn't already have one\r\n const autoRateLimiter = getAutoRateLimiter(\r\n route,\r\n options.strictRateLimitPatterns\r\n );\r\n \r\n const reqLogger = getRequestLogger(req);\r\n \r\n if (autoRateLimiter) {\r\n reqLogger.debug(\"Auto rate limiter applied\", {\r\n route: route.pattern,\r\n patterns: options.strictRateLimitPatterns,\r\n });\r\n }\r\n\r\n const globalMws = route.middlewares ?? [];\r\n const perMethodMws = route.methodMiddlewares?.[method] ?? [];\r\n \r\n // Prepend auto rate limiter if applicable\r\n const chain = autoRateLimiter \r\n ? [autoRateLimiter, ...globalMws, ...perMethodMws]\r\n : [...globalMws, ...perMethodMws];\r\n\r\n for (const mw of chain) {\r\n // Check if this is an express-rate-limit middleware (expects req, res, next)\r\n // express-rate-limit middlewares have specific properties\r\n const isExpressRateLimit = mw && typeof mw === 'function' && \r\n ((mw as any).skip || (mw as any).resetKey || mw.name?.includes('rateLimit'));\r\n \r\n if (isExpressRateLimit) {\r\n // Call express-rate-limit middleware with (req, res, next)\r\n await new Promise<void>((resolve, reject) => {\r\n const next = (err?: any) => {\r\n if (err) reject(err);\r\n else resolve();\r\n };\r\n try {\r\n const result = mw(req, res, next);\r\n // If it returns a promise, wait for it\r\n if (result && typeof result.then === 'function') {\r\n result.then(() => resolve()).catch(reject);\r\n }\r\n } catch (err) {\r\n reject(err);\r\n }\r\n });\r\n } else {\r\n // Call framework middleware with (ctx, next)\r\n await Promise.resolve(mw(ctx, async () => {}));\r\n }\r\n \r\n if (res.headersSent) {\r\n return;\r\n }\r\n }\r\n\r\n await handler(ctx);\r\n } catch (err) {\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"API handler error\", err, {\r\n route: route.pattern,\r\n method,\r\n env,\r\n });\r\n if (!res.headersSent) {\r\n res.status(500).json({ error: \"Internal Server Error\" });\r\n }\r\n }\r\n}\r\n","import { Request, Response } from \"express\";\r\nimport { renderToPipeableStream } from \"react-dom/server\";\r\nimport {\r\n ServerContext,\r\n LoadedRoute,\r\n LoaderResult,\r\n matchRoute,\r\n} from \"@router/index\";\r\nimport {\r\n buildAppTree,\r\n buildInitialData,\r\n createDocumentTree,\r\n} from \"@rendering/index\";\r\nimport { runRouteMiddlewares } from \"./middleware\";\r\nimport { runRouteLoader } from \"./loader\";\r\nimport { handleDataResponse, handleRedirect, handleNotFound } from \"./response\";\r\nimport { tryServeSsgHtml, tryServeSsgData } from \"./ssg\";\r\nimport { ERROR_CHUNK_KEY, STATIC_PATH } from \"@constants/globals\";\r\nimport { getClientJsPath, getClientCssPath, loadAssetManifest } from \"@build/utils\";\r\nimport { sanitizeParams } from \"@security/sanitize\";\r\nimport { getRequestLogger, createModuleLogger } from \"@logger/index\";\r\n\r\nexport interface HandlePageRequestOptions {\r\n routes: LoadedRoute[];\r\n notFoundPage: LoadedRoute | null;\r\n errorPage: LoadedRoute | null;\r\n routeChunks: Record<string, string>;\r\n urlPath: string;\r\n req: Request;\r\n res: Response;\r\n env?: \"dev\" | \"prod\";\r\n ssgOutDir?: string;\r\n theme?: string;\r\n projectRoot?: string;\r\n}\r\n\r\n/**\r\n * Determines if a request is a data request (JSON).\r\n *\r\n * @param req - Express request object\r\n * @returns True if the request is a data request\r\n */\r\nexport function isDataRequest(req: Request): boolean {\r\n return (\r\n (req.query && (req.query as any).__fw_data === \"1\") ||\r\n req.headers[\"x-fw-data\"] === \"1\"\r\n );\r\n}\r\n\r\n/**\r\n * Handles a page route request.\r\n * Unifies logic between dev and prod (with SSG support in prod).\r\n *\r\n * @param options - Request handling options\r\n */\r\nexport async function handlePageRequest(\r\n options: HandlePageRequestOptions\r\n): Promise<void> {\r\n try {\r\n await handlePageRequestInternal(options);\r\n } catch (error) {\r\n const { errorPage, req, res, routeChunks, theme, projectRoot } = options;\r\n const reqLogger = getRequestLogger(req);\r\n \r\n if (errorPage) {\r\n await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env);\r\n } else {\r\n reqLogger.error(\"Unhandled error in page request\", error, {\r\n urlPath: options.urlPath,\r\n hasErrorPage: !!errorPage,\r\n });\r\n if (!res.headersSent) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n res.end(\"<!doctype html><h1>Internal Server Error</h1>\");\r\n }\r\n }\r\n }\r\n}\r\n\r\nasync function handlePageRequestInternal(\r\n options: HandlePageRequestOptions\r\n): Promise<void> {\r\n const {\r\n routes,\r\n notFoundPage,\r\n errorPage,\r\n routeChunks,\r\n urlPath,\r\n req,\r\n res,\r\n env = \"dev\",\r\n ssgOutDir,\r\n theme,\r\n projectRoot,\r\n } = options;\r\n\r\n // Get asset paths - in dev, always use non-hashed names; in prod, use manifest if available\r\n const clientJsPath = env === \"dev\" \r\n ? \"/static/client.js\" \r\n : (projectRoot ? getClientJsPath(projectRoot) : \"/static/client.js\");\r\n const clientCssPath = env === \"dev\"\r\n ? \"/static/client.css\"\r\n : (projectRoot ? getClientCssPath(projectRoot) : \"/static/client.css\");\r\n const assetManifest = env === \"prod\" && projectRoot ? loadAssetManifest(projectRoot) : null;\r\n\r\n const isDataReq = isDataRequest(req);\r\n\r\n if (env === \"prod\" && ssgOutDir) {\r\n if (isDataReq) {\r\n if (tryServeSsgData(res, ssgOutDir, urlPath)) {\r\n return;\r\n }\r\n } else {\r\n if (tryServeSsgHtml(res, ssgOutDir, urlPath)) {\r\n return;\r\n }\r\n }\r\n }\r\n\r\n const matched = matchRoute(routes, urlPath);\r\n\r\n if (!matched) {\r\n if (notFoundPage) {\r\n const ctx: ServerContext & { theme?: string } = {\r\n req,\r\n res,\r\n params: {},\r\n pathname: urlPath,\r\n locals: {},\r\n };\r\n\r\n let loaderResult = await runRouteLoader(notFoundPage, ctx);\r\n // Automatically inject theme from server into loaderResult if not already set\r\n if (!loaderResult.theme) {\r\n loaderResult.theme = theme;\r\n }\r\n \r\n const initialData = buildInitialData(urlPath, {}, loaderResult);\r\n const appTree = buildAppTree(notFoundPage, {}, initialData.props);\r\n initialData.notFound = true;\r\n \r\n // Get nonce from res.locals (set by Helmet for CSP)\r\n const nonce = (res.locals as any).nonce || undefined;\r\n\r\n const documentTree = createDocumentTree({\r\n appTree,\r\n initialData,\r\n meta: loaderResult.metadata ?? null,\r\n titleFallback: \"Not found\",\r\n descriptionFallback: \"Loly demo\",\r\n chunkHref: null,\r\n theme,\r\n clientJsPath,\r\n clientCssPath,\r\n nonce,\r\n });\r\n \r\n let didError = false;\r\n \r\n const { pipe, abort } = renderToPipeableStream(documentTree, {\r\n onShellReady() {\r\n if (didError || res.headersSent) return;\r\n \r\n res.statusCode = 404;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n pipe(res);\r\n },\r\n onShellError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"SSR shell error\", err, { route: \"not-found\" });\r\n if (!res.headersSent && errorPage) {\r\n renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);\r\n } else if (!res.headersSent) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n res.end(\"<!doctype html><h1>Internal Server Error</h1>\");\r\n }\r\n abort();\r\n },\r\n onError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"SSR error\", err, { route: \"not-found\" });\r\n },\r\n });\r\n \r\n req.on(\"close\", () => abort());\r\n return;\r\n }\r\n\r\n handleNotFound(res, urlPath);\r\n return;\r\n }\r\n\r\n const { route, params } = matched;\r\n\r\n // Security: Sanitize route parameters\r\n const sanitizedParams = sanitizeParams(params);\r\n\r\n const ctx: ServerContext = {\r\n req,\r\n res,\r\n params: sanitizedParams,\r\n pathname: urlPath,\r\n locals: {},\r\n };\r\n\r\n await runRouteMiddlewares(route, ctx);\r\n if (res.headersSent) {\r\n return;\r\n }\r\n\r\n let loaderResult: LoaderResult;\r\n try {\r\n loaderResult = await runRouteLoader(route, ctx);\r\n // Automatically inject theme from server into loaderResult if not already set\r\n if (!loaderResult.theme) {\r\n loaderResult.theme = theme;\r\n }\r\n } catch (error) {\r\n // If loader throws, handle error appropriately\r\n if (isDataReq) {\r\n // For data requests, return error JSON\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\r\n res.end(JSON.stringify({ error: true, message: String(error) }));\r\n return;\r\n } else {\r\n // For HTML requests, render error page\r\n if (errorPage) {\r\n await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env);\r\n return;\r\n } else {\r\n throw error; // Re-throw to be caught by outer try-catch\r\n }\r\n }\r\n }\r\n\r\n if (isDataReq) {\r\n handleDataResponse(res, loaderResult, theme);\r\n return;\r\n }\r\n\r\n if (loaderResult.redirect) {\r\n handleRedirect(res, loaderResult.redirect);\r\n return;\r\n }\r\n\r\n if (loaderResult.notFound) {\r\n if (isDataReq) {\r\n res.status(200).json({ notFound: true });\r\n } else {\r\n handleNotFound(res, urlPath);\r\n }\r\n return;\r\n }\r\n\r\n const initialData = buildInitialData(urlPath, params, loaderResult);\r\n const appTree = buildAppTree(route, params, initialData.props);\r\n\r\n // Get chunk href with hash if available\r\n const chunkName = routeChunks[route.pattern];\r\n let chunkHref: string | null = null;\r\n if (chunkName != null) {\r\n if (assetManifest && assetManifest.chunks[chunkName]) {\r\n // Use hashed filename from manifest\r\n chunkHref = `${STATIC_PATH}/${assetManifest.chunks[chunkName]}`;\r\n } else {\r\n // Fallback to non-hashed filename\r\n chunkHref = `${STATIC_PATH}/${chunkName}.js`;\r\n }\r\n }\r\n\r\n // Get nonce from res.locals (set by Helmet for CSP)\r\n const nonce = (res.locals as any).nonce || undefined;\r\n\r\n const documentTree = createDocumentTree({\r\n appTree,\r\n initialData,\r\n meta: loaderResult.metadata,\r\n titleFallback: \"Loly framework\",\r\n descriptionFallback: \"Loly demo\",\r\n chunkHref,\r\n theme,\r\n clientJsPath,\r\n clientCssPath,\r\n nonce,\r\n });\r\n\r\n let didError = false;\r\n\r\n const { pipe, abort } = renderToPipeableStream(documentTree, {\r\n onShellReady() {\r\n if (didError || res.headersSent) {\r\n return;\r\n }\r\n\r\n res.statusCode = 200;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n pipe(res);\r\n },\r\n\r\n onShellError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"SSR shell error\", err, { route: matched?.route?.pattern || \"unknown\" });\r\n\r\n if (!res.headersSent && errorPage) {\r\n renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);\r\n } else if (!res.headersSent) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n res.end(\"<!doctype html><h1>Internal Server Error</h1>\");\r\n }\r\n\r\n abort();\r\n },\r\n\r\n onError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"SSR error\", err, { route: matched?.route?.pattern || \"unknown\" });\r\n },\r\n });\r\n\r\n req.on(\"close\", () => {\r\n abort();\r\n });\r\n}\r\n\r\n/**\r\n * Renders the error page when an error occurs using streaming.\r\n *\r\n * @param errorPage - Error page route\r\n * @param req - Express request\r\n * @param res - Express response\r\n * @param error - Error that occurred\r\n * @param routeChunks - Route chunks mapping\r\n */\r\nasync function renderErrorPageWithStream(\r\n errorPage: LoadedRoute,\r\n req: Request,\r\n res: Response,\r\n error: unknown,\r\n routeChunks: Record<string, string>,\r\n theme?: string,\r\n projectRoot?: string,\r\n env: \"dev\" | \"prod\" = \"dev\",\r\n): Promise<void> {\r\n try {\r\n const isDataReq = isDataRequest(req);\r\n \r\n const ctx: ServerContext = {\r\n req,\r\n res,\r\n params: { error: String(error) },\r\n pathname: req.path,\r\n locals: { error },\r\n };\r\n\r\n let loaderResult = await runRouteLoader(errorPage, ctx);\r\n // Automatically inject theme from server into loaderResult if not already set\r\n if (!loaderResult.theme && theme) {\r\n loaderResult.theme = theme;\r\n }\r\n\r\n const initialData = buildInitialData(req.path, { error: String(error) }, loaderResult);\r\n initialData.error = true;\r\n \r\n // If this is a data request, return JSON instead of HTML\r\n if (isDataReq) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\r\n res.end(JSON.stringify({\r\n error: true,\r\n message: String(error),\r\n props: initialData.props,\r\n metadata: loaderResult.metadata ?? null,\r\n theme: loaderResult.theme ?? theme ?? null,\r\n }));\r\n return;\r\n }\r\n const appTree = buildAppTree(errorPage, { error: String(error) }, initialData.props);\r\n\r\n // Get asset paths with hashes (if in production and manifest exists)\r\n // In dev, always use non-hashed names; in prod, use manifest if available\r\n const clientJsPath = env === \"dev\"\r\n ? \"/static/client.js\"\r\n : (projectRoot ? getClientJsPath(projectRoot) : \"/static/client.js\");\r\n const clientCssPath = env === \"dev\"\r\n ? \"/static/client.css\"\r\n : (projectRoot ? getClientCssPath(projectRoot) : \"/static/client.css\");\r\n const assetManifest = env === \"prod\" && projectRoot ? loadAssetManifest(projectRoot) : null;\r\n\r\n const chunkName = routeChunks[ERROR_CHUNK_KEY];\r\n let chunkHref: string | null = null;\r\n if (chunkName != null) {\r\n if (assetManifest && assetManifest.chunks[chunkName]) {\r\n chunkHref = `${STATIC_PATH}/${assetManifest.chunks[chunkName]}`;\r\n } else {\r\n chunkHref = `${STATIC_PATH}/${chunkName}.js`;\r\n }\r\n }\r\n\r\n // Get nonce from res.locals (set by Helmet for CSP)\r\n const nonce = (res.locals as any).nonce || undefined;\r\n\r\n const documentTree = createDocumentTree({\r\n appTree,\r\n initialData,\r\n meta: loaderResult.metadata ?? null,\r\n titleFallback: \"Error\",\r\n descriptionFallback: \"An error occurred\",\r\n chunkHref,\r\n theme,\r\n clientJsPath,\r\n clientCssPath,\r\n nonce,\r\n });\r\n\r\n let didError = false;\r\n\r\n const { pipe, abort } = renderToPipeableStream(documentTree, {\r\n onShellReady() {\r\n if (didError || res.headersSent) {\r\n return;\r\n }\r\n\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n pipe(res);\r\n },\r\n onShellError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"Error rendering error page\", err, { type: \"shellError\" });\r\n if (!res.headersSent) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n res.end(\"<!doctype html><h1>Internal Server Error</h1>\");\r\n }\r\n abort();\r\n },\r\n onError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"Error in error page\", err);\r\n },\r\n });\r\n\r\n req.on(\"close\", () => {\r\n abort();\r\n });\r\n } catch (renderErr) {\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"Error rendering error page (catch)\", renderErr, { type: \"renderException\" });\r\n if (!res.headersSent) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n res.end(\"<!doctype html><h1>Internal Server Error</h1>\");\r\n }\r\n }\r\n}\r\n\r\n","import { ServerContext, LoadedRoute } from \"@router/index\";\r\n\r\n/**\r\n * Executes route middlewares in chain.\r\n *\r\n * @param route - Route definition\r\n * @param ctx - Server context\r\n */\r\nexport async function runRouteMiddlewares(\r\n route: LoadedRoute,\r\n ctx: ServerContext\r\n): Promise<void> {\r\n for (const mw of route.middlewares) {\r\n await Promise.resolve(\r\n mw(ctx, async () => {\r\n /* no-op */\r\n })\r\n );\r\n if (ctx.res.headersSent) {\r\n return;\r\n }\r\n }\r\n}\r\n\r\n","import { ServerContext, LoadedRoute, LoaderResult } from \"@router/index\";\r\n\r\n/**\r\n * Executes the route loader if it exists.\r\n *\r\n * @param route - Route definition\r\n * @param ctx - Server context\r\n * @returns Loader result\r\n */\r\nexport async function runRouteLoader(\r\n route: LoadedRoute,\r\n ctx: ServerContext\r\n): Promise<LoaderResult> {\r\n if (!route.loader) {\r\n return { props: {} };\r\n }\r\n\r\n return await route.loader(ctx);\r\n}\r\n\r\n","import { Response } from \"express\";\r\nimport { LoaderResult } from \"@router/index\";\r\n\r\n/**\r\n * Handles data request responses (JSON).\r\n *\r\n * @param res - Express response object\r\n * @param loaderResult - Loader result\r\n * @param theme - Optional theme value to include in response\r\n */\r\nexport function handleDataResponse(\r\n res: Response,\r\n loaderResult: LoaderResult,\r\n theme?: string\r\n): void {\r\n res.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\r\n\r\n if (loaderResult.redirect) {\r\n res.statusCode = 200;\r\n res.end(JSON.stringify({ redirect: loaderResult.redirect }));\r\n return;\r\n }\r\n\r\n if (loaderResult.notFound) {\r\n res.statusCode = 404;\r\n res.end(JSON.stringify({ notFound: true }));\r\n return;\r\n }\r\n\r\n res.statusCode = 200;\r\n res.end(\r\n JSON.stringify({\r\n props: loaderResult.props ?? {},\r\n metadata: loaderResult.metadata ?? null,\r\n theme: loaderResult.theme ?? theme ?? null,\r\n })\r\n );\r\n}\r\n\r\n/**\r\n * Handles redirects for HTML responses.\r\n *\r\n * @param res - Express response object\r\n * @param redirect - Redirect configuration\r\n */\r\nexport function handleRedirect(\r\n res: Response,\r\n redirect: { destination: string; permanent?: boolean }\r\n): void {\r\n const { destination, permanent } = redirect;\r\n res.redirect(permanent ? 301 : 302, destination);\r\n}\r\n\r\n/**\r\n * Handles not found responses for HTML.\r\n *\r\n * @param res - Express response object\r\n * @param urlPath - Optional URL path for error message\r\n */\r\nexport function handleNotFound(res: Response, urlPath?: string): void {\r\n res.statusCode = 200;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n if (urlPath) {\r\n res.end(`<h1>404 - Not Found</h1><p>Route not found: ${urlPath}</p>`);\r\n } else {\r\n res.end(\"<h1>404 - Not Found</h1>\");\r\n }\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { Response } from \"express\";\r\nimport { createModuleLogger } from \"@logger/index\";\r\n\r\nconst logger = createModuleLogger(\"ssg\");\r\n\r\n/**\r\n * Gets the SSG directory path for a route.\r\n *\r\n * @param baseDir - Base SSG output directory\r\n * @param urlPath - URL path\r\n * @returns Directory path for the route\r\n */\r\nexport function getSsgDirForPath(baseDir: string, urlPath: string): string {\r\n const clean = urlPath === \"/\" ? \"\" : urlPath.replace(/^\\/+/, \"\");\r\n return path.join(baseDir, clean);\r\n}\r\n\r\n/**\r\n * Gets the SSG HTML file path for a URL.\r\n *\r\n * @param baseDir - Base SSG output directory\r\n * @param urlPath - URL path\r\n * @returns HTML file path\r\n */\r\nexport function getSsgHtmlPath(baseDir: string, urlPath: string): string {\r\n const dir = getSsgDirForPath(baseDir, urlPath);\r\n return path.join(dir, \"index.html\");\r\n}\r\n\r\n/**\r\n * Gets the SSG data.json file path for a URL.\r\n *\r\n * @param baseDir - Base SSG output directory\r\n * @param urlPath - URL path\r\n * @returns Data JSON file path\r\n */\r\nexport function getSsgDataPath(baseDir: string, urlPath: string): string {\r\n const dir = getSsgDirForPath(baseDir, urlPath);\r\n return path.join(dir, \"data.json\");\r\n}\r\n\r\n/**\r\n * Attempts to serve SSG HTML if it exists.\r\n *\r\n * @param res - Express response object\r\n * @param ssgOutDir - SSG output directory\r\n * @param urlPath - URL path\r\n * @returns True if served, false if not found\r\n */\r\nexport function tryServeSsgHtml(\r\n res: Response,\r\n ssgOutDir: string,\r\n urlPath: string\r\n): boolean {\r\n const ssgHtmlPath = getSsgHtmlPath(ssgOutDir, urlPath);\r\n\r\n if (!fs.existsSync(ssgHtmlPath)) {\r\n return false;\r\n }\r\n\r\n logger.info(\"Serving SSG HTML\", { urlPath, ssgHtmlPath });\r\n\r\n // For SSG files, we need to allow 'unsafe-inline' since we can't generate nonces\r\n // for static HTML files. Override the CSP header set by Helmet.\r\n // Note: setHeader will override any existing header with the same name\r\n res.setHeader(\r\n \"Content-Security-Policy\",\r\n \"default-src 'self'; \" +\r\n \"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; \" +\r\n \"script-src 'self' 'unsafe-inline'; \" +\r\n \"img-src 'self' data: https:; \" +\r\n \"connect-src 'self' https:; \" +\r\n \"font-src 'self' data: https://fonts.gstatic.com; \" +\r\n \"object-src 'none'; \" +\r\n \"media-src 'self' https:; \" +\r\n \"frame-src 'none';\"\r\n );\r\n\r\n res.statusCode = 200;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n const stream = fs.createReadStream(ssgHtmlPath, { encoding: \"utf-8\" });\r\n stream.pipe(res);\r\n return true;\r\n}\r\n\r\n/**\r\n * Attempts to serve SSG data.json if it exists.\r\n *\r\n * @param res - Express response object\r\n * @param ssgOutDir - SSG output directory\r\n * @param urlPath - URL path\r\n * @returns True if served, false if not found\r\n */\r\nexport function tryServeSsgData(\r\n res: Response,\r\n ssgOutDir: string,\r\n urlPath: string\r\n): boolean {\r\n const ssgDataPath = getSsgDataPath(ssgOutDir, urlPath);\r\n\r\n if (!fs.existsSync(ssgDataPath)) {\r\n return false;\r\n }\r\n\r\n try {\r\n const raw = fs.readFileSync(ssgDataPath, \"utf-8\");\r\n res.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\r\n res.status(200).end(raw);\r\n return true;\r\n } catch (err) {\r\n logger.error(\"Error reading SSG data\", err, { urlPath, ssgDataPath });\r\n return false;\r\n }\r\n}\r\n\r\n","import express from \"express\";\r\nimport { LoadedRoute, ApiRoute, WssRoute } from \"@router/index.types\";\r\nimport { handleApiRequest, handlePageRequest } from \"./handlers\";\r\nimport { RouteLoader } from \"@router/index\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\nimport { getBuildDir, type FrameworkConfig } from \"@src/config\";\r\nimport { getServerConfig } from \"@server/config\";\r\nimport path from \"path\";\r\n\r\nexport interface SetupRoutesOptions {\r\n app: express.Application;\r\n routes: LoadedRoute[];\r\n apiRoutes: ApiRoute[];\r\n notFoundPage: LoadedRoute | null;\r\n errorPage: LoadedRoute | null;\r\n isDev: boolean;\r\n projectRoot: string;\r\n routeLoader: RouteLoader;\r\n getRoutes?: () => {\r\n routes: LoadedRoute[];\r\n apiRoutes: ApiRoute[];\r\n };\r\n config?: FrameworkConfig;\r\n}\r\n\r\n/**\r\n * Sets up route handlers for the Express application.\r\n * Unifies logic between dev and prod environments.\r\n *\r\n * @param options - Route setup options\r\n */\r\nexport function setupRoutes(options: SetupRoutesOptions): void {\r\n const {\r\n app,\r\n routes: initialRoutes,\r\n apiRoutes: initialApiRoutes,\r\n notFoundPage,\r\n errorPage,\r\n isDev,\r\n projectRoot,\r\n routeLoader,\r\n getRoutes,\r\n config,\r\n } = options;\r\n\r\n // Cache route chunks - they don't change during runtime\r\n const routeChunks = routeLoader.loadRouteChunks();\r\n\r\n // SSG directory - available in both dev and prod if files exist\r\n const ssgOutDir = path.join(\r\n config ? getBuildDir(projectRoot, config) : path.join(projectRoot, BUILD_FOLDER_NAME),\r\n \"ssg\"\r\n );\r\n\r\n app.all(\"/api/*\", async (req, res) => {\r\n const apiRoutes = isDev && getRoutes\r\n ? getRoutes().apiRoutes\r\n : initialApiRoutes;\r\n\r\n // Get rate limit configuration for auto-application\r\n const serverConfig = await getServerConfig(projectRoot);\r\n const strictPatterns = serverConfig.rateLimit?.strictPatterns || [];\r\n\r\n await handleApiRequest({\r\n apiRoutes,\r\n urlPath: req.path,\r\n req,\r\n res,\r\n env: isDev ? \"dev\" : \"prod\",\r\n strictRateLimitPatterns: strictPatterns,\r\n });\r\n });\r\n\r\n app.get(\"*\", async (req, res) => {\r\n let routes = initialRoutes;\r\n let currentNotFoundPage = notFoundPage;\r\n\r\n if (isDev && getRoutes) {\r\n routes = getRoutes().routes;\r\n // In dev, reload not-found on each request to support hot-reload\r\n currentNotFoundPage = routeLoader.loadNotFoundRoute();\r\n }\r\n\r\n const currentErrorPage = isDev && getRoutes\r\n ? routeLoader.loadErrorRoute()\r\n : errorPage;\r\n\r\n await handlePageRequest({\r\n routes,\r\n notFoundPage: currentNotFoundPage,\r\n errorPage: currentErrorPage,\r\n routeChunks,\r\n urlPath: req.path,\r\n req,\r\n res,\r\n env: isDev ? \"dev\" : \"prod\",\r\n ssgOutDir,\r\n theme: req.cookies?.theme || \"light\",\r\n projectRoot,\r\n });\r\n });\r\n}\r\n\r\n","import { Server as HttpServer } from \"http\";\r\nimport { Server, Socket } from \"socket.io\";\r\nimport { WssRoute, WssContext } from \"@router/index.types\";\r\n\r\nexport interface SetupWssEventsOptions {\r\n httpServer: HttpServer;\r\n wssRoutes: WssRoute[];\r\n}\r\n\r\n/**\r\n * Generates helper actions for WebSocket context.\r\n * \r\n * Wraps Socket.IO methods in arrow functions to preserve the correct context\r\n * when used later in event handlers.\r\n * \r\n * @param socket - The Socket.IO socket instance\r\n * @param namespace - The Socket.IO namespace instance\r\n * @returns Actions object with helper methods for the namespace\r\n */\r\nconst generateActions = (socket: Socket, namespace: any): WssContext['actions'] => {\r\n return {\r\n // Emit to all clients in the namespace\r\n emit: (event: string, ...args: any[]) => {\r\n socket.nsp.emit(event, ...args);\r\n },\r\n \r\n // Emit to a specific socket by Socket.IO socket ID\r\n emitTo: (socketId: string, event: string, ...args: any[]) => {\r\n const targetSocket = namespace.sockets.get(socketId);\r\n if (targetSocket) {\r\n targetSocket.emit(event, ...args);\r\n }\r\n },\r\n \r\n // Emit to a specific client by custom clientId\r\n // Requires clientId to be stored in socket.data.clientId during connection\r\n emitToClient: (clientId: string, event: string, ...args: any[]) => {\r\n // Find socket by clientId stored in socket.data\r\n namespace.sockets.forEach((s: Socket) => {\r\n if (s.data?.clientId === clientId) {\r\n s.emit(event, ...args);\r\n }\r\n });\r\n },\r\n \r\n // Broadcast to all clients except the sender\r\n broadcast: (event: string, ...args: any[]) => {\r\n socket.broadcast.emit(event, ...args);\r\n },\r\n };\r\n};\r\n\r\n/**\r\n * Sets up Socket.IO server and registers WebSocket event handlers for each route.\r\n * \r\n * This function:\r\n * - Creates a Socket.IO server instance with the '/wss' path\r\n * - Extracts namespaces from route patterns (removes '/wss' prefix)\r\n * - Registers connection handlers for each namespace\r\n * - Maps event handlers from route definitions to Socket.IO events\r\n * \r\n * @param options - WebSocket setup options\r\n * \r\n * @example\r\n * ```ts\r\n * setupWssEvents({\r\n * httpServer,\r\n * wssRoutes: [{ pattern: '/wss/chat', handlers: { ... } }]\r\n * });\r\n * ```\r\n */\r\nexport function setupWssEvents(options: SetupWssEventsOptions): void {\r\n const { httpServer, wssRoutes } = options;\r\n\r\n if (wssRoutes.length === 0) {\r\n return;\r\n }\r\n\r\n const io = new Server(httpServer, {\r\n path: '/wss'\r\n });\r\n\r\n for (const wssRoute of wssRoutes) {\r\n // Extract namespace from route pattern by removing the '/wss' prefix\r\n // Example: Pattern '/wss/chat' -> Namespace '/chat'\r\n // Example: Pattern '/wss' -> Namespace '/'\r\n let namespacePath = wssRoute.pattern.replace(/^\\/wss/, '');\r\n \r\n // Ensure namespace always starts with '/'\r\n if (!namespacePath.startsWith('/')) {\r\n namespacePath = '/' + namespacePath;\r\n }\r\n \r\n // If empty after removal, use root namespace\r\n if (namespacePath === '') {\r\n namespacePath = '/';\r\n }\r\n \r\n const namespace = io.of(namespacePath);\r\n\r\n // Set up connection handler for this namespace\r\n namespace.on('connection', (socket: Socket) => {\r\n // Register all event handlers defined in the route\r\n Object.entries(wssRoute.handlers).forEach(([event, handler]) => {\r\n if (event.toLowerCase() === 'connection') {\r\n // Connection handler is executed immediately upon connection\r\n const ctx: WssContext = {\r\n socket,\r\n io: namespace.server,\r\n params: {},\r\n pathname: wssRoute.pattern,\r\n actions: generateActions(socket, namespace),\r\n };\r\n handler(ctx as any);\r\n } else {\r\n // For other events, register them on the socket instance\r\n socket.on(event, (data) => {\r\n const ctx: WssContext = {\r\n socket,\r\n io: namespace.server,\r\n actions: generateActions(socket, namespace),\r\n params: {},\r\n pathname: wssRoute.pattern,\r\n data,\r\n };\r\n handler(ctx as any);\r\n });\r\n }\r\n });\r\n });\r\n }\r\n}\r\n","import http from \"http\";\r\nimport express from \"express\";\r\nimport cors from \"cors\";\r\nimport helmet from \"helmet\";\r\nimport cookieParser from \"cookie-parser\";\r\nimport compression from \"compression\";\r\nimport crypto from \"crypto\";\r\nimport { getServerConfig } from \"@server/config\";\r\nimport { createRateLimiter } from \"@server/middleware/rate-limit\";\r\nimport { requestLoggerMiddleware, createModuleLogger } from \"@logger/index\";\r\n\r\ninterface SetupAppOptions {\r\n projectRoot: string;\r\n}\r\n\r\nexport const setupApplication = async ({\r\n projectRoot,\r\n}: SetupAppOptions): Promise<{\r\n app: express.Express;\r\n httpServer: http.Server<\r\n typeof http.IncomingMessage,\r\n typeof http.ServerResponse\r\n >;\r\n}> => {\r\n const app = express();\r\n\r\n const serverConfig = await getServerConfig(projectRoot);\r\n\r\n const { bodyLimit, corsOrigin, rateLimit, security } = serverConfig;\r\n\r\n // Security: Helmet with configurable CSP\r\n const helmetConfig: any = {};\r\n \r\n if (security?.contentSecurityPolicy !== false) {\r\n // In development, allow unsafe-inline and unsafe-eval for hot reload\r\n if (process.env.NODE_ENV === \"development\") {\r\n helmetConfig.contentSecurityPolicy = {\r\n directives: {\r\n defaultSrc: [\"'self'\"],\r\n styleSrc: [\"'self'\", \"'unsafe-inline'\", \"https://fonts.googleapis.com\"],\r\n scriptSrc: [\"'self'\", \"'unsafe-inline'\", \"'unsafe-eval'\"],\r\n imgSrc: [\"'self'\", \"data:\", \"https:\"],\r\n // Allow fetch/XHR to any HTTPS endpoint - users can restrict in their config if needed\r\n connectSrc: [\"'self'\", \"ws:\", \"wss:\", \"https:\"],\r\n fontSrc: [\"'self'\", \"data:\", \"https://fonts.gstatic.com\"],\r\n },\r\n };\r\n } else {\r\n // Use function-based CSP to enable nonce support in production\r\n const userCSP = security?.contentSecurityPolicy;\r\n const nonceFunction = (req: express.Request, res: express.Response) => {\r\n // Nonce is generated by middleware and stored in res.locals.nonce\r\n // This allows inline scripts with the nonce attribute\r\n const nonce = (res as any).locals?.nonce || \"\";\r\n return nonce ? `'nonce-${nonce}'` : \"'self'\";\r\n };\r\n \r\n const defaultCSP = {\r\n directives: {\r\n defaultSrc: [\"'self'\"],\r\n styleSrc: [\"'self'\", \"'unsafe-inline'\", \"https://fonts.googleapis.com\"],\r\n scriptSrc: [\"'self'\", nonceFunction],\r\n imgSrc: [\"'self'\", \"data:\", \"https:\"],\r\n // Allow fetch/XHR to any HTTPS endpoint - users can restrict in their config if needed\r\n connectSrc: [\"'self'\", \"https:\"],\r\n fontSrc: [\"'self'\", \"data:\", \"https://fonts.gstatic.com\"],\r\n objectSrc: [\"'none'\"],\r\n mediaSrc: [\"'self'\", \"https:\"],\r\n frameSrc: [\"'none'\"],\r\n },\r\n };\r\n\r\n if (userCSP && typeof userCSP === \"object\" && !Array.isArray(userCSP)) {\r\n // Merge user CSP with default, but ensure scriptSrc includes nonce support\r\n const userDirectives = userCSP.directives || {};\r\n const mergedDirectives: any = {\r\n ...defaultCSP.directives,\r\n ...userDirectives,\r\n };\r\n \r\n // Ensure scriptSrc includes nonce support even if user provided custom scriptSrc\r\n const userScriptSrc = userDirectives.scriptSrc;\r\n if (userScriptSrc && Array.isArray(userScriptSrc)) {\r\n // Check if nonce function is already included\r\n const hasNonceSupport = userScriptSrc.some((src) => \r\n typeof src === \"function\"\r\n );\r\n \r\n if (!hasNonceSupport) {\r\n // Add nonce function to user's scriptSrc\r\n mergedDirectives.scriptSrc = [\r\n ...userScriptSrc,\r\n nonceFunction,\r\n ];\r\n } else {\r\n mergedDirectives.scriptSrc = userScriptSrc;\r\n }\r\n }\r\n \r\n // Ensure connectSrc includes https: for flexibility - merge arrays instead of replacing\r\n const userConnectSrc = userDirectives.connectSrc;\r\n if (userConnectSrc && Array.isArray(userConnectSrc)) {\r\n // If user provided connectSrc, merge with defaults to ensure https: is included\r\n const defaultConnectSrc = defaultCSP.directives.connectSrc || [];\r\n const mergedConnectSrc = [...new Set([...defaultConnectSrc, ...userConnectSrc])];\r\n mergedDirectives.connectSrc = mergedConnectSrc;\r\n }\r\n \r\n // Ensure styleSrc includes Google Fonts\r\n const userStyleSrc = userDirectives.styleSrc;\r\n if (userStyleSrc && Array.isArray(userStyleSrc)) {\r\n const defaultStyleSrc = defaultCSP.directives.styleSrc || [];\r\n const mergedStyleSrc = [...new Set([...defaultStyleSrc, ...userStyleSrc])];\r\n mergedDirectives.styleSrc = mergedStyleSrc;\r\n }\r\n \r\n // Ensure fontSrc includes Google Fonts\r\n const userFontSrc = userDirectives.fontSrc;\r\n if (userFontSrc && Array.isArray(userFontSrc)) {\r\n const defaultFontSrc = defaultCSP.directives.fontSrc || [];\r\n const mergedFontSrc = [...new Set([...defaultFontSrc, ...userFontSrc])];\r\n mergedDirectives.fontSrc = mergedFontSrc;\r\n }\r\n \r\n helmetConfig.contentSecurityPolicy = {\r\n ...userCSP,\r\n directives: mergedDirectives,\r\n };\r\n } else {\r\n helmetConfig.contentSecurityPolicy = defaultCSP;\r\n }\r\n }\r\n } else {\r\n helmetConfig.contentSecurityPolicy = false;\r\n }\r\n\r\n // HSTS configuration\r\n if (security?.hsts !== false) {\r\n helmetConfig.hsts = security?.hsts === true \r\n ? { maxAge: 31536000, includeSubDomains: true }\r\n : security?.hsts;\r\n } else {\r\n helmetConfig.hsts = false;\r\n }\r\n\r\n // Generate nonce for CSP inline scripts (only in production)\r\n // In development, unsafe-inline is allowed\r\n // IMPORTANT: This must run BEFORE helmet so the nonce is available when CSP is evaluated\r\n if (process.env.NODE_ENV !== \"development\" && security?.contentSecurityPolicy !== false) {\r\n app.use((req: express.Request, res: express.Response, next: express.NextFunction) => {\r\n // Generate a unique nonce for this request\r\n const nonce = crypto.randomBytes(16).toString(\"base64\");\r\n (res.locals as any).nonce = nonce;\r\n next();\r\n });\r\n }\r\n\r\n app.use(helmet(helmetConfig));\r\n\r\n // Logging: Request logger middleware (adds request ID and logs requests/responses)\r\n // Must be early in the middleware chain to capture all requests\r\n // Filters out static assets and other noisy paths by default\r\n const appLogger = createModuleLogger(\"framework\");\r\n app.use(requestLoggerMiddleware({ \r\n logger: appLogger.child({ component: \"server\" }),\r\n logRequests: process.env.LOG_REQUESTS === \"true\", // Default to false (only errors/warnings)\r\n logResponses: process.env.LOG_RESPONSES !== \"false\", // Default to true (but filtered)\r\n logStaticAssets: process.env.LOG_STATIC_ASSETS === \"true\", // Default to false\r\n }));\r\n\r\n // Security: CORS with proper origin validation\r\n const corsOptions: cors.CorsOptions = {\r\n credentials: true,\r\n };\r\n\r\n if (typeof corsOrigin === \"function\") {\r\n corsOptions.origin = corsOrigin;\r\n } else if (Array.isArray(corsOrigin)) {\r\n corsOptions.origin = corsOrigin.length > 0 ? corsOrigin : false;\r\n } else if (corsOrigin === true) {\r\n // Allow all origins (development only)\r\n corsOptions.origin = true;\r\n } else if (typeof corsOrigin === \"string\") {\r\n corsOptions.origin = corsOrigin === \"*\" \r\n ? (process.env.NODE_ENV === \"development\" ? true : false)\r\n : [corsOrigin];\r\n } else {\r\n // Default: no CORS in production, allow all in development\r\n corsOptions.origin = process.env.NODE_ENV === \"development\";\r\n }\r\n\r\n app.use(cors(corsOptions));\r\n\r\n // Security: Rate limiting\r\n if (rateLimit) {\r\n const generalLimiter = createRateLimiter({\r\n windowMs: rateLimit.windowMs,\r\n max: rateLimit.max,\r\n });\r\n \r\n // Apply general rate limiting to all routes\r\n app.use(generalLimiter);\r\n }\r\n\r\n app.use(cookieParser());\r\n\r\n app.use(express.json({ limit: bodyLimit }));\r\n app.use(express.urlencoded({ extended: true, limit: bodyLimit }));\r\n\r\n app.use(compression());\r\n\r\n // Create http server\r\n const httpServer = http.createServer(app);\r\n\r\n return {\r\n app,\r\n httpServer,\r\n };\r\n};\r\n","import { hydrateRoot } from \"react-dom/client\";\r\nimport { APP_CONTAINER_ID } from \"./constants\";\r\nimport { getWindowData } from \"./window-data\";\r\nimport { matchRouteClient } from \"./route-matcher\";\r\nimport { applyMetadata } from \"./metadata\";\r\nimport { AppShell } from \"./AppShell\";\r\nimport type {\r\n InitialData,\r\n ClientRouteLoaded,\r\n RouteViewState,\r\n} from \"./types\";\r\n\r\nexport async function loadInitialRoute(\r\n initialUrl: string,\r\n initialData: InitialData | null,\r\n routes: ClientRouteLoaded[],\r\n notFoundRoute: ClientRouteLoaded | null,\r\n errorRoute: ClientRouteLoaded | null\r\n): Promise<RouteViewState> {\r\n const isInitialNotFound = initialData?.notFound === true;\r\n const isInitialError = initialData?.error === true;\r\n\r\n let initialRoute: ClientRouteLoaded | null = null;\r\n let initialParams: Record<string, string> = {};\r\n let initialComponents = null;\r\n\r\n if (isInitialError && errorRoute) {\r\n initialRoute = errorRoute;\r\n initialParams = initialData?.params ?? {};\r\n initialComponents = await errorRoute.load();\r\n } else if (isInitialNotFound && notFoundRoute) {\r\n initialRoute = notFoundRoute;\r\n initialParams = {};\r\n initialComponents = await notFoundRoute.load();\r\n } else {\r\n const match = matchRouteClient(initialUrl, routes);\r\n if (match) {\r\n initialRoute = match.route;\r\n initialParams = match.params;\r\n initialComponents = await match.route.load();\r\n } else if (notFoundRoute) {\r\n initialRoute = notFoundRoute;\r\n initialParams = {};\r\n initialComponents = await notFoundRoute.load();\r\n } else {\r\n console.warn(\r\n `[client] No route match found for ${initialUrl}. Available routes:`,\r\n routes.map((r) => r.pattern)\r\n );\r\n }\r\n }\r\n\r\n return {\r\n url: initialUrl,\r\n route: initialRoute,\r\n params: initialParams,\r\n components: initialComponents,\r\n props: initialData?.props ?? {},\r\n };\r\n}\r\n\r\n/**\r\n * Sets up hot reload via Server-Sent Events (SSE) in development mode.\r\n * Listens for file changes and reloads the page when needed.\r\n */\r\nfunction setupHotReload(): void {\r\n // Only enable hot reload in development mode\r\n // In production, process.env.NODE_ENV is replaced by DefinePlugin with \"production\"\r\n // @ts-ignore - process.env.NODE_ENV is replaced by DefinePlugin at build time\r\n const nodeEnv: string = (typeof process !== \"undefined\" && process?.env?.NODE_ENV) || \"production\";\r\n const isDev = nodeEnv !== \"production\";\r\n \r\n if (!isDev) {\r\n return; // Skip hot reload in production\r\n }\r\n\r\n try {\r\n console.log(\"[hot-reload] Attempting to connect to /__fw/hot...\");\r\n const eventSource = new EventSource(\"/__fw/hot\");\r\n let reloadTimeout: ReturnType<typeof setTimeout> | null = null;\r\n\r\n eventSource.addEventListener(\"message\", (event) => {\r\n const data = event.data;\r\n if (data && data.startsWith(\"reload:\")) {\r\n const filePath = data.slice(7);\r\n console.log(`[hot-reload] File changed: ${filePath}`);\r\n\r\n // Clear any pending reload\r\n if (reloadTimeout) {\r\n clearTimeout(reloadTimeout);\r\n }\r\n\r\n // Wait a bit for the bundler to finish compiling and files to be written\r\n // Increased timeout to ensure everything is ready\r\n reloadTimeout = setTimeout(() => {\r\n console.log(\"[hot-reload] Reloading page...\");\r\n // Force reload without cache to ensure we get the latest files\r\n window.location.reload();\r\n }, 500);\r\n }\r\n });\r\n\r\n eventSource.addEventListener(\"ping\", () => {\r\n console.log(\"[hot-reload] ✓ Connected to hot reload server\");\r\n });\r\n\r\n eventSource.onopen = () => {\r\n console.log(\"[hot-reload] ✓ SSE connection opened\");\r\n };\r\n\r\n eventSource.onerror = (error) => {\r\n // Log connection state for debugging\r\n const states = [\"CONNECTING\", \"OPEN\", \"CLOSED\"];\r\n const state = states[eventSource.readyState] || \"UNKNOWN\";\r\n \r\n if (eventSource.readyState === EventSource.CONNECTING) {\r\n // Still connecting, might be normal\r\n console.log(\"[hot-reload] Connecting...\");\r\n } else if (eventSource.readyState === EventSource.OPEN) {\r\n console.warn(\"[hot-reload] Connection error (but connection is open):\", error);\r\n } else {\r\n // Connection closed - might be production mode or server not running\r\n console.log(\"[hot-reload] Connection closed (readyState:\", state, \")\");\r\n }\r\n // EventSource automatically reconnects, so we don't need to do anything\r\n };\r\n } catch (error) {\r\n // Fail silently if EventSource is not supported\r\n console.log(\"[hot-reload] EventSource not supported or error:\", error);\r\n }\r\n}\r\n\r\n/**\r\n * Bootstraps the client-side application.\r\n *\r\n * @param routes - Array of client routes\r\n * @param notFoundRoute - Not-found route definition\r\n * @param errorRoute - Error route definition\r\n */\r\nexport function bootstrapClient(\r\n routes: ClientRouteLoaded[],\r\n notFoundRoute: ClientRouteLoaded | null,\r\n errorRoute: ClientRouteLoaded | null = null\r\n): void {\r\n // Set up hot reload in development mode\r\n console.log(\"[client] Bootstrap starting, setting up hot reload...\");\r\n setupHotReload();\r\n\r\n (async function bootstrap() {\r\n const container = document.getElementById(APP_CONTAINER_ID);\r\n const initialData = getWindowData();\r\n\r\n if (!container) {\r\n console.error(`Container #${APP_CONTAINER_ID} not found for hydration`);\r\n return;\r\n }\r\n\r\n const initialUrl = window.location.pathname + window.location.search;\r\n\r\n try {\r\n const initialState = await loadInitialRoute(\r\n initialUrl,\r\n initialData,\r\n routes,\r\n notFoundRoute,\r\n errorRoute\r\n );\r\n\r\n if (initialData?.metadata) {\r\n applyMetadata(initialData.metadata);\r\n }\r\n\r\n hydrateRoot(\r\n container,\r\n <AppShell\r\n initialState={initialState}\r\n routes={routes}\r\n notFoundRoute={notFoundRoute}\r\n errorRoute={errorRoute}\r\n />\r\n );\r\n } catch (error) {\r\n console.error(\r\n \"[client] Error loading initial route components for\",\r\n initialUrl,\r\n error\r\n );\r\n\r\n window.location.reload();\r\n }\r\n })();\r\n}\r\n\r\n","import { useEffect, useState, useRef, useCallback } from \"react\";\r\nimport { RouterView } from \"./RouterView\";\r\nimport {\r\n navigate,\r\n createClickHandler,\r\n createPopStateHandler,\r\n type NavigationHandlers,\r\n} from \"./navigation\";\r\nimport { RouterContext } from \"./RouterContext\";\r\nimport type {\r\n RouteViewState,\r\n ClientRouteLoaded,\r\n} from \"./types\";\r\n\r\nexport interface AppShellProps {\r\n initialState: RouteViewState;\r\n routes: ClientRouteLoaded[];\r\n notFoundRoute: ClientRouteLoaded | null;\r\n errorRoute: ClientRouteLoaded | null;\r\n}\r\n\r\nexport function AppShell({\r\n initialState,\r\n routes,\r\n notFoundRoute,\r\n errorRoute,\r\n}: AppShellProps) {\r\n const [state, setState] = useState<RouteViewState>(initialState);\r\n const handlersRef = useRef<NavigationHandlers>({\r\n setState,\r\n routes,\r\n notFoundRoute,\r\n errorRoute,\r\n });\r\n\r\n // Mantener handlersRef actualizado\r\n useEffect(() => {\r\n handlersRef.current = {\r\n setState,\r\n routes,\r\n notFoundRoute,\r\n errorRoute,\r\n };\r\n }, [routes, notFoundRoute, errorRoute]);\r\n\r\n // Create navigate function for router context\r\n const handleNavigate = useCallback(\r\n async (\r\n nextUrl: string,\r\n options?: { revalidate?: boolean; replace?: boolean }\r\n ) => {\r\n await navigate(nextUrl, handlersRef.current, {\r\n revalidate: options?.revalidate,\r\n });\r\n },\r\n []\r\n );\r\n\r\n useEffect(() => {\r\n // Flag para evitar múltiples listeners (por si React Strict Mode ejecuta dos veces)\r\n let isMounted = true;\r\n\r\n async function handleNavigateInternal(\r\n nextUrl: string,\r\n options?: { revalidate?: boolean }\r\n ) {\r\n if (!isMounted) return;\r\n await navigate(nextUrl, handlersRef.current, options);\r\n }\r\n\r\n const handleClick = createClickHandler(handleNavigateInternal);\r\n const handlePopState = createPopStateHandler(handleNavigateInternal);\r\n\r\n // Usar capture: false (burbujeo) para que los eventos del input se manejen primero\r\n window.addEventListener(\"click\", handleClick, false);\r\n window.addEventListener(\"popstate\", handlePopState, false);\r\n\r\n return () => {\r\n isMounted = false;\r\n window.removeEventListener(\"click\", handleClick, false);\r\n window.removeEventListener(\"popstate\", handlePopState, false);\r\n };\r\n }, []); // Solo ejecutar una vez al montar\r\n\r\n const isError = state.route === errorRoute;\r\n const isNotFound = state.route === notFoundRoute;\r\n const routeType = isError ? \"error\" : isNotFound ? \"notfound\" : \"normal\";\r\n const routeKey = `${state.url}:${routeType}`;\r\n\r\n return (\r\n <RouterContext.Provider value={{ navigate: handleNavigate }}>\r\n <RouterView key={routeKey} state={state} />\r\n </RouterContext.Provider>\r\n );\r\n}\r\n\r\n","import type { RouteViewState } from \"./types\";\r\n\r\nexport function RouterView({ state }: { state: RouteViewState }) {\r\n if (!state.route) {\r\n // Don't show 404 if we're waiting for components to load\r\n if (state.components === null) {\r\n return null;\r\n }\r\n return <h1>404 - Route not found</h1>;\r\n }\r\n\r\n if (!state.components) {\r\n return null;\r\n }\r\n\r\n const { Page, layouts } = state.components;\r\n const { params, props } = state;\r\n\r\n let element = <Page params={params} {...props} />;\r\n\r\n const layoutChain = layouts.slice().reverse();\r\n for (const Layout of layoutChain) {\r\n element = (\r\n <Layout params={params} {...props}>\r\n {element}\r\n </Layout>\r\n );\r\n }\r\n\r\n return element;\r\n}\r\n\r\n","type RouteData = {\n ok: boolean;\n status: number;\n json: any;\n};\n\ntype CacheEntry =\n | { status: \"pending\"; promise: Promise<RouteData> }\n | { status: \"fulfilled\"; value: RouteData }\n | { status: \"rejected\"; error: any };\n\n// Use window to guarantee a single shared cache instance\n// across all bundles/modules\nconst CACHE_KEY = \"__FW_DATA_CACHE__\";\n\n// Maximum number of entries in the cache (LRU)\nconst MAX_CACHE_SIZE = 100;\n\ntype CacheStore = {\n data: Map<string, CacheEntry>;\n index: Map<string, Set<string>>; // pathBase -> Set of keys\n lru: string[]; // Ordered list: most recent at end, oldest at start\n};\n\nfunction getCacheStore(): CacheStore {\n if (typeof window !== \"undefined\") {\n if (!(window as any)[CACHE_KEY]) {\n (window as any)[CACHE_KEY] = {\n data: new Map<string, CacheEntry>(),\n index: new Map<string, Set<string>>(),\n lru: [],\n };\n }\n return (window as any)[CACHE_KEY];\n }\n // Fallback for SSR (though this shouldn't be used on the client)\n return {\n data: new Map<string, CacheEntry>(),\n index: new Map<string, Set<string>>(),\n lru: [],\n };\n}\n\nconst cacheStore = getCacheStore();\nconst dataCache = cacheStore.data;\nconst pathIndex = cacheStore.index;\nconst lru = cacheStore.lru;\n\n// Helper functions for cache management\n\n/**\n * Extract base path from a cache key (removes query params)\n */\nfunction extractPathBase(key: string): string {\n return key.split(\"?\")[0];\n}\n\n/**\n * Add key to path index\n */\nfunction addToIndex(key: string): void {\n const pathBase = extractPathBase(key);\n if (!pathIndex.has(pathBase)) {\n pathIndex.set(pathBase, new Set());\n }\n pathIndex.get(pathBase)!.add(key);\n}\n\n/**\n * Remove key from path index\n */\nfunction removeFromIndex(key: string): void {\n const pathBase = extractPathBase(key);\n const keys = pathIndex.get(pathBase);\n if (keys) {\n keys.delete(key);\n if (keys.size === 0) {\n pathIndex.delete(pathBase);\n }\n }\n}\n\n/**\n * Update LRU order - move key to end (most recent)\n */\nfunction updateLRU(key: string): void {\n const index = lru.indexOf(key);\n if (index !== -1) {\n lru.splice(index, 1);\n }\n lru.push(key);\n}\n\n/**\n * Remove oldest entries if cache exceeds MAX_CACHE_SIZE\n */\nfunction evictOldest(): void {\n while (lru.length >= MAX_CACHE_SIZE && lru.length > 0) {\n const oldestKey = lru.shift()!;\n dataCache.delete(oldestKey);\n removeFromIndex(oldestKey);\n }\n}\n\n/**\n * Set cache entry and maintain indexes\n */\nfunction setCacheEntry(key: string, entry: CacheEntry): void {\n const existingEntry = dataCache.get(key);\n const wasFulfilled = existingEntry?.status === \"fulfilled\";\n \n dataCache.set(key, entry);\n \n // Only track fulfilled entries in LRU and index (not pending/rejected)\n if (entry.status === \"fulfilled\") {\n // Add to index if it wasn't already fulfilled (new entry or transition from pending/rejected)\n if (!wasFulfilled) {\n addToIndex(key);\n }\n updateLRU(key);\n evictOldest();\n } else if (wasFulfilled) {\n // If entry was fulfilled and now isn't (transitioning to pending/rejected), remove from index\n removeFromIndex(key);\n }\n}\n\n/**\n * Delete cache entry and clean up indexes\n */\nfunction deleteCacheEntry(key: string): void {\n if (dataCache.has(key)) {\n dataCache.delete(key);\n removeFromIndex(key);\n const lruIndex = lru.indexOf(key);\n if (lruIndex !== -1) {\n lru.splice(lruIndex, 1);\n }\n }\n}\n\nfunction buildDataUrl(url: string): string {\n return url + (url.includes(\"?\") ? \"&\" : \"?\") + \"__fw_data=1\";\n}\n\nasync function fetchRouteDataOnce(url: string): Promise<RouteData> {\n const dataUrl = buildDataUrl(url);\n\n const res = await fetch(dataUrl, {\n headers: {\n \"x-fw-data\": \"1\",\n Accept: \"application/json\",\n },\n });\n\n let json: any = {};\n\n try {\n const text = await res.text();\n if (text) {\n json = JSON.parse(text);\n }\n } catch (parseError) {\n console.error(\n \"[client][cache] Failed to parse response as JSON:\",\n parseError\n );\n }\n\n const result: RouteData = {\n ok: res.ok,\n status: res.status,\n json,\n };\n\n return result;\n}\n\n/**\n * Revalidates route data by removing it from the cache.\n * The next time you navigate to this route, fresh data will be fetched from the server.\n * This is a client-side function and does not require a server-side revalidation.\n *\n * @param path - The route path to revalidate (e.g., '/posts/1' or '/posts/1?page=2')\n * If query params are not included, revalidates all variants of that route.\n *\n * @example\n * ```ts\n * // After saving something to the DB, revalidate the route\n * await saveToDatabase(data);\n * revalidatePath('/posts');\n * \n * // Revalidate a specific route with query params\n * revalidatePath('/posts?page=2');\n * ```\n */\nexport function revalidatePath(path: string): void {\n // Normalize the base path (without query params)\n const normalizedPath = path.split(\"?\")[0];\n const hasQueryParams = path.includes(\"?\");\n \n // Get all keys for this path base from index (O(1) lookup)\n const keysForPath = pathIndex.get(normalizedPath);\n \n if (!keysForPath || keysForPath.size === 0) {\n return; // No entries to revalidate\n }\n \n // If the path includes specific query params, extract them\n let specificQueryParams: string | undefined;\n if (hasQueryParams) {\n const queryPart = path.split(\"?\")[1];\n // Sort query params for consistent comparison\n specificQueryParams = queryPart\n .split(\"&\")\n .filter((p) => !p.startsWith(\"__fw_data=\"))\n .sort()\n .join(\"&\");\n }\n \n // Iterate only over keys for this path (much smaller set)\n const keysToDelete: string[] = [];\n for (const key of keysForPath) {\n // If specific query params were specified, check if they match\n if (hasQueryParams && specificQueryParams) {\n const [, keyQuery = \"\"] = key.split(\"?\");\n const keyQueryParams = keyQuery\n .split(\"&\")\n .filter((p) => !p.startsWith(\"__fw_data=\"))\n .sort()\n .join(\"&\");\n \n if (keyQueryParams === specificQueryParams) {\n keysToDelete.push(key);\n }\n } else {\n // If no specific query params, revalidate all variants\n keysToDelete.push(key);\n }\n }\n \n // Delete matching entries\n keysToDelete.forEach((key) => {\n deleteCacheEntry(key);\n });\n}\n\n/**\n * Revalidates and refreshes the current page data.\n * Similar to Next.js's `router.refresh()`.\n * \n * This function:\n * 1. Removes the current route from cache\n * 2. Fetches fresh data from the server\n * 3. Updates window.__FW_DATA__ with the new data\n * 4. Dispatches a 'fw-data-refresh' event for components to listen to\n * \n * @returns Promise that resolves with the fresh route data\n * \n * @example\n * ```ts\n * // Refresh current page data after a mutation\n * await revalidate();\n * ```\n */\nexport async function revalidate(): Promise<RouteData> {\n if (typeof window === \"undefined\") {\n throw new Error(\"revalidate() can only be called on the client\");\n }\n\n const pathname = window.location.pathname + window.location.search;\n \n // Revalidate the path (remove from cache)\n revalidatePath(pathname);\n \n // Fetch fresh data\n const freshData = await getRouteData(pathname, { revalidate: true });\n \n // Update window.__FW_DATA__ if it exists\n if ((window as any).__FW_DATA__ && freshData.ok && freshData.json) {\n const currentData = (window as any).__FW_DATA__;\n (window as any).__FW_DATA__ = {\n ...currentData,\n pathname: pathname.split(\"?\")[0],\n params: freshData.json.params || currentData.params || {},\n props: freshData.json.props || currentData.props || {},\n metadata: freshData.json.metadata ?? currentData.metadata ?? null,\n notFound: freshData.json.notFound ?? false,\n error: freshData.json.error ?? false,\n };\n \n // Dispatch event for components to listen to\n window.dispatchEvent(new CustomEvent(\"fw-data-refresh\", {\n detail: { data: freshData },\n }));\n }\n \n return freshData;\n}\n\n/**\n * @deprecated Use `revalidatePath()` instead. This function is kept for backwards compatibility.\n */\nexport function revalidateRouteData(url: string): void {\n revalidatePath(url);\n}\n\nexport function prefetchRouteData(url: string): void {\n const key = buildDataUrl(url);\n\n const cached = dataCache.get(key);\n\n if (cached && cached.status !== \"rejected\") {\n // Update LRU if it exists and is fulfilled\n if (cached.status === \"fulfilled\") {\n updateLRU(key);\n }\n return;\n }\n\n const promise = fetchRouteDataOnce(url)\n .then((value) => {\n setCacheEntry(key, { status: \"fulfilled\", value });\n return value;\n })\n .catch((error) => {\n console.error(\"[client][cache] Error prefetching route data:\", error);\n dataCache.set(key, { status: \"rejected\", error });\n throw error;\n });\n\n dataCache.set(key, { status: \"pending\", promise });\n}\n\nexport type GetRouteDataOptions = {\n /**\n * If true, forces revalidation of route data,\n * ignoring the cache and fetching fresh data from the server.\n * Similar to Next.js's `router.refresh()` behavior.\n */\n revalidate?: boolean;\n};\n\nexport async function getRouteData(\n url: string,\n options?: GetRouteDataOptions\n): Promise<RouteData> {\n const key = buildDataUrl(url);\n\n // If revalidation is requested, remove the entry from cache\n if (options?.revalidate) {\n deleteCacheEntry(key);\n }\n\n const entry = dataCache.get(key);\n\n if (entry) {\n if (entry.status === \"fulfilled\") {\n // Update LRU: mark as recently used\n updateLRU(key);\n return entry.value;\n }\n if (entry.status === \"pending\") {\n return entry.promise;\n }\n }\n\n // No entry in cache, fetch it\n const promise = fetchRouteDataOnce(url)\n .then((value) => {\n setCacheEntry(key, { status: \"fulfilled\", value });\n return value;\n })\n .catch((error) => {\n console.error(\"[client][cache] Error fetching route data:\", error);\n dataCache.set(key, { status: \"rejected\", error });\n throw error;\n });\n\n dataCache.set(key, { status: \"pending\", promise });\n return promise;\n}\n","import { createContext, useContext } from \"react\";\r\n\r\nexport type NavigateFunction = (\r\n url: string,\r\n options?: { revalidate?: boolean; replace?: boolean }\r\n) => Promise<void>;\r\n\r\nexport interface RouterContextValue {\r\n navigate: NavigateFunction;\r\n}\r\n\r\nexport const RouterContext = createContext<RouterContextValue | null>(null);\r\n\r\nexport function useRouterContext(): RouterContextValue {\r\n const context = useContext(RouterContext);\r\n if (!context) {\r\n throw new Error(\r\n \"useRouter must be used within a RouterProvider. Make sure you're using it inside a Loly app.\"\r\n );\r\n }\r\n return context;\r\n}\r\n","import { z, ZodSchema, ZodError } from \"zod\";\r\n\r\n/**\r\n * Validation error with detailed information.\r\n */\r\nexport class ValidationError extends Error {\r\n constructor(\r\n public errors: z.ZodIssue[],\r\n message = \"Validation failed\"\r\n ) {\r\n super(message);\r\n this.name = \"ValidationError\";\r\n }\r\n\r\n /**\r\n * Formats validation errors into a user-friendly format.\r\n */\r\n format(): Record<string, string[]> {\r\n const formatted: Record<string, string[]> = {};\r\n for (const error of this.errors) {\r\n const path = error.path.join(\".\");\r\n if (!formatted[path]) {\r\n formatted[path] = [];\r\n }\r\n formatted[path].push(error.message);\r\n }\r\n return formatted;\r\n }\r\n}\r\n\r\n/**\r\n * Validates data against a Zod schema.\r\n * \r\n * @param schema - Zod schema to validate against\r\n * @param data - Data to validate\r\n * @returns Validated data\r\n * @throws ValidationError if validation fails\r\n */\r\nexport function validate<T>(\r\n schema: ZodSchema<T>,\r\n data: unknown\r\n): T {\r\n try {\r\n return schema.parse(data);\r\n } catch (error) {\r\n if (error instanceof ZodError) {\r\n throw new ValidationError(error.errors);\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Safely validates data and returns a result object.\r\n * \r\n * @param schema - Zod schema to validate against\r\n * @param data - Data to validate\r\n * @returns Result object with success flag and data/error\r\n */\r\nexport function safeValidate<T>(\r\n schema: ZodSchema<T>,\r\n data: unknown\r\n): { success: true; data: T } | { success: false; error: ValidationError } {\r\n try {\r\n const validated = schema.parse(data);\r\n return { success: true, data: validated };\r\n } catch (error) {\r\n if (error instanceof ZodError) {\r\n return {\r\n success: false,\r\n error: new ValidationError(error.errors),\r\n };\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Common validation schemas for reuse.\r\n */\r\nexport const commonSchemas = {\r\n /**\r\n * Validates a string parameter (e.g., route params).\r\n */\r\n stringParam: z.string().min(1).max(255),\r\n\r\n /**\r\n * Validates an optional string parameter.\r\n */\r\n optionalStringParam: z.string().max(255).optional(),\r\n\r\n /**\r\n * Validates a numeric ID parameter.\r\n */\r\n idParam: z.string().regex(/^\\d+$/, \"ID must be numeric\").transform(Number),\r\n\r\n /**\r\n * Validates a UUID parameter.\r\n */\r\n uuidParam: z.string().uuid(\"Invalid UUID format\"),\r\n\r\n /**\r\n * Validates pagination parameters.\r\n */\r\n pagination: z.object({\r\n page: z.string().regex(/^\\d+$/).transform(Number).default(\"1\"),\r\n limit: z.string().regex(/^\\d+$/).transform(Number).default(\"10\"),\r\n }),\r\n\r\n /**\r\n * Validates a search query parameter.\r\n */\r\n searchQuery: z.string().min(1).max(100).optional(),\r\n};\r\n\r\n"],"mappings":"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","names":["import_path","import_fs","import_path","path","fs","import_fs","import_path","path","fs","fs","path","import_fs","import_path","import_fs","import_path","path","fs","path","fs","import_fs","import_path","path","fs","import_fs","import_path","path","fs","import_fs","import_path","import_fs","import_path","ROUTE_FILE_REGEX","path","fs","path","fs","import_core","import_path","import_fs","import_path","fs","path","BUILD_FOLDER_NAME","STATIC_PATH","path","dotenv","import_path","import_fs","resolve","path","fs","import_path","import_path","path","import_fs","import_path","React","path","fs","path","import_path","import_fs","import_fs","import_path","path","fs","fs","path","esbuild","import_path","import_fs","DEFAULT_CONFIG","path","fs","import_fs","import_path","import_path","import_fs","import_promises","sysPath","path","presolve","basename","pjoin","prelative","psep","import_fs","import_promises","osType","path","fs_watch","rawEmitter","listener","basename","dirname","newStats","closer","fsrealpath","resolve","realpath","stats","relative","path","DOUBLE_SLASH_RE","testString","stats","statcb","now","stat","import_path","path","import_path","path","getRoutes","path","express","rateLimit","path","pino","logger","module","path","resolve","import_server","import_fs","import_path","logger","path","fs","ctx","loaderResult","initialData","appTree","nonce","documentTree","didError","pipe","abort","import_path","path","import_express","express","rateLimit","crypto","helmet","cors","cookieParser","compression","http","import_dotenv","dotenv","logger","path","fs","import_client","import_react","import_react","import_jsx_runtime","import_jsx_runtime","process","path"]}
|
|
1
|
+
{"version":3,"sources":["../constants/globals.ts","../modules/cli/index.ts","../modules/router/loader-pages.ts","../modules/router/constants/index.ts","../modules/router/path.ts","../modules/router/layout.ts","../modules/router/loader.ts","../modules/router/loader-api.ts","../modules/router/helpers/routes/index.ts","../modules/router/matcher.ts","../modules/router/manifest.ts","../modules/router/loader-routes.ts","../modules/router/route-loader.ts","../modules/router/loader-wss.ts","../modules/build/bundler/client.ts","../modules/build/config/client.ts","../modules/build/utils/index.ts","../modules/build/ssg/builder.ts","../modules/build/ssg/path.ts","../modules/build/ssg/renderer.ts","../modules/rendering/createDocumentTree/index.ts","../modules/rendering/initialData/index.ts","../modules/rendering/routerData/index.ts","../modules/build/bundler/server.ts","../modules/server/utils/server-dir.ts","../modules/server/init.ts","../modules/server/config.ts","../modules/build/index.ts","../src/config.ts","../src/server.ts","../modules/server/setup.ts","../../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js","../../../node_modules/.pnpm/readdirp@4.1.2/node_modules/readdirp/esm/index.js","../../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/handler.js","../modules/dev/hot-reload-client/index.ts","../modules/dev/hot-reload-server/index.ts","../modules/security/sanitize.ts","../modules/server/middleware/rate-limit.ts","../modules/server/middleware/auto-rate-limit.ts","../modules/logger/index.ts","../modules/server/handlers/api.ts","../modules/server/handlers/pages.ts","../modules/server/handlers/middleware.ts","../modules/server/handlers/loader.ts","../modules/server/handlers/response.ts","../modules/server/handlers/ssg.ts","../modules/server/routes.ts","../modules/server/wss.ts","../modules/server/application.ts","../modules/runtime/client/bootstrap.tsx","../modules/runtime/client/AppShell.tsx","../modules/runtime/client/RouterView.tsx","../modules/react/cache/client-data-cache/index.ts","../modules/runtime/client/RouterContext.tsx","../modules/validation/index.ts"],"sourcesContent":["export const BUILD_FOLDER_NAME = '.loly';\r\nexport const STYLE_FILE_NAME = 'styles.css';\r\n\r\n// Framework runtime constants\r\nexport const WINDOW_DATA_KEY = '__FW_DATA__';\r\nexport const ROUTER_DATA_KEY = '__LOLY_ROUTER_DATA__';\r\nexport const APP_CONTAINER_ID = '__app';\r\nexport const STATIC_PATH = '/static';\r\nexport const NOT_FOUND_PATTERN = '/not-found';\r\nexport const ERROR_PATTERN = '/error';\r\nexport const NOT_FOUND_CHUNK_KEY = '__fw_not_found__';\r\nexport const ERROR_CHUNK_KEY = '__fw_error__';\r\n\r\n// Special page file names\r\nexport const NOT_FOUND_FILE_PREFIX = '_not-found';\r\nexport const ERROR_FILE_PREFIX = '_error';\r\nexport const PAGE_FILE_NAME = 'page';\r\nexport const LAYOUT_FILE_NAME = 'layout';\r\n\r\n// Static asset paths\r\nexport const FAVICON_PATH = '/static/favicon.png';\r\nexport const CLIENT_CSS_PATH = '/static/client.css';\r\nexport const CLIENT_JS_PATH = '/static/client.js';\r\nexport const ASSETS_BASE_DIR = '/static/assets';","// src/cli/index.ts\r\n\r\n\r\n// Register tsx so Node can require/import TypeScript config files\r\n// like `loly.config.ts` from CJS entrypoints.\r\ndeclare const require: any;\r\n\r\ntry {\r\n if (typeof require !== \"undefined\") {\r\n require(\"tsx/cjs\");\r\n }\r\n} catch {\r\n // If tsx is not installed for some reason, we just skip it.\r\n // The framework will then only work with plain JS configs.\r\n}\r\n\r\n\r\nimport path from \"path\";\r\nimport process from \"process\";\r\nimport type {\r\n StartDevServerOptions,\r\n StartProdServerOptions,\r\n} from \"../../src/server\";\r\nimport type { BuildAppOptions } from \"../build\";\r\nimport { buildApp } from\"../build\";\r\nimport { startDevServer, startProdServer } from \"../../src/index\";\r\n\r\n/**\r\n * Shape of parsed CLI flags.\r\n *\r\n * Example:\r\n * --port 3000 -> { port: \"3000\" }\r\n * --appDir=app -> { appDir: \"app\" }\r\n * --flag -> { flag: true }\r\n */\r\ntype CliFlags = Record<string, string | boolean>;\r\n\r\n/**\r\n * Very small flag parser for patterns like:\r\n * --port 3000\r\n * --appDir=app\r\n * --flag\r\n */\r\nfunction parseArgs(argv: string[]): CliFlags {\r\n const args: CliFlags = {};\r\n\r\n for (let i = 0; i < argv.length; i++) {\r\n let arg = argv[i];\r\n if (!arg.startsWith(\"--\")) continue;\r\n\r\n // Strip leading \"--\"\r\n arg = arg.slice(2);\r\n\r\n // Handle \"--key=value\"\r\n if (arg.includes(\"=\")) {\r\n const [key, ...rest] = arg.split(\"=\");\r\n args[key] = rest.join(\"=\");\r\n continue;\r\n }\r\n\r\n // Handle \"--key value\" or boolean flag\r\n const next = argv[i + 1];\r\n if (next && !next.startsWith(\"--\")) {\r\n args[arg] = next;\r\n i++; // skip value\r\n } else {\r\n args[arg] = true;\r\n }\r\n }\r\n\r\n return args;\r\n}\r\n\r\n/**\r\n * Print high-level usage and options.\r\n */\r\nfunction printHelp(): void {\r\n console.log(`\r\nloly - CLI for the framework\r\n\r\nUsage:\r\n loly dev [--port 3000] [--appDir app]\r\n loly build [--appDir app]\r\n loly start [--port 3000] [--appDir app]\r\n\r\nOptions:\r\n --port HTTP port for the dev/prod server (default: 3000)\r\n --appDir App directory relative to project root (default: \"app\")\r\n`);\r\n}\r\n\r\n/**\r\n * Main CLI entrypoint.\r\n *\r\n * Supported commands:\r\n * - dev\r\n * - build\r\n * - start\r\n */\r\nasync function run(): Promise<void> {\r\n const argv = process.argv.slice(2);\r\n const command = argv[0];\r\n\r\n if (\r\n !command ||\r\n command === \"help\" ||\r\n command === \"--help\" ||\r\n command === \"-h\"\r\n ) {\r\n printHelp();\r\n return;\r\n }\r\n\r\n const args = parseArgs(argv.slice(1));\r\n\r\n const projectRoot = process.cwd();\r\n const appDir = path.resolve(projectRoot, (args.appDir as string) || \"app\");\r\n const port =\r\n typeof args.port === \"string\" && args.port.trim().length > 0\r\n ? Number(args.port)\r\n : 3000;\r\n\r\n switch (command) {\r\n case \"dev\": {\r\n // Set a sensible default environment\r\n process.env.NODE_ENV ||= \"development\";\r\n\r\n const options: StartDevServerOptions = {\r\n rootDir: projectRoot,\r\n appDir,\r\n port,\r\n };\r\n\r\n startDevServer(options);\r\n break;\r\n }\r\n\r\n case \"build\": {\r\n process.env.NODE_ENV ||= \"production\";\r\n\r\n const options: BuildAppOptions = {\r\n rootDir: projectRoot,\r\n appDir,\r\n };\r\n\r\n await buildApp(options);\r\n \r\n // Force exit to ensure process terminates after build\r\n // This prevents hanging due to open handles from loaded modules\r\n process.exit(0);\r\n break;\r\n }\r\n\r\n case \"start\": {\r\n process.env.NODE_ENV ||= \"production\";\r\n\r\n const options: StartProdServerOptions = {\r\n rootDir: projectRoot,\r\n appDir,\r\n port,\r\n };\r\n\r\n await startProdServer(options);\r\n break;\r\n }\r\n\r\n default: {\r\n console.error(`Unknown command: \"${command}\"\\n`);\r\n printHelp();\r\n process.exit(1);\r\n }\r\n }\r\n}\r\n\r\nrun().catch((err) => {\r\n console.error(\"[loly] CLI error:\", err);\r\n process.exit(1);\r\n});\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { LoadedRoute, PageComponent } from \"./index.types\";\r\nimport { PAGE_FILE_REGEX } from \"./constants\";\r\nimport { buildRoutePathFromDir, buildRegexFromRoutePath } from \"./path\";\r\nimport { loadLayoutsForDir } from \"./layout\";\r\nimport { loadLoaderForDir } from \"./loader\";\r\n\r\n/**\r\n * Scans the app directory and loads all page routes.\r\n * \r\n * Recursively walks through the app directory, finding all `page.tsx`, `page.ts`,\r\n * `page.jsx`, or `page.js` files and creating route definitions.\r\n * \r\n * @param appDir - Root directory of the app (e.g., 'app')\r\n * @returns Array of loaded routes with components, layouts, loaders, etc.\r\n * \r\n * @example\r\n * const routes = loadRoutes('app');\r\n * // [\r\n * // { pattern: '/', component: HomePage, layouts: [], ... },\r\n * // { pattern: '/blog/[slug]', component: BlogPage, layouts: [RootLayout], ... },\r\n * // ]\r\n */\r\nexport function loadRoutes(appDir: string): LoadedRoute[] {\r\n if (!fs.existsSync(appDir)) {\r\n return [];\r\n }\r\n\r\n const routes: LoadedRoute[] = [];\r\n\r\n function walk(currentDir: string) {\r\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(currentDir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n walk(fullPath);\r\n continue;\r\n }\r\n\r\n if (!PAGE_FILE_REGEX.test(entry.name)) continue;\r\n\r\n // Skip special error pages - they're handled separately\r\n if (entry.name.startsWith(\"_not-found.\") || entry.name.startsWith(\"_error.\")) {\r\n continue;\r\n }\r\n\r\n const relDir = path.relative(appDir, currentDir);\r\n const routePath = buildRoutePathFromDir(relDir);\r\n const { regex, paramNames } = buildRegexFromRoutePath(routePath);\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n const mod = require(fullPath);\r\n const component: PageComponent = mod.default;\r\n\r\n if (!component) {\r\n continue;\r\n }\r\n\r\n const { components: layouts, files: layoutFiles } = loadLayoutsForDir(\r\n currentDir,\r\n appDir\r\n );\r\n\r\n const { middlewares, loader, dynamic, generateStaticParams } =\r\n loadLoaderForDir(currentDir);\r\n\r\n routes.push({\r\n pattern: routePath,\r\n regex,\r\n paramNames,\r\n component,\r\n layouts,\r\n pageFile: fullPath,\r\n layoutFiles,\r\n middlewares,\r\n loader,\r\n dynamic,\r\n generateStaticParams,\r\n });\r\n }\r\n }\r\n\r\n walk(appDir);\r\n\r\n return routes;\r\n}\r\n\r\n","import type { FrameworkConfig } from \"@src/config\";\r\n\r\nexport const PAGE_FILE_REGEX = /^page\\.(tsx|ts|jsx|js)$/;\r\nexport const LAYOUT_FILE_BASENAME = \"layout\";\r\n\r\n/**\r\n * Creates a regex pattern for page files based on configuration.\r\n * \r\n * @param config - Framework configuration\r\n * @returns Regex pattern for matching page files\r\n */\r\nexport function createPageFileRegex(config: FrameworkConfig): RegExp {\r\n const pageName = config.conventions.page;\r\n return new RegExp(`^${pageName}\\\\.(tsx|ts|jsx|js)$`);\r\n}\r\n\r\n/**\r\n * Gets the layout file basename from configuration.\r\n * \r\n * @param config - Framework configuration\r\n * @returns Layout file basename\r\n */\r\nexport function getLayoutFileBasename(config: FrameworkConfig): string {\r\n return config.conventions.layout;\r\n}","/**\r\n * Path utilities for building route paths and regex patterns.\r\n */\r\n\r\n/**\r\n * Builds a route path from a relative directory path.\r\n * \r\n * @param relDir - Relative directory path (e.g., '', 'about', 'blog\\\\[slug]')\r\n * @returns Route path (e.g., '/', '/about', '/blog/[slug]')\r\n * \r\n * @example\r\n * buildRoutePathFromDir('') // '/'\r\n * buildRoutePathFromDir('about') // '/about'\r\n * buildRoutePathFromDir('blog\\\\[slug]') // '/blog/[slug]'\r\n */\r\nexport function buildRoutePathFromDir(relDir: string): string {\r\n if (!relDir || relDir === \".\") return \"/\";\r\n const clean = relDir.replace(/\\\\/g, \"/\");\r\n return \"/\" + clean;\r\n}\r\n\r\n/**\r\n * Builds a regex pattern and parameter names from a route path.\r\n * \r\n * Supports:\r\n * - Static segments: `/about` → `/^\\/about\\/?$/`\r\n * - Dynamic segments: `[slug]` → captures single segment\r\n * - Catch-all segments: `[...path]` → captures remaining path (must be last)\r\n * \r\n * @param routePath - Route path pattern (e.g., '/blog/[slug]', '/post/[...path]')\r\n * @returns Object with regex pattern and parameter names\r\n * \r\n * @example\r\n * buildRegexFromRoutePath('/blog/[slug]')\r\n * // { regex: /^\\/blog\\/([^\\/]+)\\/?$/, paramNames: ['slug'] }\r\n * \r\n * buildRegexFromRoutePath('/post/[...path]')\r\n * // { regex: /^\\/post\\/(.+)\\/?$/, paramNames: ['path'] }\r\n * \r\n * @throws Error if catch-all segment is not the last segment\r\n */\r\nexport function buildRegexFromRoutePath(routePath: string): {\r\n regex: RegExp;\r\n paramNames: string[];\r\n} {\r\n const segments = routePath.split(\"/\").filter(Boolean);\r\n const paramNames: string[] = [];\r\n const regexParts: string[] = [];\r\n\r\n for (let i = 0; i < segments.length; i++) {\r\n const seg = segments[i];\r\n\r\n // 1) Catch-all: [...slug]\r\n if (seg.startsWith(\"[...\") && seg.endsWith(\"]\")) {\r\n const paramName = seg.slice(4, -1); // \"[...slug]\" -> \"slug\"\r\n paramNames.push(paramName);\r\n\r\n // Catch-all must be the last segment\r\n if (i !== segments.length - 1) {\r\n throw new Error(\r\n `Catch-all segment \"${seg}\" in \"${routePath}\" must be the last segment.`\r\n );\r\n }\r\n\r\n // (.+) = one or more characters (non-empty), allows \"/\" inside\r\n regexParts.push(\"(.+)\");\r\n continue;\r\n }\r\n\r\n // 2) Normal param: [slug]\r\n if (seg.startsWith(\"[\") && seg.endsWith(\"]\")) {\r\n const paramName = seg.slice(1, -1);\r\n paramNames.push(paramName);\r\n regexParts.push(\"([^/]+)\");\r\n continue;\r\n }\r\n\r\n // 3) Static segment - escape special regex characters\r\n const escaped = seg.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\r\n regexParts.push(escaped);\r\n }\r\n\r\n const regexSource = \"^/\" + regexParts.join(\"/\") + \"/?$\";\r\n const regex = new RegExp(regexSource);\r\n\r\n return { regex, paramNames };\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { LayoutComponent } from \"./index.types\";\r\nimport { LAYOUT_FILE_BASENAME } from \"./constants\";\r\n\r\n/**\r\n * Finds a layout file in the given directory.\r\n * \r\n * Checks for layout files in this order:\r\n * 1. layout.tsx\r\n * 2. layout.ts\r\n * 3. layout.jsx\r\n * 4. layout.js\r\n * \r\n * @param dir - Directory to search for layout file\r\n * @returns Full path to layout file, or null if not found\r\n */\r\nexport function findLayoutFileInDir(dir: string): string | null {\r\n const candidates = [\r\n `${LAYOUT_FILE_BASENAME}.tsx`,\r\n `${LAYOUT_FILE_BASENAME}.ts`,\r\n `${LAYOUT_FILE_BASENAME}.jsx`,\r\n `${LAYOUT_FILE_BASENAME}.js`,\r\n ];\r\n\r\n for (const file of candidates) {\r\n const fullPath = path.join(dir, file);\r\n if (fs.existsSync(fullPath)) return fullPath;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Loads all layout components for a page directory.\r\n * \r\n * Walks up from the page directory to the app root, collecting layouts\r\n * at each level. Returns layouts in order from root to most specific.\r\n * \r\n * @param pageDir - Directory containing the page file\r\n * @param appDir - Root app directory\r\n * @returns Object with layout components and their file paths\r\n * \r\n * @example\r\n * // app/layout.tsx (root)\r\n * // app/blog/layout.tsx (blog)\r\n * // app/blog/[slug]/page.tsx (page)\r\n * \r\n * loadLayoutsForDir('app/blog/[slug]', 'app')\r\n * // Returns: [RootLayout, BlogLayout] (in that order)\r\n */\r\nexport function loadLayoutsForDir(\r\n pageDir: string,\r\n appDir: string\r\n): { components: LayoutComponent[]; files: string[] } {\r\n const componentsBottomUp: LayoutComponent[] = [];\r\n const filesBottomUp: string[] = [];\r\n\r\n let currentDir = pageDir;\r\n const appDirResolved = path.resolve(appDir);\r\n\r\n while (true) {\r\n const layoutFile = findLayoutFileInDir(currentDir);\r\n if (layoutFile) {\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n const mod = require(layoutFile);\r\n const LayoutComp: LayoutComponent = mod.default;\r\n if (LayoutComp) {\r\n componentsBottomUp.push(LayoutComp);\r\n filesBottomUp.push(layoutFile);\r\n }\r\n }\r\n\r\n const currentResolved = path.resolve(currentDir);\r\n if (currentResolved === appDirResolved) break;\r\n\r\n const parent = path.dirname(currentDir);\r\n if (parent === currentDir) break; // Reached filesystem root\r\n currentDir = parent;\r\n }\r\n\r\n // Reverse to get root → most specific order\r\n return {\r\n components: componentsBottomUp.reverse(),\r\n files: filesBottomUp.reverse(),\r\n };\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport {\r\n DynamicMode,\r\n GenerateStaticParams,\r\n RouteMiddleware,\r\n ServerLoader,\r\n} from \"./index.types\";\r\n\r\nconst NAMING = {\r\n // Constants & Fns\r\n BEFORE_MIDDLEWARES: \"beforeServerData\",\r\n GET_SERVER_DATA_FN: \"getServerSideProps\",\r\n GENERATE_SSG_PARAMS: \"generateStaticParams\",\r\n RENDER_TYPE_CONST: \"dynamic\",\r\n\r\n // Files\r\n SERVER_HOOK: 'server.hook',\r\n};\r\n\r\n/**\r\n * Loads server-side hooks (loader, middlewares, SSG config) from a directory.\r\n *\r\n * Looks for `server.hook.ts` or `server.hook.js` in the given directory.\r\n *\r\n * @param currentDir - Directory to search for server hook file\r\n * @returns Object containing middlewares, loader, dynamic mode, and generateStaticParams\r\n *\r\n * @example\r\n * // app/blog/[slug]/server.hook.ts\r\n * export const beforeServerData = [authMiddleware];\r\n * export const getServerSideProps = async (ctx) => ({ props: {} });\r\n * export const dynamic = \"force-static\";\r\n * export const generateStaticParams = async () => [{ slug: \"post-1\" }];\r\n */\r\nexport function loadLoaderForDir(currentDir: string): {\r\n middlewares: RouteMiddleware[];\r\n loader: ServerLoader | null;\r\n dynamic: DynamicMode;\r\n generateStaticParams: GenerateStaticParams | null;\r\n} {\r\n const loaderTs = path.join(currentDir, `${NAMING.SERVER_HOOK}.ts`);\r\n const loaderJs = path.join(currentDir, `${NAMING.SERVER_HOOK}.js`);\r\n\r\n const file = fs.existsSync(loaderTs)\r\n ? loaderTs\r\n : fs.existsSync(loaderJs)\r\n ? loaderJs\r\n : null;\r\n\r\n if (!file) {\r\n return {\r\n middlewares: [],\r\n loader: null,\r\n dynamic: \"auto\",\r\n generateStaticParams: null,\r\n };\r\n }\r\n\r\n // Ensure tsx is loaded for TypeScript files during build\r\n // tsx automatically reads tsconfig.json from the project root to resolve path aliases\r\n if (file.endsWith('.ts') || file.endsWith('.tsx')) {\r\n try {\r\n // Load tsx if not already loaded - it will handle TypeScript compilation and path resolution\r\n require('tsx/cjs');\r\n } catch (e) {\r\n // tsx might already be loaded, ignore error\r\n }\r\n }\r\n\r\n let mod;\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n mod = require(file);\r\n } catch (error) {\r\n console.error(\r\n `[framework][loader] Error loading server hook from ${file}:`,\r\n error\r\n );\r\n // Return defaults if module fails to load\r\n return {\r\n middlewares: [],\r\n loader: null,\r\n dynamic: \"auto\",\r\n generateStaticParams: null,\r\n };\r\n }\r\n\r\n const middlewares: RouteMiddleware[] = Array.isArray(\r\n mod?.[NAMING.BEFORE_MIDDLEWARES]\r\n )\r\n ? mod[NAMING.BEFORE_MIDDLEWARES]\r\n : [];\r\n\r\n const loader: ServerLoader | null =\r\n typeof mod?.[NAMING.GET_SERVER_DATA_FN] === \"function\"\r\n ? mod[NAMING.GET_SERVER_DATA_FN]\r\n : null;\r\n\r\n const dynamic: DynamicMode =\r\n mod?.[NAMING.RENDER_TYPE_CONST] === \"force-static\" ||\r\n mod?.[NAMING.RENDER_TYPE_CONST] === \"force-dynamic\"\r\n ? mod.dynamic\r\n : \"auto\";\r\n\r\n const generateStaticParams: GenerateStaticParams | null =\r\n typeof mod?.[NAMING.GENERATE_SSG_PARAMS] === \"function\"\r\n ? mod[NAMING.GENERATE_SSG_PARAMS]\r\n : null;\r\n\r\n return {\r\n middlewares,\r\n loader,\r\n dynamic,\r\n generateStaticParams,\r\n };\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { ApiRoute } from \"./index.types\";\r\nimport {\r\n extractApiHandlers,\r\n extractApiMiddlewares,\r\n extractRouteRegex,\r\n loadModuleSafely,\r\n} from \"./helpers/routes\";\r\n\r\nconst ROUTE_FILE_REGEX = /route\\.(ts|tsx|js|jsx)$/;\r\nconst HTTP_METHODS = [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"];\r\n\r\n/**\r\n * Scans the app/api directory and loads all API routes.\r\n * \r\n * Recursively walks through the app/api directory, finding all `route.ts`, `route.tsx`,\r\n * `route.js`, or `route.jsx` files and creating API route definitions.\r\n * \r\n * @param appDir - Root directory of the app (e.g., 'app')\r\n * @returns Array of loaded API routes with handlers and middlewares\r\n * \r\n * @example\r\n * const apiRoutes = loadApiRoutes('app');\r\n * // [\r\n * // {\r\n * // pattern: '/api/posts/[id]',\r\n * // handlers: { GET: getPost, POST: updatePost },\r\n * // middlewares: [authMiddleware],\r\n * // methodMiddlewares: { GET: [logMiddleware] },\r\n * // },\r\n * // ]\r\n */\r\nexport function loadApiRoutes(appDir: string): ApiRoute[] {\r\n const apiRoot = path.join(appDir, \"api\");\r\n const routes: ApiRoute[] = [];\r\n\r\n if (!fs.existsSync(apiRoot)) return routes;\r\n\r\n function walk(currentDir: string) {\r\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(currentDir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n walk(fullPath);\r\n continue;\r\n }\r\n\r\n // Only process route files\r\n if (!ROUTE_FILE_REGEX.test(entry.name)) continue;\r\n\r\n const relToApp = path.relative(appDir, fullPath).replace(/\\\\/g, \"/\");\r\n const withoutRoute = relToApp.replace(/\\/route\\.(ts|tsx|js|jsx)$/, \"\");\r\n const pattern = \"/\" + withoutRoute;\r\n\r\n const { regex, paramNames } = extractRouteRegex(pattern);\r\n\r\n const mod = loadModuleSafely(fullPath);\r\n if (!mod) {\r\n continue;\r\n }\r\n\r\n const handlers = extractApiHandlers(mod, HTTP_METHODS);\r\n const { global: globalMiddlewares, methodSpecific: methodMiddlewares } =\r\n extractApiMiddlewares(mod, HTTP_METHODS);\r\n\r\n routes.push({\r\n pattern,\r\n regex,\r\n paramNames,\r\n handlers,\r\n middlewares: globalMiddlewares,\r\n methodMiddlewares,\r\n filePath: fullPath,\r\n });\r\n }\r\n }\r\n\r\n walk(apiRoot);\r\n\r\n return routes;\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport {\r\n ApiHandler,\r\n ApiMiddleware,\r\n LayoutComponent,\r\n PageComponent,\r\n RoutesManifest,\r\n} from \"../../index.types\";\r\nimport { buildRegexFromRoutePath } from \"../../path\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\n/**\r\n * Reads and parses the routes manifest file.\r\n */\r\nexport function readManifest(projectRoot: string): RoutesManifest | null {\r\n const manifestPath = path.join(\r\n projectRoot,\r\n BUILD_FOLDER_NAME,\r\n \"routes-manifest.json\"\r\n );\r\n\r\n if (!fs.existsSync(manifestPath)) {\r\n return null;\r\n }\r\n\r\n const raw = fs.readFileSync(manifestPath, \"utf-8\");\r\n return JSON.parse(raw) as RoutesManifest;\r\n}\r\n\r\n/**\r\n * Safely loads a module with error handling.\r\n */\r\nexport function loadModuleSafely(filePath: string): any | null {\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n return require(filePath);\r\n } catch (err) {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Loads and processes layout components from layout file paths.\r\n */\r\nexport function loadLayouts(\r\n layoutFiles: string[],\r\n projectRoot: string\r\n): LayoutComponent[] {\r\n const layoutMods = layoutFiles.map((lf) => {\r\n const fullPath = path.join(projectRoot, lf);\r\n return loadModuleSafely(fullPath);\r\n });\r\n\r\n return layoutMods\r\n .filter((m): m is { default: LayoutComponent } => !!m?.default)\r\n .map((m) => m.default);\r\n}\r\n\r\n/**\r\n * Builds regex and extracts param names from a route pattern.\r\n */\r\nexport function extractRouteRegex(pattern: string, paramNames?: string[]) {\r\n const { regex, paramNames: extractedParamNames } =\r\n buildRegexFromRoutePath(pattern);\r\n return {\r\n regex,\r\n paramNames: paramNames ?? extractedParamNames,\r\n };\r\n}\r\n\r\n/**\r\n * Extracts HTTP method handlers from a module.\r\n */\r\nexport function extractApiHandlers(\r\n mod: any,\r\n methods: string[]\r\n): Record<string, ApiHandler> {\r\n const handlers: Record<string, ApiHandler> = {};\r\n\r\n for (const method of methods) {\r\n if (typeof mod[method] === \"function\") {\r\n handlers[method] = mod[method] as ApiHandler;\r\n }\r\n }\r\n\r\n return handlers;\r\n}\r\n\r\n/**\r\n * Extracts global and method-specific middlewares from a module.\r\n */\r\nexport function extractApiMiddlewares(\r\n mod: any,\r\n methods: string[]\r\n): {\r\n global: ApiMiddleware[];\r\n methodSpecific: Record<string, ApiMiddleware[]>;\r\n} {\r\n const globalMiddlewares: ApiMiddleware[] = Array.isArray(mod.beforeApi)\r\n ? mod.beforeApi\r\n : [];\r\n\r\n const methodMiddlewares: Record<string, ApiMiddleware[]> = {};\r\n\r\n for (const method of methods) {\r\n const key = `before${method}`;\r\n const mws = mod[key];\r\n if (Array.isArray(mws)) {\r\n methodMiddlewares[method] = mws as ApiMiddleware[];\r\n }\r\n }\r\n\r\n return {\r\n global: globalMiddlewares,\r\n methodSpecific: methodMiddlewares,\r\n };\r\n}\r\n\r\n/**\r\n * Extracts WebSocket event handlers from a module.\r\n */\r\nexport function extractWssHandlers(\r\n mod: any,\r\n events: string[]\r\n): Record<string, ApiHandler> {\r\n const handlers: Record<string, ApiHandler> = {};\r\n\r\n if (!Array.isArray(mod.events)) {\r\n return handlers;\r\n }\r\n\r\n for (const eventName of events) {\r\n if (typeof eventName === \"string\") {\r\n const event = mod.events.find(\r\n (e: { name: string }) => e.name?.toLowerCase() === eventName.toLowerCase()\r\n );\r\n if (event?.handler) {\r\n handlers[eventName] = event.handler as ApiHandler;\r\n }\r\n }\r\n }\r\n\r\n return handlers;\r\n}\r\n\r\n/**\r\n * Extracts all WebSocket event handlers directly from a module's events array.\r\n * This is used when scanning filesystem routes where we iterate over all events.\r\n */\r\nexport function extractWssHandlersFromModule(mod: any): Record<string, ApiHandler> {\r\n const handlers: Record<string, ApiHandler> = {};\r\n\r\n if (!Array.isArray(mod?.events)) {\r\n return handlers;\r\n }\r\n\r\n for (const event of mod.events) {\r\n if (typeof event.handler === \"function\" && typeof event.name === \"string\") {\r\n handlers[event.name.toLowerCase()] = event.handler as ApiHandler;\r\n }\r\n }\r\n\r\n return handlers;\r\n}\r\n\r\n/**\r\n * Loads a page component from a file path.\r\n */\r\nexport function loadPageComponent(\r\n pageFile: string,\r\n projectRoot: string\r\n): PageComponent | null {\r\n const fullPath = path.join(projectRoot, pageFile);\r\n const pageMod = loadModuleSafely(fullPath);\r\n return pageMod?.default || null;\r\n}\r\n\r\n","import { ApiRoute, LoadedRoute } from \"./index.types\";\r\n\r\n/**\r\n * Matches a URL path against loaded routes and returns the matched route with params.\r\n * \r\n * @param routes - Array of loaded routes to match against\r\n * @param urlPath - URL path to match (e.g., '/blog/my-post')\r\n * @returns Matched route with extracted parameters, or null if no match\r\n * \r\n * @example\r\n * const routes = loadRoutes('app');\r\n * const match = matchRoute(routes, '/blog/my-post');\r\n * // { route: LoadedRoute, params: { slug: 'my-post' } }\r\n */\r\nexport function matchRoute(\r\n routes: LoadedRoute[],\r\n urlPath: string\r\n): { route: LoadedRoute; params: Record<string, string> } | null {\r\n for (const route of routes) {\r\n const match = route.regex.exec(urlPath);\r\n if (!match) continue;\r\n\r\n const params: Record<string, string> = {};\r\n route.paramNames.forEach((name, idx) => {\r\n params[name] = match[idx + 1];\r\n });\r\n\r\n return { route, params };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Matches a URL path against API routes and returns the matched route with params.\r\n * \r\n * @param routes - Array of API routes to match against\r\n * @param pathname - URL path to match (e.g., '/api/posts/123')\r\n * @returns Matched API route with extracted parameters, or null if no match\r\n * \r\n * @example\r\n * const apiRoutes = loadApiRoutes('app');\r\n * const match = matchApiRoute(apiRoutes, '/api/posts/123');\r\n * // { route: ApiRoute, params: { id: '123' } }\r\n */\r\nexport function matchApiRoute(\r\n routes: ApiRoute[],\r\n pathname: string\r\n): { route: ApiRoute; params: Record<string, string> } | null {\r\n for (const r of routes) {\r\n const match = r.regex.exec(pathname);\r\n if (!match) continue;\r\n\r\n const params: Record<string, string> = {};\r\n r.paramNames.forEach((name, idx) => {\r\n params[name] = match[idx + 1];\r\n });\r\n\r\n return { route: r, params };\r\n }\r\n return null;\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport {\r\n ApiRoute,\r\n ApiRouteManifestEntry,\r\n LoadedRoute,\r\n PageRouteManifestEntry,\r\n RoutesManifest,\r\n WssRoute,\r\n WssRouteManifestEntry,\r\n} from \"./index.types\";\r\nimport {\r\n BUILD_FOLDER_NAME,\r\n STYLE_FILE_NAME,\r\n NOT_FOUND_FILE_PREFIX,\r\n ERROR_FILE_PREFIX,\r\n NOT_FOUND_CHUNK_KEY,\r\n ERROR_CHUNK_KEY,\r\n NOT_FOUND_PATTERN,\r\n ERROR_PATTERN,\r\n} from \"@constants/globals\";\r\n\r\n/**\r\n * Writes the client-side routes manifest file.\r\n *\r\n * Generates a TypeScript file that exports route definitions with lazy-loaded\r\n * components for code splitting. The manifest is used by the client runtime\r\n * to handle client-side navigation.\r\n *\r\n * @param routes - Array of loaded routes\r\n * @param projectRoot - Root directory of the project\r\n * @param errorRoute - Optional error route for client-side error handling\r\n */\r\nexport function writeClientRoutesManifest(\r\n routes: LoadedRoute[],\r\n projectRoot: string\r\n): void {\r\n const fwDir = path.join(projectRoot, BUILD_FOLDER_NAME);\r\n if (!fs.existsSync(fwDir)) {\r\n fs.mkdirSync(fwDir, { recursive: true });\r\n }\r\n\r\n const manifestPath = path.join(fwDir, \"routes-client.ts\");\r\n const manifestDir = path.dirname(manifestPath);\r\n\r\n function toImportPath(filePath: string): string {\r\n const relRaw = path.relative(manifestDir, filePath).replace(/\\\\/g, \"/\");\r\n const rel = relRaw.startsWith(\".\") ? relRaw : \"./\" + relRaw;\r\n // Remove extension so bundler can resolve .tsx, .ts, .jsx, .js\r\n return rel.replace(/\\.(tsx|ts|jsx|js)$/, \"\");\r\n }\r\n\r\n function findUserNotFound(): string | null {\r\n const candidates = [\r\n `app/${NOT_FOUND_FILE_PREFIX}.tsx`,\r\n `app/${NOT_FOUND_FILE_PREFIX}.ts`,\r\n `app/${NOT_FOUND_FILE_PREFIX}.jsx`,\r\n `app/${NOT_FOUND_FILE_PREFIX}.js`,\r\n // Fallback to old style for backward compatibility\r\n \"app/not-found/page.tsx\",\r\n \"app/not-found/page.ts\",\r\n \"app/not-found/page.jsx\",\r\n \"app/not-found/page.js\",\r\n ];\r\n\r\n for (const rel of candidates) {\r\n const full = path.join(projectRoot, rel);\r\n if (fs.existsSync(full)) return full;\r\n }\r\n return null;\r\n }\r\n\r\n function findUserError(): string | null {\r\n const candidates = [\r\n `app/${ERROR_FILE_PREFIX}.tsx`,\r\n `app/${ERROR_FILE_PREFIX}.ts`,\r\n `app/${ERROR_FILE_PREFIX}.jsx`,\r\n `app/${ERROR_FILE_PREFIX}.js`,\r\n ];\r\n\r\n for (const rel of candidates) {\r\n const full = path.join(projectRoot, rel);\r\n if (fs.existsSync(full)) return full;\r\n }\r\n return null;\r\n }\r\n\r\n function findRootLayout(): string | null {\r\n const candidates = [\r\n \"app/layout.tsx\",\r\n \"app/layout.ts\",\r\n \"app/layout.jsx\",\r\n \"app/layout.js\",\r\n ];\r\n\r\n for (const rel of candidates) {\r\n const full = path.join(projectRoot, rel);\r\n if (fs.existsSync(full)) return full;\r\n }\r\n return null;\r\n }\r\n\r\n const lines: string[] = [];\r\n const chunkMap: Record<string, string> = {};\r\n\r\n lines.push(`import React from \"react\";`);\r\n lines.push(\"\");\r\n\r\n lines.push(`export interface ClientLoadedComponents {`);\r\n lines.push(` Page: React.ComponentType<any>;`);\r\n lines.push(` layouts: React.ComponentType<any>[];`);\r\n lines.push(`}`);\r\n lines.push(\"\");\r\n\r\n lines.push(`export interface ClientRouteLoaded {`);\r\n lines.push(` pattern: string;`);\r\n lines.push(` paramNames: string[];`);\r\n lines.push(` load: () => Promise<ClientLoadedComponents>;`);\r\n lines.push(`}`);\r\n lines.push(\"\");\r\n\r\n // --- rutas normales ---\r\n lines.push(`export const routes: ClientRouteLoaded[] = [`);\r\n\r\n for (const route of routes) {\r\n const pattern = route.pattern;\r\n const paramNames = route.paramNames;\r\n\r\n const modulePaths = [route.pageFile, ...route.layoutFiles].map(\r\n toImportPath\r\n );\r\n\r\n const safeName =\r\n pattern.replace(/^\\//, \"\").replace(/\\//g, \"_\").replace(/\\[|\\]/g, \"\") ||\r\n \"root\";\r\n\r\n const chunkName = `route-${safeName}`;\r\n chunkMap[pattern] = chunkName;\r\n\r\n lines.push(\" {\");\r\n lines.push(` pattern: ${JSON.stringify(pattern)},`);\r\n lines.push(` paramNames: ${JSON.stringify(paramNames)},`);\r\n lines.push(` load: async () => {`);\r\n lines.push(` const mods = await Promise.all([`);\r\n\r\n for (const p of modulePaths) {\r\n lines.push(\r\n ` import(/* webpackChunkName: \"${chunkName}\" */ \"${p}\"),`\r\n );\r\n }\r\n\r\n lines.push(\" ]);\");\r\n lines.push(\" const [pageMod, ...layoutMods] = mods;\");\r\n lines.push(\" return {\");\r\n lines.push(\" Page: pageMod.default,\");\r\n lines.push(\" layouts: layoutMods.map((m) => m.default),\");\r\n lines.push(\" };\");\r\n lines.push(\" },\");\r\n lines.push(\" },\");\r\n }\r\n\r\n lines.push(\"];\");\r\n lines.push(\"\");\r\n\r\n const notFoundPath = findUserNotFound();\r\n const errorPath = findUserError();\r\n const rootLayoutPath = findRootLayout();\r\n\r\n if (notFoundPath) {\r\n const notFoundImportPath = toImportPath(notFoundPath);\r\n const chunkName = \"route-not-found\";\r\n\r\n lines.push(`export const notFoundRoute: ClientRouteLoaded = {`);\r\n lines.push(` pattern: \"${NOT_FOUND_CHUNK_KEY}\",`);\r\n lines.push(` paramNames: [],`);\r\n lines.push(` load: async () => {`);\r\n lines.push(` const mods = await Promise.all([`);\r\n lines.push(\r\n ` import(/* webpackChunkName: \"${chunkName}\" */ \"${notFoundImportPath}\"),`\r\n );\r\n\r\n if (rootLayoutPath) {\r\n const rootLayoutImportPath = toImportPath(rootLayoutPath);\r\n lines.push(\r\n ` import(/* webpackChunkName: \"${chunkName}\" */ \"${rootLayoutImportPath}\"),`\r\n );\r\n }\r\n\r\n lines.push(` ]);`);\r\n lines.push(` const [pageMod, ...layoutMods] = mods;`);\r\n lines.push(` return {`);\r\n lines.push(` Page: pageMod.default,`);\r\n lines.push(` layouts: layoutMods.map((m) => m.default),`);\r\n lines.push(` };`);\r\n lines.push(` },`);\r\n lines.push(`};`);\r\n lines.push(\"\");\r\n\r\n chunkMap[NOT_FOUND_CHUNK_KEY] = chunkName;\r\n } else {\r\n lines.push(`export const notFoundRoute: ClientRouteLoaded | null = null;`);\r\n lines.push(\"\");\r\n }\r\n\r\n if (errorPath) {\r\n const errorImportPath = toImportPath(errorPath);\r\n const chunkName = \"route-error\";\r\n\r\n lines.push(`export const errorRoute: ClientRouteLoaded = {`);\r\n lines.push(` pattern: \"${ERROR_CHUNK_KEY}\",`);\r\n lines.push(` paramNames: [],`);\r\n lines.push(` load: async () => {`);\r\n lines.push(` const mods = await Promise.all([`);\r\n lines.push(\r\n ` import(/* webpackChunkName: \"${chunkName}\" */ \"${errorImportPath}\"),`\r\n );\r\n\r\n if (rootLayoutPath) {\r\n const rootLayoutImportPath = toImportPath(rootLayoutPath);\r\n lines.push(\r\n ` import(/* webpackChunkName: \"${chunkName}\" */ \"${rootLayoutImportPath}\"),`\r\n );\r\n }\r\n\r\n lines.push(` ]);`);\r\n lines.push(` const [pageMod, ...layoutMods] = mods;`);\r\n lines.push(` return {`);\r\n lines.push(` Page: pageMod.default,`);\r\n lines.push(` layouts: layoutMods.map((m) => m.default),`);\r\n lines.push(` };`);\r\n lines.push(` },`);\r\n lines.push(`};`);\r\n lines.push(\"\");\r\n\r\n chunkMap[ERROR_CHUNK_KEY] = chunkName;\r\n } else {\r\n lines.push(`export const errorRoute: ClientRouteLoaded | null = null;`);\r\n lines.push(\"\");\r\n }\r\n\r\n fs.writeFileSync(manifestPath, lines.join(\"\\n\"), \"utf-8\");\r\n\r\n const chunksJsonPath = path.join(fwDir, \"route-chunks.json\");\r\n fs.writeFileSync(chunksJsonPath, JSON.stringify(chunkMap, null, 2), \"utf-8\");\r\n}\r\n\r\n/**\r\n * Writes the client bootstrap manifest file.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n */\r\nexport function writeClientBoostrapManifest(projectRoot: string): void {\r\n const buildDir = path.join(projectRoot, BUILD_FOLDER_NAME);\r\n if (!fs.existsSync(buildDir)) {\r\n fs.mkdirSync(buildDir, { recursive: true });\r\n }\r\n\r\n const manifestPath = path.join(buildDir, \"boostrap.ts\");\r\n\r\n const lines: string[] = [];\r\n\r\n lines.push(`import \"../app/${STYLE_FILE_NAME}\";`);\r\n lines.push(\"\");\r\n\r\n lines.push(`import {`);\r\n lines.push(` routes,`);\r\n lines.push(` type ClientRouteLoaded,`);\r\n lines.push(` notFoundRoute,`);\r\n lines.push(` errorRoute,`);\r\n lines.push(`} from \"./routes-client\";`);\r\n lines.push(\"\");\r\n\r\n lines.push(`import { bootstrapClient } from \"@lolyjs/core/runtime\"`);\r\n lines.push(\"\");\r\n lines.push(\r\n \"bootstrapClient(routes as ClientRouteLoaded[], notFoundRoute, errorRoute);\"\r\n );\r\n\r\n fs.writeFileSync(manifestPath, lines.join(\"\\n\"), \"utf-8\");\r\n}\r\n\r\n/**\r\n * Writes the routes manifest JSON file.\r\n *\r\n * This manifest contains only data (no functions) and is:\r\n * - Readable by Node without compiling TypeScript\r\n * - Usable by the production server\r\n * - Usable by build/SSG processes\r\n *\r\n * @param routes - Array of loaded page routes\r\n * @param apiRoutes - Array of loaded API routes\r\n * @param notFoundRoute - Not-found route definition\r\n * @param errorRoute - Error route definition (optional)\r\n * @param projectRoot - Root directory of the project\r\n * @param serverOutDir - Server output directory from buildServerApp\r\n * @param appDir - Absolute path to the app directory\r\n */\r\nexport function writeRoutesManifest({\r\n routes,\r\n apiRoutes,\r\n wssRoutes,\r\n notFoundRoute,\r\n errorRoute,\r\n projectRoot,\r\n serverOutDir,\r\n appDir,\r\n}: {\r\n routes: LoadedRoute[];\r\n apiRoutes: ApiRoute[];\r\n wssRoutes: WssRoute[];\r\n notFoundRoute: LoadedRoute;\r\n errorRoute: LoadedRoute | null;\r\n projectRoot: string;\r\n serverOutDir: string;\r\n appDir: string;\r\n}) {\r\n const fwDir = path.join(projectRoot, BUILD_FOLDER_NAME);\r\n if (!fs.existsSync(fwDir)) {\r\n fs.mkdirSync(fwDir, { recursive: true });\r\n }\r\n\r\n const manifestPath = path.join(fwDir, \"routes-manifest.json\");\r\n\r\n const toRelative = (abs: string) =>\r\n path.relative(projectRoot, abs).replace(/\\\\/g, \"/\");\r\n\r\n const convertToJs = (file: string) =>\r\n file.replace(/\\.(ts|tsx|jsx|mjs|cjs)$/i, \".js\");\r\n\r\n const pageEntries: PageRouteManifestEntry[] = routes.map((r) => {\r\n const relativeSource = path.relative(appDir, r.pageFile);\r\n\r\n const jsPageFile = path.join(serverOutDir, convertToJs(relativeSource));\r\n\r\n const jsLayoutFiles = r.layoutFiles.map((lf) => {\r\n const rel = path.relative(appDir, lf);\r\n return path.join(serverOutDir, convertToJs(rel));\r\n });\r\n\r\n return {\r\n type: \"page\",\r\n pattern: r.pattern,\r\n paramNames: r.paramNames,\r\n pageFile: toRelative(jsPageFile),\r\n layoutFiles: jsLayoutFiles.map(toRelative),\r\n dynamic: r.dynamic,\r\n };\r\n });\r\n\r\n const apiEntries: ApiRouteManifestEntry[] = apiRoutes\r\n .map((r) => {\r\n const anyRoute = r as any;\r\n const filePath: string | undefined = anyRoute.filePath;\r\n\r\n if (!filePath) {\r\n return undefined;\r\n }\r\n\r\n const relSource = path.relative(appDir, filePath);\r\n\r\n const jsApiFile = path.join(serverOutDir, convertToJs(relSource));\r\n\r\n const methods = Object.keys(r.handlers || {});\r\n\r\n const entry: ApiRouteManifestEntry = {\r\n type: \"api\",\r\n pattern: r.pattern,\r\n paramNames: r.paramNames,\r\n file: toRelative(jsApiFile),\r\n methods,\r\n };\r\n\r\n return entry;\r\n })\r\n .filter((e): e is ApiRouteManifestEntry => !!e);\r\n\r\n const wssEntries: WssRouteManifestEntry[] = wssRoutes\r\n .map((r) => {\r\n const anyRoute = r as any;\r\n const filePath: string | undefined = anyRoute.filePath;\r\n\r\n if (!filePath) {\r\n return undefined;\r\n }\r\n\r\n const relSource = path.relative(appDir, filePath);\r\n\r\n const jsApiFile = path.join(serverOutDir, convertToJs(relSource));\r\n\r\n const events = Object.keys(r.handlers || {});\r\n\r\n const entry: WssRouteManifestEntry = {\r\n type: \"wss\",\r\n pattern: r.pattern,\r\n paramNames: r.paramNames,\r\n file: toRelative(jsApiFile),\r\n events,\r\n };\r\n\r\n return entry;\r\n })\r\n .filter((e): e is WssRouteManifestEntry => !!e);\r\n\r\n // Build not-found page entry\r\n const notFoundLayoutFiles = notFoundRoute.layoutFiles || [];\r\n const notFoundJsLayoutFiles = notFoundLayoutFiles.map((lf) => {\r\n const rel = path.relative(appDir, lf);\r\n return path.join(serverOutDir, convertToJs(rel));\r\n });\r\n\r\n const notFoundRelativeSource = notFoundRoute.pageFile\r\n ? path.relative(appDir, notFoundRoute.pageFile)\r\n : `${NOT_FOUND_FILE_PREFIX}.tsx`;\r\n const notFoundJsPageFile = notFoundRoute.pageFile\r\n ? path.join(serverOutDir, convertToJs(notFoundRelativeSource))\r\n : path.join(serverOutDir, convertToJs(`${NOT_FOUND_FILE_PREFIX}.tsx`));\r\n\r\n const notFoundPage: PageRouteManifestEntry = {\r\n type: \"page\",\r\n pageFile: toRelative(notFoundJsPageFile),\r\n layoutFiles: notFoundJsLayoutFiles.map(toRelative),\r\n dynamic: \"force-static\",\r\n paramNames: [],\r\n pattern: NOT_FOUND_PATTERN,\r\n };\r\n\r\n // Build error page entry (if exists)\r\n let errorPageEntry: PageRouteManifestEntry | undefined;\r\n if (errorRoute && errorRoute.pageFile) {\r\n const errorLayoutFiles = errorRoute.layoutFiles || [];\r\n const errorJsLayoutFiles = errorLayoutFiles.map((lf) => {\r\n const rel = path.relative(appDir, lf);\r\n return path.join(serverOutDir, convertToJs(rel));\r\n });\r\n\r\n const errorRelativeSource = path.relative(appDir, errorRoute.pageFile);\r\n const errorJsPageFile = path.join(\r\n serverOutDir,\r\n convertToJs(errorRelativeSource)\r\n );\r\n\r\n errorPageEntry = {\r\n type: \"page\",\r\n pageFile: toRelative(errorJsPageFile),\r\n layoutFiles: errorJsLayoutFiles.map(toRelative),\r\n dynamic: \"force-static\",\r\n paramNames: [],\r\n pattern: ERROR_PATTERN,\r\n };\r\n }\r\n\r\n const manifest: RoutesManifest = {\r\n version: 1,\r\n basePath: \"\",\r\n caseSensitive: false,\r\n pages404: true,\r\n routes: pageEntries,\r\n apiRoutes: apiEntries,\r\n notFound: notFoundPage,\r\n wssRoutes: wssEntries,\r\n ...(errorPageEntry && { error: errorPageEntry }),\r\n };\r\n\r\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), \"utf-8\");\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport {\r\n ApiRoute,\r\n LoadedRoute,\r\n WssRoute,\r\n} from \"./index.types\";\r\nimport { loadLoaderForDir } from \"./loader\";\r\nimport { BUILD_FOLDER_NAME, ERROR_PATTERN } from \"@constants/globals\";\r\nimport {\r\n extractApiHandlers,\r\n extractApiMiddlewares,\r\n extractRouteRegex,\r\n extractWssHandlers,\r\n loadLayouts,\r\n loadModuleSafely,\r\n loadPageComponent,\r\n readManifest,\r\n} from \"./helpers/routes\";\r\n\r\n/**\r\n * Loads page and API routes from the routes manifest file.\r\n * Used in production to avoid filesystem scanning.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @returns Object containing loaded routes and API routes\r\n */\r\nexport function loadRoutesFromManifest(projectRoot: string): {\r\n routes: LoadedRoute[];\r\n apiRoutes: ApiRoute[];\r\n wssRoutes: WssRoute[];\r\n} {\r\n const manifest = readManifest(projectRoot);\r\n if (!manifest) {\r\n return { routes: [], apiRoutes: [], wssRoutes: [] };\r\n }\r\n\r\n const pageRoutes: LoadedRoute[] = [];\r\n\r\n for (const entry of manifest.routes) {\r\n const { regex, paramNames } = extractRouteRegex(\r\n entry.pattern,\r\n entry.paramNames\r\n );\r\n\r\n const component = loadPageComponent(entry.pageFile, projectRoot);\r\n if (!component) {\r\n continue;\r\n }\r\n\r\n const layouts = loadLayouts(entry.layoutFiles, projectRoot);\r\n const pageFile = path.join(projectRoot, entry.pageFile);\r\n const layoutFiles = entry.layoutFiles.map((f) =>\r\n path.join(projectRoot, f)\r\n );\r\n const pageDir = path.dirname(pageFile);\r\n const { middlewares, loader, dynamic, generateStaticParams } =\r\n loadLoaderForDir(pageDir);\r\n\r\n pageRoutes.push({\r\n pattern: entry.pattern,\r\n regex,\r\n paramNames,\r\n component,\r\n layouts,\r\n pageFile,\r\n layoutFiles,\r\n middlewares,\r\n loader,\r\n dynamic: entry.dynamic ?? dynamic,\r\n generateStaticParams,\r\n });\r\n }\r\n\r\n const apiRoutes: ApiRoute[] = [];\r\n const httpMethods = [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"];\r\n\r\n for (const entry of manifest.apiRoutes) {\r\n const { regex, paramNames } = extractRouteRegex(\r\n entry.pattern,\r\n entry.paramNames\r\n );\r\n const filePath = path.join(projectRoot, entry.file);\r\n const mod = loadModuleSafely(filePath);\r\n\r\n if (!mod) {\r\n continue;\r\n }\r\n\r\n const handlers = extractApiHandlers(mod, httpMethods);\r\n const { global: globalMiddlewares, methodSpecific: methodMiddlewares } =\r\n extractApiMiddlewares(mod, httpMethods);\r\n\r\n apiRoutes.push({\r\n pattern: entry.pattern,\r\n regex,\r\n paramNames,\r\n handlers,\r\n middlewares: globalMiddlewares,\r\n methodMiddlewares,\r\n filePath,\r\n });\r\n }\r\n\r\n const wssRoutes: WssRoute[] = [];\r\n\r\n for (const entry of manifest.wssRoutes) {\r\n const { regex, paramNames } = extractRouteRegex(\r\n entry.pattern,\r\n entry.paramNames\r\n );\r\n const filePath = path.join(projectRoot, entry.file);\r\n const mod = loadModuleSafely(filePath);\r\n\r\n if (!mod) {\r\n continue;\r\n }\r\n\r\n const handlers = extractWssHandlers(mod, entry.events || []);\r\n const { global: globalMiddlewares, methodSpecific: methodMiddlewares } =\r\n extractApiMiddlewares(mod, []);\r\n\r\n wssRoutes.push({\r\n pattern: entry.pattern,\r\n regex,\r\n paramNames,\r\n handlers,\r\n middlewares: globalMiddlewares,\r\n methodMiddlewares,\r\n filePath,\r\n });\r\n }\r\n\r\n return { routes: pageRoutes, apiRoutes, wssRoutes };\r\n}\r\n\r\n/**\r\n * Loads route chunks mapping from the manifest file.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @returns Record mapping route patterns to chunk names\r\n */\r\nexport function loadChunksFromManifest(projectRoot: string): Record<string, string> {\r\n const chunksPath = path.join(\r\n projectRoot,\r\n BUILD_FOLDER_NAME,\r\n \"route-chunks.json\"\r\n );\r\n let routeChunks: Record<string, string> = {};\r\n if (fs.existsSync(chunksPath)) {\r\n try {\r\n routeChunks = JSON.parse(fs.readFileSync(chunksPath, \"utf-8\"));\r\n } catch (err) {\r\n // Silently fail if chunks file is invalid\r\n }\r\n }\r\n\r\n return routeChunks;\r\n}\r\n\r\n/**\r\n * Loads the not-found route from the routes manifest.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @returns LoadedRoute for the not-found page, or null if not found\r\n */\r\nexport function loadNotFoundFromManifest(\r\n projectRoot: string\r\n): LoadedRoute | null {\r\n const manifest = readManifest(projectRoot);\r\n if (!manifest) {\r\n return null;\r\n }\r\n\r\n const component = loadPageComponent(manifest.notFound.pageFile, projectRoot);\r\n if (!component) {\r\n return null;\r\n }\r\n\r\n const layouts = loadLayouts(manifest.notFound.layoutFiles, projectRoot);\r\n const pageFile = path.join(projectRoot, manifest.notFound.pageFile);\r\n\r\n return {\r\n pattern: \"\",\r\n regex: new RegExp(\"\"),\r\n paramNames: [],\r\n component,\r\n layouts,\r\n pageFile,\r\n layoutFiles: [],\r\n middlewares: [],\r\n loader: null,\r\n dynamic: \"force-static\",\r\n generateStaticParams: null,\r\n };\r\n}\r\n\r\n/**\r\n * Loads the error route from the routes manifest.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @returns LoadedRoute for the error page, or null if not found\r\n */\r\nexport function loadErrorFromManifest(\r\n projectRoot: string\r\n): LoadedRoute | null {\r\n const manifest = readManifest(projectRoot);\r\n if (!manifest) {\r\n return null;\r\n }\r\n\r\n // Check if error page exists in manifest\r\n const errorEntry = (manifest as any).error;\r\n if (!errorEntry) {\r\n return null;\r\n }\r\n\r\n const component = loadPageComponent(errorEntry.pageFile, projectRoot);\r\n if (!component) {\r\n return null;\r\n }\r\n\r\n const layoutFiles = (errorEntry.layoutFiles || []) as string[];\r\n const layouts = loadLayouts(layoutFiles, projectRoot);\r\n const pageFile = path.join(projectRoot, errorEntry.pageFile);\r\n\r\n return {\r\n pattern: ERROR_PATTERN,\r\n regex: new RegExp(`^${ERROR_PATTERN}/?$`),\r\n paramNames: [],\r\n component,\r\n layouts,\r\n pageFile,\r\n layoutFiles: [],\r\n middlewares: [],\r\n loader: null,\r\n dynamic: \"force-static\",\r\n generateStaticParams: null,\r\n };\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { ApiRoute, LoadedRoute, PageComponent, WssRoute } from \"./index.types\";\r\n\r\nimport { loadLayoutsForDir } from \"./layout\";\r\nimport { loadLoaderForDir } from \"./loader\";\r\nimport {\r\n loadRoutesFromManifest,\r\n loadNotFoundFromManifest,\r\n loadErrorFromManifest,\r\n loadChunksFromManifest,\r\n} from \"./loader-routes\";\r\nimport { loadRoutes } from \"./loader-pages\";\r\nimport { loadApiRoutes } from \"./loader-api\";\r\nimport {\r\n NOT_FOUND_PATTERN,\r\n ERROR_PATTERN,\r\n NOT_FOUND_FILE_PREFIX,\r\n ERROR_FILE_PREFIX,\r\n} from \"@constants/globals\";\r\nimport { loadWssRoutes } from \"./loader-wss\";\r\n\r\n/**\r\n * Unified interface for loading routes from different sources.\r\n * Abstracts the difference between filesystem (dev) and manifest (prod) loading.\r\n */\r\nexport interface RouteLoader {\r\n loadRoutes(): LoadedRoute[];\r\n loadApiRoutes(): ApiRoute[];\r\n loadWssRoutes(): WssRoute[];\r\n loadNotFoundRoute(): LoadedRoute | null;\r\n loadErrorRoute(): LoadedRoute | null;\r\n loadRouteChunks(): Record<string, string>;\r\n}\r\n\r\n/**\r\n * Loads routes directly from the filesystem.\r\n * Used in development mode.\r\n */\r\nexport class FilesystemRouteLoader implements RouteLoader {\r\n constructor(private appDir: string) {}\r\n\r\n loadRoutes(): LoadedRoute[] {\r\n return loadRoutes(this.appDir);\r\n }\r\n\r\n loadApiRoutes(): ApiRoute[] {\r\n return loadApiRoutes(this.appDir);\r\n }\r\n\r\n loadWssRoutes(): WssRoute[] {\r\n return loadWssRoutes(this.appDir);\r\n }\r\n\r\n loadNotFoundRoute(): LoadedRoute | null {\r\n return loadNotFoundRouteFromFilesystem(this.appDir);\r\n }\r\n\r\n loadErrorRoute(): LoadedRoute | null {\r\n return loadErrorRouteFromFilesystem(this.appDir);\r\n }\r\n\r\n loadRouteChunks(): Record<string, string> {\r\n // In dev, route chunks are not critical, return empty\r\n return {};\r\n }\r\n}\r\n\r\n/**\r\n * Loads routes from the compiled manifest file.\r\n * Used in production mode.\r\n */\r\nexport class ManifestRouteLoader implements RouteLoader {\r\n constructor(private projectRoot: string) {}\r\n\r\n loadRoutes(): LoadedRoute[] {\r\n const { routes } = loadRoutesFromManifest(this.projectRoot);\r\n return routes;\r\n }\r\n\r\n loadApiRoutes(): ApiRoute[] {\r\n const { apiRoutes } = loadRoutesFromManifest(this.projectRoot);\r\n return apiRoutes;\r\n }\r\n\r\n loadWssRoutes(): WssRoute[] {\r\n const { wssRoutes } = loadRoutesFromManifest(this.projectRoot);\r\n return wssRoutes;\r\n }\r\n\r\n loadNotFoundRoute(): LoadedRoute | null {\r\n return loadNotFoundFromManifest(this.projectRoot);\r\n }\r\n\r\n loadErrorRoute(): LoadedRoute | null {\r\n return loadErrorFromManifest(this.projectRoot);\r\n }\r\n\r\n loadRouteChunks(): Record<string, string> {\r\n return loadChunksFromManifest(this.projectRoot);\r\n }\r\n}\r\n\r\n/**\r\n * Loads the not-found route from the filesystem.\r\n * Looks for `_not-found.tsx` in the app root (Next.js style).\r\n *\r\n * @param appDir - Root directory of the app\r\n * @returns LoadedRoute for the not-found page, or null if not found\r\n */\r\nexport function loadNotFoundRouteFromFilesystem(\r\n appDir: string\r\n): LoadedRoute | null {\r\n const notFoundCandidates = [\r\n path.join(appDir, `${NOT_FOUND_FILE_PREFIX}.tsx`),\r\n path.join(appDir, `${NOT_FOUND_FILE_PREFIX}.ts`),\r\n path.join(appDir, `${NOT_FOUND_FILE_PREFIX}.jsx`),\r\n path.join(appDir, `${NOT_FOUND_FILE_PREFIX}.js`),\r\n // Fallback to old style for backward compatibility\r\n path.join(appDir, \"not-found\", \"page.tsx\"),\r\n path.join(appDir, \"not-found\", \"page.ts\"),\r\n path.join(appDir, \"not-found\", \"page.jsx\"),\r\n path.join(appDir, \"not-found\", \"page.js\"),\r\n ];\r\n\r\n let notFoundFile: string | null = null;\r\n for (const candidate of notFoundCandidates) {\r\n if (fs.existsSync(candidate)) {\r\n notFoundFile = candidate;\r\n break;\r\n }\r\n }\r\n\r\n if (!notFoundFile) {\r\n return null;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n const mod = require(notFoundFile);\r\n const component: PageComponent = mod.default;\r\n\r\n if (!component) {\r\n return null;\r\n }\r\n\r\n // For _not-found.tsx in root, use appDir as the directory\r\n const notFoundDir = notFoundFile.includes(NOT_FOUND_FILE_PREFIX)\r\n ? appDir\r\n : path.dirname(notFoundFile);\r\n\r\n const { components: layouts, files: layoutFiles } = loadLayoutsForDir(\r\n notFoundDir,\r\n appDir\r\n );\r\n\r\n const { middlewares, loader, dynamic, generateStaticParams } =\r\n loadLoaderForDir(notFoundDir);\r\n\r\n return {\r\n pattern: NOT_FOUND_PATTERN,\r\n regex: new RegExp(`^${NOT_FOUND_PATTERN}/?$`),\r\n paramNames: [],\r\n component,\r\n layouts,\r\n pageFile: notFoundFile,\r\n layoutFiles,\r\n middlewares,\r\n loader,\r\n dynamic,\r\n generateStaticParams,\r\n };\r\n}\r\n\r\n/**\r\n * Loads the error route from the filesystem.\r\n * Looks for `_error.tsx` in the app root (Next.js style).\r\n *\r\n * @param appDir - Root directory of the app\r\n * @returns LoadedRoute for the error page, or null if not found\r\n */\r\nexport function loadErrorRouteFromFilesystem(\r\n appDir: string\r\n): LoadedRoute | null {\r\n const errorCandidates = [\r\n path.join(appDir, `${ERROR_FILE_PREFIX}.tsx`),\r\n path.join(appDir, `${ERROR_FILE_PREFIX}.ts`),\r\n path.join(appDir, `${ERROR_FILE_PREFIX}.jsx`),\r\n path.join(appDir, `${ERROR_FILE_PREFIX}.js`),\r\n ];\r\n\r\n let errorFile: string | null = null;\r\n for (const candidate of errorCandidates) {\r\n if (fs.existsSync(candidate)) {\r\n errorFile = candidate;\r\n break;\r\n }\r\n }\r\n\r\n if (!errorFile) {\r\n return null;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n const mod = require(errorFile);\r\n const component: PageComponent = mod.default;\r\n\r\n if (!component) {\r\n return null;\r\n }\r\n\r\n const { components: layouts, files: layoutFiles } = loadLayoutsForDir(\r\n appDir,\r\n appDir\r\n );\r\n\r\n const { middlewares, loader, dynamic, generateStaticParams } =\r\n loadLoaderForDir(appDir);\r\n\r\n return {\r\n pattern: ERROR_PATTERN,\r\n regex: new RegExp(`^${ERROR_PATTERN}/?$`),\r\n paramNames: [],\r\n component,\r\n layouts,\r\n pageFile: errorFile,\r\n layoutFiles,\r\n middlewares,\r\n loader,\r\n dynamic,\r\n generateStaticParams,\r\n };\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { WssRoute } from \"./index.types\";\r\nimport {\r\n extractApiMiddlewares,\r\n extractRouteRegex,\r\n extractWssHandlersFromModule,\r\n loadModuleSafely,\r\n} from \"./helpers/routes\";\r\n\r\nconst ROUTE_FILE_REGEX = /events\\.(ts|tsx|js|jsx)$/;\r\n\r\nexport function loadWssRoutes(appDir: string): WssRoute[] {\r\n const apiRoot = path.join(appDir, \"wss\");\r\n const routes: WssRoute[] = [];\r\n\r\n if (!fs.existsSync(apiRoot)) return routes;\r\n\r\n function walk(currentDir: string) {\r\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(currentDir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n walk(fullPath);\r\n continue;\r\n }\r\n\r\n // Only process route files\r\n if (!ROUTE_FILE_REGEX.test(entry.name)) continue;\r\n\r\n const relToApp = path.relative(appDir, fullPath).replace(/\\\\/g, \"/\");\r\n const withoutRoute = relToApp.replace(/\\/events\\.(ts|tsx|js|jsx)$/, \"\");\r\n const pattern = \"/\" + withoutRoute;\r\n\r\n const { regex, paramNames } = extractRouteRegex(pattern);\r\n\r\n const mod = loadModuleSafely(fullPath);\r\n if (!mod) {\r\n continue;\r\n }\r\n\r\n const handlers = extractWssHandlersFromModule(mod);\r\n const { global: globalMiddlewares, methodSpecific: methodMiddlewares } =\r\n extractApiMiddlewares(mod, []);\r\n\r\n routes.push({\r\n pattern,\r\n regex,\r\n paramNames,\r\n handlers,\r\n middlewares: globalMiddlewares,\r\n methodMiddlewares,\r\n filePath: fullPath,\r\n });\r\n }\r\n }\r\n\r\n walk(apiRoot);\r\n\r\n return routes;\r\n}\r\n\r\n","import { rspack, type Compiler } from \"@rspack/core\";\r\nimport { createClientConfig } from \"../config/client\";\r\nimport { copyStaticAssets, generateAssetManifest } from \"../utils\";\r\nimport path from \"path\";\r\nimport fs from \"fs\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\nexport interface ClientBundlerResult {\r\n outDir: string;\r\n waitForBuild?: () => Promise<void>;\r\n}\r\n\r\n/**\r\n * Starts the client bundler in watch mode for development.\r\n * \r\n * Automatically rebuilds when files change and copies static assets.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param mode - Build mode ('development' or 'production'), defaults to 'development'\r\n * @returns Output directory path\r\n * \r\n * @example\r\n * const { outDir } = startClientBundler('/path/to/project', 'development');\r\n * // Bundler is now watching for changes\r\n */\r\nexport function startClientBundler(\r\n projectRoot: string,\r\n mode: \"development\" | \"production\" = \"development\"\r\n): ClientBundlerResult {\r\n const { config, outDir } = createClientConfig(projectRoot, mode);\r\n\r\n copyStaticAssets(projectRoot, outDir);\r\n\r\n const compiler = rspack(config);\r\n \r\n // Track build state\r\n let isBuilding = false;\r\n let buildResolve: (() => void) | null = null;\r\n let buildPromise: Promise<void> | null = null;\r\n let lastBuildTime = Date.now();\r\n\r\n // Mark as building when compilation starts\r\n compiler.hooks.compile.tap(\"HotReload\", () => {\r\n isBuilding = true;\r\n // Create new promise for this build\r\n buildPromise = new Promise<void>((resolve) => {\r\n buildResolve = resolve;\r\n });\r\n });\r\n\r\n compiler.watch({}, (err, stats) => {\r\n if (err) {\r\n console.error(\"[framework][client] Rspack error:\", err);\r\n isBuilding = false;\r\n lastBuildTime = Date.now();\r\n // Resolve any waiting promises even on error\r\n if (buildResolve) {\r\n buildResolve();\r\n buildResolve = null;\r\n buildPromise = null;\r\n }\r\n return;\r\n }\r\n if (!stats) {\r\n isBuilding = false;\r\n lastBuildTime = Date.now();\r\n return;\r\n }\r\n\r\n if (stats.hasErrors()) {\r\n console.error(\r\n \"[framework][client] Build with errors:\\n\",\r\n stats.toString(\"errors-only\")\r\n );\r\n } else {\r\n console.log(\"[framework][client] ✓ Client bundle rebuilt successfully\");\r\n }\r\n \r\n isBuilding = false;\r\n lastBuildTime = Date.now();\r\n \r\n // Resolve waiting promise\r\n if (buildResolve) {\r\n buildResolve();\r\n buildResolve = null;\r\n buildPromise = null;\r\n }\r\n });\r\n\r\n return {\r\n outDir,\r\n waitForBuild: async () => {\r\n // If currently building, wait for it to finish\r\n if (isBuilding && buildPromise) {\r\n await buildPromise;\r\n // Give it a small delay to ensure files are written to disk\r\n await new Promise(resolve => setTimeout(resolve, 100));\r\n return;\r\n }\r\n \r\n // If not building, check if a build just finished recently\r\n // (within last 500ms) - this handles the case where the build\r\n // finished just before we checked\r\n const timeSinceLastBuild = Date.now() - lastBuildTime;\r\n if (timeSinceLastBuild < 500) {\r\n // Build just finished, wait a bit for files to be written\r\n await new Promise(resolve => setTimeout(resolve, 200));\r\n return;\r\n }\r\n \r\n // No build in progress and none recently finished, return immediately\r\n return Promise.resolve();\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Builds the client bundle for production.\r\n * \r\n * Creates an optimized production bundle and copies static assets.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Promise that resolves with output directory path\r\n * \r\n * @example\r\n * const { outDir } = await buildClientBundle('/path/to/project');\r\n * // Production bundle created at {BUILD_FOLDER_NAME}/client\r\n */\r\nexport function buildClientBundle(\r\n projectRoot: string\r\n): Promise<ClientBundlerResult> {\r\n const { config, outDir } = createClientConfig(projectRoot, \"production\");\r\n const compiler = rspack(config);\r\n\r\n return new Promise<ClientBundlerResult>((resolve, reject) => {\r\n compiler.run((err, stats) => {\r\n compiler.close(() => {});\r\n\r\n if (err) {\r\n console.error(\"[framework][client] Build error:\", err);\r\n return reject(err);\r\n }\r\n if (!stats) {\r\n const error = new Error(\"No stats from Rspack\");\r\n console.error(\"[framework][client] Build error:\", error);\r\n return reject(error);\r\n }\r\n if (stats.hasErrors()) {\r\n console.error(\r\n \"[framework][client] Build with errors:\\n\",\r\n stats.toString(\"errors-only\")\r\n );\r\n return reject(new Error(\"Client build failed\"));\r\n }\r\n\r\n copyStaticAssets(projectRoot, outDir);\r\n\r\n // Generate asset manifest with hashed filenames\r\n const assetManifest = generateAssetManifest(outDir);\r\n \r\n // Save asset manifest\r\n const manifestPath = path.join(projectRoot, BUILD_FOLDER_NAME, \"asset-manifest.json\");\r\n fs.writeFileSync(manifestPath, JSON.stringify(assetManifest, null, 2), \"utf-8\");\r\n\r\n resolve({ outDir });\r\n });\r\n });\r\n}\r\n\r\n","import path from \"path\";\r\nimport fs from \"fs\";\r\nimport { rspack, type Configuration } from \"@rspack/core\";\r\nimport { loadAliasesFromTsconfig } from \"../utils\";\r\nimport dotenv from 'dotenv';\r\nimport { BUILD_FOLDER_NAME, STATIC_PATH } from \"@constants/globals\";\r\n\r\n/**\r\n * Creates Rspack configuration for client bundle.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @param mode - Build mode ('development' or 'production')\r\n * @returns Rspack configuration and output directory\r\n *\r\n * @example\r\n * const { config, outDir } = createClientConfig('/path/to/project', 'production');\r\n */\r\nexport function createClientConfig(\r\n projectRoot: string,\r\n mode: \"development\" | \"production\"\r\n): { config: Configuration; outDir: string } {\r\n const buildDir = path.join(projectRoot, BUILD_FOLDER_NAME);\r\n const clientEntry = path.join(buildDir, \"boostrap.ts\");\r\n const outDir = path.join(buildDir, \"client\");\r\n\r\n dotenv.config({\r\n path: projectRoot,\r\n });\r\n\r\n const publicEnv: Record<string, string> = {};\r\n\r\n for (const [key, value] of Object.entries(process.env)) {\r\n if (key.startsWith(\"PUBLIC_\")) {\r\n publicEnv[`process.env.${key}`] = JSON.stringify(value ?? \"\");\r\n }\r\n }\r\n\r\n const config: Configuration = {\r\n mode,\r\n entry: {\r\n client: clientEntry,\r\n },\r\n output: {\r\n path: outDir,\r\n filename: mode === \"production\" ? \"client.[contenthash].js\" : \"client.js\", // Main entry\r\n chunkFilename: mode === \"production\" ? \"[name].[contenthash].js\" : \"[name].js\", // Code-split chunks (route-..., 0.js, etc.)\r\n publicPath: `${STATIC_PATH}/`,\r\n },\r\n context: projectRoot,\r\n resolve: {\r\n extensions: [\".tsx\", \".ts\", \".jsx\", \".js\"],\r\n alias: loadAliasesFromTsconfig(projectRoot),\r\n },\r\n module: {\r\n rules: [\r\n {\r\n test: /\\.[jt]sx?$/,\r\n loader: \"builtin:swc-loader\",\r\n options: {\r\n jsc: {\r\n parser: { syntax: \"typescript\", tsx: true },\r\n transform: {\r\n react: {\r\n runtime: \"automatic\",\r\n development: mode === \"development\",\r\n refresh: false,\r\n },\r\n },\r\n },\r\n },\r\n },\r\n {\r\n test: /\\.css$/,\r\n use: [\r\n rspack.CssExtractRspackPlugin.loader,\r\n \"css-loader\",\r\n \"postcss-loader\",\r\n ],\r\n },\r\n ],\r\n },\r\n plugins: [\r\n new rspack.DefinePlugin({\r\n \"process.env.NODE_ENV\": JSON.stringify(process.env.NODE_ENV),\r\n ...publicEnv,\r\n }),\r\n new rspack.CssExtractRspackPlugin({\r\n filename: mode === \"production\" ? \"client.[contenthash].css\" : \"client.css\",\r\n }),\r\n ],\r\n infrastructureLogging: {\r\n level: \"error\",\r\n },\r\n stats: \"minimal\",\r\n };\r\n\r\n return { config, outDir };\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\n\r\n/**\r\n * Ensures a directory exists, creating it recursively if needed.\r\n * \r\n * This is a convenience wrapper around `fs.mkdirSync` with `recursive: true`.\r\n * \r\n * @param dir - Directory path to ensure exists\r\n * \r\n * @example\r\n * ensureDir('/path/to/directory');\r\n * // Directory is created if it doesn't exist\r\n */\r\nexport function ensureDir(dir: string): void {\r\n fs.mkdirSync(dir, { recursive: true });\r\n}\r\n\r\n/**\r\n * Loads path aliases from tsconfig.json.\r\n * \r\n * Reads the tsconfig.json file and extracts path mappings from the `paths` option.\r\n * Falls back to a default `@app` alias if tsconfig.json is not found or invalid.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Record of alias keys to resolved paths\r\n * \r\n * @example\r\n * // tsconfig.json\r\n * // {\r\n * // \"compilerOptions\": {\r\n * // \"paths\": {\r\n * // \"@components/*\": [\"components/*\"]\r\n * // }\r\n * // }\r\n * // }\r\n * \r\n * loadAliasesFromTsconfig('/project')\r\n * // { '@components': '/project/components', '@app': '/project/app' }\r\n */\r\nexport function loadAliasesFromTsconfig(\r\n projectRoot: string\r\n): Record<string, string> {\r\n const tsconfigPath = path.join(projectRoot, \"tsconfig.json\");\r\n const aliases: Record<string, string> = {};\r\n\r\n if (!fs.existsSync(tsconfigPath)) {\r\n // Fallback: default @app alias\r\n aliases[\"@app\"] = path.resolve(projectRoot, \"app\");\r\n return aliases;\r\n }\r\n\r\n let tsconfig: any;\r\n try {\r\n tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, \"utf-8\"));\r\n } catch (err) {\r\n console.warn(\"[framework] Could not read tsconfig.json:\", err);\r\n aliases[\"@app\"] = path.resolve(projectRoot, \"app\");\r\n return aliases;\r\n }\r\n\r\n const compilerOptions = tsconfig.compilerOptions ?? {};\r\n const paths = compilerOptions.paths ?? {};\r\n const baseUrl = compilerOptions.baseUrl ?? \".\";\r\n\r\n for (const [aliasPattern, targets] of Object.entries(paths) as [\r\n string,\r\n string[]\r\n ][]) {\r\n if (!Array.isArray(targets) || targets.length === 0) continue;\r\n\r\n // aliasPattern like \"@components/*\" -> \"@components\"\r\n const aliasKey = aliasPattern.replace(/\\/\\*$/, \"\");\r\n const firstTarget = targets[0]; // \"components/*\"\r\n const targetPath = firstTarget.replace(/\\/\\*$/, \"\");\r\n\r\n const resolved = path.resolve(projectRoot, baseUrl, targetPath);\r\n aliases[aliasKey] = resolved;\r\n }\r\n\r\n // Fallback: ensure @app alias exists\r\n if (!aliases[\"@app\"]) {\r\n aliases[\"@app\"] = path.resolve(projectRoot, \"app\");\r\n }\r\n\r\n return aliases;\r\n}\r\n\r\n/**\r\n * Recursively copies a directory and all its contents.\r\n * \r\n * @param srcDir - Source directory to copy from\r\n * @param destDir - Destination directory to copy to\r\n */\r\nexport function copyDirRecursive(srcDir: string, destDir: string): void {\r\n if (!fs.existsSync(srcDir)) return;\r\n ensureDir(destDir);\r\n\r\n const entries = fs.readdirSync(srcDir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n const srcPath = path.join(srcDir, entry.name);\r\n const destPath = path.join(destDir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n copyDirRecursive(srcPath, destPath);\r\n } else if (entry.isFile()) {\r\n fs.copyFileSync(srcPath, destPath);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Copies static assets to the output directory.\r\n * \r\n * Copies:\r\n * 1. `assets/` directory (if exists) → `outDir/assets/`\r\n * 2. Favicon files (`favicon.ico` or `favicon.png`) from `app/` or project root\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param outDir - Output directory to copy assets to\r\n * \r\n * @example\r\n * copyStaticAssets('/project', '/project/{BUILD_FOLDER_NAME}/client');\r\n * // Copies assets/ and favicon.* to {BUILD_FOLDER_NAME}/client/\r\n */\r\nexport function copyStaticAssets(projectRoot: string, outDir: string): void {\r\n // 1) Copy assets/ directory (if exists) → {BUILD_FOLDER_NAME}/client/assets/\r\n const assetsSrc = path.join(projectRoot, \"assets\");\r\n const assetsDest = path.join(outDir, \"assets\");\r\n copyDirRecursive(assetsSrc, assetsDest);\r\n\r\n // 2) Find and copy favicon from app/ or project root\r\n const appDir = path.join(projectRoot, \"app\");\r\n const candidates = [\"favicon.ico\", \"favicon.png\"];\r\n\r\n for (const name of candidates) {\r\n const fromApp = path.join(appDir, name);\r\n const fromRoot = path.join(projectRoot, name);\r\n\r\n let src: string | null = null;\r\n if (fs.existsSync(fromApp)) src = fromApp;\r\n else if (fs.existsSync(fromRoot)) src = fromRoot;\r\n\r\n if (src) {\r\n const dest = path.join(outDir, name); // Will be served as ${STATIC_PATH}/favicon.*\r\n ensureDir(path.dirname(dest));\r\n fs.copyFileSync(src, dest);\r\n break; // Use the first one found\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Asset manifest interface for tracking hashed filenames.\r\n */\r\nexport interface AssetManifest {\r\n client: {\r\n js: string; // e.g., \"client.abc123.js\"\r\n css: string; // e.g., \"client.def456.css\"\r\n };\r\n chunks: Record<string, string>; // chunk name -> hashed filename, e.g., \"route-root\" -> \"route-root.xyz789.js\"\r\n}\r\n\r\n/**\r\n * Generates an asset manifest by scanning the build output directory.\r\n * \r\n * Finds files with content hashes and maps them to their logical names.\r\n * \r\n * @param outDir - Output directory to scan\r\n * @returns Asset manifest with hashed filenames\r\n * \r\n * @example\r\n * const manifest = generateAssetManifest('/project/.loly/client');\r\n * // { client: { js: 'client.abc123.js', css: 'client.def456.css' }, chunks: {...} }\r\n */\r\nexport function generateAssetManifest(outDir: string): AssetManifest {\r\n const manifest: AssetManifest = {\r\n client: {\r\n js: \"client.js\",\r\n css: \"client.css\",\r\n },\r\n chunks: {},\r\n };\r\n\r\n if (!fs.existsSync(outDir)) {\r\n return manifest;\r\n }\r\n\r\n const files = fs.readdirSync(outDir);\r\n \r\n // Find client.js (with or without hash)\r\n const clientJsMatch = files.find((f) => /^client\\.[\\w-]+\\.js$/.test(f) || f === \"client.js\");\r\n if (clientJsMatch) {\r\n manifest.client.js = clientJsMatch;\r\n }\r\n\r\n // Find client.css (with or without hash)\r\n const clientCssMatch = files.find((f) => /^client\\.[\\w-]+\\.css$/.test(f) || f === \"client.css\");\r\n if (clientCssMatch) {\r\n manifest.client.css = clientCssMatch;\r\n }\r\n\r\n // Find all chunk files (route-*.js, 0.js, 1.js, etc. with or without hash)\r\n // Pattern: route-*.js or numeric chunks like 0.js, 1.js, etc.\r\n for (const file of files) {\r\n if (!file.endsWith(\".js\")) continue;\r\n \r\n // Skip the main client.js file\r\n if (file === manifest.client.js) continue;\r\n \r\n // Match route chunks: route-*.js or route-*.[hash].js\r\n const routeMatch = file.match(/^(route-[^.]+)(\\.[\\w-]+)?\\.js$/);\r\n if (routeMatch) {\r\n const chunkName = routeMatch[1]; // e.g., \"route-root\"\r\n manifest.chunks[chunkName] = file;\r\n continue;\r\n }\r\n \r\n // Match numeric chunks: 0.js, 1.js, etc. or 0.[hash].js\r\n const numericMatch = file.match(/^(\\d+)(\\.[\\w-]+)?\\.js$/);\r\n if (numericMatch) {\r\n const chunkName = numericMatch[1]; // e.g., \"0\"\r\n manifest.chunks[chunkName] = file;\r\n }\r\n }\r\n\r\n return manifest;\r\n}\r\n\r\n/**\r\n * Loads the asset manifest from the build directory.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Asset manifest or null if not found\r\n */\r\nexport function loadAssetManifest(projectRoot: string): AssetManifest | null {\r\n const { BUILD_FOLDER_NAME } = require(\"@constants/globals\");\r\n const manifestPath = path.join(projectRoot, BUILD_FOLDER_NAME, \"asset-manifest.json\");\r\n \r\n if (!fs.existsSync(manifestPath)) {\r\n return null;\r\n }\r\n\r\n try {\r\n const manifest: AssetManifest = JSON.parse(fs.readFileSync(manifestPath, \"utf-8\"));\r\n return manifest;\r\n } catch (err) {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Gets the client JS path with hash from the asset manifest.\r\n * Falls back to default path if manifest is not available.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Path to client JS file (e.g., \"/static/client.abc123.js\")\r\n */\r\nexport function getClientJsPath(projectRoot: string): string {\r\n const { STATIC_PATH } = require(\"@constants/globals\");\r\n const manifest = loadAssetManifest(projectRoot);\r\n const filename = manifest?.client.js || \"client.js\";\r\n return `${STATIC_PATH}/${filename}`;\r\n}\r\n\r\n/**\r\n * Gets the client CSS path with hash from the asset manifest.\r\n * Falls back to default path if manifest is not available.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Path to client CSS file (e.g., \"/static/client.def456.css\")\r\n */\r\nexport function getClientCssPath(projectRoot: string): string {\r\n const { STATIC_PATH } = require(\"@constants/globals\");\r\n const manifest = loadAssetManifest(projectRoot);\r\n const filename = manifest?.client.css || \"client.css\";\r\n return `${STATIC_PATH}/${filename}`;\r\n}","import path from \"path\";\r\nimport type { LoadedRoute } from \"@router/index\";\r\nimport { buildPathFromPattern } from \"./path\";\r\nimport { renderStaticRoute } from \"./renderer\";\r\nimport { ensureDir } from \"../utils\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\n/**\r\n * Builds static pages for routes marked with `dynamic: \"force-static\"`.\r\n * \r\n * For each static route:\r\n * 1. Calls `generateStaticParams()` to get all parameter combinations\r\n * 2. Renders each combination to HTML and data.json\r\n * 3. Writes files to `{BUILD_FOLDER_NAME}/ssg/{path}/index.html` and `data.json`\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param routes - Array of loaded routes\r\n * \r\n * @example\r\n * await buildStaticPages('/path/to/project', routes);\r\n *\r\n */\r\nexport async function buildStaticPages(\r\n projectRoot: string,\r\n routes: LoadedRoute[]\r\n): Promise<void> {\r\n const ssgOutDir = path.join(projectRoot, BUILD_FOLDER_NAME, \"ssg\");\r\n ensureDir(ssgOutDir);\r\n\r\n for (const route of routes) {\r\n // Only process routes marked as static\r\n if (route.dynamic !== \"force-static\") continue;\r\n\r\n let allParams: Array<Record<string, string>> = [];\r\n\r\n if (route.paramNames.length === 0) {\r\n allParams = [{}];\r\n } else {\r\n if (!route.generateStaticParams) {\r\n console.warn(\r\n `[framework][ssg] Route ${route.pattern} is marked as force-static but has no generateStaticParams function. Skipping.`\r\n );\r\n continue;\r\n }\r\n \r\n try {\r\n console.log(`[framework][ssg] Generating static params for route: ${route.pattern}`);\r\n \r\n // Add timeout to detect hanging\r\n let timeoutId: NodeJS.Timeout | null = null;\r\n const timeoutPromise = new Promise((_, reject) => {\r\n timeoutId = setTimeout(() => {\r\n reject(new Error(`generateStaticParams for route ${route.pattern} timed out after 30 seconds`));\r\n }, 30000);\r\n });\r\n \r\n const sp = await Promise.race([\r\n route.generateStaticParams(),\r\n timeoutPromise\r\n ]) as Array<Record<string, string>>;\r\n \r\n // Clear timeout if it's still pending\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n }\r\n \r\n allParams = sp;\r\n console.log(`[framework][ssg] Generated ${sp.length} static params for route: ${route.pattern}`);\r\n } catch (error) {\r\n console.error(\r\n `[framework][ssg] Error generating static params for route ${route.pattern}:`,\r\n error\r\n );\r\n throw error;\r\n }\r\n }\r\n for (const params of allParams) {\r\n const urlPath = buildPathFromPattern(route.pattern, params);\r\n await renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params);\r\n }\r\n }\r\n \r\n console.log(`[framework][ssg] Finished building all static pages`);\r\n}\r\n\r\n","import path from \"path\";\r\n\r\n/**\r\n * Builds a URL path from a route pattern and parameters.\r\n * \r\n * Replaces dynamic segments ([slug], [...path]) with actual parameter values.\r\n * \r\n * @param pattern - Route pattern (e.g., '/blog/[slug]', '/post/[...path]')\r\n * @param params - Parameter values to substitute\r\n * @returns Actual URL path\r\n * \r\n * @example\r\n * buildPathFromPattern('/blog/[slug]', { slug: 'my-post' })\r\n * // '/blog/my-post'\r\n * \r\n * buildPathFromPattern('/post/[...path]', { path: 'a/b/c' })\r\n * // '/post/a/b/c'\r\n * \r\n * @throws Error if required parameters are missing\r\n */\r\nexport function buildPathFromPattern(\r\n pattern: string,\r\n params: Record<string, string>\r\n): string {\r\n const segments = pattern.split(\"/\").filter(Boolean);\r\n const parts: string[] = [];\r\n\r\n for (const seg of segments) {\r\n // Catch-all parameter: [...path]\r\n if (seg.startsWith(\"[...\") && seg.endsWith(\"]\")) {\r\n const name = seg.slice(4, -1);\r\n const value = params[name];\r\n if (!value) {\r\n throw new Error(\r\n `Missing parameter \"${name}\" for catch-all pattern \"${pattern}\"`\r\n );\r\n }\r\n parts.push(value);\r\n }\r\n // Normal parameter: [slug]\r\n else if (seg.startsWith(\"[\") && seg.endsWith(\"]\")) {\r\n const name = seg.slice(1, -1);\r\n const value = params[name];\r\n if (!value) {\r\n throw new Error(`Missing parameter \"${name}\" for pattern \"${pattern}\"`);\r\n }\r\n parts.push(encodeURIComponent(value));\r\n }\r\n // Static segment\r\n else {\r\n parts.push(seg);\r\n }\r\n }\r\n\r\n return \"/\" + parts.join(\"/\");\r\n}\r\n\r\n/**\r\n * Converts a URL path to an output directory path.\r\n * \r\n * @param baseDir - Base output directory\r\n * @param urlPath - URL path (e.g., '/blog/my-post' or '/')\r\n * @returns Directory path relative to baseDir\r\n * \r\n * @example\r\n * pathToOutDir('/output/ssg', '/blog/my-post')\r\n * // '/output/ssg/blog/my-post'\r\n * \r\n * pathToOutDir('/output/ssg', '/')\r\n * // '/output/ssg'\r\n */\r\nexport function pathToOutDir(baseDir: string, urlPath: string): string {\r\n const clean = urlPath === \"/\" ? \"\" : urlPath.replace(/^\\/+/, \"\");\r\n return path.join(baseDir, clean);\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { renderToString } from \"react-dom/server\";\r\nimport { loadChunksFromManifest, type LoadedRoute, type LoaderResult, type ServerContext } from \"@router/index\";\r\nimport {\r\n buildAppTree,\r\n buildInitialData,\r\n buildRouterData,\r\n createDocumentTree,\r\n} from \"@rendering/index\";\r\nimport { pathToOutDir } from \"./path\";\r\nimport { ensureDir, getClientJsPath, getClientCssPath, loadAssetManifest } from \"../utils\";\r\nimport { STATIC_PATH } from \"@constants/globals\";\r\n\r\n/**\r\n * Renders a static page for SSG.\r\n * \r\n * Executes middlewares and loader, then renders the React component tree\r\n * to HTML. Writes both the HTML file and the data JSON file.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param ssgOutDir - SSG output directory\r\n * @param route - Route definition\r\n * @param urlPath - URL path for this page\r\n * @param params - Route parameters\r\n * \r\n * @example\r\n * await renderStaticRoute(\r\n * '/project',\r\n * '/project/{BUILD_FOLDER_NAME}/ssg',\r\n * route,\r\n * '/blog/my-post',\r\n * { slug: 'my-post' }\r\n * );\r\n */\r\nexport async function renderStaticRoute(\r\n projectRoot: string,\r\n ssgOutDir: string,\r\n route: LoadedRoute,\r\n urlPath: string,\r\n params: Record<string, string>\r\n): Promise<void> {\r\n const routeChunks = loadChunksFromManifest(projectRoot);\r\n const assetManifest = loadAssetManifest(projectRoot);\r\n const clientJsPath = getClientJsPath(projectRoot);\r\n const clientCssPath = getClientCssPath(projectRoot);\r\n \r\n // Get chunk href with hash if available\r\n const chunkName = routeChunks[route.pattern];\r\n let chunkHref: string | null = null;\r\n if (chunkName != null) {\r\n if (assetManifest && assetManifest.chunks[chunkName]) {\r\n chunkHref = `${STATIC_PATH}/${assetManifest.chunks[chunkName]}`;\r\n } else {\r\n chunkHref = `${STATIC_PATH}/${chunkName}.js`;\r\n }\r\n }\r\n\r\n // Mock request/response objects for SSG\r\n const req: any = {\r\n method: \"GET\",\r\n headers: {},\r\n query: {},\r\n path: urlPath,\r\n };\r\n\r\n const res: any = {\r\n statusCode: 200,\r\n headers: {} as Record<string, string>,\r\n setHeader(name: string, value: string) {\r\n this.headers[name.toLowerCase()] = value;\r\n },\r\n get headersSent() {\r\n return false;\r\n },\r\n };\r\n\r\n const ctx: ServerContext = {\r\n req,\r\n res,\r\n params,\r\n pathname: urlPath,\r\n locals: {},\r\n };\r\n\r\n // Execute middlewares\r\n for (const mw of route.middlewares) {\r\n await Promise.resolve(\r\n mw(ctx, async () => {\r\n /* no-op */\r\n })\r\n );\r\n }\r\n\r\n // Execute loader\r\n let loaderResult: LoaderResult = { props: {} };\r\n\r\n if (route.loader) {\r\n loaderResult = await route.loader(ctx);\r\n }\r\n\r\n if (loaderResult.redirect || loaderResult.notFound) {\r\n return;\r\n }\r\n\r\n // Build React component tree\r\n const initialData = buildInitialData(urlPath, params, loaderResult);\r\n const routerData = buildRouterData(req);\r\n const appTree = buildAppTree(route, params, initialData.props);\r\n const documentTree = createDocumentTree({\r\n appTree,\r\n initialData,\r\n routerData,\r\n meta: loaderResult.metadata,\r\n titleFallback: \"My Framework Dev\",\r\n descriptionFallback: \"Static page generated by @lolyjs/core.\",\r\n chunkHref,\r\n clientJsPath,\r\n clientCssPath,\r\n });\r\n\r\n // Render to HTML (hydratable, same as SSR)\r\n const html = \"<!DOCTYPE html>\" + renderToString(documentTree);\r\n\r\n // Write files\r\n const dir = pathToOutDir(ssgOutDir, urlPath);\r\n ensureDir(dir);\r\n\r\n const htmlFile = path.join(dir, \"index.html\");\r\n const dataFile = path.join(dir, \"data.json\");\r\n\r\n fs.writeFileSync(htmlFile, html, \"utf-8\");\r\n fs.writeFileSync(dataFile, JSON.stringify(initialData, null, 2), \"utf-8\");\r\n}\r\n\r\n","import React, { ReactElement } from \"react\";\r\nimport type { LoaderResult, PageComponent, LoadedRoute } from \"@router/index\";\r\nimport { InitialData, RouterData } from \"../index.types\";\r\nimport {\r\n WINDOW_DATA_KEY,\r\n APP_CONTAINER_ID,\r\n FAVICON_PATH,\r\n ROUTER_DATA_KEY,\r\n} from \"@constants/globals\";\r\n\r\n/**\r\n * Builds the app tree (Page + layouts) in the same way for SSR and SSG.\r\n *\r\n * @param route - Route definition\r\n * @param params - Route parameters\r\n * @param props - Props from loader\r\n * @returns React element tree\r\n */\r\nexport function buildAppTree(\r\n route: LoadedRoute,\r\n params: Record<string, string>,\r\n props: any\r\n): ReactElement {\r\n const Page = route.component as PageComponent;\r\n\r\n let appTree: ReactElement = React.createElement(Page, {\r\n params,\r\n ...props,\r\n });\r\n\r\n const layoutChain = route.layouts.slice().reverse();\r\n\r\n for (const Layout of layoutChain) {\r\n appTree = React.createElement(Layout as PageComponent, {\r\n params,\r\n ...props,\r\n children: appTree,\r\n });\r\n }\r\n\r\n return appTree;\r\n}\r\n\r\n/**\r\n * Builds the complete HTML document tree. Used by both SSR and SSG.\r\n *\r\n * @param options - Document tree options\r\n * @returns React element representing the HTML document\r\n */\r\nexport function createDocumentTree(options: {\r\n appTree: ReactElement;\r\n initialData: InitialData;\r\n routerData: RouterData;\r\n meta: LoaderResult[\"metadata\"];\r\n titleFallback?: string;\r\n descriptionFallback?: string;\r\n chunkHref?: string | null;\r\n theme?: string;\r\n clientJsPath?: string;\r\n clientCssPath?: string;\r\n nonce?: string;\r\n}): ReactElement {\r\n const {\r\n appTree,\r\n initialData,\r\n routerData,\r\n meta,\r\n titleFallback,\r\n descriptionFallback,\r\n chunkHref,\r\n theme,\r\n clientJsPath = \"/static/client.js\",\r\n clientCssPath = \"/static/client.css\",\r\n nonce,\r\n } = options;\r\n\r\n const metaObj = meta ?? {};\r\n const title = (metaObj as any).title ?? titleFallback ?? \"My Framework Dev\";\r\n const lang = (metaObj as any).lang ?? \"en\";\r\n const description =\r\n (metaObj as any).description ??\r\n descriptionFallback ??\r\n \"Demo Loly framework\";\r\n\r\n const extraMetaTags: ReactElement[] = [];\r\n\r\n if (description) {\r\n extraMetaTags.push(\r\n React.createElement(\"meta\", {\r\n name: \"description\",\r\n content: description,\r\n })\r\n );\r\n }\r\n\r\n if (Array.isArray((metaObj as any).metaTags)) {\r\n for (const tag of (metaObj as any).metaTags) {\r\n extraMetaTags.push(\r\n React.createElement(\"meta\", {\r\n name: tag.name,\r\n property: tag.property,\r\n content: tag.content,\r\n })\r\n );\r\n }\r\n }\r\n\r\n const serialized = JSON.stringify({\r\n ...initialData,\r\n theme,\r\n });\r\n\r\n const routerSerialized = JSON.stringify({\r\n ...routerData,\r\n });\r\n\r\n const documentTree = React.createElement(\r\n \"html\",\r\n { lang },\r\n React.createElement(\r\n \"head\",\r\n null,\r\n React.createElement(\"meta\", { charSet: \"utf-8\" }),\r\n React.createElement(\"title\", null, title),\r\n React.createElement(\"meta\", {\r\n name: \"viewport\",\r\n content: \"width=device-width, initial-scale=1\",\r\n }),\r\n ...extraMetaTags,\r\n chunkHref &&\r\n React.createElement(\"link\", {\r\n rel: \"modulepreload\",\r\n href: chunkHref,\r\n as: \"script\",\r\n }),\r\n React.createElement(\"link\", {\r\n rel: \"icon\",\r\n href: FAVICON_PATH,\r\n type: \"image/png\",\r\n }),\r\n React.createElement(\"link\", {\r\n rel: \"stylesheet\",\r\n href: clientCssPath,\r\n }),\r\n React.createElement(\"script\", {\r\n src: clientJsPath,\r\n defer: true,\r\n })\r\n ),\r\n React.createElement(\r\n \"body\",\r\n { \r\n style: { margin: 0 }, \r\n className: [initialData.className, theme].filter(Boolean).join(\" \"),\r\n suppressHydrationWarning: true // Allow theme class to differ between server and client initially\r\n },\r\n React.createElement(\"div\", { id: APP_CONTAINER_ID }, appTree)\r\n ),\r\n React.createElement(\"script\", {\r\n nonce: nonce,\r\n dangerouslySetInnerHTML: {\r\n __html: `window.${WINDOW_DATA_KEY} = ${serialized};`,\r\n },\r\n }),\r\n React.createElement(\"script\", {\r\n nonce: nonce,\r\n dangerouslySetInnerHTML: {\r\n __html: `window.${ROUTER_DATA_KEY} = ${routerSerialized};`,\r\n },\r\n })\r\n );\r\n\r\n return documentTree;\r\n}\r\n","import { InitialData } from \"../index.types\";\nimport type { LoaderResult } from \"@router/index\";\n\n/**\n * Builds InitialData in a consistent way.\n *\n * @param urlPath - URL path\n * @param params - Route parameters\n * @param loaderResult - Loader result\n * @returns Initial data object\n */\nexport function buildInitialData(\n urlPath: string,\n params: Record<string, string>,\n loaderResult: LoaderResult,\n): InitialData {\n // Include theme in props so it's available to layouts and pages\n const props = {\n ...(loaderResult.props ?? {}),\n ...(loaderResult.theme ? { theme: loaderResult.theme } : {}),\n };\n \n return {\n pathname: urlPath,\n params,\n props,\n metadata: loaderResult.metadata ?? null,\n className: loaderResult.className ?? \"\",\n error: false,\n notFound: false,\n };\n}\n","import { RouterData } from \"@rendering/index.types\";\r\nimport { Request } from \"express\";\r\n\r\nexport const buildRouterData = (req: Request): RouterData => {\r\n return {\r\n pathname: req.path,\r\n params: req.params,\r\n searchParams: req.query,\r\n };\r\n};\r\n","import path from \"path\";\r\nimport fs from \"fs\";\r\nimport esbuild from \"esbuild\";\r\nimport { ensureDir } from \"../utils\";\r\nimport { INIT_FILE_NAME } from \"@server/init\";\r\nimport { CONFIG_FILE_NAME } from \"@server/config\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\nconst SERVER_FILES = [INIT_FILE_NAME, CONFIG_FILE_NAME];\r\n\r\nexport interface BuildServerResult {\r\n outDir: string;\r\n}\r\n\r\nfunction collectAppSources(appDir: string): string[] {\r\n const entries: string[] = [];\r\n\r\n function walk(dir: string) {\r\n const items = fs.readdirSync(dir, { withFileTypes: true });\r\n\r\n for (const item of items) {\r\n const full = path.join(dir, item.name);\r\n\r\n if (item.isDirectory()) {\r\n walk(full);\r\n continue;\r\n }\r\n\r\n if (item.isFile()) {\r\n if (full.endsWith(\".d.ts\")) continue;\r\n\r\n if (\r\n full.endsWith(\".ts\") ||\r\n full.endsWith(\".tsx\") ||\r\n full.endsWith(\".js\") ||\r\n full.endsWith(\".jsx\")\r\n ) {\r\n entries.push(full);\r\n }\r\n }\r\n }\r\n }\r\n\r\n walk(appDir);\r\n return entries;\r\n}\r\n\r\n/**\r\n * Builds the server application.\r\n *\r\n * Compiles app directory with bundling enabled, and server files (init/config)\r\n * without bundling for direct require access.\r\n *\r\n * @param projectRoot - Root directory of the project\r\n * @param appDir - App directory to build\r\n * @returns Promise resolving to build result with output directory\r\n */\r\nexport async function buildServerApp(\r\n projectRoot: string,\r\n appDir: string\r\n): Promise<BuildServerResult> {\r\n const outDir = path.join(projectRoot, BUILD_FOLDER_NAME, \"server\");\r\n\r\n const entryPoints = collectAppSources(appDir);\r\n ensureDir(outDir);\r\n\r\n if (entryPoints.length === 0) {\r\n return { outDir };\r\n }\r\n\r\n await esbuild.build({\r\n entryPoints,\r\n outdir: outDir,\r\n outbase: appDir,\r\n platform: \"node\",\r\n format: \"cjs\",\r\n target: \"node18\",\r\n jsx: \"automatic\",\r\n sourcemap: true,\r\n bundle: true,\r\n splitting: false,\r\n logLevel: \"info\",\r\n tsconfig: path.join(projectRoot, \"tsconfig.json\"),\r\n packages: \"external\",\r\n });\r\n\r\n for (const fileName of SERVER_FILES) {\r\n const initTS = path.join(projectRoot, `${fileName}.ts`);\r\n const initJS = path.join(outDir, `${fileName}.js`);\r\n\r\n if (fs.existsSync(initTS)) {\r\n await esbuild.build({\r\n entryPoints: [initTS],\r\n outfile: initJS,\r\n platform: \"node\",\r\n format: \"cjs\",\r\n target: \"node18\",\r\n jsx: \"automatic\",\r\n sourcemap: true,\r\n bundle: false,\r\n logLevel: \"info\",\r\n tsconfig: path.join(projectRoot, \"tsconfig.json\"),\r\n });\r\n }\r\n }\r\n\r\n return { outDir };\r\n}\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\nexport const getServerFile = async (projectRoot: string, fileName: string) => {\r\n const fileTS = path.join(projectRoot, `${fileName}.ts`);\r\n const fileJS = path.join(projectRoot, BUILD_FOLDER_NAME, \"server\", `${fileName}.js`);\r\n\r\n const isDev = process.env.NODE_ENV === \"development\";\r\n let mod: any = null;\r\n\r\n if (isDev) {\r\n if (!fs.existsSync(fileTS)) {\r\n return null;\r\n }\r\n\r\n require(\"tsx/cjs\");\r\n mod = require(fileTS);\r\n } else {\r\n if (!fs.existsSync(fileJS)) {\r\n return null;\r\n }\r\n\r\n mod = require(fileJS);\r\n }\r\n\r\n return mod;\r\n};\r\n","import http from \"http\";\r\nimport { getServerFile } from \"./utils/server-dir\";\r\n\r\nexport const INIT_FILE_NAME = 'init.server';\r\n\r\nexport interface InitServerData {\r\n server: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;\r\n}\r\n\r\nexport async function runInitIfExists(\r\n projectRoot: string,\r\n serverData: InitServerData\r\n): Promise<Record<string, any>> {\r\n let mod: any = await getServerFile(projectRoot, INIT_FILE_NAME);\r\n\r\n if (typeof mod?.init === \"function\") {\r\n const serverContext: any = { ...serverData };\r\n await mod.init({ serverContext });\r\n\r\n return serverContext;\r\n }\r\n\r\n return {};\r\n}\r\n","import { getServerFile } from \"./utils/server-dir\";\r\n\r\nexport const CONFIG_FILE_NAME = \"loly.config\";\r\n\r\nexport interface ServerConfig {\r\n bodyLimit?: string;\r\n corsOrigin?: string | string[] | boolean | ((origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) => void);\r\n rateLimit?: {\r\n windowMs?: number;\r\n max?: number;\r\n apiMax?: number;\r\n strictMax?: number;\r\n // Auto-apply strict rate limiting to routes matching these patterns\r\n strictPatterns?: string[];\r\n };\r\n security?: {\r\n contentSecurityPolicy?: boolean | Record<string, any>;\r\n hsts?: boolean | { maxAge?: number; includeSubDomains?: boolean };\r\n };\r\n}\r\n\r\nconst DEFAULT_CONFIG: ServerConfig = {\r\n bodyLimit: '1mb',\r\n corsOrigin: process.env.CORS_ORIGIN \r\n ? (process.env.CORS_ORIGIN.includes(',') \r\n ? process.env.CORS_ORIGIN.split(',').map(s => s.trim())\r\n : process.env.CORS_ORIGIN)\r\n : (process.env.NODE_ENV === 'production' ? [] : true),\r\n rateLimit: {\r\n windowMs: 15 * 60 * 1000, // 15 minutes\r\n max: 100, // General requests\r\n apiMax: 100, // API requests\r\n strictMax: 5, // Strict endpoints (auth, etc.)\r\n // Auto-apply strict rate limiting to these route patterns\r\n strictPatterns: [\r\n '/api/auth/**',\r\n '/api/login/**',\r\n '/api/register/**',\r\n '/api/password/**',\r\n '/api/reset/**',\r\n '/api/verify/**',\r\n ],\r\n },\r\n security: {\r\n contentSecurityPolicy: {\r\n directives: {\r\n defaultSrc: [\"'self'\"],\r\n styleSrc: [\"'self'\", \"'unsafe-inline'\"],\r\n scriptSrc: [\"'self'\", \"'unsafe-inline'\", \"'unsafe-eval'\"], // Needed for dev\r\n imgSrc: [\"'self'\", \"data:\", \"https:\"],\r\n connectSrc: [\"'self'\"],\r\n fontSrc: [\"'self'\", \"data:\"],\r\n objectSrc: [\"'none'\"],\r\n mediaSrc: [\"'self'\"],\r\n frameSrc: [\"'none'\"],\r\n },\r\n },\r\n hsts: {\r\n maxAge: 31536000, // 1 year\r\n includeSubDomains: true,\r\n },\r\n },\r\n}\r\n\r\nexport async function getServerConfig(\r\n projectRoot: string,\r\n): Promise<ServerConfig> {\r\n let mod: any = await getServerFile(projectRoot, CONFIG_FILE_NAME);\r\n\r\n if (typeof mod?.config === \"function\") {\r\n const options = mod?.config(process.env.NODE_ENV) as ServerConfig;\r\n\r\n // Deep merge for nested objects\r\n const merged: ServerConfig = {\r\n ...DEFAULT_CONFIG,\r\n ...options,\r\n rateLimit: {\r\n ...DEFAULT_CONFIG.rateLimit,\r\n ...options.rateLimit,\r\n },\r\n security: {\r\n ...DEFAULT_CONFIG.security,\r\n ...options.security,\r\n },\r\n };\r\n\r\n return merged;\r\n }\r\n\r\n return DEFAULT_CONFIG;\r\n}\r\n","import path from \"path\";\r\nimport {\r\n loadApiRoutes,\r\n LoadedRoute,\r\n loadRoutes,\r\n writeClientBoostrapManifest,\r\n writeClientRoutesManifest,\r\n writeRoutesManifest,\r\n loadNotFoundRouteFromFilesystem,\r\n loadErrorRouteFromFilesystem,\r\n} from \"@router/index\";\r\nimport { buildClientBundle } from \"./bundler/client\";\r\nimport { buildStaticPages } from \"./ssg\";\r\nimport { buildServerApp } from \"./bundler/server\";\r\nimport { NOT_FOUND_PATTERN } from \"@constants/globals\";\r\nimport { loadConfig, getAppDir, type FrameworkConfig } from \"@src/config\";\r\nimport { loadWssRoutes } from \"@router/loader-wss\";\r\n\r\nexport interface BuildAppOptions {\r\n rootDir?: string;\r\n appDir?: string;\r\n config?: FrameworkConfig;\r\n}\r\n\r\nexport async function buildApp(options: BuildAppOptions = {}): Promise<void> {\r\n const projectRoot = options.rootDir ?? process.cwd();\r\n const config = options.config ?? loadConfig(projectRoot);\r\n const appDir = options.appDir ?? getAppDir(projectRoot, config);\r\n\r\n process.env.LOLY_BUILD = \"1\";\r\n\r\n const routes = loadRoutes(appDir);\r\n const apiRoutes = loadApiRoutes(appDir);\r\n const wssRoutes = loadWssRoutes(appDir);\r\n\r\n const { outDir: serverOutDir } = await buildServerApp(projectRoot, appDir);\r\n\r\n // Load special error pages (_not-found.tsx, _error.tsx)\r\n const notFoundRoute = loadNotFoundRouteFromFilesystem(appDir);\r\n const errorRoute = loadErrorRouteFromFilesystem(appDir);\r\n\r\n if (!notFoundRoute) {\r\n console.warn(\r\n `[framework][build] No not-found route found. Consider creating ${config.directories.app}/${config.conventions.notFound}.tsx`\r\n );\r\n }\r\n\r\n // Create a minimal not-found route if none exists\r\n const fallbackNotFound: LoadedRoute = notFoundRoute || {\r\n pattern: NOT_FOUND_PATTERN,\r\n regex: new RegExp(`^${NOT_FOUND_PATTERN}/?$`),\r\n paramNames: [],\r\n component: () => null,\r\n layouts: [],\r\n pageFile: \"\",\r\n layoutFiles: [],\r\n middlewares: [],\r\n loader: null,\r\n dynamic: \"force-static\",\r\n generateStaticParams: null,\r\n };\r\n\r\n writeRoutesManifest({\r\n routes,\r\n apiRoutes,\r\n wssRoutes,\r\n notFoundRoute: fallbackNotFound,\r\n errorRoute,\r\n projectRoot,\r\n serverOutDir,\r\n appDir,\r\n });\r\n\r\n writeClientBoostrapManifest(projectRoot);\r\n\r\n writeClientRoutesManifest(routes, projectRoot);\r\n\r\n await buildClientBundle(projectRoot);\r\n\r\n await buildStaticPages(projectRoot, routes);\r\n\r\n delete process.env.LOLY_BUILD;\r\n\r\n console.log(`[framework][build] Build completed successfully`);\r\n}\r\n\r\nexport { startClientBundler, buildClientBundle } from \"./bundler/client\";\r\nexport { buildServerApp } from \"./bundler/server\";\r\nexport { buildStaticPages } from \"./ssg\";\r\n","import path from \"path\";\r\nimport fs from \"fs\";\r\nimport { BUILD_FOLDER_NAME } from \"../constants/globals\";\r\n\r\n/**\r\n * Framework configuration interface.\r\n * \r\n * Allows customization of framework behavior without code changes.\r\n */\r\nexport interface FrameworkConfig {\r\n // Directory structure\r\n directories: {\r\n app: string; // Default: 'app'\r\n build: string; // Default: '.loly'\r\n static: string; // Default: 'public'\r\n };\r\n \r\n // File naming conventions\r\n conventions: {\r\n page: string; // Default: 'page'\r\n layout: string; // Default: 'layout'\r\n notFound: string; // Default: '_not-found'\r\n error: string; // Default: '_error'\r\n api: string; // Default: 'route'\r\n };\r\n \r\n // Routing\r\n routing: {\r\n trailingSlash: 'always' | 'never' | 'ignore';\r\n caseSensitive: boolean;\r\n basePath: string; // Default: ''\r\n };\r\n \r\n // Build\r\n build: {\r\n clientBundler: 'rspack' | 'webpack' | 'vite';\r\n serverBundler: 'esbuild' | 'tsup' | 'swc';\r\n outputFormat: 'cjs' | 'esm';\r\n };\r\n \r\n // Server\r\n server: {\r\n adapter: 'express' | 'fastify' | 'koa';\r\n port: number;\r\n host: string;\r\n };\r\n \r\n // Rendering\r\n rendering: {\r\n framework: 'react' | 'preact' | 'vue' | 'svelte';\r\n streaming: boolean;\r\n ssr: boolean;\r\n ssg: boolean;\r\n };\r\n \r\n // Plugins (to be implemented in Phase 2)\r\n plugins?: any[];\r\n}\r\n\r\n/**\r\n * Default framework configuration.\r\n */\r\nexport const DEFAULT_CONFIG: FrameworkConfig = {\r\n directories: {\r\n app: 'app',\r\n build: BUILD_FOLDER_NAME,\r\n static: 'public',\r\n },\r\n conventions: {\r\n page: 'page',\r\n layout: 'layout',\r\n notFound: '_not-found',\r\n error: '_error',\r\n api: 'route',\r\n },\r\n routing: {\r\n trailingSlash: 'ignore',\r\n caseSensitive: false,\r\n basePath: '',\r\n },\r\n build: {\r\n clientBundler: 'rspack',\r\n serverBundler: 'esbuild',\r\n outputFormat: 'cjs',\r\n },\r\n server: {\r\n adapter: 'express',\r\n port: 3000,\r\n host: 'localhost',\r\n },\r\n rendering: {\r\n framework: 'react',\r\n streaming: true,\r\n ssr: true,\r\n ssg: true,\r\n },\r\n plugins: [],\r\n};\r\n\r\n/**\r\n * Deep merge utility for configuration objects.\r\n */\r\nfunction deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {\r\n const result = { ...target };\r\n \r\n for (const key in source) {\r\n const sourceValue = source[key];\r\n if (sourceValue && typeof sourceValue === 'object' && !Array.isArray(sourceValue)) {\r\n const targetValue = result[key];\r\n if (targetValue && typeof targetValue === 'object' && !Array.isArray(targetValue)) {\r\n result[key] = deepMerge(targetValue, sourceValue as any);\r\n } else {\r\n result[key] = sourceValue as T[Extract<keyof T, string>];\r\n }\r\n } else if (sourceValue !== undefined) {\r\n result[key] = sourceValue as T[Extract<keyof T, string>];\r\n }\r\n }\r\n \r\n return result;\r\n}\r\n\r\n/**\r\n * Loads framework configuration from project root.\r\n * \r\n * Looks for configuration in the following order:\r\n * 1. loly.config.ts (TypeScript)\r\n * 2. loly.config.js (JavaScript)\r\n * 3. loly.config.json (JSON)\r\n * \r\n * Merges user config with defaults and validates.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @returns Framework configuration\r\n */\r\nexport function loadConfig(projectRoot: string): FrameworkConfig {\r\n const configFiles = [\r\n path.join(projectRoot, 'loly.config.ts'),\r\n path.join(projectRoot, 'loly.config.js'),\r\n path.join(projectRoot, 'loly.config.json'),\r\n ];\r\n\r\n let userConfig: Partial<FrameworkConfig> = {};\r\n\r\n // Try to load config file\r\n for (const configFile of configFiles) {\r\n if (fs.existsSync(configFile)) {\r\n try {\r\n if (configFile.endsWith('.json')) {\r\n // Load JSON config\r\n const content = fs.readFileSync(configFile, 'utf-8');\r\n userConfig = JSON.parse(content);\r\n } else {\r\n // Load TS/JS config (requires require/import)\r\n // In production, these should be compiled\r\n // For now, we'll use require with tsx in dev\r\n if (process.env.NODE_ENV === 'development') {\r\n require('tsx/cjs');\r\n }\r\n const mod = require(configFile);\r\n userConfig = typeof mod.default === 'function' \r\n ? mod.default(process.env.NODE_ENV)\r\n : (mod.default || mod.config || mod);\r\n }\r\n break;\r\n } catch (error) {\r\n console.warn(`[framework] Failed to load config from ${configFile}:`, error);\r\n }\r\n }\r\n }\r\n\r\n // Merge with defaults\r\n const config = deepMerge(DEFAULT_CONFIG, userConfig);\r\n\r\n // Validate critical paths\r\n const appDir = path.join(projectRoot, config.directories.app);\r\n if (!fs.existsSync(appDir) && process.env.NODE_ENV !== 'test') {\r\n console.warn(`[framework] App directory not found: ${appDir}`);\r\n }\r\n\r\n return config;\r\n}\r\n\r\n/**\r\n * Gets the resolved app directory path.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param config - Framework configuration\r\n * @returns Resolved app directory path\r\n */\r\nexport function getAppDir(projectRoot: string, config: FrameworkConfig): string {\r\n return path.resolve(projectRoot, config.directories.app);\r\n}\r\n\r\n/**\r\n * Gets the resolved build directory path.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param config - Framework configuration\r\n * @returns Resolved build directory path\r\n */\r\nexport function getBuildDir(projectRoot: string, config: FrameworkConfig): string {\r\n return path.join(projectRoot, config.directories.build);\r\n}\r\n\r\n/**\r\n * Gets the resolved static directory path.\r\n * \r\n * @param projectRoot - Root directory of the project\r\n * @param config - Framework configuration\r\n * @returns Resolved static directory path\r\n */\r\nexport function getStaticDir(projectRoot: string, config: FrameworkConfig): string {\r\n return path.resolve(projectRoot, config.directories.static);\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { runInitIfExists } from \"@server/init\";\r\nimport { setupServer, setupRoutes, setupWssEvents } from \"@server/index\";\r\nimport { setupApplication } from \"@server/application\";\r\nimport { FilesystemRouteLoader, ManifestRouteLoader } from \"@router/index\";\r\nimport {\r\n loadConfig,\r\n getAppDir,\r\n getBuildDir,\r\n type FrameworkConfig,\r\n} from \"./config\";\r\nimport { createModuleLogger } from \"@logger/index\";\r\nimport dotenv from \"dotenv\";\r\n\r\ndotenv.config();\r\n\r\nconst logger = createModuleLogger(\"server\");\r\n\r\nexport interface StartServerOptions {\r\n port?: number;\r\n rootDir?: string;\r\n appDir?: string;\r\n isDev?: boolean;\r\n config?: FrameworkConfig;\r\n}\r\n\r\n/**\r\n * Unified server startup function.\r\n * Handles both development and production modes.\r\n *\r\n * @param options - Server startup options\r\n */\r\nexport async function startServer(options: StartServerOptions = {}) {\r\n const isDev = options.isDev ?? process.env.NODE_ENV === \"development\";\r\n const projectRoot = options.rootDir ?? process.cwd();\r\n\r\n // Load configuration\r\n const config = options.config ?? loadConfig(projectRoot);\r\n\r\n // Use config values, but allow overrides from options and environment variables\r\n // PORT and HOST are standard environment variables in hosting platforms (Render, Heroku, etc.)\r\n const port =\r\n options.port ??\r\n (process.env.PORT ? parseInt(process.env.PORT, 10) : undefined) ??\r\n config.server.port;\r\n\r\n // In production, default to 0.0.0.0 to be accessible from outside\r\n // This is required for platforms like Render.com, Heroku, etc.\r\n const host =\r\n process.env.HOST ?? (!isDev ? \"0.0.0.0\" : undefined) ?? config.server.host;\r\n\r\n const appDir =\r\n options.appDir ??\r\n (isDev\r\n ? getAppDir(projectRoot, config)\r\n : path.join(getBuildDir(projectRoot, config), \"server\"));\r\n\r\n if (!isDev && !fs.existsSync(appDir)) {\r\n logger.error(\"Compiled directory not found\", undefined, {\r\n buildDir: config.directories.build,\r\n appDir,\r\n environment: \"production\",\r\n });\r\n process.exit(1);\r\n }\r\n\r\n const { app, httpServer } = await setupApplication({\r\n projectRoot,\r\n });\r\n\r\n // @TODO: Remove or validate if send the server is needed\r\n await runInitIfExists(projectRoot, { server: httpServer });\r\n\r\n const { routes, apiRoutes, wssRoutes, notFoundPage, errorPage, getRoutes } =\r\n setupServer(app, {\r\n projectRoot,\r\n appDir,\r\n isDev,\r\n config,\r\n });\r\n\r\n const routeLoader = isDev\r\n ? new FilesystemRouteLoader(appDir)\r\n : new ManifestRouteLoader(projectRoot);\r\n\r\n // Set up Socket.IO server and WebSocket event handlers\r\n setupWssEvents({\r\n httpServer,\r\n wssRoutes,\r\n });\r\n\r\n setupRoutes({\r\n app,\r\n routes,\r\n apiRoutes,\r\n notFoundPage,\r\n errorPage,\r\n isDev,\r\n projectRoot,\r\n routeLoader,\r\n getRoutes,\r\n config,\r\n });\r\n\r\n httpServer.listen(port, host, () => {\r\n if (isDev) {\r\n logger.info(\"🚀 Dev server running\", {\r\n url: `http://${host}:${port}`,\r\n appDir,\r\n });\r\n logger.info(\"🧭 Reading routes from\", { appDir });\r\n logger.info(\"📦 Client served from /static/client.js\");\r\n } else {\r\n const buildDir = config.directories.build;\r\n logger.info(\"🚀 Prod server running\", {\r\n url: `http://${host}:${port}`,\r\n appDir,\r\n buildDir,\r\n });\r\n logger.info(\"🧭 Reading compiled routes from\", { appDir });\r\n logger.info(\"📦 Client served from\", {\r\n path: `/static (${buildDir}/client)`,\r\n });\r\n logger.info(\"📄 SSG served from\", {\r\n path: `${buildDir}/ssg (if exists)`,\r\n });\r\n }\r\n });\r\n}\r\n\r\nexport interface StartDevServerOptions {\r\n port?: number;\r\n rootDir?: string;\r\n appDir?: string;\r\n}\r\n\r\n/**\r\n * Development server startup.\r\n * Wrapper around startServer for backward compatibility.\r\n *\r\n * @param options - Server options\r\n */\r\nexport async function startDevServer(options: StartDevServerOptions = {}) {\r\n return startServer({\r\n ...options,\r\n isDev: true,\r\n });\r\n}\r\n\r\nexport interface StartProdServerOptions {\r\n port?: number;\r\n rootDir?: string;\r\n appDir?: string;\r\n}\r\n\r\n/**\r\n * Production server startup.\r\n * Wrapper around startServer for backward compatibility.\r\n *\r\n * @param options - Server options\r\n */\r\nexport async function startProdServer(options: StartProdServerOptions = {}) {\r\n return startServer({\r\n ...options,\r\n isDev: false,\r\n });\r\n}\r\n","import express from \"express\";\r\nimport path from \"path\";\r\nimport {\r\n FilesystemRouteLoader,\r\n ManifestRouteLoader,\r\n RouteLoader,\r\n writeClientRoutesManifest,\r\n} from \"@router/index\";\r\nimport { startClientBundler } from \"@build/bundler/client\";\r\nimport { setupHotReload } from \"@dev/hot-reload-client\";\r\nimport { clearAppRequireCache } from \"@dev/hot-reload-server\";\r\nimport { LoadedRoute, ApiRoute, WssRoute } from \"@router/index.types\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\nimport { getBuildDir } from \"@src/config\";\r\n\r\nexport { RouteLoader };\r\n\r\nimport type { FrameworkConfig } from \"@src/config\";\r\n\r\nexport interface ServerSetupOptions {\r\n projectRoot: string;\r\n appDir: string;\r\n isDev: boolean;\r\n config?: FrameworkConfig;\r\n}\r\n\r\nexport interface ServerSetupResult {\r\n routes: LoadedRoute[];\r\n wssRoutes: WssRoute[];\r\n notFoundPage: LoadedRoute | null;\r\n errorPage: LoadedRoute | null;\r\n apiRoutes: ApiRoute[];\r\n getRoutes?: () => {\r\n routes: LoadedRoute[];\r\n apiRoutes: ApiRoute[];\r\n };\r\n}\r\n\r\n/**\r\n * Sets up routes and bundler based on environment (dev/prod).\r\n *\r\n * @param app - Express application instance\r\n * @param options - Setup options\r\n * @returns Server setup result with routes and handlers\r\n */\r\nexport function setupServer(\r\n app: express.Application,\r\n options: ServerSetupOptions\r\n): ServerSetupResult {\r\n const { projectRoot, appDir, isDev, config } = options;\r\n\r\n const routeLoader: RouteLoader = isDev\r\n ? new FilesystemRouteLoader(appDir)\r\n : new ManifestRouteLoader(projectRoot);\r\n\r\n if (isDev) {\r\n const { outDir, waitForBuild } = startClientBundler(projectRoot, \"development\");\r\n \r\n // Callback to reload routes manifest and clear cache when files change\r\n const onFileChange = async (filePath: string) => {\r\n const rel = path.relative(appDir, filePath);\r\n const isPageFile = filePath.includes(\"page.tsx\") || filePath.includes(\"page.ts\") || \r\n filePath.includes(\"layout.tsx\") || filePath.includes(\"layout.ts\") ||\r\n filePath.includes(\"_not-found\") || filePath.includes(\"_error\");\r\n const isTsFile = filePath.endsWith(\".ts\") || filePath.endsWith(\".tsx\");\r\n \r\n // Clear require cache for ANY TypeScript/TSX file change\r\n // This ensures components, utilities, hooks, etc. are reloaded correctly\r\n if (isTsFile) {\r\n clearAppRequireCache(appDir);\r\n console.log(`[hot-reload] Cleared require cache for: ${rel}`);\r\n }\r\n \r\n // Reload client routes manifest for page files (affects client-side routing)\r\n // This is needed when routes are added/removed/changed\r\n if (isPageFile) {\r\n const loader = new FilesystemRouteLoader(appDir);\r\n const newRoutes = loader.loadRoutes();\r\n writeClientRoutesManifest(newRoutes, projectRoot);\r\n console.log(\"[hot-reload] Client routes manifest reloaded\");\r\n }\r\n \r\n // Note: \r\n // - API routes are already reloaded on each request via getRoutes().apiRoutes\r\n // - WSS routes require server restart to take effect (Socket.IO setup is one-time)\r\n // - Components and other files are handled by the bundler (Rspack watch mode)\r\n // and the require cache is cleared above to ensure server-side code reloads\r\n };\r\n \r\n setupHotReload({ app, appDir, waitForBuild, onFileChange });\r\n \r\n app.use(\"/static\", express.static(outDir));\r\n\r\n const routes = routeLoader.loadRoutes();\r\n const wssRoutes = routeLoader.loadWssRoutes();\r\n const notFoundPage = routeLoader.loadNotFoundRoute();\r\n const errorPage = routeLoader.loadErrorRoute();\r\n writeClientRoutesManifest(routes, projectRoot);\r\n\r\n function getRoutes() {\r\n clearAppRequireCache(appDir);\r\n const loader = new FilesystemRouteLoader(appDir);\r\n return {\r\n routes: loader.loadRoutes(),\r\n apiRoutes: loader.loadApiRoutes(),\r\n };\r\n }\r\n\r\n return {\r\n routes,\r\n wssRoutes,\r\n notFoundPage,\r\n errorPage,\r\n apiRoutes: routeLoader.loadApiRoutes(),\r\n getRoutes,\r\n };\r\n } else {\r\n const routes = routeLoader.loadRoutes();\r\n const apiRoutes = routeLoader.loadApiRoutes();\r\n const wssRoutes = routeLoader.loadWssRoutes();\r\n const notFoundPage = routeLoader.loadNotFoundRoute();\r\n const errorPage = routeLoader.loadErrorRoute();\r\n\r\n const buildDir = config ? getBuildDir(projectRoot, config) : path.join(projectRoot, BUILD_FOLDER_NAME);\r\n const clientOutDir = path.join(buildDir, \"client\");\r\n app.use(\r\n \"/static\",\r\n express.static(clientOutDir, {\r\n maxAge: \"1y\",\r\n immutable: true,\r\n })\r\n );\r\n\r\n return {\r\n routes,\r\n apiRoutes,\r\n wssRoutes,\r\n notFoundPage,\r\n errorPage,\r\n };\r\n }\r\n}\r\n","/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */\nimport { stat as statcb } from 'fs';\nimport { stat, readdir } from 'fs/promises';\nimport { EventEmitter } from 'events';\nimport * as sysPath from 'path';\nimport { readdirp } from 'readdirp';\nimport { NodeFsHandler, EVENTS as EV, isWindows, isIBMi, EMPTY_FN, STR_CLOSE, STR_END, } from './handler.js';\nconst SLASH = '/';\nconst SLASH_SLASH = '//';\nconst ONE_DOT = '.';\nconst TWO_DOTS = '..';\nconst STRING_TYPE = 'string';\nconst BACK_SLASH_RE = /\\\\/g;\nconst DOUBLE_SLASH_RE = /\\/\\//;\nconst DOT_RE = /\\..*\\.(sw[px])$|~$|\\.subl.*\\.tmp/;\nconst REPLACER_RE = /^\\.[/\\\\]/;\nfunction arrify(item) {\n return Array.isArray(item) ? item : [item];\n}\nconst isMatcherObject = (matcher) => typeof matcher === 'object' && matcher !== null && !(matcher instanceof RegExp);\nfunction createPattern(matcher) {\n if (typeof matcher === 'function')\n return matcher;\n if (typeof matcher === 'string')\n return (string) => matcher === string;\n if (matcher instanceof RegExp)\n return (string) => matcher.test(string);\n if (typeof matcher === 'object' && matcher !== null) {\n return (string) => {\n if (matcher.path === string)\n return true;\n if (matcher.recursive) {\n const relative = sysPath.relative(matcher.path, string);\n if (!relative) {\n return false;\n }\n return !relative.startsWith('..') && !sysPath.isAbsolute(relative);\n }\n return false;\n };\n }\n return () => false;\n}\nfunction normalizePath(path) {\n if (typeof path !== 'string')\n throw new Error('string expected');\n path = sysPath.normalize(path);\n path = path.replace(/\\\\/g, '/');\n let prepend = false;\n if (path.startsWith('//'))\n prepend = true;\n const DOUBLE_SLASH_RE = /\\/\\//;\n while (path.match(DOUBLE_SLASH_RE))\n path = path.replace(DOUBLE_SLASH_RE, '/');\n if (prepend)\n path = '/' + path;\n return path;\n}\nfunction matchPatterns(patterns, testString, stats) {\n const path = normalizePath(testString);\n for (let index = 0; index < patterns.length; index++) {\n const pattern = patterns[index];\n if (pattern(path, stats)) {\n return true;\n }\n }\n return false;\n}\nfunction anymatch(matchers, testString) {\n if (matchers == null) {\n throw new TypeError('anymatch: specify first argument');\n }\n // Early cache for matchers.\n const matchersArray = arrify(matchers);\n const patterns = matchersArray.map((matcher) => createPattern(matcher));\n if (testString == null) {\n return (testString, stats) => {\n return matchPatterns(patterns, testString, stats);\n };\n }\n return matchPatterns(patterns, testString);\n}\nconst unifyPaths = (paths_) => {\n const paths = arrify(paths_).flat();\n if (!paths.every((p) => typeof p === STRING_TYPE)) {\n throw new TypeError(`Non-string provided as watch path: ${paths}`);\n }\n return paths.map(normalizePathToUnix);\n};\n// If SLASH_SLASH occurs at the beginning of path, it is not replaced\n// because \"//StoragePC/DrivePool/Movies\" is a valid network path\nconst toUnix = (string) => {\n let str = string.replace(BACK_SLASH_RE, SLASH);\n let prepend = false;\n if (str.startsWith(SLASH_SLASH)) {\n prepend = true;\n }\n while (str.match(DOUBLE_SLASH_RE)) {\n str = str.replace(DOUBLE_SLASH_RE, SLASH);\n }\n if (prepend) {\n str = SLASH + str;\n }\n return str;\n};\n// Our version of upath.normalize\n// TODO: this is not equal to path-normalize module - investigate why\nconst normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path)));\n// TODO: refactor\nconst normalizeIgnored = (cwd = '') => (path) => {\n if (typeof path === 'string') {\n return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path));\n }\n else {\n return path;\n }\n};\nconst getAbsolutePath = (path, cwd) => {\n if (sysPath.isAbsolute(path)) {\n return path;\n }\n return sysPath.join(cwd, path);\n};\nconst EMPTY_SET = Object.freeze(new Set());\n/**\n * Directory entry.\n */\nclass DirEntry {\n constructor(dir, removeWatcher) {\n this.path = dir;\n this._removeWatcher = removeWatcher;\n this.items = new Set();\n }\n add(item) {\n const { items } = this;\n if (!items)\n return;\n if (item !== ONE_DOT && item !== TWO_DOTS)\n items.add(item);\n }\n async remove(item) {\n const { items } = this;\n if (!items)\n return;\n items.delete(item);\n if (items.size > 0)\n return;\n const dir = this.path;\n try {\n await readdir(dir);\n }\n catch (err) {\n if (this._removeWatcher) {\n this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir));\n }\n }\n }\n has(item) {\n const { items } = this;\n if (!items)\n return;\n return items.has(item);\n }\n getChildren() {\n const { items } = this;\n if (!items)\n return [];\n return [...items.values()];\n }\n dispose() {\n this.items.clear();\n this.path = '';\n this._removeWatcher = EMPTY_FN;\n this.items = EMPTY_SET;\n Object.freeze(this);\n }\n}\nconst STAT_METHOD_F = 'stat';\nconst STAT_METHOD_L = 'lstat';\nexport class WatchHelper {\n constructor(path, follow, fsw) {\n this.fsw = fsw;\n const watchPath = path;\n this.path = path = path.replace(REPLACER_RE, '');\n this.watchPath = watchPath;\n this.fullWatchPath = sysPath.resolve(watchPath);\n this.dirParts = [];\n this.dirParts.forEach((parts) => {\n if (parts.length > 1)\n parts.pop();\n });\n this.followSymlinks = follow;\n this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;\n }\n entryPath(entry) {\n return sysPath.join(this.watchPath, sysPath.relative(this.watchPath, entry.fullPath));\n }\n filterPath(entry) {\n const { stats } = entry;\n if (stats && stats.isSymbolicLink())\n return this.filterDir(entry);\n const resolvedPath = this.entryPath(entry);\n // TODO: what if stats is undefined? remove !\n return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);\n }\n filterDir(entry) {\n return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);\n }\n}\n/**\n * Watches files & directories for changes. Emitted events:\n * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`\n *\n * new FSWatcher()\n * .add(directories)\n * .on('add', path => log('File', path, 'was added'))\n */\nexport class FSWatcher extends EventEmitter {\n // Not indenting methods for history sake; for now.\n constructor(_opts = {}) {\n super();\n this.closed = false;\n this._closers = new Map();\n this._ignoredPaths = new Set();\n this._throttled = new Map();\n this._streams = new Set();\n this._symlinkPaths = new Map();\n this._watched = new Map();\n this._pendingWrites = new Map();\n this._pendingUnlinks = new Map();\n this._readyCount = 0;\n this._readyEmitted = false;\n const awf = _opts.awaitWriteFinish;\n const DEF_AWF = { stabilityThreshold: 2000, pollInterval: 100 };\n const opts = {\n // Defaults\n persistent: true,\n ignoreInitial: false,\n ignorePermissionErrors: false,\n interval: 100,\n binaryInterval: 300,\n followSymlinks: true,\n usePolling: false,\n // useAsync: false,\n atomic: true, // NOTE: overwritten later (depends on usePolling)\n ..._opts,\n // Change format\n ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),\n awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === 'object' ? { ...DEF_AWF, ...awf } : false,\n };\n // Always default to polling on IBM i because fs.watch() is not available on IBM i.\n if (isIBMi)\n opts.usePolling = true;\n // Editor atomic write normalization enabled by default with fs.watch\n if (opts.atomic === undefined)\n opts.atomic = !opts.usePolling;\n // opts.atomic = typeof _opts.atomic === 'number' ? _opts.atomic : 100;\n // Global override. Useful for developers, who need to force polling for all\n // instances of chokidar, regardless of usage / dependency depth\n const envPoll = process.env.CHOKIDAR_USEPOLLING;\n if (envPoll !== undefined) {\n const envLower = envPoll.toLowerCase();\n if (envLower === 'false' || envLower === '0')\n opts.usePolling = false;\n else if (envLower === 'true' || envLower === '1')\n opts.usePolling = true;\n else\n opts.usePolling = !!envLower;\n }\n const envInterval = process.env.CHOKIDAR_INTERVAL;\n if (envInterval)\n opts.interval = Number.parseInt(envInterval, 10);\n // This is done to emit ready only once, but each 'add' will increase that?\n let readyCalls = 0;\n this._emitReady = () => {\n readyCalls++;\n if (readyCalls >= this._readyCount) {\n this._emitReady = EMPTY_FN;\n this._readyEmitted = true;\n // use process.nextTick to allow time for listener to be bound\n process.nextTick(() => this.emit(EV.READY));\n }\n };\n this._emitRaw = (...args) => this.emit(EV.RAW, ...args);\n this._boundRemove = this._remove.bind(this);\n this.options = opts;\n this._nodeFsHandler = new NodeFsHandler(this);\n // You’re frozen when your heart’s not open.\n Object.freeze(opts);\n }\n _addIgnoredPath(matcher) {\n if (isMatcherObject(matcher)) {\n // return early if we already have a deeply equal matcher object\n for (const ignored of this._ignoredPaths) {\n if (isMatcherObject(ignored) &&\n ignored.path === matcher.path &&\n ignored.recursive === matcher.recursive) {\n return;\n }\n }\n }\n this._ignoredPaths.add(matcher);\n }\n _removeIgnoredPath(matcher) {\n this._ignoredPaths.delete(matcher);\n // now find any matcher objects with the matcher as path\n if (typeof matcher === 'string') {\n for (const ignored of this._ignoredPaths) {\n // TODO (43081j): make this more efficient.\n // probably just make a `this._ignoredDirectories` or some\n // such thing.\n if (isMatcherObject(ignored) && ignored.path === matcher) {\n this._ignoredPaths.delete(ignored);\n }\n }\n }\n }\n // Public methods\n /**\n * Adds paths to be watched on an existing FSWatcher instance.\n * @param paths_ file or file list. Other arguments are unused\n */\n add(paths_, _origAdd, _internal) {\n const { cwd } = this.options;\n this.closed = false;\n this._closePromise = undefined;\n let paths = unifyPaths(paths_);\n if (cwd) {\n paths = paths.map((path) => {\n const absPath = getAbsolutePath(path, cwd);\n // Check `path` instead of `absPath` because the cwd portion can't be a glob\n return absPath;\n });\n }\n paths.forEach((path) => {\n this._removeIgnoredPath(path);\n });\n this._userIgnored = undefined;\n if (!this._readyCount)\n this._readyCount = 0;\n this._readyCount += paths.length;\n Promise.all(paths.map(async (path) => {\n const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, undefined, 0, _origAdd);\n if (res)\n this._emitReady();\n return res;\n })).then((results) => {\n if (this.closed)\n return;\n results.forEach((item) => {\n if (item)\n this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item));\n });\n });\n return this;\n }\n /**\n * Close watchers or start ignoring events from specified paths.\n */\n unwatch(paths_) {\n if (this.closed)\n return this;\n const paths = unifyPaths(paths_);\n const { cwd } = this.options;\n paths.forEach((path) => {\n // convert to absolute path unless relative path already matches\n if (!sysPath.isAbsolute(path) && !this._closers.has(path)) {\n if (cwd)\n path = sysPath.join(cwd, path);\n path = sysPath.resolve(path);\n }\n this._closePath(path);\n this._addIgnoredPath(path);\n if (this._watched.has(path)) {\n this._addIgnoredPath({\n path,\n recursive: true,\n });\n }\n // reset the cached userIgnored anymatch fn\n // to make ignoredPaths changes effective\n this._userIgnored = undefined;\n });\n return this;\n }\n /**\n * Close watchers and remove all listeners from watched paths.\n */\n close() {\n if (this._closePromise) {\n return this._closePromise;\n }\n this.closed = true;\n // Memory management.\n this.removeAllListeners();\n const closers = [];\n this._closers.forEach((closerList) => closerList.forEach((closer) => {\n const promise = closer();\n if (promise instanceof Promise)\n closers.push(promise);\n }));\n this._streams.forEach((stream) => stream.destroy());\n this._userIgnored = undefined;\n this._readyCount = 0;\n this._readyEmitted = false;\n this._watched.forEach((dirent) => dirent.dispose());\n this._closers.clear();\n this._watched.clear();\n this._streams.clear();\n this._symlinkPaths.clear();\n this._throttled.clear();\n this._closePromise = closers.length\n ? Promise.all(closers).then(() => undefined)\n : Promise.resolve();\n return this._closePromise;\n }\n /**\n * Expose list of watched paths\n * @returns for chaining\n */\n getWatched() {\n const watchList = {};\n this._watched.forEach((entry, dir) => {\n const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir;\n const index = key || ONE_DOT;\n watchList[index] = entry.getChildren().sort();\n });\n return watchList;\n }\n emitWithAll(event, args) {\n this.emit(event, ...args);\n if (event !== EV.ERROR)\n this.emit(EV.ALL, event, ...args);\n }\n // Common helpers\n // --------------\n /**\n * Normalize and emit events.\n * Calling _emit DOES NOT MEAN emit() would be called!\n * @param event Type of event\n * @param path File or directory path\n * @param stats arguments to be passed with event\n * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n async _emit(event, path, stats) {\n if (this.closed)\n return;\n const opts = this.options;\n if (isWindows)\n path = sysPath.normalize(path);\n if (opts.cwd)\n path = sysPath.relative(opts.cwd, path);\n const args = [path];\n if (stats != null)\n args.push(stats);\n const awf = opts.awaitWriteFinish;\n let pw;\n if (awf && (pw = this._pendingWrites.get(path))) {\n pw.lastChange = new Date();\n return this;\n }\n if (opts.atomic) {\n if (event === EV.UNLINK) {\n this._pendingUnlinks.set(path, [event, ...args]);\n setTimeout(() => {\n this._pendingUnlinks.forEach((entry, path) => {\n this.emit(...entry);\n this.emit(EV.ALL, ...entry);\n this._pendingUnlinks.delete(path);\n });\n }, typeof opts.atomic === 'number' ? opts.atomic : 100);\n return this;\n }\n if (event === EV.ADD && this._pendingUnlinks.has(path)) {\n event = EV.CHANGE;\n this._pendingUnlinks.delete(path);\n }\n }\n if (awf && (event === EV.ADD || event === EV.CHANGE) && this._readyEmitted) {\n const awfEmit = (err, stats) => {\n if (err) {\n event = EV.ERROR;\n args[0] = err;\n this.emitWithAll(event, args);\n }\n else if (stats) {\n // if stats doesn't exist the file must have been deleted\n if (args.length > 1) {\n args[1] = stats;\n }\n else {\n args.push(stats);\n }\n this.emitWithAll(event, args);\n }\n };\n this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);\n return this;\n }\n if (event === EV.CHANGE) {\n const isThrottled = !this._throttle(EV.CHANGE, path, 50);\n if (isThrottled)\n return this;\n }\n if (opts.alwaysStat &&\n stats === undefined &&\n (event === EV.ADD || event === EV.ADD_DIR || event === EV.CHANGE)) {\n const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path;\n let stats;\n try {\n stats = await stat(fullPath);\n }\n catch (err) {\n // do nothing\n }\n // Suppress event when fs_stat fails, to avoid sending undefined 'stat'\n if (!stats || this.closed)\n return;\n args.push(stats);\n }\n this.emitWithAll(event, args);\n return this;\n }\n /**\n * Common handler for errors\n * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n _handleError(error) {\n const code = error && error.code;\n if (error &&\n code !== 'ENOENT' &&\n code !== 'ENOTDIR' &&\n (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))) {\n this.emit(EV.ERROR, error);\n }\n return error || this.closed;\n }\n /**\n * Helper utility for throttling\n * @param actionType type being throttled\n * @param path being acted upon\n * @param timeout duration of time to suppress duplicate actions\n * @returns tracking object or false if action should be suppressed\n */\n _throttle(actionType, path, timeout) {\n if (!this._throttled.has(actionType)) {\n this._throttled.set(actionType, new Map());\n }\n const action = this._throttled.get(actionType);\n if (!action)\n throw new Error('invalid throttle');\n const actionPath = action.get(path);\n if (actionPath) {\n actionPath.count++;\n return false;\n }\n // eslint-disable-next-line prefer-const\n let timeoutObject;\n const clear = () => {\n const item = action.get(path);\n const count = item ? item.count : 0;\n action.delete(path);\n clearTimeout(timeoutObject);\n if (item)\n clearTimeout(item.timeoutObject);\n return count;\n };\n timeoutObject = setTimeout(clear, timeout);\n const thr = { timeoutObject, clear, count: 0 };\n action.set(path, thr);\n return thr;\n }\n _incrReadyCount() {\n return this._readyCount++;\n }\n /**\n * Awaits write operation to finish.\n * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.\n * @param path being acted upon\n * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished\n * @param event\n * @param awfEmit Callback to be called when ready for event to be emitted.\n */\n _awaitWriteFinish(path, threshold, event, awfEmit) {\n const awf = this.options.awaitWriteFinish;\n if (typeof awf !== 'object')\n return;\n const pollInterval = awf.pollInterval;\n let timeoutHandler;\n let fullPath = path;\n if (this.options.cwd && !sysPath.isAbsolute(path)) {\n fullPath = sysPath.join(this.options.cwd, path);\n }\n const now = new Date();\n const writes = this._pendingWrites;\n function awaitWriteFinishFn(prevStat) {\n statcb(fullPath, (err, curStat) => {\n if (err || !writes.has(path)) {\n if (err && err.code !== 'ENOENT')\n awfEmit(err);\n return;\n }\n const now = Number(new Date());\n if (prevStat && curStat.size !== prevStat.size) {\n writes.get(path).lastChange = now;\n }\n const pw = writes.get(path);\n const df = now - pw.lastChange;\n if (df >= threshold) {\n writes.delete(path);\n awfEmit(undefined, curStat);\n }\n else {\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);\n }\n });\n }\n if (!writes.has(path)) {\n writes.set(path, {\n lastChange: now,\n cancelWait: () => {\n writes.delete(path);\n clearTimeout(timeoutHandler);\n return event;\n },\n });\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);\n }\n }\n /**\n * Determines whether user has asked to ignore this path.\n */\n _isIgnored(path, stats) {\n if (this.options.atomic && DOT_RE.test(path))\n return true;\n if (!this._userIgnored) {\n const { cwd } = this.options;\n const ign = this.options.ignored;\n const ignored = (ign || []).map(normalizeIgnored(cwd));\n const ignoredPaths = [...this._ignoredPaths];\n const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];\n this._userIgnored = anymatch(list, undefined);\n }\n return this._userIgnored(path, stats);\n }\n _isntIgnored(path, stat) {\n return !this._isIgnored(path, stat);\n }\n /**\n * Provides a set of common helpers and properties relating to symlink handling.\n * @param path file or directory pattern being watched\n */\n _getWatchHelpers(path) {\n return new WatchHelper(path, this.options.followSymlinks, this);\n }\n // Directory helpers\n // -----------------\n /**\n * Provides directory tracking objects\n * @param directory path of the directory\n */\n _getWatchedDir(directory) {\n const dir = sysPath.resolve(directory);\n if (!this._watched.has(dir))\n this._watched.set(dir, new DirEntry(dir, this._boundRemove));\n return this._watched.get(dir);\n }\n // File helpers\n // ------------\n /**\n * Check for read permissions: https://stackoverflow.com/a/11781404/1358405\n */\n _hasReadPermissions(stats) {\n if (this.options.ignorePermissionErrors)\n return true;\n return Boolean(Number(stats.mode) & 0o400);\n }\n /**\n * Handles emitting unlink events for\n * files and directories, and via recursion, for\n * files and directories within directories that are unlinked\n * @param directory within which the following item is located\n * @param item base path of item/directory\n */\n _remove(directory, item, isDirectory) {\n // if what is being deleted is a directory, get that directory's paths\n // for recursive deleting and cleaning of watched object\n // if it is not a directory, nestedDirectoryChildren will be empty array\n const path = sysPath.join(directory, item);\n const fullPath = sysPath.resolve(path);\n isDirectory =\n isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);\n // prevent duplicate handling in case of arriving here nearly simultaneously\n // via multiple paths (such as _handleFile and _handleDir)\n if (!this._throttle('remove', path, 100))\n return;\n // if the only watched file is removed, watch for its return\n if (!isDirectory && this._watched.size === 1) {\n this.add(directory, item, true);\n }\n // This will create a new entry in the watched object in either case\n // so we got to do the directory check beforehand\n const wp = this._getWatchedDir(path);\n const nestedDirectoryChildren = wp.getChildren();\n // Recursively remove children directories / files.\n nestedDirectoryChildren.forEach((nested) => this._remove(path, nested));\n // Check if item was on the watched list and remove it\n const parent = this._getWatchedDir(directory);\n const wasTracked = parent.has(item);\n parent.remove(item);\n // Fixes issue #1042 -> Relative paths were detected and added as symlinks\n // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),\n // but never removed from the map in case the path was deleted.\n // This leads to an incorrect state if the path was recreated:\n // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553\n if (this._symlinkPaths.has(fullPath)) {\n this._symlinkPaths.delete(fullPath);\n }\n // If we wait for this file to be fully written, cancel the wait.\n let relPath = path;\n if (this.options.cwd)\n relPath = sysPath.relative(this.options.cwd, path);\n if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {\n const event = this._pendingWrites.get(relPath).cancelWait();\n if (event === EV.ADD)\n return;\n }\n // The Entry will either be a directory that just got removed\n // or a bogus entry to a file, in either case we have to remove it\n this._watched.delete(path);\n this._watched.delete(fullPath);\n const eventName = isDirectory ? EV.UNLINK_DIR : EV.UNLINK;\n if (wasTracked && !this._isIgnored(path))\n this._emit(eventName, path);\n // Avoid conflicts if we later create another file with the same name\n this._closePath(path);\n }\n /**\n * Closes all watchers for a path\n */\n _closePath(path) {\n this._closeFile(path);\n const dir = sysPath.dirname(path);\n this._getWatchedDir(dir).remove(sysPath.basename(path));\n }\n /**\n * Closes only file-specific watchers\n */\n _closeFile(path) {\n const closers = this._closers.get(path);\n if (!closers)\n return;\n closers.forEach((closer) => closer());\n this._closers.delete(path);\n }\n _addPathCloser(path, closer) {\n if (!closer)\n return;\n let list = this._closers.get(path);\n if (!list) {\n list = [];\n this._closers.set(path, list);\n }\n list.push(closer);\n }\n _readdirp(root, opts) {\n if (this.closed)\n return;\n const options = { type: EV.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };\n let stream = readdirp(root, options);\n this._streams.add(stream);\n stream.once(STR_CLOSE, () => {\n stream = undefined;\n });\n stream.once(STR_END, () => {\n if (stream) {\n this._streams.delete(stream);\n stream = undefined;\n }\n });\n return stream;\n }\n}\n/**\n * Instantiates watcher with paths to be tracked.\n * @param paths file / directory paths\n * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others\n * @returns an instance of FSWatcher for chaining.\n * @example\n * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });\n * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })\n */\nexport function watch(paths, options = {}) {\n const watcher = new FSWatcher(options);\n watcher.add(paths);\n return watcher;\n}\nexport default { watch, FSWatcher };\n","import { stat, lstat, readdir, realpath } from 'node:fs/promises';\nimport { Readable } from 'node:stream';\nimport { resolve as presolve, relative as prelative, join as pjoin, sep as psep } from 'node:path';\nexport const EntryTypes = {\n FILE_TYPE: 'files',\n DIR_TYPE: 'directories',\n FILE_DIR_TYPE: 'files_directories',\n EVERYTHING_TYPE: 'all',\n};\nconst defaultOptions = {\n root: '.',\n fileFilter: (_entryInfo) => true,\n directoryFilter: (_entryInfo) => true,\n type: EntryTypes.FILE_TYPE,\n lstat: false,\n depth: 2147483648,\n alwaysStat: false,\n highWaterMark: 4096,\n};\nObject.freeze(defaultOptions);\nconst RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';\nconst NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);\nconst ALL_TYPES = [\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n];\nconst DIR_TYPES = new Set([\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n]);\nconst FILE_TYPES = new Set([\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n]);\nconst isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);\nconst wantBigintFsStats = process.platform === 'win32';\nconst emptyFn = (_entryInfo) => true;\nconst normalizeFilter = (filter) => {\n if (filter === undefined)\n return emptyFn;\n if (typeof filter === 'function')\n return filter;\n if (typeof filter === 'string') {\n const fl = filter.trim();\n return (entry) => entry.basename === fl;\n }\n if (Array.isArray(filter)) {\n const trItems = filter.map((item) => item.trim());\n return (entry) => trItems.some((f) => entry.basename === f);\n }\n return emptyFn;\n};\n/** Readable readdir stream, emitting new files as they're being listed. */\nexport class ReaddirpStream extends Readable {\n constructor(options = {}) {\n super({\n objectMode: true,\n autoDestroy: true,\n highWaterMark: options.highWaterMark,\n });\n const opts = { ...defaultOptions, ...options };\n const { root, type } = opts;\n this._fileFilter = normalizeFilter(opts.fileFilter);\n this._directoryFilter = normalizeFilter(opts.directoryFilter);\n const statMethod = opts.lstat ? lstat : stat;\n // Use bigint stats if it's windows and stat() supports options (node 10+).\n if (wantBigintFsStats) {\n this._stat = (path) => statMethod(path, { bigint: true });\n }\n else {\n this._stat = statMethod;\n }\n this._maxDepth = opts.depth ?? defaultOptions.depth;\n this._wantsDir = type ? DIR_TYPES.has(type) : false;\n this._wantsFile = type ? FILE_TYPES.has(type) : false;\n this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;\n this._root = presolve(root);\n this._isDirent = !opts.alwaysStat;\n this._statsProp = this._isDirent ? 'dirent' : 'stats';\n this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };\n // Launch stream with one parent, the root dir.\n this.parents = [this._exploreDir(root, 1)];\n this.reading = false;\n this.parent = undefined;\n }\n async _read(batch) {\n if (this.reading)\n return;\n this.reading = true;\n try {\n while (!this.destroyed && batch > 0) {\n const par = this.parent;\n const fil = par && par.files;\n if (fil && fil.length > 0) {\n const { path, depth } = par;\n const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path));\n const awaited = await Promise.all(slice);\n for (const entry of awaited) {\n if (!entry)\n continue;\n if (this.destroyed)\n return;\n const entryType = await this._getEntryType(entry);\n if (entryType === 'directory' && this._directoryFilter(entry)) {\n if (depth <= this._maxDepth) {\n this.parents.push(this._exploreDir(entry.fullPath, depth + 1));\n }\n if (this._wantsDir) {\n this.push(entry);\n batch--;\n }\n }\n else if ((entryType === 'file' || this._includeAsFile(entry)) &&\n this._fileFilter(entry)) {\n if (this._wantsFile) {\n this.push(entry);\n batch--;\n }\n }\n }\n }\n else {\n const parent = this.parents.pop();\n if (!parent) {\n this.push(null);\n break;\n }\n this.parent = await parent;\n if (this.destroyed)\n return;\n }\n }\n }\n catch (error) {\n this.destroy(error);\n }\n finally {\n this.reading = false;\n }\n }\n async _exploreDir(path, depth) {\n let files;\n try {\n files = await readdir(path, this._rdOptions);\n }\n catch (error) {\n this._onError(error);\n }\n return { files, depth, path };\n }\n async _formatEntry(dirent, path) {\n let entry;\n const basename = this._isDirent ? dirent.name : dirent;\n try {\n const fullPath = presolve(pjoin(path, basename));\n entry = { path: prelative(this._root, fullPath), fullPath, basename };\n entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);\n }\n catch (err) {\n this._onError(err);\n return;\n }\n return entry;\n }\n _onError(err) {\n if (isNormalFlowError(err) && !this.destroyed) {\n this.emit('warn', err);\n }\n else {\n this.destroy(err);\n }\n }\n async _getEntryType(entry) {\n // entry may be undefined, because a warning or an error were emitted\n // and the statsProp is undefined\n if (!entry && this._statsProp in entry) {\n return '';\n }\n const stats = entry[this._statsProp];\n if (stats.isFile())\n return 'file';\n if (stats.isDirectory())\n return 'directory';\n if (stats && stats.isSymbolicLink()) {\n const full = entry.fullPath;\n try {\n const entryRealPath = await realpath(full);\n const entryRealPathStats = await lstat(entryRealPath);\n if (entryRealPathStats.isFile()) {\n return 'file';\n }\n if (entryRealPathStats.isDirectory()) {\n const len = entryRealPath.length;\n if (full.startsWith(entryRealPath) && full.substr(len, 1) === psep) {\n const recursiveError = new Error(`Circular symlink detected: \"${full}\" points to \"${entryRealPath}\"`);\n // @ts-ignore\n recursiveError.code = RECURSIVE_ERROR_CODE;\n return this._onError(recursiveError);\n }\n return 'directory';\n }\n }\n catch (error) {\n this._onError(error);\n return '';\n }\n }\n }\n _includeAsFile(entry) {\n const stats = entry && entry[this._statsProp];\n return stats && this._wantsEverything && !stats.isDirectory();\n }\n}\n/**\n * Streaming version: Reads all files and directories in given root recursively.\n * Consumes ~constant small amount of RAM.\n * @param root Root directory\n * @param options Options to specify root (start directory), filters and recursion depth\n */\nexport function readdirp(root, options = {}) {\n // @ts-ignore\n let type = options.entryType || options.type;\n if (type === 'both')\n type = EntryTypes.FILE_DIR_TYPE; // backwards-compatibility\n if (type)\n options.type = type;\n if (!root) {\n throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');\n }\n else if (typeof root !== 'string') {\n throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');\n }\n else if (type && !ALL_TYPES.includes(type)) {\n throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);\n }\n options.root = root;\n return new ReaddirpStream(options);\n}\n/**\n * Promise version: Reads all files and directories in given root recursively.\n * Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.\n * @returns array of paths and their entry infos\n */\nexport function readdirpPromise(root, options = {}) {\n return new Promise((resolve, reject) => {\n const files = [];\n readdirp(root, options)\n .on('data', (entry) => files.push(entry))\n .on('end', () => resolve(files))\n .on('error', (error) => reject(error));\n });\n}\nexport default readdirp;\n","import { watchFile, unwatchFile, watch as fs_watch } from 'fs';\nimport { open, stat, lstat, realpath as fsrealpath } from 'fs/promises';\nimport * as sysPath from 'path';\nimport { type as osType } from 'os';\nexport const STR_DATA = 'data';\nexport const STR_END = 'end';\nexport const STR_CLOSE = 'close';\nexport const EMPTY_FN = () => { };\nexport const IDENTITY_FN = (val) => val;\nconst pl = process.platform;\nexport const isWindows = pl === 'win32';\nexport const isMacos = pl === 'darwin';\nexport const isLinux = pl === 'linux';\nexport const isFreeBSD = pl === 'freebsd';\nexport const isIBMi = osType() === 'OS400';\nexport const EVENTS = {\n ALL: 'all',\n READY: 'ready',\n ADD: 'add',\n CHANGE: 'change',\n ADD_DIR: 'addDir',\n UNLINK: 'unlink',\n UNLINK_DIR: 'unlinkDir',\n RAW: 'raw',\n ERROR: 'error',\n};\nconst EV = EVENTS;\nconst THROTTLE_MODE_WATCH = 'watch';\nconst statMethods = { lstat, stat };\nconst KEY_LISTENERS = 'listeners';\nconst KEY_ERR = 'errHandlers';\nconst KEY_RAW = 'rawEmitters';\nconst HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];\n// prettier-ignore\nconst binaryExtensions = new Set([\n '3dm', '3ds', '3g2', '3gp', '7z', 'a', 'aac', 'adp', 'afdesign', 'afphoto', 'afpub', 'ai',\n 'aif', 'aiff', 'alz', 'ape', 'apk', 'appimage', 'ar', 'arj', 'asf', 'au', 'avi',\n 'bak', 'baml', 'bh', 'bin', 'bk', 'bmp', 'btif', 'bz2', 'bzip2',\n 'cab', 'caf', 'cgm', 'class', 'cmx', 'cpio', 'cr2', 'cur', 'dat', 'dcm', 'deb', 'dex', 'djvu',\n 'dll', 'dmg', 'dng', 'doc', 'docm', 'docx', 'dot', 'dotm', 'dra', 'DS_Store', 'dsk', 'dts',\n 'dtshd', 'dvb', 'dwg', 'dxf',\n 'ecelp4800', 'ecelp7470', 'ecelp9600', 'egg', 'eol', 'eot', 'epub', 'exe',\n 'f4v', 'fbs', 'fh', 'fla', 'flac', 'flatpak', 'fli', 'flv', 'fpx', 'fst', 'fvt',\n 'g3', 'gh', 'gif', 'graffle', 'gz', 'gzip',\n 'h261', 'h263', 'h264', 'icns', 'ico', 'ief', 'img', 'ipa', 'iso',\n 'jar', 'jpeg', 'jpg', 'jpgv', 'jpm', 'jxr', 'key', 'ktx',\n 'lha', 'lib', 'lvp', 'lz', 'lzh', 'lzma', 'lzo',\n 'm3u', 'm4a', 'm4v', 'mar', 'mdi', 'mht', 'mid', 'midi', 'mj2', 'mka', 'mkv', 'mmr', 'mng',\n 'mobi', 'mov', 'movie', 'mp3',\n 'mp4', 'mp4a', 'mpeg', 'mpg', 'mpga', 'mxu',\n 'nef', 'npx', 'numbers', 'nupkg',\n 'o', 'odp', 'ods', 'odt', 'oga', 'ogg', 'ogv', 'otf', 'ott',\n 'pages', 'pbm', 'pcx', 'pdb', 'pdf', 'pea', 'pgm', 'pic', 'png', 'pnm', 'pot', 'potm',\n 'potx', 'ppa', 'ppam',\n 'ppm', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx', 'psd', 'pya', 'pyc', 'pyo', 'pyv',\n 'qt',\n 'rar', 'ras', 'raw', 'resources', 'rgb', 'rip', 'rlc', 'rmf', 'rmvb', 'rpm', 'rtf', 'rz',\n 's3m', 's7z', 'scpt', 'sgi', 'shar', 'snap', 'sil', 'sketch', 'slk', 'smv', 'snk', 'so',\n 'stl', 'suo', 'sub', 'swf',\n 'tar', 'tbz', 'tbz2', 'tga', 'tgz', 'thmx', 'tif', 'tiff', 'tlz', 'ttc', 'ttf', 'txz',\n 'udf', 'uvh', 'uvi', 'uvm', 'uvp', 'uvs', 'uvu',\n 'viv', 'vob',\n 'war', 'wav', 'wax', 'wbmp', 'wdp', 'weba', 'webm', 'webp', 'whl', 'wim', 'wm', 'wma',\n 'wmv', 'wmx', 'woff', 'woff2', 'wrm', 'wvx',\n 'xbm', 'xif', 'xla', 'xlam', 'xls', 'xlsb', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx', 'xm',\n 'xmind', 'xpi', 'xpm', 'xwd', 'xz',\n 'z', 'zip', 'zipx',\n]);\nconst isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());\n// TODO: emit errors properly. Example: EMFILE on Macos.\nconst foreach = (val, fn) => {\n if (val instanceof Set) {\n val.forEach(fn);\n }\n else {\n fn(val);\n }\n};\nconst addAndConvert = (main, prop, item) => {\n let container = main[prop];\n if (!(container instanceof Set)) {\n main[prop] = container = new Set([container]);\n }\n container.add(item);\n};\nconst clearItem = (cont) => (key) => {\n const set = cont[key];\n if (set instanceof Set) {\n set.clear();\n }\n else {\n delete cont[key];\n }\n};\nconst delFromSet = (main, prop, item) => {\n const container = main[prop];\n if (container instanceof Set) {\n container.delete(item);\n }\n else if (container === item) {\n delete main[prop];\n }\n};\nconst isEmptySet = (val) => (val instanceof Set ? val.size === 0 : !val);\nconst FsWatchInstances = new Map();\n/**\n * Instantiates the fs_watch interface\n * @param path to be watched\n * @param options to be passed to fs_watch\n * @param listener main event handler\n * @param errHandler emits info about errors\n * @param emitRaw emits raw event data\n * @returns {NativeFsWatcher}\n */\nfunction createFsWatchInstance(path, options, listener, errHandler, emitRaw) {\n const handleEvent = (rawEvent, evPath) => {\n listener(path);\n emitRaw(rawEvent, evPath, { watchedPath: path });\n // emit based on events occurring for files from a directory's watcher in\n // case the file's watcher misses it (and rely on throttling to de-dupe)\n if (evPath && path !== evPath) {\n fsWatchBroadcast(sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath));\n }\n };\n try {\n return fs_watch(path, {\n persistent: options.persistent,\n }, handleEvent);\n }\n catch (error) {\n errHandler(error);\n return undefined;\n }\n}\n/**\n * Helper for passing fs_watch event data to a collection of listeners\n * @param fullPath absolute path bound to fs_watch instance\n */\nconst fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {\n const cont = FsWatchInstances.get(fullPath);\n if (!cont)\n return;\n foreach(cont[listenerType], (listener) => {\n listener(val1, val2, val3);\n });\n};\n/**\n * Instantiates the fs_watch interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path\n * @param fullPath absolute path\n * @param options to be passed to fs_watch\n * @param handlers container for event listener functions\n */\nconst setFsWatchListener = (path, fullPath, options, handlers) => {\n const { listener, errHandler, rawEmitter } = handlers;\n let cont = FsWatchInstances.get(fullPath);\n let watcher;\n if (!options.persistent) {\n watcher = createFsWatchInstance(path, options, listener, errHandler, rawEmitter);\n if (!watcher)\n return;\n return watcher.close.bind(watcher);\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_ERR, errHandler);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n watcher = createFsWatchInstance(path, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, // no need to use broadcast here\n fsWatchBroadcast.bind(null, fullPath, KEY_RAW));\n if (!watcher)\n return;\n watcher.on(EV.ERROR, async (error) => {\n const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);\n if (cont)\n cont.watcherUnusable = true; // documented since Node 10.4.1\n // Workaround for https://github.com/joyent/node/issues/4337\n if (isWindows && error.code === 'EPERM') {\n try {\n const fd = await open(path, 'r');\n await fd.close();\n broadcastErr(error);\n }\n catch (err) {\n // do nothing\n }\n }\n else {\n broadcastErr(error);\n }\n });\n cont = {\n listeners: listener,\n errHandlers: errHandler,\n rawEmitters: rawEmitter,\n watcher,\n };\n FsWatchInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // removes this instance's listeners and closes the underlying fs_watch\n // instance if there are no more listeners left\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_ERR, errHandler);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n // Check to protect against issue gh-730.\n // if (cont.watcherUnusable) {\n cont.watcher.close();\n // }\n FsWatchInstances.delete(fullPath);\n HANDLER_KEYS.forEach(clearItem(cont));\n // @ts-ignore\n cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n// fs_watchFile helpers\n// object to hold per-process fs_watchFile instances\n// (may be shared across chokidar FSWatcher instances)\nconst FsWatchFileInstances = new Map();\n/**\n * Instantiates the fs_watchFile interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path to be watched\n * @param fullPath absolute path\n * @param options options to be passed to fs_watchFile\n * @param handlers container for event listener functions\n * @returns closer\n */\nconst setFsWatchFileListener = (path, fullPath, options, handlers) => {\n const { listener, rawEmitter } = handlers;\n let cont = FsWatchFileInstances.get(fullPath);\n // let listeners = new Set();\n // let rawEmitters = new Set();\n const copts = cont && cont.options;\n if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {\n // \"Upgrade\" the watcher to persistence or a quicker interval.\n // This creates some unlikely edge case issues if the user mixes\n // settings in a very weird way, but solving for those cases\n // doesn't seem worthwhile for the added complexity.\n // listeners = cont.listeners;\n // rawEmitters = cont.rawEmitters;\n unwatchFile(fullPath);\n cont = undefined;\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n // TODO\n // listeners.add(listener);\n // rawEmitters.add(rawEmitter);\n cont = {\n listeners: listener,\n rawEmitters: rawEmitter,\n options,\n watcher: watchFile(fullPath, options, (curr, prev) => {\n foreach(cont.rawEmitters, (rawEmitter) => {\n rawEmitter(EV.CHANGE, fullPath, { curr, prev });\n });\n const currmtime = curr.mtimeMs;\n if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {\n foreach(cont.listeners, (listener) => listener(path, curr));\n }\n }),\n };\n FsWatchFileInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // Removes this instance's listeners and closes the underlying fs_watchFile\n // instance if there are no more listeners left.\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n FsWatchFileInstances.delete(fullPath);\n unwatchFile(fullPath);\n cont.options = cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n/**\n * @mixin\n */\nexport class NodeFsHandler {\n constructor(fsW) {\n this.fsw = fsW;\n this._boundHandleError = (error) => fsW._handleError(error);\n }\n /**\n * Watch file for changes with fs_watchFile or fs_watch.\n * @param path to file or dir\n * @param listener on fs change\n * @returns closer for the watcher instance\n */\n _watchWithNodeFs(path, listener) {\n const opts = this.fsw.options;\n const directory = sysPath.dirname(path);\n const basename = sysPath.basename(path);\n const parent = this.fsw._getWatchedDir(directory);\n parent.add(basename);\n const absolutePath = sysPath.resolve(path);\n const options = {\n persistent: opts.persistent,\n };\n if (!listener)\n listener = EMPTY_FN;\n let closer;\n if (opts.usePolling) {\n const enableBin = opts.interval !== opts.binaryInterval;\n options.interval = enableBin && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;\n closer = setFsWatchFileListener(path, absolutePath, options, {\n listener,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n else {\n closer = setFsWatchListener(path, absolutePath, options, {\n listener,\n errHandler: this._boundHandleError,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n return closer;\n }\n /**\n * Watch a file and emit add event if warranted.\n * @returns closer for the watcher instance\n */\n _handleFile(file, stats, initialAdd) {\n if (this.fsw.closed) {\n return;\n }\n const dirname = sysPath.dirname(file);\n const basename = sysPath.basename(file);\n const parent = this.fsw._getWatchedDir(dirname);\n // stats is always present\n let prevStats = stats;\n // if the file is already being watched, do nothing\n if (parent.has(basename))\n return;\n const listener = async (path, newStats) => {\n if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))\n return;\n if (!newStats || newStats.mtimeMs === 0) {\n try {\n const newStats = await stat(file);\n if (this.fsw.closed)\n return;\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats.ino) {\n this.fsw._closeFile(path);\n prevStats = newStats;\n const closer = this._watchWithNodeFs(file, listener);\n if (closer)\n this.fsw._addPathCloser(path, closer);\n }\n else {\n prevStats = newStats;\n }\n }\n catch (error) {\n // Fix issues where mtime is null but file is still present\n this.fsw._remove(dirname, basename);\n }\n // add is about to be emitted if file not already tracked in parent\n }\n else if (parent.has(basename)) {\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n prevStats = newStats;\n }\n };\n // kick off the watcher\n const closer = this._watchWithNodeFs(file, listener);\n // emit an add event if we're supposed to\n if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {\n if (!this.fsw._throttle(EV.ADD, file, 0))\n return;\n this.fsw._emit(EV.ADD, file, stats);\n }\n return closer;\n }\n /**\n * Handle symlinks encountered while reading a dir.\n * @param entry returned by readdirp\n * @param directory path of dir being read\n * @param path of this item\n * @param item basename of this item\n * @returns true if no more processing is needed for this entry.\n */\n async _handleSymlink(entry, directory, path, item) {\n if (this.fsw.closed) {\n return;\n }\n const full = entry.fullPath;\n const dir = this.fsw._getWatchedDir(directory);\n if (!this.fsw.options.followSymlinks) {\n // watch symlink directly (don't follow) and detect changes\n this.fsw._incrReadyCount();\n let linkPath;\n try {\n linkPath = await fsrealpath(path);\n }\n catch (e) {\n this.fsw._emitReady();\n return true;\n }\n if (this.fsw.closed)\n return;\n if (dir.has(item)) {\n if (this.fsw._symlinkPaths.get(full) !== linkPath) {\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.CHANGE, path, entry.stats);\n }\n }\n else {\n dir.add(item);\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.ADD, path, entry.stats);\n }\n this.fsw._emitReady();\n return true;\n }\n // don't follow the same symlink more than once\n if (this.fsw._symlinkPaths.has(full)) {\n return true;\n }\n this.fsw._symlinkPaths.set(full, true);\n }\n _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {\n // Normalize the directory name on Windows\n directory = sysPath.join(directory, '');\n throttler = this.fsw._throttle('readdir', directory, 1000);\n if (!throttler)\n return;\n const previous = this.fsw._getWatchedDir(wh.path);\n const current = new Set();\n let stream = this.fsw._readdirp(directory, {\n fileFilter: (entry) => wh.filterPath(entry),\n directoryFilter: (entry) => wh.filterDir(entry),\n });\n if (!stream)\n return;\n stream\n .on(STR_DATA, async (entry) => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const item = entry.path;\n let path = sysPath.join(directory, item);\n current.add(item);\n if (entry.stats.isSymbolicLink() &&\n (await this._handleSymlink(entry, directory, path, item))) {\n return;\n }\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n // Files that present in current directory snapshot\n // but absent in previous are added to watch list and\n // emit `add` event.\n if (item === target || (!target && !previous.has(item))) {\n this.fsw._incrReadyCount();\n // ensure relativeness of path is preserved in case of watcher reuse\n path = sysPath.join(dir, sysPath.relative(dir, path));\n this._addToNodeFs(path, initialAdd, wh, depth + 1);\n }\n })\n .on(EV.ERROR, this._boundHandleError);\n return new Promise((resolve, reject) => {\n if (!stream)\n return reject();\n stream.once(STR_END, () => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const wasThrottled = throttler ? throttler.clear() : false;\n resolve(undefined);\n // Files that absent in current directory snapshot\n // but present in previous emit `remove` event\n // and are removed from @watched[directory].\n previous\n .getChildren()\n .filter((item) => {\n return item !== directory && !current.has(item);\n })\n .forEach((item) => {\n this.fsw._remove(directory, item);\n });\n stream = undefined;\n // one more time for any missed in case changes came in extremely quickly\n if (wasThrottled)\n this._handleRead(directory, false, wh, target, dir, depth, throttler);\n });\n });\n }\n /**\n * Read directory to add / remove files from `@watched` list and re-read it on change.\n * @param dir fs path\n * @param stats\n * @param initialAdd\n * @param depth relative to user-supplied path\n * @param target child path targeted for watch\n * @param wh Common watch helpers for this path\n * @param realpath\n * @returns closer for the watcher instance.\n */\n async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {\n const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));\n const tracked = parentDir.has(sysPath.basename(dir));\n if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {\n this.fsw._emit(EV.ADD_DIR, dir, stats);\n }\n // ensure dir is tracked (harmless if redundant)\n parentDir.add(sysPath.basename(dir));\n this.fsw._getWatchedDir(dir);\n let throttler;\n let closer;\n const oDepth = this.fsw.options.depth;\n if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {\n if (!target) {\n await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);\n if (this.fsw.closed)\n return;\n }\n closer = this._watchWithNodeFs(dir, (dirPath, stats) => {\n // if current directory is removed, do nothing\n if (stats && stats.mtimeMs === 0)\n return;\n this._handleRead(dirPath, false, wh, target, dir, depth, throttler);\n });\n }\n return closer;\n }\n /**\n * Handle added file, directory, or glob pattern.\n * Delegates call to _handleFile / _handleDir after checks.\n * @param path to file or ir\n * @param initialAdd was the file added at watch instantiation?\n * @param priorWh depth relative to user-supplied path\n * @param depth Child path actually targeted for watch\n * @param target Child path actually targeted for watch\n */\n async _addToNodeFs(path, initialAdd, priorWh, depth, target) {\n const ready = this.fsw._emitReady;\n if (this.fsw._isIgnored(path) || this.fsw.closed) {\n ready();\n return false;\n }\n const wh = this.fsw._getWatchHelpers(path);\n if (priorWh) {\n wh.filterPath = (entry) => priorWh.filterPath(entry);\n wh.filterDir = (entry) => priorWh.filterDir(entry);\n }\n // evaluate what is at the path we're being asked to watch\n try {\n const stats = await statMethods[wh.statMethod](wh.watchPath);\n if (this.fsw.closed)\n return;\n if (this.fsw._isIgnored(wh.watchPath, stats)) {\n ready();\n return false;\n }\n const follow = this.fsw.options.followSymlinks;\n let closer;\n if (stats.isDirectory()) {\n const absPath = sysPath.resolve(path);\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (absPath !== targetPath && targetPath !== undefined) {\n this.fsw._symlinkPaths.set(absPath, targetPath);\n }\n }\n else if (stats.isSymbolicLink()) {\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n const parent = sysPath.dirname(wh.watchPath);\n this.fsw._getWatchedDir(parent).add(wh.watchPath);\n this.fsw._emit(EV.ADD, wh.watchPath, stats);\n closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (targetPath !== undefined) {\n this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);\n }\n }\n else {\n closer = this._handleFile(wh.watchPath, stats, initialAdd);\n }\n ready();\n if (closer)\n this.fsw._addPathCloser(path, closer);\n return false;\n }\n catch (error) {\n if (this.fsw._handleError(error)) {\n ready();\n return path;\n }\n }\n }\n}\n","import type { Application, Request, Response } from \"express\";\r\nimport chokidar from \"chokidar\";\r\nimport path from \"path\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\n\r\nexport interface HotReloadOptions {\r\n app: Application;\r\n appDir: string; // carpeta de la app (ej: apps/example/app)\r\n route?: string; // endpoint SSE, default: \"/__fw/hot\"\r\n waitForBuild?: () => Promise<void>; // Function to wait for client bundle to finish building\r\n onFileChange?: (filePath: string) => void | Promise<void>; // Callback when file changes\r\n}\r\n\r\n/**\r\n * Sets up an SSE endpoint and file watcher on appDir.\r\n * Each change triggers a reload to connected clients.\r\n *\r\n * @param options - Hot reload options\r\n */\r\nexport function setupHotReload({\r\n app,\r\n appDir,\r\n route = \"/__fw/hot\",\r\n waitForBuild,\r\n onFileChange,\r\n}: HotReloadOptions) {\r\n const clients = new Set<Response>();\r\n\r\n app.get(route, (req: Request, res: Response) => {\r\n res.setHeader(\"Content-Type\", \"text/event-stream\");\r\n res.setHeader(\"Cache-Control\", \"no-cache\");\r\n res.setHeader(\"Connection\", \"keep-alive\");\r\n res.flushHeaders?.();\r\n\r\n res.write(`event: ping\\ndata: connected\\n\\n`);\r\n clients.add(res);\r\n\r\n req.on(\"close\", () => {\r\n clients.delete(res);\r\n });\r\n });\r\n\r\n const watcher = chokidar.watch(appDir, {\r\n ignoreInitial: true,\r\n ignored: [\"**/node_modules/**\", `**/${BUILD_FOLDER_NAME}/**`, \"**/.git/**\"],\r\n });\r\n\r\n async function broadcastReload(reason: string, filePath: string) {\r\n const rel = path.relative(appDir, filePath);\r\n console.log(`[hot-reload] ${reason}: ${rel}`);\r\n\r\n // Call onFileChange callback if provided (e.g., to reload routes manifest)\r\n if (onFileChange) {\r\n try {\r\n await onFileChange(filePath);\r\n } catch (error) {\r\n console.warn(\"[hot-reload] Error in onFileChange callback:\", error);\r\n }\r\n }\r\n\r\n // Wait for client bundle to finish building before sending reload event\r\n if (waitForBuild) {\r\n try {\r\n console.log(\"[hot-reload] Waiting for client bundle to finish...\");\r\n await waitForBuild();\r\n console.log(\"[hot-reload] Client bundle ready, sending reload event\");\r\n } catch (error) {\r\n console.warn(\"[hot-reload] Error waiting for build:\", error);\r\n // Continue anyway, don't block reload\r\n }\r\n }\r\n\r\n for (const res of clients) {\r\n res.write(`event: message\\ndata: reload:${rel}\\n\\n`);\r\n }\r\n }\r\n\r\n watcher\r\n .on(\"add\", (filePath) => broadcastReload(\"add\", filePath))\r\n .on(\"change\", (filePath) => broadcastReload(\"change\", filePath))\r\n .on(\"unlink\", (filePath) => broadcastReload(\"unlink\", filePath));\r\n}\r\n","import path from \"path\";\r\n\r\n/**\r\n * Clears the require cache for files in the app directory.\r\n *\r\n * @param appDir - App directory path\r\n */\r\nexport function clearAppRequireCache(appDir: string) {\r\n const appDirNormalized = path.resolve(appDir);\r\n\r\n for (const id of Object.keys(require.cache)) {\r\n if (id.startsWith(appDirNormalized)) {\r\n delete require.cache[id];\r\n }\r\n }\r\n}\r\n","/**\r\n * Security utilities for input sanitization.\r\n */\r\n\r\n/**\r\n * Sanitizes a string by removing potentially dangerous characters.\r\n * Basic sanitization - for production, consider using a library like DOMPurify.\r\n * \r\n * @param input - String to sanitize\r\n * @returns Sanitized string\r\n */\r\nexport function sanitizeString(input: string): string {\r\n if (typeof input !== \"string\") {\r\n return String(input);\r\n }\r\n\r\n // Remove null bytes\r\n let sanitized = input.replace(/\\0/g, \"\");\r\n\r\n // Remove control characters except newlines and tabs\r\n sanitized = sanitized.replace(/[\\x00-\\x08\\x0B-\\x0C\\x0E-\\x1F\\x7F]/g, \"\");\r\n\r\n return sanitized;\r\n}\r\n\r\n/**\r\n * Sanitizes an object by recursively sanitizing all string values.\r\n * \r\n * @param obj - Object to sanitize\r\n * @returns Sanitized object\r\n */\r\nexport function sanitizeObject<T extends Record<string, any>>(obj: T): T {\r\n if (obj === null || obj === undefined) {\r\n return obj;\r\n }\r\n\r\n if (typeof obj !== \"object\") {\r\n return typeof obj === \"string\" ? (sanitizeString(obj) as any) : obj;\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map((item) => sanitizeObject(item)) as any;\r\n }\r\n\r\n const sanitized: any = {};\r\n for (const key in obj) {\r\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\r\n const value = obj[key];\r\n if (typeof value === \"string\") {\r\n sanitized[key] = sanitizeString(value);\r\n } else if (typeof value === \"object\" && value !== null) {\r\n sanitized[key] = sanitizeObject(value);\r\n } else {\r\n sanitized[key] = value;\r\n }\r\n }\r\n }\r\n\r\n return sanitized;\r\n}\r\n\r\n/**\r\n * Sanitizes route parameters.\r\n * \r\n * @param params - Route parameters object\r\n * @returns Sanitized parameters\r\n */\r\nexport function sanitizeParams<T extends Record<string, string | string[]>>(\r\n params: T\r\n): T {\r\n const sanitized: any = {};\r\n for (const key in params) {\r\n if (Object.prototype.hasOwnProperty.call(params, key)) {\r\n const value = params[key];\r\n if (Array.isArray(value)) {\r\n sanitized[key] = value.map((v) => sanitizeString(String(v)));\r\n } else {\r\n sanitized[key] = sanitizeString(String(value));\r\n }\r\n }\r\n }\r\n return sanitized;\r\n}\r\n\r\n/**\r\n * Sanitizes query parameters.\r\n * \r\n * @param query - Query parameters object\r\n * @returns Sanitized query parameters\r\n */\r\nexport function sanitizeQuery<T extends Record<string, any>>(query: T): T {\r\n return sanitizeObject(query);\r\n}\r\n\r\n","import rateLimit from \"express-rate-limit\";\r\n\r\nexport interface RateLimitConfig {\r\n windowMs?: number;\r\n max?: number;\r\n message?: string;\r\n standardHeaders?: boolean;\r\n legacyHeaders?: boolean;\r\n skipSuccessfulRequests?: boolean;\r\n skipFailedRequests?: boolean;\r\n}\r\n\r\n/**\r\n * Creates a rate limiter middleware with configurable options.\r\n * \r\n * @param config - Rate limiting configuration\r\n * @returns Express rate limit middleware\r\n */\r\nexport function createRateLimiter(config: RateLimitConfig = {}) {\r\n const {\r\n windowMs = 15 * 60 * 1000, // 15 minutes\r\n max = 100, // limit each IP to 100 requests per windowMs\r\n message = \"Too many requests from this IP, please try again later.\",\r\n standardHeaders = true,\r\n legacyHeaders = false,\r\n skipSuccessfulRequests = false,\r\n skipFailedRequests = false,\r\n } = config;\r\n\r\n return rateLimit({\r\n windowMs,\r\n max,\r\n message: {\r\n error: message,\r\n },\r\n standardHeaders,\r\n legacyHeaders,\r\n skipSuccessfulRequests,\r\n skipFailedRequests,\r\n });\r\n}\r\n\r\n/**\r\n * Default rate limiter for general API routes.\r\n * Limits: 100 requests per 15 minutes per IP\r\n */\r\nexport const defaultRateLimiter = createRateLimiter({\r\n windowMs: 15 * 60 * 1000, // 15 minutes\r\n max: 100,\r\n message: \"Too many requests from this IP, please try again later.\",\r\n});\r\n\r\n/**\r\n * Strict rate limiter for authentication and sensitive endpoints.\r\n * Limits: 5 requests per 15 minutes per IP\r\n */\r\nexport const strictRateLimiter = createRateLimiter({\r\n windowMs: 15 * 60 * 1000, // 15 minutes\r\n max: 5,\r\n message: \"Too many authentication attempts, please try again later.\",\r\n});\r\n\r\n/**\r\n * Lenient rate limiter for public pages.\r\n * Limits: 200 requests per 15 minutes per IP\r\n */\r\nexport const lenientRateLimiter = createRateLimiter({\r\n windowMs: 15 * 60 * 1000, // 15 minutes\r\n max: 200,\r\n message: \"Too many requests from this IP, please try again later.\",\r\n});\r\n\r\n","import { ApiRoute } from \"@router/index.types\";\nimport { strictRateLimiter, defaultRateLimiter, lenientRateLimiter } from \"./rate-limit\";\n\n/**\n * Determines if a route path matches any of the strict patterns.\n * \n * @param path - Route path to check\n * @param patterns - Array of patterns to match against\n * @returns True if path matches any pattern\n */\nexport function matchesStrictPattern(\n path: string,\n patterns: string[]\n): boolean {\n for (const pattern of patterns) {\n // Convert pattern to regex\n // ** matches any path segment\n // * matches single path segment\n const regexPattern = pattern\n .replace(/\\*\\*/g, \".*\") // ** -> .*\n .replace(/\\*/g, \"[^/]*\") // * -> [^/]*\n .replace(/\\//g, \"\\\\/\"); // / -> \\/\n\n const regex = new RegExp(`^${regexPattern}$`);\n if (regex.test(path)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Checks if a middleware is a rate limiter.\n * \n * @param mw - Middleware to check\n * @returns True if middleware is a rate limiter\n */\nfunction isRateLimiter(mw: any): boolean {\n if (!mw) return false;\n \n // Check if it's one of our known rate limiters\n if (mw === strictRateLimiter || mw === defaultRateLimiter || mw === lenientRateLimiter) {\n return true;\n }\n \n // Check for express-rate-limit signature\n // Rate limiters from express-rate-limit have specific properties\n if (typeof mw === 'function' && mw.name && mw.name.includes('rateLimit')) {\n return true;\n }\n \n // Check if middleware function has rate limit properties\n if (mw && typeof mw === 'function' && (mw as any).skip || (mw as any).resetKey) {\n return true;\n }\n \n return false;\n}\n\n/**\n * Gets the appropriate rate limiter for a route based on configuration.\n * \n * @param route - API route\n * @param strictPatterns - Patterns that should use strict rate limiting\n * @returns Rate limiter middleware or null if route already has rate limiting\n */\nexport function getAutoRateLimiter(\n route: ApiRoute,\n strictPatterns: string[] = []\n): any | null {\n // If route already has rate limiting middleware, don't add another\n const hasRateLimiter = route.middlewares?.some(isRateLimiter) ||\n Object.values(route.methodMiddlewares || {}).some((mws: any[]) => \n mws?.some(isRateLimiter)\n );\n\n if (hasRateLimiter) {\n return null; // Route already has rate limiting\n }\n\n // Check if route matches strict patterns\n if (strictPatterns.length > 0 && matchesStrictPattern(route.pattern, strictPatterns)) {\n console.log(`[rate-limit] Applying strict rate limiter to route: ${route.pattern}`);\n return strictRateLimiter;\n }\n\n // Default: no auto rate limiting (global rate limiter already applied)\n return null;\n}\n\n","import pino from \"pino\";\r\nimport type { Logger as PinoLogger } from \"pino\";\r\nimport type { Request, Response } from \"express\";\r\n\r\nexport type LogLevel = \"fatal\" | \"error\" | \"warn\" | \"info\" | \"debug\" | \"trace\";\r\n\r\nexport interface LoggerContext {\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface LoggerOptions {\r\n level?: LogLevel;\r\n enabled?: boolean;\r\n pretty?: boolean;\r\n destination?: pino.DestinationStream;\r\n}\r\n\r\n/**\r\n * Creates a Pino logger instance with appropriate configuration for dev/prod.\r\n * \r\n * - Development: Pretty printed with colors via pino-pretty\r\n * - Production: JSON structured output for log aggregation\r\n */\r\nfunction createLogger(options: LoggerOptions = {}): PinoLogger {\r\n const {\r\n level = (process.env.LOG_LEVEL as LogLevel) || (process.env.NODE_ENV === \"development\" ? \"debug\" : \"info\"),\r\n enabled = process.env.LOG_ENABLED !== \"false\",\r\n pretty = process.env.NODE_ENV === \"development\",\r\n destination,\r\n } = options;\r\n\r\n if (!enabled) {\r\n // Return a no-op logger\r\n return pino({ enabled: false });\r\n }\r\n\r\n const baseConfig: pino.LoggerOptions = {\r\n level,\r\n base: {\r\n name: \"@lolyjs/core\",\r\n env: process.env.NODE_ENV || \"development\",\r\n },\r\n timestamp: pino.stdTimeFunctions.isoTime,\r\n formatters: {\r\n level: (label) => {\r\n return { level: label };\r\n },\r\n },\r\n };\r\n\r\n // In development, use pino-pretty for colored, human-readable output\r\n if (pretty && !destination) {\r\n try {\r\n // Dynamic import to avoid bundling pino-pretty in production\r\n const pinoPretty = require(\"pino-pretty\");\r\n return pino(\r\n baseConfig,\r\n pinoPretty({\r\n colorize: true,\r\n translateTime: \"HH:MM:ss Z\",\r\n ignore: \"pid,hostname\",\r\n singleLine: false,\r\n messageFormat: \"[{module}] {msg}\",\r\n })\r\n );\r\n } catch (e) {\r\n // Fallback if pino-pretty is not available\r\n console.warn(\"[logger] pino-pretty not available, using default formatter\");\r\n }\r\n }\r\n\r\n // Production: structured JSON logging\r\n return destination ? pino(baseConfig, destination) : pino(baseConfig);\r\n}\r\n\r\n// Singleton logger instance\r\nlet loggerInstance: PinoLogger | null = null;\r\n\r\n/**\r\n * Gets or creates the singleton logger instance.\r\n */\r\nexport function getLogger(options?: LoggerOptions): PinoLogger {\r\n if (!loggerInstance) {\r\n loggerInstance = createLogger(options);\r\n }\r\n return loggerInstance;\r\n}\r\n\r\n/**\r\n * Sets a custom logger instance (useful for testing or custom configuration).\r\n */\r\nexport function setLogger(customLogger: PinoLogger): void {\r\n loggerInstance = customLogger;\r\n}\r\n\r\n/**\r\n * Resets the logger instance (useful for testing).\r\n */\r\nexport function resetLogger(): void {\r\n loggerInstance = null;\r\n}\r\n\r\n/**\r\n * Logger class wrapper for easier usage with context.\r\n */\r\nexport class Logger {\r\n private pino: PinoLogger;\r\n private context: LoggerContext;\r\n\r\n constructor(logger?: PinoLogger, context: LoggerContext = {}) {\r\n this.pino = logger || getLogger();\r\n this.context = context;\r\n }\r\n\r\n /**\r\n * Creates a child logger with additional context.\r\n */\r\n child(context: LoggerContext): Logger {\r\n return new Logger(this.pino.child(context), { ...this.context, ...context });\r\n }\r\n\r\n /**\r\n * Logs a fatal error (application should terminate).\r\n */\r\n fatal(message: string, context?: LoggerContext): void {\r\n this.pino.fatal({ ...this.context, ...context }, message);\r\n }\r\n\r\n /**\r\n * Logs an error.\r\n */\r\n error(message: string, error?: Error | unknown, context?: LoggerContext): void {\r\n const errorContext: LoggerContext = { ...this.context, ...context };\r\n \r\n if (error instanceof Error) {\r\n errorContext.error = {\r\n name: error.name,\r\n message: error.message,\r\n stack: error.stack,\r\n };\r\n } else if (error) {\r\n errorContext.error = error;\r\n }\r\n\r\n this.pino.error(errorContext, message);\r\n }\r\n\r\n /**\r\n * Logs a warning.\r\n */\r\n warn(message: string, context?: LoggerContext): void {\r\n this.pino.warn({ ...this.context, ...context }, message);\r\n }\r\n\r\n /**\r\n * Logs informational message.\r\n */\r\n info(message: string, context?: LoggerContext): void {\r\n this.pino.info({ ...this.context, ...context }, message);\r\n }\r\n\r\n /**\r\n * Logs a debug message (only in development or when level is debug).\r\n */\r\n debug(message: string, context?: LoggerContext): void {\r\n this.pino.debug({ ...this.context, ...context }, message);\r\n }\r\n\r\n /**\r\n * Logs a trace message (most verbose).\r\n */\r\n trace(message: string, context?: LoggerContext): void {\r\n this.pino.trace({ ...this.context, ...context }, message);\r\n }\r\n}\r\n\r\n/**\r\n * Default logger instance.\r\n */\r\nexport const logger = new Logger();\r\n\r\n/**\r\n * Creates a logger for a specific module/component.\r\n */\r\nexport function createModuleLogger(module: string, context?: LoggerContext): Logger {\r\n return logger.child({ module, ...context });\r\n}\r\n\r\n/**\r\n * Generates a unique request ID for request tracking.\r\n */\r\nexport function generateRequestId(): string {\r\n return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\r\n}\r\n\r\n/**\r\n * Default paths to ignore from request logging (static assets, favicon, etc.)\r\n */\r\nconst DEFAULT_IGNORED_PATHS = [\r\n /^\\/static\\//, // Static assets\r\n /^\\/favicon\\.ico$/i, // Favicon\r\n /^\\/_next\\//, // Next.js internals (if used)\r\n /^\\/\\.well-known\\//, // Well-known paths\r\n /^\\/__webpack/, // Webpack dev server\r\n /^\\/sockjs-node/, // Hot reload websocket\r\n];\r\n\r\n/**\r\n * Checks if a path should be ignored from logging.\r\n */\r\nfunction shouldIgnorePath(path: string, ignoredPaths: (string | RegExp)[]): boolean {\r\n return ignoredPaths.some(pattern => {\r\n if (typeof pattern === \"string\") {\r\n return path === pattern || path.startsWith(pattern);\r\n }\r\n return pattern.test(path);\r\n });\r\n}\r\n\r\n/**\r\n * Express middleware for request logging.\r\n * Adds request ID to res.locals and logs incoming requests.\r\n */\r\nexport function requestLoggerMiddleware(options: {\r\n logger?: Logger;\r\n logRequests?: boolean;\r\n logResponses?: boolean;\r\n ignorePaths?: (string | RegExp)[];\r\n logStaticAssets?: boolean;\r\n} = {}) {\r\n const {\r\n logger: customLogger = logger,\r\n logRequests = true,\r\n logResponses = true,\r\n ignorePaths = DEFAULT_IGNORED_PATHS,\r\n logStaticAssets = false,\r\n } = options;\r\n\r\n return (req: Request, res: Response, next: () => void): void => {\r\n // Generate or use existing request ID\r\n const requestId = (req.headers[\"x-request-id\"] as string) || generateRequestId();\r\n (res.locals as any).requestId = requestId;\r\n\r\n // Add request ID to response headers\r\n res.setHeader(\"X-Request-ID\", requestId);\r\n\r\n // Check if we should ignore this path\r\n const shouldIgnore = !logStaticAssets && shouldIgnorePath(req.path, ignorePaths);\r\n\r\n // Create request-scoped logger (always available for handlers, minimal context to avoid duplication)\r\n const reqLogger = customLogger.child({\r\n requestId,\r\n method: req.method,\r\n path: req.path,\r\n });\r\n\r\n // Store logger in request for use in handlers (always available)\r\n (req as any).logger = reqLogger;\r\n\r\n // Log incoming request (only if not ignored and enabled)\r\n if (logRequests && !shouldIgnore) {\r\n reqLogger.debug(`${req.method} ${req.path}`, {\r\n query: Object.keys(req.query).length > 0 ? req.query : undefined,\r\n });\r\n }\r\n\r\n // Log response when finished (only if not ignored)\r\n if (logResponses && !shouldIgnore) {\r\n const startTime = Date.now();\r\n \r\n res.on(\"finish\", () => {\r\n const duration = Date.now() - startTime;\r\n // Only log errors and warnings by default, or successful requests if explicitly enabled\r\n const shouldLogSuccess = logRequests === true; // Only if logRequests is explicitly true\r\n \r\n if (res.statusCode >= 500) {\r\n reqLogger.error(`${req.method} ${req.path} ${res.statusCode}`, {\r\n statusCode: res.statusCode,\r\n duration: `${duration}ms`,\r\n });\r\n } else if (res.statusCode >= 400) {\r\n reqLogger.warn(`${req.method} ${req.path} ${res.statusCode}`, {\r\n statusCode: res.statusCode,\r\n duration: `${duration}ms`,\r\n });\r\n } else if (shouldLogSuccess) {\r\n // Only log successful requests if explicitly enabled\r\n reqLogger.debug(`${req.method} ${req.path} ${res.statusCode}`, {\r\n statusCode: res.statusCode,\r\n duration: `${duration}ms`,\r\n });\r\n }\r\n });\r\n }\r\n\r\n next();\r\n };\r\n}\r\n\r\n/**\r\n * Gets the logger from the request object (set by requestLoggerMiddleware).\r\n */\r\nexport function getRequestLogger(req: Request): Logger {\r\n return (req as any).logger || logger.child({ requestId: \"unknown\" });\r\n}\r\n\r\n","import { Request, Response } from \"express\";\r\nimport { ApiContext, ApiRoute, matchApiRoute } from \"@router/index\";\r\nimport { sanitizeParams, sanitizeQuery } from \"@security/sanitize\";\r\nimport { getAutoRateLimiter } from \"@server/middleware/auto-rate-limit\";\r\nimport { getRequestLogger, createModuleLogger } from \"@logger/index\";\r\n\r\nexport interface HandleApiRequestOptions {\r\n apiRoutes: ApiRoute[];\r\n urlPath: string;\r\n req: Request;\r\n res: Response;\r\n env?: \"dev\" | \"prod\";\r\n strictRateLimitPatterns?: string[];\r\n}\r\n\r\n/**\r\n * Handles an API route request.\r\n * Unifies logic between dev and prod.\r\n *\r\n * @param options - Request handling options\r\n */\r\nexport async function handleApiRequest(\r\n options: HandleApiRequestOptions\r\n): Promise<void> {\r\n const { apiRoutes, urlPath, req, res, env = \"dev\" } = options;\r\n\r\n const matched = matchApiRoute(apiRoutes, urlPath);\r\n\r\n if (!matched) {\r\n res.status(404).json({ error: \"Not Found\" });\r\n return;\r\n }\r\n\r\n const { route, params } = matched;\r\n const method = req.method.toUpperCase();\r\n const handler = route.handlers[method];\r\n\r\n if (!handler) {\r\n res.setHeader(\"Allow\", Object.keys(route.handlers).join(\", \"));\r\n res.status(405).json({ error: \"Method Not Allowed\" });\r\n return;\r\n }\r\n\r\n // Security: Sanitize route parameters and query parameters\r\n const sanitizedParams = sanitizeParams(params);\r\n const sanitizedQuery = sanitizeQuery(req.query as Record<string, any>);\r\n\r\n const ctx: ApiContext = {\r\n req,\r\n res,\r\n Response: (body: any = {}, status = 200) => res.status(status).json(body),\r\n NotFound: (body: any = {}) => res.status(404).json(body),\r\n params: sanitizedParams,\r\n pathname: urlPath,\r\n locals: {},\r\n };\r\n\r\n // Update req.query with sanitized values\r\n req.query = sanitizedQuery as any;\r\n\r\n try {\r\n // Auto-apply rate limiting if route matches strict patterns and doesn't already have one\r\n const autoRateLimiter = getAutoRateLimiter(\r\n route,\r\n options.strictRateLimitPatterns\r\n );\r\n \r\n const reqLogger = getRequestLogger(req);\r\n \r\n if (autoRateLimiter) {\r\n reqLogger.debug(\"Auto rate limiter applied\", {\r\n route: route.pattern,\r\n patterns: options.strictRateLimitPatterns,\r\n });\r\n }\r\n\r\n const globalMws = route.middlewares ?? [];\r\n const perMethodMws = route.methodMiddlewares?.[method] ?? [];\r\n \r\n // Prepend auto rate limiter if applicable\r\n const chain = autoRateLimiter \r\n ? [autoRateLimiter, ...globalMws, ...perMethodMws]\r\n : [...globalMws, ...perMethodMws];\r\n\r\n for (const mw of chain) {\r\n // Check if this is an express-rate-limit middleware (expects req, res, next)\r\n // express-rate-limit middlewares have specific properties\r\n const isExpressRateLimit = mw && typeof mw === 'function' && \r\n ((mw as any).skip || (mw as any).resetKey || mw.name?.includes('rateLimit'));\r\n \r\n if (isExpressRateLimit) {\r\n // Call express-rate-limit middleware with (req, res, next)\r\n await new Promise<void>((resolve, reject) => {\r\n const next = (err?: any) => {\r\n if (err) reject(err);\r\n else resolve();\r\n };\r\n try {\r\n const result = mw(req, res, next);\r\n // If it returns a promise, wait for it\r\n if (result && typeof result.then === 'function') {\r\n result.then(() => resolve()).catch(reject);\r\n }\r\n } catch (err) {\r\n reject(err);\r\n }\r\n });\r\n } else {\r\n // Call framework middleware with (ctx, next)\r\n await Promise.resolve(mw(ctx, async () => {}));\r\n }\r\n \r\n if (res.headersSent) {\r\n return;\r\n }\r\n }\r\n\r\n await handler(ctx);\r\n } catch (err) {\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"API handler error\", err, {\r\n route: route.pattern,\r\n method,\r\n env,\r\n });\r\n if (!res.headersSent) {\r\n res.status(500).json({ error: \"Internal Server Error\" });\r\n }\r\n }\r\n}\r\n","import { Request, Response } from \"express\";\r\nimport { renderToPipeableStream } from \"react-dom/server\";\r\nimport {\r\n ServerContext,\r\n LoadedRoute,\r\n LoaderResult,\r\n matchRoute,\r\n} from \"@router/index\";\r\nimport {\r\n buildAppTree,\r\n buildInitialData,\r\n createDocumentTree,\r\n buildRouterData,\r\n} from \"@rendering/index\";\r\nimport { runRouteMiddlewares } from \"./middleware\";\r\nimport { runRouteLoader } from \"./loader\";\r\nimport { handleDataResponse, handleRedirect, handleNotFound } from \"./response\";\r\nimport { tryServeSsgHtml, tryServeSsgData } from \"./ssg\";\r\nimport { ERROR_CHUNK_KEY, STATIC_PATH } from \"@constants/globals\";\r\nimport { getClientJsPath, getClientCssPath, loadAssetManifest } from \"@build/utils\";\r\nimport { sanitizeParams } from \"@security/sanitize\";\r\nimport { getRequestLogger } from \"@logger/index\";\r\n\r\nexport interface HandlePageRequestOptions {\r\n routes: LoadedRoute[];\r\n notFoundPage: LoadedRoute | null;\r\n errorPage: LoadedRoute | null;\r\n routeChunks: Record<string, string>;\r\n urlPath: string;\r\n req: Request;\r\n res: Response;\r\n env?: \"dev\" | \"prod\";\r\n ssgOutDir?: string;\r\n theme?: string;\r\n projectRoot?: string;\r\n}\r\n\r\n/**\r\n * Determines if a request is a data request (JSON).\r\n *\r\n * @param req - Express request object\r\n * @returns True if the request is a data request\r\n */\r\nexport function isDataRequest(req: Request): boolean {\r\n return (\r\n (req.query && (req.query as any).__fw_data === \"1\") ||\r\n req.headers[\"x-fw-data\"] === \"1\"\r\n );\r\n}\r\n\r\n/**\r\n * Handles a page route request.\r\n * Unifies logic between dev and prod (with SSG support in prod).\r\n *\r\n * @param options - Request handling options\r\n */\r\nexport async function handlePageRequest(\r\n options: HandlePageRequestOptions\r\n): Promise<void> {\r\n try {\r\n await handlePageRequestInternal(options);\r\n } catch (error) {\r\n const { errorPage, req, res, routeChunks, theme, projectRoot } = options;\r\n const reqLogger = getRequestLogger(req);\r\n \r\n if (errorPage) {\r\n await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env);\r\n } else {\r\n reqLogger.error(\"Unhandled error in page request\", error, {\r\n urlPath: options.urlPath,\r\n hasErrorPage: !!errorPage,\r\n });\r\n if (!res.headersSent) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n res.end(\"<!doctype html><h1>Internal Server Error</h1>\");\r\n }\r\n }\r\n }\r\n}\r\n\r\nasync function handlePageRequestInternal(\r\n options: HandlePageRequestOptions\r\n): Promise<void> {\r\n const {\r\n routes,\r\n notFoundPage,\r\n errorPage,\r\n routeChunks,\r\n urlPath,\r\n req,\r\n res,\r\n env = \"dev\",\r\n ssgOutDir,\r\n theme,\r\n projectRoot,\r\n } = options;\r\n\r\n // Get asset paths - in dev, always use non-hashed names; in prod, use manifest if available\r\n const clientJsPath = env === \"dev\" \r\n ? \"/static/client.js\" \r\n : (projectRoot ? getClientJsPath(projectRoot) : \"/static/client.js\");\r\n const clientCssPath = env === \"dev\"\r\n ? \"/static/client.css\"\r\n : (projectRoot ? getClientCssPath(projectRoot) : \"/static/client.css\");\r\n const assetManifest = env === \"prod\" && projectRoot ? loadAssetManifest(projectRoot) : null;\r\n\r\n const isDataReq = isDataRequest(req);\r\n\r\n if (env === \"prod\" && ssgOutDir) {\r\n if (isDataReq) {\r\n if (tryServeSsgData(res, ssgOutDir, urlPath)) {\r\n return;\r\n }\r\n } else {\r\n if (tryServeSsgHtml(res, ssgOutDir, urlPath)) {\r\n return;\r\n }\r\n }\r\n }\r\n\r\n const matched = matchRoute(routes, urlPath);\r\n\r\n const routerData = buildRouterData(req);\r\n\r\n if (!matched) {\r\n if (notFoundPage) {\r\n const ctx: ServerContext & { theme?: string } = {\r\n req,\r\n res,\r\n params: {},\r\n pathname: urlPath,\r\n locals: {},\r\n };\r\n\r\n let loaderResult = await runRouteLoader(notFoundPage, ctx);\r\n // Automatically inject theme from server into loaderResult if not already set\r\n if (!loaderResult.theme) {\r\n loaderResult.theme = theme;\r\n }\r\n \r\n const initialData = buildInitialData(urlPath, {}, loaderResult);\r\n const appTree = buildAppTree(notFoundPage, {}, initialData.props);\r\n initialData.notFound = true;\r\n \r\n // Get nonce from res.locals (set by Helmet for CSP)\r\n const nonce = (res.locals as any).nonce || undefined;\r\n\r\n const documentTree = createDocumentTree({\r\n appTree,\r\n initialData,\r\n routerData,\r\n meta: loaderResult.metadata ?? null,\r\n titleFallback: \"Not found\",\r\n descriptionFallback: \"Loly demo\",\r\n chunkHref: null,\r\n theme,\r\n clientJsPath,\r\n clientCssPath,\r\n nonce,\r\n });\r\n \r\n let didError = false;\r\n \r\n const { pipe, abort } = renderToPipeableStream(documentTree, {\r\n onShellReady() {\r\n if (didError || res.headersSent) return;\r\n \r\n res.statusCode = 404;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n pipe(res);\r\n },\r\n onShellError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"SSR shell error\", err, { route: \"not-found\" });\r\n if (!res.headersSent && errorPage) {\r\n renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);\r\n } else if (!res.headersSent) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n res.end(\"<!doctype html><h1>Internal Server Error</h1>\");\r\n }\r\n abort();\r\n },\r\n onError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"SSR error\", err, { route: \"not-found\" });\r\n },\r\n });\r\n \r\n req.on(\"close\", () => abort());\r\n return;\r\n }\r\n\r\n handleNotFound(res, urlPath);\r\n return;\r\n }\r\n\r\n const { route, params } = matched;\r\n\r\n // Security: Sanitize route parameters\r\n const sanitizedParams = sanitizeParams(params);\r\n\r\n const ctx: ServerContext = {\r\n req,\r\n res,\r\n params: sanitizedParams,\r\n pathname: urlPath,\r\n locals: {},\r\n };\r\n\r\n await runRouteMiddlewares(route, ctx);\r\n if (res.headersSent) {\r\n return;\r\n }\r\n\r\n let loaderResult: LoaderResult;\r\n try {\r\n loaderResult = await runRouteLoader(route, ctx);\r\n // Automatically inject theme from server into loaderResult if not already set\r\n if (!loaderResult.theme) {\r\n loaderResult.theme = theme;\r\n }\r\n } catch (error) {\r\n // If loader throws, handle error appropriately\r\n if (isDataReq) {\r\n // For data requests, return error JSON\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\r\n res.end(JSON.stringify({ error: true, message: String(error) }));\r\n return;\r\n } else {\r\n // For HTML requests, render error page\r\n if (errorPage) {\r\n await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env);\r\n return;\r\n } else {\r\n throw error; // Re-throw to be caught by outer try-catch\r\n }\r\n }\r\n }\r\n\r\n if (isDataReq) {\r\n handleDataResponse(res, loaderResult, theme);\r\n return;\r\n }\r\n\r\n if (loaderResult.redirect) {\r\n handleRedirect(res, loaderResult.redirect);\r\n return;\r\n }\r\n\r\n if (loaderResult.notFound) {\r\n if (isDataReq) {\r\n res.status(200).json({ notFound: true });\r\n } else {\r\n handleNotFound(res, urlPath);\r\n }\r\n return;\r\n }\r\n\r\n const initialData = buildInitialData(urlPath, params, loaderResult);\r\n const appTree = buildAppTree(route, params, initialData.props);\r\n\r\n // Get chunk href with hash if available\r\n const chunkName = routeChunks[route.pattern];\r\n let chunkHref: string | null = null;\r\n if (chunkName != null) {\r\n if (assetManifest && assetManifest.chunks[chunkName]) {\r\n // Use hashed filename from manifest\r\n chunkHref = `${STATIC_PATH}/${assetManifest.chunks[chunkName]}`;\r\n } else {\r\n // Fallback to non-hashed filename\r\n chunkHref = `${STATIC_PATH}/${chunkName}.js`;\r\n }\r\n }\r\n\r\n // Get nonce from res.locals (set by Helmet for CSP)\r\n const nonce = (res.locals as any).nonce || undefined;\r\n\r\n const documentTree = createDocumentTree({\r\n appTree,\r\n initialData,\r\n routerData,\r\n meta: loaderResult.metadata,\r\n titleFallback: \"Loly framework\",\r\n descriptionFallback: \"Loly demo\",\r\n chunkHref,\r\n theme,\r\n clientJsPath,\r\n clientCssPath,\r\n nonce,\r\n });\r\n\r\n let didError = false;\r\n\r\n const { pipe, abort } = renderToPipeableStream(documentTree, {\r\n onShellReady() {\r\n if (didError || res.headersSent) {\r\n return;\r\n }\r\n\r\n res.statusCode = 200;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n pipe(res);\r\n },\r\n\r\n onShellError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"SSR shell error\", err, { route: matched?.route?.pattern || \"unknown\" });\r\n\r\n if (!res.headersSent && errorPage) {\r\n renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);\r\n } else if (!res.headersSent) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n res.end(\"<!doctype html><h1>Internal Server Error</h1>\");\r\n }\r\n\r\n abort();\r\n },\r\n\r\n onError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"SSR error\", err, { route: matched?.route?.pattern || \"unknown\" });\r\n },\r\n });\r\n\r\n req.on(\"close\", () => {\r\n abort();\r\n });\r\n}\r\n\r\n/**\r\n * Renders the error page when an error occurs using streaming.\r\n *\r\n * @param errorPage - Error page route\r\n * @param req - Express request\r\n * @param res - Express response\r\n * @param error - Error that occurred\r\n * @param routeChunks - Route chunks mapping\r\n */\r\nasync function renderErrorPageWithStream(\r\n errorPage: LoadedRoute,\r\n req: Request,\r\n res: Response,\r\n error: unknown,\r\n routeChunks: Record<string, string>,\r\n theme?: string,\r\n projectRoot?: string,\r\n env: \"dev\" | \"prod\" = \"dev\",\r\n): Promise<void> {\r\n try {\r\n const isDataReq = isDataRequest(req);\r\n \r\n const ctx: ServerContext = {\r\n req,\r\n res,\r\n params: { error: String(error) },\r\n pathname: req.path,\r\n locals: { error },\r\n };\r\n\r\n let loaderResult = await runRouteLoader(errorPage, ctx);\r\n // Automatically inject theme from server into loaderResult if not already set\r\n if (!loaderResult.theme && theme) {\r\n loaderResult.theme = theme;\r\n }\r\n\r\n const initialData = buildInitialData(req.path, { error: String(error) }, loaderResult);\r\n const routerData = buildRouterData(req);\r\n initialData.error = true;\r\n \r\n // If this is a data request, return JSON instead of HTML\r\n if (isDataReq) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\r\n res.end(JSON.stringify({\r\n error: true,\r\n message: String(error),\r\n props: initialData.props,\r\n metadata: loaderResult.metadata ?? null,\r\n theme: loaderResult.theme ?? theme ?? null,\r\n }));\r\n return;\r\n }\r\n const appTree = buildAppTree(errorPage, { error: String(error) }, initialData.props);\r\n\r\n // Get asset paths with hashes (if in production and manifest exists)\r\n // In dev, always use non-hashed names; in prod, use manifest if available\r\n const clientJsPath = env === \"dev\"\r\n ? \"/static/client.js\"\r\n : (projectRoot ? getClientJsPath(projectRoot) : \"/static/client.js\");\r\n const clientCssPath = env === \"dev\"\r\n ? \"/static/client.css\"\r\n : (projectRoot ? getClientCssPath(projectRoot) : \"/static/client.css\");\r\n const assetManifest = env === \"prod\" && projectRoot ? loadAssetManifest(projectRoot) : null;\r\n\r\n const chunkName = routeChunks[ERROR_CHUNK_KEY];\r\n let chunkHref: string | null = null;\r\n if (chunkName != null) {\r\n if (assetManifest && assetManifest.chunks[chunkName]) {\r\n chunkHref = `${STATIC_PATH}/${assetManifest.chunks[chunkName]}`;\r\n } else {\r\n chunkHref = `${STATIC_PATH}/${chunkName}.js`;\r\n }\r\n }\r\n\r\n // Get nonce from res.locals (set by Helmet for CSP)\r\n const nonce = (res.locals as any).nonce || undefined;\r\n\r\n const documentTree = createDocumentTree({\r\n appTree,\r\n initialData,\r\n routerData,\r\n meta: loaderResult.metadata ?? null,\r\n titleFallback: \"Error\",\r\n descriptionFallback: \"An error occurred\",\r\n chunkHref,\r\n theme,\r\n clientJsPath,\r\n clientCssPath,\r\n nonce,\r\n });\r\n\r\n let didError = false;\r\n\r\n const { pipe, abort } = renderToPipeableStream(documentTree, {\r\n onShellReady() {\r\n if (didError || res.headersSent) {\r\n return;\r\n }\r\n\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n pipe(res);\r\n },\r\n onShellError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"Error rendering error page\", err, { type: \"shellError\" });\r\n if (!res.headersSent) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n res.end(\"<!doctype html><h1>Internal Server Error</h1>\");\r\n }\r\n abort();\r\n },\r\n onError(err) {\r\n didError = true;\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"Error in error page\", err);\r\n },\r\n });\r\n\r\n req.on(\"close\", () => {\r\n abort();\r\n });\r\n } catch (renderErr) {\r\n const reqLogger = getRequestLogger(req);\r\n reqLogger.error(\"Error rendering error page (catch)\", renderErr, { type: \"renderException\" });\r\n if (!res.headersSent) {\r\n res.statusCode = 500;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n res.end(\"<!doctype html><h1>Internal Server Error</h1>\");\r\n }\r\n }\r\n}\r\n\r\n","import { ServerContext, LoadedRoute } from \"@router/index\";\r\n\r\n/**\r\n * Executes route middlewares in chain.\r\n *\r\n * @param route - Route definition\r\n * @param ctx - Server context\r\n */\r\nexport async function runRouteMiddlewares(\r\n route: LoadedRoute,\r\n ctx: ServerContext\r\n): Promise<void> {\r\n for (const mw of route.middlewares) {\r\n await Promise.resolve(\r\n mw(ctx, async () => {\r\n /* no-op */\r\n })\r\n );\r\n if (ctx.res.headersSent) {\r\n return;\r\n }\r\n }\r\n}\r\n\r\n","import { ServerContext, LoadedRoute, LoaderResult } from \"@router/index\";\r\n\r\n/**\r\n * Executes the route loader if it exists.\r\n *\r\n * @param route - Route definition\r\n * @param ctx - Server context\r\n * @returns Loader result\r\n */\r\nexport async function runRouteLoader(\r\n route: LoadedRoute,\r\n ctx: ServerContext\r\n): Promise<LoaderResult> {\r\n if (!route.loader) {\r\n return { props: {} };\r\n }\r\n\r\n return await route.loader(ctx);\r\n}\r\n\r\n","import { Response } from \"express\";\r\nimport { LoaderResult } from \"@router/index\";\r\n\r\n/**\r\n * Handles data request responses (JSON).\r\n *\r\n * @param res - Express response object\r\n * @param loaderResult - Loader result\r\n * @param theme - Optional theme value to include in response\r\n */\r\nexport function handleDataResponse(\r\n res: Response,\r\n loaderResult: LoaderResult,\r\n theme?: string\r\n): void {\r\n res.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\r\n\r\n if (loaderResult.redirect) {\r\n res.statusCode = 200;\r\n res.end(JSON.stringify({ redirect: loaderResult.redirect }));\r\n return;\r\n }\r\n\r\n if (loaderResult.notFound) {\r\n res.statusCode = 404;\r\n res.end(JSON.stringify({ notFound: true }));\r\n return;\r\n }\r\n\r\n res.statusCode = 200;\r\n res.end(\r\n JSON.stringify({\r\n props: loaderResult.props ?? {},\r\n metadata: loaderResult.metadata ?? null,\r\n theme: loaderResult.theme ?? theme ?? null,\r\n })\r\n );\r\n}\r\n\r\n/**\r\n * Handles redirects for HTML responses.\r\n *\r\n * @param res - Express response object\r\n * @param redirect - Redirect configuration\r\n */\r\nexport function handleRedirect(\r\n res: Response,\r\n redirect: { destination: string; permanent?: boolean }\r\n): void {\r\n const { destination, permanent } = redirect;\r\n res.redirect(permanent ? 301 : 302, destination);\r\n}\r\n\r\n/**\r\n * Handles not found responses for HTML.\r\n *\r\n * @param res - Express response object\r\n * @param urlPath - Optional URL path for error message\r\n */\r\nexport function handleNotFound(res: Response, urlPath?: string): void {\r\n res.statusCode = 200;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n if (urlPath) {\r\n res.end(`<h1>404 - Not Found</h1><p>Route not found: ${urlPath}</p>`);\r\n } else {\r\n res.end(\"<h1>404 - Not Found</h1>\");\r\n }\r\n}\r\n\r\n","import fs from \"fs\";\r\nimport path from \"path\";\r\nimport { Response } from \"express\";\r\nimport { createModuleLogger } from \"@logger/index\";\r\n\r\nconst logger = createModuleLogger(\"ssg\");\r\n\r\n/**\r\n * Gets the SSG directory path for a route.\r\n *\r\n * @param baseDir - Base SSG output directory\r\n * @param urlPath - URL path\r\n * @returns Directory path for the route\r\n */\r\nexport function getSsgDirForPath(baseDir: string, urlPath: string): string {\r\n const clean = urlPath === \"/\" ? \"\" : urlPath.replace(/^\\/+/, \"\");\r\n return path.join(baseDir, clean);\r\n}\r\n\r\n/**\r\n * Gets the SSG HTML file path for a URL.\r\n *\r\n * @param baseDir - Base SSG output directory\r\n * @param urlPath - URL path\r\n * @returns HTML file path\r\n */\r\nexport function getSsgHtmlPath(baseDir: string, urlPath: string): string {\r\n const dir = getSsgDirForPath(baseDir, urlPath);\r\n return path.join(dir, \"index.html\");\r\n}\r\n\r\n/**\r\n * Gets the SSG data.json file path for a URL.\r\n *\r\n * @param baseDir - Base SSG output directory\r\n * @param urlPath - URL path\r\n * @returns Data JSON file path\r\n */\r\nexport function getSsgDataPath(baseDir: string, urlPath: string): string {\r\n const dir = getSsgDirForPath(baseDir, urlPath);\r\n return path.join(dir, \"data.json\");\r\n}\r\n\r\n/**\r\n * Attempts to serve SSG HTML if it exists.\r\n *\r\n * @param res - Express response object\r\n * @param ssgOutDir - SSG output directory\r\n * @param urlPath - URL path\r\n * @returns True if served, false if not found\r\n */\r\nexport function tryServeSsgHtml(\r\n res: Response,\r\n ssgOutDir: string,\r\n urlPath: string\r\n): boolean {\r\n const ssgHtmlPath = getSsgHtmlPath(ssgOutDir, urlPath);\r\n\r\n if (!fs.existsSync(ssgHtmlPath)) {\r\n return false;\r\n }\r\n\r\n logger.info(\"Serving SSG HTML\", { urlPath, ssgHtmlPath });\r\n\r\n // For SSG files, we need to allow 'unsafe-inline' since we can't generate nonces\r\n // for static HTML files. Override the CSP header set by Helmet.\r\n // Note: setHeader will override any existing header with the same name\r\n res.setHeader(\r\n \"Content-Security-Policy\",\r\n \"default-src 'self'; \" +\r\n \"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; \" +\r\n \"script-src 'self' 'unsafe-inline'; \" +\r\n \"img-src 'self' data: https:; \" +\r\n \"connect-src 'self' https:; \" +\r\n \"font-src 'self' data: https://fonts.gstatic.com; \" +\r\n \"object-src 'none'; \" +\r\n \"media-src 'self' https:; \" +\r\n \"frame-src 'none';\"\r\n );\r\n\r\n res.statusCode = 200;\r\n res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\");\r\n const stream = fs.createReadStream(ssgHtmlPath, { encoding: \"utf-8\" });\r\n stream.pipe(res);\r\n return true;\r\n}\r\n\r\n/**\r\n * Attempts to serve SSG data.json if it exists.\r\n *\r\n * @param res - Express response object\r\n * @param ssgOutDir - SSG output directory\r\n * @param urlPath - URL path\r\n * @returns True if served, false if not found\r\n */\r\nexport function tryServeSsgData(\r\n res: Response,\r\n ssgOutDir: string,\r\n urlPath: string\r\n): boolean {\r\n const ssgDataPath = getSsgDataPath(ssgOutDir, urlPath);\r\n\r\n if (!fs.existsSync(ssgDataPath)) {\r\n return false;\r\n }\r\n\r\n try {\r\n const raw = fs.readFileSync(ssgDataPath, \"utf-8\");\r\n res.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\r\n res.status(200).end(raw);\r\n return true;\r\n } catch (err) {\r\n logger.error(\"Error reading SSG data\", err, { urlPath, ssgDataPath });\r\n return false;\r\n }\r\n}\r\n\r\n","import express from \"express\";\r\nimport { LoadedRoute, ApiRoute, WssRoute } from \"@router/index.types\";\r\nimport { handleApiRequest, handlePageRequest } from \"./handlers\";\r\nimport { RouteLoader } from \"@router/index\";\r\nimport { BUILD_FOLDER_NAME } from \"@constants/globals\";\r\nimport { getBuildDir, type FrameworkConfig } from \"@src/config\";\r\nimport { getServerConfig } from \"@server/config\";\r\nimport path from \"path\";\r\n\r\nexport interface SetupRoutesOptions {\r\n app: express.Application;\r\n routes: LoadedRoute[];\r\n apiRoutes: ApiRoute[];\r\n notFoundPage: LoadedRoute | null;\r\n errorPage: LoadedRoute | null;\r\n isDev: boolean;\r\n projectRoot: string;\r\n routeLoader: RouteLoader;\r\n getRoutes?: () => {\r\n routes: LoadedRoute[];\r\n apiRoutes: ApiRoute[];\r\n };\r\n config?: FrameworkConfig;\r\n}\r\n\r\n/**\r\n * Sets up route handlers for the Express application.\r\n * Unifies logic between dev and prod environments.\r\n *\r\n * @param options - Route setup options\r\n */\r\nexport function setupRoutes(options: SetupRoutesOptions): void {\r\n const {\r\n app,\r\n routes: initialRoutes,\r\n apiRoutes: initialApiRoutes,\r\n notFoundPage,\r\n errorPage,\r\n isDev,\r\n projectRoot,\r\n routeLoader,\r\n getRoutes,\r\n config,\r\n } = options;\r\n\r\n // Cache route chunks - they don't change during runtime\r\n const routeChunks = routeLoader.loadRouteChunks();\r\n\r\n // SSG directory - available in both dev and prod if files exist\r\n const ssgOutDir = path.join(\r\n config ? getBuildDir(projectRoot, config) : path.join(projectRoot, BUILD_FOLDER_NAME),\r\n \"ssg\"\r\n );\r\n\r\n app.all(\"/api/*\", async (req, res) => {\r\n const apiRoutes = isDev && getRoutes\r\n ? getRoutes().apiRoutes\r\n : initialApiRoutes;\r\n\r\n // Get rate limit configuration for auto-application\r\n const serverConfig = await getServerConfig(projectRoot);\r\n const strictPatterns = serverConfig.rateLimit?.strictPatterns || [];\r\n\r\n await handleApiRequest({\r\n apiRoutes,\r\n urlPath: req.path,\r\n req,\r\n res,\r\n env: isDev ? \"dev\" : \"prod\",\r\n strictRateLimitPatterns: strictPatterns,\r\n });\r\n });\r\n\r\n app.get(\"*\", async (req, res) => {\r\n let routes = initialRoutes;\r\n let currentNotFoundPage = notFoundPage;\r\n\r\n if (isDev && getRoutes) {\r\n routes = getRoutes().routes;\r\n // In dev, reload not-found on each request to support hot-reload\r\n currentNotFoundPage = routeLoader.loadNotFoundRoute();\r\n }\r\n\r\n const currentErrorPage = isDev && getRoutes\r\n ? routeLoader.loadErrorRoute()\r\n : errorPage;\r\n\r\n await handlePageRequest({\r\n routes,\r\n notFoundPage: currentNotFoundPage,\r\n errorPage: currentErrorPage,\r\n routeChunks,\r\n urlPath: req.path,\r\n req,\r\n res,\r\n env: isDev ? \"dev\" : \"prod\",\r\n ssgOutDir,\r\n theme: req.cookies?.theme || \"light\",\r\n projectRoot,\r\n });\r\n });\r\n}\r\n\r\n","import { Server as HttpServer } from \"http\";\r\nimport { Server, Socket } from \"socket.io\";\r\nimport { WssRoute, WssContext } from \"@router/index.types\";\r\n\r\nexport interface SetupWssEventsOptions {\r\n httpServer: HttpServer;\r\n wssRoutes: WssRoute[];\r\n}\r\n\r\n/**\r\n * Generates helper actions for WebSocket context.\r\n * \r\n * Wraps Socket.IO methods in arrow functions to preserve the correct context\r\n * when used later in event handlers.\r\n * \r\n * @param socket - The Socket.IO socket instance\r\n * @param namespace - The Socket.IO namespace instance\r\n * @returns Actions object with helper methods for the namespace\r\n */\r\nconst generateActions = (socket: Socket, namespace: any): WssContext['actions'] => {\r\n return {\r\n // Emit to all clients in the namespace\r\n emit: (event: string, ...args: any[]) => {\r\n socket.nsp.emit(event, ...args);\r\n },\r\n \r\n // Emit to a specific socket by Socket.IO socket ID\r\n emitTo: (socketId: string, event: string, ...args: any[]) => {\r\n const targetSocket = namespace.sockets.get(socketId);\r\n if (targetSocket) {\r\n targetSocket.emit(event, ...args);\r\n }\r\n },\r\n \r\n // Emit to a specific client by custom clientId\r\n // Requires clientId to be stored in socket.data.clientId during connection\r\n emitToClient: (clientId: string, event: string, ...args: any[]) => {\r\n // Find socket by clientId stored in socket.data\r\n namespace.sockets.forEach((s: Socket) => {\r\n if (s.data?.clientId === clientId) {\r\n s.emit(event, ...args);\r\n }\r\n });\r\n },\r\n \r\n // Broadcast to all clients except the sender\r\n broadcast: (event: string, ...args: any[]) => {\r\n socket.broadcast.emit(event, ...args);\r\n },\r\n };\r\n};\r\n\r\n/**\r\n * Sets up Socket.IO server and registers WebSocket event handlers for each route.\r\n * \r\n * This function:\r\n * - Creates a Socket.IO server instance with the '/wss' path\r\n * - Extracts namespaces from route patterns (removes '/wss' prefix)\r\n * - Registers connection handlers for each namespace\r\n * - Maps event handlers from route definitions to Socket.IO events\r\n * \r\n * @param options - WebSocket setup options\r\n * \r\n * @example\r\n * ```ts\r\n * setupWssEvents({\r\n * httpServer,\r\n * wssRoutes: [{ pattern: '/wss/chat', handlers: { ... } }]\r\n * });\r\n * ```\r\n */\r\nexport function setupWssEvents(options: SetupWssEventsOptions): void {\r\n const { httpServer, wssRoutes } = options;\r\n\r\n if (wssRoutes.length === 0) {\r\n return;\r\n }\r\n\r\n const io = new Server(httpServer, {\r\n path: '/wss'\r\n });\r\n\r\n for (const wssRoute of wssRoutes) {\r\n // Extract namespace from route pattern by removing the '/wss' prefix\r\n // Example: Pattern '/wss/chat' -> Namespace '/chat'\r\n // Example: Pattern '/wss' -> Namespace '/'\r\n let namespacePath = wssRoute.pattern.replace(/^\\/wss/, '');\r\n \r\n // Ensure namespace always starts with '/'\r\n if (!namespacePath.startsWith('/')) {\r\n namespacePath = '/' + namespacePath;\r\n }\r\n \r\n // If empty after removal, use root namespace\r\n if (namespacePath === '') {\r\n namespacePath = '/';\r\n }\r\n \r\n const namespace = io.of(namespacePath);\r\n\r\n // Set up connection handler for this namespace\r\n namespace.on('connection', (socket: Socket) => {\r\n // Register all event handlers defined in the route\r\n Object.entries(wssRoute.handlers).forEach(([event, handler]) => {\r\n if (event.toLowerCase() === 'connection') {\r\n // Connection handler is executed immediately upon connection\r\n const ctx: WssContext = {\r\n socket,\r\n io: namespace.server,\r\n params: {},\r\n pathname: wssRoute.pattern,\r\n actions: generateActions(socket, namespace),\r\n };\r\n handler(ctx as any);\r\n } else {\r\n // For other events, register them on the socket instance\r\n socket.on(event, (data) => {\r\n const ctx: WssContext = {\r\n socket,\r\n io: namespace.server,\r\n actions: generateActions(socket, namespace),\r\n params: {},\r\n pathname: wssRoute.pattern,\r\n data,\r\n };\r\n handler(ctx as any);\r\n });\r\n }\r\n });\r\n });\r\n }\r\n}\r\n","import http from \"http\";\r\nimport express from \"express\";\r\nimport cors from \"cors\";\r\nimport helmet from \"helmet\";\r\nimport cookieParser from \"cookie-parser\";\r\nimport compression from \"compression\";\r\nimport crypto from \"crypto\";\r\nimport { getServerConfig } from \"@server/config\";\r\nimport { createRateLimiter } from \"@server/middleware/rate-limit\";\r\nimport { requestLoggerMiddleware, createModuleLogger } from \"@logger/index\";\r\n\r\ninterface SetupAppOptions {\r\n projectRoot: string;\r\n}\r\n\r\nexport const setupApplication = async ({\r\n projectRoot,\r\n}: SetupAppOptions): Promise<{\r\n app: express.Express;\r\n httpServer: http.Server<\r\n typeof http.IncomingMessage,\r\n typeof http.ServerResponse\r\n >;\r\n}> => {\r\n const app = express();\r\n\r\n const serverConfig = await getServerConfig(projectRoot);\r\n\r\n const { bodyLimit, corsOrigin, rateLimit, security } = serverConfig;\r\n\r\n // Security: Helmet with configurable CSP\r\n const helmetConfig: any = {};\r\n \r\n if (security?.contentSecurityPolicy !== false) {\r\n // In development, allow unsafe-inline and unsafe-eval for hot reload\r\n if (process.env.NODE_ENV === \"development\") {\r\n helmetConfig.contentSecurityPolicy = {\r\n directives: {\r\n defaultSrc: [\"'self'\"],\r\n styleSrc: [\"'self'\", \"'unsafe-inline'\", \"https://fonts.googleapis.com\"],\r\n scriptSrc: [\"'self'\", \"'unsafe-inline'\", \"'unsafe-eval'\"],\r\n imgSrc: [\"'self'\", \"data:\", \"https:\"],\r\n // Allow fetch/XHR to any HTTPS endpoint - users can restrict in their config if needed\r\n connectSrc: [\"'self'\", \"ws:\", \"wss:\", \"https:\"],\r\n fontSrc: [\"'self'\", \"data:\", \"https://fonts.gstatic.com\"],\r\n },\r\n };\r\n } else {\r\n // Use function-based CSP to enable nonce support in production\r\n const userCSP = security?.contentSecurityPolicy;\r\n const nonceFunction = (req: express.Request, res: express.Response) => {\r\n // Nonce is generated by middleware and stored in res.locals.nonce\r\n // This allows inline scripts with the nonce attribute\r\n const nonce = (res as any).locals?.nonce || \"\";\r\n return nonce ? `'nonce-${nonce}'` : \"'self'\";\r\n };\r\n \r\n const defaultCSP = {\r\n directives: {\r\n defaultSrc: [\"'self'\"],\r\n styleSrc: [\"'self'\", \"'unsafe-inline'\", \"https://fonts.googleapis.com\"],\r\n scriptSrc: [\"'self'\", nonceFunction],\r\n imgSrc: [\"'self'\", \"data:\", \"https:\"],\r\n // Allow fetch/XHR to any HTTPS endpoint - users can restrict in their config if needed\r\n connectSrc: [\"'self'\", \"https:\"],\r\n fontSrc: [\"'self'\", \"data:\", \"https://fonts.gstatic.com\"],\r\n objectSrc: [\"'none'\"],\r\n mediaSrc: [\"'self'\", \"https:\"],\r\n frameSrc: [\"'none'\"],\r\n },\r\n };\r\n\r\n if (userCSP && typeof userCSP === \"object\" && !Array.isArray(userCSP)) {\r\n // Merge user CSP with default, but ensure scriptSrc includes nonce support\r\n const userDirectives = userCSP.directives || {};\r\n const mergedDirectives: any = {\r\n ...defaultCSP.directives,\r\n ...userDirectives,\r\n };\r\n \r\n // Ensure scriptSrc includes nonce support even if user provided custom scriptSrc\r\n const userScriptSrc = userDirectives.scriptSrc;\r\n if (userScriptSrc && Array.isArray(userScriptSrc)) {\r\n // Check if nonce function is already included\r\n const hasNonceSupport = userScriptSrc.some((src) => \r\n typeof src === \"function\"\r\n );\r\n \r\n if (!hasNonceSupport) {\r\n // Add nonce function to user's scriptSrc\r\n mergedDirectives.scriptSrc = [\r\n ...userScriptSrc,\r\n nonceFunction,\r\n ];\r\n } else {\r\n mergedDirectives.scriptSrc = userScriptSrc;\r\n }\r\n }\r\n \r\n // Ensure connectSrc includes https: for flexibility - merge arrays instead of replacing\r\n const userConnectSrc = userDirectives.connectSrc;\r\n if (userConnectSrc && Array.isArray(userConnectSrc)) {\r\n // If user provided connectSrc, merge with defaults to ensure https: is included\r\n const defaultConnectSrc = defaultCSP.directives.connectSrc || [];\r\n const mergedConnectSrc = [...new Set([...defaultConnectSrc, ...userConnectSrc])];\r\n mergedDirectives.connectSrc = mergedConnectSrc;\r\n }\r\n \r\n // Ensure styleSrc includes Google Fonts\r\n const userStyleSrc = userDirectives.styleSrc;\r\n if (userStyleSrc && Array.isArray(userStyleSrc)) {\r\n const defaultStyleSrc = defaultCSP.directives.styleSrc || [];\r\n const mergedStyleSrc = [...new Set([...defaultStyleSrc, ...userStyleSrc])];\r\n mergedDirectives.styleSrc = mergedStyleSrc;\r\n }\r\n \r\n // Ensure fontSrc includes Google Fonts\r\n const userFontSrc = userDirectives.fontSrc;\r\n if (userFontSrc && Array.isArray(userFontSrc)) {\r\n const defaultFontSrc = defaultCSP.directives.fontSrc || [];\r\n const mergedFontSrc = [...new Set([...defaultFontSrc, ...userFontSrc])];\r\n mergedDirectives.fontSrc = mergedFontSrc;\r\n }\r\n \r\n helmetConfig.contentSecurityPolicy = {\r\n ...userCSP,\r\n directives: mergedDirectives,\r\n };\r\n } else {\r\n helmetConfig.contentSecurityPolicy = defaultCSP;\r\n }\r\n }\r\n } else {\r\n helmetConfig.contentSecurityPolicy = false;\r\n }\r\n\r\n // HSTS configuration\r\n if (security?.hsts !== false) {\r\n helmetConfig.hsts = security?.hsts === true \r\n ? { maxAge: 31536000, includeSubDomains: true }\r\n : security?.hsts;\r\n } else {\r\n helmetConfig.hsts = false;\r\n }\r\n\r\n // Generate nonce for CSP inline scripts (only in production)\r\n // In development, unsafe-inline is allowed\r\n // IMPORTANT: This must run BEFORE helmet so the nonce is available when CSP is evaluated\r\n if (process.env.NODE_ENV !== \"development\" && security?.contentSecurityPolicy !== false) {\r\n app.use((req: express.Request, res: express.Response, next: express.NextFunction) => {\r\n // Generate a unique nonce for this request\r\n const nonce = crypto.randomBytes(16).toString(\"base64\");\r\n (res.locals as any).nonce = nonce;\r\n next();\r\n });\r\n }\r\n\r\n app.use(helmet(helmetConfig));\r\n\r\n // Logging: Request logger middleware (adds request ID and logs requests/responses)\r\n // Must be early in the middleware chain to capture all requests\r\n // Filters out static assets and other noisy paths by default\r\n const appLogger = createModuleLogger(\"framework\");\r\n app.use(requestLoggerMiddleware({ \r\n logger: appLogger.child({ component: \"server\" }),\r\n logRequests: process.env.LOG_REQUESTS === \"true\", // Default to false (only errors/warnings)\r\n logResponses: process.env.LOG_RESPONSES !== \"false\", // Default to true (but filtered)\r\n logStaticAssets: process.env.LOG_STATIC_ASSETS === \"true\", // Default to false\r\n }));\r\n\r\n // Security: CORS with proper origin validation\r\n const corsOptions: cors.CorsOptions = {\r\n credentials: true,\r\n };\r\n\r\n if (typeof corsOrigin === \"function\") {\r\n corsOptions.origin = corsOrigin;\r\n } else if (Array.isArray(corsOrigin)) {\r\n corsOptions.origin = corsOrigin.length > 0 ? corsOrigin : false;\r\n } else if (corsOrigin === true) {\r\n // Allow all origins (development only)\r\n corsOptions.origin = true;\r\n } else if (typeof corsOrigin === \"string\") {\r\n corsOptions.origin = corsOrigin === \"*\" \r\n ? (process.env.NODE_ENV === \"development\" ? true : false)\r\n : [corsOrigin];\r\n } else {\r\n // Default: no CORS in production, allow all in development\r\n corsOptions.origin = process.env.NODE_ENV === \"development\";\r\n }\r\n\r\n app.use(cors(corsOptions));\r\n\r\n // Security: Rate limiting\r\n if (rateLimit) {\r\n const generalLimiter = createRateLimiter({\r\n windowMs: rateLimit.windowMs,\r\n max: rateLimit.max,\r\n });\r\n \r\n // Apply general rate limiting to all routes\r\n app.use(generalLimiter);\r\n }\r\n\r\n app.use(cookieParser());\r\n\r\n app.use(express.json({ limit: bodyLimit }));\r\n app.use(express.urlencoded({ extended: true, limit: bodyLimit }));\r\n\r\n app.use(compression());\r\n\r\n // Create http server\r\n const httpServer = http.createServer(app);\r\n\r\n return {\r\n app,\r\n httpServer,\r\n };\r\n};\r\n","import { hydrateRoot } from \"react-dom/client\";\r\nimport { APP_CONTAINER_ID } from \"./constants\";\r\nimport { getWindowData, getRouterData, setRouterData } from \"./window-data\";\r\nimport { matchRouteClient } from \"./route-matcher\";\r\nimport { applyMetadata } from \"./metadata\";\r\nimport { AppShell } from \"./AppShell\";\r\nimport type {\r\n InitialData,\r\n ClientRouteLoaded,\r\n RouteViewState,\r\n} from \"./types\";\r\n\r\nexport async function loadInitialRoute(\r\n initialUrl: string,\r\n initialData: InitialData | null,\r\n routes: ClientRouteLoaded[],\r\n notFoundRoute: ClientRouteLoaded | null,\r\n errorRoute: ClientRouteLoaded | null\r\n): Promise<RouteViewState> {\r\n const isInitialNotFound = initialData?.notFound === true;\r\n const isInitialError = initialData?.error === true;\r\n\r\n let initialRoute: ClientRouteLoaded | null = null;\r\n let initialParams: Record<string, string> = {};\r\n let initialComponents = null;\r\n\r\n if (isInitialError && errorRoute) {\r\n initialRoute = errorRoute;\r\n initialParams = initialData?.params ?? {};\r\n initialComponents = await errorRoute.load();\r\n } else if (isInitialNotFound && notFoundRoute) {\r\n initialRoute = notFoundRoute;\r\n initialParams = {};\r\n initialComponents = await notFoundRoute.load();\r\n } else {\r\n const match = matchRouteClient(initialUrl, routes);\r\n if (match) {\r\n initialRoute = match.route;\r\n initialParams = match.params;\r\n initialComponents = await match.route.load();\r\n } else if (notFoundRoute) {\r\n initialRoute = notFoundRoute;\r\n initialParams = {};\r\n initialComponents = await notFoundRoute.load();\r\n } else {\r\n console.warn(\r\n `[client] No route match found for ${initialUrl}. Available routes:`,\r\n routes.map((r) => r.pattern)\r\n );\r\n }\r\n }\r\n\r\n return {\r\n url: initialUrl,\r\n route: initialRoute,\r\n params: initialParams,\r\n components: initialComponents,\r\n props: initialData?.props ?? {},\r\n };\r\n}\r\n\r\n/**\r\n * Sets up hot reload via Server-Sent Events (SSE) in development mode.\r\n * Listens for file changes and reloads the page when needed.\r\n */\r\nfunction setupHotReload(): void {\r\n // Only enable hot reload in development mode\r\n // In production, process.env.NODE_ENV is replaced by DefinePlugin with \"production\"\r\n // @ts-ignore - process.env.NODE_ENV is replaced by DefinePlugin at build time\r\n const nodeEnv: string = (typeof process !== \"undefined\" && process?.env?.NODE_ENV) || \"production\";\r\n const isDev = nodeEnv !== \"production\";\r\n \r\n if (!isDev) {\r\n return; // Skip hot reload in production\r\n }\r\n\r\n try {\r\n console.log(\"[hot-reload] Attempting to connect to /__fw/hot...\");\r\n const eventSource = new EventSource(\"/__fw/hot\");\r\n let reloadTimeout: ReturnType<typeof setTimeout> | null = null;\r\n\r\n eventSource.addEventListener(\"message\", (event) => {\r\n const data = event.data;\r\n if (data && data.startsWith(\"reload:\")) {\r\n const filePath = data.slice(7);\r\n console.log(`[hot-reload] File changed: ${filePath}`);\r\n\r\n // Clear any pending reload\r\n if (reloadTimeout) {\r\n clearTimeout(reloadTimeout);\r\n }\r\n\r\n // Wait a bit for the bundler to finish compiling and files to be written\r\n // Increased timeout to ensure everything is ready\r\n reloadTimeout = setTimeout(() => {\r\n console.log(\"[hot-reload] Reloading page...\");\r\n // Force reload without cache to ensure we get the latest files\r\n window.location.reload();\r\n }, 500);\r\n }\r\n });\r\n\r\n eventSource.addEventListener(\"ping\", () => {\r\n console.log(\"[hot-reload] ✓ Connected to hot reload server\");\r\n });\r\n\r\n eventSource.onopen = () => {\r\n console.log(\"[hot-reload] ✓ SSE connection opened\");\r\n };\r\n\r\n eventSource.onerror = (error) => {\r\n // Log connection state for debugging\r\n const states = [\"CONNECTING\", \"OPEN\", \"CLOSED\"];\r\n const state = states[eventSource.readyState] || \"UNKNOWN\";\r\n \r\n if (eventSource.readyState === EventSource.CONNECTING) {\r\n // Still connecting, might be normal\r\n console.log(\"[hot-reload] Connecting...\");\r\n } else if (eventSource.readyState === EventSource.OPEN) {\r\n console.warn(\"[hot-reload] Connection error (but connection is open):\", error);\r\n } else {\r\n // Connection closed - might be production mode or server not running\r\n console.log(\"[hot-reload] Connection closed (readyState:\", state, \")\");\r\n }\r\n // EventSource automatically reconnects, so we don't need to do anything\r\n };\r\n } catch (error) {\r\n // Fail silently if EventSource is not supported\r\n console.log(\"[hot-reload] EventSource not supported or error:\", error);\r\n }\r\n}\r\n\r\n/**\r\n * Bootstraps the client-side application.\r\n *\r\n * @param routes - Array of client routes\r\n * @param notFoundRoute - Not-found route definition\r\n * @param errorRoute - Error route definition\r\n */\r\nexport function bootstrapClient(\r\n routes: ClientRouteLoaded[],\r\n notFoundRoute: ClientRouteLoaded | null,\r\n errorRoute: ClientRouteLoaded | null = null\r\n): void {\r\n // Set up hot reload in development mode\r\n console.log(\"[client] Bootstrap starting, setting up hot reload...\");\r\n setupHotReload();\r\n\r\n (async function bootstrap() {\r\n const container = document.getElementById(APP_CONTAINER_ID);\r\n const initialData = getWindowData();\r\n\r\n if (!container) {\r\n console.error(`Container #${APP_CONTAINER_ID} not found for hydration`);\r\n return;\r\n }\r\n\r\n const initialUrl = window.location.pathname + window.location.search;\r\n\r\n // Initialize routerData from server if available, otherwise build from URL\r\n let routerData = getRouterData();\r\n if (!routerData) {\r\n const url = new URL(initialUrl, window.location.origin);\r\n routerData = {\r\n pathname: url.pathname,\r\n params: initialData?.params || {},\r\n searchParams: Object.fromEntries(url.searchParams.entries()),\r\n };\r\n setRouterData(routerData);\r\n }\r\n\r\n try {\r\n const initialState = await loadInitialRoute(\r\n initialUrl,\r\n initialData,\r\n routes,\r\n notFoundRoute,\r\n errorRoute\r\n );\r\n\r\n if (initialData?.metadata) {\r\n applyMetadata(initialData.metadata);\r\n }\r\n\r\n hydrateRoot(\r\n container,\r\n <AppShell\r\n initialState={initialState}\r\n routes={routes}\r\n notFoundRoute={notFoundRoute}\r\n errorRoute={errorRoute}\r\n />\r\n );\r\n } catch (error) {\r\n console.error(\r\n \"[client] Error loading initial route components for\",\r\n initialUrl,\r\n error\r\n );\r\n\r\n window.location.reload();\r\n }\r\n })();\r\n}\r\n\r\n","import { useEffect, useState, useRef, useCallback } from \"react\";\r\nimport { RouterView } from \"./RouterView\";\r\nimport {\r\n navigate,\r\n createClickHandler,\r\n createPopStateHandler,\r\n type NavigationHandlers,\r\n} from \"./navigation\";\r\nimport { RouterContext } from \"./RouterContext\";\r\nimport { ROUTER_NAVIGATE_KEY } from \"./constants\";\r\nimport type {\r\n RouteViewState,\r\n ClientRouteLoaded,\r\n} from \"./types\";\r\n\r\nexport interface AppShellProps {\r\n initialState: RouteViewState;\r\n routes: ClientRouteLoaded[];\r\n notFoundRoute: ClientRouteLoaded | null;\r\n errorRoute: ClientRouteLoaded | null;\r\n}\r\n\r\nexport function AppShell({\r\n initialState,\r\n routes,\r\n notFoundRoute,\r\n errorRoute,\r\n}: AppShellProps) {\r\n const [state, setState] = useState<RouteViewState>(initialState);\r\n const handlersRef = useRef<NavigationHandlers>({\r\n setState,\r\n routes,\r\n notFoundRoute,\r\n errorRoute,\r\n });\r\n\r\n // Mantener handlersRef actualizado\r\n useEffect(() => {\r\n handlersRef.current = {\r\n setState,\r\n routes,\r\n notFoundRoute,\r\n errorRoute,\r\n };\r\n }, [routes, notFoundRoute, errorRoute]);\r\n\r\n // Create navigate function for router context\r\n const handleNavigate = useCallback(\r\n async (\r\n nextUrl: string,\r\n options?: { revalidate?: boolean; replace?: boolean }\r\n ) => {\r\n await navigate(nextUrl, handlersRef.current, {\r\n revalidate: options?.revalidate,\r\n });\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * SOLUTION: Expose navigate function globally as fallback\r\n * \r\n * During React hydration, components rendered in layouts may execute before\r\n * RouterContext is fully available. By exposing navigate globally, useRouter\r\n * can access it even when the context isn't ready yet, ensuring SPA navigation\r\n * works correctly from the first render.\r\n * \r\n * This is similar to how window.__FW_DATA__ is used for initial data.\r\n */\r\n useEffect(() => {\r\n if (typeof window !== \"undefined\") {\r\n (window as any)[ROUTER_NAVIGATE_KEY] = handleNavigate;\r\n return () => {\r\n delete (window as any)[ROUTER_NAVIGATE_KEY];\r\n };\r\n }\r\n }, [handleNavigate]);\r\n\r\n useEffect(() => {\r\n // Flag para evitar múltiples listeners (por si React Strict Mode ejecuta dos veces)\r\n let isMounted = true;\r\n\r\n async function handleNavigateInternal(\r\n nextUrl: string,\r\n options?: { revalidate?: boolean }\r\n ) {\r\n if (!isMounted) return;\r\n await navigate(nextUrl, handlersRef.current, options);\r\n }\r\n\r\n const handleClick = createClickHandler(handleNavigateInternal);\r\n const handlePopState = createPopStateHandler(handleNavigateInternal);\r\n\r\n // Usar capture: false (burbujeo) para que los eventos del input se manejen primero\r\n window.addEventListener(\"click\", handleClick, false);\r\n window.addEventListener(\"popstate\", handlePopState, false);\r\n\r\n return () => {\r\n isMounted = false;\r\n window.removeEventListener(\"click\", handleClick, false);\r\n window.removeEventListener(\"popstate\", handlePopState, false);\r\n };\r\n }, []); // Solo ejecutar una vez al montar\r\n\r\n const isError = state.route === errorRoute;\r\n const isNotFound = state.route === notFoundRoute;\r\n const routeType = isError ? \"error\" : isNotFound ? \"notfound\" : \"normal\";\r\n const routeKey = `${state.url}:${routeType}`;\r\n\r\n return (\r\n <RouterContext.Provider value={{ navigate: handleNavigate }}>\r\n <RouterView key={routeKey} state={state} />\r\n </RouterContext.Provider>\r\n );\r\n}\r\n\r\n","import type { RouteViewState } from \"./types\";\r\n\r\nexport function RouterView({ state }: { state: RouteViewState }) {\r\n if (!state.route) {\r\n // Don't show 404 if we're waiting for components to load\r\n if (state.components === null) {\r\n return null;\r\n }\r\n return <h1>404 - Route not found</h1>;\r\n }\r\n\r\n if (!state.components) {\r\n return null;\r\n }\r\n\r\n const { Page, layouts } = state.components;\r\n const { params, props } = state;\r\n\r\n let element = <Page params={params} {...props} />;\r\n\r\n const layoutChain = layouts.slice().reverse();\r\n for (const Layout of layoutChain) {\r\n element = (\r\n <Layout params={params} {...props}>\r\n {element}\r\n </Layout>\r\n );\r\n }\r\n\r\n return element;\r\n}\r\n\r\n","type RouteData = {\n ok: boolean;\n status: number;\n json: any;\n};\n\ntype CacheEntry =\n | { status: \"pending\"; promise: Promise<RouteData> }\n | { status: \"fulfilled\"; value: RouteData }\n | { status: \"rejected\"; error: any };\n\n// Use window to guarantee a single shared cache instance\n// across all bundles/modules\nconst CACHE_KEY = \"__FW_DATA_CACHE__\";\n\n// Maximum number of entries in the cache (LRU)\nconst MAX_CACHE_SIZE = 100;\n\ntype CacheStore = {\n data: Map<string, CacheEntry>;\n index: Map<string, Set<string>>; // pathBase -> Set of keys\n lru: string[]; // Ordered list: most recent at end, oldest at start\n};\n\nfunction getCacheStore(): CacheStore {\n if (typeof window !== \"undefined\") {\n if (!(window as any)[CACHE_KEY]) {\n (window as any)[CACHE_KEY] = {\n data: new Map<string, CacheEntry>(),\n index: new Map<string, Set<string>>(),\n lru: [],\n };\n }\n return (window as any)[CACHE_KEY];\n }\n // Fallback for SSR (though this shouldn't be used on the client)\n return {\n data: new Map<string, CacheEntry>(),\n index: new Map<string, Set<string>>(),\n lru: [],\n };\n}\n\nconst cacheStore = getCacheStore();\nconst dataCache = cacheStore.data;\nconst pathIndex = cacheStore.index;\nconst lru = cacheStore.lru;\n\n// Helper functions for cache management\n\n/**\n * Extract base path from a cache key (removes query params)\n */\nfunction extractPathBase(key: string): string {\n return key.split(\"?\")[0];\n}\n\n/**\n * Add key to path index\n */\nfunction addToIndex(key: string): void {\n const pathBase = extractPathBase(key);\n if (!pathIndex.has(pathBase)) {\n pathIndex.set(pathBase, new Set());\n }\n pathIndex.get(pathBase)!.add(key);\n}\n\n/**\n * Remove key from path index\n */\nfunction removeFromIndex(key: string): void {\n const pathBase = extractPathBase(key);\n const keys = pathIndex.get(pathBase);\n if (keys) {\n keys.delete(key);\n if (keys.size === 0) {\n pathIndex.delete(pathBase);\n }\n }\n}\n\n/**\n * Update LRU order - move key to end (most recent)\n */\nfunction updateLRU(key: string): void {\n const index = lru.indexOf(key);\n if (index !== -1) {\n lru.splice(index, 1);\n }\n lru.push(key);\n}\n\n/**\n * Remove oldest entries if cache exceeds MAX_CACHE_SIZE\n */\nfunction evictOldest(): void {\n while (lru.length >= MAX_CACHE_SIZE && lru.length > 0) {\n const oldestKey = lru.shift()!;\n dataCache.delete(oldestKey);\n removeFromIndex(oldestKey);\n }\n}\n\n/**\n * Set cache entry and maintain indexes\n */\nfunction setCacheEntry(key: string, entry: CacheEntry): void {\n const existingEntry = dataCache.get(key);\n const wasFulfilled = existingEntry?.status === \"fulfilled\";\n \n dataCache.set(key, entry);\n \n // Only track fulfilled entries in LRU and index (not pending/rejected)\n if (entry.status === \"fulfilled\") {\n // Add to index if it wasn't already fulfilled (new entry or transition from pending/rejected)\n if (!wasFulfilled) {\n addToIndex(key);\n }\n updateLRU(key);\n evictOldest();\n } else if (wasFulfilled) {\n // If entry was fulfilled and now isn't (transitioning to pending/rejected), remove from index\n removeFromIndex(key);\n }\n}\n\n/**\n * Delete cache entry and clean up indexes\n */\nfunction deleteCacheEntry(key: string): void {\n if (dataCache.has(key)) {\n dataCache.delete(key);\n removeFromIndex(key);\n const lruIndex = lru.indexOf(key);\n if (lruIndex !== -1) {\n lru.splice(lruIndex, 1);\n }\n }\n}\n\nfunction buildDataUrl(url: string): string {\n return url + (url.includes(\"?\") ? \"&\" : \"?\") + \"__fw_data=1\";\n}\n\nasync function fetchRouteDataOnce(url: string): Promise<RouteData> {\n const dataUrl = buildDataUrl(url);\n\n const res = await fetch(dataUrl, {\n headers: {\n \"x-fw-data\": \"1\",\n Accept: \"application/json\",\n },\n });\n\n let json: any = {};\n\n try {\n const text = await res.text();\n if (text) {\n json = JSON.parse(text);\n }\n } catch (parseError) {\n console.error(\n \"[client][cache] Failed to parse response as JSON:\",\n parseError\n );\n }\n\n const result: RouteData = {\n ok: res.ok,\n status: res.status,\n json,\n };\n\n return result;\n}\n\n/**\n * Revalidates route data by removing it from the cache.\n * The next time you navigate to this route, fresh data will be fetched from the server.\n * This is a client-side function and does not require a server-side revalidation.\n *\n * @param path - The route path to revalidate (e.g., '/posts/1' or '/posts/1?page=2')\n * If query params are not included, revalidates all variants of that route.\n *\n * @example\n * ```ts\n * // After saving something to the DB, revalidate the route\n * await saveToDatabase(data);\n * revalidatePath('/posts');\n * \n * // Revalidate a specific route with query params\n * revalidatePath('/posts?page=2');\n * ```\n */\nexport function revalidatePath(path: string): void {\n // Normalize the base path (without query params)\n const normalizedPath = path.split(\"?\")[0];\n const hasQueryParams = path.includes(\"?\");\n \n // Get all keys for this path base from index (O(1) lookup)\n const keysForPath = pathIndex.get(normalizedPath);\n \n if (!keysForPath || keysForPath.size === 0) {\n return; // No entries to revalidate\n }\n \n // If the path includes specific query params, extract them\n let specificQueryParams: string | undefined;\n if (hasQueryParams) {\n const queryPart = path.split(\"?\")[1];\n // Sort query params for consistent comparison\n specificQueryParams = queryPart\n .split(\"&\")\n .filter((p) => !p.startsWith(\"__fw_data=\"))\n .sort()\n .join(\"&\");\n }\n \n // Iterate only over keys for this path (much smaller set)\n const keysToDelete: string[] = [];\n for (const key of keysForPath) {\n // If specific query params were specified, check if they match\n if (hasQueryParams && specificQueryParams) {\n const [, keyQuery = \"\"] = key.split(\"?\");\n const keyQueryParams = keyQuery\n .split(\"&\")\n .filter((p) => !p.startsWith(\"__fw_data=\"))\n .sort()\n .join(\"&\");\n \n if (keyQueryParams === specificQueryParams) {\n keysToDelete.push(key);\n }\n } else {\n // If no specific query params, revalidate all variants\n keysToDelete.push(key);\n }\n }\n \n // Delete matching entries\n keysToDelete.forEach((key) => {\n deleteCacheEntry(key);\n });\n}\n\n/**\n * Revalidates and refreshes the current page data.\n * Similar to Next.js's `router.refresh()`.\n * \n * This function:\n * 1. Removes the current route from cache\n * 2. Fetches fresh data from the server\n * 3. Updates window.__FW_DATA__ with the new data\n * 4. Dispatches a 'fw-data-refresh' event for components to listen to\n * \n * @returns Promise that resolves with the fresh route data\n * \n * @example\n * ```ts\n * // Refresh current page data after a mutation\n * await revalidate();\n * ```\n */\nexport async function revalidate(): Promise<RouteData> {\n if (typeof window === \"undefined\") {\n throw new Error(\"revalidate() can only be called on the client\");\n }\n\n const pathname = window.location.pathname + window.location.search;\n \n // Revalidate the path (remove from cache)\n revalidatePath(pathname);\n \n // Fetch fresh data\n const freshData = await getRouteData(pathname, { revalidate: true });\n \n // Update window.__FW_DATA__ if it exists\n if ((window as any).__FW_DATA__ && freshData.ok && freshData.json) {\n const currentData = (window as any).__FW_DATA__;\n (window as any).__FW_DATA__ = {\n ...currentData,\n pathname: pathname.split(\"?\")[0],\n params: freshData.json.params || currentData.params || {},\n props: freshData.json.props || currentData.props || {},\n metadata: freshData.json.metadata ?? currentData.metadata ?? null,\n notFound: freshData.json.notFound ?? false,\n error: freshData.json.error ?? false,\n };\n \n // Dispatch event for components to listen to\n window.dispatchEvent(new CustomEvent(\"fw-data-refresh\", {\n detail: { data: freshData },\n }));\n }\n \n return freshData;\n}\n\n/**\n * @deprecated Use `revalidatePath()` instead. This function is kept for backwards compatibility.\n */\nexport function revalidateRouteData(url: string): void {\n revalidatePath(url);\n}\n\nexport function prefetchRouteData(url: string): void {\n const key = buildDataUrl(url);\n\n const cached = dataCache.get(key);\n\n if (cached && cached.status !== \"rejected\") {\n // Update LRU if it exists and is fulfilled\n if (cached.status === \"fulfilled\") {\n updateLRU(key);\n }\n return;\n }\n\n const promise = fetchRouteDataOnce(url)\n .then((value) => {\n setCacheEntry(key, { status: \"fulfilled\", value });\n return value;\n })\n .catch((error) => {\n console.error(\"[client][cache] Error prefetching route data:\", error);\n dataCache.set(key, { status: \"rejected\", error });\n throw error;\n });\n\n dataCache.set(key, { status: \"pending\", promise });\n}\n\nexport type GetRouteDataOptions = {\n /**\n * If true, forces revalidation of route data,\n * ignoring the cache and fetching fresh data from the server.\n * Similar to Next.js's `router.refresh()` behavior.\n */\n revalidate?: boolean;\n};\n\nexport async function getRouteData(\n url: string,\n options?: GetRouteDataOptions\n): Promise<RouteData> {\n const key = buildDataUrl(url);\n\n // If revalidation is requested, remove the entry from cache\n if (options?.revalidate) {\n deleteCacheEntry(key);\n }\n\n const entry = dataCache.get(key);\n\n if (entry) {\n if (entry.status === \"fulfilled\") {\n // Update LRU: mark as recently used\n updateLRU(key);\n return entry.value;\n }\n if (entry.status === \"pending\") {\n return entry.promise;\n }\n }\n\n // No entry in cache, fetch it\n const promise = fetchRouteDataOnce(url)\n .then((value) => {\n setCacheEntry(key, { status: \"fulfilled\", value });\n return value;\n })\n .catch((error) => {\n console.error(\"[client][cache] Error fetching route data:\", error);\n dataCache.set(key, { status: \"rejected\", error });\n throw error;\n });\n\n dataCache.set(key, { status: \"pending\", promise });\n return promise;\n}\n","import { createContext, useContext } from \"react\";\r\n\r\nexport type NavigateFunction = (\r\n url: string,\r\n options?: { revalidate?: boolean; replace?: boolean }\r\n) => Promise<void>;\r\n\r\nexport interface RouterContextValue {\r\n navigate: NavigateFunction;\r\n}\r\n\r\nexport const RouterContext = createContext<RouterContextValue | null>(null);\r\n\r\nexport function useRouterContext(): RouterContextValue {\r\n const context = useContext(RouterContext);\r\n if (!context) {\r\n throw new Error(\r\n \"useRouter must be used within a RouterProvider. Make sure you're using it inside a Loly app.\"\r\n );\r\n }\r\n return context;\r\n}\r\n","import { z, ZodSchema, ZodError } from \"zod\";\r\n\r\n/**\r\n * Validation error with detailed information.\r\n */\r\nexport class ValidationError extends Error {\r\n constructor(\r\n public errors: z.ZodIssue[],\r\n message = \"Validation failed\"\r\n ) {\r\n super(message);\r\n this.name = \"ValidationError\";\r\n }\r\n\r\n /**\r\n * Formats validation errors into a user-friendly format.\r\n */\r\n format(): Record<string, string[]> {\r\n const formatted: Record<string, string[]> = {};\r\n for (const error of this.errors) {\r\n const path = error.path.join(\".\");\r\n if (!formatted[path]) {\r\n formatted[path] = [];\r\n }\r\n formatted[path].push(error.message);\r\n }\r\n return formatted;\r\n }\r\n}\r\n\r\n/**\r\n * Validates data against a Zod schema.\r\n * \r\n * @param schema - Zod schema to validate against\r\n * @param data - Data to validate\r\n * @returns Validated data\r\n * @throws ValidationError if validation fails\r\n */\r\nexport function validate<T>(\r\n schema: ZodSchema<T>,\r\n data: unknown\r\n): T {\r\n try {\r\n return schema.parse(data);\r\n } catch (error) {\r\n if (error instanceof ZodError) {\r\n throw new ValidationError(error.errors);\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Safely validates data and returns a result object.\r\n * \r\n * @param schema - Zod schema to validate against\r\n * @param data - Data to validate\r\n * @returns Result object with success flag and data/error\r\n */\r\nexport function safeValidate<T>(\r\n schema: ZodSchema<T>,\r\n data: unknown\r\n): { success: true; data: T } | { success: false; error: ValidationError } {\r\n try {\r\n const validated = schema.parse(data);\r\n return { success: true, data: validated };\r\n } catch (error) {\r\n if (error instanceof ZodError) {\r\n return {\r\n success: false,\r\n error: new ValidationError(error.errors),\r\n };\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Common validation schemas for reuse.\r\n */\r\nexport const commonSchemas = {\r\n /**\r\n * Validates a string parameter (e.g., route params).\r\n */\r\n stringParam: z.string().min(1).max(255),\r\n\r\n /**\r\n * Validates an optional string parameter.\r\n */\r\n optionalStringParam: z.string().max(255).optional(),\r\n\r\n /**\r\n * Validates a numeric ID parameter.\r\n */\r\n idParam: z.string().regex(/^\\d+$/, \"ID must be numeric\").transform(Number),\r\n\r\n /**\r\n * Validates a UUID parameter.\r\n */\r\n uuidParam: z.string().uuid(\"Invalid UUID format\"),\r\n\r\n /**\r\n * Validates pagination parameters.\r\n */\r\n pagination: z.object({\r\n page: z.string().regex(/^\\d+$/).transform(Number).default(\"1\"),\r\n limit: z.string().regex(/^\\d+$/).transform(Number).default(\"10\"),\r\n }),\r\n\r\n /**\r\n * Validates a search query parameter.\r\n */\r\n searchQuery: z.string().min(1).max(100).optional(),\r\n};\r\n\r\n"],"mappings":"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","names":["import_path","import_fs","import_path","path","fs","import_fs","import_path","path","fs","fs","path","import_fs","import_path","import_fs","import_path","path","fs","path","fs","import_fs","import_path","path","fs","import_fs","import_path","path","fs","import_fs","import_path","import_fs","import_path","ROUTE_FILE_REGEX","path","fs","path","fs","import_core","import_path","import_fs","import_path","fs","path","BUILD_FOLDER_NAME","STATIC_PATH","path","dotenv","import_path","import_fs","resolve","path","fs","import_path","import_path","path","import_fs","import_path","React","path","fs","path","import_path","import_fs","import_fs","import_path","path","fs","fs","path","esbuild","import_path","import_fs","DEFAULT_CONFIG","path","fs","import_fs","import_path","import_path","import_fs","import_promises","sysPath","path","presolve","basename","pjoin","prelative","psep","import_fs","import_promises","osType","path","fs_watch","rawEmitter","listener","basename","dirname","newStats","closer","fsrealpath","resolve","realpath","stats","relative","path","DOUBLE_SLASH_RE","testString","stats","statcb","now","stat","import_path","path","import_path","path","getRoutes","path","express","rateLimit","path","pino","logger","module","path","resolve","import_server","import_fs","import_path","logger","path","fs","ctx","loaderResult","initialData","appTree","nonce","documentTree","didError","pipe","abort","import_path","path","import_express","express","rateLimit","crypto","helmet","cors","cookieParser","compression","http","import_dotenv","dotenv","logger","path","fs","import_client","import_react","import_react","import_jsx_runtime","import_jsx_runtime","process","path"]}
|