alepha 0.20.2 → 0.20.3

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.
Files changed (208) hide show
  1. package/README.md +0 -1
  2. package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
  3. package/assets/swagger-ui/swagger-ui.css +1 -1
  4. package/dist/api/audits/index.browser.js +49 -0
  5. package/dist/api/audits/index.browser.js.map +1 -1
  6. package/dist/api/audits/index.d.ts.map +1 -1
  7. package/dist/api/audits/index.js +49 -0
  8. package/dist/api/audits/index.js.map +1 -1
  9. package/dist/api/files/index.d.ts.map +1 -1
  10. package/dist/api/files/index.js.map +1 -1
  11. package/dist/api/jobs/index.d.ts +16 -75
  12. package/dist/api/jobs/index.d.ts.map +1 -1
  13. package/dist/api/jobs/index.js.map +1 -1
  14. package/dist/api/keys/index.js.map +1 -1
  15. package/dist/api/notifications/index.d.ts +1 -10
  16. package/dist/api/notifications/index.d.ts.map +1 -1
  17. package/dist/api/organizations/index.d.ts.map +1 -1
  18. package/dist/api/parameters/index.browser.js +37 -0
  19. package/dist/api/parameters/index.browser.js.map +1 -1
  20. package/dist/api/parameters/index.d.ts +4 -65
  21. package/dist/api/parameters/index.d.ts.map +1 -1
  22. package/dist/api/parameters/index.js +37 -0
  23. package/dist/api/parameters/index.js.map +1 -1
  24. package/dist/api/payments/index.d.ts.map +1 -1
  25. package/dist/api/payments/index.js.map +1 -1
  26. package/dist/api/users/index.d.ts +207 -5184
  27. package/dist/api/users/index.d.ts.map +1 -1
  28. package/dist/api/users/index.js +2 -4
  29. package/dist/api/users/index.js.map +1 -1
  30. package/dist/api/verifications/index.d.ts.map +1 -1
  31. package/dist/api/verifications/index.js +2 -1
  32. package/dist/api/verifications/index.js.map +1 -1
  33. package/dist/bucket/index.js +5 -1
  34. package/dist/bucket/index.js.map +1 -1
  35. package/dist/bucket/index.workerd.js +5 -1
  36. package/dist/bucket/index.workerd.js.map +1 -1
  37. package/dist/cache/core/index.js.map +1 -1
  38. package/dist/cache/core/index.workerd.js.map +1 -1
  39. package/dist/captcha/index.js.map +1 -1
  40. package/dist/cli/core/index.d.ts +217 -11647
  41. package/dist/cli/core/index.d.ts.map +1 -1
  42. package/dist/cli/core/index.js +706 -42
  43. package/dist/cli/core/index.js.map +1 -1
  44. package/dist/cli/devtools/index.js +7 -1
  45. package/dist/cli/devtools/index.js.map +1 -1
  46. package/dist/cli/platform/index.d.ts +41 -64
  47. package/dist/cli/platform/index.d.ts.map +1 -1
  48. package/dist/cli/platform/index.js +47 -0
  49. package/dist/cli/platform/index.js.map +1 -1
  50. package/dist/cli/vendor/index.js +15 -0
  51. package/dist/cli/vendor/index.js.map +1 -1
  52. package/dist/command/index.js +1 -1
  53. package/dist/command/index.js.map +1 -1
  54. package/dist/core/index.browser.js.map +1 -1
  55. package/dist/core/index.d.ts +2 -8
  56. package/dist/core/index.d.ts.map +1 -1
  57. package/dist/core/index.js.map +1 -1
  58. package/dist/core/index.native.js.map +1 -1
  59. package/dist/core/index.workerd.js.map +1 -1
  60. package/dist/crypto/index.js.map +1 -1
  61. package/dist/datetime/index.js.map +1 -1
  62. package/dist/email/core/index.js.map +1 -1
  63. package/dist/email/smtp/index.js +2 -10522
  64. package/dist/email/smtp/index.js.map +1 -1
  65. package/dist/fake/index.d.ts +4 -8085
  66. package/dist/fake/index.d.ts.map +1 -1
  67. package/dist/fake/index.js +3 -33554
  68. package/dist/fake/index.js.map +1 -1
  69. package/dist/lock/core/index.js.map +1 -1
  70. package/dist/lock/redis/index.js.map +1 -1
  71. package/dist/logger/index.js +32 -1
  72. package/dist/logger/index.js.map +1 -1
  73. package/dist/mcp/index.js +5 -1
  74. package/dist/mcp/index.js.map +1 -1
  75. package/dist/orm/core/index.browser.js +1 -361
  76. package/dist/orm/core/index.browser.js.map +1 -1
  77. package/dist/orm/core/index.bun.js +14 -406
  78. package/dist/orm/core/index.bun.js.map +1 -1
  79. package/dist/orm/core/index.d.ts +96 -5117
  80. package/dist/orm/core/index.d.ts.map +1 -1
  81. package/dist/orm/core/index.js +23 -419
  82. package/dist/orm/core/index.js.map +1 -1
  83. package/dist/orm/postgres/index.bun.js +17 -20
  84. package/dist/orm/postgres/index.bun.js.map +1 -1
  85. package/dist/orm/postgres/index.d.ts +2 -613
  86. package/dist/orm/postgres/index.d.ts.map +1 -1
  87. package/dist/orm/postgres/index.js +17 -20
  88. package/dist/orm/postgres/index.js.map +1 -1
  89. package/dist/react/core/index.js.map +1 -1
  90. package/dist/react/i18n/index.js.map +1 -1
  91. package/dist/react/intro/index.js +22 -17
  92. package/dist/react/intro/index.js.map +1 -1
  93. package/dist/react/router/index.browser.js +78 -2
  94. package/dist/react/router/index.browser.js.map +1 -1
  95. package/dist/react/router/index.d.ts +22 -1
  96. package/dist/react/router/index.d.ts.map +1 -1
  97. package/dist/react/router/index.js +102 -4
  98. package/dist/react/router/index.js.map +1 -1
  99. package/dist/react/testing/index.d.ts +1 -411
  100. package/dist/react/testing/index.d.ts.map +1 -1
  101. package/dist/react/testing/index.js +13 -12293
  102. package/dist/react/testing/index.js.map +1 -1
  103. package/dist/react/ui/index.js +3 -0
  104. package/dist/react/ui/index.js.map +1 -1
  105. package/dist/react/websocket/index.js.map +1 -1
  106. package/dist/redis/index.js.map +1 -1
  107. package/dist/scheduler/index.d.ts +1 -83
  108. package/dist/scheduler/index.d.ts.map +1 -1
  109. package/dist/scheduler/index.js +2 -391
  110. package/dist/scheduler/index.js.map +1 -1
  111. package/dist/scheduler/index.workerd.js +2 -391
  112. package/dist/scheduler/index.workerd.js.map +1 -1
  113. package/dist/security/index.browser.js.map +1 -1
  114. package/dist/security/index.d.ts +2 -325
  115. package/dist/security/index.d.ts.map +1 -1
  116. package/dist/security/index.js +3 -1362
  117. package/dist/security/index.js.map +1 -1
  118. package/dist/server/auth/index.d.ts +1 -1054
  119. package/dist/server/auth/index.d.ts.map +1 -1
  120. package/dist/server/auth/index.js +16 -1224
  121. package/dist/server/auth/index.js.map +1 -1
  122. package/dist/server/cookies/index.js.map +1 -1
  123. package/dist/server/core/index.browser.js.map +1 -1
  124. package/dist/server/core/index.d.ts +1 -4
  125. package/dist/server/core/index.d.ts.map +1 -1
  126. package/dist/server/core/index.js +19 -4
  127. package/dist/server/core/index.js.map +1 -1
  128. package/dist/server/links/index.browser.js.map +1 -1
  129. package/dist/server/links/index.js.map +1 -1
  130. package/dist/server/metrics/index.d.ts +1 -514
  131. package/dist/server/metrics/index.d.ts.map +1 -1
  132. package/dist/server/metrics/index.js +4 -4356
  133. package/dist/server/metrics/index.js.map +1 -1
  134. package/dist/server/rate-limit/index.js.map +1 -1
  135. package/dist/server/static/index.js.map +1 -1
  136. package/dist/server/swagger/index.js +1 -1
  137. package/dist/server/swagger/index.js.map +1 -1
  138. package/dist/sms/index.js.map +1 -1
  139. package/dist/system/index.browser.js.map +1 -1
  140. package/dist/system/index.js.map +1 -1
  141. package/dist/system/index.workerd.js.map +1 -1
  142. package/dist/topic/core/index.js.map +1 -1
  143. package/dist/websocket/index.browser.js +21 -0
  144. package/dist/websocket/index.browser.js.map +1 -1
  145. package/dist/websocket/index.js +21 -0
  146. package/dist/websocket/index.js.map +1 -1
  147. package/package.json +18 -15
  148. package/src/api/files/__tests__/FileController.spec.ts +1 -1
  149. package/src/api/jobs/__tests__/$job.spec.ts +5 -1
  150. package/src/api/users/schemas/userQuerySchema.ts +0 -1
  151. package/src/api/users/services/UserService.ts +1 -5
  152. package/src/api/verifications/__tests__/CodeVerification.spec.ts +14 -0
  153. package/src/api/verifications/__tests__/LinkVerification.spec.ts +14 -0
  154. package/src/api/verifications/services/VerificationService.ts +1 -0
  155. package/src/cli/core/__tests__/init.spec.ts +208 -0
  156. package/src/cli/core/commands/init.ts +12 -0
  157. package/src/cli/core/services/PackageManagerUtils.ts +23 -6
  158. package/src/cli/core/services/ProjectScaffolder.ts +298 -20
  159. package/src/cli/core/tasks/BuildDockerTask.ts +9 -10
  160. package/src/cli/core/tasks/BuildServerTask.ts +8 -0
  161. package/src/cli/core/templates/apiIndexTs.ts +23 -1
  162. package/src/cli/core/templates/componentsJsonTs.ts +39 -0
  163. package/src/cli/core/templates/mainCss.ts +1 -0
  164. package/src/cli/core/templates/saasAdminLayoutTsx.ts +77 -0
  165. package/src/cli/core/templates/saasAdminPagesTsx.ts +26 -0
  166. package/src/cli/core/templates/saasAuthLayoutTsx.ts +20 -0
  167. package/src/cli/core/templates/saasAuthPagesTsx.ts +62 -0
  168. package/src/cli/core/templates/saasRealmProviderTs.ts +46 -0
  169. package/src/cli/core/templates/webAppRouterTs.ts +104 -1
  170. package/src/cli/core/templates/webIndexTs.ts +23 -1
  171. package/src/cli/platform/__tests__/SecretsCommand.spec.ts +2 -0
  172. package/src/command/providers/CliProvider.ts +1 -1
  173. package/src/core/interfaces/Service.ts +3 -1
  174. package/src/core/providers/TypeProvider.ts +1 -1
  175. package/src/logger/services/Logger.ts +1 -1
  176. package/src/mcp/__tests__/$resource.spec.ts +1 -1
  177. package/src/mcp/__tests__/$tool.spec.ts +1 -1
  178. package/src/mcp/__tests__/McpServerProvider.spec.ts +1 -1
  179. package/src/orm/__tests__/$repository-tests.ts +1 -0
  180. package/src/orm/__tests__/orm-next-tests.ts +2 -67
  181. package/src/orm/__tests__/orm-next.spec.ts +0 -21
  182. package/src/orm/core/index.shared.ts +0 -2
  183. package/src/orm/core/index.ts +1 -2
  184. package/src/orm/core/primitives/$repository.ts +3 -6
  185. package/src/orm/core/providers/drivers/DatabaseProvider.ts +0 -5
  186. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +11 -13
  187. package/src/orm/core/services/ModelBuilder.ts +1 -13
  188. package/src/orm/core/services/Repository.ts +1 -42
  189. package/src/orm/core/services/SqliteModelBuilder.ts +2 -33
  190. package/src/orm/postgres/services/PostgresModelBuilder.ts +10 -45
  191. package/src/react/intro/components/GettingStartedAuthSlide.tsx +11 -4
  192. package/src/react/router/__tests__/ReactBrowserProvider.browser.spec.ts +213 -2
  193. package/src/react/router/providers/ReactBrowserProvider.ts +73 -0
  194. package/src/react/router/providers/ReactBrowserRouterProvider.ts +1 -1
  195. package/src/react/router/providers/ReactPreloadProvider.ts +1 -1
  196. package/src/react/router/providers/ReactServerProvider.ts +1 -0
  197. package/src/scheduler/providers/CronProvider.ts +1 -1
  198. package/src/security/primitives/$basicAuth.ts +1 -1
  199. package/src/server/auth/providers/ServerAuthProvider.ts +5 -1
  200. package/src/server/core/interfaces/ServerRequest.ts +1 -0
  201. package/src/server/core/providers/ServerProvider.ts +1 -1
  202. package/src/server/core/providers/ServerRouterProvider.ts +2 -2
  203. package/src/server/core/services/HttpClient.ts +1 -1
  204. package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
  205. package/dist/react/testing/chunk-DBEY4PJZ.js +0 -16
  206. package/src/orm/core/__tests__/parseQueryString.spec.ts +0 -196
  207. package/src/orm/core/helpers/parseQueryString.ts +0 -502
  208. package/src/orm/core/primitives/$view.ts +0 -88
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["NotFoundPage","NestedView","NotFoundPage"],"sources":["../../../src/react/router/constants/PAGE_PRELOAD_KEY.ts","../../../src/react/router/services/ReactPageService.ts","../../../src/react/router/primitives/$page.ts","../../../src/react/router/hooks/useRouterState.ts","../../../src/react/router/components/ErrorViewer.tsx","../../../src/react/router/contexts/RouterLayerContext.ts","../../../src/react/router/errors/Redirection.ts","../../../src/react/router/components/NestedView.tsx","../../../src/react/router/components/NotFound.tsx","../../../src/react/router/providers/ReactPageProvider.ts","../../../src/react/router/atoms/ssrManifestAtom.ts","../../../src/react/router/providers/SSRManifestProvider.ts","../../../src/react/router/providers/ReactPreloadProvider.ts","../../../src/react/router/providers/ReactServerTemplateProvider.ts","../../../src/react/router/providers/ReactServerProvider.ts","../../../src/react/router/services/ReactPageServerService.ts","../../../src/react/router/providers/ReactBrowserRouterProvider.ts","../../../src/react/router/providers/ReactBrowserProvider.ts","../../../src/react/router/services/ReactRouter.ts","../../../src/react/router/hooks/useRouter.ts","../../../src/react/router/components/Link.tsx","../../../src/react/router/hooks/useActive.ts","../../../src/react/router/hooks/useQueryParams.ts","../../../src/react/router/index.ts"],"sourcesContent":["/**\n * Symbol key for SSR module preloading path.\n * Using Symbol.for() allows the Vite plugin to inject this at build time.\n * @internal\n */\nexport const PAGE_PRELOAD_KEY = Symbol.for(\"alepha.page.preload\");\n","import { AlephaError } from \"alepha\";\nimport type {\n PagePrimitiveRenderOptions,\n PagePrimitiveRenderResult,\n} from \"../primitives/$page.ts\";\n\n/**\n * $page methods interface.\n */\nexport abstract class ReactPageService {\n public fetch(\n pathname: string,\n options: PagePrimitiveRenderOptions = {},\n ): Promise<{\n html: string;\n response: Response;\n }> {\n throw new AlephaError(\"Fetch is not available for this environment.\");\n }\n\n public render(\n name: string,\n options: PagePrimitiveRenderOptions = {},\n ): Promise<PagePrimitiveRenderResult> {\n throw new AlephaError(\"Render is not available for this environment.\");\n }\n}\n","import {\n $inject,\n type Async,\n createPrimitive,\n KIND,\n type Middleware,\n OPTIONS,\n Primitive,\n type Static,\n type TSchema,\n} from \"alepha\";\nimport { $cache } from \"alepha/cache\";\nimport type { ClientOnlyProps } from \"alepha/react\";\nimport type { Head } from \"alepha/react/head\";\nimport type { ServerRequest } from \"alepha/server\";\nimport type { FC, ReactNode } from \"react\";\nimport { PAGE_PRELOAD_KEY } from \"../constants/PAGE_PRELOAD_KEY.ts\";\nimport type { Redirection } from \"../errors/Redirection.ts\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\nimport { ReactPageService } from \"../services/ReactPageService.ts\";\n\n/**\n * Main primitive for defining a React route in the application.\n *\n * The $page primitive is the core building block for creating type-safe, SSR-enabled React routes.\n * It provides a declarative way to define pages with powerful features:\n *\n * **Routing & Navigation**\n * - URL pattern matching with parameters (e.g., `/users/:id`)\n * - Nested routing with parent-child relationships\n * - Type-safe URL parameter and query string validation\n *\n * **Data Loading**\n * - Server-side data fetching with the `loader` function\n * - Automatic serialization and hydration for SSR\n * - Access to request context, URL params, and parent data\n *\n * **Component Loading**\n * - Direct component rendering or lazy loading for code splitting\n * - Client-only rendering when browser APIs are needed\n * - Automatic fallback handling during hydration\n *\n * **Performance Optimization**\n * - Static generation for pre-rendered pages at build time\n * - Server-side caching with configurable TTL and providers\n * - Code splitting through lazy component loading\n *\n * **Error Handling**\n * - Custom error handlers with support for redirects\n * - Hierarchical error handling (child → parent)\n * - HTTP status code handling (404, 401, etc.)\n *\n * @example Simple page with data fetching\n * ```typescript\n * const userProfile = $page({\n * path: \"/users/:id\",\n * schema: {\n * params: t.object({ id: t.integer() }),\n * query: t.object({ tab: t.optional(t.text()) })\n * },\n * loader: async ({ params }) => {\n * const user = await userApi.getUser(params.id);\n * return { user };\n * },\n * lazy: () => import(\"./UserProfile.tsx\")\n * });\n * ```\n *\n * @example Nested routing with error handling\n * ```typescript\n * const projectSection = $page({\n * path: \"/projects/:id\",\n * children: () => [projectBoard, projectSettings],\n * loader: async ({ params }) => {\n * const project = await projectApi.get(params.id);\n * return { project };\n * },\n * errorHandler: (error) => {\n * if (HttpError.is(error, 404)) {\n * return <ProjectNotFound />;\n * }\n * }\n * });\n * ```\n *\n * @example Static generation with caching\n * ```typescript\n * const blogPost = $page({\n * path: \"/blog/:slug\",\n * static: {\n * entries: posts.map(p => ({ params: { slug: p.slug } }))\n * },\n * loader: async ({ params }) => {\n * const post = await loadPost(params.slug);\n * return { post };\n * }\n * });\n * ```\n */\nexport const $page = <\n TConfig extends PageConfigSchema = PageConfigSchema,\n TProps extends object = TPropsDefault,\n TPropsParent extends object = TPropsParentDefault,\n>(\n options: PagePrimitiveOptions<TConfig, TProps, TPropsParent>,\n): PagePrimitive<TConfig, TProps, TPropsParent> => {\n return createPrimitive(PagePrimitive<TConfig, TProps, TPropsParent>, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface PagePrimitiveOptions<\n TConfig extends PageConfigSchema = PageConfigSchema,\n TProps extends object = TPropsDefault,\n TPropsParent extends object = TPropsParentDefault,\n> {\n /**\n * Identifier name for the page. Must be unique.\n *\n * @default Primitive key\n */\n name?: string;\n\n /**\n * Add a pathname to the page.\n *\n * Pathname can contain parameters, like `/post/:slug`.\n *\n * @default \"\"\n */\n path?: string;\n\n /**\n * Add an input schema to define:\n * - `params`: parameters from the pathname.\n * - `query`: query parameters from the URL.\n */\n schema?: TConfig;\n\n /**\n * Middleware to apply to the loader function.\n * Works the same as `use` on `$action` and `$job`.\n *\n * @example\n * ```ts\n * dashboard = $page({\n * use: [$cache({ ttl: [5, \"minutes\"] })],\n * loader: async ({ params }) => this.dashboardService.getData(),\n * lazy: () => import(\"./Dashboard.tsx\"),\n * });\n * ```\n */\n use?: Middleware[];\n\n /**\n * Load data before rendering the page.\n *\n * This function receives\n * - the request context (params, query, etc.)\n * - the parent props (if page has a parent)\n *\n * > In SSR, the returned data will be serialized and sent to the client, then reused during the client-side hydration.\n *\n * Loader can be stopped by throwing an error, which will be handled by the `errorHandler` function.\n * It's common to throw a `NotFoundError` to display a 404 page.\n *\n * RedirectError can be thrown to redirect the user to another page.\n */\n loader?: (context: PageLoader<TConfig, TPropsParent>) => Async<TProps>;\n\n /**\n * Default props to pass to the component when rendering the page.\n *\n * Resolved props from the `resolve` function will override these default props.\n */\n props?: () => Partial<TProps>;\n\n /**\n * The component to render when the page is loaded.\n *\n * If `lazy` is defined, this will be ignored.\n * Prefer using `lazy` to improve the initial loading time.\n */\n component?: FC<TProps & TPropsParent>;\n\n /**\n * Lazy load the component when the page is loaded.\n *\n * It's recommended to use this for components to improve the initial loading time\n * and enable code-splitting.\n */\n lazy?: () => Promise<{ default: FC<TProps & TPropsParent> }>;\n\n /**\n * Attach child pages to create nested routes, adopting them as children of\n * this page.\n *\n * Use this when you want a parent to own children it cannot modify — most\n * notably pages that come from an injected router in another package, whose\n * `$page` definitions are frozen and cannot declare `parent` themselves.\n *\n * ```ts\n * layout = $page({\n * path: \"/app\",\n * children: () => [\n * this.productRouter.catalogPage, // from $inject(ProductRouter)\n * this.productRouter.checkoutPage,\n * ],\n * });\n * ```\n *\n * Use a thunk (`() => [...]`) when the children are defined later in the\n * same class.\n *\n * **Declare each edge from one side only.** If a child already sets\n * `parent: thisPage`, do NOT also add it to `children` — the link is\n * already established, and declaring it on both sides creates a TypeScript\n * circular dependency between the two class fields (each references the\n * other before it is initialised).\n */\n children?: Array<PagePrimitive> | (() => Array<PagePrimitive>);\n\n /**\n * Define a parent page for nested routing.\n *\n * Use this when you own the child page and can edit its definition — it is\n * the simplest way to nest routes and reads top-down. For pages you do NOT\n * own (e.g. pages exposed by an injected router from another package), let\n * the parent adopt them via its `children` option instead.\n *\n * **Declare each edge from one side only.** If you set `parent` here, do\n * NOT also add this page to the parent's `children` array — the link is\n * already established, and declaring it on both sides creates a TypeScript\n * circular dependency between the two class fields.\n */\n parent?: PagePrimitive<PageConfigSchema, TPropsParent, any>;\n\n /**\n * Function to determine if the page can be accessed.\n *\n * If it returns false, the page will not be accessible and a 403 Forbidden error will be returned.\n * This function can be used to implement permission-based access control.\n */\n can?: () => boolean;\n\n /**\n * Catch any error from the `loader` function or during `rendering`.\n *\n * Expected to return one of the following:\n * - a ReactNode to render an error page\n * - a Redirection to redirect the user\n * - undefined to let the error propagate\n *\n * If not defined, the error will be thrown and handled by the server or client error handler.\n * If a leaf $page does not define an error handler, the error can be caught by parent pages.\n *\n * @example Catch a 404 from API and render a custom not found component:\n * ```ts\n * loader: async ({ params, query }) => {\n * api.fetch(\"/api/resource\", { params, query });\n * },\n * errorHandler: (error, context) => {\n * if (HttpError.is(error, 404)) {\n * return <ResourceNotFound />;\n * }\n * }\n * ```\n *\n * @example Catch an 401 error and redirect the user to the login page:\n * ```ts\n * loader: async ({ params, query }) => {\n * // but the user is not authenticated\n * api.fetch(\"/api/resource\", { params, query });\n * },\n * errorHandler: (error, context) => {\n * if (HttpError.is(error, 401)) {\n * // throwing a Redirection is also valid!\n * return new Redirection(\"/login\");\n * }\n * }\n * ```\n */\n errorHandler?: ErrorHandler;\n\n /**\n * If true, the page will be considered as a static page, immutable and cacheable.\n * Replace boolean by an object to define static entries. (e.g. list of params/query)\n *\n * Browser-side: it only works with the build pipeline, which can pre-render the page at build time.\n *\n * Server-side: It will act as timeless cached page. You can use `cache` to configure the cache behavior.\n */\n static?:\n | boolean\n | {\n entries?: Array<Partial<PageRequestConfig<TConfig>>>;\n };\n\n /**\n * If true, force the page to be rendered only on the client-side (browser).\n * It uses the `<ClientOnly/>` component to render the page.\n */\n client?: boolean | ClientOnlyProps;\n\n /**\n * Called before the server response is sent to the client. (server only)\n */\n onServerResponse?: (request: ServerRequest) => unknown;\n\n /**\n * Called when user enters the page. (browser only)\n *\n * Useful for browser-only side effects like analytics, scroll management,\n * or focus handling that don't need to return data to the component.\n *\n * @example\n * ```ts\n * onEnter: () => {\n * analytics.trackPageView(\"/dashboard\");\n * window.scrollTo(0, 0);\n * }\n * ```\n */\n onEnter?: () => void;\n\n /**\n * Called when user leaves the page. (browser only)\n */\n onLeave?: () => void;\n\n /**\n * @experimental\n *\n * Add a css animation when the page is loaded or unloaded.\n * It uses CSS animations, so you need to define the keyframes in your CSS.\n *\n * @example Simple animation name\n * ```ts\n * animation: \"fadeIn\"\n * ```\n *\n * CSS example:\n * ```css\n * @keyframes fadeIn {\n * from { opacity: 0; }\n * to { opacity: 1; }\n * }\n * ```\n *\n * @example Detailed animation\n * ```ts\n * animation: {\n * enter: { name: \"fadeIn\", duration: 300 },\n * exit: { name: \"fadeOut\", duration: 200, timing: \"ease-in-out\" },\n * }\n * ```\n *\n * @example Only exit animation\n * ```ts\n * animation: {\n * exit: \"fadeOut\"\n * }\n * ```\n *\n * @example With custom timing function\n * ```ts\n * animation: {\n * enter: { name: \"fadeIn\", duration: 300, timing: \"cubic-bezier(0.4, 0, 0.2, 1)\" },\n * exit: { name: \"fadeOut\", duration: 200, timing: \"ease-in-out\" },\n * }\n * ```\n */\n animation?: PageAnimation;\n\n /**\n * Head configuration for the page (title, meta tags, etc.).\n *\n * Can be a static object or a function that receives resolved props.\n *\n * @example Static head\n * ```ts\n * head: {\n * title: \"My Page\",\n * description: \"Page description\",\n * }\n * ```\n *\n * @example Dynamic head based on props\n * ```ts\n * head: (props) => ({\n * title: props.user.name,\n * description: `Profile of ${props.user.name}`,\n * })\n * ```\n */\n head?: Head | ((props: TProps, previous?: Head) => Head);\n\n /**\n * Redirect to another path when this page is matched.\n *\n * This is a shorthand for throwing a `Redirection` in the loader.\n * The redirect is performed before any loader or component rendering.\n *\n * @example\n * ```ts\n * home = $page({\n * path: \"/\",\n * redirect: \"/dashboard\",\n * });\n * ```\n */\n redirect?: string;\n\n /**\n * Label for the page, used for navigation menus or breadcrumbs.\n *\n * This is optional and can be used by the application to display a user-friendly name for the page.\n * It has no functional impact on routing or rendering.\n */\n label?: string;\n\n /**\n * Source path for SSR module preloading.\n *\n * This is automatically injected by the viteAlephaPreload plugin.\n * It maps to the source file path used in Vite's SSR manifest.\n *\n * @internal\n */\n [PAGE_PRELOAD_KEY]?: string;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class PagePrimitive<\n TConfig extends PageConfigSchema = PageConfigSchema,\n TProps extends object = TPropsDefault,\n TPropsParent extends object = TPropsParentDefault,\n> extends Primitive<PagePrimitiveOptions<TConfig, TProps, TPropsParent>> {\n protected readonly reactPageService = $inject(ReactPageService);\n\n protected onInit() {\n if (this.options.static) {\n this.options.use ??= [];\n if (!this.options.use.some((m) => m[OPTIONS]?.name === \"$cache\")) {\n this.options.use.push(\n $cache({\n name: `page:${this.name}`,\n provider: \"memory\",\n ttl: [1, \"week\"],\n }),\n );\n }\n }\n }\n\n public get name(): string {\n return this.options.name ?? this.config.propertyKey;\n }\n\n /**\n * For testing or build purposes.\n *\n * This will render the page (HTML layout included or not) and return the HTML + context.\n * Only valid for server-side rendering, it will throw an error if called on the client-side.\n */\n public async render(\n options?: PagePrimitiveRenderOptions,\n ): Promise<PagePrimitiveRenderResult> {\n return this.reactPageService.render(this.name, options);\n }\n\n public async fetch(options?: PagePrimitiveRenderOptions): Promise<{\n html: string;\n response: Response;\n }> {\n return this.reactPageService.fetch(this.options.path || \"\", options);\n }\n}\n\n$page[KIND] = PagePrimitive;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type ErrorHandler = (\n error: Error,\n state: ReactRouterState,\n) => ReactNode | Redirection | undefined;\n\nexport interface PageConfigSchema {\n query?: TSchema;\n params?: TSchema;\n}\n\nexport type TPropsDefault = any;\n\nexport type TPropsParentDefault = {};\n\nexport interface PagePrimitiveRenderOptions {\n params?: Record<string, string>;\n query?: Record<string, string>;\n\n /**\n * If true, the HTML layout will be included in the response.\n * If false, only the page content will be returned.\n *\n * @default true\n */\n html?: boolean;\n hydration?: boolean;\n}\n\nexport interface PagePrimitiveRenderResult {\n html: string;\n state: ReactRouterState;\n redirect?: string;\n}\n\nexport interface PageRequestConfig<\n TConfig extends PageConfigSchema = PageConfigSchema,\n> {\n params: TConfig[\"params\"] extends TSchema\n ? Static<TConfig[\"params\"]>\n : Record<string, string>;\n\n query: TConfig[\"query\"] extends TSchema\n ? Static<TConfig[\"query\"]>\n : Record<string, string>;\n}\n\nexport type PageLoader<\n TConfig extends PageConfigSchema = PageConfigSchema,\n TPropsParent extends object = TPropsParentDefault,\n> = PageRequestConfig<TConfig> &\n TPropsParent &\n Omit<ReactRouterState, \"layers\" | \"onError\">;\n\nexport type PageAnimation =\n | PageAnimationObject\n | ((state: ReactRouterState) => PageAnimationObject | undefined);\n\ntype PageAnimationObject =\n | CssAnimationName\n | {\n enter?: CssAnimation | CssAnimationName;\n exit?: CssAnimation | CssAnimationName;\n };\n\ntype CssAnimationName = string;\n\ntype CssAnimation = {\n name: string;\n duration?: number;\n timing?: string;\n};\n","import { AlephaError } from \"alepha\";\nimport { useStore } from \"alepha/react\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\n\nexport const useRouterState = (): ReactRouterState => {\n const [state] = useStore(\"alepha.react.router.state\");\n if (!state) {\n throw new AlephaError(\"Missing react router state\");\n }\n return state;\n};\n","import type { Alepha } from \"alepha\";\nimport { type CSSProperties, useState } from \"react\";\nimport { useRouterState } from \"../hooks/useRouterState.ts\";\n\nexport interface ErrorViewerProps {\n error: Error;\n alepha: Alepha;\n onRetry?: () => void;\n}\n\nconst mono =\n 'ui-monospace, \"JetBrains Mono\", SFMono-Regular, Menlo, Monaco, Consolas, monospace';\n\nconst ErrorViewer = (props: ErrorViewerProps) => {\n if (props.alepha.isProduction()) {\n return <ProdErrorPage error={props.error} />;\n }\n\n return <DevErrorPage {...props} />;\n};\n\nexport default ErrorViewer;\n\n// ----- Dev Error Page -----\n\nconst DevErrorPage = (props: ErrorViewerProps) => {\n const [copied, setCopied] = useState(false);\n const state = useRouterState();\n const pathname = state.url.pathname;\n\n const handleCopy = () => {\n const text = buildErrorText(props.error);\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n };\n\n const status = getHttpStatus(props.error);\n\n return (\n <div style={dev.overlay}>\n <div style={dev.card}>\n <div style={dev.header}>\n <div style={dev.headerLeft}>\n <div style={dev.icon}>!</div>\n <div style={dev.title}>{props.error.name || \"Error\"}</div>\n </div>\n <div style={dev.headerRight}>\n {props.onRetry && (\n <button\n type=\"button\"\n style={dev.retryBtn}\n onClick={props.onRetry}\n >\n Retry\n </button>\n )}\n <button type=\"button\" style={dev.copyBtn} onClick={handleCopy}>\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n </div>\n </div>\n\n <ErrorBlock error={props.error} />\n\n <div style={dev.meta}>\n {pathname && <span style={dev.metaItem}>{pathname}</span>}\n <span style={dev.metaItem}>{new Date().toLocaleTimeString()}</span>\n {status && <span style={dev.statusBadge}>{status}</span>}\n </div>\n </div>\n </div>\n );\n};\n\n// ----- Error Block (recursive) -----\n\nconst ErrorBlock = (props: { error: Error; depth?: number }) => {\n const { error, depth = 0 } = props;\n\n return (\n <>\n {depth > 0 && <div style={dev.causedBy}>Caused by:</div>}\n <pre style={dev.messageBlock}>\n {error.name}: {error.message}\n </pre>\n {error.stack && (\n <>\n <div style={dev.stackLabel}>STACK TRACE</div>\n <pre style={dev.stackBlock}>{cleanStack(error.stack)}</pre>\n </>\n )}\n {error.cause instanceof Error && (\n <ErrorBlock error={error.cause} depth={depth + 1} />\n )}\n </>\n );\n};\n\n// ----- Prod Error Page -----\n\ninterface ProdErrorPageProps {\n error: Error;\n}\n\nconst ProdErrorPage = (props: ProdErrorPageProps) => {\n const requestId = (props.error as any).requestId;\n\n const handleReload = () => {\n if (typeof window !== \"undefined\") {\n window.location.reload();\n }\n };\n\n return (\n <div style={prod.page}>\n <div style={prod.card}>\n <div style={prod.heading}>Something went wrong</div>\n <div style={prod.subtitle}>\n We're having trouble processing your request.\n </div>\n {requestId && <div style={prod.refText}>Reference: {requestId}</div>}\n <div style={prod.actions}>\n <button type=\"button\" style={prod.reloadBtn} onClick={handleReload}>\n Reload page\n </button>\n <a href=\"/\" style={prod.homeLink}>\n Go home\n </a>\n </div>\n </div>\n </div>\n );\n};\n\n// ----- Helpers -----\n\nfunction cleanStack(stack: string): string {\n return stack\n .split(\"\\n\")\n .slice(1)\n .map((l) => l.trim())\n .join(\"\\n\");\n}\n\nfunction buildErrorText(error: Error): string {\n const parts: string[] = [];\n\n const append = (err: Error, depth: number) => {\n if (depth > 0) {\n parts.push(`\\nCaused by:`);\n }\n parts.push(`${err.name}: ${err.message}`);\n if (err.stack) {\n parts.push(cleanStack(err.stack));\n }\n if (err.cause instanceof Error) {\n append(err.cause, depth + 1);\n }\n };\n\n append(error, 0);\n return parts.join(\"\\n\");\n}\n\nfunction getHttpStatus(error: Error): number | undefined {\n if (\"status\" in error && typeof (error as any).status === \"number\") {\n return (error as any).status;\n }\n return undefined;\n}\n\n// ----- Dev Styles -----\n\nconst dev: Record<string, CSSProperties> = {\n overlay: {\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483647,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"24px\",\n backgroundColor: \"rgba(0, 0, 0, 0.75)\",\n backdropFilter: \"blur(4px)\",\n fontFamily: mono,\n fontSize: \"13px\",\n color: \"#e5e7eb\",\n boxSizing: \"border-box\",\n overflow: \"auto\",\n },\n card: {\n width: \"100%\",\n maxWidth: \"900px\",\n maxHeight: \"90vh\",\n overflow: \"auto\",\n padding: \"24px\",\n backgroundColor: \"#111\",\n borderLeft: \"4px solid #ef4444\",\n borderRadius: \"8px\",\n boxShadow: \"0 25px 50px rgba(0, 0, 0, 0.5)\",\n },\n header: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: \"20px\",\n flexWrap: \"wrap\",\n gap: \"12px\",\n },\n headerLeft: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"12px\",\n minWidth: 0,\n },\n headerRight: {\n display: \"flex\",\n gap: \"8px\",\n flexShrink: 0,\n },\n icon: {\n width: \"28px\",\n height: \"28px\",\n borderRadius: \"50%\",\n backgroundColor: \"#ef4444\",\n color: \"#fff\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontWeight: 700,\n fontSize: \"16px\",\n flexShrink: 0,\n },\n title: {\n color: \"#f87171\",\n fontSize: \"18px\",\n fontWeight: 700,\n },\n retryBtn: {\n padding: \"6px 16px\",\n backgroundColor: \"#2563eb\",\n color: \"#fff\",\n border: \"none\",\n borderRadius: \"6px\",\n cursor: \"pointer\",\n fontFamily: mono,\n fontSize: \"12px\",\n fontWeight: 600,\n },\n copyBtn: {\n padding: \"6px 16px\",\n backgroundColor: \"transparent\",\n color: \"#9ca3af\",\n border: \"1px solid #374151\",\n borderRadius: \"6px\",\n cursor: \"pointer\",\n fontFamily: mono,\n fontSize: \"12px\",\n fontWeight: 600,\n },\n messageBlock: {\n margin: \"0 0 12px\",\n padding: \"12px\",\n backgroundColor: \"#1f2937\",\n borderRadius: \"6px\",\n color: \"#f9fafb\",\n fontSize: \"13px\",\n lineHeight: 1.6,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n overflow: \"auto\",\n },\n stackLabel: {\n fontSize: \"10px\",\n color: \"#6b7280\",\n textTransform: \"uppercase\",\n letterSpacing: \"1.5px\",\n marginBottom: \"6px\",\n fontWeight: 600,\n },\n stackBlock: {\n margin: \"0 0 20px\",\n padding: \"12px\",\n backgroundColor: \"#0f172a\",\n borderRadius: \"6px\",\n color: \"#94a3b8\",\n fontSize: \"12px\",\n lineHeight: 1.6,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-all\",\n overflow: \"auto\",\n },\n causedBy: {\n fontSize: \"10px\",\n color: \"#6b7280\",\n textTransform: \"uppercase\",\n letterSpacing: \"1.5px\",\n marginBottom: \"8px\",\n paddingTop: \"12px\",\n borderTop: \"1px solid #374151\",\n fontWeight: 600,\n },\n meta: {\n display: \"flex\",\n gap: \"16px\",\n alignItems: \"center\",\n paddingTop: \"12px\",\n borderTop: \"1px solid #1f2937\",\n flexWrap: \"wrap\",\n },\n metaItem: {\n fontSize: \"11px\",\n color: \"#6b7280\",\n },\n statusBadge: {\n fontSize: \"11px\",\n color: \"#fbbf24\",\n backgroundColor: \"#422006\",\n padding: \"2px 8px\",\n borderRadius: \"4px\",\n fontWeight: 600,\n },\n};\n\n// ----- Prod Styles -----\n\nconst prod: Record<string, CSSProperties> = {\n page: {\n minHeight: \"100vh\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"#0f172a\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n padding: \"24px\",\n },\n card: {\n textAlign: \"center\",\n maxWidth: \"440px\",\n },\n heading: {\n fontSize: \"28px\",\n fontWeight: 700,\n color: \"#f1f5f9\",\n marginBottom: \"12px\",\n },\n subtitle: {\n fontSize: \"16px\",\n color: \"#94a3b8\",\n marginBottom: \"24px\",\n lineHeight: 1.5,\n },\n refText: {\n fontSize: \"13px\",\n color: \"#64748b\",\n marginBottom: \"24px\",\n fontFamily: mono,\n },\n actions: {\n display: \"flex\",\n gap: \"12px\",\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n reloadBtn: {\n padding: \"10px 24px\",\n backgroundColor: \"#2563eb\",\n color: \"#fff\",\n border: \"none\",\n borderRadius: \"8px\",\n cursor: \"pointer\",\n fontSize: \"14px\",\n fontWeight: 600,\n },\n homeLink: {\n padding: \"10px 24px\",\n color: \"#94a3b8\",\n textDecoration: \"none\",\n fontSize: \"14px\",\n },\n};\n","import { createContext } from \"react\";\nimport type { ErrorHandler } from \"../primitives/$page.ts\";\n\nexport interface RouterLayerContextValue {\n index: number;\n path: string;\n onError: ErrorHandler;\n}\n\nexport const RouterLayerContext = createContext<\n RouterLayerContextValue | undefined\n>(undefined);\n","import { AlephaError } from \"alepha\";\n\n/**\n * Used for Redirection during the page loading.\n *\n * Depends on the context, it can be thrown or just returned.\n *\n * @example\n * ```ts\n * import { Redirection } from \"alepha/react\";\n *\n * const MyPage = $page({\n * loader: async () => {\n * if (needRedirect) {\n * throw new Redirection(\"/new-path\");\n * }\n * },\n * });\n * ```\n */\nexport class Redirection extends AlephaError {\n public readonly redirect: string;\n\n constructor(redirect: string) {\n super(\"Redirection\");\n this.redirect = redirect;\n }\n}\n","import { ErrorBoundary, useAlepha, useEvents } from \"alepha/react\";\nimport { memo, type ReactNode, use, useRef, useState } from \"react\";\nimport { RouterLayerContext } from \"../contexts/RouterLayerContext.ts\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport { useRouterState } from \"../hooks/useRouterState.ts\";\nimport type { PageAnimation } from \"../primitives/$page.ts\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\nimport ErrorViewer from \"./ErrorViewer.tsx\";\n\nexport interface NestedViewProps {\n children?: ReactNode;\n errorBoundary?: false | ((error: Error, reset: () => void) => ReactNode);\n}\n\n/**\n * A component that renders the current view of the nested router layer.\n *\n * To be simple, it renders the `element` of the current child page of a parent page.\n *\n * @example\n * ```tsx\n * import { NestedView } from \"alepha/react\";\n *\n * class App {\n * parent = $page({\n * component: () => <NestedView />,\n * });\n *\n * child = $page({\n * parent: this.root,\n * component: () => <div>Child Page</div>,\n * });\n * }\n * ```\n */\nconst NestedView = (props: NestedViewProps) => {\n const routerLayer = use(RouterLayerContext);\n const index = routerLayer?.index ?? 0;\n const onError = routerLayer?.onError;\n const state = useRouterState();\n const alepha = useAlepha();\n const [boundaryKey, setBoundaryKey] = useState(0);\n\n const [view, setView] = useState<ReactNode | undefined>(\n state.layers[index]?.element,\n );\n\n const [animation, setAnimation] = useState(\"\");\n const animationExitDuration = useRef<number>(0);\n const animationExitNow = useRef<number>(0);\n\n useEvents(\n {\n \"react:transition:begin\": async ({ previous, state }) => {\n // --------- Animations Begin ---------\n const layer = previous.layers[index];\n if (!layer) {\n return;\n }\n\n if (`${state.url.pathname}/`.startsWith(`${layer.path}/`)) {\n return;\n }\n\n const animationExit = parseAnimation(\n layer.route?.animation,\n state,\n \"exit\",\n );\n\n if (animationExit) {\n const duration = animationExit.duration || 200;\n animationExitNow.current = Date.now();\n animationExitDuration.current = duration;\n setAnimation(animationExit.animation);\n } else {\n animationExitNow.current = 0;\n animationExitDuration.current = 0;\n setAnimation(\"\");\n }\n // --------- Animations End ---------\n },\n \"react:transition:end\": async ({ state }) => {\n const layer = state.layers[index];\n\n // --------- Animations Begin ---------\n if (animationExitNow.current) {\n const duration = animationExitDuration.current;\n const diff = Date.now() - animationExitNow.current;\n if (diff < duration) {\n await new Promise((resolve) =>\n setTimeout(resolve, duration - diff),\n );\n }\n }\n // --------- Animations End ---------\n\n if (!layer?.cache) {\n setView(layer?.element);\n\n // --------- Animations Begin ---------\n const animationEnter = parseAnimation(\n layer?.route?.animation,\n state,\n \"enter\",\n );\n\n if (animationEnter) {\n setAnimation(animationEnter.animation);\n } else {\n setAnimation(\"\");\n }\n // --------- Animations End ---------\n }\n },\n },\n [],\n );\n\n let element = view ?? props.children ?? null;\n\n // --------- Animations Begin ---------\n if (animation) {\n element = (\n <div\n style={{\n display: \"flex\",\n flex: 1,\n height: \"100%\",\n width: \"100%\",\n position: \"relative\",\n overflow: \"hidden\",\n }}\n >\n <div\n style={{ height: \"100%\", width: \"100%\", display: \"flex\", animation }}\n >\n {element}\n </div>\n </div>\n );\n }\n // --------- Animations End ---------\n\n if (props.errorBoundary === false) {\n return <>{element}</>;\n }\n\n if (props.errorBoundary) {\n return (\n <ErrorBoundary key={boundaryKey} fallback={props.errorBoundary}>\n {element}\n </ErrorBoundary>\n );\n }\n\n const fallback = (error: Error) => {\n const result = onError?.(error, state) ?? (\n <ErrorViewer error={error} alepha={alepha} />\n );\n if (result instanceof Redirection) {\n return \"Redirection inside ErrorBoundary is not allowed.\";\n }\n return result as ReactNode;\n };\n\n return (\n <ErrorBoundary key={boundaryKey} fallback={fallback}>\n {element}\n </ErrorBoundary>\n );\n};\n\nexport default memo(NestedView);\n\nfunction parseAnimation(\n animationLike: PageAnimation | undefined,\n state: ReactRouterState,\n type: \"enter\" | \"exit\" = \"enter\",\n):\n | {\n duration: number;\n animation: string;\n }\n | undefined {\n if (!animationLike) {\n return undefined;\n }\n\n const DEFAULT_DURATION = 300;\n\n const animation =\n typeof animationLike === \"function\" ? animationLike(state) : animationLike;\n\n if (typeof animation === \"string\") {\n if (type === \"exit\") {\n return;\n }\n return {\n duration: DEFAULT_DURATION,\n animation: `${DEFAULT_DURATION}ms ${animation}`,\n };\n }\n\n if (typeof animation === \"object\") {\n const anim = animation[type];\n const duration =\n typeof anim === \"object\"\n ? (anim.duration ?? DEFAULT_DURATION)\n : DEFAULT_DURATION;\n const name = typeof anim === \"object\" ? anim.name : anim;\n\n if (type === \"exit\") {\n const timing = typeof anim === \"object\" ? (anim.timing ?? \"\") : \"\";\n return {\n duration,\n animation: `${duration}ms ${timing} ${name}`,\n };\n }\n\n const timing = typeof anim === \"object\" ? (anim.timing ?? \"\") : \"\";\n\n return {\n duration,\n animation: `${duration}ms ${timing} ${name}`,\n };\n }\n\n return undefined;\n}\n","import type { CSSProperties } from \"react\";\n\n/**\n * Default 404 Not Found page component.\n */\nconst NotFound = (props: { style?: CSSProperties }) => (\n <div\n style={{\n width: \"100%\",\n minHeight: \"90vh\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n textAlign: \"center\",\n fontFamily:\n 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n padding: \"2rem\",\n ...props.style,\n }}\n >\n <div style={{ fontSize: \"6rem\", fontWeight: 200, lineHeight: 1 }}>404</div>\n <div style={{ fontSize: \"0.875rem\", marginTop: \"1rem\", opacity: 0.6 }}>\n Page not found\n </div>\n </div>\n);\n\nexport default NotFound;\n","import {\n $atom,\n $hook,\n $inject,\n $state,\n Alepha,\n AlephaError,\n type TSchema,\n t,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { AlephaContext, ClientOnly } from \"alepha/react\";\nimport type { Head } from \"alepha/react/head\";\nimport { createElement, type ReactNode, StrictMode } from \"react\";\nimport ErrorViewer from \"../components/ErrorViewer.tsx\";\nimport NestedView from \"../components/NestedView.tsx\";\nimport NotFoundPage from \"../components/NotFound.tsx\";\nimport { RouterLayerContext } from \"../contexts/RouterLayerContext.ts\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport {\n $page,\n type ErrorHandler,\n type PagePrimitive,\n type PagePrimitiveOptions,\n} from \"../primitives/$page.ts\";\n\n// -------------------------------------------------------------------------------------------------------------------\n\nexport const reactPageOptions = $atom({\n name: \"alepha.react.page.options\",\n description: \"Configuration options for the React page provider.\",\n schema: t.object({\n /**\n * Enable React StrictMode wrapper.\n */\n strictMode: t.boolean({ default: true }),\n /**\n * RegExp pattern (as string) to detect file-like URLs (e.g. /hello.txt, /wp-login.php).\n * When a request hits the catch-all wildcard route and matches this pattern,\n * SSR is skipped and a plain 404 response is returned instead.\n *\n * Set to empty string to disable this behavior.\n *\n * @default \"\\\\.[a-zA-Z0-9]{1,10}$\"\n */\n staticFilePattern: t.string(),\n }),\n default: {\n strictMode: true,\n staticFilePattern: \"\\\\.[a-zA-Z0-9]{1,10}$\",\n },\n});\n\n// -------------------------------------------------------------------------------------------------------------------\n\n/**\n * Handle page routes for React applications. (Browser and Server)\n */\nexport class ReactPageProvider {\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly log = $logger();\n protected readonly options = $state(reactPageOptions);\n protected readonly alepha = $inject(Alepha);\n protected readonly pages: PageRoute[] = [];\n protected nextIdCursor = 0;\n\n protected readonly configure = $hook({\n on: \"configure\",\n handler: () => {\n let hasNotFoundHandler = false;\n const pages = this.alepha.primitives($page);\n\n const hasParent = (it: PagePrimitive) => {\n if (it.options.parent) {\n return true;\n }\n\n for (const page of pages) {\n const children = page.options.children\n ? Array.isArray(page.options.children)\n ? page.options.children\n : page.options.children()\n : [];\n if (children.includes(it)) {\n return true;\n }\n }\n };\n\n for (const page of pages) {\n if (page.options.path === \"/*\") {\n hasNotFoundHandler = true;\n }\n\n // skip children, we only want root pages\n if (hasParent(page)) {\n continue;\n }\n\n this.add(this.map(pages, page));\n }\n\n if (!hasNotFoundHandler && pages.length > 0) {\n // add a default 404 page if not already defined\n this.add({\n path: \"/*\",\n name: \"notFound\",\n component: NotFoundPage,\n onServerResponse: ({ reply }) => {\n reply.status = 404;\n },\n });\n }\n },\n });\n\n // -------------------------------------------------------------------------------------------------------------------\n\n public getPages(): PageRoute[] {\n return this.pages;\n }\n\n public getConcretePages(): ConcretePageRoute[] {\n const pages: ConcretePageRoute[] = [];\n for (const page of this.pages) {\n if (page.children && page.children.length > 0) {\n continue;\n }\n\n // check if the page has dynamic params\n const fullPath = this.pathname(page.name);\n if (fullPath.includes(\":\") || fullPath.includes(\"*\")) {\n if (typeof page.static === \"object\") {\n const entries = page.static.entries;\n if (entries && entries.length > 0) {\n for (const entry of entries) {\n const params = entry.params as Record<string, string>;\n const path = this.compile(page.path ?? \"\", params);\n if (!path.includes(\":\") && !path.includes(\"*\")) {\n pages.push({\n ...page,\n name: params[Object.keys(params)[0]],\n staticName: page.name,\n path,\n ...entry,\n });\n }\n }\n }\n }\n\n continue;\n }\n\n pages.push(page);\n }\n return pages;\n }\n\n public page(name: string): PageRoute {\n for (const page of this.pages) {\n if (page.name === name) {\n return page;\n }\n }\n\n throw new AlephaError(`Page '${name}' not found`);\n }\n\n public pathname(\n name: string,\n options: {\n params?: Record<string, string>;\n query?: Record<string, string>;\n } = {},\n ) {\n const page = this.page(name);\n if (!page) {\n throw new AlephaError(`Page ${name} not found`);\n }\n\n let url = page.path ?? \"\";\n let parent = page.parent;\n while (parent) {\n url = `${parent.path ?? \"\"}/${url}`;\n parent = parent.parent;\n }\n\n url = this.compile(url, options.params ?? {});\n\n if (options.query) {\n const query = new URLSearchParams(options.query);\n if (query.toString()) {\n url += `?${query.toString()}`;\n }\n }\n\n return url.replace(/\\/\\/+/g, \"/\") || \"/\";\n }\n\n public url(\n name: string,\n options: { params?: Record<string, string>; host?: string } = {},\n ): URL {\n return new URL(\n this.pathname(name, options),\n // use provided base or default to http://localhost\n options.host ?? `http://localhost`,\n );\n }\n\n public root(state: ReactRouterState): ReactNode {\n const root = createElement(\n AlephaContext.Provider,\n { value: this.alepha },\n createElement(NestedView, {}, state.layers[0]?.element),\n );\n\n if (this.options.strictMode) {\n return createElement(StrictMode, {}, root);\n }\n\n return root;\n }\n\n protected convertStringObjectToObject = (\n schema?: TSchema,\n value?: any,\n ): any => {\n if (t.schema.isObject(schema) && typeof value === \"object\") {\n for (const key in schema.properties) {\n if (\n t.schema.isObject(schema.properties[key]) &&\n typeof value[key] === \"string\"\n ) {\n try {\n value[key] = this.alepha.codec.decode(\n schema.properties[key],\n decodeURIComponent(value[key]),\n );\n } catch (e) {\n // ignore\n }\n }\n }\n }\n return value;\n };\n\n /**\n * Create a new RouterState based on a given route and request.\n * This method resolves the layers for the route, applying any query and params schemas defined in the route.\n * It also handles errors and redirects.\n */\n public async createLayers(\n route: PageRoute,\n state: ReactRouterState,\n previous: PreviousLayerData[] = [],\n ): Promise<CreateLayersResult> {\n let context: Record<string, any> = {}; // all props\n const stack: Array<RouterStackItem> = [{ route }]; // stack of routes\n\n let parent = route.parent;\n while (parent) {\n stack.unshift({ route: parent });\n parent = parent.parent;\n }\n\n let forceRefresh = false;\n\n for (let i = 0; i < stack.length; i++) {\n const it = stack[i];\n const route = it.route;\n const config: Record<string, any> = {};\n\n try {\n this.convertStringObjectToObject(route.schema?.query, state.query);\n config.query = route.schema?.query\n ? this.alepha.codec.decode(route.schema.query, state.query)\n : {};\n } catch (e) {\n it.error = e instanceof Error ? e : new Error(String(e));\n break;\n }\n\n try {\n config.params = route.schema?.params\n ? this.alepha.codec.decode(route.schema.params, state.params)\n : {};\n } catch (e) {\n it.error = e instanceof Error ? e : new Error(String(e));\n break;\n }\n\n // save config\n it.config = {\n ...config,\n };\n\n // check if previous layer is the same, reuse if possible\n if (previous?.[i] && !forceRefresh && previous[i].name === route.name) {\n const url = (str?: string) => (str ? str.replace(/\\/\\/+/g, \"/\") : \"/\");\n\n const prev = JSON.stringify({\n part: url(previous[i].part),\n params: previous[i].config?.params ?? {},\n });\n\n const curr = JSON.stringify({\n part: url(route.path),\n params: config.params ?? {},\n });\n\n if (prev === curr) {\n // part is the same, reuse previous layer\n it.props = previous[i].props;\n it.error = previous[i].error;\n it.cache = true;\n context = {\n ...context,\n ...it.props,\n };\n continue;\n }\n\n // part is different, force refresh of next layers\n forceRefresh = true;\n }\n\n // redirect shorthand\n if (route.redirect) {\n return { redirect: route.redirect };\n }\n\n // no loader, render a basic view by default\n if (!route.loader) {\n continue;\n }\n\n try {\n const args = Object.create(state);\n Object.assign(args, config, context);\n const props = (await route.loader?.(args)) ?? {};\n\n // save props\n it.props = {\n ...props,\n };\n\n // add props to context\n context = {\n ...context,\n ...props,\n };\n } catch (e) {\n // check if we need to redirect\n if (e instanceof Redirection) {\n return {\n redirect: e.redirect,\n };\n }\n\n this.log.error(\"Page loader has failed\", e);\n\n it.error = e instanceof Error ? e : new Error(String(e));\n break;\n }\n }\n\n let acc = \"\";\n for (let i = 0; i < stack.length; i++) {\n const it = stack[i];\n const props = it.props ?? {};\n\n const params = { ...it.config?.params };\n for (const key of Object.keys(params)) {\n params[key] = String(params[key]);\n }\n\n acc += \"/\";\n acc += it.route.path ? this.compile(it.route.path, params) : \"\";\n const path = acc.replace(/\\/+/, \"/\");\n const localErrorHandler = this.getErrorHandler(it.route);\n if (localErrorHandler) {\n const onErrorParent = state.onError;\n state.onError = (error, context) => {\n const result = localErrorHandler(error, context);\n // if nothing happen, call the parent\n if (result === undefined) {\n return onErrorParent(error, context);\n }\n return result;\n };\n }\n\n // normal use case\n if (!it.error) {\n try {\n const element = await this.createElement(\n it.route,\n {\n // default props attached to page\n ...(it.route.props ? it.route.props() : {}),\n // resolved props\n ...props,\n // context props (from previous layers)\n ...context,\n },\n state.url,\n );\n\n state.layers.push({\n name: it.route.name,\n props,\n part: it.route.path,\n config: it.config,\n element: this.renderView(i + 1, path, element, it.route),\n index: i + 1,\n path,\n route: it.route,\n cache: it.cache,\n });\n } catch (e) {\n it.error = e instanceof Error ? e : new Error(String(e));\n }\n }\n\n // handler has thrown an error, render an error view\n if (it.error) {\n try {\n let element: ReactNode | Redirection | undefined =\n await state.onError(it.error, state);\n\n if (element === undefined) {\n throw it.error;\n }\n\n if (element instanceof Redirection) {\n return {\n redirect: element.redirect,\n };\n }\n\n if (element === null) {\n element = this.renderError(it.error);\n }\n\n state.layers.push({\n props,\n error: it.error,\n name: it.route.name,\n part: it.route.path,\n config: it.config,\n element: this.renderView(i + 1, path, element, it.route),\n index: i + 1,\n path,\n route: it.route,\n cache: it.cache,\n });\n break;\n } catch (e) {\n if (e instanceof Redirection) {\n return {\n redirect: e.redirect,\n };\n }\n throw e;\n }\n }\n }\n\n return { state };\n }\n\n protected getErrorHandler(route: PageRoute): ErrorHandler | undefined {\n if (route.errorHandler) return route.errorHandler;\n let parent = route.parent;\n while (parent) {\n if (parent.errorHandler) return parent.errorHandler;\n parent = parent.parent;\n }\n }\n\n protected async createElement(\n page: PageRoute,\n props: Record<string, any>,\n targetUrl?: URL,\n ): Promise<ReactNode> {\n if (page.lazy && page.component) {\n this.log.warn(\n `Page ${page.name} has both lazy and component options, lazy will be used`,\n );\n }\n\n if (page.lazy) {\n try {\n const component = await page.lazy();\n return createElement(component.default, props);\n } catch (error) {\n if (this.alepha.isBrowser() && this.isChunkLoadError(error)) {\n if (this.reloadAfterChunkError(targetUrl)) {\n return undefined;\n }\n }\n throw error;\n }\n }\n\n if (page.component) {\n return createElement(page.component, props);\n }\n\n return undefined;\n }\n\n /**\n * Detect chunk load errors caused by stale dynamic imports after a deployment.\n * When new assets are deployed with different hashes, old chunk URLs return 404.\n */\n protected isChunkLoadError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const msg = error.message;\n return (\n /Failed to fetch dynamically imported module/.test(msg) ||\n /error loading dynamically imported module/i.test(msg) ||\n /Unable to preload CSS/.test(msg) ||\n /Importing a module script failed/.test(msg)\n );\n }\n\n /**\n * Navigate to the target URL to fetch updated assets after a chunk load failure.\n * Uses sessionStorage to prevent infinite reload loops.\n * Returns true if navigation was initiated.\n */\n protected reloadAfterChunkError(url?: URL): boolean {\n const key = \"alepha:chunk-reload\";\n const lastReload = sessionStorage.getItem(key);\n const now = this.dateTimeProvider.nowMillis();\n\n if (lastReload && now - Number(lastReload) < 10_000) {\n this.log.error(\n \"Chunk load failed after recent reload, not retrying to avoid loop\",\n );\n return false;\n }\n\n this.log.warn(\"Chunk load failed after deployment, reloading page\");\n sessionStorage.setItem(key, String(now));\n window.location.assign(\n url ? url.pathname + url.search : window.location.href,\n );\n return true;\n }\n\n public renderError(error: Error): ReactNode {\n return createElement(ErrorViewer, { error, alepha: this.alepha });\n }\n\n public renderEmptyView(): ReactNode {\n return createElement(NestedView, {});\n }\n\n public href(\n page: { options: { name?: string } },\n params: Record<string, any> = {},\n ): string {\n const found = this.pages.find((it) => it.name === page.options.name);\n if (!found) {\n throw new AlephaError(`Page ${page.options.name} not found`);\n }\n\n let url = found.path ?? \"\";\n let parent = found.parent;\n while (parent) {\n url = `${parent.path ?? \"\"}/${url}`;\n parent = parent.parent;\n }\n\n url = this.compile(url, params);\n\n return url.replace(/\\/\\/+/g, \"/\") || \"/\";\n }\n\n public compile(path: string, params: Record<string, string> = {}) {\n for (const [key, value] of Object.entries(params)) {\n path = path.replace(`:${key}`, value);\n }\n return path;\n }\n\n protected renderView(\n index: number,\n path: string,\n view: ReactNode | undefined,\n page: PageRoute,\n ): ReactNode {\n view ??= this.renderEmptyView();\n\n const element = page.client\n ? createElement(\n ClientOnly,\n typeof page.client === \"object\" ? page.client : {},\n view,\n )\n : view;\n\n return createElement(\n RouterLayerContext.Provider,\n {\n value: {\n index,\n path,\n onError:\n this.getErrorHandler(page) ?? ((error) => this.renderError(error)),\n },\n },\n element,\n );\n }\n\n protected map(\n pages: Array<PagePrimitive>,\n target: PagePrimitive,\n ): PageRouteEntry {\n const children = target.options.children\n ? Array.isArray(target.options.children)\n ? target.options.children\n : target.options.children()\n : [];\n\n const getChildrenFromParent = (it: PagePrimitive): PagePrimitive[] => {\n const children = [];\n for (const page of pages) {\n if (page.options.parent === it) {\n children.push(page);\n }\n }\n return children;\n };\n\n children.push(...getChildrenFromParent(target));\n\n return {\n ...target.options,\n name: target.name,\n parent: undefined,\n children: children.map((it) => this.map(pages, it)),\n } as PageRoute;\n }\n\n public add(entry: PageRouteEntry) {\n if (this.alepha.isReady()) {\n throw new AlephaError(\"Router is already initialized\");\n }\n\n entry.name ??= this.nextId();\n const page = entry as PageRoute;\n\n page.match = this.createMatch(page);\n this.pages.push(page);\n\n if (page.children) {\n for (const child of page.children) {\n (child as PageRoute).parent = page;\n this.add(child);\n }\n }\n }\n\n protected createMatch(page: PageRoute): string {\n let url = page.path ?? \"/\";\n let target = page.parent;\n while (target) {\n url = `${target.path ?? \"\"}/${url}`;\n target = target.parent;\n }\n\n let path = url.replace(/\\/\\/+/g, \"/\");\n\n if (path.endsWith(\"/\") && path !== \"/\") {\n // remove trailing slash\n path = path.slice(0, -1);\n }\n\n return path;\n }\n\n protected nextId(): string {\n this.nextIdCursor += 1;\n return `P${this.nextIdCursor}`;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const isPageRoute = (it: any): it is PageRoute => {\n return (\n it &&\n typeof it === \"object\" &&\n typeof it.path === \"string\" &&\n typeof it.page === \"object\"\n );\n};\n\nexport interface PageRouteEntry\n extends Omit<PagePrimitiveOptions, \"children\" | \"parent\"> {\n children?: PageRouteEntry[];\n}\n\nexport interface ConcretePageRoute extends PageRoute {\n /**\n * When exported, static routes can be split into multiple pages with different params.\n * We replace 'name' by the new name for each static entry, and old 'name' becomes 'staticName'.\n */\n staticName?: string;\n\n params?: Record<string, string>;\n}\n\nexport interface PageRoute extends PageRouteEntry {\n type: \"page\";\n name: string;\n parent?: PageRoute;\n match: string;\n\n /**\n * Optional meta information associated with the page route, can be used for any purpose (e.g. menu label, icon, etc.).\n */\n label?: string;\n}\n\nexport interface Layer {\n config?: {\n query?: Record<string, any>;\n params?: Record<string, any>;\n // stack of resolved props\n context?: Record<string, any>;\n };\n\n name: string;\n props?: Record<string, any>;\n error?: Error;\n part?: string;\n element: ReactNode;\n index: number;\n path: string;\n route?: PageRoute;\n cache?: boolean;\n}\n\nexport type PreviousLayerData = Omit<Layer, \"element\" | \"index\" | \"path\">;\n\nexport interface AnchorProps {\n href: string;\n onClick: (ev?: any) => any;\n}\n\nexport interface ReactRouterState {\n /**\n * Stack of layers for the current page.\n */\n layers: Array<Layer>;\n\n /**\n * URL of the current page.\n */\n url: URL;\n\n /**\n * Error handler for the current page.\n */\n onError: ErrorHandler;\n\n /**\n * Params extracted from the URL for the current page.\n */\n params: Record<string, any>;\n\n /**\n * Query parameters extracted from the URL for the current page.\n */\n query: Record<string, string>;\n\n /**\n * Optional meta information associated with the current page.\n */\n meta: Record<string, any>;\n\n /**\n * Head configuration for the current page (title, meta tags, etc.).\n * Populated by HeadProvider during SSR.\n */\n head: Head;\n\n /**\n * Optional name of the current page route\n */\n name?: string;\n}\n\nexport interface RouterStackItem {\n route: PageRoute;\n config?: Record<string, any>;\n props?: Record<string, any>;\n error?: Error;\n cache?: boolean;\n}\n\nexport interface CreateLayersResult {\n redirect?: string;\n state?: ReactRouterState;\n}\n","import { $atom, t } from \"alepha\";\n\n/**\n * Schema for the SSR manifest atom.\n */\nexport const ssrManifestAtomSchema = t.object({\n /**\n * Base path for assets (from Vite's base config).\n * Used to prefix asset URLs when serving from a subpath.\n * @example \"/devtools\" or \"/\"\n */\n base: t.optional(t.string()),\n\n /**\n * Preload manifest mapping short keys to source paths.\n * Generated by viteAlephaSsrPreload plugin at build time.\n */\n preload: t.optional(t.record(t.string(), t.string())),\n\n /**\n * Client manifest mapping source files to their output information.\n * Only includes fields actually used for preloading.\n */\n client: t.optional(\n t.record(\n t.string(),\n t.object({\n file: t.string(),\n isEntry: t.optional(t.boolean()),\n imports: t.optional(t.array(t.string())),\n css: t.optional(t.array(t.string())),\n }),\n ),\n ),\n\n /**\n * Dev mode head content.\n * Contains pre-transformed scripts injected by Vite and plugins (React, etc.).\n * Only set in dev mode via ViteDevServerProvider.\n */\n devHead: t.optional(t.string()),\n\n /**\n * Auto-detected favicon path and MIME type.\n * Format: \"type:path\" (e.g., \"image/svg+xml:/favicon.svg\").\n * Set at build/dev time by scanning the public directory.\n */\n favicon: t.optional(t.string()),\n});\n\n/**\n * Type for the SSR manifest schema.\n */\nexport type SsrManifestAtomSchema = typeof ssrManifestAtomSchema;\n\n/**\n * SSR Manifest atom containing all manifest data for SSR module preloading.\n *\n * This atom is populated at build time by embedding manifest data into the\n * generated index.js. This approach is optimal for serverless deployments\n * as it eliminates filesystem reads at runtime.\n *\n * The manifest includes:\n * - preload: Maps short hash keys to source paths (from viteAlephaSsrPreload)\n * - client: Maps source files to their output info (file, imports, css)\n */\nexport const ssrManifestAtom = $atom({\n name: \"alepha.react.ssr.manifest\",\n description: \"SSR manifest for module preloading\",\n schema: ssrManifestAtomSchema,\n default: {},\n});\n","import { $inject, Alepha, type Static } from \"alepha\";\nimport {\n type SsrManifestAtomSchema,\n ssrManifestAtom,\n} from \"../atoms/ssrManifestAtom.ts\";\nimport { PAGE_PRELOAD_KEY } from \"../constants/PAGE_PRELOAD_KEY.ts\";\nimport type { PageRoute } from \"./ReactPageProvider.ts\";\n\n/**\n * Provider for SSR manifest data used for module preloading.\n *\n * The manifest is populated at build time by embedding data into the\n * generated index.js via the ssrManifestAtom. This eliminates filesystem\n * reads at runtime, making it optimal for serverless deployments.\n *\n * Manifest files are generated during `vite build`:\n * - manifest.json (client manifest)\n * - preload-manifest.json (from viteAlephaSsrPreload plugin)\n */\nexport class SSRManifestProvider {\n protected readonly alepha = $inject(Alepha);\n\n /**\n * Get the manifest from the store at runtime.\n * This ensures the manifest is available even when set after module load.\n */\n protected get manifest(): Static<SsrManifestAtomSchema> {\n return (\n (this.alepha.store.get(\n ssrManifestAtom,\n ) as Static<SsrManifestAtomSchema>) ?? {}\n );\n }\n\n /**\n * Get the full manifest object.\n */\n public getManifest(): Static<SsrManifestAtomSchema> {\n return this.manifest;\n }\n\n /**\n * Get the base path for assets (from Vite's base config).\n * Returns empty string if base is \"/\" (default), otherwise returns the base path.\n */\n protected get base(): string {\n return this.manifest.base ?? \"\";\n }\n\n /**\n * Get the preload manifest.\n */\n protected get preloadManifest(): PreloadManifest | undefined {\n return this.manifest.preload;\n }\n\n /**\n * Get the client manifest.\n */\n protected get clientManifest(): ClientManifest | undefined {\n return this.manifest.client;\n }\n\n /**\n * Resolve a preload key to its source path.\n *\n * The key is a short hash injected by viteAlephaSsrPreload plugin,\n * which maps to the full source path in the preload manifest.\n *\n * @param key - Short hash key (e.g., \"a1b2c3d4\")\n * @returns Source path (e.g., \"src/pages/UserDetail.tsx\") or undefined\n */\n public resolvePreloadKey(key: string): string | undefined {\n return this.preloadManifest?.[key];\n }\n\n /**\n * Get all chunks required for a source file, including transitive dependencies.\n *\n * Uses the client manifest to recursively resolve all imported chunks.\n *\n * @param sourcePath - Source file path (e.g., \"src/pages/Home.tsx\")\n * @returns Array of chunk URLs to preload, or empty array if not found\n */\n public getChunks(sourcePath: string): string[] {\n if (!this.clientManifest) {\n return [];\n }\n\n // Find entry in client manifest\n const entry = this.findManifestEntry(sourcePath);\n if (!entry) {\n return [];\n }\n\n // Recursively collect all chunks\n const chunks = new Set<string>();\n const visited = new Set<string>();\n\n this.collectChunksRecursive(sourcePath, chunks, visited);\n\n return Array.from(chunks);\n }\n\n /**\n * Find manifest entry for a source path, trying different extensions.\n */\n protected findManifestEntry(sourcePath: string) {\n if (!this.clientManifest) return undefined;\n\n // Try exact match\n if (this.clientManifest[sourcePath]) {\n return this.clientManifest[sourcePath];\n }\n\n // Try with different extensions\n const basePath = sourcePath.replace(/\\.[^.]+$/, \"\");\n for (const ext of [\".tsx\", \".ts\", \".jsx\", \".js\"]) {\n const pathWithExt = basePath + ext;\n if (this.clientManifest[pathWithExt]) {\n return this.clientManifest[pathWithExt];\n }\n }\n\n return undefined;\n }\n\n /**\n * Recursively collect all chunk URLs for a manifest entry.\n */\n protected collectChunksRecursive(\n key: string,\n chunks: Set<string>,\n visited: Set<string>,\n ): void {\n if (visited.has(key)) return;\n visited.add(key);\n\n if (!this.clientManifest) return;\n\n const entry = this.clientManifest[key];\n if (!entry) return;\n\n const base = this.base;\n\n // Add main chunk file (with base path for URL)\n if (entry.file) {\n chunks.add(`${base}/${entry.file}`);\n }\n\n // Add CSS files\n if (entry.css) {\n for (const css of entry.css) {\n chunks.add(`${base}/${css}`);\n }\n }\n\n // Recursively process imports (but skip entry point)\n if (entry.imports) {\n for (const imp of entry.imports) {\n // Skip the main entry point (index.html) - it's already being loaded\n if (imp === \"index.html\" || imp.endsWith(\".html\")) {\n continue;\n }\n this.collectChunksRecursive(imp, chunks, visited);\n }\n }\n\n // Note: We intentionally do NOT follow dynamicImports\n // Those are lazy-loaded and shouldn't be preloaded\n }\n\n /**\n * Collect modulepreload links for a route and its parent chain.\n */\n public collectPreloadLinks(\n route: PageRoute,\n ): Array<{ rel: string; href: string; as?: string; crossorigin?: string }> {\n if (!this.isAvailable()) {\n return [];\n }\n\n const preloadPaths: string[] = [];\n let current: PageRoute | undefined = route;\n\n while (current) {\n const preloadKey = current[PAGE_PRELOAD_KEY];\n if (preloadKey) {\n const sourcePath = this.resolvePreloadKey(preloadKey);\n if (sourcePath) {\n preloadPaths.push(sourcePath);\n }\n }\n current = current.parent;\n }\n\n if (preloadPaths.length === 0) {\n return [];\n }\n\n const chunks = this.getChunksForMultiple(preloadPaths);\n\n return chunks.map((href) => {\n if (href.endsWith(\".css\")) {\n // Must include crossorigin to match Vite's dynamic CSS loading which always uses crossorigin=\"\"\n return { rel: \"preload\", href, as: \"style\", crossorigin: \"\" };\n }\n return { rel: \"modulepreload\", href };\n });\n }\n\n /**\n * Get all chunks for multiple source files.\n *\n * @param sourcePaths - Array of source file paths\n * @returns Deduplicated array of chunk URLs\n */\n public getChunksForMultiple(sourcePaths: string[]): string[] {\n const allChunks = new Set<string>();\n\n for (const path of sourcePaths) {\n const chunks = this.getChunks(path);\n for (const chunk of chunks) {\n allChunks.add(chunk);\n }\n }\n\n return Array.from(allChunks);\n }\n\n /**\n * Check if manifest is loaded and available.\n */\n public isAvailable(): boolean {\n return this.clientManifest !== undefined;\n }\n\n /**\n * Cached entry assets - computed once at first access.\n */\n protected cachedEntryAssets: EntryAssets | null = null;\n\n /**\n * Get the entry point assets (main entry.js and associated CSS files).\n *\n * These assets are always required for all pages and can be preloaded\n * before page-specific loaders run.\n *\n * @returns Entry assets with js and css paths, or null if manifest unavailable\n */\n public getEntryAssets(): EntryAssets | null {\n if (this.cachedEntryAssets) {\n return this.cachedEntryAssets;\n }\n\n if (!this.clientManifest) {\n return null;\n }\n\n const base = this.base;\n\n // Find the entry point in the client manifest\n for (const [key, entry] of Object.entries(this.clientManifest)) {\n if (entry.isEntry) {\n this.cachedEntryAssets = {\n js: `${base}/${entry.file}`,\n css: entry.css?.map((css) => `${base}/${css}`) ?? [],\n };\n return this.cachedEntryAssets;\n }\n }\n\n return null;\n }\n\n /**\n * Build preload link tags for entry assets.\n *\n * @returns Array of link objects ready to be rendered\n */\n public getEntryPreloadLinks(): Array<{\n rel: string;\n href: string;\n as?: string;\n crossorigin?: string;\n }> {\n const assets = this.getEntryAssets();\n if (!assets) {\n return [];\n }\n\n const links: Array<{\n rel: string;\n href: string;\n as?: string;\n crossorigin?: string;\n }> = [];\n\n // Add CSS preloads first (critical for rendering)\n for (const css of assets.css) {\n links.push({ rel: \"stylesheet\", href: css, crossorigin: \"\" });\n }\n\n // Add entry JS modulepreload\n if (assets.js) {\n links.push({ rel: \"modulepreload\", href: assets.js });\n }\n\n return links;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Entry assets structure containing the main entry JS and associated CSS files.\n */\nexport interface EntryAssets {\n /**\n * Main entry JavaScript file (e.g., \"/assets/entry.abc123.js\")\n */\n js?: string;\n /**\n * Associated CSS files (e.g., [\"/assets/style.abc123.css\"])\n */\n css: string[];\n}\n\n/**\n * Client manifest structure from Vite.\n * Only includes fields actually used for preloading.\n */\nexport interface ClientManifest {\n [key: string]: {\n file: string;\n isEntry?: boolean;\n imports?: string[];\n css?: string[];\n };\n}\n\n/**\n * Preload manifest mapping short keys to source paths.\n * Generated by viteAlephaSsrPreload plugin at build time.\n */\nexport type PreloadManifest = Record<string, string>;\n","import { $hook, $inject, Alepha } from \"alepha\";\nimport { SSRManifestProvider } from \"./SSRManifestProvider.ts\";\n\n/**\n * Adds HTTP Link headers for preloading entry assets.\n *\n * Benefits:\n * - Early Hints (103): Servers can send preload hints before the full response\n * - CDN optimization: Many CDNs use Link headers to optimize asset delivery\n * - Browser prefetching: Browsers can start fetching resources earlier\n *\n * The Link header is computed once at first request and cached for reuse.\n */\nexport class ReactPreloadProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly ssrManifest = $inject(SSRManifestProvider);\n\n /**\n * Cached Link header value - computed once, reused for all requests.\n */\n protected cachedLinkHeader: string | null | undefined;\n\n /**\n * Build the Link header string from entry assets.\n *\n * Format: <url>; rel=preload; as=type, <url>; rel=modulepreload\n *\n * @returns Link header string or null if no assets\n */\n protected buildLinkHeader(): string | null {\n const assets = this.ssrManifest.getEntryAssets();\n if (!assets) return null;\n\n const links: string[] = [];\n\n // CSS - preload as style\n for (const css of assets.css) {\n links.push(`<${css}>; rel=preload; as=style`);\n }\n\n // JS - modulepreload for ES modules\n if (assets.js) {\n links.push(`<${assets.js}>; rel=modulepreload`);\n }\n\n return links.length > 0 ? links.join(\", \") : null;\n }\n\n /**\n * Get the cached Link header, computing it on first access.\n */\n protected getLinkHeader(): string | null {\n if (this.cachedLinkHeader === undefined) {\n this.cachedLinkHeader = this.buildLinkHeader();\n }\n return this.cachedLinkHeader;\n }\n\n /**\n * Add Link header to HTML responses for asset preloading.\n */\n protected readonly onResponse = $hook({\n on: \"server:onResponse\",\n priority: \"first\",\n handler: ({ response }) => {\n // Only add to HTML responses (SSR pages)\n const contentType = response.headers[\"content-type\"];\n if (!contentType || !contentType.includes(\"text/html\")) {\n return;\n }\n\n const linkHeader = this.getLinkHeader();\n if (!linkHeader) {\n return;\n }\n\n // Append to existing Link header if present\n if (response.headers.link) {\n response.headers.link = `${response.headers.link}, ${linkHeader}`;\n } else {\n response.headers.link = linkHeader;\n }\n },\n });\n}\n","import { $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { AlephaContext } from \"alepha/react\";\nimport type { SimpleHead } from \"alepha/react/head\";\nimport { createElement, type ReactNode } from \"react\";\nimport { renderToString } from \"react-dom/server\";\nimport ErrorViewer from \"../components/ErrorViewer.tsx\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport type { ReactRouterState } from \"./ReactPageProvider.ts\";\n\n/**\n * Handles HTML streaming for SSR.\n *\n * Uses hardcoded HTML structure - all customization via $head primitive.\n * Pre-encodes static parts as Uint8Array for zero-copy streaming.\n */\nexport class ReactServerTemplateProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n\n /**\n * Shared TextEncoder - reused across all requests.\n */\n protected readonly encoder = new TextEncoder();\n\n /**\n * Pre-encoded static HTML parts for zero-copy streaming.\n */\n protected readonly SLOTS = {\n DOCTYPE: this.encoder.encode(\"<!DOCTYPE html>\\n\"),\n HTML_OPEN: this.encoder.encode(\"<html\"),\n HTML_CLOSE: this.encoder.encode(\">\\n\"),\n HEAD_OPEN: this.encoder.encode(\"<head>\"),\n HEAD_CLOSE: this.encoder.encode(\"</head>\\n\"),\n BODY_OPEN: this.encoder.encode(\"<body\"),\n BODY_CLOSE: this.encoder.encode(\">\\n\"),\n ROOT_OPEN: this.encoder.encode('<div id=\"root\">'),\n ROOT_CLOSE: this.encoder.encode(\"</div>\\n\"),\n BODY_HTML_CLOSE: this.encoder.encode(\"</body>\\n</html>\"),\n HYDRATION_PREFIX: this.encoder.encode(\n '<script id=\"__ssr\" type=\"application/json\">',\n ),\n HYDRATION_SUFFIX: this.encoder.encode(\"</script>\"),\n } as const;\n\n /**\n * Early head content (charset, viewport, entry assets).\n * Set once during configuration, reused for all requests.\n */\n protected earlyHeadContent = \"\";\n\n /**\n * Root element ID for React mounting.\n */\n public readonly rootId = \"root\";\n\n /**\n * Regex for extracting root div content from HTML.\n */\n public readonly rootDivRegex = new RegExp(\n `<div[^>]*\\\\s+id=[\"']${this.rootId}[\"'][^>]*>([\\\\s\\\\S]*?)<\\\\/div>`,\n \"i\",\n );\n\n /**\n * Extract content inside the root div from HTML.\n */\n public extractRootContent(html: string): string | undefined {\n return html.match(this.rootDivRegex)?.[1];\n }\n\n /**\n * Set early head content (charset, viewport, entry assets).\n * Called once during server configuration.\n */\n public setEarlyHeadContent(\n entryAssets: string,\n globalHead?: SimpleHead,\n ): void {\n const charset = globalHead?.charset ?? \"UTF-8\";\n const viewport =\n globalHead?.viewport ?? \"width=device-width, initial-scale=1\";\n\n this.earlyHeadContent =\n `<meta charset=\"${this.escapeHtml(charset)}\">\\n` +\n `<meta name=\"viewport\" content=\"${this.escapeHtml(viewport)}\">\\n` +\n entryAssets;\n }\n\n /**\n * Render attributes record to HTML string.\n */\n public renderAttributes(attrs?: Record<string, string>): string {\n if (!attrs) return \"\";\n const entries = Object.entries(attrs);\n if (entries.length === 0) return \"\";\n return entries\n .map(([key, value]) => ` ${key}=\"${this.escapeHtml(value)}\"`)\n .join(\"\");\n }\n\n /**\n * Render head content (title, meta, link, script tags).\n */\n public renderHeadContent(head?: SimpleHead): string {\n if (!head) return \"\";\n\n let content = \"\";\n\n if (head.title) {\n content += `<title>${this.escapeHtml(head.title)}</title>\\n`;\n }\n\n if (head.meta) {\n for (const meta of head.meta) {\n if (meta.property) {\n content += `<meta property=\"${this.escapeHtml(meta.property)}\" content=\"${this.escapeHtml(meta.content)}\">\\n`;\n } else if (meta.name) {\n content += `<meta name=\"${this.escapeHtml(meta.name)}\" content=\"${this.escapeHtml(meta.content)}\">\\n`;\n }\n }\n }\n\n if (head.link) {\n for (const link of head.link) {\n content += `<link rel=\"${this.escapeHtml(link.rel)}\" href=\"${this.escapeHtml(link.href)}\"`;\n if (link.type) content += ` type=\"${this.escapeHtml(link.type)}\"`;\n if (link.as) content += ` as=\"${this.escapeHtml(link.as)}\"`;\n if (link.crossorigin != null) content += ' crossorigin=\"\"';\n content += \">\\n\";\n }\n }\n\n if (head.script) {\n for (const script of head.script) {\n if (typeof script === \"string\") {\n content += `<script>${script}</script>\\n`;\n } else {\n const { content: scriptContent, ...rest } = script;\n const attrs = Object.entries(rest)\n .filter(([, v]) => v !== false && v !== undefined)\n .map(([k, v]) =>\n v === true ? k : `${k}=\"${this.escapeHtml(String(v))}\"`,\n )\n .join(\" \");\n content += scriptContent\n ? `<script ${attrs}>${scriptContent}</script>\\n`\n : `<script ${attrs}></script>\\n`;\n }\n }\n }\n\n return content;\n }\n\n /**\n * Escape HTML special characters.\n */\n public escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#039;\");\n }\n\n /**\n * Safely serialize data to JSON for embedding in HTML.\n */\n public safeJsonSerialize(data: unknown): string {\n return JSON.stringify(data)\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/&/g, \"\\\\u0026\");\n }\n\n /**\n * Build hydration data from router state.\n */\n public buildHydrationData(state: ReactRouterState): HydrationData {\n const layers = state.layers.map((layer) => ({\n part: layer.part,\n name: layer.name,\n config: layer.config,\n props: layer.props,\n error: layer.error\n ? {\n ...layer.error,\n name: layer.error.name,\n message: layer.error.message,\n stack: !this.alepha.isProduction() ? layer.error.stack : undefined,\n }\n : undefined,\n }));\n\n return {\n \"alepha.react.router.layers\": layers,\n ...this.alepha.store.exportAtoms(\"current\"),\n };\n }\n\n // ---------------------------------------------------------------------------\n // Core streaming methods\n // ---------------------------------------------------------------------------\n\n /**\n * Pipe React stream to controller with backpressure handling.\n * Returns true if stream completed successfully, false if error occurred.\n */\n protected async pipeReactStream(\n controller: ReadableStreamDefaultController<Uint8Array>,\n reactStream: ReadableStream<Uint8Array>,\n state: ReactRouterState,\n ): Promise<boolean> {\n const reader = reactStream.getReader();\n\n try {\n while (true) {\n // Backpressure: wait if buffer is full\n if (controller.desiredSize !== null && controller.desiredSize <= 0) {\n await new Promise<void>((resolve) => queueMicrotask(resolve));\n }\n\n const { done, value } = await reader.read();\n if (done) break;\n controller.enqueue(value);\n }\n return true;\n } catch (error) {\n this.log.error(\"React stream error\", error);\n controller.enqueue(\n this.encoder.encode(\n this.renderErrorToString(\n error instanceof Error ? error : new Error(String(error)),\n state,\n ),\n ),\n );\n return false;\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Stream complete HTML document (head already closed).\n * Used by both createHtmlStream and late phase of createEarlyHtmlStream.\n */\n protected async streamBodyAndClose(\n controller: ReadableStreamDefaultController<Uint8Array>,\n reactStream: ReadableStream<Uint8Array>,\n state: ReactRouterState,\n hydration: boolean,\n ): Promise<void> {\n const { encoder, SLOTS: slots } = this;\n\n // Body open\n controller.enqueue(slots.BODY_OPEN);\n controller.enqueue(\n encoder.encode(this.renderAttributes(state.head?.bodyAttributes)),\n );\n controller.enqueue(slots.BODY_CLOSE);\n\n // Root + React content\n controller.enqueue(slots.ROOT_OPEN);\n await this.pipeReactStream(controller, reactStream, state);\n controller.enqueue(slots.ROOT_CLOSE);\n\n // Hydration\n if (hydration) {\n controller.enqueue(slots.HYDRATION_PREFIX);\n controller.enqueue(\n encoder.encode(this.safeJsonSerialize(this.buildHydrationData(state))),\n );\n controller.enqueue(slots.HYDRATION_SUFFIX);\n }\n\n controller.enqueue(slots.BODY_HTML_CLOSE);\n }\n\n // ---------------------------------------------------------------------------\n // Public streaming APIs\n // ---------------------------------------------------------------------------\n\n /**\n * Create HTML stream with early head optimization.\n *\n * Flow:\n * 1. Send DOCTYPE, <html>, <head> open, entry preloads (IMMEDIATE)\n * 2. Run async work (page loaders)\n * 3. Send rest of head, body, React content, hydration\n */\n public createEarlyHtmlStream(\n globalHead: SimpleHead,\n asyncWork: () => Promise<\n | { state: ReactRouterState; reactStream: ReadableStream<Uint8Array> }\n | { redirect: string }\n | null\n >,\n options: {\n hydration?: boolean;\n state?: ReactRouterState;\n onError?: (error: unknown) => void;\n } = {},\n ): ReadableStream<Uint8Array> {\n const { hydration = true, onError } = options;\n const { encoder, SLOTS: slots } = this;\n\n let headClosed = false;\n let bodyStarted = false;\n let routerState: ReactRouterState | undefined = options.state;\n\n return new ReadableStream<Uint8Array>({\n start: async (controller) => {\n try {\n // === EARLY PHASE (before async work) ===\n controller.enqueue(slots.DOCTYPE);\n controller.enqueue(slots.HTML_OPEN);\n controller.enqueue(\n encoder.encode(this.renderAttributes(globalHead?.htmlAttributes)),\n );\n controller.enqueue(slots.HTML_CLOSE);\n controller.enqueue(slots.HEAD_OPEN);\n if (this.earlyHeadContent) {\n controller.enqueue(encoder.encode(this.earlyHeadContent));\n }\n\n // === ASYNC WORK ===\n const result = await asyncWork();\n\n // Handle redirect\n if (!result || \"redirect\" in result) {\n if (result && \"redirect\" in result) {\n this.log.debug(\"Loader redirect, using meta refresh\", {\n redirect: result.redirect,\n });\n controller.enqueue(\n encoder.encode(\n `<meta http-equiv=\"refresh\" content=\"0; url=${this.escapeHtml(result.redirect)}\">\\n`,\n ),\n );\n }\n controller.enqueue(slots.HEAD_CLOSE);\n controller.enqueue(encoder.encode(\"<body></body></html>\"));\n controller.close();\n return;\n }\n\n const { state, reactStream } = result;\n routerState = state;\n\n // === LATE PHASE (after async work) ===\n controller.enqueue(\n encoder.encode(this.renderHeadContent(state.head)),\n );\n controller.enqueue(slots.HEAD_CLOSE);\n headClosed = true;\n bodyStarted = true;\n\n await this.streamBodyAndClose(\n controller,\n reactStream,\n state,\n hydration,\n );\n controller.close();\n } catch (error) {\n onError?.(error);\n try {\n this.injectErrorHtml(controller, error, routerState, {\n headClosed,\n bodyStarted,\n });\n controller.close();\n } catch {\n controller.error(error);\n }\n }\n },\n });\n }\n\n /**\n * Create HTML stream (non-early version, for testing/prerender).\n */\n public createHtmlStream(\n reactStream: ReadableStream<Uint8Array>,\n state: ReactRouterState,\n options: { hydration?: boolean; onError?: (error: unknown) => void } = {},\n ): ReadableStream<Uint8Array> {\n const { hydration = true, onError } = options;\n const { encoder, SLOTS: slots } = this;\n\n return new ReadableStream<Uint8Array>({\n start: async (controller) => {\n try {\n // Head\n controller.enqueue(slots.DOCTYPE);\n controller.enqueue(slots.HTML_OPEN);\n controller.enqueue(\n encoder.encode(this.renderAttributes(state.head?.htmlAttributes)),\n );\n controller.enqueue(slots.HTML_CLOSE);\n controller.enqueue(slots.HEAD_OPEN);\n if (this.earlyHeadContent) {\n controller.enqueue(encoder.encode(this.earlyHeadContent));\n }\n controller.enqueue(\n encoder.encode(this.renderHeadContent(state.head)),\n );\n controller.enqueue(slots.HEAD_CLOSE);\n\n // Body (shared logic)\n await this.streamBodyAndClose(\n controller,\n reactStream,\n state,\n hydration,\n );\n controller.close();\n } catch (error) {\n onError?.(error);\n controller.error(error);\n }\n },\n });\n }\n\n // ---------------------------------------------------------------------------\n // Error handling\n // ---------------------------------------------------------------------------\n\n /**\n * Inject error HTML when streaming fails.\n */\n protected injectErrorHtml(\n controller: ReadableStreamDefaultController<Uint8Array>,\n error: unknown,\n routerState: ReactRouterState | undefined,\n streamState: { headClosed: boolean; bodyStarted: boolean },\n ): void {\n const { encoder, SLOTS: slots } = this;\n\n if (!streamState.headClosed) {\n controller.enqueue(\n encoder.encode(this.renderHeadContent(routerState?.head)),\n );\n controller.enqueue(slots.HEAD_CLOSE);\n }\n\n if (!streamState.bodyStarted) {\n controller.enqueue(slots.BODY_OPEN);\n controller.enqueue(\n encoder.encode(\n this.renderAttributes(routerState?.head?.bodyAttributes),\n ),\n );\n controller.enqueue(slots.BODY_CLOSE);\n controller.enqueue(slots.ROOT_OPEN);\n }\n\n controller.enqueue(\n encoder.encode(\n this.renderErrorToString(\n error instanceof Error ? error : new Error(String(error)),\n routerState,\n ),\n ),\n );\n\n controller.enqueue(slots.ROOT_CLOSE);\n\n if (routerState) {\n controller.enqueue(slots.HYDRATION_PREFIX);\n controller.enqueue(\n encoder.encode(\n this.safeJsonSerialize(this.buildHydrationData(routerState)),\n ),\n );\n controller.enqueue(slots.HYDRATION_SUFFIX);\n }\n\n controller.enqueue(slots.BODY_HTML_CLOSE);\n }\n\n /**\n * Render error to HTML string.\n */\n protected renderErrorToString(\n error: Error,\n routerState: ReactRouterState | undefined,\n ): string {\n this.log.error(\"SSR rendering error\", error);\n\n let errorElement: ReactNode;\n\n if (routerState?.onError) {\n try {\n const result = routerState.onError(error, routerState);\n if (result instanceof Redirection) {\n this.log.warn(\"Error handler returned Redirection but headers sent\", {\n redirect: result.redirect,\n });\n } else if (result != null) {\n errorElement = result;\n }\n } catch (handlerError) {\n this.log.error(\"Error handler threw\", handlerError);\n }\n }\n\n if (!errorElement) {\n errorElement = createElement(ErrorViewer, {\n error,\n alepha: this.alepha,\n });\n }\n\n const wrappedElement = createElement(\n AlephaContext.Provider,\n { value: this.alepha },\n errorElement,\n );\n\n try {\n return renderToString(wrappedElement);\n } catch (renderError) {\n this.log.error(\"Failed to render error component\", renderError);\n return error.message;\n }\n }\n}\n\n/**\n * Hydration state serialized to a JSON script tag with id=\"__ssr\"\n */\nexport interface HydrationData {\n \"alepha.react.router.layers\": Array<{\n part?: string;\n name?: string;\n config?: Record<string, any>;\n props?: Record<string, any>;\n error?: { name: string; message: string; stack?: string };\n }>;\n [key: string]: unknown;\n}\n","import { join } from \"node:path\";\nimport {\n $atom,\n $env,\n $hook,\n $inject,\n $state,\n Alepha,\n type Middleware,\n OPTIONS,\n PipelineHandler,\n type Static,\n t,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { ServerHeadProvider } from \"alepha/react/head\";\nimport { type ServerHandler, ServerRouterProvider } from \"alepha/server\";\nimport { ServerLinksProvider } from \"alepha/server/links\";\nimport { ServerStaticProvider } from \"alepha/server/static\";\nimport { FileSystemProvider } from \"alepha/system\";\nimport { renderToReadableStream } from \"react-dom/server\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport {\n $page,\n type PagePrimitiveRenderOptions,\n type PagePrimitiveRenderResult,\n} from \"../primitives/$page.ts\";\nimport {\n type PageRoute,\n ReactPageProvider,\n type ReactRouterState,\n reactPageOptions,\n} from \"./ReactPageProvider.ts\";\nimport { ReactServerTemplateProvider } from \"./ReactServerTemplateProvider.ts\";\nimport { SSRManifestProvider } from \"./SSRManifestProvider.ts\";\n\n/**\n * React server provider responsible for SSR and static file serving.\n *\n * Coordinates between:\n * - ReactPageProvider: Page routing and layer resolution\n * - ReactServerTemplateProvider: HTML template parsing and streaming\n * - ServerHeadProvider: Head content management\n * - SSRManifestProvider: Module preload link collection\n *\n * Uses `react-dom/server` under the hood.\n */\nexport class ReactServerProvider {\n /**\n * SSR response headers - pre-allocated to avoid object creation per request.\n */\n protected readonly SSR_HEADERS = {\n \"content-type\": \"text/html\",\n \"cache-control\": \"no-store, no-cache, must-revalidate, proxy-revalidate\",\n pragma: \"no-cache\",\n expires: \"0\",\n } as const;\n\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly env = $env(envSchema);\n protected readonly pageApi = $inject(ReactPageProvider);\n protected readonly templateProvider = $inject(ReactServerTemplateProvider);\n protected readonly serverHeadProvider = $inject(ServerHeadProvider);\n protected readonly serverStaticProvider = $inject(ServerStaticProvider);\n protected readonly serverRouterProvider = $inject(ServerRouterProvider);\n protected readonly ssrManifestProvider = $inject(SSRManifestProvider);\n\n /**\n * Cached check for ServerLinksProvider - avoids has() lookup per request.\n */\n protected hasServerLinksProvider = false;\n\n protected readonly options = $state(reactServerOptions);\n protected readonly pageOptions = $state(reactPageOptions);\n\n /**\n * Configure the React server provider.\n */\n public readonly onConfigure = $hook({\n on: \"configure\",\n handler: async () => {\n const pages = this.alepha.primitives($page);\n\n const ssrEnabled =\n pages.length > 0 && this.env.REACT_SSR_ENABLED !== false;\n\n this.alepha.store.set(\"alepha.react.server.ssr\", ssrEnabled);\n\n // production mode\n let root = \"\";\n\n // non-serverless mode only -> serve static files\n if (!this.alepha.isServerless() && !this.alepha.isViteDev()) {\n root = await this.getPublicDirectory();\n if (!root) {\n this.log.warn(\n \"Missing static files, static file server will be disabled\",\n );\n } else {\n this.log.debug(`Using static files from: ${root}`);\n await this.configureStaticServer(root);\n }\n }\n\n if (ssrEnabled) {\n this.registerPages();\n this.log.info(\"SSR OK\");\n return;\n }\n\n // no SSR enabled, serve a minimal fallback\n this.log.info(\"SSR is disabled\");\n },\n });\n\n /**\n * Register all pages as server routes.\n */\n protected registerPages(): void {\n // Set up early head content (entry assets)\n this.setupEarlyHeadContent();\n\n // Cache ServerLinksProvider check at startup\n this.hasServerLinksProvider = this.alepha.has(ServerLinksProvider);\n\n for (const page of this.pageApi.getPages()) {\n if (page.component || page.lazy || page.redirect) {\n this.log.debug(`+ ${page.match} -> ${page.name}`);\n\n // Collect middleware from the entire parent chain + own page.\n // Parent middleware runs first (outermost → innermost).\n const allMiddleware = this.collectMiddleware(page);\n\n // Separate $cache from server-level middleware.\n // $cache is applied inside createHandler around the render function,\n // not around the entire server handler (which works via side effects).\n const cacheMiddleware = allMiddleware.filter(\n (m) => m[OPTIONS]?.name === \"$cache\",\n );\n const serverMiddleware = allMiddleware.filter(\n (m) => m[OPTIONS]?.name !== \"$cache\",\n );\n\n const rawHandler = this.createHandler(page, cacheMiddleware);\n const handler = serverMiddleware.length\n ? new PipelineHandler(rawHandler, serverMiddleware)\n : rawHandler;\n\n this.serverRouterProvider.createRoute({\n ...page,\n schema: undefined, // schema is handled by the page primitive provider\n method: \"GET\",\n path: page.match,\n handler,\n });\n }\n }\n }\n\n /**\n * Set up early head content with entry assets.\n *\n * This content is sent immediately when streaming starts, before page loaders run,\n * allowing the browser to start downloading entry.js and CSS files early.\n */\n protected setupEarlyHeadContent(): void {\n const globalHead = this.serverHeadProvider.resolveGlobalHead();\n const manifest = this.ssrManifestProvider.getManifest();\n const faviconTag = this.buildFaviconTag(manifest.favicon);\n\n // Dev mode: use pre-transformed head content from Vite\n if (manifest.devHead) {\n const devContent = faviconTag\n ? `${faviconTag}\\n${manifest.devHead}\\n`\n : `${manifest.devHead}\\n`;\n this.templateProvider.setEarlyHeadContent(devContent, globalHead);\n this.log.debug(\"Early head content set (dev mode)\");\n return;\n }\n\n // Production: build from SSR manifest entry assets\n const parts: string[] = [];\n if (faviconTag) {\n parts.push(faviconTag);\n }\n const assets = this.ssrManifestProvider.getEntryAssets();\n if (assets) {\n for (const css of assets.css) {\n parts.push(`<link rel=\"stylesheet\" href=\"${css}\">`);\n }\n if (assets.js) {\n parts.push(\n `<script type=\"module\" crossorigin=\"\" src=\"${assets.js}\"></script>`,\n );\n }\n }\n\n this.templateProvider.setEarlyHeadContent(\n parts.length > 0 ? `${parts.join(\"\\n\")}\\n` : \"\",\n globalHead,\n );\n\n this.log.debug(\"Early head content set\", {\n parts: parts.length,\n });\n }\n\n /**\n * Build a favicon link tag from the manifest favicon value.\n * Format is \"mimeType:/path\" (e.g., \"image/svg+xml:/favicon.svg\").\n */\n protected buildFaviconTag(favicon: string | undefined): string | undefined {\n if (!favicon) {\n return undefined;\n }\n const colonIndex = favicon.indexOf(\":\");\n if (colonIndex === -1) {\n return undefined;\n }\n const type = favicon.slice(0, colonIndex);\n const href = favicon.slice(colonIndex + 1);\n return `<link rel=\"icon\" type=\"${type}\" href=\"${href}\">`;\n }\n\n /**\n * Get the public directory path where static files are located.\n */\n protected async getPublicDirectory(): Promise<string> {\n const maybe = [\n join(process.cwd(), `dist/${this.options.publicDir}`),\n join(process.cwd(), this.options.publicDir),\n ];\n\n for (const it of maybe) {\n if (await this.fs.exists(it)) {\n return it;\n }\n }\n\n return \"\";\n }\n\n /**\n * Configure the static file server to serve files from the given root directory.\n */\n protected async configureStaticServer(root: string) {\n await this.serverStaticProvider.createStaticServer({\n root,\n cacheControl: {\n maxAge: 3600,\n immutable: true,\n },\n ...this.options.staticServer,\n });\n }\n\n /**\n * Resolve the static file pattern from page options.\n * Returns a compiled RegExp, or `false` if disabled (empty string).\n */\n protected resolveStaticFilePattern(): RegExp | false {\n const pattern = this.pageOptions.staticFilePattern;\n if (!pattern) return false;\n return new RegExp(pattern);\n }\n\n /**\n * Collect middleware from the entire parent chain + the page itself.\n * Parent middleware runs first (outermost → innermost → page).\n */\n protected collectMiddleware(page: PageRoute): Middleware[] {\n const chain: Middleware[][] = [];\n let current: PageRoute | undefined = page;\n\n while (current) {\n if (current.use?.length) {\n chain.unshift(current.use);\n }\n current = current.parent;\n }\n\n return chain.flat();\n }\n\n /**\n * Create the request handler for a page route.\n *\n * When cacheMiddleware is provided, uses a non-streaming path that renders\n * to a string so the result can be cached. Otherwise uses early HTML streaming.\n */\n protected createHandler(\n route: PageRoute,\n cacheMiddleware: Middleware[] = [],\n ): ServerHandler {\n const hasCache = cacheMiddleware.length > 0;\n const isCatchAll = route.match === \"/*\";\n const staticFilePattern = isCatchAll\n ? this.resolveStaticFilePattern()\n : false;\n\n return async (serverRequest) => {\n const { url, reply, query, params } = serverRequest;\n\n // Skip SSR for file-like URLs hitting the catch-all wildcard.\n // Bots and crawlers often probe paths like /hello.txt, /wp-login.php, etc.\n // Rendering a full React page for these is wasteful — return a plain 404 instead.\n if (staticFilePattern && staticFilePattern.test(url.pathname)) {\n reply.status = 404;\n reply.headers[\"content-type\"] = \"text/plain\";\n return \"Not Found\";\n }\n\n this.log.trace(\"Rendering page\", { name: route.name });\n\n // Initialize router state\n const state: ReactRouterState = {\n url,\n params,\n query,\n name: route.name,\n onError: () => null,\n layers: [],\n meta: {},\n head: {},\n };\n\n // Set up API links if available\n if (this.hasServerLinksProvider) {\n this.alepha.store.set(\n \"alepha.server.request.apiLinks\",\n await this.alepha.inject(ServerLinksProvider).getUserApiLinks({\n user: (serverRequest as any).user, // TODO: fix type\n authorization: serverRequest.headers.authorization,\n }),\n );\n }\n\n // Check access permissions (walk up the parent chain)\n let target: PageRoute | undefined = route;\n while (target) {\n if (target.can && !target.can()) {\n this.log.warn(\n `Access to page '${route.name}' is forbidden by can() check on '${target.name}'`,\n );\n reply.status = 403;\n reply.headers[\"content-type\"] = \"text/plain\";\n return \"Forbidden\";\n }\n target = target.parent;\n }\n\n await this.alepha.events.emit(\"react:server:render:begin\", {\n request: serverRequest,\n state,\n });\n\n // Apply SSR headers early\n Object.assign(reply.headers, this.SSR_HEADERS);\n\n if (hasCache) {\n // When $cache middleware is present, render to string so the result\n // is serializable. Streaming is not compatible with $cache since\n // ReadableStream cannot be serialized/deserialized.\n const renderFn = async (\n _url: string,\n ): Promise<{ html: string; redirect?: string }> => {\n const { redirect, reactStream } = await this.renderPage(route, state);\n if (redirect) {\n return { redirect, html: \"\" };\n }\n const htmlStream = this.templateProvider.createHtmlStream(\n reactStream!,\n state,\n { hydration: true },\n );\n return { html: await this.streamToString(htmlStream) };\n };\n\n const result = await new PipelineHandler(renderFn, cacheMiddleware).run(\n url.href,\n );\n\n if (result.redirect) {\n reply.status = 302;\n reply.headers.location = result.redirect;\n return;\n }\n\n route.onServerResponse?.(serverRequest);\n reply.body = result.html;\n return;\n }\n\n // Resolve global head for early streaming (htmlAttributes only)\n const globalHead = this.serverHeadProvider.resolveGlobalHead();\n\n // Create optimized HTML stream with early head\n const htmlStream = this.templateProvider.createEarlyHtmlStream(\n globalHead,\n async () => {\n // === ASYNC WORK (runs while early head is being sent) ===\n const result = await this.renderPage(route, state);\n\n if (result.redirect) {\n // Return redirect URL - template provider will inject meta refresh\n // since HTTP headers have already been sent\n return { redirect: result.redirect };\n }\n\n return { state, reactStream: result.reactStream! };\n },\n {\n hydration: true,\n state,\n onError: (error) => {\n if (error instanceof Redirection) {\n this.log.debug(\"Streaming resulted in redirection\", {\n redirect: error.redirect,\n });\n // Can't do redirect after streaming started - already handled above\n } else {\n // disable logging here, it's noisy and duplicate\n // this.log.error(\"HTML stream error\", error);\n }\n },\n },\n );\n\n this.log.trace(\"Page streaming started (early head optimization)\");\n route.onServerResponse?.(serverRequest);\n reply.body = htmlStream.pipeThrough(\n new TransformStream({\n flush: () => {\n this.log.info(\"Page streaming completed\", { name: route.name });\n },\n }),\n );\n };\n }\n\n // ---------------------------------------------------------------------------\n // Core rendering logic - shared between SSR handler and static prerendering\n // ---------------------------------------------------------------------------\n\n /**\n * Core page rendering logic shared between SSR handler and static prerendering.\n *\n * Handles:\n * - Layer resolution (loaders)\n * - Redirect detection\n * - Head content filling\n * - Preload link collection\n * - React stream rendering\n *\n * @param route - The page route to render\n * @param state - The router state\n * @returns Render result with redirect or React stream\n */\n protected async renderPage(\n route: PageRoute,\n state: ReactRouterState,\n ): Promise<{ redirect?: string; reactStream?: ReadableStream<Uint8Array> }> {\n // Resolve page layers (loaders)\n const { redirect } = await this.pageApi.createLayers(route, state);\n if (redirect) {\n this.log.debug(\"Resolver resulted in redirection\", { redirect });\n return { redirect };\n }\n\n // Fill head from route config\n this.serverHeadProvider.fillHead(state);\n\n // Collect and inject modulepreload links for page-specific chunks\n const preloadLinks = this.ssrManifestProvider.collectPreloadLinks(route);\n if (preloadLinks.length > 0) {\n state.head ??= {};\n state.head.link = [...(state.head.link ?? []), ...preloadLinks];\n }\n\n // Render React to stream\n\n const element = this.pageApi.root(state);\n this.alepha.store.set(\"alepha.react.router.state\", state);\n\n const reactStream = await renderToReadableStream(element, {\n onError: (error: unknown) => {\n if (error instanceof Redirection) {\n this.log.warn(\"Redirect during streaming ignored\", {\n redirect: error.redirect,\n });\n } else {\n // disable logging here, it's noisy and duplicate\n // this.log.error(\"Streaming render error\", error);\n }\n },\n });\n\n return { reactStream };\n }\n\n // ---------------------------------------------------------------------------\n // Testing utilities - kept for backwards compatibility with tests\n // ---------------------------------------------------------------------------\n\n /**\n * For testing purposes, renders a page to HTML string.\n * Uses the same streaming code path as production, then collects to string.\n *\n * @param name - Page name to render\n * @param options - Render options (params, query, html, hydration)\n */\n public async render(\n name: string,\n options: PagePrimitiveRenderOptions = {},\n ): Promise<PagePrimitiveRenderResult> {\n const page = this.pageApi.page(name);\n const url = new URL(this.pageApi.url(name, options));\n const state: ReactRouterState = {\n url,\n params: options.params ?? {},\n query: options.query ?? {},\n onError: () => null,\n layers: [],\n meta: {},\n head: {},\n };\n\n this.log.trace(\"Rendering\", { url });\n\n await this.alepha.events.emit(\"react:server:render:begin\", { state });\n\n // Render page and collect the stream into a serializable result.\n // This must happen inside the middleware pipeline so that $cache\n // wraps a function returning { html, redirect? } — not a ReadableStream.\n // The URL string is passed as argument so middleware like $cache can\n // derive a unique cache key per URL (params + query).\n const renderFn = async (\n _url: string,\n ): Promise<{\n html: string;\n redirect?: string;\n }> => {\n const { redirect, reactStream } = await this.renderPage(page, state);\n if (redirect) {\n return { redirect, html: \"\" };\n }\n\n if (!options.html) {\n return { html: await this.streamToString(reactStream!) };\n }\n\n const htmlStream = this.templateProvider.createHtmlStream(\n reactStream!,\n state,\n { hydration: options.hydration ?? true },\n );\n return { html: await this.streamToString(htmlStream) };\n };\n\n const allMiddleware = this.collectMiddleware(page);\n const result = allMiddleware.length\n ? await new PipelineHandler(renderFn, allMiddleware).run(url.href)\n : await renderFn(url.href);\n\n if (result.redirect) {\n return { state, html: \"\", redirect: result.redirect };\n }\n\n await this.alepha.events.emit(\"react:server:render:end\", {\n state,\n html: result.html,\n });\n\n return { state, html: result.html };\n }\n\n /**\n * Collect a ReadableStream into a string.\n */\n protected async streamToString(\n stream: ReadableStream<Uint8Array>,\n ): Promise<string> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n const chunks: string[] = [];\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(decoder.decode(value, { stream: true }));\n }\n chunks.push(decoder.decode()); // Flush remaining\n } finally {\n reader.releaseLock();\n }\n\n return chunks.join(\"\");\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst envSchema = t.object({\n REACT_SSR_ENABLED: t.optional(\n t.boolean({\n description:\n \"Enable or disable server-side rendering (SSR) for React pages. When set to false, pages are rendered client-side only.\",\n }),\n ),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n interface State {\n \"alepha.react.server.ssr\"?: boolean;\n }\n}\n\n/**\n * React server provider configuration atom\n */\n/**\n * Default pattern matching file-like URLs (e.g. /hello.txt, /wp-login.php).\n * Matches paths whose last segment contains a dot followed by 1-10 alphanumeric characters.\n */\nexport const DEFAULT_STATIC_FILE_PATTERN = \"\\\\.[a-zA-Z0-9]{1,10}$\";\n\nexport const reactServerOptions = $atom({\n name: \"alepha.react.server.options\",\n schema: t.object({\n publicDir: t.string(),\n staticServer: t.object({\n disabled: t.boolean(),\n path: t.string({\n description: \"URL path where static files will be served.\",\n }),\n }),\n }),\n default: {\n publicDir: \"public\",\n staticServer: {\n disabled: false,\n path: \"/\",\n },\n },\n});\n\nexport type ReactServerProviderOptions = Static<\n typeof reactServerOptions.schema\n>;\n\ndeclare module \"alepha\" {\n interface State {\n [reactServerOptions.key]: ReactServerProviderOptions;\n }\n}\n","import { $inject, AlephaError } from \"alepha\";\nimport { ServerProvider } from \"alepha/server\";\nimport type {\n PagePrimitiveRenderOptions,\n PagePrimitiveRenderResult,\n} from \"../primitives/$page.ts\";\nimport { ReactServerProvider } from \"../providers/ReactServerProvider.ts\";\nimport { ReactServerTemplateProvider } from \"../providers/ReactServerTemplateProvider.ts\";\nimport { ReactPageService } from \"./ReactPageService.ts\";\n\n/**\n * $page methods for server-side.\n */\nexport class ReactPageServerService extends ReactPageService {\n protected readonly reactServerProvider = $inject(ReactServerProvider);\n protected readonly templateProvider = $inject(ReactServerTemplateProvider);\n protected readonly serverProvider = $inject(ServerProvider);\n\n public async render(\n name: string,\n options: PagePrimitiveRenderOptions = {},\n ): Promise<PagePrimitiveRenderResult> {\n return this.reactServerProvider.render(name, options);\n }\n\n public async fetch(\n pathname: string,\n options: PagePrimitiveRenderOptions = {},\n ): Promise<{\n html: string;\n response: Response;\n }> {\n const response = await fetch(`${this.serverProvider.hostname}/${pathname}`);\n\n const html = await response.text();\n if (options?.html) {\n return { html, response };\n }\n\n // take only text inside the root div\n const rootContent = this.templateProvider.extractRootContent(html);\n if (rootContent !== undefined) {\n return { html: rootContent, response };\n }\n\n throw new AlephaError(\"Invalid HTML response\");\n }\n}\n","import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { BrowserHeadProvider } from \"alepha/react/head\";\nimport { type Route, RouterProvider } from \"alepha/router\";\nimport { ForbiddenError } from \"alepha/server\";\nimport { createElement, type ReactNode } from \"react\";\nimport NotFoundPage from \"../components/NotFound.tsx\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport {\n isPageRoute,\n type PageRoute,\n type PageRouteEntry,\n type PreviousLayerData,\n ReactPageProvider,\n type ReactRouterState,\n} from \"./ReactPageProvider.ts\";\n\nexport interface BrowserRoute extends Route {\n page: PageRoute;\n}\n\n/**\n * Implementation of AlephaRouter for React in browser environment.\n */\nexport class ReactBrowserRouterProvider extends RouterProvider<BrowserRoute> {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly pageApi = $inject(ReactPageProvider);\n protected readonly browserHeadProvider = $inject(BrowserHeadProvider);\n\n public add(entry: PageRouteEntry) {\n this.pageApi.add(entry);\n }\n\n protected readonly configure = $hook({\n on: \"configure\",\n handler: async () => {\n for (const page of this.pageApi.getPages()) {\n // mount only if a view is provided\n if (page.component || page.lazy || page.redirect) {\n this.push({\n path: page.match,\n page,\n });\n }\n }\n },\n });\n\n public async transition(\n url: URL,\n previous: PreviousLayerData[] = [],\n meta = {},\n isStale: () => boolean = () => false,\n ): Promise<string | void> {\n const { pathname, search } = url;\n\n const entry: Partial<ReactRouterState> = {\n url,\n query: {},\n params: {},\n layers: [],\n onError: () => null,\n meta,\n };\n\n const state = entry as ReactRouterState;\n\n // Emit both action and transition events\n await this.alepha.events.emit(\"react:action:begin\", {\n type: \"transition\",\n });\n await this.alepha.events.emit(\"react:transition:begin\", {\n previous: this.alepha.store.get(\"alepha.react.router.state\")!,\n state,\n });\n\n try {\n const { route, params } = this.match(pathname);\n\n const query: Record<string, string> = {};\n if (search) {\n for (const [key, value] of new URLSearchParams(search).entries()) {\n query[key] = String(value);\n }\n }\n\n if (route?.page.can) {\n const canAccess = route.page.can();\n if (!canAccess) {\n throw new ForbiddenError(\"Access denied to this page.\");\n }\n }\n\n state.name = route?.page.name;\n state.query = query;\n state.params = params ?? {};\n\n if (isPageRoute(route)) {\n const { redirect } = await this.pageApi.createLayers(\n route.page,\n state,\n previous,\n );\n // A newer navigation already won — bail before committing or\n // emitting any further events. The caller (ReactBrowserProvider)\n // also re-checks staleness, but stopping here avoids running\n // success hooks for a transition the user no longer wants.\n if (isStale()) {\n return;\n }\n if (redirect) {\n return redirect;\n }\n }\n\n if (state.layers.length === 0) {\n state.layers.push({\n name: \"not-found\",\n element: createElement(NotFoundPage),\n index: 0,\n path: \"/\",\n });\n }\n\n await this.alepha.events.emit(\"react:action:success\", {\n type: \"transition\",\n });\n await this.alepha.events.emit(\"react:transition:success\", { state });\n } catch (e) {\n // If we were superseded mid-flight, swallow the error: the user has\n // already moved on, and an error UI for an abandoned page would\n // overwrite the newer page they actually want.\n if (isStale()) {\n return;\n }\n\n this.log.error(\"Transition has failed\", e);\n\n let element: ReactNode | undefined;\n try {\n const result = state.onError(e as Error, state);\n if (result != null && !(result instanceof Redirection)) {\n element = result as ReactNode;\n }\n } catch {\n // error handler itself failed, fall through to default\n }\n\n state.layers = [\n {\n name: \"error\",\n element: element ?? this.pageApi.renderError(e as Error),\n index: 0,\n path: \"/\",\n },\n ];\n\n await this.alepha.events.emit(\"react:action:error\", {\n type: \"transition\",\n error: e as Error,\n });\n await this.alepha.events.emit(\"react:transition:error\", {\n error: e as Error,\n state,\n });\n }\n\n // Final supersession check before any side effects (onLeave/onEnter,\n // store mutation, head rewrite). Stale transitions must be a complete\n // no-op from this point on.\n if (isStale()) {\n return;\n }\n\n // [feature]: local hook for leaving a page\n if (previous) {\n for (let i = 0; i < previous.length; i++) {\n const layer = previous[i];\n if (state.layers[i]?.name !== layer.name && layer.name !== \"error\") {\n this.pageApi.page(layer.name)?.onLeave?.();\n }\n }\n }\n\n // [feature]: local hook for entering a page\n for (let i = 0; i < state.layers.length; i++) {\n const layer = state.layers[i];\n if (previous?.[i]?.name !== layer.name && layer.name !== \"error\") {\n this.pageApi.page(layer.name)?.onEnter?.();\n }\n }\n\n this.alepha.store.set(\"alepha.react.router.state\", state);\n\n await this.alepha.events.emit(\"react:action:end\", {\n type: \"transition\",\n });\n await this.alepha.events.emit(\"react:transition:end\", {\n state,\n });\n\n // Fill and render head from route configurations\n this.browserHeadProvider.fillAndRenderHead(state);\n }\n\n public root(state: ReactRouterState): ReactNode {\n return this.pageApi.root(state);\n }\n}\n","import {\n $atom,\n $hook,\n $inject,\n $state,\n Alepha,\n type State,\n type Static,\n t,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { BrowserHeadProvider } from \"alepha/react/head\";\nimport { LinkProvider } from \"alepha/server/links\";\nimport type { RouterPushOptions } from \"../services/ReactRouter.ts\";\nimport { ReactBrowserRouterProvider } from \"./ReactBrowserRouterProvider.ts\";\nimport type {\n PreviousLayerData,\n ReactRouterState,\n} from \"./ReactPageProvider.ts\";\n\nexport type { RouterPushOptions } from \"../services/ReactRouter.ts\";\n\n/**\n * React browser renderer configuration atom\n */\nexport const reactBrowserOptions = $atom({\n name: \"alepha.react.browser.options\",\n schema: t.object({\n scrollRestoration: t.enum([\"top\", \"manual\"]), // TODO: must be per page?\n }),\n default: {\n scrollRestoration: \"top\" as const,\n },\n});\n\nexport type ReactBrowserRendererOptions = Static<\n typeof reactBrowserOptions.schema\n>;\n\ndeclare module \"alepha\" {\n interface State {\n [reactBrowserOptions.key]: ReactBrowserRendererOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class ReactBrowserProvider {\n protected readonly log = $logger();\n protected readonly client = $inject(LinkProvider);\n protected readonly alepha = $inject(Alepha);\n protected readonly router = $inject(ReactBrowserRouterProvider);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly browserHeadProvider = $inject(BrowserHeadProvider);\n\n protected readonly options = $state(reactBrowserOptions);\n\n public get rootId() {\n return \"root\";\n }\n\n protected getRootElement() {\n const root = this.document.getElementById(this.rootId);\n if (root) {\n return root;\n }\n\n const div = this.document.createElement(\"div\");\n div.id = this.rootId;\n\n this.document.body.prepend(div);\n\n return div;\n }\n\n public transitioning?: {\n to: string;\n from?: string;\n };\n\n /**\n * Monotonic counter used to detect stale (superseded) transitions.\n *\n * Each call to `render()` captures `++this.transitionId` and any\n * subsequent `render()` invalidates older in-flight transitions.\n * This prevents a slow page from racing past a newer navigation\n * (e.g. user clicks /pageA which has a 2s loader, then clicks /pageB\n * — pageB must remain the committed page).\n */\n protected transitionId = 0;\n\n public get state(): ReactRouterState {\n return this.alepha.store.get(\"alepha.react.router.state\")!;\n }\n\n /**\n * Accessor for Document DOM API.\n */\n public get document() {\n return window.document;\n }\n\n /**\n * Accessor for History DOM API.\n */\n public get history() {\n return window.history;\n }\n\n /**\n * Accessor for Location DOM API.\n */\n public get location() {\n return window.location;\n }\n\n public get base() {\n const base = import.meta.env?.BASE_URL;\n if (!base || base === \"/\") {\n return \"\";\n }\n\n return base;\n }\n\n public get url(): string {\n const url = this.location.pathname + this.location.search;\n if (this.base) {\n return url.replace(this.base, \"\");\n }\n return url;\n }\n\n public pushState(path: string, replace?: boolean) {\n const url = this.base + path;\n\n if (replace) {\n this.history.replaceState({}, \"\", url);\n } else {\n this.history.pushState({}, \"\", url);\n }\n }\n\n public async invalidate(props?: Record<string, any>) {\n const previous: PreviousLayerData[] = [];\n\n this.log.trace(\"Invalidating layers\");\n\n if (props) {\n const [key] = Object.keys(props);\n const value = props[key];\n\n for (const layer of this.state.layers) {\n if (layer.props?.[key]) {\n previous.push({\n ...layer,\n props: {\n ...layer.props,\n [key]: value,\n },\n });\n break;\n }\n previous.push(layer);\n }\n }\n\n await this.render({ previous });\n }\n\n public async push(\n url: string,\n options: RouterPushOptions = {},\n ): Promise<void> {\n this.log.trace(`Going to ${url}`, {\n url,\n options,\n });\n\n const myTransitionId = ++this.transitionId;\n\n await this.render({\n url,\n previous: options.force ? [] : this.state.layers,\n meta: options.meta,\n transitionId: myTransitionId,\n });\n\n // A newer navigation has superseded us — bail out without touching\n // history, otherwise we'd push a duplicate/stale entry.\n if (myTransitionId !== this.transitionId) {\n return;\n }\n\n // when redirecting in browser\n if (this.state.url.pathname + this.state.url.search !== url) {\n this.pushState(this.state.url.pathname + this.state.url.search);\n return;\n }\n\n this.pushState(url, options.replace);\n }\n\n protected async render(options: RouterRenderOptions = {}): Promise<void> {\n const myTransitionId = options.transitionId ?? ++this.transitionId;\n const previous = options.previous ?? this.state.layers;\n const url = options.url ?? this.url;\n const start = this.dateTimeProvider.now();\n\n this.transitioning = {\n to: url,\n from: this.state?.url.pathname,\n };\n\n this.log.debug(\"Transitioning...\", {\n to: url,\n });\n\n const isStale = () => this.transitionId !== myTransitionId;\n\n const redirect = await this.router.transition(\n new URL(`http://localhost${url}`),\n previous,\n options.meta,\n isStale,\n );\n\n // A newer navigation has superseded us between the time we awaited\n // transition() and now. Drop everything: don't follow redirects, don't\n // log success, don't clear `transitioning` (the newer render owns it).\n if (isStale()) {\n this.log.debug(\"Transition superseded — discarding stale result\", {\n to: url,\n });\n return;\n }\n\n if (redirect) {\n this.log.info(\"Redirecting to\", {\n redirect,\n });\n\n // if redirect is an absolute URL, use window.location.href (full page reload)\n if (redirect.startsWith(\"http\")) {\n window.location.href = redirect;\n } else {\n // if redirect is a relative URL, use render() (single page app)\n return await this.render({ url: redirect });\n }\n }\n\n const ms = this.dateTimeProvider.now().diff(start);\n this.log.info(`Transition OK [${ms}ms]`, this.transitioning);\n\n this.transitioning = undefined;\n }\n\n /**\n * Get embedded layers from the server.\n */\n protected getHydrationState(): ReactHydrationState | undefined {\n try {\n const el = this.document.getElementById(\"__ssr\");\n if (el?.textContent) {\n return JSON.parse(el.textContent) as ReactHydrationState;\n }\n } catch (error) {\n console.error(error);\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n protected readonly onTransitionEnd = $hook({\n on: \"react:transition:end\",\n handler: () => {\n if (\n this.options.scrollRestoration === \"top\" &&\n typeof window !== \"undefined\" &&\n !this.alepha.isTest()\n ) {\n this.log.trace(\"Restoring scroll position to top\");\n window.scrollTo(0, 0);\n }\n },\n });\n\n public readonly ready = $hook({\n on: \"ready\",\n handler: async () => {\n const hydration = this.getHydrationState();\n const previous = hydration?.[\"alepha.react.router.layers\"] ?? [];\n\n if (hydration) {\n // low budget, but works for now\n for (const [key, value] of Object.entries(hydration)) {\n if (key !== \"alepha.react.router.layers\") {\n this.alepha.set(key as keyof State, value);\n }\n }\n }\n\n await this.render({ previous });\n\n const element = this.router.root(this.state);\n\n await this.alepha.events.emit(\"react:browser:render\", {\n element,\n root: this.getRootElement(),\n hydration,\n state: this.state,\n });\n\n window.addEventListener(\"popstate\", () => {\n // when you update silently queryParams or hash, skip rendering\n // if you want to force a rendering, use #go()\n if (this.base + this.state.url.pathname === this.location.pathname) {\n return;\n }\n\n this.log.debug(\"Popstate event triggered - rendering new state\", {\n url: this.location.pathname + this.location.search,\n });\n\n this.render();\n });\n },\n });\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type ReactHydrationState = {\n \"alepha.react.router.layers\"?: Array<PreviousLayerData>;\n} & {\n [key: string]: any;\n};\n\nexport interface RouterRenderOptions {\n url?: string;\n previous?: PreviousLayerData[];\n meta?: Record<string, any>;\n /**\n * Transition id used to detect supersession by a newer navigation.\n * When omitted, render() allocates a fresh id internally.\n */\n transitionId?: number;\n}\n","import { $inject, Alepha, AlephaError } from \"alepha\";\nimport type { PagePrimitive } from \"../primitives/$page.ts\";\nimport { ReactBrowserProvider } from \"../providers/ReactBrowserProvider.ts\";\nimport {\n type AnchorProps,\n ReactPageProvider,\n type ReactRouterState,\n} from \"../providers/ReactPageProvider.ts\";\n\nexport interface RouterPushOptions {\n replace?: boolean;\n params?: Record<string, string>;\n query?: Record<string, string>;\n meta?: Record<string, any>;\n /**\n * Recreate the whole page, ignoring the current state.\n */\n force?: boolean;\n}\n\n/**\n * Friendly browser router API.\n *\n * Can be safely used server-side, but most methods will be no-op.\n */\nexport class ReactRouter<T extends object> {\n protected readonly alepha = $inject(Alepha);\n protected readonly pageApi = $inject(ReactPageProvider);\n\n public get state(): ReactRouterState {\n return this.alepha.store.get(\"alepha.react.router.state\")!;\n }\n\n public get pages() {\n return this.pageApi.getPages();\n }\n\n public get concretePages() {\n return this.pageApi.getConcretePages();\n }\n\n public get browser(): ReactBrowserProvider | undefined {\n if (this.alepha.isBrowser()) {\n return this.alepha.inject(ReactBrowserProvider);\n }\n // server-side\n return undefined;\n }\n\n public isActive(\n href: string,\n options: {\n startWith?: boolean;\n } = {},\n ): boolean {\n const current = this.state.url.pathname;\n let isActive =\n current === href || current === `${href}/` || `${current}/` === href;\n\n if (options.startWith && !isActive) {\n isActive = current.startsWith(href);\n }\n\n return isActive;\n }\n\n public node(\n name: keyof VirtualRouter<T> | string,\n config: {\n params?: Record<string, any>;\n query?: Record<string, any>;\n } = {},\n ): any {\n // TODO: improve typing (or just remove this method)\n const page = this.pageApi.page(name as string);\n if (!page.lazy && !page.component) {\n return {\n ...page,\n label: page.label ?? page.name,\n children: undefined,\n };\n }\n\n return {\n ...page,\n label: page.label ?? page.name,\n href: this.path(name, config),\n children: undefined,\n };\n }\n\n public path(\n name: keyof VirtualRouter<T> | string,\n config: {\n params?: Record<string, any>;\n query?: Record<string, any>;\n } = {},\n ): string {\n return this.pageApi.pathname(name as string, {\n params: {\n ...this.state?.params,\n ...config.params,\n },\n query: config.query,\n });\n }\n\n /**\n * Reload the current page.\n * This is equivalent to calling `go()` with the current pathname and search.\n */\n public async reload() {\n if (!this.browser) {\n return;\n }\n\n await this.push(this.location.pathname + this.location.search, {\n replace: true,\n force: true,\n });\n }\n\n public getURL(): URL {\n if (!this.browser) {\n return this.state.url;\n }\n\n return new URL(this.location.href);\n }\n\n public get location(): Location {\n if (!this.browser) {\n throw new AlephaError(\"Browser is required\");\n }\n\n return this.browser.location;\n }\n\n public get current(): ReactRouterState {\n return this.state;\n }\n\n public get pathname(): string {\n return this.state.url.pathname;\n }\n\n public get query(): Record<string, string> {\n const query: Record<string, string> = {};\n\n for (const [key, value] of new URLSearchParams(\n this.state.url.search,\n ).entries()) {\n query[key] = String(value);\n }\n\n return query;\n }\n\n public async back() {\n this.browser?.history.back();\n }\n\n public async forward() {\n this.browser?.history.forward();\n }\n\n public async invalidate(props?: Record<string, any>) {\n await this.browser?.invalidate(props);\n }\n\n public async push(path: string, options?: RouterPushOptions): Promise<void>;\n public async push(\n path: keyof VirtualRouter<T>,\n options?: RouterPushOptions,\n ): Promise<void>;\n public async push(\n path: string | keyof VirtualRouter<T>,\n options?: RouterPushOptions,\n ): Promise<void> {\n for (const page of this.pages) {\n if (page.name === path) {\n await this.browser?.push(\n this.path(path as keyof VirtualRouter<T>, options),\n options,\n );\n return;\n }\n }\n\n await this.browser?.push(path as string, options);\n }\n\n public anchor(path: string, options?: RouterPushOptions): AnchorProps;\n public anchor(\n path: keyof VirtualRouter<T>,\n options?: RouterPushOptions,\n ): AnchorProps;\n public anchor(\n path: string | keyof VirtualRouter<T>,\n options: RouterPushOptions = {},\n ): AnchorProps {\n let href = path as string;\n\n for (const page of this.pages) {\n if (page.name === path) {\n href = this.path(path as keyof VirtualRouter<T>, options);\n break;\n }\n }\n\n return {\n href: this.base(href),\n onClick: (ev: any) => {\n ev.stopPropagation();\n ev.preventDefault();\n\n this.push(href, options).catch(console.error);\n },\n };\n }\n\n /**\n * Prepend the base URL to the given path.\n */\n public base(path: string): string {\n const base = import.meta.env?.BASE_URL;\n if (!base || base === \"/\") {\n return path;\n }\n\n return base + path;\n }\n\n /**\n * Set query params.\n *\n * @param record\n * @param options\n */\n public setQueryParams(\n record:\n | Record<string, any>\n | ((queryParams: Record<string, any>) => Record<string, any>),\n options: {\n /**\n * If true, this will add a new entry to the history stack.\n */\n push?: boolean;\n } = {},\n ) {\n const func = typeof record === \"function\" ? record : () => record;\n const search = new URLSearchParams(func(this.query)).toString();\n const path = search ? `${this.pathname}?${search}` : this.pathname;\n const state = this.base(path);\n\n if (options.push) {\n window.history.pushState({}, \"\", state);\n } else {\n window.history.replaceState({}, \"\", state);\n }\n }\n}\n\nexport type VirtualRouter<T> = {\n [K in keyof T as T[K] extends PagePrimitive ? K : never]: T[K];\n};\n","import { useInject } from \"alepha/react\";\nimport { ReactRouter } from \"../services/ReactRouter.ts\";\n\n/**\n * Use this hook to access the React Router instance.\n *\n * You can add a type parameter to specify the type of your application.\n * This will allow you to use the router in a typesafe way.\n *\n * @example\n * class App {\n * home = $page();\n * }\n *\n * const router = useRouter<App>();\n * router.push(\"home\"); // typesafe\n */\nexport const useRouter = <T extends object = any>(): ReactRouter<T> => {\n return useInject(ReactRouter<T>);\n};\n","import { type AnchorHTMLAttributes, createElement } from \"react\";\nimport { useRouter } from \"../hooks/useRouter.ts\";\n\nexport interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string;\n}\n\n/**\n * Link component for client-side navigation.\n *\n * It's a simple wrapper around an anchor (`<a>`) element using the `useRouter` hook.\n */\nconst Link = (props: LinkProps) => {\n const router = useRouter();\n\n return createElement(\n \"a\",\n { ...props, ...router.anchor(props.href) },\n props.children,\n );\n};\n\nexport default Link;\n","import { useState } from \"react\";\nimport type { AnchorProps } from \"../providers/ReactPageProvider.ts\";\nimport { useRouter } from \"./useRouter.ts\";\nimport { useRouterState } from \"./useRouterState.ts\";\n\nexport interface UseActiveOptions {\n href: string;\n startWith?: boolean;\n}\n\n/**\n * Hook to determine if a given route is active and to provide anchor props for navigation.\n * This hook refreshes on router state changes.\n */\nexport const useActive = (args: string | UseActiveOptions): UseActiveHook => {\n useRouterState();\n\n const router = useRouter();\n const [isPending, setPending] = useState(false);\n\n const options: UseActiveOptions =\n typeof args === \"string\" ? { href: args } : { ...args, href: args.href };\n const href = options.href;\n const isActive = router.isActive(href, options);\n\n return {\n isPending,\n isActive,\n anchorProps: {\n href: router.base(href),\n onClick: async (ev?: any) => {\n ev?.stopPropagation();\n ev?.preventDefault();\n if (isActive) return;\n if (isPending) return;\n\n setPending(true);\n try {\n await router.push(href);\n } finally {\n setPending(false);\n }\n },\n },\n };\n};\n\nexport interface UseActiveHook {\n isActive: boolean;\n anchorProps: AnchorProps;\n isPending: boolean;\n}\n","import type { Alepha, Static, TObject } from \"alepha\";\nimport { useAlepha } from \"alepha/react\";\nimport { useEffect, useState } from \"react\";\nimport { useRouter } from \"./useRouter.ts\";\n\n/**\n * Hook to manage query parameters in the URL using a defined schema.\n */\nexport const useQueryParams = <T extends TObject>(\n schema: T,\n options: UseQueryParamsHookOptions = {},\n): [Partial<Static<T>>, (data: Static<T>) => void] => {\n const alepha = useAlepha();\n\n const key = options.key ?? \"q\";\n const router = useRouter();\n const querystring = router.query[key];\n\n const [queryParams = {}, setQueryParams] = useState<Static<T> | undefined>(\n decode(alepha, schema, router.query[key]),\n );\n\n useEffect(() => {\n setQueryParams(decode(alepha, schema, querystring));\n }, [querystring]);\n\n return [\n queryParams,\n (queryParams: Static<T>) => {\n setQueryParams(queryParams);\n router.setQueryParams((data) => {\n return { ...data, [key]: encode(alepha, schema, queryParams) };\n });\n },\n ];\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface UseQueryParamsHookOptions {\n format?: \"base64\" | \"querystring\";\n key?: string;\n push?: boolean;\n}\n\nconst encode = (alepha: Alepha, schema: TObject, data: any) => {\n return btoa(JSON.stringify(alepha.codec.decode(schema, data)));\n};\n\nconst decode = <T extends TObject>(\n alepha: Alepha,\n schema: T,\n data: any,\n): Static<T> | undefined => {\n try {\n return alepha.codec.decode(\n schema,\n JSON.parse(atob(decodeURIComponent(data))),\n );\n } catch {\n return;\n }\n};\n","import { $module } from \"alepha\";\nimport { AlephaDateTime } from \"alepha/datetime\";\nimport { AlephaReact } from \"alepha/react\";\nimport { AlephaReactHead } from \"alepha/react/head\";\nimport { AlephaServer, type ServerRequest } from \"alepha/server\";\nimport { AlephaServerEtag } from \"alepha/server/etag\";\nimport { AlephaServerLinks } from \"alepha/server/links\";\nimport type { ReactNode } from \"react\";\nimport { $page, type PageAnimation } from \"./primitives/$page.ts\";\nimport type { ReactHydrationState } from \"./providers/ReactBrowserProvider.ts\";\nimport {\n ReactPageProvider,\n type ReactRouterState,\n} from \"./providers/ReactPageProvider.ts\";\nimport { ReactPreloadProvider } from \"./providers/ReactPreloadProvider.ts\";\nimport { ReactServerProvider } from \"./providers/ReactServerProvider.ts\";\nimport { ReactServerTemplateProvider } from \"./providers/ReactServerTemplateProvider.ts\";\nimport { SSRManifestProvider } from \"./providers/SSRManifestProvider.ts\";\nimport { ReactPageServerService } from \"./services/ReactPageServerService.ts\";\nimport { ReactPageService } from \"./services/ReactPageService.ts\";\nimport { ReactRouter } from \"./services/ReactRouter.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./index.shared.ts\";\nexport * from \"./providers/ReactBrowserProvider.ts\";\nexport * from \"./providers/ReactPageProvider.ts\";\nexport * from \"./providers/ReactPreloadProvider.ts\";\nexport * from \"./providers/ReactServerProvider.ts\";\nexport * from \"./providers/ReactServerTemplateProvider.ts\";\nexport * from \"./providers/SSRManifestProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n interface State {\n \"alepha.react.router.state\"?: ReactRouterState;\n }\n\n interface Hooks {\n /**\n * Fires when the React application is starting to be rendered on the server.\n */\n \"react:server:render:begin\": {\n request?: ServerRequest;\n state: ReactRouterState;\n };\n /**\n * Fires when the React application has been rendered on the server.\n */\n \"react:server:render:end\": {\n request?: ServerRequest;\n state: ReactRouterState;\n html: string;\n };\n // -----------------------------------------------------------------------------------------------------------------\n /**\n * Fires when the React application is being rendered on the browser.\n *\n * Note: this one is not really necessary, it's a hack because we need to isolate renderer from server code in order\n * to avoid including react-dom/client in server bundles.\n */\n \"react:browser:render\": {\n root: HTMLElement;\n element: ReactNode;\n state: ReactRouterState;\n hydration?: ReactHydrationState;\n };\n // -----------------------------------------------------------------------------------------------------------------\n // SPECIFIC: Route transitions\n /**\n * Fires when a route transition is starting.\n */\n \"react:transition:begin\": {\n previous: ReactRouterState;\n state: ReactRouterState;\n animation?: PageAnimation;\n };\n /**\n * Fires when a route transition has succeeded.\n */\n \"react:transition:success\": {\n state: ReactRouterState;\n };\n /**\n * Fires when a route transition has failed.\n */\n \"react:transition:error\": {\n state: ReactRouterState;\n error: Error;\n };\n /**\n * Fires when a route transition has completed, regardless of success or failure.\n */\n \"react:transition:end\": {\n state: ReactRouterState;\n };\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Provides declarative routing with the `$page` primitive for building type-safe React routes.\n *\n * This module enables:\n * - URL pattern matching with parameters (e.g., `/users/:id`)\n * - Nested routing with parent-child relationships\n * - Type-safe URL parameter and query string validation\n * - Server-side data fetching with the `loader` function\n * - Lazy loading and code splitting\n * - Page animations and error handling\n *\n * @see {@link $page}\n * @module alepha.react.router\n */\nexport const AlephaReactRouter = $module({\n name: \"alepha.react.router\",\n primitives: [$page],\n services: [\n ReactPageProvider,\n ReactPageService,\n ReactPreloadProvider,\n ReactRouter,\n ReactServerProvider,\n ReactServerTemplateProvider,\n SSRManifestProvider,\n ReactPageServerService,\n ],\n register: (alepha) =>\n alepha\n .with(AlephaReact)\n .with(AlephaReactHead)\n .with(AlephaDateTime)\n .with(AlephaServer)\n .with(AlephaServerEtag)\n .with(AlephaServerLinks)\n .with({\n provide: ReactPageService,\n use: ReactPageServerService,\n })\n .with(SSRManifestProvider)\n .with(ReactServerTemplateProvider)\n .with(ReactPreloadProvider)\n .with(ReactServerProvider)\n .with(ReactPageProvider)\n .with(ReactRouter),\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["NotFoundPage","NestedView","NotFoundPage"],"sources":["../../../src/react/router/constants/PAGE_PRELOAD_KEY.ts","../../../src/react/router/services/ReactPageService.ts","../../../src/react/router/primitives/$page.ts","../../../src/react/router/hooks/useRouterState.ts","../../../src/react/router/components/ErrorViewer.tsx","../../../src/react/router/contexts/RouterLayerContext.ts","../../../src/react/router/errors/Redirection.ts","../../../src/react/router/components/NestedView.tsx","../../../src/react/router/components/NotFound.tsx","../../../src/react/router/providers/ReactPageProvider.ts","../../../src/react/router/atoms/ssrManifestAtom.ts","../../../src/react/router/providers/SSRManifestProvider.ts","../../../src/react/router/providers/ReactPreloadProvider.ts","../../../src/react/router/providers/ReactServerTemplateProvider.ts","../../../src/react/router/providers/ReactServerProvider.ts","../../../src/react/router/services/ReactPageServerService.ts","../../../src/react/router/providers/ReactBrowserRouterProvider.ts","../../../src/react/router/providers/ReactBrowserProvider.ts","../../../src/react/router/services/ReactRouter.ts","../../../src/react/router/hooks/useRouter.ts","../../../src/react/router/components/Link.tsx","../../../src/react/router/hooks/useActive.ts","../../../src/react/router/hooks/useQueryParams.ts","../../../src/react/router/index.ts"],"sourcesContent":["/**\n * Symbol key for SSR module preloading path.\n * Using Symbol.for() allows the Vite plugin to inject this at build time.\n * @internal\n */\nexport const PAGE_PRELOAD_KEY = Symbol.for(\"alepha.page.preload\");\n","import { AlephaError } from \"alepha\";\nimport type {\n PagePrimitiveRenderOptions,\n PagePrimitiveRenderResult,\n} from \"../primitives/$page.ts\";\n\n/**\n * $page methods interface.\n */\nexport abstract class ReactPageService {\n public fetch(\n pathname: string,\n options: PagePrimitiveRenderOptions = {},\n ): Promise<{\n html: string;\n response: Response;\n }> {\n throw new AlephaError(\"Fetch is not available for this environment.\");\n }\n\n public render(\n name: string,\n options: PagePrimitiveRenderOptions = {},\n ): Promise<PagePrimitiveRenderResult> {\n throw new AlephaError(\"Render is not available for this environment.\");\n }\n}\n","import {\n $inject,\n type Async,\n createPrimitive,\n KIND,\n type Middleware,\n OPTIONS,\n Primitive,\n type Static,\n type TSchema,\n} from \"alepha\";\nimport { $cache } from \"alepha/cache\";\nimport type { ClientOnlyProps } from \"alepha/react\";\nimport type { Head } from \"alepha/react/head\";\nimport type { ServerRequest } from \"alepha/server\";\nimport type { FC, ReactNode } from \"react\";\nimport { PAGE_PRELOAD_KEY } from \"../constants/PAGE_PRELOAD_KEY.ts\";\nimport type { Redirection } from \"../errors/Redirection.ts\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\nimport { ReactPageService } from \"../services/ReactPageService.ts\";\n\n/**\n * Main primitive for defining a React route in the application.\n *\n * The $page primitive is the core building block for creating type-safe, SSR-enabled React routes.\n * It provides a declarative way to define pages with powerful features:\n *\n * **Routing & Navigation**\n * - URL pattern matching with parameters (e.g., `/users/:id`)\n * - Nested routing with parent-child relationships\n * - Type-safe URL parameter and query string validation\n *\n * **Data Loading**\n * - Server-side data fetching with the `loader` function\n * - Automatic serialization and hydration for SSR\n * - Access to request context, URL params, and parent data\n *\n * **Component Loading**\n * - Direct component rendering or lazy loading for code splitting\n * - Client-only rendering when browser APIs are needed\n * - Automatic fallback handling during hydration\n *\n * **Performance Optimization**\n * - Static generation for pre-rendered pages at build time\n * - Server-side caching with configurable TTL and providers\n * - Code splitting through lazy component loading\n *\n * **Error Handling**\n * - Custom error handlers with support for redirects\n * - Hierarchical error handling (child → parent)\n * - HTTP status code handling (404, 401, etc.)\n *\n * @example Simple page with data fetching\n * ```typescript\n * const userProfile = $page({\n * path: \"/users/:id\",\n * schema: {\n * params: t.object({ id: t.integer() }),\n * query: t.object({ tab: t.optional(t.text()) })\n * },\n * loader: async ({ params }) => {\n * const user = await userApi.getUser(params.id);\n * return { user };\n * },\n * lazy: () => import(\"./UserProfile.tsx\")\n * });\n * ```\n *\n * @example Nested routing with error handling\n * ```typescript\n * const projectSection = $page({\n * path: \"/projects/:id\",\n * children: () => [projectBoard, projectSettings],\n * loader: async ({ params }) => {\n * const project = await projectApi.get(params.id);\n * return { project };\n * },\n * errorHandler: (error) => {\n * if (HttpError.is(error, 404)) {\n * return <ProjectNotFound />;\n * }\n * }\n * });\n * ```\n *\n * @example Static generation with caching\n * ```typescript\n * const blogPost = $page({\n * path: \"/blog/:slug\",\n * static: {\n * entries: posts.map(p => ({ params: { slug: p.slug } }))\n * },\n * loader: async ({ params }) => {\n * const post = await loadPost(params.slug);\n * return { post };\n * }\n * });\n * ```\n */\nexport const $page = <\n TConfig extends PageConfigSchema = PageConfigSchema,\n TProps extends object = TPropsDefault,\n TPropsParent extends object = TPropsParentDefault,\n>(\n options: PagePrimitiveOptions<TConfig, TProps, TPropsParent>,\n): PagePrimitive<TConfig, TProps, TPropsParent> => {\n return createPrimitive(PagePrimitive<TConfig, TProps, TPropsParent>, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface PagePrimitiveOptions<\n TConfig extends PageConfigSchema = PageConfigSchema,\n TProps extends object = TPropsDefault,\n TPropsParent extends object = TPropsParentDefault,\n> {\n /**\n * Identifier name for the page. Must be unique.\n *\n * @default Primitive key\n */\n name?: string;\n\n /**\n * Add a pathname to the page.\n *\n * Pathname can contain parameters, like `/post/:slug`.\n *\n * @default \"\"\n */\n path?: string;\n\n /**\n * Add an input schema to define:\n * - `params`: parameters from the pathname.\n * - `query`: query parameters from the URL.\n */\n schema?: TConfig;\n\n /**\n * Middleware to apply to the loader function.\n * Works the same as `use` on `$action` and `$job`.\n *\n * @example\n * ```ts\n * dashboard = $page({\n * use: [$cache({ ttl: [5, \"minutes\"] })],\n * loader: async ({ params }) => this.dashboardService.getData(),\n * lazy: () => import(\"./Dashboard.tsx\"),\n * });\n * ```\n */\n use?: Middleware[];\n\n /**\n * Load data before rendering the page.\n *\n * This function receives\n * - the request context (params, query, etc.)\n * - the parent props (if page has a parent)\n *\n * > In SSR, the returned data will be serialized and sent to the client, then reused during the client-side hydration.\n *\n * Loader can be stopped by throwing an error, which will be handled by the `errorHandler` function.\n * It's common to throw a `NotFoundError` to display a 404 page.\n *\n * RedirectError can be thrown to redirect the user to another page.\n */\n loader?: (context: PageLoader<TConfig, TPropsParent>) => Async<TProps>;\n\n /**\n * Default props to pass to the component when rendering the page.\n *\n * Resolved props from the `resolve` function will override these default props.\n */\n props?: () => Partial<TProps>;\n\n /**\n * The component to render when the page is loaded.\n *\n * If `lazy` is defined, this will be ignored.\n * Prefer using `lazy` to improve the initial loading time.\n */\n component?: FC<TProps & TPropsParent>;\n\n /**\n * Lazy load the component when the page is loaded.\n *\n * It's recommended to use this for components to improve the initial loading time\n * and enable code-splitting.\n */\n lazy?: () => Promise<{ default: FC<TProps & TPropsParent> }>;\n\n /**\n * Attach child pages to create nested routes, adopting them as children of\n * this page.\n *\n * Use this when you want a parent to own children it cannot modify — most\n * notably pages that come from an injected router in another package, whose\n * `$page` definitions are frozen and cannot declare `parent` themselves.\n *\n * ```ts\n * layout = $page({\n * path: \"/app\",\n * children: () => [\n * this.productRouter.catalogPage, // from $inject(ProductRouter)\n * this.productRouter.checkoutPage,\n * ],\n * });\n * ```\n *\n * Use a thunk (`() => [...]`) when the children are defined later in the\n * same class.\n *\n * **Declare each edge from one side only.** If a child already sets\n * `parent: thisPage`, do NOT also add it to `children` — the link is\n * already established, and declaring it on both sides creates a TypeScript\n * circular dependency between the two class fields (each references the\n * other before it is initialised).\n */\n children?: Array<PagePrimitive> | (() => Array<PagePrimitive>);\n\n /**\n * Define a parent page for nested routing.\n *\n * Use this when you own the child page and can edit its definition — it is\n * the simplest way to nest routes and reads top-down. For pages you do NOT\n * own (e.g. pages exposed by an injected router from another package), let\n * the parent adopt them via its `children` option instead.\n *\n * **Declare each edge from one side only.** If you set `parent` here, do\n * NOT also add this page to the parent's `children` array — the link is\n * already established, and declaring it on both sides creates a TypeScript\n * circular dependency between the two class fields.\n */\n parent?: PagePrimitive<PageConfigSchema, TPropsParent, any>;\n\n /**\n * Function to determine if the page can be accessed.\n *\n * If it returns false, the page will not be accessible and a 403 Forbidden error will be returned.\n * This function can be used to implement permission-based access control.\n */\n can?: () => boolean;\n\n /**\n * Catch any error from the `loader` function or during `rendering`.\n *\n * Expected to return one of the following:\n * - a ReactNode to render an error page\n * - a Redirection to redirect the user\n * - undefined to let the error propagate\n *\n * If not defined, the error will be thrown and handled by the server or client error handler.\n * If a leaf $page does not define an error handler, the error can be caught by parent pages.\n *\n * @example Catch a 404 from API and render a custom not found component:\n * ```ts\n * loader: async ({ params, query }) => {\n * api.fetch(\"/api/resource\", { params, query });\n * },\n * errorHandler: (error, context) => {\n * if (HttpError.is(error, 404)) {\n * return <ResourceNotFound />;\n * }\n * }\n * ```\n *\n * @example Catch an 401 error and redirect the user to the login page:\n * ```ts\n * loader: async ({ params, query }) => {\n * // but the user is not authenticated\n * api.fetch(\"/api/resource\", { params, query });\n * },\n * errorHandler: (error, context) => {\n * if (HttpError.is(error, 401)) {\n * // throwing a Redirection is also valid!\n * return new Redirection(\"/login\");\n * }\n * }\n * ```\n */\n errorHandler?: ErrorHandler;\n\n /**\n * If true, the page will be considered as a static page, immutable and cacheable.\n * Replace boolean by an object to define static entries. (e.g. list of params/query)\n *\n * Browser-side: it only works with the build pipeline, which can pre-render the page at build time.\n *\n * Server-side: It will act as timeless cached page. You can use `cache` to configure the cache behavior.\n */\n static?:\n | boolean\n | {\n entries?: Array<Partial<PageRequestConfig<TConfig>>>;\n };\n\n /**\n * If true, force the page to be rendered only on the client-side (browser).\n * It uses the `<ClientOnly/>` component to render the page.\n */\n client?: boolean | ClientOnlyProps;\n\n /**\n * Called before the server response is sent to the client. (server only)\n */\n onServerResponse?: (request: ServerRequest) => unknown;\n\n /**\n * Called when user enters the page. (browser only)\n *\n * Useful for browser-only side effects like analytics, scroll management,\n * or focus handling that don't need to return data to the component.\n *\n * @example\n * ```ts\n * onEnter: () => {\n * analytics.trackPageView(\"/dashboard\");\n * window.scrollTo(0, 0);\n * }\n * ```\n */\n onEnter?: () => void;\n\n /**\n * Called when user leaves the page. (browser only)\n */\n onLeave?: () => void;\n\n /**\n * @experimental\n *\n * Add a css animation when the page is loaded or unloaded.\n * It uses CSS animations, so you need to define the keyframes in your CSS.\n *\n * @example Simple animation name\n * ```ts\n * animation: \"fadeIn\"\n * ```\n *\n * CSS example:\n * ```css\n * @keyframes fadeIn {\n * from { opacity: 0; }\n * to { opacity: 1; }\n * }\n * ```\n *\n * @example Detailed animation\n * ```ts\n * animation: {\n * enter: { name: \"fadeIn\", duration: 300 },\n * exit: { name: \"fadeOut\", duration: 200, timing: \"ease-in-out\" },\n * }\n * ```\n *\n * @example Only exit animation\n * ```ts\n * animation: {\n * exit: \"fadeOut\"\n * }\n * ```\n *\n * @example With custom timing function\n * ```ts\n * animation: {\n * enter: { name: \"fadeIn\", duration: 300, timing: \"cubic-bezier(0.4, 0, 0.2, 1)\" },\n * exit: { name: \"fadeOut\", duration: 200, timing: \"ease-in-out\" },\n * }\n * ```\n */\n animation?: PageAnimation;\n\n /**\n * Head configuration for the page (title, meta tags, etc.).\n *\n * Can be a static object or a function that receives resolved props.\n *\n * @example Static head\n * ```ts\n * head: {\n * title: \"My Page\",\n * description: \"Page description\",\n * }\n * ```\n *\n * @example Dynamic head based on props\n * ```ts\n * head: (props) => ({\n * title: props.user.name,\n * description: `Profile of ${props.user.name}`,\n * })\n * ```\n */\n head?: Head | ((props: TProps, previous?: Head) => Head);\n\n /**\n * Redirect to another path when this page is matched.\n *\n * This is a shorthand for throwing a `Redirection` in the loader.\n * The redirect is performed before any loader or component rendering.\n *\n * @example\n * ```ts\n * home = $page({\n * path: \"/\",\n * redirect: \"/dashboard\",\n * });\n * ```\n */\n redirect?: string;\n\n /**\n * Label for the page, used for navigation menus or breadcrumbs.\n *\n * This is optional and can be used by the application to display a user-friendly name for the page.\n * It has no functional impact on routing or rendering.\n */\n label?: string;\n\n /**\n * Source path for SSR module preloading.\n *\n * This is automatically injected by the viteAlephaPreload plugin.\n * It maps to the source file path used in Vite's SSR manifest.\n *\n * @internal\n */\n [PAGE_PRELOAD_KEY]?: string;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class PagePrimitive<\n TConfig extends PageConfigSchema = PageConfigSchema,\n TProps extends object = TPropsDefault,\n TPropsParent extends object = TPropsParentDefault,\n> extends Primitive<PagePrimitiveOptions<TConfig, TProps, TPropsParent>> {\n protected readonly reactPageService = $inject(ReactPageService);\n\n protected onInit() {\n if (this.options.static) {\n this.options.use ??= [];\n if (!this.options.use.some((m) => m[OPTIONS]?.name === \"$cache\")) {\n this.options.use.push(\n $cache({\n name: `page:${this.name}`,\n provider: \"memory\",\n ttl: [1, \"week\"],\n }),\n );\n }\n }\n }\n\n public get name(): string {\n return this.options.name ?? this.config.propertyKey;\n }\n\n /**\n * For testing or build purposes.\n *\n * This will render the page (HTML layout included or not) and return the HTML + context.\n * Only valid for server-side rendering, it will throw an error if called on the client-side.\n */\n public async render(\n options?: PagePrimitiveRenderOptions,\n ): Promise<PagePrimitiveRenderResult> {\n return this.reactPageService.render(this.name, options);\n }\n\n public async fetch(options?: PagePrimitiveRenderOptions): Promise<{\n html: string;\n response: Response;\n }> {\n return this.reactPageService.fetch(this.options.path || \"\", options);\n }\n}\n\n$page[KIND] = PagePrimitive;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type ErrorHandler = (\n error: Error,\n state: ReactRouterState,\n) => ReactNode | Redirection | undefined;\n\nexport interface PageConfigSchema {\n query?: TSchema;\n params?: TSchema;\n}\n\nexport type TPropsDefault = any;\n\nexport type TPropsParentDefault = {};\n\nexport interface PagePrimitiveRenderOptions {\n params?: Record<string, string>;\n query?: Record<string, string>;\n\n /**\n * If true, the HTML layout will be included in the response.\n * If false, only the page content will be returned.\n *\n * @default true\n */\n html?: boolean;\n hydration?: boolean;\n}\n\nexport interface PagePrimitiveRenderResult {\n html: string;\n state: ReactRouterState;\n redirect?: string;\n}\n\nexport interface PageRequestConfig<\n TConfig extends PageConfigSchema = PageConfigSchema,\n> {\n params: TConfig[\"params\"] extends TSchema\n ? Static<TConfig[\"params\"]>\n : Record<string, string>;\n\n query: TConfig[\"query\"] extends TSchema\n ? Static<TConfig[\"query\"]>\n : Record<string, string>;\n}\n\nexport type PageLoader<\n TConfig extends PageConfigSchema = PageConfigSchema,\n TPropsParent extends object = TPropsParentDefault,\n> = PageRequestConfig<TConfig> &\n TPropsParent &\n Omit<ReactRouterState, \"layers\" | \"onError\">;\n\nexport type PageAnimation =\n | PageAnimationObject\n | ((state: ReactRouterState) => PageAnimationObject | undefined);\n\ntype PageAnimationObject =\n | CssAnimationName\n | {\n enter?: CssAnimation | CssAnimationName;\n exit?: CssAnimation | CssAnimationName;\n };\n\ntype CssAnimationName = string;\n\ntype CssAnimation = {\n name: string;\n duration?: number;\n timing?: string;\n};\n","import { AlephaError } from \"alepha\";\nimport { useStore } from \"alepha/react\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\n\nexport const useRouterState = (): ReactRouterState => {\n const [state] = useStore(\"alepha.react.router.state\");\n if (!state) {\n throw new AlephaError(\"Missing react router state\");\n }\n return state;\n};\n","import type { Alepha } from \"alepha\";\nimport { type CSSProperties, useState } from \"react\";\nimport { useRouterState } from \"../hooks/useRouterState.ts\";\n\nexport interface ErrorViewerProps {\n error: Error;\n alepha: Alepha;\n onRetry?: () => void;\n}\n\nconst mono =\n 'ui-monospace, \"JetBrains Mono\", SFMono-Regular, Menlo, Monaco, Consolas, monospace';\n\nconst ErrorViewer = (props: ErrorViewerProps) => {\n if (props.alepha.isProduction()) {\n return <ProdErrorPage error={props.error} />;\n }\n\n return <DevErrorPage {...props} />;\n};\n\nexport default ErrorViewer;\n\n// ----- Dev Error Page -----\n\nconst DevErrorPage = (props: ErrorViewerProps) => {\n const [copied, setCopied] = useState(false);\n const state = useRouterState();\n const pathname = state.url.pathname;\n\n const handleCopy = () => {\n const text = buildErrorText(props.error);\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n };\n\n const status = getHttpStatus(props.error);\n\n return (\n <div style={dev.overlay}>\n <div style={dev.card}>\n <div style={dev.header}>\n <div style={dev.headerLeft}>\n <div style={dev.icon}>!</div>\n <div style={dev.title}>{props.error.name || \"Error\"}</div>\n </div>\n <div style={dev.headerRight}>\n {props.onRetry && (\n <button\n type=\"button\"\n style={dev.retryBtn}\n onClick={props.onRetry}\n >\n Retry\n </button>\n )}\n <button type=\"button\" style={dev.copyBtn} onClick={handleCopy}>\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n </div>\n </div>\n\n <ErrorBlock error={props.error} />\n\n <div style={dev.meta}>\n {pathname && <span style={dev.metaItem}>{pathname}</span>}\n <span style={dev.metaItem}>{new Date().toLocaleTimeString()}</span>\n {status && <span style={dev.statusBadge}>{status}</span>}\n </div>\n </div>\n </div>\n );\n};\n\n// ----- Error Block (recursive) -----\n\nconst ErrorBlock = (props: { error: Error; depth?: number }) => {\n const { error, depth = 0 } = props;\n\n return (\n <>\n {depth > 0 && <div style={dev.causedBy}>Caused by:</div>}\n <pre style={dev.messageBlock}>\n {error.name}: {error.message}\n </pre>\n {error.stack && (\n <>\n <div style={dev.stackLabel}>STACK TRACE</div>\n <pre style={dev.stackBlock}>{cleanStack(error.stack)}</pre>\n </>\n )}\n {error.cause instanceof Error && (\n <ErrorBlock error={error.cause} depth={depth + 1} />\n )}\n </>\n );\n};\n\n// ----- Prod Error Page -----\n\ninterface ProdErrorPageProps {\n error: Error;\n}\n\nconst ProdErrorPage = (props: ProdErrorPageProps) => {\n const requestId = (props.error as any).requestId;\n\n const handleReload = () => {\n if (typeof window !== \"undefined\") {\n window.location.reload();\n }\n };\n\n return (\n <div style={prod.page}>\n <div style={prod.card}>\n <div style={prod.heading}>Something went wrong</div>\n <div style={prod.subtitle}>\n We're having trouble processing your request.\n </div>\n {requestId && <div style={prod.refText}>Reference: {requestId}</div>}\n <div style={prod.actions}>\n <button type=\"button\" style={prod.reloadBtn} onClick={handleReload}>\n Reload page\n </button>\n <a href=\"/\" style={prod.homeLink}>\n Go home\n </a>\n </div>\n </div>\n </div>\n );\n};\n\n// ----- Helpers -----\n\nfunction cleanStack(stack: string): string {\n return stack\n .split(\"\\n\")\n .slice(1)\n .map((l) => l.trim())\n .join(\"\\n\");\n}\n\nfunction buildErrorText(error: Error): string {\n const parts: string[] = [];\n\n const append = (err: Error, depth: number) => {\n if (depth > 0) {\n parts.push(`\\nCaused by:`);\n }\n parts.push(`${err.name}: ${err.message}`);\n if (err.stack) {\n parts.push(cleanStack(err.stack));\n }\n if (err.cause instanceof Error) {\n append(err.cause, depth + 1);\n }\n };\n\n append(error, 0);\n return parts.join(\"\\n\");\n}\n\nfunction getHttpStatus(error: Error): number | undefined {\n if (\"status\" in error && typeof (error as any).status === \"number\") {\n return (error as any).status;\n }\n return undefined;\n}\n\n// ----- Dev Styles -----\n\nconst dev: Record<string, CSSProperties> = {\n overlay: {\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483647,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"24px\",\n backgroundColor: \"rgba(0, 0, 0, 0.75)\",\n backdropFilter: \"blur(4px)\",\n fontFamily: mono,\n fontSize: \"13px\",\n color: \"#e5e7eb\",\n boxSizing: \"border-box\",\n overflow: \"auto\",\n },\n card: {\n width: \"100%\",\n maxWidth: \"900px\",\n maxHeight: \"90vh\",\n overflow: \"auto\",\n padding: \"24px\",\n backgroundColor: \"#111\",\n borderLeft: \"4px solid #ef4444\",\n borderRadius: \"8px\",\n boxShadow: \"0 25px 50px rgba(0, 0, 0, 0.5)\",\n },\n header: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: \"20px\",\n flexWrap: \"wrap\",\n gap: \"12px\",\n },\n headerLeft: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"12px\",\n minWidth: 0,\n },\n headerRight: {\n display: \"flex\",\n gap: \"8px\",\n flexShrink: 0,\n },\n icon: {\n width: \"28px\",\n height: \"28px\",\n borderRadius: \"50%\",\n backgroundColor: \"#ef4444\",\n color: \"#fff\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontWeight: 700,\n fontSize: \"16px\",\n flexShrink: 0,\n },\n title: {\n color: \"#f87171\",\n fontSize: \"18px\",\n fontWeight: 700,\n },\n retryBtn: {\n padding: \"6px 16px\",\n backgroundColor: \"#2563eb\",\n color: \"#fff\",\n border: \"none\",\n borderRadius: \"6px\",\n cursor: \"pointer\",\n fontFamily: mono,\n fontSize: \"12px\",\n fontWeight: 600,\n },\n copyBtn: {\n padding: \"6px 16px\",\n backgroundColor: \"transparent\",\n color: \"#9ca3af\",\n border: \"1px solid #374151\",\n borderRadius: \"6px\",\n cursor: \"pointer\",\n fontFamily: mono,\n fontSize: \"12px\",\n fontWeight: 600,\n },\n messageBlock: {\n margin: \"0 0 12px\",\n padding: \"12px\",\n backgroundColor: \"#1f2937\",\n borderRadius: \"6px\",\n color: \"#f9fafb\",\n fontSize: \"13px\",\n lineHeight: 1.6,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n overflow: \"auto\",\n },\n stackLabel: {\n fontSize: \"10px\",\n color: \"#6b7280\",\n textTransform: \"uppercase\",\n letterSpacing: \"1.5px\",\n marginBottom: \"6px\",\n fontWeight: 600,\n },\n stackBlock: {\n margin: \"0 0 20px\",\n padding: \"12px\",\n backgroundColor: \"#0f172a\",\n borderRadius: \"6px\",\n color: \"#94a3b8\",\n fontSize: \"12px\",\n lineHeight: 1.6,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-all\",\n overflow: \"auto\",\n },\n causedBy: {\n fontSize: \"10px\",\n color: \"#6b7280\",\n textTransform: \"uppercase\",\n letterSpacing: \"1.5px\",\n marginBottom: \"8px\",\n paddingTop: \"12px\",\n borderTop: \"1px solid #374151\",\n fontWeight: 600,\n },\n meta: {\n display: \"flex\",\n gap: \"16px\",\n alignItems: \"center\",\n paddingTop: \"12px\",\n borderTop: \"1px solid #1f2937\",\n flexWrap: \"wrap\",\n },\n metaItem: {\n fontSize: \"11px\",\n color: \"#6b7280\",\n },\n statusBadge: {\n fontSize: \"11px\",\n color: \"#fbbf24\",\n backgroundColor: \"#422006\",\n padding: \"2px 8px\",\n borderRadius: \"4px\",\n fontWeight: 600,\n },\n};\n\n// ----- Prod Styles -----\n\nconst prod: Record<string, CSSProperties> = {\n page: {\n minHeight: \"100vh\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"#0f172a\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n padding: \"24px\",\n },\n card: {\n textAlign: \"center\",\n maxWidth: \"440px\",\n },\n heading: {\n fontSize: \"28px\",\n fontWeight: 700,\n color: \"#f1f5f9\",\n marginBottom: \"12px\",\n },\n subtitle: {\n fontSize: \"16px\",\n color: \"#94a3b8\",\n marginBottom: \"24px\",\n lineHeight: 1.5,\n },\n refText: {\n fontSize: \"13px\",\n color: \"#64748b\",\n marginBottom: \"24px\",\n fontFamily: mono,\n },\n actions: {\n display: \"flex\",\n gap: \"12px\",\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n reloadBtn: {\n padding: \"10px 24px\",\n backgroundColor: \"#2563eb\",\n color: \"#fff\",\n border: \"none\",\n borderRadius: \"8px\",\n cursor: \"pointer\",\n fontSize: \"14px\",\n fontWeight: 600,\n },\n homeLink: {\n padding: \"10px 24px\",\n color: \"#94a3b8\",\n textDecoration: \"none\",\n fontSize: \"14px\",\n },\n};\n","import { createContext } from \"react\";\nimport type { ErrorHandler } from \"../primitives/$page.ts\";\n\nexport interface RouterLayerContextValue {\n index: number;\n path: string;\n onError: ErrorHandler;\n}\n\nexport const RouterLayerContext = createContext<\n RouterLayerContextValue | undefined\n>(undefined);\n","import { AlephaError } from \"alepha\";\n\n/**\n * Used for Redirection during the page loading.\n *\n * Depends on the context, it can be thrown or just returned.\n *\n * @example\n * ```ts\n * import { Redirection } from \"alepha/react\";\n *\n * const MyPage = $page({\n * loader: async () => {\n * if (needRedirect) {\n * throw new Redirection(\"/new-path\");\n * }\n * },\n * });\n * ```\n */\nexport class Redirection extends AlephaError {\n public readonly redirect: string;\n\n constructor(redirect: string) {\n super(\"Redirection\");\n this.redirect = redirect;\n }\n}\n","import { ErrorBoundary, useAlepha, useEvents } from \"alepha/react\";\nimport { memo, type ReactNode, use, useRef, useState } from \"react\";\nimport { RouterLayerContext } from \"../contexts/RouterLayerContext.ts\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport { useRouterState } from \"../hooks/useRouterState.ts\";\nimport type { PageAnimation } from \"../primitives/$page.ts\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\nimport ErrorViewer from \"./ErrorViewer.tsx\";\n\nexport interface NestedViewProps {\n children?: ReactNode;\n errorBoundary?: false | ((error: Error, reset: () => void) => ReactNode);\n}\n\n/**\n * A component that renders the current view of the nested router layer.\n *\n * To be simple, it renders the `element` of the current child page of a parent page.\n *\n * @example\n * ```tsx\n * import { NestedView } from \"alepha/react\";\n *\n * class App {\n * parent = $page({\n * component: () => <NestedView />,\n * });\n *\n * child = $page({\n * parent: this.root,\n * component: () => <div>Child Page</div>,\n * });\n * }\n * ```\n */\nconst NestedView = (props: NestedViewProps) => {\n const routerLayer = use(RouterLayerContext);\n const index = routerLayer?.index ?? 0;\n const onError = routerLayer?.onError;\n const state = useRouterState();\n const alepha = useAlepha();\n const [boundaryKey, setBoundaryKey] = useState(0);\n\n const [view, setView] = useState<ReactNode | undefined>(\n state.layers[index]?.element,\n );\n\n const [animation, setAnimation] = useState(\"\");\n const animationExitDuration = useRef<number>(0);\n const animationExitNow = useRef<number>(0);\n\n useEvents(\n {\n \"react:transition:begin\": async ({ previous, state }) => {\n // --------- Animations Begin ---------\n const layer = previous.layers[index];\n if (!layer) {\n return;\n }\n\n if (`${state.url.pathname}/`.startsWith(`${layer.path}/`)) {\n return;\n }\n\n const animationExit = parseAnimation(\n layer.route?.animation,\n state,\n \"exit\",\n );\n\n if (animationExit) {\n const duration = animationExit.duration || 200;\n animationExitNow.current = Date.now();\n animationExitDuration.current = duration;\n setAnimation(animationExit.animation);\n } else {\n animationExitNow.current = 0;\n animationExitDuration.current = 0;\n setAnimation(\"\");\n }\n // --------- Animations End ---------\n },\n \"react:transition:end\": async ({ state }) => {\n const layer = state.layers[index];\n\n // --------- Animations Begin ---------\n if (animationExitNow.current) {\n const duration = animationExitDuration.current;\n const diff = Date.now() - animationExitNow.current;\n if (diff < duration) {\n await new Promise((resolve) =>\n setTimeout(resolve, duration - diff),\n );\n }\n }\n // --------- Animations End ---------\n\n if (!layer?.cache) {\n setView(layer?.element);\n\n // --------- Animations Begin ---------\n const animationEnter = parseAnimation(\n layer?.route?.animation,\n state,\n \"enter\",\n );\n\n if (animationEnter) {\n setAnimation(animationEnter.animation);\n } else {\n setAnimation(\"\");\n }\n // --------- Animations End ---------\n }\n },\n },\n [],\n );\n\n let element = view ?? props.children ?? null;\n\n // --------- Animations Begin ---------\n if (animation) {\n element = (\n <div\n style={{\n display: \"flex\",\n flex: 1,\n height: \"100%\",\n width: \"100%\",\n position: \"relative\",\n overflow: \"hidden\",\n }}\n >\n <div\n style={{ height: \"100%\", width: \"100%\", display: \"flex\", animation }}\n >\n {element}\n </div>\n </div>\n );\n }\n // --------- Animations End ---------\n\n if (props.errorBoundary === false) {\n return <>{element}</>;\n }\n\n if (props.errorBoundary) {\n return (\n <ErrorBoundary key={boundaryKey} fallback={props.errorBoundary}>\n {element}\n </ErrorBoundary>\n );\n }\n\n const fallback = (error: Error) => {\n const result = onError?.(error, state) ?? (\n <ErrorViewer error={error} alepha={alepha} />\n );\n if (result instanceof Redirection) {\n return \"Redirection inside ErrorBoundary is not allowed.\";\n }\n return result as ReactNode;\n };\n\n return (\n <ErrorBoundary key={boundaryKey} fallback={fallback}>\n {element}\n </ErrorBoundary>\n );\n};\n\nexport default memo(NestedView);\n\nfunction parseAnimation(\n animationLike: PageAnimation | undefined,\n state: ReactRouterState,\n type: \"enter\" | \"exit\" = \"enter\",\n):\n | {\n duration: number;\n animation: string;\n }\n | undefined {\n if (!animationLike) {\n return undefined;\n }\n\n const DEFAULT_DURATION = 300;\n\n const animation =\n typeof animationLike === \"function\" ? animationLike(state) : animationLike;\n\n if (typeof animation === \"string\") {\n if (type === \"exit\") {\n return;\n }\n return {\n duration: DEFAULT_DURATION,\n animation: `${DEFAULT_DURATION}ms ${animation}`,\n };\n }\n\n if (typeof animation === \"object\") {\n const anim = animation[type];\n const duration =\n typeof anim === \"object\"\n ? (anim.duration ?? DEFAULT_DURATION)\n : DEFAULT_DURATION;\n const name = typeof anim === \"object\" ? anim.name : anim;\n\n if (type === \"exit\") {\n const timing = typeof anim === \"object\" ? (anim.timing ?? \"\") : \"\";\n return {\n duration,\n animation: `${duration}ms ${timing} ${name}`,\n };\n }\n\n const timing = typeof anim === \"object\" ? (anim.timing ?? \"\") : \"\";\n\n return {\n duration,\n animation: `${duration}ms ${timing} ${name}`,\n };\n }\n\n return undefined;\n}\n","import type { CSSProperties } from \"react\";\n\n/**\n * Default 404 Not Found page component.\n */\nconst NotFound = (props: { style?: CSSProperties }) => (\n <div\n style={{\n width: \"100%\",\n minHeight: \"90vh\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n textAlign: \"center\",\n fontFamily:\n 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n padding: \"2rem\",\n ...props.style,\n }}\n >\n <div style={{ fontSize: \"6rem\", fontWeight: 200, lineHeight: 1 }}>404</div>\n <div style={{ fontSize: \"0.875rem\", marginTop: \"1rem\", opacity: 0.6 }}>\n Page not found\n </div>\n </div>\n);\n\nexport default NotFound;\n","import {\n $atom,\n $hook,\n $inject,\n $state,\n Alepha,\n AlephaError,\n type TSchema,\n t,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { AlephaContext, ClientOnly } from \"alepha/react\";\nimport type { Head } from \"alepha/react/head\";\nimport { createElement, type ReactNode, StrictMode } from \"react\";\nimport ErrorViewer from \"../components/ErrorViewer.tsx\";\nimport NestedView from \"../components/NestedView.tsx\";\nimport NotFoundPage from \"../components/NotFound.tsx\";\nimport { RouterLayerContext } from \"../contexts/RouterLayerContext.ts\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport {\n $page,\n type ErrorHandler,\n type PagePrimitive,\n type PagePrimitiveOptions,\n} from \"../primitives/$page.ts\";\n\n// -------------------------------------------------------------------------------------------------------------------\n\nexport const reactPageOptions = $atom({\n name: \"alepha.react.page.options\",\n description: \"Configuration options for the React page provider.\",\n schema: t.object({\n /**\n * Enable React StrictMode wrapper.\n */\n strictMode: t.boolean({ default: true }),\n /**\n * RegExp pattern (as string) to detect file-like URLs (e.g. /hello.txt, /wp-login.php).\n * When a request hits the catch-all wildcard route and matches this pattern,\n * SSR is skipped and a plain 404 response is returned instead.\n *\n * Set to empty string to disable this behavior.\n *\n * @default \"\\\\.[a-zA-Z0-9]{1,10}$\"\n */\n staticFilePattern: t.string(),\n }),\n default: {\n strictMode: true,\n staticFilePattern: \"\\\\.[a-zA-Z0-9]{1,10}$\",\n },\n});\n\n// -------------------------------------------------------------------------------------------------------------------\n\n/**\n * Handle page routes for React applications. (Browser and Server)\n */\nexport class ReactPageProvider {\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly log = $logger();\n protected readonly options = $state(reactPageOptions);\n protected readonly alepha = $inject(Alepha);\n protected readonly pages: PageRoute[] = [];\n protected nextIdCursor = 0;\n\n protected readonly configure = $hook({\n on: \"configure\",\n handler: () => {\n let hasNotFoundHandler = false;\n const pages = this.alepha.primitives($page);\n\n const hasParent = (it: PagePrimitive) => {\n if (it.options.parent) {\n return true;\n }\n\n for (const page of pages) {\n const children = page.options.children\n ? Array.isArray(page.options.children)\n ? page.options.children\n : page.options.children()\n : [];\n if (children.includes(it)) {\n return true;\n }\n }\n };\n\n for (const page of pages) {\n if (page.options.path === \"/*\") {\n hasNotFoundHandler = true;\n }\n\n // skip children, we only want root pages\n if (hasParent(page)) {\n continue;\n }\n\n this.add(this.map(pages, page));\n }\n\n if (!hasNotFoundHandler && pages.length > 0) {\n // add a default 404 page if not already defined\n this.add({\n path: \"/*\",\n name: \"notFound\",\n component: NotFoundPage,\n onServerResponse: ({ reply }) => {\n reply.status = 404;\n },\n });\n }\n },\n });\n\n // -------------------------------------------------------------------------------------------------------------------\n\n public getPages(): PageRoute[] {\n return this.pages;\n }\n\n public getConcretePages(): ConcretePageRoute[] {\n const pages: ConcretePageRoute[] = [];\n for (const page of this.pages) {\n if (page.children && page.children.length > 0) {\n continue;\n }\n\n // check if the page has dynamic params\n const fullPath = this.pathname(page.name);\n if (fullPath.includes(\":\") || fullPath.includes(\"*\")) {\n if (typeof page.static === \"object\") {\n const entries = page.static.entries;\n if (entries && entries.length > 0) {\n for (const entry of entries) {\n const params = entry.params as Record<string, string>;\n const path = this.compile(page.path ?? \"\", params);\n if (!path.includes(\":\") && !path.includes(\"*\")) {\n pages.push({\n ...page,\n name: params[Object.keys(params)[0]],\n staticName: page.name,\n path,\n ...entry,\n });\n }\n }\n }\n }\n\n continue;\n }\n\n pages.push(page);\n }\n return pages;\n }\n\n public page(name: string): PageRoute {\n for (const page of this.pages) {\n if (page.name === name) {\n return page;\n }\n }\n\n throw new AlephaError(`Page '${name}' not found`);\n }\n\n public pathname(\n name: string,\n options: {\n params?: Record<string, string>;\n query?: Record<string, string>;\n } = {},\n ) {\n const page = this.page(name);\n if (!page) {\n throw new AlephaError(`Page ${name} not found`);\n }\n\n let url = page.path ?? \"\";\n let parent = page.parent;\n while (parent) {\n url = `${parent.path ?? \"\"}/${url}`;\n parent = parent.parent;\n }\n\n url = this.compile(url, options.params ?? {});\n\n if (options.query) {\n const query = new URLSearchParams(options.query);\n if (query.toString()) {\n url += `?${query.toString()}`;\n }\n }\n\n return url.replace(/\\/\\/+/g, \"/\") || \"/\";\n }\n\n public url(\n name: string,\n options: { params?: Record<string, string>; host?: string } = {},\n ): URL {\n return new URL(\n this.pathname(name, options),\n // use provided base or default to http://localhost\n options.host ?? `http://localhost`,\n );\n }\n\n public root(state: ReactRouterState): ReactNode {\n const root = createElement(\n AlephaContext.Provider,\n { value: this.alepha },\n createElement(NestedView, {}, state.layers[0]?.element),\n );\n\n if (this.options.strictMode) {\n return createElement(StrictMode, {}, root);\n }\n\n return root;\n }\n\n protected convertStringObjectToObject = (\n schema?: TSchema,\n value?: any,\n ): any => {\n if (t.schema.isObject(schema) && typeof value === \"object\") {\n for (const key in schema.properties) {\n if (\n t.schema.isObject(schema.properties[key]) &&\n typeof value[key] === \"string\"\n ) {\n try {\n value[key] = this.alepha.codec.decode(\n schema.properties[key],\n decodeURIComponent(value[key]),\n );\n } catch (e) {\n // ignore\n }\n }\n }\n }\n return value;\n };\n\n /**\n * Create a new RouterState based on a given route and request.\n * This method resolves the layers for the route, applying any query and params schemas defined in the route.\n * It also handles errors and redirects.\n */\n public async createLayers(\n route: PageRoute,\n state: ReactRouterState,\n previous: PreviousLayerData[] = [],\n ): Promise<CreateLayersResult> {\n let context: Record<string, any> = {}; // all props\n const stack: Array<RouterStackItem> = [{ route }]; // stack of routes\n\n let parent = route.parent;\n while (parent) {\n stack.unshift({ route: parent });\n parent = parent.parent;\n }\n\n let forceRefresh = false;\n\n for (let i = 0; i < stack.length; i++) {\n const it = stack[i];\n const route = it.route;\n const config: Record<string, any> = {};\n\n try {\n this.convertStringObjectToObject(route.schema?.query, state.query);\n config.query = route.schema?.query\n ? this.alepha.codec.decode(route.schema.query, state.query)\n : {};\n } catch (e) {\n it.error = e instanceof Error ? e : new Error(String(e));\n break;\n }\n\n try {\n config.params = route.schema?.params\n ? this.alepha.codec.decode(route.schema.params, state.params)\n : {};\n } catch (e) {\n it.error = e instanceof Error ? e : new Error(String(e));\n break;\n }\n\n // save config\n it.config = {\n ...config,\n };\n\n // check if previous layer is the same, reuse if possible\n if (previous?.[i] && !forceRefresh && previous[i].name === route.name) {\n const url = (str?: string) => (str ? str.replace(/\\/\\/+/g, \"/\") : \"/\");\n\n const prev = JSON.stringify({\n part: url(previous[i].part),\n params: previous[i].config?.params ?? {},\n });\n\n const curr = JSON.stringify({\n part: url(route.path),\n params: config.params ?? {},\n });\n\n if (prev === curr) {\n // part is the same, reuse previous layer\n it.props = previous[i].props;\n it.error = previous[i].error;\n it.cache = true;\n context = {\n ...context,\n ...it.props,\n };\n continue;\n }\n\n // part is different, force refresh of next layers\n forceRefresh = true;\n }\n\n // redirect shorthand\n if (route.redirect) {\n return { redirect: route.redirect };\n }\n\n // no loader, render a basic view by default\n if (!route.loader) {\n continue;\n }\n\n try {\n const args = Object.create(state);\n Object.assign(args, config, context);\n const props = (await route.loader?.(args)) ?? {};\n\n // save props\n it.props = {\n ...props,\n };\n\n // add props to context\n context = {\n ...context,\n ...props,\n };\n } catch (e) {\n // check if we need to redirect\n if (e instanceof Redirection) {\n return {\n redirect: e.redirect,\n };\n }\n\n this.log.error(\"Page loader has failed\", e);\n\n it.error = e instanceof Error ? e : new Error(String(e));\n break;\n }\n }\n\n let acc = \"\";\n for (let i = 0; i < stack.length; i++) {\n const it = stack[i];\n const props = it.props ?? {};\n\n const params = { ...it.config?.params };\n for (const key of Object.keys(params)) {\n params[key] = String(params[key]);\n }\n\n acc += \"/\";\n acc += it.route.path ? this.compile(it.route.path, params) : \"\";\n const path = acc.replace(/\\/+/, \"/\");\n const localErrorHandler = this.getErrorHandler(it.route);\n if (localErrorHandler) {\n const onErrorParent = state.onError;\n state.onError = (error, context) => {\n const result = localErrorHandler(error, context);\n // if nothing happen, call the parent\n if (result === undefined) {\n return onErrorParent(error, context);\n }\n return result;\n };\n }\n\n // normal use case\n if (!it.error) {\n try {\n const element = await this.createElement(\n it.route,\n {\n // default props attached to page\n ...(it.route.props ? it.route.props() : {}),\n // resolved props\n ...props,\n // context props (from previous layers)\n ...context,\n },\n state.url,\n );\n\n state.layers.push({\n name: it.route.name,\n props,\n part: it.route.path,\n config: it.config,\n element: this.renderView(i + 1, path, element, it.route),\n index: i + 1,\n path,\n route: it.route,\n cache: it.cache,\n });\n } catch (e) {\n it.error = e instanceof Error ? e : new Error(String(e));\n }\n }\n\n // handler has thrown an error, render an error view\n if (it.error) {\n try {\n let element: ReactNode | Redirection | undefined =\n await state.onError(it.error, state);\n\n if (element === undefined) {\n throw it.error;\n }\n\n if (element instanceof Redirection) {\n return {\n redirect: element.redirect,\n };\n }\n\n if (element === null) {\n element = this.renderError(it.error);\n }\n\n state.layers.push({\n props,\n error: it.error,\n name: it.route.name,\n part: it.route.path,\n config: it.config,\n element: this.renderView(i + 1, path, element, it.route),\n index: i + 1,\n path,\n route: it.route,\n cache: it.cache,\n });\n break;\n } catch (e) {\n if (e instanceof Redirection) {\n return {\n redirect: e.redirect,\n };\n }\n throw e;\n }\n }\n }\n\n return { state };\n }\n\n protected getErrorHandler(route: PageRoute): ErrorHandler | undefined {\n if (route.errorHandler) return route.errorHandler;\n let parent = route.parent;\n while (parent) {\n if (parent.errorHandler) return parent.errorHandler;\n parent = parent.parent;\n }\n }\n\n protected async createElement(\n page: PageRoute,\n props: Record<string, any>,\n targetUrl?: URL,\n ): Promise<ReactNode> {\n if (page.lazy && page.component) {\n this.log.warn(\n `Page ${page.name} has both lazy and component options, lazy will be used`,\n );\n }\n\n if (page.lazy) {\n try {\n const component = await page.lazy();\n return createElement(component.default, props);\n } catch (error) {\n if (this.alepha.isBrowser() && this.isChunkLoadError(error)) {\n if (this.reloadAfterChunkError(targetUrl)) {\n return undefined;\n }\n }\n throw error;\n }\n }\n\n if (page.component) {\n return createElement(page.component, props);\n }\n\n return undefined;\n }\n\n /**\n * Detect chunk load errors caused by stale dynamic imports after a deployment.\n * When new assets are deployed with different hashes, old chunk URLs return 404.\n */\n protected isChunkLoadError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const msg = error.message;\n return (\n /Failed to fetch dynamically imported module/.test(msg) ||\n /error loading dynamically imported module/i.test(msg) ||\n /Unable to preload CSS/.test(msg) ||\n /Importing a module script failed/.test(msg)\n );\n }\n\n /**\n * Navigate to the target URL to fetch updated assets after a chunk load failure.\n * Uses sessionStorage to prevent infinite reload loops.\n * Returns true if navigation was initiated.\n */\n protected reloadAfterChunkError(url?: URL): boolean {\n const key = \"alepha:chunk-reload\";\n const lastReload = sessionStorage.getItem(key);\n const now = this.dateTimeProvider.nowMillis();\n\n if (lastReload && now - Number(lastReload) < 10_000) {\n this.log.error(\n \"Chunk load failed after recent reload, not retrying to avoid loop\",\n );\n return false;\n }\n\n this.log.warn(\"Chunk load failed after deployment, reloading page\");\n sessionStorage.setItem(key, String(now));\n window.location.assign(\n url ? url.pathname + url.search : window.location.href,\n );\n return true;\n }\n\n public renderError(error: Error): ReactNode {\n return createElement(ErrorViewer, { error, alepha: this.alepha });\n }\n\n public renderEmptyView(): ReactNode {\n return createElement(NestedView, {});\n }\n\n public href(\n page: { options: { name?: string } },\n params: Record<string, any> = {},\n ): string {\n const found = this.pages.find((it) => it.name === page.options.name);\n if (!found) {\n throw new AlephaError(`Page ${page.options.name} not found`);\n }\n\n let url = found.path ?? \"\";\n let parent = found.parent;\n while (parent) {\n url = `${parent.path ?? \"\"}/${url}`;\n parent = parent.parent;\n }\n\n url = this.compile(url, params);\n\n return url.replace(/\\/\\/+/g, \"/\") || \"/\";\n }\n\n public compile(path: string, params: Record<string, string> = {}) {\n for (const [key, value] of Object.entries(params)) {\n path = path.replace(`:${key}`, value);\n }\n return path;\n }\n\n protected renderView(\n index: number,\n path: string,\n view: ReactNode | undefined,\n page: PageRoute,\n ): ReactNode {\n view ??= this.renderEmptyView();\n\n const element = page.client\n ? createElement(\n ClientOnly,\n typeof page.client === \"object\" ? page.client : {},\n view,\n )\n : view;\n\n return createElement(\n RouterLayerContext.Provider,\n {\n value: {\n index,\n path,\n onError:\n this.getErrorHandler(page) ?? ((error) => this.renderError(error)),\n },\n },\n element,\n );\n }\n\n protected map(\n pages: Array<PagePrimitive>,\n target: PagePrimitive,\n ): PageRouteEntry {\n const children = target.options.children\n ? Array.isArray(target.options.children)\n ? target.options.children\n : target.options.children()\n : [];\n\n const getChildrenFromParent = (it: PagePrimitive): PagePrimitive[] => {\n const children = [];\n for (const page of pages) {\n if (page.options.parent === it) {\n children.push(page);\n }\n }\n return children;\n };\n\n children.push(...getChildrenFromParent(target));\n\n return {\n ...target.options,\n name: target.name,\n parent: undefined,\n children: children.map((it) => this.map(pages, it)),\n } as PageRoute;\n }\n\n public add(entry: PageRouteEntry) {\n if (this.alepha.isReady()) {\n throw new AlephaError(\"Router is already initialized\");\n }\n\n entry.name ??= this.nextId();\n const page = entry as PageRoute;\n\n page.match = this.createMatch(page);\n this.pages.push(page);\n\n if (page.children) {\n for (const child of page.children) {\n (child as PageRoute).parent = page;\n this.add(child);\n }\n }\n }\n\n protected createMatch(page: PageRoute): string {\n let url = page.path ?? \"/\";\n let target = page.parent;\n while (target) {\n url = `${target.path ?? \"\"}/${url}`;\n target = target.parent;\n }\n\n let path = url.replace(/\\/\\/+/g, \"/\");\n\n if (path.endsWith(\"/\") && path !== \"/\") {\n // remove trailing slash\n path = path.slice(0, -1);\n }\n\n return path;\n }\n\n protected nextId(): string {\n this.nextIdCursor += 1;\n return `P${this.nextIdCursor}`;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const isPageRoute = (it: any): it is PageRoute => {\n return (\n it &&\n typeof it === \"object\" &&\n typeof it.path === \"string\" &&\n typeof it.page === \"object\"\n );\n};\n\nexport interface PageRouteEntry\n extends Omit<PagePrimitiveOptions, \"children\" | \"parent\"> {\n children?: PageRouteEntry[];\n}\n\nexport interface ConcretePageRoute extends PageRoute {\n /**\n * When exported, static routes can be split into multiple pages with different params.\n * We replace 'name' by the new name for each static entry, and old 'name' becomes 'staticName'.\n */\n staticName?: string;\n\n params?: Record<string, string>;\n}\n\nexport interface PageRoute extends PageRouteEntry {\n type: \"page\";\n name: string;\n parent?: PageRoute;\n match: string;\n\n /**\n * Optional meta information associated with the page route, can be used for any purpose (e.g. menu label, icon, etc.).\n */\n label?: string;\n}\n\nexport interface Layer {\n config?: {\n query?: Record<string, any>;\n params?: Record<string, any>;\n // stack of resolved props\n context?: Record<string, any>;\n };\n\n name: string;\n props?: Record<string, any>;\n error?: Error;\n part?: string;\n element: ReactNode;\n index: number;\n path: string;\n route?: PageRoute;\n cache?: boolean;\n}\n\nexport type PreviousLayerData = Omit<Layer, \"element\" | \"index\" | \"path\">;\n\nexport interface AnchorProps {\n href: string;\n onClick: (ev?: any) => any;\n}\n\nexport interface ReactRouterState {\n /**\n * Stack of layers for the current page.\n */\n layers: Array<Layer>;\n\n /**\n * URL of the current page.\n */\n url: URL;\n\n /**\n * Error handler for the current page.\n */\n onError: ErrorHandler;\n\n /**\n * Params extracted from the URL for the current page.\n */\n params: Record<string, any>;\n\n /**\n * Query parameters extracted from the URL for the current page.\n */\n query: Record<string, string>;\n\n /**\n * Optional meta information associated with the current page.\n */\n meta: Record<string, any>;\n\n /**\n * Head configuration for the current page (title, meta tags, etc.).\n * Populated by HeadProvider during SSR.\n */\n head: Head;\n\n /**\n * Optional name of the current page route\n */\n name?: string;\n}\n\nexport interface RouterStackItem {\n route: PageRoute;\n config?: Record<string, any>;\n props?: Record<string, any>;\n error?: Error;\n cache?: boolean;\n}\n\nexport interface CreateLayersResult {\n redirect?: string;\n state?: ReactRouterState;\n}\n","import { $atom, t } from \"alepha\";\n\n/**\n * Schema for the SSR manifest atom.\n */\nexport const ssrManifestAtomSchema = t.object({\n /**\n * Base path for assets (from Vite's base config).\n * Used to prefix asset URLs when serving from a subpath.\n * @example \"/devtools\" or \"/\"\n */\n base: t.optional(t.string()),\n\n /**\n * Preload manifest mapping short keys to source paths.\n * Generated by viteAlephaSsrPreload plugin at build time.\n */\n preload: t.optional(t.record(t.string(), t.string())),\n\n /**\n * Client manifest mapping source files to their output information.\n * Only includes fields actually used for preloading.\n */\n client: t.optional(\n t.record(\n t.string(),\n t.object({\n file: t.string(),\n isEntry: t.optional(t.boolean()),\n imports: t.optional(t.array(t.string())),\n css: t.optional(t.array(t.string())),\n }),\n ),\n ),\n\n /**\n * Dev mode head content.\n * Contains pre-transformed scripts injected by Vite and plugins (React, etc.).\n * Only set in dev mode via ViteDevServerProvider.\n */\n devHead: t.optional(t.string()),\n\n /**\n * Auto-detected favicon path and MIME type.\n * Format: \"type:path\" (e.g., \"image/svg+xml:/favicon.svg\").\n * Set at build/dev time by scanning the public directory.\n */\n favicon: t.optional(t.string()),\n});\n\n/**\n * Type for the SSR manifest schema.\n */\nexport type SsrManifestAtomSchema = typeof ssrManifestAtomSchema;\n\n/**\n * SSR Manifest atom containing all manifest data for SSR module preloading.\n *\n * This atom is populated at build time by embedding manifest data into the\n * generated index.js. This approach is optimal for serverless deployments\n * as it eliminates filesystem reads at runtime.\n *\n * The manifest includes:\n * - preload: Maps short hash keys to source paths (from viteAlephaSsrPreload)\n * - client: Maps source files to their output info (file, imports, css)\n */\nexport const ssrManifestAtom = $atom({\n name: \"alepha.react.ssr.manifest\",\n description: \"SSR manifest for module preloading\",\n schema: ssrManifestAtomSchema,\n default: {},\n});\n","import { $inject, Alepha, type Static } from \"alepha\";\nimport {\n type SsrManifestAtomSchema,\n ssrManifestAtom,\n} from \"../atoms/ssrManifestAtom.ts\";\nimport { PAGE_PRELOAD_KEY } from \"../constants/PAGE_PRELOAD_KEY.ts\";\nimport type { PageRoute } from \"./ReactPageProvider.ts\";\n\n/**\n * Provider for SSR manifest data used for module preloading.\n *\n * The manifest is populated at build time by embedding data into the\n * generated index.js via the ssrManifestAtom. This eliminates filesystem\n * reads at runtime, making it optimal for serverless deployments.\n *\n * Manifest files are generated during `vite build`:\n * - manifest.json (client manifest)\n * - preload-manifest.json (from viteAlephaSsrPreload plugin)\n */\nexport class SSRManifestProvider {\n protected readonly alepha = $inject(Alepha);\n\n /**\n * Get the manifest from the store at runtime.\n * This ensures the manifest is available even when set after module load.\n */\n protected get manifest(): Static<SsrManifestAtomSchema> {\n return (\n (this.alepha.store.get(\n ssrManifestAtom,\n ) as Static<SsrManifestAtomSchema>) ?? {}\n );\n }\n\n /**\n * Get the full manifest object.\n */\n public getManifest(): Static<SsrManifestAtomSchema> {\n return this.manifest;\n }\n\n /**\n * Get the base path for assets (from Vite's base config).\n * Returns empty string if base is \"/\" (default), otherwise returns the base path.\n */\n protected get base(): string {\n return this.manifest.base ?? \"\";\n }\n\n /**\n * Get the preload manifest.\n */\n protected get preloadManifest(): PreloadManifest | undefined {\n return this.manifest.preload;\n }\n\n /**\n * Get the client manifest.\n */\n protected get clientManifest(): ClientManifest | undefined {\n return this.manifest.client;\n }\n\n /**\n * Resolve a preload key to its source path.\n *\n * The key is a short hash injected by viteAlephaSsrPreload plugin,\n * which maps to the full source path in the preload manifest.\n *\n * @param key - Short hash key (e.g., \"a1b2c3d4\")\n * @returns Source path (e.g., \"src/pages/UserDetail.tsx\") or undefined\n */\n public resolvePreloadKey(key: string): string | undefined {\n return this.preloadManifest?.[key];\n }\n\n /**\n * Get all chunks required for a source file, including transitive dependencies.\n *\n * Uses the client manifest to recursively resolve all imported chunks.\n *\n * @param sourcePath - Source file path (e.g., \"src/pages/Home.tsx\")\n * @returns Array of chunk URLs to preload, or empty array if not found\n */\n public getChunks(sourcePath: string): string[] {\n if (!this.clientManifest) {\n return [];\n }\n\n // Find entry in client manifest\n const entry = this.findManifestEntry(sourcePath);\n if (!entry) {\n return [];\n }\n\n // Recursively collect all chunks\n const chunks = new Set<string>();\n const visited = new Set<string>();\n\n this.collectChunksRecursive(sourcePath, chunks, visited);\n\n return Array.from(chunks);\n }\n\n /**\n * Find manifest entry for a source path, trying different extensions.\n */\n protected findManifestEntry(sourcePath: string) {\n if (!this.clientManifest) return undefined;\n\n // Try exact match\n if (this.clientManifest[sourcePath]) {\n return this.clientManifest[sourcePath];\n }\n\n // Try with different extensions\n const basePath = sourcePath.replace(/\\.[^.]+$/, \"\");\n for (const ext of [\".tsx\", \".ts\", \".jsx\", \".js\"]) {\n const pathWithExt = basePath + ext;\n if (this.clientManifest[pathWithExt]) {\n return this.clientManifest[pathWithExt];\n }\n }\n\n return undefined;\n }\n\n /**\n * Recursively collect all chunk URLs for a manifest entry.\n */\n protected collectChunksRecursive(\n key: string,\n chunks: Set<string>,\n visited: Set<string>,\n ): void {\n if (visited.has(key)) return;\n visited.add(key);\n\n if (!this.clientManifest) return;\n\n const entry = this.clientManifest[key];\n if (!entry) return;\n\n const base = this.base;\n\n // Add main chunk file (with base path for URL)\n if (entry.file) {\n chunks.add(`${base}/${entry.file}`);\n }\n\n // Add CSS files\n if (entry.css) {\n for (const css of entry.css) {\n chunks.add(`${base}/${css}`);\n }\n }\n\n // Recursively process imports (but skip entry point)\n if (entry.imports) {\n for (const imp of entry.imports) {\n // Skip the main entry point (index.html) - it's already being loaded\n if (imp === \"index.html\" || imp.endsWith(\".html\")) {\n continue;\n }\n this.collectChunksRecursive(imp, chunks, visited);\n }\n }\n\n // Note: We intentionally do NOT follow dynamicImports\n // Those are lazy-loaded and shouldn't be preloaded\n }\n\n /**\n * Collect modulepreload links for a route and its parent chain.\n */\n public collectPreloadLinks(\n route: PageRoute,\n ): Array<{ rel: string; href: string; as?: string; crossorigin?: string }> {\n if (!this.isAvailable()) {\n return [];\n }\n\n const preloadPaths: string[] = [];\n let current: PageRoute | undefined = route;\n\n while (current) {\n const preloadKey = current[PAGE_PRELOAD_KEY];\n if (preloadKey) {\n const sourcePath = this.resolvePreloadKey(preloadKey);\n if (sourcePath) {\n preloadPaths.push(sourcePath);\n }\n }\n current = current.parent;\n }\n\n if (preloadPaths.length === 0) {\n return [];\n }\n\n const chunks = this.getChunksForMultiple(preloadPaths);\n\n return chunks.map((href) => {\n if (href.endsWith(\".css\")) {\n // Must include crossorigin to match Vite's dynamic CSS loading which always uses crossorigin=\"\"\n return { rel: \"preload\", href, as: \"style\", crossorigin: \"\" };\n }\n return { rel: \"modulepreload\", href };\n });\n }\n\n /**\n * Get all chunks for multiple source files.\n *\n * @param sourcePaths - Array of source file paths\n * @returns Deduplicated array of chunk URLs\n */\n public getChunksForMultiple(sourcePaths: string[]): string[] {\n const allChunks = new Set<string>();\n\n for (const path of sourcePaths) {\n const chunks = this.getChunks(path);\n for (const chunk of chunks) {\n allChunks.add(chunk);\n }\n }\n\n return Array.from(allChunks);\n }\n\n /**\n * Check if manifest is loaded and available.\n */\n public isAvailable(): boolean {\n return this.clientManifest !== undefined;\n }\n\n /**\n * Cached entry assets - computed once at first access.\n */\n protected cachedEntryAssets: EntryAssets | null = null;\n\n /**\n * Get the entry point assets (main entry.js and associated CSS files).\n *\n * These assets are always required for all pages and can be preloaded\n * before page-specific loaders run.\n *\n * @returns Entry assets with js and css paths, or null if manifest unavailable\n */\n public getEntryAssets(): EntryAssets | null {\n if (this.cachedEntryAssets) {\n return this.cachedEntryAssets;\n }\n\n if (!this.clientManifest) {\n return null;\n }\n\n const base = this.base;\n\n // Find the entry point in the client manifest\n for (const [key, entry] of Object.entries(this.clientManifest)) {\n if (entry.isEntry) {\n this.cachedEntryAssets = {\n js: `${base}/${entry.file}`,\n css: entry.css?.map((css) => `${base}/${css}`) ?? [],\n };\n return this.cachedEntryAssets;\n }\n }\n\n return null;\n }\n\n /**\n * Build preload link tags for entry assets.\n *\n * @returns Array of link objects ready to be rendered\n */\n public getEntryPreloadLinks(): Array<{\n rel: string;\n href: string;\n as?: string;\n crossorigin?: string;\n }> {\n const assets = this.getEntryAssets();\n if (!assets) {\n return [];\n }\n\n const links: Array<{\n rel: string;\n href: string;\n as?: string;\n crossorigin?: string;\n }> = [];\n\n // Add CSS preloads first (critical for rendering)\n for (const css of assets.css) {\n links.push({ rel: \"stylesheet\", href: css, crossorigin: \"\" });\n }\n\n // Add entry JS modulepreload\n if (assets.js) {\n links.push({ rel: \"modulepreload\", href: assets.js });\n }\n\n return links;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Entry assets structure containing the main entry JS and associated CSS files.\n */\nexport interface EntryAssets {\n /**\n * Main entry JavaScript file (e.g., \"/assets/entry.abc123.js\")\n */\n js?: string;\n /**\n * Associated CSS files (e.g., [\"/assets/style.abc123.css\"])\n */\n css: string[];\n}\n\n/**\n * Client manifest structure from Vite.\n * Only includes fields actually used for preloading.\n */\nexport interface ClientManifest {\n [key: string]: {\n file: string;\n isEntry?: boolean;\n imports?: string[];\n css?: string[];\n };\n}\n\n/**\n * Preload manifest mapping short keys to source paths.\n * Generated by viteAlephaSsrPreload plugin at build time.\n */\nexport type PreloadManifest = Record<string, string>;\n","import { $hook, $inject, Alepha } from \"alepha\";\nimport { SSRManifestProvider } from \"./SSRManifestProvider.ts\";\n\n/**\n * Adds HTTP Link headers for preloading entry assets.\n *\n * Benefits:\n * - Early Hints (103): Servers can send preload hints before the full response\n * - CDN optimization: Many CDNs use Link headers to optimize asset delivery\n * - Browser prefetching: Browsers can start fetching resources earlier\n *\n * The Link header is computed once at first request and cached for reuse.\n */\nexport class ReactPreloadProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly ssrManifest = $inject(SSRManifestProvider);\n\n /**\n * Cached Link header value - computed once, reused for all requests.\n */\n protected cachedLinkHeader: string | null | undefined;\n\n /**\n * Build the Link header string from entry assets.\n *\n * Format: <url>; rel=preload; as=type, <url>; rel=modulepreload\n *\n * @returns Link header string or null if no assets\n */\n protected buildLinkHeader(): string | null {\n const assets = this.ssrManifest.getEntryAssets();\n if (!assets) return null;\n\n const links: string[] = [];\n\n // CSS - preload as style\n for (const css of assets.css) {\n links.push(`<${css}>; rel=preload; as=style`);\n }\n\n // JS - modulepreload for ES modules\n if (assets.js) {\n links.push(`<${assets.js}>; rel=modulepreload`);\n }\n\n return links.length > 0 ? links.join(\", \") : null;\n }\n\n /**\n * Get the cached Link header, computing it on first access.\n */\n protected getLinkHeader(): string | null {\n if (this.cachedLinkHeader === undefined) {\n this.cachedLinkHeader = this.buildLinkHeader();\n }\n return this.cachedLinkHeader;\n }\n\n /**\n * Add Link header to HTML responses for asset preloading.\n */\n protected readonly onResponse = $hook({\n on: \"server:onResponse\",\n priority: \"first\",\n handler: ({ response }) => {\n // Only add to HTML responses (SSR pages)\n const contentType = response.headers[\"content-type\"];\n if (!contentType?.includes(\"text/html\")) {\n return;\n }\n\n const linkHeader = this.getLinkHeader();\n if (!linkHeader) {\n return;\n }\n\n // Append to existing Link header if present\n if (response.headers.link) {\n response.headers.link = `${response.headers.link}, ${linkHeader}`;\n } else {\n response.headers.link = linkHeader;\n }\n },\n });\n}\n","import { $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { AlephaContext } from \"alepha/react\";\nimport type { SimpleHead } from \"alepha/react/head\";\nimport { createElement, type ReactNode } from \"react\";\nimport { renderToString } from \"react-dom/server\";\nimport ErrorViewer from \"../components/ErrorViewer.tsx\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport type { ReactRouterState } from \"./ReactPageProvider.ts\";\n\n/**\n * Handles HTML streaming for SSR.\n *\n * Uses hardcoded HTML structure - all customization via $head primitive.\n * Pre-encodes static parts as Uint8Array for zero-copy streaming.\n */\nexport class ReactServerTemplateProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n\n /**\n * Shared TextEncoder - reused across all requests.\n */\n protected readonly encoder = new TextEncoder();\n\n /**\n * Pre-encoded static HTML parts for zero-copy streaming.\n */\n protected readonly SLOTS = {\n DOCTYPE: this.encoder.encode(\"<!DOCTYPE html>\\n\"),\n HTML_OPEN: this.encoder.encode(\"<html\"),\n HTML_CLOSE: this.encoder.encode(\">\\n\"),\n HEAD_OPEN: this.encoder.encode(\"<head>\"),\n HEAD_CLOSE: this.encoder.encode(\"</head>\\n\"),\n BODY_OPEN: this.encoder.encode(\"<body\"),\n BODY_CLOSE: this.encoder.encode(\">\\n\"),\n ROOT_OPEN: this.encoder.encode('<div id=\"root\">'),\n ROOT_CLOSE: this.encoder.encode(\"</div>\\n\"),\n BODY_HTML_CLOSE: this.encoder.encode(\"</body>\\n</html>\"),\n HYDRATION_PREFIX: this.encoder.encode(\n '<script id=\"__ssr\" type=\"application/json\">',\n ),\n HYDRATION_SUFFIX: this.encoder.encode(\"</script>\"),\n } as const;\n\n /**\n * Early head content (charset, viewport, entry assets).\n * Set once during configuration, reused for all requests.\n */\n protected earlyHeadContent = \"\";\n\n /**\n * Root element ID for React mounting.\n */\n public readonly rootId = \"root\";\n\n /**\n * Regex for extracting root div content from HTML.\n */\n public readonly rootDivRegex = new RegExp(\n `<div[^>]*\\\\s+id=[\"']${this.rootId}[\"'][^>]*>([\\\\s\\\\S]*?)<\\\\/div>`,\n \"i\",\n );\n\n /**\n * Extract content inside the root div from HTML.\n */\n public extractRootContent(html: string): string | undefined {\n return html.match(this.rootDivRegex)?.[1];\n }\n\n /**\n * Set early head content (charset, viewport, entry assets).\n * Called once during server configuration.\n */\n public setEarlyHeadContent(\n entryAssets: string,\n globalHead?: SimpleHead,\n ): void {\n const charset = globalHead?.charset ?? \"UTF-8\";\n const viewport =\n globalHead?.viewport ?? \"width=device-width, initial-scale=1\";\n\n this.earlyHeadContent =\n `<meta charset=\"${this.escapeHtml(charset)}\">\\n` +\n `<meta name=\"viewport\" content=\"${this.escapeHtml(viewport)}\">\\n` +\n entryAssets;\n }\n\n /**\n * Render attributes record to HTML string.\n */\n public renderAttributes(attrs?: Record<string, string>): string {\n if (!attrs) return \"\";\n const entries = Object.entries(attrs);\n if (entries.length === 0) return \"\";\n return entries\n .map(([key, value]) => ` ${key}=\"${this.escapeHtml(value)}\"`)\n .join(\"\");\n }\n\n /**\n * Render head content (title, meta, link, script tags).\n */\n public renderHeadContent(head?: SimpleHead): string {\n if (!head) return \"\";\n\n let content = \"\";\n\n if (head.title) {\n content += `<title>${this.escapeHtml(head.title)}</title>\\n`;\n }\n\n if (head.meta) {\n for (const meta of head.meta) {\n if (meta.property) {\n content += `<meta property=\"${this.escapeHtml(meta.property)}\" content=\"${this.escapeHtml(meta.content)}\">\\n`;\n } else if (meta.name) {\n content += `<meta name=\"${this.escapeHtml(meta.name)}\" content=\"${this.escapeHtml(meta.content)}\">\\n`;\n }\n }\n }\n\n if (head.link) {\n for (const link of head.link) {\n content += `<link rel=\"${this.escapeHtml(link.rel)}\" href=\"${this.escapeHtml(link.href)}\"`;\n if (link.type) content += ` type=\"${this.escapeHtml(link.type)}\"`;\n if (link.as) content += ` as=\"${this.escapeHtml(link.as)}\"`;\n if (link.crossorigin != null) content += ' crossorigin=\"\"';\n content += \">\\n\";\n }\n }\n\n if (head.script) {\n for (const script of head.script) {\n if (typeof script === \"string\") {\n content += `<script>${script}</script>\\n`;\n } else {\n const { content: scriptContent, ...rest } = script;\n const attrs = Object.entries(rest)\n .filter(([, v]) => v !== false && v !== undefined)\n .map(([k, v]) =>\n v === true ? k : `${k}=\"${this.escapeHtml(String(v))}\"`,\n )\n .join(\" \");\n content += scriptContent\n ? `<script ${attrs}>${scriptContent}</script>\\n`\n : `<script ${attrs}></script>\\n`;\n }\n }\n }\n\n return content;\n }\n\n /**\n * Escape HTML special characters.\n */\n public escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#039;\");\n }\n\n /**\n * Safely serialize data to JSON for embedding in HTML.\n */\n public safeJsonSerialize(data: unknown): string {\n return JSON.stringify(data)\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/&/g, \"\\\\u0026\");\n }\n\n /**\n * Build hydration data from router state.\n */\n public buildHydrationData(state: ReactRouterState): HydrationData {\n const layers = state.layers.map((layer) => ({\n part: layer.part,\n name: layer.name,\n config: layer.config,\n props: layer.props,\n error: layer.error\n ? {\n ...layer.error,\n name: layer.error.name,\n message: layer.error.message,\n stack: !this.alepha.isProduction() ? layer.error.stack : undefined,\n }\n : undefined,\n }));\n\n return {\n \"alepha.react.router.layers\": layers,\n ...this.alepha.store.exportAtoms(\"current\"),\n };\n }\n\n // ---------------------------------------------------------------------------\n // Core streaming methods\n // ---------------------------------------------------------------------------\n\n /**\n * Pipe React stream to controller with backpressure handling.\n * Returns true if stream completed successfully, false if error occurred.\n */\n protected async pipeReactStream(\n controller: ReadableStreamDefaultController<Uint8Array>,\n reactStream: ReadableStream<Uint8Array>,\n state: ReactRouterState,\n ): Promise<boolean> {\n const reader = reactStream.getReader();\n\n try {\n while (true) {\n // Backpressure: wait if buffer is full\n if (controller.desiredSize !== null && controller.desiredSize <= 0) {\n await new Promise<void>((resolve) => queueMicrotask(resolve));\n }\n\n const { done, value } = await reader.read();\n if (done) break;\n controller.enqueue(value);\n }\n return true;\n } catch (error) {\n this.log.error(\"React stream error\", error);\n controller.enqueue(\n this.encoder.encode(\n this.renderErrorToString(\n error instanceof Error ? error : new Error(String(error)),\n state,\n ),\n ),\n );\n return false;\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Stream complete HTML document (head already closed).\n * Used by both createHtmlStream and late phase of createEarlyHtmlStream.\n */\n protected async streamBodyAndClose(\n controller: ReadableStreamDefaultController<Uint8Array>,\n reactStream: ReadableStream<Uint8Array>,\n state: ReactRouterState,\n hydration: boolean,\n ): Promise<void> {\n const { encoder, SLOTS: slots } = this;\n\n // Body open\n controller.enqueue(slots.BODY_OPEN);\n controller.enqueue(\n encoder.encode(this.renderAttributes(state.head?.bodyAttributes)),\n );\n controller.enqueue(slots.BODY_CLOSE);\n\n // Root + React content\n controller.enqueue(slots.ROOT_OPEN);\n await this.pipeReactStream(controller, reactStream, state);\n controller.enqueue(slots.ROOT_CLOSE);\n\n // Hydration\n if (hydration) {\n controller.enqueue(slots.HYDRATION_PREFIX);\n controller.enqueue(\n encoder.encode(this.safeJsonSerialize(this.buildHydrationData(state))),\n );\n controller.enqueue(slots.HYDRATION_SUFFIX);\n }\n\n controller.enqueue(slots.BODY_HTML_CLOSE);\n }\n\n // ---------------------------------------------------------------------------\n // Public streaming APIs\n // ---------------------------------------------------------------------------\n\n /**\n * Create HTML stream with early head optimization.\n *\n * Flow:\n * 1. Send DOCTYPE, <html>, <head> open, entry preloads (IMMEDIATE)\n * 2. Run async work (page loaders)\n * 3. Send rest of head, body, React content, hydration\n */\n public createEarlyHtmlStream(\n globalHead: SimpleHead,\n asyncWork: () => Promise<\n | { state: ReactRouterState; reactStream: ReadableStream<Uint8Array> }\n | { redirect: string }\n | null\n >,\n options: {\n hydration?: boolean;\n state?: ReactRouterState;\n onError?: (error: unknown) => void;\n } = {},\n ): ReadableStream<Uint8Array> {\n const { hydration = true, onError } = options;\n const { encoder, SLOTS: slots } = this;\n\n let headClosed = false;\n let bodyStarted = false;\n let routerState: ReactRouterState | undefined = options.state;\n\n return new ReadableStream<Uint8Array>({\n start: async (controller) => {\n try {\n // === EARLY PHASE (before async work) ===\n controller.enqueue(slots.DOCTYPE);\n controller.enqueue(slots.HTML_OPEN);\n controller.enqueue(\n encoder.encode(this.renderAttributes(globalHead?.htmlAttributes)),\n );\n controller.enqueue(slots.HTML_CLOSE);\n controller.enqueue(slots.HEAD_OPEN);\n if (this.earlyHeadContent) {\n controller.enqueue(encoder.encode(this.earlyHeadContent));\n }\n\n // === ASYNC WORK ===\n const result = await asyncWork();\n\n // Handle redirect\n if (!result || \"redirect\" in result) {\n if (result && \"redirect\" in result) {\n this.log.debug(\"Loader redirect, using meta refresh\", {\n redirect: result.redirect,\n });\n controller.enqueue(\n encoder.encode(\n `<meta http-equiv=\"refresh\" content=\"0; url=${this.escapeHtml(result.redirect)}\">\\n`,\n ),\n );\n }\n controller.enqueue(slots.HEAD_CLOSE);\n controller.enqueue(encoder.encode(\"<body></body></html>\"));\n controller.close();\n return;\n }\n\n const { state, reactStream } = result;\n routerState = state;\n\n // === LATE PHASE (after async work) ===\n controller.enqueue(\n encoder.encode(this.renderHeadContent(state.head)),\n );\n controller.enqueue(slots.HEAD_CLOSE);\n headClosed = true;\n bodyStarted = true;\n\n await this.streamBodyAndClose(\n controller,\n reactStream,\n state,\n hydration,\n );\n controller.close();\n } catch (error) {\n onError?.(error);\n try {\n this.injectErrorHtml(controller, error, routerState, {\n headClosed,\n bodyStarted,\n });\n controller.close();\n } catch {\n controller.error(error);\n }\n }\n },\n });\n }\n\n /**\n * Create HTML stream (non-early version, for testing/prerender).\n */\n public createHtmlStream(\n reactStream: ReadableStream<Uint8Array>,\n state: ReactRouterState,\n options: { hydration?: boolean; onError?: (error: unknown) => void } = {},\n ): ReadableStream<Uint8Array> {\n const { hydration = true, onError } = options;\n const { encoder, SLOTS: slots } = this;\n\n return new ReadableStream<Uint8Array>({\n start: async (controller) => {\n try {\n // Head\n controller.enqueue(slots.DOCTYPE);\n controller.enqueue(slots.HTML_OPEN);\n controller.enqueue(\n encoder.encode(this.renderAttributes(state.head?.htmlAttributes)),\n );\n controller.enqueue(slots.HTML_CLOSE);\n controller.enqueue(slots.HEAD_OPEN);\n if (this.earlyHeadContent) {\n controller.enqueue(encoder.encode(this.earlyHeadContent));\n }\n controller.enqueue(\n encoder.encode(this.renderHeadContent(state.head)),\n );\n controller.enqueue(slots.HEAD_CLOSE);\n\n // Body (shared logic)\n await this.streamBodyAndClose(\n controller,\n reactStream,\n state,\n hydration,\n );\n controller.close();\n } catch (error) {\n onError?.(error);\n controller.error(error);\n }\n },\n });\n }\n\n // ---------------------------------------------------------------------------\n // Error handling\n // ---------------------------------------------------------------------------\n\n /**\n * Inject error HTML when streaming fails.\n */\n protected injectErrorHtml(\n controller: ReadableStreamDefaultController<Uint8Array>,\n error: unknown,\n routerState: ReactRouterState | undefined,\n streamState: { headClosed: boolean; bodyStarted: boolean },\n ): void {\n const { encoder, SLOTS: slots } = this;\n\n if (!streamState.headClosed) {\n controller.enqueue(\n encoder.encode(this.renderHeadContent(routerState?.head)),\n );\n controller.enqueue(slots.HEAD_CLOSE);\n }\n\n if (!streamState.bodyStarted) {\n controller.enqueue(slots.BODY_OPEN);\n controller.enqueue(\n encoder.encode(\n this.renderAttributes(routerState?.head?.bodyAttributes),\n ),\n );\n controller.enqueue(slots.BODY_CLOSE);\n controller.enqueue(slots.ROOT_OPEN);\n }\n\n controller.enqueue(\n encoder.encode(\n this.renderErrorToString(\n error instanceof Error ? error : new Error(String(error)),\n routerState,\n ),\n ),\n );\n\n controller.enqueue(slots.ROOT_CLOSE);\n\n if (routerState) {\n controller.enqueue(slots.HYDRATION_PREFIX);\n controller.enqueue(\n encoder.encode(\n this.safeJsonSerialize(this.buildHydrationData(routerState)),\n ),\n );\n controller.enqueue(slots.HYDRATION_SUFFIX);\n }\n\n controller.enqueue(slots.BODY_HTML_CLOSE);\n }\n\n /**\n * Render error to HTML string.\n */\n protected renderErrorToString(\n error: Error,\n routerState: ReactRouterState | undefined,\n ): string {\n this.log.error(\"SSR rendering error\", error);\n\n let errorElement: ReactNode;\n\n if (routerState?.onError) {\n try {\n const result = routerState.onError(error, routerState);\n if (result instanceof Redirection) {\n this.log.warn(\"Error handler returned Redirection but headers sent\", {\n redirect: result.redirect,\n });\n } else if (result != null) {\n errorElement = result;\n }\n } catch (handlerError) {\n this.log.error(\"Error handler threw\", handlerError);\n }\n }\n\n if (!errorElement) {\n errorElement = createElement(ErrorViewer, {\n error,\n alepha: this.alepha,\n });\n }\n\n const wrappedElement = createElement(\n AlephaContext.Provider,\n { value: this.alepha },\n errorElement,\n );\n\n try {\n return renderToString(wrappedElement);\n } catch (renderError) {\n this.log.error(\"Failed to render error component\", renderError);\n return error.message;\n }\n }\n}\n\n/**\n * Hydration state serialized to a JSON script tag with id=\"__ssr\"\n */\nexport interface HydrationData {\n \"alepha.react.router.layers\": Array<{\n part?: string;\n name?: string;\n config?: Record<string, any>;\n props?: Record<string, any>;\n error?: { name: string; message: string; stack?: string };\n }>;\n [key: string]: unknown;\n}\n","import { join } from \"node:path\";\nimport {\n $atom,\n $env,\n $hook,\n $inject,\n $state,\n Alepha,\n type Middleware,\n OPTIONS,\n PipelineHandler,\n type Static,\n t,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { ServerHeadProvider } from \"alepha/react/head\";\nimport { type ServerHandler, ServerRouterProvider } from \"alepha/server\";\nimport { ServerLinksProvider } from \"alepha/server/links\";\nimport { ServerStaticProvider } from \"alepha/server/static\";\nimport { FileSystemProvider } from \"alepha/system\";\nimport { renderToReadableStream } from \"react-dom/server\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport {\n $page,\n type PagePrimitiveRenderOptions,\n type PagePrimitiveRenderResult,\n} from \"../primitives/$page.ts\";\nimport {\n type PageRoute,\n ReactPageProvider,\n type ReactRouterState,\n reactPageOptions,\n} from \"./ReactPageProvider.ts\";\nimport { ReactServerTemplateProvider } from \"./ReactServerTemplateProvider.ts\";\nimport { SSRManifestProvider } from \"./SSRManifestProvider.ts\";\n\n/**\n * React server provider responsible for SSR and static file serving.\n *\n * Coordinates between:\n * - ReactPageProvider: Page routing and layer resolution\n * - ReactServerTemplateProvider: HTML template parsing and streaming\n * - ServerHeadProvider: Head content management\n * - SSRManifestProvider: Module preload link collection\n *\n * Uses `react-dom/server` under the hood.\n */\nexport class ReactServerProvider {\n /**\n * SSR response headers - pre-allocated to avoid object creation per request.\n */\n protected readonly SSR_HEADERS = {\n \"content-type\": \"text/html\",\n \"cache-control\": \"no-store, no-cache, must-revalidate, proxy-revalidate\",\n pragma: \"no-cache\",\n expires: \"0\",\n } as const;\n\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly env = $env(envSchema);\n protected readonly pageApi = $inject(ReactPageProvider);\n protected readonly templateProvider = $inject(ReactServerTemplateProvider);\n protected readonly serverHeadProvider = $inject(ServerHeadProvider);\n protected readonly serverStaticProvider = $inject(ServerStaticProvider);\n protected readonly serverRouterProvider = $inject(ServerRouterProvider);\n protected readonly ssrManifestProvider = $inject(SSRManifestProvider);\n\n /**\n * Cached check for ServerLinksProvider - avoids has() lookup per request.\n */\n protected hasServerLinksProvider = false;\n\n protected readonly options = $state(reactServerOptions);\n protected readonly pageOptions = $state(reactPageOptions);\n\n /**\n * Configure the React server provider.\n */\n public readonly onConfigure = $hook({\n on: \"configure\",\n handler: async () => {\n const pages = this.alepha.primitives($page);\n\n const ssrEnabled =\n pages.length > 0 && this.env.REACT_SSR_ENABLED !== false;\n\n this.alepha.store.set(\"alepha.react.server.ssr\", ssrEnabled);\n\n // production mode\n let root = \"\";\n\n // non-serverless mode only -> serve static files\n if (!this.alepha.isServerless() && !this.alepha.isViteDev()) {\n root = await this.getPublicDirectory();\n if (!root) {\n this.log.warn(\n \"Missing static files, static file server will be disabled\",\n );\n } else {\n this.log.debug(`Using static files from: ${root}`);\n await this.configureStaticServer(root);\n }\n }\n\n if (ssrEnabled) {\n this.registerPages();\n this.log.info(\"SSR OK\");\n return;\n }\n\n // no SSR enabled, serve a minimal fallback\n this.log.info(\"SSR is disabled\");\n },\n });\n\n /**\n * Register all pages as server routes.\n */\n protected registerPages(): void {\n // Set up early head content (entry assets)\n this.setupEarlyHeadContent();\n\n // Cache ServerLinksProvider check at startup\n this.hasServerLinksProvider = this.alepha.has(ServerLinksProvider);\n\n for (const page of this.pageApi.getPages()) {\n if (page.component || page.lazy || page.redirect) {\n this.log.debug(`+ ${page.match} -> ${page.name}`);\n\n // Collect middleware from the entire parent chain + own page.\n // Parent middleware runs first (outermost → innermost).\n const allMiddleware = this.collectMiddleware(page);\n\n // Separate $cache from server-level middleware.\n // $cache is applied inside createHandler around the render function,\n // not around the entire server handler (which works via side effects).\n const cacheMiddleware = allMiddleware.filter(\n (m) => m[OPTIONS]?.name === \"$cache\",\n );\n const serverMiddleware = allMiddleware.filter(\n (m) => m[OPTIONS]?.name !== \"$cache\",\n );\n\n const rawHandler = this.createHandler(page, cacheMiddleware);\n const handler = serverMiddleware.length\n ? new PipelineHandler(rawHandler, serverMiddleware)\n : rawHandler;\n\n this.serverRouterProvider.createRoute({\n ...page,\n schema: undefined, // schema is handled by the page primitive provider\n method: \"GET\",\n path: page.match,\n handler,\n });\n }\n }\n }\n\n /**\n * Set up early head content with entry assets.\n *\n * This content is sent immediately when streaming starts, before page loaders run,\n * allowing the browser to start downloading entry.js and CSS files early.\n */\n protected setupEarlyHeadContent(): void {\n const globalHead = this.serverHeadProvider.resolveGlobalHead();\n const manifest = this.ssrManifestProvider.getManifest();\n const faviconTag = this.buildFaviconTag(manifest.favicon);\n\n // Dev mode: use pre-transformed head content from Vite\n if (manifest.devHead) {\n const devContent = faviconTag\n ? `${faviconTag}\\n${manifest.devHead}\\n`\n : `${manifest.devHead}\\n`;\n this.templateProvider.setEarlyHeadContent(devContent, globalHead);\n this.log.debug(\"Early head content set (dev mode)\");\n return;\n }\n\n // Production: build from SSR manifest entry assets\n const parts: string[] = [];\n if (faviconTag) {\n parts.push(faviconTag);\n }\n const assets = this.ssrManifestProvider.getEntryAssets();\n if (assets) {\n for (const css of assets.css) {\n parts.push(`<link rel=\"stylesheet\" href=\"${css}\">`);\n }\n if (assets.js) {\n parts.push(\n `<script type=\"module\" crossorigin=\"\" src=\"${assets.js}\"></script>`,\n );\n }\n }\n\n this.templateProvider.setEarlyHeadContent(\n parts.length > 0 ? `${parts.join(\"\\n\")}\\n` : \"\",\n globalHead,\n );\n\n this.log.debug(\"Early head content set\", {\n parts: parts.length,\n });\n }\n\n /**\n * Build a favicon link tag from the manifest favicon value.\n * Format is \"mimeType:/path\" (e.g., \"image/svg+xml:/favicon.svg\").\n */\n protected buildFaviconTag(favicon: string | undefined): string | undefined {\n if (!favicon) {\n return undefined;\n }\n const colonIndex = favicon.indexOf(\":\");\n if (colonIndex === -1) {\n return undefined;\n }\n const type = favicon.slice(0, colonIndex);\n const href = favicon.slice(colonIndex + 1);\n return `<link rel=\"icon\" type=\"${type}\" href=\"${href}\">`;\n }\n\n /**\n * Get the public directory path where static files are located.\n */\n protected async getPublicDirectory(): Promise<string> {\n const maybe = [\n join(process.cwd(), `dist/${this.options.publicDir}`),\n join(process.cwd(), this.options.publicDir),\n ];\n\n for (const it of maybe) {\n if (await this.fs.exists(it)) {\n return it;\n }\n }\n\n return \"\";\n }\n\n /**\n * Configure the static file server to serve files from the given root directory.\n */\n protected async configureStaticServer(root: string) {\n await this.serverStaticProvider.createStaticServer({\n root,\n cacheControl: {\n maxAge: 3600,\n immutable: true,\n },\n ...this.options.staticServer,\n });\n }\n\n /**\n * Resolve the static file pattern from page options.\n * Returns a compiled RegExp, or `false` if disabled (empty string).\n */\n protected resolveStaticFilePattern(): RegExp | false {\n const pattern = this.pageOptions.staticFilePattern;\n if (!pattern) return false;\n return new RegExp(pattern);\n }\n\n /**\n * Collect middleware from the entire parent chain + the page itself.\n * Parent middleware runs first (outermost → innermost → page).\n */\n protected collectMiddleware(page: PageRoute): Middleware[] {\n const chain: Middleware[][] = [];\n let current: PageRoute | undefined = page;\n\n while (current) {\n if (current.use?.length) {\n chain.unshift(current.use);\n }\n current = current.parent;\n }\n\n return chain.flat();\n }\n\n /**\n * Create the request handler for a page route.\n *\n * When cacheMiddleware is provided, uses a non-streaming path that renders\n * to a string so the result can be cached. Otherwise uses early HTML streaming.\n */\n protected createHandler(\n route: PageRoute,\n cacheMiddleware: Middleware[] = [],\n ): ServerHandler {\n const hasCache = cacheMiddleware.length > 0;\n const isCatchAll = route.match === \"/*\";\n const staticFilePattern = isCatchAll\n ? this.resolveStaticFilePattern()\n : false;\n\n return async (serverRequest) => {\n const { url, reply, query, params } = serverRequest;\n\n // Skip SSR for file-like URLs hitting the catch-all wildcard.\n // Bots and crawlers often probe paths like /hello.txt, /wp-login.php, etc.\n // Rendering a full React page for these is wasteful — return a plain 404 instead.\n // biome-ignore lint/complexity/useOptionalChain: staticFilePattern is `false | RegExp`; optional chaining doesn't narrow `false`\n if (staticFilePattern && staticFilePattern.test(url.pathname)) {\n reply.status = 404;\n reply.headers[\"content-type\"] = \"text/plain\";\n return \"Not Found\";\n }\n\n this.log.trace(\"Rendering page\", { name: route.name });\n\n // Initialize router state\n const state: ReactRouterState = {\n url,\n params,\n query,\n name: route.name,\n onError: () => null,\n layers: [],\n meta: {},\n head: {},\n };\n\n // Set up API links if available\n if (this.hasServerLinksProvider) {\n this.alepha.store.set(\n \"alepha.server.request.apiLinks\",\n await this.alepha.inject(ServerLinksProvider).getUserApiLinks({\n user: (serverRequest as any).user, // TODO: fix type\n authorization: serverRequest.headers.authorization,\n }),\n );\n }\n\n // Check access permissions (walk up the parent chain)\n let target: PageRoute | undefined = route;\n while (target) {\n if (target.can && !target.can()) {\n this.log.warn(\n `Access to page '${route.name}' is forbidden by can() check on '${target.name}'`,\n );\n reply.status = 403;\n reply.headers[\"content-type\"] = \"text/plain\";\n return \"Forbidden\";\n }\n target = target.parent;\n }\n\n await this.alepha.events.emit(\"react:server:render:begin\", {\n request: serverRequest,\n state,\n });\n\n // Apply SSR headers early\n Object.assign(reply.headers, this.SSR_HEADERS);\n\n if (hasCache) {\n // When $cache middleware is present, render to string so the result\n // is serializable. Streaming is not compatible with $cache since\n // ReadableStream cannot be serialized/deserialized.\n const renderFn = async (\n _url: string,\n ): Promise<{ html: string; redirect?: string }> => {\n const { redirect, reactStream } = await this.renderPage(route, state);\n if (redirect) {\n return { redirect, html: \"\" };\n }\n const htmlStream = this.templateProvider.createHtmlStream(\n reactStream!,\n state,\n { hydration: true },\n );\n return { html: await this.streamToString(htmlStream) };\n };\n\n const result = await new PipelineHandler(renderFn, cacheMiddleware).run(\n url.href,\n );\n\n if (result.redirect) {\n reply.status = 302;\n reply.headers.location = result.redirect;\n return;\n }\n\n route.onServerResponse?.(serverRequest);\n reply.body = result.html;\n return;\n }\n\n // Resolve global head for early streaming (htmlAttributes only)\n const globalHead = this.serverHeadProvider.resolveGlobalHead();\n\n // Create optimized HTML stream with early head\n const htmlStream = this.templateProvider.createEarlyHtmlStream(\n globalHead,\n async () => {\n // === ASYNC WORK (runs while early head is being sent) ===\n const result = await this.renderPage(route, state);\n\n if (result.redirect) {\n // Return redirect URL - template provider will inject meta refresh\n // since HTTP headers have already been sent\n return { redirect: result.redirect };\n }\n\n return { state, reactStream: result.reactStream! };\n },\n {\n hydration: true,\n state,\n onError: (error) => {\n if (error instanceof Redirection) {\n this.log.debug(\"Streaming resulted in redirection\", {\n redirect: error.redirect,\n });\n // Can't do redirect after streaming started - already handled above\n } else {\n // disable logging here, it's noisy and duplicate\n // this.log.error(\"HTML stream error\", error);\n }\n },\n },\n );\n\n this.log.trace(\"Page streaming started (early head optimization)\");\n route.onServerResponse?.(serverRequest);\n reply.body = htmlStream.pipeThrough(\n new TransformStream({\n flush: () => {\n this.log.info(\"Page streaming completed\", { name: route.name });\n },\n }),\n );\n };\n }\n\n // ---------------------------------------------------------------------------\n // Core rendering logic - shared between SSR handler and static prerendering\n // ---------------------------------------------------------------------------\n\n /**\n * Core page rendering logic shared between SSR handler and static prerendering.\n *\n * Handles:\n * - Layer resolution (loaders)\n * - Redirect detection\n * - Head content filling\n * - Preload link collection\n * - React stream rendering\n *\n * @param route - The page route to render\n * @param state - The router state\n * @returns Render result with redirect or React stream\n */\n protected async renderPage(\n route: PageRoute,\n state: ReactRouterState,\n ): Promise<{ redirect?: string; reactStream?: ReadableStream<Uint8Array> }> {\n // Resolve page layers (loaders)\n const { redirect } = await this.pageApi.createLayers(route, state);\n if (redirect) {\n this.log.debug(\"Resolver resulted in redirection\", { redirect });\n return { redirect };\n }\n\n // Fill head from route config\n this.serverHeadProvider.fillHead(state);\n\n // Collect and inject modulepreload links for page-specific chunks\n const preloadLinks = this.ssrManifestProvider.collectPreloadLinks(route);\n if (preloadLinks.length > 0) {\n state.head ??= {};\n state.head.link = [...(state.head.link ?? []), ...preloadLinks];\n }\n\n // Render React to stream\n\n const element = this.pageApi.root(state);\n this.alepha.store.set(\"alepha.react.router.state\", state);\n\n const reactStream = await renderToReadableStream(element, {\n onError: (error: unknown) => {\n if (error instanceof Redirection) {\n this.log.warn(\"Redirect during streaming ignored\", {\n redirect: error.redirect,\n });\n } else {\n // disable logging here, it's noisy and duplicate\n // this.log.error(\"Streaming render error\", error);\n }\n },\n });\n\n return { reactStream };\n }\n\n // ---------------------------------------------------------------------------\n // Testing utilities - kept for backwards compatibility with tests\n // ---------------------------------------------------------------------------\n\n /**\n * For testing purposes, renders a page to HTML string.\n * Uses the same streaming code path as production, then collects to string.\n *\n * @param name - Page name to render\n * @param options - Render options (params, query, html, hydration)\n */\n public async render(\n name: string,\n options: PagePrimitiveRenderOptions = {},\n ): Promise<PagePrimitiveRenderResult> {\n const page = this.pageApi.page(name);\n const url = new URL(this.pageApi.url(name, options));\n const state: ReactRouterState = {\n url,\n params: options.params ?? {},\n query: options.query ?? {},\n onError: () => null,\n layers: [],\n meta: {},\n head: {},\n };\n\n this.log.trace(\"Rendering\", { url });\n\n await this.alepha.events.emit(\"react:server:render:begin\", { state });\n\n // Render page and collect the stream into a serializable result.\n // This must happen inside the middleware pipeline so that $cache\n // wraps a function returning { html, redirect? } — not a ReadableStream.\n // The URL string is passed as argument so middleware like $cache can\n // derive a unique cache key per URL (params + query).\n const renderFn = async (\n _url: string,\n ): Promise<{\n html: string;\n redirect?: string;\n }> => {\n const { redirect, reactStream } = await this.renderPage(page, state);\n if (redirect) {\n return { redirect, html: \"\" };\n }\n\n if (!options.html) {\n return { html: await this.streamToString(reactStream!) };\n }\n\n const htmlStream = this.templateProvider.createHtmlStream(\n reactStream!,\n state,\n { hydration: options.hydration ?? true },\n );\n return { html: await this.streamToString(htmlStream) };\n };\n\n const allMiddleware = this.collectMiddleware(page);\n const result = allMiddleware.length\n ? await new PipelineHandler(renderFn, allMiddleware).run(url.href)\n : await renderFn(url.href);\n\n if (result.redirect) {\n return { state, html: \"\", redirect: result.redirect };\n }\n\n await this.alepha.events.emit(\"react:server:render:end\", {\n state,\n html: result.html,\n });\n\n return { state, html: result.html };\n }\n\n /**\n * Collect a ReadableStream into a string.\n */\n protected async streamToString(\n stream: ReadableStream<Uint8Array>,\n ): Promise<string> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n const chunks: string[] = [];\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(decoder.decode(value, { stream: true }));\n }\n chunks.push(decoder.decode()); // Flush remaining\n } finally {\n reader.releaseLock();\n }\n\n return chunks.join(\"\");\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst envSchema = t.object({\n REACT_SSR_ENABLED: t.optional(\n t.boolean({\n description:\n \"Enable or disable server-side rendering (SSR) for React pages. When set to false, pages are rendered client-side only.\",\n }),\n ),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n interface State {\n \"alepha.react.server.ssr\"?: boolean;\n }\n}\n\n/**\n * React server provider configuration atom\n */\n/**\n * Default pattern matching file-like URLs (e.g. /hello.txt, /wp-login.php).\n * Matches paths whose last segment contains a dot followed by 1-10 alphanumeric characters.\n */\nexport const DEFAULT_STATIC_FILE_PATTERN = \"\\\\.[a-zA-Z0-9]{1,10}$\";\n\nexport const reactServerOptions = $atom({\n name: \"alepha.react.server.options\",\n schema: t.object({\n publicDir: t.string(),\n staticServer: t.object({\n disabled: t.boolean(),\n path: t.string({\n description: \"URL path where static files will be served.\",\n }),\n }),\n }),\n default: {\n publicDir: \"public\",\n staticServer: {\n disabled: false,\n path: \"/\",\n },\n },\n});\n\nexport type ReactServerProviderOptions = Static<\n typeof reactServerOptions.schema\n>;\n\ndeclare module \"alepha\" {\n interface State {\n [reactServerOptions.key]: ReactServerProviderOptions;\n }\n}\n","import { $inject, AlephaError } from \"alepha\";\nimport { ServerProvider } from \"alepha/server\";\nimport type {\n PagePrimitiveRenderOptions,\n PagePrimitiveRenderResult,\n} from \"../primitives/$page.ts\";\nimport { ReactServerProvider } from \"../providers/ReactServerProvider.ts\";\nimport { ReactServerTemplateProvider } from \"../providers/ReactServerTemplateProvider.ts\";\nimport { ReactPageService } from \"./ReactPageService.ts\";\n\n/**\n * $page methods for server-side.\n */\nexport class ReactPageServerService extends ReactPageService {\n protected readonly reactServerProvider = $inject(ReactServerProvider);\n protected readonly templateProvider = $inject(ReactServerTemplateProvider);\n protected readonly serverProvider = $inject(ServerProvider);\n\n public async render(\n name: string,\n options: PagePrimitiveRenderOptions = {},\n ): Promise<PagePrimitiveRenderResult> {\n return this.reactServerProvider.render(name, options);\n }\n\n public async fetch(\n pathname: string,\n options: PagePrimitiveRenderOptions = {},\n ): Promise<{\n html: string;\n response: Response;\n }> {\n const response = await fetch(`${this.serverProvider.hostname}/${pathname}`);\n\n const html = await response.text();\n if (options?.html) {\n return { html, response };\n }\n\n // take only text inside the root div\n const rootContent = this.templateProvider.extractRootContent(html);\n if (rootContent !== undefined) {\n return { html: rootContent, response };\n }\n\n throw new AlephaError(\"Invalid HTML response\");\n }\n}\n","import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { BrowserHeadProvider } from \"alepha/react/head\";\nimport { type Route, RouterProvider } from \"alepha/router\";\nimport { ForbiddenError } from \"alepha/server\";\nimport { createElement, type ReactNode } from \"react\";\nimport NotFoundPage from \"../components/NotFound.tsx\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport {\n isPageRoute,\n type PageRoute,\n type PageRouteEntry,\n type PreviousLayerData,\n ReactPageProvider,\n type ReactRouterState,\n} from \"./ReactPageProvider.ts\";\n\nexport interface BrowserRoute extends Route {\n page: PageRoute;\n}\n\n/**\n * Implementation of AlephaRouter for React in browser environment.\n */\nexport class ReactBrowserRouterProvider extends RouterProvider<BrowserRoute> {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly pageApi = $inject(ReactPageProvider);\n protected readonly browserHeadProvider = $inject(BrowserHeadProvider);\n\n public add(entry: PageRouteEntry) {\n this.pageApi.add(entry);\n }\n\n protected readonly configure = $hook({\n on: \"configure\",\n handler: async () => {\n for (const page of this.pageApi.getPages()) {\n // mount only if a view is provided\n if (page.component || page.lazy || page.redirect) {\n this.push({\n path: page.match,\n page,\n });\n }\n }\n },\n });\n\n public async transition(\n url: URL,\n previous: PreviousLayerData[] = [],\n meta = {},\n isStale: () => boolean = () => false,\n ): Promise<string | undefined> {\n const { pathname, search } = url;\n\n const entry: Partial<ReactRouterState> = {\n url,\n query: {},\n params: {},\n layers: [],\n onError: () => null,\n meta,\n };\n\n const state = entry as ReactRouterState;\n\n // Emit both action and transition events\n await this.alepha.events.emit(\"react:action:begin\", {\n type: \"transition\",\n });\n await this.alepha.events.emit(\"react:transition:begin\", {\n previous: this.alepha.store.get(\"alepha.react.router.state\")!,\n state,\n });\n\n try {\n const { route, params } = this.match(pathname);\n\n const query: Record<string, string> = {};\n if (search) {\n for (const [key, value] of new URLSearchParams(search).entries()) {\n query[key] = String(value);\n }\n }\n\n if (route?.page.can) {\n const canAccess = route.page.can();\n if (!canAccess) {\n throw new ForbiddenError(\"Access denied to this page.\");\n }\n }\n\n state.name = route?.page.name;\n state.query = query;\n state.params = params ?? {};\n\n if (isPageRoute(route)) {\n const { redirect } = await this.pageApi.createLayers(\n route.page,\n state,\n previous,\n );\n // A newer navigation already won — bail before committing or\n // emitting any further events. The caller (ReactBrowserProvider)\n // also re-checks staleness, but stopping here avoids running\n // success hooks for a transition the user no longer wants.\n if (isStale()) {\n return;\n }\n if (redirect) {\n return redirect;\n }\n }\n\n if (state.layers.length === 0) {\n state.layers.push({\n name: \"not-found\",\n element: createElement(NotFoundPage),\n index: 0,\n path: \"/\",\n });\n }\n\n await this.alepha.events.emit(\"react:action:success\", {\n type: \"transition\",\n });\n await this.alepha.events.emit(\"react:transition:success\", { state });\n } catch (e) {\n // If we were superseded mid-flight, swallow the error: the user has\n // already moved on, and an error UI for an abandoned page would\n // overwrite the newer page they actually want.\n if (isStale()) {\n return;\n }\n\n this.log.error(\"Transition has failed\", e);\n\n let element: ReactNode | undefined;\n try {\n const result = state.onError(e as Error, state);\n if (result != null && !(result instanceof Redirection)) {\n element = result as ReactNode;\n }\n } catch {\n // error handler itself failed, fall through to default\n }\n\n state.layers = [\n {\n name: \"error\",\n element: element ?? this.pageApi.renderError(e as Error),\n index: 0,\n path: \"/\",\n },\n ];\n\n await this.alepha.events.emit(\"react:action:error\", {\n type: \"transition\",\n error: e as Error,\n });\n await this.alepha.events.emit(\"react:transition:error\", {\n error: e as Error,\n state,\n });\n }\n\n // Final supersession check before any side effects (onLeave/onEnter,\n // store mutation, head rewrite). Stale transitions must be a complete\n // no-op from this point on.\n if (isStale()) {\n return;\n }\n\n // [feature]: local hook for leaving a page\n if (previous) {\n for (let i = 0; i < previous.length; i++) {\n const layer = previous[i];\n if (state.layers[i]?.name !== layer.name && layer.name !== \"error\") {\n this.pageApi.page(layer.name)?.onLeave?.();\n }\n }\n }\n\n // [feature]: local hook for entering a page\n for (let i = 0; i < state.layers.length; i++) {\n const layer = state.layers[i];\n if (previous?.[i]?.name !== layer.name && layer.name !== \"error\") {\n this.pageApi.page(layer.name)?.onEnter?.();\n }\n }\n\n this.alepha.store.set(\"alepha.react.router.state\", state);\n\n await this.alepha.events.emit(\"react:action:end\", {\n type: \"transition\",\n });\n await this.alepha.events.emit(\"react:transition:end\", {\n state,\n });\n\n // Fill and render head from route configurations\n this.browserHeadProvider.fillAndRenderHead(state);\n }\n\n public root(state: ReactRouterState): ReactNode {\n return this.pageApi.root(state);\n }\n}\n","import {\n $atom,\n $hook,\n $inject,\n $state,\n Alepha,\n type State,\n type Static,\n t,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { BrowserHeadProvider } from \"alepha/react/head\";\nimport { LinkProvider } from \"alepha/server/links\";\nimport type { RouterPushOptions } from \"../services/ReactRouter.ts\";\nimport { ReactBrowserRouterProvider } from \"./ReactBrowserRouterProvider.ts\";\nimport type {\n PreviousLayerData,\n ReactRouterState,\n} from \"./ReactPageProvider.ts\";\n\nexport type { RouterPushOptions } from \"../services/ReactRouter.ts\";\n\n/**\n * React browser renderer configuration atom\n */\nexport const reactBrowserOptions = $atom({\n name: \"alepha.react.browser.options\",\n schema: t.object({\n scrollRestoration: t.enum([\"top\", \"manual\"]), // TODO: must be per page?\n /**\n * Intercept clicks on plain `<a href=\"/...\">` anchors and route them\n * through the SPA router, so authors don't need `<Link>` everywhere\n * (notably for SSR/Markdown HTML rendered as raw markup).\n *\n * Skips: modifier keys, non-primary mouse buttons, `target` other than\n * `_self`, `download`, `data-no-router`, non-http(s) schemes, hash-only\n * hrefs, external origins, and clicks already `defaultPrevented`.\n */\n interceptAnchorClicks: t.boolean({ default: true }),\n }),\n default: {\n scrollRestoration: \"top\" as const,\n interceptAnchorClicks: true,\n },\n});\n\nexport type ReactBrowserRendererOptions = Static<\n typeof reactBrowserOptions.schema\n>;\n\ndeclare module \"alepha\" {\n interface State {\n [reactBrowserOptions.key]: ReactBrowserRendererOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class ReactBrowserProvider {\n protected readonly log = $logger();\n protected readonly client = $inject(LinkProvider);\n protected readonly alepha = $inject(Alepha);\n protected readonly router = $inject(ReactBrowserRouterProvider);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly browserHeadProvider = $inject(BrowserHeadProvider);\n\n protected readonly options = $state(reactBrowserOptions);\n\n public get rootId() {\n return \"root\";\n }\n\n protected getRootElement() {\n const root = this.document.getElementById(this.rootId);\n if (root) {\n return root;\n }\n\n const div = this.document.createElement(\"div\");\n div.id = this.rootId;\n\n this.document.body.prepend(div);\n\n return div;\n }\n\n public transitioning?: {\n to: string;\n from?: string;\n };\n\n /**\n * Monotonic counter used to detect stale (superseded) transitions.\n *\n * Each call to `render()` captures `++this.transitionId` and any\n * subsequent `render()` invalidates older in-flight transitions.\n * This prevents a slow page from racing past a newer navigation\n * (e.g. user clicks /pageA which has a 2s loader, then clicks /pageB\n * — pageB must remain the committed page).\n */\n protected transitionId = 0;\n\n public get state(): ReactRouterState {\n return this.alepha.store.get(\"alepha.react.router.state\")!;\n }\n\n /**\n * Accessor for Document DOM API.\n */\n public get document() {\n return window.document;\n }\n\n /**\n * Accessor for History DOM API.\n */\n public get history() {\n return window.history;\n }\n\n /**\n * Accessor for Location DOM API.\n */\n public get location() {\n return window.location;\n }\n\n public get base() {\n const base = import.meta.env?.BASE_URL;\n if (!base || base === \"/\") {\n return \"\";\n }\n\n return base;\n }\n\n public get url(): string {\n const url = this.location.pathname + this.location.search;\n if (this.base) {\n return url.replace(this.base, \"\");\n }\n return url;\n }\n\n public pushState(path: string, replace?: boolean) {\n const url = this.base + path;\n\n if (replace) {\n this.history.replaceState({}, \"\", url);\n } else {\n this.history.pushState({}, \"\", url);\n }\n }\n\n public async invalidate(props?: Record<string, any>) {\n const previous: PreviousLayerData[] = [];\n\n this.log.trace(\"Invalidating layers\");\n\n if (props) {\n const [key] = Object.keys(props);\n const value = props[key];\n\n for (const layer of this.state.layers) {\n if (layer.props?.[key]) {\n previous.push({\n ...layer,\n props: {\n ...layer.props,\n [key]: value,\n },\n });\n break;\n }\n previous.push(layer);\n }\n }\n\n await this.render({ previous });\n }\n\n public async push(\n url: string,\n options: RouterPushOptions = {},\n ): Promise<void> {\n this.log.trace(`Going to ${url}`, {\n url,\n options,\n });\n\n const myTransitionId = ++this.transitionId;\n\n await this.render({\n url,\n previous: options.force ? [] : this.state.layers,\n meta: options.meta,\n transitionId: myTransitionId,\n });\n\n // A newer navigation has superseded us — bail out without touching\n // history, otherwise we'd push a duplicate/stale entry.\n if (myTransitionId !== this.transitionId) {\n return;\n }\n\n // when redirecting in browser\n if (this.state.url.pathname + this.state.url.search !== url) {\n this.pushState(this.state.url.pathname + this.state.url.search);\n return;\n }\n\n this.pushState(url, options.replace);\n }\n\n protected async render(options: RouterRenderOptions = {}): Promise<void> {\n const myTransitionId = options.transitionId ?? ++this.transitionId;\n const previous = options.previous ?? this.state.layers;\n const url = options.url ?? this.url;\n const start = this.dateTimeProvider.now();\n\n this.transitioning = {\n to: url,\n from: this.state?.url.pathname,\n };\n\n this.log.debug(\"Transitioning...\", {\n to: url,\n });\n\n const isStale = () => this.transitionId !== myTransitionId;\n\n const redirect = await this.router.transition(\n new URL(`http://localhost${url}`),\n previous,\n options.meta,\n isStale,\n );\n\n // A newer navigation has superseded us between the time we awaited\n // transition() and now. Drop everything: don't follow redirects, don't\n // log success, don't clear `transitioning` (the newer render owns it).\n if (isStale()) {\n this.log.debug(\"Transition superseded — discarding stale result\", {\n to: url,\n });\n return;\n }\n\n if (redirect) {\n this.log.info(\"Redirecting to\", {\n redirect,\n });\n\n // if redirect is an absolute URL, use window.location.href (full page reload)\n if (redirect.startsWith(\"http\")) {\n window.location.href = redirect;\n } else {\n // if redirect is a relative URL, use render() (single page app)\n return await this.render({ url: redirect });\n }\n }\n\n const ms = this.dateTimeProvider.now().diff(start);\n this.log.info(`Transition OK [${ms}ms]`, this.transitioning);\n\n this.transitioning = undefined;\n }\n\n /**\n * Get embedded layers from the server.\n */\n protected getHydrationState(): ReactHydrationState | undefined {\n try {\n const el = this.document.getElementById(\"__ssr\");\n if (el?.textContent) {\n return JSON.parse(el.textContent) as ReactHydrationState;\n }\n } catch (error) {\n console.error(error);\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n protected readonly onTransitionEnd = $hook({\n on: \"react:transition:end\",\n handler: () => {\n if (\n this.options.scrollRestoration === \"top\" &&\n typeof window !== \"undefined\" &&\n !this.alepha.isTest()\n ) {\n this.log.trace(\"Restoring scroll position to top\");\n window.scrollTo(0, 0);\n }\n },\n });\n\n public readonly ready = $hook({\n on: \"ready\",\n handler: async () => {\n const hydration = this.getHydrationState();\n const previous = hydration?.[\"alepha.react.router.layers\"] ?? [];\n\n if (hydration) {\n // low budget, but works for now\n for (const [key, value] of Object.entries(hydration)) {\n if (key !== \"alepha.react.router.layers\") {\n this.alepha.set(key as keyof State, value);\n }\n }\n }\n\n await this.render({ previous });\n\n const element = this.router.root(this.state);\n\n await this.alepha.events.emit(\"react:browser:render\", {\n element,\n root: this.getRootElement(),\n hydration,\n state: this.state,\n });\n\n window.addEventListener(\"popstate\", () => {\n // when you update silently queryParams or hash, skip rendering\n // if you want to force a rendering, use #go()\n if (this.base + this.state.url.pathname === this.location.pathname) {\n return;\n }\n\n this.log.debug(\"Popstate event triggered - rendering new state\", {\n url: this.location.pathname + this.location.search,\n });\n\n this.render();\n });\n\n this.attachAnchorInterceptor();\n },\n });\n\n /**\n * Attach a delegated click listener that routes plain `<a href=\"/...\">`\n * clicks through the SPA router. Returns a detach function (used in tests).\n *\n * Bails out on modifier keys, non-primary mouse buttons, `target`, `download`,\n * `data-no-router`, hash-only/external/non-http hrefs, and already-prevented\n * events. Honors the runtime `interceptAnchorClicks` flag.\n */\n protected attachAnchorInterceptor(): () => void {\n const onClick = (ev: MouseEvent) => {\n if (!this.options.interceptAnchorClicks) return;\n if (ev.defaultPrevented) return;\n if (ev.button !== 0) return;\n if (ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey) return;\n\n const node = ev.target as Element | null;\n const a = node?.closest?.(\"a\");\n if (!a) return;\n\n if (a.hasAttribute(\"download\")) return;\n if (a.hasAttribute(\"data-no-router\")) return;\n\n const target = a.getAttribute(\"target\");\n if (target && target !== \"_self\") return;\n\n const href = a.getAttribute(\"href\");\n if (!href) return;\n if (href.startsWith(\"#\")) return;\n if (/^[a-z][a-z0-9+.-]*:/i.test(href)) {\n // absolute scheme: only intercept if it points at our own origin\n let url: URL;\n try {\n url = new URL(href);\n } catch {\n return;\n }\n if (url.origin !== this.location.origin) return;\n ev.preventDefault();\n const path = url.pathname + url.search + url.hash;\n this.push(this.stripBase(path)).catch((e) => this.log.error(e));\n return;\n }\n\n ev.preventDefault();\n const url = new URL(href, this.location.href);\n const path = url.pathname + url.search + url.hash;\n this.push(this.stripBase(path)).catch((e) => this.log.error(e));\n };\n\n this.document.addEventListener(\"click\", onClick);\n return () => this.document.removeEventListener(\"click\", onClick);\n }\n\n protected stripBase(path: string): string {\n if (this.base && path.startsWith(this.base)) {\n return path.slice(this.base.length) || \"/\";\n }\n return path;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type ReactHydrationState = {\n \"alepha.react.router.layers\"?: Array<PreviousLayerData>;\n} & {\n [key: string]: any;\n};\n\nexport interface RouterRenderOptions {\n url?: string;\n previous?: PreviousLayerData[];\n meta?: Record<string, any>;\n /**\n * Transition id used to detect supersession by a newer navigation.\n * When omitted, render() allocates a fresh id internally.\n */\n transitionId?: number;\n}\n","import { $inject, Alepha, AlephaError } from \"alepha\";\nimport type { PagePrimitive } from \"../primitives/$page.ts\";\nimport { ReactBrowserProvider } from \"../providers/ReactBrowserProvider.ts\";\nimport {\n type AnchorProps,\n ReactPageProvider,\n type ReactRouterState,\n} from \"../providers/ReactPageProvider.ts\";\n\nexport interface RouterPushOptions {\n replace?: boolean;\n params?: Record<string, string>;\n query?: Record<string, string>;\n meta?: Record<string, any>;\n /**\n * Recreate the whole page, ignoring the current state.\n */\n force?: boolean;\n}\n\n/**\n * Friendly browser router API.\n *\n * Can be safely used server-side, but most methods will be no-op.\n */\nexport class ReactRouter<T extends object> {\n protected readonly alepha = $inject(Alepha);\n protected readonly pageApi = $inject(ReactPageProvider);\n\n public get state(): ReactRouterState {\n return this.alepha.store.get(\"alepha.react.router.state\")!;\n }\n\n public get pages() {\n return this.pageApi.getPages();\n }\n\n public get concretePages() {\n return this.pageApi.getConcretePages();\n }\n\n public get browser(): ReactBrowserProvider | undefined {\n if (this.alepha.isBrowser()) {\n return this.alepha.inject(ReactBrowserProvider);\n }\n // server-side\n return undefined;\n }\n\n public isActive(\n href: string,\n options: {\n startWith?: boolean;\n } = {},\n ): boolean {\n const current = this.state.url.pathname;\n let isActive =\n current === href || current === `${href}/` || `${current}/` === href;\n\n if (options.startWith && !isActive) {\n isActive = current.startsWith(href);\n }\n\n return isActive;\n }\n\n public node(\n name: keyof VirtualRouter<T> | string,\n config: {\n params?: Record<string, any>;\n query?: Record<string, any>;\n } = {},\n ): any {\n // TODO: improve typing (or just remove this method)\n const page = this.pageApi.page(name as string);\n if (!page.lazy && !page.component) {\n return {\n ...page,\n label: page.label ?? page.name,\n children: undefined,\n };\n }\n\n return {\n ...page,\n label: page.label ?? page.name,\n href: this.path(name, config),\n children: undefined,\n };\n }\n\n public path(\n name: keyof VirtualRouter<T> | string,\n config: {\n params?: Record<string, any>;\n query?: Record<string, any>;\n } = {},\n ): string {\n return this.pageApi.pathname(name as string, {\n params: {\n ...this.state?.params,\n ...config.params,\n },\n query: config.query,\n });\n }\n\n /**\n * Reload the current page.\n * This is equivalent to calling `go()` with the current pathname and search.\n */\n public async reload() {\n if (!this.browser) {\n return;\n }\n\n await this.push(this.location.pathname + this.location.search, {\n replace: true,\n force: true,\n });\n }\n\n public getURL(): URL {\n if (!this.browser) {\n return this.state.url;\n }\n\n return new URL(this.location.href);\n }\n\n public get location(): Location {\n if (!this.browser) {\n throw new AlephaError(\"Browser is required\");\n }\n\n return this.browser.location;\n }\n\n public get current(): ReactRouterState {\n return this.state;\n }\n\n public get pathname(): string {\n return this.state.url.pathname;\n }\n\n public get query(): Record<string, string> {\n const query: Record<string, string> = {};\n\n for (const [key, value] of new URLSearchParams(\n this.state.url.search,\n ).entries()) {\n query[key] = String(value);\n }\n\n return query;\n }\n\n public async back() {\n this.browser?.history.back();\n }\n\n public async forward() {\n this.browser?.history.forward();\n }\n\n public async invalidate(props?: Record<string, any>) {\n await this.browser?.invalidate(props);\n }\n\n public async push(path: string, options?: RouterPushOptions): Promise<void>;\n public async push(\n path: keyof VirtualRouter<T>,\n options?: RouterPushOptions,\n ): Promise<void>;\n public async push(\n path: string | keyof VirtualRouter<T>,\n options?: RouterPushOptions,\n ): Promise<void> {\n for (const page of this.pages) {\n if (page.name === path) {\n await this.browser?.push(\n this.path(path as keyof VirtualRouter<T>, options),\n options,\n );\n return;\n }\n }\n\n await this.browser?.push(path as string, options);\n }\n\n public anchor(path: string, options?: RouterPushOptions): AnchorProps;\n public anchor(\n path: keyof VirtualRouter<T>,\n options?: RouterPushOptions,\n ): AnchorProps;\n public anchor(\n path: string | keyof VirtualRouter<T>,\n options: RouterPushOptions = {},\n ): AnchorProps {\n let href = path as string;\n\n for (const page of this.pages) {\n if (page.name === path) {\n href = this.path(path as keyof VirtualRouter<T>, options);\n break;\n }\n }\n\n return {\n href: this.base(href),\n onClick: (ev: any) => {\n ev.stopPropagation();\n ev.preventDefault();\n\n this.push(href, options).catch(console.error);\n },\n };\n }\n\n /**\n * Prepend the base URL to the given path.\n */\n public base(path: string): string {\n const base = import.meta.env?.BASE_URL;\n if (!base || base === \"/\") {\n return path;\n }\n\n return base + path;\n }\n\n /**\n * Set query params.\n *\n * @param record\n * @param options\n */\n public setQueryParams(\n record:\n | Record<string, any>\n | ((queryParams: Record<string, any>) => Record<string, any>),\n options: {\n /**\n * If true, this will add a new entry to the history stack.\n */\n push?: boolean;\n } = {},\n ) {\n const func = typeof record === \"function\" ? record : () => record;\n const search = new URLSearchParams(func(this.query)).toString();\n const path = search ? `${this.pathname}?${search}` : this.pathname;\n const state = this.base(path);\n\n if (options.push) {\n window.history.pushState({}, \"\", state);\n } else {\n window.history.replaceState({}, \"\", state);\n }\n }\n}\n\nexport type VirtualRouter<T> = {\n [K in keyof T as T[K] extends PagePrimitive ? K : never]: T[K];\n};\n","import { useInject } from \"alepha/react\";\nimport { ReactRouter } from \"../services/ReactRouter.ts\";\n\n/**\n * Use this hook to access the React Router instance.\n *\n * You can add a type parameter to specify the type of your application.\n * This will allow you to use the router in a typesafe way.\n *\n * @example\n * class App {\n * home = $page();\n * }\n *\n * const router = useRouter<App>();\n * router.push(\"home\"); // typesafe\n */\nexport const useRouter = <T extends object = any>(): ReactRouter<T> => {\n return useInject(ReactRouter<T>);\n};\n","import { type AnchorHTMLAttributes, createElement } from \"react\";\nimport { useRouter } from \"../hooks/useRouter.ts\";\n\nexport interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string;\n}\n\n/**\n * Link component for client-side navigation.\n *\n * It's a simple wrapper around an anchor (`<a>`) element using the `useRouter` hook.\n */\nconst Link = (props: LinkProps) => {\n const router = useRouter();\n\n return createElement(\n \"a\",\n { ...props, ...router.anchor(props.href) },\n props.children,\n );\n};\n\nexport default Link;\n","import { useState } from \"react\";\nimport type { AnchorProps } from \"../providers/ReactPageProvider.ts\";\nimport { useRouter } from \"./useRouter.ts\";\nimport { useRouterState } from \"./useRouterState.ts\";\n\nexport interface UseActiveOptions {\n href: string;\n startWith?: boolean;\n}\n\n/**\n * Hook to determine if a given route is active and to provide anchor props for navigation.\n * This hook refreshes on router state changes.\n */\nexport const useActive = (args: string | UseActiveOptions): UseActiveHook => {\n useRouterState();\n\n const router = useRouter();\n const [isPending, setPending] = useState(false);\n\n const options: UseActiveOptions =\n typeof args === \"string\" ? { href: args } : { ...args, href: args.href };\n const href = options.href;\n const isActive = router.isActive(href, options);\n\n return {\n isPending,\n isActive,\n anchorProps: {\n href: router.base(href),\n onClick: async (ev?: any) => {\n ev?.stopPropagation();\n ev?.preventDefault();\n if (isActive) return;\n if (isPending) return;\n\n setPending(true);\n try {\n await router.push(href);\n } finally {\n setPending(false);\n }\n },\n },\n };\n};\n\nexport interface UseActiveHook {\n isActive: boolean;\n anchorProps: AnchorProps;\n isPending: boolean;\n}\n","import type { Alepha, Static, TObject } from \"alepha\";\nimport { useAlepha } from \"alepha/react\";\nimport { useEffect, useState } from \"react\";\nimport { useRouter } from \"./useRouter.ts\";\n\n/**\n * Hook to manage query parameters in the URL using a defined schema.\n */\nexport const useQueryParams = <T extends TObject>(\n schema: T,\n options: UseQueryParamsHookOptions = {},\n): [Partial<Static<T>>, (data: Static<T>) => void] => {\n const alepha = useAlepha();\n\n const key = options.key ?? \"q\";\n const router = useRouter();\n const querystring = router.query[key];\n\n const [queryParams = {}, setQueryParams] = useState<Static<T> | undefined>(\n decode(alepha, schema, router.query[key]),\n );\n\n useEffect(() => {\n setQueryParams(decode(alepha, schema, querystring));\n }, [querystring]);\n\n return [\n queryParams,\n (queryParams: Static<T>) => {\n setQueryParams(queryParams);\n router.setQueryParams((data) => {\n return { ...data, [key]: encode(alepha, schema, queryParams) };\n });\n },\n ];\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface UseQueryParamsHookOptions {\n format?: \"base64\" | \"querystring\";\n key?: string;\n push?: boolean;\n}\n\nconst encode = (alepha: Alepha, schema: TObject, data: any) => {\n return btoa(JSON.stringify(alepha.codec.decode(schema, data)));\n};\n\nconst decode = <T extends TObject>(\n alepha: Alepha,\n schema: T,\n data: any,\n): Static<T> | undefined => {\n try {\n return alepha.codec.decode(\n schema,\n JSON.parse(atob(decodeURIComponent(data))),\n );\n } catch {\n return;\n }\n};\n","import { $module } from \"alepha\";\nimport { AlephaDateTime } from \"alepha/datetime\";\nimport { AlephaReact } from \"alepha/react\";\nimport { AlephaReactHead } from \"alepha/react/head\";\nimport { AlephaServer, type ServerRequest } from \"alepha/server\";\nimport { AlephaServerEtag } from \"alepha/server/etag\";\nimport { AlephaServerLinks } from \"alepha/server/links\";\nimport type { ReactNode } from \"react\";\nimport { $page, type PageAnimation } from \"./primitives/$page.ts\";\nimport type { ReactHydrationState } from \"./providers/ReactBrowserProvider.ts\";\nimport {\n ReactPageProvider,\n type ReactRouterState,\n} from \"./providers/ReactPageProvider.ts\";\nimport { ReactPreloadProvider } from \"./providers/ReactPreloadProvider.ts\";\nimport { ReactServerProvider } from \"./providers/ReactServerProvider.ts\";\nimport { ReactServerTemplateProvider } from \"./providers/ReactServerTemplateProvider.ts\";\nimport { SSRManifestProvider } from \"./providers/SSRManifestProvider.ts\";\nimport { ReactPageServerService } from \"./services/ReactPageServerService.ts\";\nimport { ReactPageService } from \"./services/ReactPageService.ts\";\nimport { ReactRouter } from \"./services/ReactRouter.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./index.shared.ts\";\nexport * from \"./providers/ReactBrowserProvider.ts\";\nexport * from \"./providers/ReactPageProvider.ts\";\nexport * from \"./providers/ReactPreloadProvider.ts\";\nexport * from \"./providers/ReactServerProvider.ts\";\nexport * from \"./providers/ReactServerTemplateProvider.ts\";\nexport * from \"./providers/SSRManifestProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n interface State {\n \"alepha.react.router.state\"?: ReactRouterState;\n }\n\n interface Hooks {\n /**\n * Fires when the React application is starting to be rendered on the server.\n */\n \"react:server:render:begin\": {\n request?: ServerRequest;\n state: ReactRouterState;\n };\n /**\n * Fires when the React application has been rendered on the server.\n */\n \"react:server:render:end\": {\n request?: ServerRequest;\n state: ReactRouterState;\n html: string;\n };\n // -----------------------------------------------------------------------------------------------------------------\n /**\n * Fires when the React application is being rendered on the browser.\n *\n * Note: this one is not really necessary, it's a hack because we need to isolate renderer from server code in order\n * to avoid including react-dom/client in server bundles.\n */\n \"react:browser:render\": {\n root: HTMLElement;\n element: ReactNode;\n state: ReactRouterState;\n hydration?: ReactHydrationState;\n };\n // -----------------------------------------------------------------------------------------------------------------\n // SPECIFIC: Route transitions\n /**\n * Fires when a route transition is starting.\n */\n \"react:transition:begin\": {\n previous: ReactRouterState;\n state: ReactRouterState;\n animation?: PageAnimation;\n };\n /**\n * Fires when a route transition has succeeded.\n */\n \"react:transition:success\": {\n state: ReactRouterState;\n };\n /**\n * Fires when a route transition has failed.\n */\n \"react:transition:error\": {\n state: ReactRouterState;\n error: Error;\n };\n /**\n * Fires when a route transition has completed, regardless of success or failure.\n */\n \"react:transition:end\": {\n state: ReactRouterState;\n };\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Provides declarative routing with the `$page` primitive for building type-safe React routes.\n *\n * This module enables:\n * - URL pattern matching with parameters (e.g., `/users/:id`)\n * - Nested routing with parent-child relationships\n * - Type-safe URL parameter and query string validation\n * - Server-side data fetching with the `loader` function\n * - Lazy loading and code splitting\n * - Page animations and error handling\n *\n * @see {@link $page}\n * @module alepha.react.router\n */\nexport const AlephaReactRouter = $module({\n name: \"alepha.react.router\",\n primitives: [$page],\n services: [\n ReactPageProvider,\n ReactPageService,\n ReactPreloadProvider,\n ReactRouter,\n ReactServerProvider,\n ReactServerTemplateProvider,\n SSRManifestProvider,\n ReactPageServerService,\n ],\n register: (alepha) =>\n alepha\n .with(AlephaReact)\n .with(AlephaReactHead)\n .with(AlephaDateTime)\n .with(AlephaServer)\n .with(AlephaServerEtag)\n .with(AlephaServerLinks)\n .with({\n provide: ReactPageService,\n use: ReactPageServerService,\n })\n .with(SSRManifestProvider)\n .with(ReactServerTemplateProvider)\n .with(ReactPreloadProvider)\n .with(ReactServerProvider)\n .with(ReactPageProvider)\n .with(ReactRouter),\n});\n"],"mappings":"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"}