@alepha/react 0.14.2 → 0.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/auth/index.browser.js +29 -14
  2. package/dist/auth/index.browser.js.map +1 -1
  3. package/dist/auth/index.js +960 -195
  4. package/dist/auth/index.js.map +1 -1
  5. package/dist/core/index.d.ts +4 -0
  6. package/dist/core/index.d.ts.map +1 -1
  7. package/dist/core/index.js +7 -4
  8. package/dist/core/index.js.map +1 -1
  9. package/dist/head/index.browser.js +59 -19
  10. package/dist/head/index.browser.js.map +1 -1
  11. package/dist/head/index.d.ts +99 -560
  12. package/dist/head/index.d.ts.map +1 -1
  13. package/dist/head/index.js +92 -87
  14. package/dist/head/index.js.map +1 -1
  15. package/dist/router/index.browser.js +30 -15
  16. package/dist/router/index.browser.js.map +1 -1
  17. package/dist/router/index.d.ts +616 -192
  18. package/dist/router/index.d.ts.map +1 -1
  19. package/dist/router/index.js +961 -196
  20. package/dist/router/index.js.map +1 -1
  21. package/package.json +4 -4
  22. package/src/auth/__tests__/$auth.spec.ts +188 -0
  23. package/src/core/__tests__/Router.spec.tsx +169 -0
  24. package/src/core/hooks/useAction.browser.spec.tsx +569 -0
  25. package/src/core/hooks/useAction.ts +11 -0
  26. package/src/form/hooks/useForm.browser.spec.tsx +366 -0
  27. package/src/head/helpers/SeoExpander.spec.ts +203 -0
  28. package/src/head/hooks/useHead.spec.tsx +288 -0
  29. package/src/head/index.ts +11 -28
  30. package/src/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
  31. package/src/head/providers/BrowserHeadProvider.ts +25 -19
  32. package/src/head/providers/HeadProvider.ts +76 -10
  33. package/src/head/providers/ServerHeadProvider.ts +22 -138
  34. package/src/i18n/__tests__/integration.spec.tsx +239 -0
  35. package/src/i18n/components/Localize.spec.tsx +357 -0
  36. package/src/i18n/hooks/useI18n.browser.spec.tsx +438 -0
  37. package/src/i18n/providers/I18nProvider.spec.ts +389 -0
  38. package/src/router/__tests__/page-head-browser.browser.spec.ts +91 -0
  39. package/src/router/__tests__/page-head.spec.ts +44 -0
  40. package/src/router/__tests__/seo-head.spec.ts +121 -0
  41. package/src/router/atoms/ssrManifestAtom.ts +60 -0
  42. package/src/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
  43. package/src/router/errors/Redirection.ts +1 -1
  44. package/src/router/index.shared.ts +1 -0
  45. package/src/router/index.ts +16 -2
  46. package/src/router/primitives/$page.browser.spec.tsx +702 -0
  47. package/src/router/primitives/$page.spec.tsx +702 -0
  48. package/src/router/primitives/$page.ts +46 -10
  49. package/src/router/providers/ReactBrowserProvider.ts +14 -29
  50. package/src/router/providers/ReactBrowserRouterProvider.ts +5 -0
  51. package/src/router/providers/ReactPageProvider.ts +11 -4
  52. package/src/router/providers/ReactServerProvider.spec.tsx +316 -0
  53. package/src/router/providers/ReactServerProvider.ts +331 -315
  54. package/src/router/providers/ReactServerTemplateProvider.ts +775 -0
  55. package/src/router/providers/SSRManifestProvider.ts +365 -0
  56. package/src/router/services/ReactPageServerService.ts +5 -3
  57. package/src/router/services/ReactRouter.ts +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["state","ErrorViewer","envSchema","NestedView","route","context","ErrorViewer","NotFoundPage","children","NotFoundPage","envSchema","element"],"sources":["../../src/auth/providers/ReactAuthProvider.ts","../../src/router/services/ReactPageService.ts","../../src/router/primitives/$page.ts","../../src/router/components/NotFound.tsx","../../src/router/components/ErrorViewer.tsx","../../src/router/contexts/RouterLayerContext.ts","../../src/router/errors/Redirection.ts","../../src/router/hooks/useRouterState.ts","../../src/router/components/NestedView.tsx","../../src/router/providers/ReactPageProvider.ts","../../src/router/providers/ReactBrowserRouterProvider.ts","../../src/router/providers/ReactBrowserProvider.ts","../../src/router/services/ReactRouter.ts","../../src/router/providers/ReactServerProvider.ts","../../src/router/services/ReactPageServerService.ts","../../src/router/index.ts","../../src/auth/services/ReactAuth.ts","../../src/auth/hooks/useAuth.ts","../../src/auth/index.ts"],"sourcesContent":["import { $hook, $inject, Alepha } from \"alepha\";\n\nexport class ReactAuthProvider {\n protected readonly alepha = $inject(Alepha);\n\n public readonly onRender = $hook({\n on: \"react:server:render:begin\",\n handler: async ({ request, state }) => {\n if (request?.user) {\n const { token, realm, ...user } = request.user; // do not send token and realm to the client\n this.alepha.store.set(\"alepha.server.request.user\", user); // for hydration, browser, etc...\n state.user = user;\n }\n },\n });\n}\n","import { AlephaError } from \"alepha\";\nimport type { PagePrimitiveRenderOptions, PagePrimitiveRenderResult, } from \"../../router/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 Primitive,\n KIND,\n type Static,\n type TSchema,\n} from \"alepha\";\nimport type { ServerRequest } from \"alepha/server\";\nimport type { ServerRouteCache } from \"alepha/server/cache\";\nimport type { FC, ReactNode } from \"react\";\nimport type { Redirection } from \"../errors/Redirection.ts\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\nimport { ReactPageService } from \"../services/ReactPageService.ts\";\nimport type { ClientOnlyProps } from \"@alepha/react\";\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 `resolve` 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 * **Page Animations**\n * - CSS-based enter/exit animations\n * - Dynamic animations based on page state\n * - Custom timing and easing functions\n *\n * **Lifecycle Management**\n * - Server response hooks for headers and status codes\n * - Page leave handlers for cleanup (browser only)\n * - Permission-based access control\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 * resolve: 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 * resolve: 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 * resolve: 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(\n PagePrimitive<TConfig, TProps, TPropsParent>,\n options,\n );\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 * 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 * Resolve 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 resolve?: (context: PageResolve<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.\n * This will make the page a parent route.\n */\n children?: Array<PagePrimitive> | (() => Array<PagePrimitive>);\n\n /**\n * Define a parent page for nested routing.\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 `resolve` 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 * resolve: 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 * resolve: 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 `alepha/vite`, 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 cache?: ServerRouteCache;\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 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\nexport type ErrorHandler = (\n error: Error,\n state: ReactRouterState,\n) => ReactNode | Redirection | undefined;\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.cache ??= {\n store: {\n provider: \"memory\",\n ttl: [1, \"week\"],\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 public match(url: string): boolean {\n // TODO: Implement a way to match the URL against the pathname\n return false;\n }\n\n public pathname(config: any) {\n // TODO: Implement a way to generate the pathname based on the config\n return this.options.path || \"\";\n }\n}\n\n$page[KIND] = PagePrimitive;\n\n// ---------------------------------------------------------------------------------------------------------------------\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 PageResolve<\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 type { CSSProperties } from \"react\";\n\n/**\n * Default 404 Not Found page component.\n */\n const 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 type { Alepha } from \"alepha\";\nimport { type CSSProperties, useState } from \"react\";\n\ninterface ErrorViewerProps {\n error: Error;\n alepha: Alepha;\n}\n\ninterface StackFrame {\n fn: string;\n file: string;\n line: string;\n col: string;\n raw: string;\n}\n\n/**\n * Error viewer component that displays error details in development mode\n */\nconst ErrorViewer = ({ error, alepha }: ErrorViewerProps) => {\n const [expanded, setExpanded] = useState(false);\n const isProduction = alepha.isProduction();\n\n if (isProduction) {\n return <ErrorViewerProduction />;\n }\n\n const frames = parseStackTrace(error.stack);\n const visibleFrames = expanded ? frames : frames.slice(0, 6);\n const hiddenCount = frames.length - 6;\n\n return (\n <div style={styles.overlay}>\n <div style={styles.container}>\n <Header error={error} />\n <StackTraceSection\n frames={frames}\n visibleFrames={visibleFrames}\n expanded={expanded}\n hiddenCount={hiddenCount}\n onToggle={() => setExpanded(!expanded)}\n />\n </div>\n </div>\n );\n};\n\nexport default ErrorViewer;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Parse stack trace string into structured frames\n */\nfunction parseStackTrace(stack?: string): StackFrame[] {\n if (!stack) return [];\n\n const lines = stack.split(\"\\n\").slice(1);\n const frames: StackFrame[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"at \")) continue;\n\n const frame = parseStackLine(trimmed);\n if (frame) frames.push(frame);\n }\n\n return frames;\n}\n\n/**\n * Parse a single stack trace line into a structured frame\n */\nfunction parseStackLine(line: string): StackFrame | null {\n const withFn = line.match(/^at\\s+(.+?)\\s+\\((.+):(\\d+):(\\d+)\\)$/);\n if (withFn) {\n return {\n fn: withFn[1],\n file: withFn[2],\n line: withFn[3],\n col: withFn[4],\n raw: line,\n };\n }\n\n const withoutFn = line.match(/^at\\s+(.+):(\\d+):(\\d+)$/);\n if (withoutFn) {\n return {\n fn: \"<anonymous>\",\n file: withoutFn[1],\n line: withoutFn[2],\n col: withoutFn[3],\n raw: line,\n };\n }\n\n return { fn: \"\", file: line.replace(/^at\\s+/, \"\"), line: \"\", col: \"\", raw: line };\n}\n\n/**\n * Copy text to clipboard\n */\nfunction copyToClipboard(text: string): void {\n navigator.clipboard.writeText(text).catch((err) => {\n console.error(\"Clipboard error:\", err);\n });\n}\n\n/**\n * Header section with error type and message\n */\nfunction Header({ error }: { error: Error }) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = () => {\n copyToClipboard(error.stack || error.message);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n };\n\n return (\n <div style={styles.header}>\n <div style={styles.headerTop}>\n <div style={styles.badge}>{error.name}</div>\n <button type=\"button\" onClick={handleCopy} style={styles.copyBtn}>\n {copied ? \"Copied\" : \"Copy Stack\"}\n </button>\n </div>\n <h1 style={styles.message}>{error.message}</h1>\n </div>\n );\n}\n\n/**\n * Stack trace section with expandable frames\n */\nfunction StackTraceSection({\n frames,\n visibleFrames,\n expanded,\n hiddenCount,\n onToggle,\n}: {\n frames: StackFrame[];\n visibleFrames: StackFrame[];\n expanded: boolean;\n hiddenCount: number;\n onToggle: () => void;\n}) {\n if (frames.length === 0) return null;\n\n return (\n <div style={styles.stackSection}>\n <div style={styles.stackHeader}>Call Stack</div>\n <div style={styles.frameList}>\n {visibleFrames.map((frame, i) => (\n <StackFrameRow key={i} frame={frame} index={i} />\n ))}\n {!expanded && hiddenCount > 0 && (\n <button type=\"button\" onClick={onToggle} style={styles.expandBtn}>\n Show {hiddenCount} more frames\n </button>\n )}\n {expanded && hiddenCount > 0 && (\n <button type=\"button\" onClick={onToggle} style={styles.expandBtn}>\n Show less\n </button>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Single stack frame row\n */\nfunction StackFrameRow({ frame, index }: { frame: StackFrame; index: number }) {\n const isFirst = index === 0;\n const fileName = frame.file.split(\"/\").pop() || frame.file;\n const dirPath = frame.file.substring(0, frame.file.length - fileName.length);\n\n return (\n <div\n style={{\n ...styles.frame,\n ...(isFirst ? styles.frameFirst : {}),\n }}\n >\n <div style={styles.frameIndex}>{index + 1}</div>\n <div style={styles.frameContent}>\n {frame.fn && (\n <div style={styles.fnName}>\n {frame.fn}\n </div>\n )}\n <div style={styles.filePath}>\n <span style={styles.dirPath}>{dirPath}</span>\n <span style={styles.fileName}>{fileName}</span>\n {frame.line && (\n <span style={styles.lineCol}>\n :{frame.line}:{frame.col}\n </span>\n )}\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * Production error view - minimal information\n */\nfunction ErrorViewerProduction() {\n return (\n <div style={styles.overlay}>\n <div style={styles.prodContainer}>\n <div style={styles.prodIcon}>!</div>\n <h1 style={styles.prodTitle}>Application Error</h1>\n <p style={styles.prodMessage}>\n An unexpected error occurred. Please try again later.\n </p>\n <button\n type=\"button\"\n onClick={() => window.location.reload()}\n style={styles.prodButton}\n >\n Reload Page\n </button>\n </div>\n </div>\n );\n}\n\nconst styles: Record<string, CSSProperties> = {\n overlay: {\n position: \"fixed\",\n inset: 0,\n backgroundColor: \"rgba(0, 0, 0, 0.8)\",\n display: \"flex\",\n alignItems: \"flex-start\",\n justifyContent: \"center\",\n padding: \"40px 20px\",\n overflow: \"auto\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n zIndex: 99999,\n },\n container: {\n width: \"100%\",\n maxWidth: \"960px\",\n backgroundColor: \"#1a1a1a\",\n borderRadius: \"12px\",\n overflow: \"hidden\",\n boxShadow: \"0 25px 50px -12px rgba(0, 0, 0, 0.5)\",\n },\n header: {\n padding: \"24px 28px\",\n borderBottom: \"1px solid #333\",\n background: \"linear-gradient(to bottom, #1f1f1f, #1a1a1a)\",\n },\n headerTop: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: \"16px\",\n },\n badge: {\n display: \"inline-block\",\n padding: \"6px 12px\",\n backgroundColor: \"#dc2626\",\n color: \"#fff\",\n fontSize: \"12px\",\n fontWeight: 600,\n borderRadius: \"6px\",\n letterSpacing: \"0.025em\",\n },\n copyBtn: {\n padding: \"8px 16px\",\n backgroundColor: \"transparent\",\n color: \"#888\",\n fontSize: \"13px\",\n fontWeight: 500,\n border: \"1px solid #444\",\n borderRadius: \"6px\",\n cursor: \"pointer\",\n transition: \"all 0.15s\",\n },\n message: {\n margin: 0,\n fontSize: \"20px\",\n fontWeight: 500,\n color: \"#fff\",\n lineHeight: 1.5,\n wordBreak: \"break-word\",\n },\n stackSection: {\n padding: \"0\",\n },\n stackHeader: {\n padding: \"16px 28px\",\n fontSize: \"11px\",\n fontWeight: 600,\n color: \"#666\",\n textTransform: \"uppercase\",\n letterSpacing: \"0.1em\",\n borderBottom: \"1px solid #2a2a2a\",\n },\n frameList: {\n display: \"flex\",\n flexDirection: \"column\",\n },\n frame: {\n display: \"flex\",\n alignItems: \"flex-start\",\n padding: \"14px 28px\",\n borderBottom: \"1px solid #252525\",\n transition: \"background-color 0.15s\",\n },\n frameFirst: {\n backgroundColor: \"rgba(220, 38, 38, 0.1)\",\n },\n frameIndex: {\n width: \"28px\",\n flexShrink: 0,\n fontSize: \"12px\",\n fontWeight: 500,\n color: \"#555\",\n fontFamily: \"monospace\",\n },\n frameContent: {\n flex: 1,\n minWidth: 0,\n },\n fnName: {\n fontSize: \"14px\",\n fontWeight: 500,\n color: \"#e5e5e5\",\n marginBottom: \"4px\",\n fontFamily:\n 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n },\n filePath: {\n fontSize: \"13px\",\n color: \"#888\",\n fontFamily:\n 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n wordBreak: \"break-all\",\n },\n dirPath: {\n color: \"#555\",\n },\n fileName: {\n color: \"#0ea5e9\",\n },\n lineCol: {\n color: \"#eab308\",\n },\n expandBtn: {\n padding: \"16px 28px\",\n backgroundColor: \"transparent\",\n color: \"#666\",\n fontSize: \"13px\",\n fontWeight: 500,\n border: \"none\",\n borderTop: \"1px solid #252525\",\n cursor: \"pointer\",\n textAlign: \"left\",\n transition: \"all 0.15s\",\n },\n prodContainer: {\n textAlign: \"center\",\n padding: \"60px 40px\",\n backgroundColor: \"#1a1a1a\",\n borderRadius: \"12px\",\n maxWidth: \"400px\",\n },\n prodIcon: {\n width: \"64px\",\n height: \"64px\",\n margin: \"0 auto 24px\",\n backgroundColor: \"#dc2626\",\n borderRadius: \"50%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"32px\",\n fontWeight: 700,\n color: \"#fff\",\n },\n prodTitle: {\n margin: \"0 0 12px\",\n fontSize: \"24px\",\n fontWeight: 600,\n color: \"#fff\",\n },\n prodMessage: {\n margin: \"0 0 28px\",\n fontSize: \"15px\",\n color: \"#888\",\n lineHeight: 1.6,\n },\n prodButton: {\n padding: \"12px 24px\",\n backgroundColor: \"#fff\",\n color: \"#000\",\n fontSize: \"14px\",\n fontWeight: 600,\n border: \"none\",\n borderRadius: \"8px\",\n cursor: \"pointer\",\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 * resolve: 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 { AlephaError } from \"alepha\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\nimport { useStore } from \"@alepha/react\";\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 { memo, type ReactNode, use, useRef, useState } from \"react\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\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 ErrorViewer from \"./ErrorViewer.tsx\";\nimport { ErrorBoundary, useAlepha, useEvents } from \"@alepha/react\";\n\nexport interface NestedViewProps {\n children?: ReactNode;\n errorBoundary?: false | ((error: Error) => 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\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 fallback={props.errorBoundary}>{element}</ErrorBoundary>\n );\n }\n\n const fallback = (error: Error) => {\n const result = onError?.(error, state) ?? <ErrorViewer error={error} alepha={alepha}/>;\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 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 {\n $env,\n $hook,\n $inject,\n Alepha,\n AlephaError,\n type Static,\n type TSchema,\n t,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { createElement, type ReactNode, StrictMode } from \"react\";\nimport { AlephaContext, ClientOnly } from \"@alepha/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\nconst envSchema = t.object({\n REACT_STRICT_MODE: t.boolean({ default: true }),\n});\n\ndeclare module \"alepha\" {\n export interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\n/**\n * Handle page routes for React applications. (Browser and Server)\n */\nexport class ReactPageProvider {\n protected readonly log = $logger();\n protected readonly env = $env(envSchema);\n protected readonly alepha = $inject(Alepha);\n protected readonly pages: PageRoute[] = [];\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 Error(`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.env.REACT_STRICT_MODE) {\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 as Error;\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 as Error;\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 // no resolve, render a basic view by default\n if (!route.resolve) {\n continue;\n }\n\n try {\n const args = Object.create(state);\n Object.assign(args, config, context);\n const props = (await route.resolve?.(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 resolver has failed\", e);\n\n it.error = e as Error;\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(it.route, {\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\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 as Error;\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 });\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 ): 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 const component = await page.lazy(); // load component\n return createElement(component.default, props);\n }\n\n if (page.component) {\n return createElement(page.component, props);\n }\n\n return undefined;\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: this.getErrorHandler(page) ?? ((error) => this.renderError(error)),\n },\n },\n element,\n );\n }\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 cache: true,\n component: NotFoundPage,\n onServerResponse: ({ reply }) => {\n reply.status = 404;\n },\n });\n }\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 _next = 0;\n\n protected nextId(): string {\n this._next += 1;\n return `P${this._next}`;\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\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 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 TransitionOptions {\n previous?: PreviousLayerData[];\n}\n\nexport interface CreateLayersResult {\n redirect?: string;\n state?: ReactRouterState;\n}\n","import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { type Route, RouterProvider } from \"alepha/router\";\nimport { createElement, type ReactNode } from \"react\";\nimport NotFoundPage from \"../components/NotFound.tsx\";\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\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) {\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 ): 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 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 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 this.log.error(\"Transition has failed\", e);\n state.layers = [\n {\n name: \"error\",\n 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 // [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) {\n this.pageApi.page(layer.name)?.onLeave?.();\n }\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\n public root(state: ReactRouterState): ReactNode {\n return this.pageApi.root(state);\n }\n}\n","import {\n $atom,\n $env,\n $hook,\n $inject,\n $use,\n Alepha,\n type State,\n type Static,\n t,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { LinkProvider } from \"alepha/server/links\";\nimport { ReactBrowserRouterProvider } from \"./ReactBrowserRouterProvider.ts\";\nimport type {\n PreviousLayerData,\n ReactRouterState,\n TransitionOptions,\n} from \"./ReactPageProvider.ts\";\nimport type { RouterGoOptions } from \"../services/ReactRouter.ts\";\n\nexport type { RouterGoOptions } from \"../services/ReactRouter.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst envSchema = t.object({\n REACT_ROOT_ID: t.text({ default: \"root\" }),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\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\"]),\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 env = $env(envSchema);\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\n protected readonly options = $use(reactBrowserOptions);\n\n protected getRootElement() {\n const root = this.document.getElementById(this.env.REACT_ROOT_ID);\n if (root) {\n return root;\n }\n\n const div = this.document.createElement(\"div\");\n div.id = this.env.REACT_ROOT_ID;\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 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 go(url: string, options: RouterGoOptions = {}): Promise<void> {\n this.log.trace(`Going to ${url}`, {\n url,\n options,\n });\n\n await this.render({\n url,\n previous: options.force ? [] : this.state.layers,\n meta: options.meta,\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 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 redirect = await this.router.transition(\n new URL(`http://localhost${url}`),\n previous,\n options.meta,\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 if (\"__ssr\" in window && typeof window.__ssr === \"object\") {\n return window.__ssr 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?.layers ?? [];\n\n if (hydration) {\n // low budget, but works for now\n for (const [key, value] of Object.entries(hydration)) {\n if (key !== \"layers\") {\n this.alepha.store.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 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","import { $inject, Alepha } from \"alepha\";\nimport { ReactBrowserProvider } from \"../providers/ReactBrowserProvider.ts\";\nimport {\n type AnchorProps,\n ReactPageProvider,\n type ReactRouterState,\n} from \"../providers/ReactPageProvider.ts\";\nimport type { PagePrimitive } from \"../primitives/$page.ts\";\n\nexport interface RouterGoOptions {\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 ) {\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.go(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 Error(\"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 go(path: string, options?: RouterGoOptions): Promise<void>;\n public async go(\n path: keyof VirtualRouter<T>,\n options?: RouterGoOptions,\n ): Promise<void>;\n public async go(\n path: string | keyof VirtualRouter<T>,\n options?: RouterGoOptions,\n ): Promise<void> {\n for (const page of this.pages) {\n if (page.name === path) {\n await this.browser?.go(\n this.path(path as keyof VirtualRouter<T>, options),\n options,\n );\n return;\n }\n }\n\n await this.browser?.go(path as string, options);\n }\n\n public anchor(path: string, options?: RouterGoOptions): AnchorProps;\n public anchor(\n path: keyof VirtualRouter<T>,\n options?: RouterGoOptions,\n ): AnchorProps;\n public anchor(\n path: string | keyof VirtualRouter<T>,\n options: RouterGoOptions = {},\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.go(href, options).catch(console.error);\n },\n };\n }\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 state = search ? `${this.pathname}?${search}` : this.pathname;\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 { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { $atom, $env, $hook, $inject, $use, Alepha, AlephaError, type Static, t, } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { type ServerHandler, ServerRouterProvider, ServerTimingProvider, } from \"alepha/server\";\nimport { ServerLinksProvider } from \"alepha/server/links\";\nimport { ServerStaticProvider } from \"alepha/server/static\";\nimport { renderToString } from \"react-dom/server\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport { $page, type PagePrimitiveRenderOptions, type PagePrimitiveRenderResult, } from \"../primitives/$page.ts\";\nimport type { ReactHydrationState } from \"./ReactBrowserProvider.ts\";\nimport { type PageRoute, ReactPageProvider, type ReactRouterState, } from \"./ReactPageProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst envSchema = t.object({\n REACT_SSR_ENABLED: t.optional(t.boolean()),\n REACT_ROOT_ID: t.text({ default: \"root\" }), // TODO: move to ReactPageProvider.options?\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n interface State {\n \"alepha.react.server.ssr\"?: boolean;\n \"alepha.react.server.template\"?: string;\n }\n}\n\n/**\n * React server provider configuration atom\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\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * React server provider responsible for SSR and static file serving.\n *\n * Use `react-dom/server` under the hood.\n */\nexport class ReactServerProvider {\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 serverStaticProvider = $inject(ServerStaticProvider);\n protected readonly serverRouterProvider = $inject(ServerRouterProvider);\n protected readonly serverTimingProvider = $inject(ServerTimingProvider);\n\n public readonly ROOT_DIV_REGEX = new RegExp(\n `<div([^>]*)\\\\s+id=[\"']${this.env.REACT_ROOT_ID}[\"']([^>]*)>(.*?)<\\\\/div>`,\n \"is\",\n );\n protected preprocessedTemplate: PreprocessedTemplate | null = null;\n\n protected readonly options = $use(reactServerOptions);\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 // development mode\n if (this.alepha.isViteDev()) {\n await this.configureVite(ssrEnabled);\n return;\n }\n\n // production mode\n let root = \"\";\n\n // non-serverless mode only -> serve static files\n if (!this.alepha.isServerless()) {\n root = 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 await this.registerPages(async () => this.template);\n this.log.info(\"SSR OK\");\n return;\n }\n\n // no SSR enabled, serve index.html for all unmatched routes\n this.log.info(\"SSR is disabled, use History API fallback\");\n this.serverRouterProvider.createRoute({\n path: \"*\",\n handler: async ({ url, reply }) => {\n if (url.pathname.includes(\".\")) {\n // If the request is for a file (e.g., /style.css), do not fallback\n reply.headers[\"content-type\"] = \"text/plain\";\n reply.body = \"Not Found\";\n reply.status = 404;\n return;\n }\n\n reply.headers[\"content-type\"] = \"text/html\";\n\n // serve index.html for all unmatched routes\n return this.template;\n },\n });\n },\n });\n\n public get template() {\n return (\n this.alepha.store.get(\"alepha.react.server.template\") ??\n \"<!DOCTYPE html><html lang='en'><head></head><body></body></html>\"\n );\n }\n\n protected async registerPages(templateLoader: TemplateLoader) {\n // Preprocess template once\n const template = await templateLoader();\n if (template) {\n this.preprocessedTemplate = this.preprocessTemplate(template);\n }\n\n for (const page of this.pageApi.getPages()) {\n if (page.component || page.lazy) {\n this.log.debug(`+ ${page.match} -> ${page.name}`);\n\n this.serverRouterProvider.createRoute({\n ...page,\n schema: undefined, // schema is handled by the page primitive provider for now (shared by browser and server)\n method: \"GET\",\n path: page.match,\n handler: this.createHandler(page, templateLoader),\n });\n }\n }\n }\n\n /**\n * Get the public directory path where static files are located.\n */\n protected getPublicDirectory(): 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 (existsSync(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 * Configure Vite for SSR.\n */\n protected async configureVite(ssrEnabled: boolean) {\n if (!ssrEnabled) {\n // do nothing, vite will handle everything for us\n return;\n }\n\n this.log.info(\"SSR (dev) OK\");\n\n const url = `http://${process.env.SERVER_HOST}:${process.env.SERVER_PORT}`;\n\n await this.registerPages(() =>\n fetch(`${url}/index.html`)\n .then((it) => it.text())\n .catch(() => undefined),\n );\n }\n\n /**\n * For testing purposes, creates a render function that can be used.\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 entry: Partial<ReactRouterState> = {\n url,\n params: options.params ?? {},\n query: options.query ?? {},\n onError: () => null,\n layers: [],\n meta: {},\n };\n const state = entry as ReactRouterState;\n\n this.log.trace(\"Rendering\", {\n url,\n });\n\n await this.alepha.events.emit(\"react:server:render:begin\", {\n state,\n });\n\n const { redirect } = await this.pageApi.createLayers(\n page,\n state as ReactRouterState,\n );\n\n if (redirect) {\n return { state, html: \"\", redirect };\n }\n\n if (!options.html) {\n this.alepha.store.set(\"alepha.react.router.state\", state);\n\n return {\n state,\n html: renderToString(this.pageApi.root(state)),\n };\n }\n\n const template = this.template ?? \"\";\n const html = this.renderToHtml(template, state, options.hydration);\n\n if (html instanceof Redirection) {\n return { state, html: \"\", redirect };\n }\n\n const result = {\n state,\n html,\n };\n\n await this.alepha.events.emit(\"react:server:render:end\", result);\n\n return result;\n }\n\n protected createHandler(\n route: PageRoute,\n templateLoader: TemplateLoader,\n ): ServerHandler {\n return async (serverRequest) => {\n const { url, reply, query, params } = serverRequest;\n const template = await templateLoader();\n if (!template) {\n throw new AlephaError(\"Missing template for SSR rendering\");\n }\n\n this.log.trace(\"Rendering page\", {\n name: route.name,\n });\n\n const entry: Partial<ReactRouterState> = {\n url,\n params,\n query,\n onError: () => null,\n layers: [],\n };\n\n const state = entry as ReactRouterState;\n\n state.name = route.name;\n\n if (this.alepha.has(ServerLinksProvider)) {\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 let target: PageRoute | undefined = route; // TODO: move to PagePrimitiveProvider\n while (target) {\n if (route.can && !route.can()) {\n this.log.warn(\n `Access to page '${route.name}' is forbidden by can() check`,\n )\n // if the page is not accessible, return 403\n reply.status = 403;\n reply.headers[\"content-type\"] = \"text/plain\";\n return \"Forbidden\";\n }\n target = target.parent;\n }\n\n // TODO: SSR strategies\n // - only when googlebot\n // - only child pages\n // if (page.client) {\n // \t// if the page is a client-only page, return 404\n // \treply.status = 200;\n // \treply.headers[\"content-type\"] = \"text/html\";\n // \treply.body = template;\n // \treturn;\n // }\n\n await this.alepha.events.emit(\"react:server:render:begin\", {\n request: serverRequest,\n state,\n });\n\n this.serverTimingProvider.beginTiming(\"createLayers\");\n\n const { redirect } = await this.pageApi.createLayers(route, state);\n\n this.serverTimingProvider.endTiming(\"createLayers\");\n\n if (redirect) {\n this.log.debug(\"Resolver resulted in redirection\", {\n redirect,\n });\n return reply.redirect(redirect);\n }\n\n reply.headers[\"content-type\"] = \"text/html\";\n\n // by default, disable caching for SSR responses\n // some plugins may override this\n reply.headers[\"cache-control\"] =\n \"no-store, no-cache, must-revalidate, proxy-revalidate\";\n reply.headers.pragma = \"no-cache\";\n reply.headers.expires = \"0\";\n\n const html = this.renderToHtml(template, state);\n if (html instanceof Redirection) {\n reply.redirect(\n typeof html.redirect === \"string\"\n ? html.redirect\n : this.pageApi.href(html.redirect),\n );\n this.log.debug(\"Rendering resulted in redirection\", {\n redirect: html.redirect,\n });\n return;\n }\n\n this.log.trace(\"Page rendered to HTML successfully\");\n\n const event = {\n request: serverRequest,\n state,\n html,\n };\n\n await this.alepha.events.emit(\"react:server:render:end\", event);\n\n route.onServerResponse?.(serverRequest);\n\n this.log.trace(\"Page rendered\", {\n name: route.name,\n });\n\n return event.html;\n };\n }\n\n public renderToHtml(\n template: string,\n state: ReactRouterState,\n hydration = true,\n ): string | Redirection {\n const element = this.pageApi.root(state);\n\n // attach react router state to the http request context\n this.alepha.store.set(\"alepha.react.router.state\", state);\n\n this.serverTimingProvider.beginTiming(\"renderToString\");\n let app = \"\";\n try {\n app = renderToString(element);\n } catch (error) {\n this.log.error(\n \"renderToString has failed, fallback to error handler\",\n error,\n );\n const element = state.onError(error as Error, state);\n if (element instanceof Redirection) {\n // if the error is a redirection, return the redirection URL\n return element;\n }\n\n app = renderToString(element);\n this.log.debug(\"Error handled successfully with fallback\");\n }\n this.serverTimingProvider.endTiming(\"renderToString\");\n\n const response = {\n html: template,\n };\n\n if (hydration) {\n const { request, context, ...store } =\n this.alepha.context.als?.getStore() ?? {}; /// TODO: als must be protected, find a way to iterate on alepha.state\n\n const hydrationData: ReactHydrationState = {\n ...store,\n // map react.router.state to the hydration state\n \"alepha.react.router.state\": undefined,\n layers: state.layers.map((it) => ({\n ...it,\n error: it.error\n ? {\n ...it.error,\n name: it.error.name,\n message: it.error.message,\n stack: !this.alepha.isProduction() ? it.error.stack : undefined,\n }\n : undefined,\n index: undefined,\n path: undefined,\n element: undefined,\n route: undefined,\n })),\n };\n\n // create hydration data\n const script = `<script>window.__ssr=${JSON.stringify(hydrationData)}</script>`;\n\n // inject app into template\n this.fillTemplate(response, app, script);\n }\n\n return response.html;\n }\n\n protected preprocessTemplate(template: string): PreprocessedTemplate {\n // Find the body close tag for script injection\n const bodyCloseMatch = template.match(/<\\/body>/i);\n const bodyCloseIndex = bodyCloseMatch?.index ?? template.length;\n\n const beforeScript = template.substring(0, bodyCloseIndex);\n const afterScript = template.substring(bodyCloseIndex);\n\n // Check if there's an existing root div\n const rootDivMatch = beforeScript.match(this.ROOT_DIV_REGEX);\n\n if (rootDivMatch) {\n // Split around the existing root div content\n const beforeDiv = beforeScript.substring(0, rootDivMatch.index!);\n const afterDivStart = rootDivMatch.index! + rootDivMatch[0].length;\n const afterDiv = beforeScript.substring(afterDivStart);\n\n const beforeApp = `${beforeDiv}<div${rootDivMatch[1]} id=\"${this.env.REACT_ROOT_ID}\"${rootDivMatch[2]}>`;\n const afterApp = `</div>${afterDiv}`;\n\n return { beforeApp, afterApp, beforeScript: \"\", afterScript };\n }\n\n // No existing root div, find body tag to inject new div\n const bodyMatch = beforeScript.match(/<body([^>]*)>/i);\n if (bodyMatch) {\n const beforeBody = beforeScript.substring(\n 0,\n bodyMatch.index! + bodyMatch[0].length,\n );\n const afterBody = beforeScript.substring(\n bodyMatch.index! + bodyMatch[0].length,\n );\n\n const beforeApp = `${beforeBody}<div id=\"${this.env.REACT_ROOT_ID}\">`;\n const afterApp = `</div>${afterBody}`;\n\n return { beforeApp, afterApp, beforeScript: \"\", afterScript };\n }\n\n // Fallback: no body tag found, just wrap everything\n return {\n beforeApp: `<div id=\"${this.env.REACT_ROOT_ID}\">`,\n afterApp: `</div>`,\n beforeScript,\n afterScript,\n };\n }\n\n protected fillTemplate(\n response: { html: string },\n app: string,\n script: string,\n ) {\n if (!this.preprocessedTemplate) {\n // Fallback to old logic if preprocessing failed\n this.preprocessedTemplate = this.preprocessTemplate(response.html);\n }\n\n // Pure concatenation - no regex replacements needed\n response.html =\n this.preprocessedTemplate.beforeApp +\n app +\n this.preprocessedTemplate.afterApp +\n script +\n this.preprocessedTemplate.afterScript;\n }\n}\n\ntype TemplateLoader = () => Promise<string | undefined>;\n\ninterface PreprocessedTemplate {\n beforeApp: string;\n afterApp: string;\n beforeScript: string;\n afterScript: string;\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 { 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 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 match = html.match(this.reactServerProvider.ROOT_DIV_REGEX);\n if (match) {\n return { html: match[3], response };\n }\n\n throw new AlephaError(\"Invalid HTML response\");\n }\n}\n","import { AlephaReact } from \"@alepha/react\";\nimport { $module } from \"alepha\";\nimport { $page, type PageAnimation } from \"./primitives/$page.ts\";\nimport { ReactRouter } from \"./services/ReactRouter.ts\";\nimport { ReactPageProvider, type ReactRouterState } from \"./providers/ReactPageProvider.ts\";\nimport { AlephaServer, type ServerRequest } from \"alepha/server\";\nimport type { ReactNode } from \"react\";\nimport type { ReactHydrationState } from \"./providers/ReactBrowserProvider.ts\";\nimport { ReactServerProvider } from \"./providers/ReactServerProvider.ts\";\nimport { ReactPageServerService } from \"./services/ReactPageServerService.ts\";\nimport { AlephaServerCache } from \"alepha/server/cache\";\nimport { AlephaServerLinks } from \"alepha/server/links\";\nimport { ReactPageService } from \"./services/ReactPageService.ts\";\nimport { AlephaDateTime } from \"alepha/datetime\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./index.shared.ts\";\nexport * from \"./providers/ReactPageProvider.ts\";\nexport * from \"./providers/ReactBrowserProvider.ts\";\nexport * from \"./providers/ReactServerProvider.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 \"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 `resolve` 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 ReactRouter, ReactServerProvider, ReactPageServerService],\n register: (alepha) =>\n alepha\n .with(AlephaReact)\n .with(AlephaDateTime)\n .with(AlephaServer)\n .with(AlephaServerCache)\n .with(AlephaServerLinks)\n .with({\n provide: ReactPageService,\n use: ReactPageServerService,\n })\n .with(ReactServerProvider)\n .with(ReactPageProvider)\n .with(ReactRouter),\n});\n","import { ReactBrowserProvider, Redirection } from \"@alepha/react/router\";\nimport { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type { UserAccountToken } from \"alepha/security\";\nimport { HttpClient } from \"alepha/server\";\nimport { alephaServerAuthRoutes, tokenResponseSchema, type Tokens, userinfoResponseSchema } from \"alepha/server/auth\";\nimport { LinkProvider } from \"alepha/server/links\";\n\n/**\n * Browser, SSR friendly, service to handle authentication.\n */\nexport class ReactAuth {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly httpClient = $inject(HttpClient);\n protected readonly linkProvider = $inject(LinkProvider);\n\n protected readonly onBeginTransition = $hook({\n on: \"react:transition:begin\",\n handler: async (event) => {\n if (this.alepha.isBrowser()) {\n Object.defineProperty(event.state, \"user\", {\n get: () => this.user,\n });\n }\n },\n });\n\n protected readonly onFetchRequest = $hook({\n on: \"client:onRequest\",\n handler: async ({ request }) => {\n if (this.alepha.isBrowser() && this.user) {\n // ensure cookies are sent with requests and refresh-able\n request.credentials ??= \"include\";\n }\n },\n });\n\n /**\n * Get the current authenticated user.\n *\n * Alias for `alepha.state.get(\"user\")`\n */\n public get user(): UserAccountToken | undefined {\n return this.alepha.store.get(\"alepha.server.request.user\");\n }\n\n public async ping() {\n const { data } = await this.httpClient.fetch(alephaServerAuthRoutes.userinfo, {\n schema: { response: userinfoResponseSchema },\n });\n\n this.alepha.store.set(\"alepha.server.request.apiLinks\", data.api);\n this.alepha.store.set(\"alepha.server.request.user\", data.user);\n\n return data.user;\n }\n\n public can(action: string): boolean {\n if (!this.user) {\n return false;\n }\n\n return this.linkProvider.can(action);\n }\n\n public async login(\n provider: string,\n options: {\n hostname?: string;\n username?: string;\n password?: string;\n redirect?: string;\n realm?: string;\n [extra: string]: any;\n },\n ): Promise<Tokens> {\n const realmParam = options.realm ? `&realm=${encodeURIComponent(options.realm)}` : \"\";\n\n if (options.username || options.password) {\n const { data } = await this.httpClient.fetch(\n `${options.hostname || \"\"}${alephaServerAuthRoutes.token}?provider=${provider}${realmParam}`,\n {\n method: \"POST\",\n body: JSON.stringify({\n username: options.username,\n password: options.password,\n }),\n schema: { response: tokenResponseSchema },\n },\n );\n\n this.alepha.store.set(\"alepha.server.request.apiLinks\", data.api);\n this.alepha.store.set(\"alepha.server.request.user\", data.user);\n\n return data;\n }\n\n if (this.alepha.isBrowser()) {\n const browser = this.alepha.inject(ReactBrowserProvider);\n const redirect =\n options.redirect ||\n (browser.transitioning\n ? window.location.origin + browser.transitioning.to\n : window.location.href);\n\n const href = `${window.location.origin}${alephaServerAuthRoutes.login}?provider=${provider}${realmParam}&redirect_uri=${encodeURIComponent(redirect)}`;\n\n if (browser.transitioning) {\n throw new Redirection(href);\n } else {\n window.location.href = href;\n return {} as Tokens;\n }\n }\n\n throw new Redirection(\n `${alephaServerAuthRoutes.login}?provider=${provider}${realmParam}&redirect_uri=${options.redirect || \"/\"}`,\n );\n }\n\n public logout() {\n window.location.href = `${alephaServerAuthRoutes.logout}?post_logout_redirect_uri=${encodeURIComponent(window.location.origin)}`;\n }\n}\n","import { useAlepha, useStore } from \"@alepha/react\";\nimport { type HttpVirtualClient, LinkProvider } from \"alepha/server/links\";\nimport { ReactAuth } from \"../services/ReactAuth.ts\";\n\nexport const useAuth = <T extends object = any>() => {\n const alepha = useAlepha();\n const [user] = useStore(\"alepha.server.request.user\");\n\n return {\n user,\n logout: () => {\n alepha.inject(ReactAuth).logout();\n },\n login: async (\n provider: keyof T,\n options: {\n username?: string;\n password?: string;\n redirect?: string;\n realm?: string;\n [extra: string]: any;\n } = {},\n ) => {\n await alepha.inject(ReactAuth).login(provider as string, options);\n },\n can: <Api extends object = any>(\n name: keyof HttpVirtualClient<Api>,\n ): boolean => {\n return alepha.inject(LinkProvider).can(name as string);\n },\n };\n};\n","import { AlephaReact } from \"@alepha/react\";\nimport { $module } from \"alepha\";\nimport type { UserAccount } from \"alepha/security\";\nimport { ReactAuthProvider } from \"./providers/ReactAuthProvider.ts\";\nimport { ReactAuth } from \"./services/ReactAuth.ts\";\nimport { $auth, AlephaServerAuth } from \"alepha/server/auth\";\nimport { AlephaServerLinks } from \"alepha/server/links\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./index.shared.ts\";\nexport * from \"./providers/ReactAuthProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"@alepha/react/router\" {\n interface ReactRouterState {\n user?: UserAccount;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * The ReactAuthModule provides authentication services for React applications.\n *\n * @see {@link ReactAuthProvider}\n * @module alepha.react.auth\n */\nexport const AlephaReactAuth = $module({\n name: \"alepha.react.auth\",\n primitives: [$auth],\n services: [AlephaReact, AlephaServerLinks, AlephaServerAuth, ReactAuthProvider, ReactAuth],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["state","ErrorViewer","envSchema","NestedView","route","context","ErrorViewer","NotFoundPage","children","NotFoundPage"],"sources":["../../src/auth/providers/ReactAuthProvider.ts","../../src/router/services/ReactPageService.ts","../../src/router/constants/PAGE_PRELOAD_KEY.ts","../../src/router/primitives/$page.ts","../../src/router/components/NotFound.tsx","../../src/router/components/ErrorViewer.tsx","../../src/router/contexts/RouterLayerContext.ts","../../src/router/errors/Redirection.ts","../../src/router/hooks/useRouterState.ts","../../src/router/components/NestedView.tsx","../../src/router/providers/ReactPageProvider.ts","../../src/router/providers/ReactBrowserRouterProvider.ts","../../src/router/providers/ReactBrowserProvider.ts","../../src/router/services/ReactRouter.ts","../../src/router/providers/ReactServerTemplateProvider.ts","../../src/router/atoms/ssrManifestAtom.ts","../../src/router/providers/SSRManifestProvider.ts","../../src/router/providers/ReactServerProvider.ts","../../src/router/services/ReactPageServerService.ts","../../src/router/index.ts","../../src/auth/services/ReactAuth.ts","../../src/auth/hooks/useAuth.ts","../../src/auth/index.ts"],"sourcesContent":["import { $hook, $inject, Alepha } from \"alepha\";\n\nexport class ReactAuthProvider {\n protected readonly alepha = $inject(Alepha);\n\n public readonly onRender = $hook({\n on: \"react:server:render:begin\",\n handler: async ({ request, state }) => {\n if (request?.user) {\n const { token, realm, ...user } = request.user; // do not send token and realm to the client\n this.alepha.store.set(\"alepha.server.request.user\", user); // for hydration, browser, etc...\n state.user = user;\n }\n },\n });\n}\n","import { AlephaError } from \"alepha\";\nimport type { PagePrimitiveRenderOptions, PagePrimitiveRenderResult, } from \"../../router/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","/**\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 {\n $inject,\n type Async,\n createPrimitive,\n Primitive,\n KIND,\n type Static,\n type TSchema,\n} from \"alepha\";\nimport type { ServerRequest } from \"alepha/server\";\nimport type { ServerRouteCache } from \"alepha/server/cache\";\nimport type { FC, ReactNode } from \"react\";\nimport type { Redirection } from \"../errors/Redirection.ts\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\nimport { ReactPageService } from \"../services/ReactPageService.ts\";\nimport type { ClientOnlyProps } from \"@alepha/react\";\nimport type { Head } from \"@alepha/react/head\";\nimport { PAGE_PRELOAD_KEY } from \"../constants/PAGE_PRELOAD_KEY.ts\";\n\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 * **Page Animations**\n * - CSS-based enter/exit animations\n * - Dynamic animations based on page state\n * - Custom timing and easing functions\n *\n * **Lifecycle Management**\n * - Server response hooks for headers and status codes\n * - Page leave handlers for cleanup (browser only)\n * - Permission-based access control\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(\n PagePrimitive<TConfig, TProps, TPropsParent>,\n options,\n );\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 * 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.\n * This will make the page a parent route.\n */\n children?: Array<PagePrimitive> | (() => Array<PagePrimitive>);\n\n /**\n * Define a parent page for nested routing.\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 `alepha/vite`, 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 cache?: ServerRouteCache;\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 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 * 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\nexport type ErrorHandler = (\n error: Error,\n state: ReactRouterState,\n) => ReactNode | Redirection | undefined;\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.cache ??= {\n store: {\n provider: \"memory\",\n ttl: [1, \"week\"],\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 public match(url: string): boolean {\n // TODO: Implement a way to match the URL against the pathname\n return false;\n }\n\n public pathname(config: any) {\n // TODO: Implement a way to generate the pathname based on the config\n return this.options.path || \"\";\n }\n}\n\n$page[KIND] = PagePrimitive;\n\n// ---------------------------------------------------------------------------------------------------------------------\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 type { CSSProperties } from \"react\";\n\n/**\n * Default 404 Not Found page component.\n */\n const 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 type { Alepha } from \"alepha\";\nimport { type CSSProperties, useState } from \"react\";\n\ninterface ErrorViewerProps {\n error: Error;\n alepha: Alepha;\n}\n\ninterface StackFrame {\n fn: string;\n file: string;\n line: string;\n col: string;\n raw: string;\n}\n\n/**\n * Error viewer component that displays error details in development mode\n */\nconst ErrorViewer = ({ error, alepha }: ErrorViewerProps) => {\n const [expanded, setExpanded] = useState(false);\n const isProduction = alepha.isProduction();\n\n if (isProduction) {\n return <ErrorViewerProduction />;\n }\n\n const frames = parseStackTrace(error.stack);\n const visibleFrames = expanded ? frames : frames.slice(0, 6);\n const hiddenCount = frames.length - 6;\n\n return (\n <div style={styles.overlay}>\n <div style={styles.container}>\n <Header error={error} />\n <StackTraceSection\n frames={frames}\n visibleFrames={visibleFrames}\n expanded={expanded}\n hiddenCount={hiddenCount}\n onToggle={() => setExpanded(!expanded)}\n />\n </div>\n </div>\n );\n};\n\nexport default ErrorViewer;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Parse stack trace string into structured frames\n */\nfunction parseStackTrace(stack?: string): StackFrame[] {\n if (!stack) return [];\n\n const lines = stack.split(\"\\n\").slice(1);\n const frames: StackFrame[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"at \")) continue;\n\n const frame = parseStackLine(trimmed);\n if (frame) frames.push(frame);\n }\n\n return frames;\n}\n\n/**\n * Parse a single stack trace line into a structured frame\n */\nfunction parseStackLine(line: string): StackFrame | null {\n const withFn = line.match(/^at\\s+(.+?)\\s+\\((.+):(\\d+):(\\d+)\\)$/);\n if (withFn) {\n return {\n fn: withFn[1],\n file: withFn[2],\n line: withFn[3],\n col: withFn[4],\n raw: line,\n };\n }\n\n const withoutFn = line.match(/^at\\s+(.+):(\\d+):(\\d+)$/);\n if (withoutFn) {\n return {\n fn: \"<anonymous>\",\n file: withoutFn[1],\n line: withoutFn[2],\n col: withoutFn[3],\n raw: line,\n };\n }\n\n return { fn: \"\", file: line.replace(/^at\\s+/, \"\"), line: \"\", col: \"\", raw: line };\n}\n\n/**\n * Copy text to clipboard\n */\nfunction copyToClipboard(text: string): void {\n navigator.clipboard.writeText(text).catch((err) => {\n console.error(\"Clipboard error:\", err);\n });\n}\n\n/**\n * Header section with error type and message\n */\nfunction Header({ error }: { error: Error }) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = () => {\n copyToClipboard(error.stack || error.message);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n };\n\n return (\n <div style={styles.header}>\n <div style={styles.headerTop}>\n <div style={styles.badge}>{error.name}</div>\n <button type=\"button\" onClick={handleCopy} style={styles.copyBtn}>\n {copied ? \"Copied\" : \"Copy Stack\"}\n </button>\n </div>\n <h1 style={styles.message}>{error.message}</h1>\n </div>\n );\n}\n\n/**\n * Stack trace section with expandable frames\n */\nfunction StackTraceSection({\n frames,\n visibleFrames,\n expanded,\n hiddenCount,\n onToggle,\n}: {\n frames: StackFrame[];\n visibleFrames: StackFrame[];\n expanded: boolean;\n hiddenCount: number;\n onToggle: () => void;\n}) {\n if (frames.length === 0) return null;\n\n return (\n <div style={styles.stackSection}>\n <div style={styles.stackHeader}>Call Stack</div>\n <div style={styles.frameList}>\n {visibleFrames.map((frame, i) => (\n <StackFrameRow key={i} frame={frame} index={i} />\n ))}\n {!expanded && hiddenCount > 0 && (\n <button type=\"button\" onClick={onToggle} style={styles.expandBtn}>\n Show {hiddenCount} more frames\n </button>\n )}\n {expanded && hiddenCount > 0 && (\n <button type=\"button\" onClick={onToggle} style={styles.expandBtn}>\n Show less\n </button>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Single stack frame row\n */\nfunction StackFrameRow({ frame, index }: { frame: StackFrame; index: number }) {\n const isFirst = index === 0;\n const fileName = frame.file.split(\"/\").pop() || frame.file;\n const dirPath = frame.file.substring(0, frame.file.length - fileName.length);\n\n return (\n <div\n style={{\n ...styles.frame,\n ...(isFirst ? styles.frameFirst : {}),\n }}\n >\n <div style={styles.frameIndex}>{index + 1}</div>\n <div style={styles.frameContent}>\n {frame.fn && (\n <div style={styles.fnName}>\n {frame.fn}\n </div>\n )}\n <div style={styles.filePath}>\n <span style={styles.dirPath}>{dirPath}</span>\n <span style={styles.fileName}>{fileName}</span>\n {frame.line && (\n <span style={styles.lineCol}>\n :{frame.line}:{frame.col}\n </span>\n )}\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * Production error view - minimal information\n */\nfunction ErrorViewerProduction() {\n return (\n <div style={styles.overlay}>\n <div style={styles.prodContainer}>\n <div style={styles.prodIcon}>!</div>\n <h1 style={styles.prodTitle}>Application Error</h1>\n <p style={styles.prodMessage}>\n An unexpected error occurred. Please try again later.\n </p>\n <button\n type=\"button\"\n onClick={() => window.location.reload()}\n style={styles.prodButton}\n >\n Reload Page\n </button>\n </div>\n </div>\n );\n}\n\nconst styles: Record<string, CSSProperties> = {\n overlay: {\n position: \"fixed\",\n inset: 0,\n backgroundColor: \"rgba(0, 0, 0, 0.8)\",\n display: \"flex\",\n alignItems: \"flex-start\",\n justifyContent: \"center\",\n padding: \"40px 20px\",\n overflow: \"auto\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n zIndex: 99999,\n },\n container: {\n width: \"100%\",\n maxWidth: \"960px\",\n backgroundColor: \"#1a1a1a\",\n borderRadius: \"12px\",\n overflow: \"hidden\",\n boxShadow: \"0 25px 50px -12px rgba(0, 0, 0, 0.5)\",\n },\n header: {\n padding: \"24px 28px\",\n borderBottom: \"1px solid #333\",\n background: \"linear-gradient(to bottom, #1f1f1f, #1a1a1a)\",\n },\n headerTop: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: \"16px\",\n },\n badge: {\n display: \"inline-block\",\n padding: \"6px 12px\",\n backgroundColor: \"#dc2626\",\n color: \"#fff\",\n fontSize: \"12px\",\n fontWeight: 600,\n borderRadius: \"6px\",\n letterSpacing: \"0.025em\",\n },\n copyBtn: {\n padding: \"8px 16px\",\n backgroundColor: \"transparent\",\n color: \"#888\",\n fontSize: \"13px\",\n fontWeight: 500,\n border: \"1px solid #444\",\n borderRadius: \"6px\",\n cursor: \"pointer\",\n transition: \"all 0.15s\",\n },\n message: {\n margin: 0,\n fontSize: \"20px\",\n fontWeight: 500,\n color: \"#fff\",\n lineHeight: 1.5,\n wordBreak: \"break-word\",\n },\n stackSection: {\n padding: \"0\",\n },\n stackHeader: {\n padding: \"16px 28px\",\n fontSize: \"11px\",\n fontWeight: 600,\n color: \"#666\",\n textTransform: \"uppercase\",\n letterSpacing: \"0.1em\",\n borderBottom: \"1px solid #2a2a2a\",\n },\n frameList: {\n display: \"flex\",\n flexDirection: \"column\",\n },\n frame: {\n display: \"flex\",\n alignItems: \"flex-start\",\n padding: \"14px 28px\",\n borderBottom: \"1px solid #252525\",\n transition: \"background-color 0.15s\",\n },\n frameFirst: {\n backgroundColor: \"rgba(220, 38, 38, 0.1)\",\n },\n frameIndex: {\n width: \"28px\",\n flexShrink: 0,\n fontSize: \"12px\",\n fontWeight: 500,\n color: \"#555\",\n fontFamily: \"monospace\",\n },\n frameContent: {\n flex: 1,\n minWidth: 0,\n },\n fnName: {\n fontSize: \"14px\",\n fontWeight: 500,\n color: \"#e5e5e5\",\n marginBottom: \"4px\",\n fontFamily:\n 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n },\n filePath: {\n fontSize: \"13px\",\n color: \"#888\",\n fontFamily:\n 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n wordBreak: \"break-all\",\n },\n dirPath: {\n color: \"#555\",\n },\n fileName: {\n color: \"#0ea5e9\",\n },\n lineCol: {\n color: \"#eab308\",\n },\n expandBtn: {\n padding: \"16px 28px\",\n backgroundColor: \"transparent\",\n color: \"#666\",\n fontSize: \"13px\",\n fontWeight: 500,\n border: \"none\",\n borderTop: \"1px solid #252525\",\n cursor: \"pointer\",\n textAlign: \"left\",\n transition: \"all 0.15s\",\n },\n prodContainer: {\n textAlign: \"center\",\n padding: \"60px 40px\",\n backgroundColor: \"#1a1a1a\",\n borderRadius: \"12px\",\n maxWidth: \"400px\",\n },\n prodIcon: {\n width: \"64px\",\n height: \"64px\",\n margin: \"0 auto 24px\",\n backgroundColor: \"#dc2626\",\n borderRadius: \"50%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"32px\",\n fontWeight: 700,\n color: \"#fff\",\n },\n prodTitle: {\n margin: \"0 0 12px\",\n fontSize: \"24px\",\n fontWeight: 600,\n color: \"#fff\",\n },\n prodMessage: {\n margin: \"0 0 28px\",\n fontSize: \"15px\",\n color: \"#888\",\n lineHeight: 1.6,\n },\n prodButton: {\n padding: \"12px 24px\",\n backgroundColor: \"#fff\",\n color: \"#000\",\n fontSize: \"14px\",\n fontWeight: 600,\n border: \"none\",\n borderRadius: \"8px\",\n cursor: \"pointer\",\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 { AlephaError } from \"alepha\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\nimport { useStore } from \"@alepha/react\";\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 { memo, type ReactNode, use, useRef, useState } from \"react\";\nimport type { ReactRouterState } from \"../providers/ReactPageProvider.ts\";\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 ErrorViewer from \"./ErrorViewer.tsx\";\nimport { ErrorBoundary, useAlepha, useEvents } from \"@alepha/react\";\n\nexport interface NestedViewProps {\n children?: ReactNode;\n errorBoundary?: false | ((error: Error) => 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\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 fallback={props.errorBoundary}>{element}</ErrorBoundary>\n );\n }\n\n const fallback = (error: Error) => {\n const result = onError?.(error, state) ?? <ErrorViewer error={error} alepha={alepha}/>;\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 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 {\n $env,\n $hook,\n $inject,\n Alepha,\n AlephaError,\n type Static,\n type TSchema,\n t,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { createElement, type ReactNode, StrictMode } from \"react\";\nimport { AlephaContext, ClientOnly } from \"@alepha/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\";\nimport type { Head } from \"@alepha/react/head\";\n\nconst envSchema = t.object({\n REACT_STRICT_MODE: t.boolean({ default: true }),\n});\n\ndeclare module \"alepha\" {\n export interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\n/**\n * Handle page routes for React applications. (Browser and Server)\n */\nexport class ReactPageProvider {\n protected readonly log = $logger();\n protected readonly env = $env(envSchema);\n protected readonly alepha = $inject(Alepha);\n protected readonly pages: PageRoute[] = [];\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 Error(`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.env.REACT_STRICT_MODE) {\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 as Error;\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 as Error;\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 // 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 as Error;\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(it.route, {\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\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 as Error;\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 });\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 ): 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 const component = await page.lazy(); // load component\n return createElement(component.default, props);\n }\n\n if (page.component) {\n return createElement(page.component, props);\n }\n\n return undefined;\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: this.getErrorHandler(page) ?? ((error) => this.renderError(error)),\n },\n },\n element,\n );\n }\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 cache: true,\n component: NotFoundPage,\n onServerResponse: ({ reply }) => {\n reply.status = 404;\n },\n });\n }\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 _next = 0;\n\n protected nextId(): string {\n this._next += 1;\n return `P${this._next}`;\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\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 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 TransitionOptions {\n previous?: PreviousLayerData[];\n}\n\nexport interface CreateLayersResult {\n redirect?: string;\n state?: ReactRouterState;\n}\n","import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { type Route, RouterProvider } from \"alepha/router\";\nimport { createElement, type ReactNode } from \"react\";\nimport { BrowserHeadProvider } from \"@alepha/react/head\";\nimport NotFoundPage from \"../components/NotFound.tsx\";\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) {\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 ): 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 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 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 this.log.error(\"Transition has failed\", e);\n state.layers = [\n {\n name: \"error\",\n 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 // [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) {\n this.pageApi.page(layer.name)?.onLeave?.();\n }\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 { $atom, $env, $hook, $inject, $use, Alepha, type State, type Static, t, } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { LinkProvider } from \"alepha/server/links\";\nimport { BrowserHeadProvider } from \"@alepha/react/head\";\nimport { ReactBrowserRouterProvider } from \"./ReactBrowserRouterProvider.ts\";\nimport type { PreviousLayerData, ReactRouterState, } from \"./ReactPageProvider.ts\";\nimport type { RouterGoOptions } from \"../services/ReactRouter.ts\";\n\nexport type { RouterGoOptions } from \"../services/ReactRouter.ts\";\n\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 = $use(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 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 go(url: string, options: RouterGoOptions = {}): Promise<void> {\n this.log.trace(`Going to ${url}`, {\n url,\n options,\n });\n\n await this.render({\n url,\n previous: options.force ? [] : this.state.layers,\n meta: options.meta,\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 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 redirect = await this.router.transition(\n new URL(`http://localhost${url}`),\n previous,\n options.meta,\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 if (\"__ssr\" in window && typeof window.__ssr === \"object\") {\n return window.__ssr 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?.layers ?? [];\n\n if (hydration) {\n // low budget, but works for now\n for (const [key, value] of Object.entries(hydration)) {\n if (key !== \"layers\") {\n this.alepha.store.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 // Fill and render head from route configurations\n this.browserHeadProvider.fillAndRenderHead(this.state);\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 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","import { $inject, Alepha } from \"alepha\";\nimport { ReactBrowserProvider } from \"../providers/ReactBrowserProvider.ts\";\nimport {\n type AnchorProps, type PageRoute,\n ReactPageProvider,\n type ReactRouterState,\n} from \"../providers/ReactPageProvider.ts\";\nimport type { PagePrimitive, PagePrimitiveOptions } from \"../primitives/$page.ts\";\n\nexport interface RouterGoOptions {\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 { // 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.go(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 Error(\"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 go(path: string, options?: RouterGoOptions): Promise<void>;\n public async go(\n path: keyof VirtualRouter<T>,\n options?: RouterGoOptions,\n ): Promise<void>;\n public async go(\n path: string | keyof VirtualRouter<T>,\n options?: RouterGoOptions,\n ): Promise<void> {\n for (const page of this.pages) {\n if (page.name === path) {\n await this.browser?.go(\n this.path(path as keyof VirtualRouter<T>, options),\n options,\n );\n return;\n }\n }\n\n await this.browser?.go(path as string, options);\n }\n\n public anchor(path: string, options?: RouterGoOptions): AnchorProps;\n public anchor(\n path: keyof VirtualRouter<T>,\n options?: RouterGoOptions,\n ): AnchorProps;\n public anchor(\n path: string | keyof VirtualRouter<T>,\n options: RouterGoOptions = {},\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.go(href, options).catch(console.error);\n },\n };\n }\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 state = search ? `${this.pathname}?${search}` : this.pathname;\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 { $inject, Alepha, AlephaError } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type { SimpleHead } from \"@alepha/react/head\";\nimport type { ReactRouterState } from \"./ReactPageProvider.ts\";\n\n/**\n * Handles HTML template parsing, preprocessing, and streaming for SSR.\n *\n * Responsibilities:\n * - Parse template once at startup into logical slots\n * - Pre-encode static parts as Uint8Array for zero-copy streaming\n * - Render dynamic parts (attributes, head content) efficiently\n * - Build hydration data for client-side rehydration\n *\n * This provider is injected into ReactServerProvider to handle all\n * template-related operations, keeping ReactServerProvider focused\n * on request handling and React rendering coordination.\n */\nexport class ReactServerTemplateProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n\n /**\n * Shared TextEncoder instance - reused across all requests.\n */\n protected readonly encoder = new TextEncoder();\n\n /**\n * Pre-encoded common strings for streaming.\n */\n protected readonly ENCODED = {\n HYDRATION_PREFIX: this.encoder.encode(\"<script>window.__ssr=\"),\n HYDRATION_SUFFIX: this.encoder.encode(\"</script>\"),\n EMPTY: this.encoder.encode(\"\"),\n } as const;\n\n /**\n * Cached template slots - parsed once, reused for all requests.\n */\n protected slots: TemplateSlots | null = null;\n\n\n /**\n * Root element ID for React mounting.\n */\n public get rootId(): string {\n return \"root\";\n }\n\n /**\n * Regex pattern for matching the root div and extracting its content.\n */\n public get rootDivRegex(): RegExp {\n return new RegExp(\n `<div([^>]*)\\\\s+id=[\"']${this.rootId}[\"']([^>]*)>([\\\\s\\\\S]*?)<\\\\/div>`,\n \"i\",\n );\n }\n\n /**\n * Extract the content inside the root div from HTML.\n *\n * @param html - Full HTML string\n * @returns The content inside the root div, or undefined if not found\n */\n public extractRootContent(html: string): string | undefined {\n const match = html.match(this.rootDivRegex);\n return match?.[3];\n }\n\n /**\n * Check if template has been parsed and slots are available.\n */\n public isReady(): boolean {\n return this.slots !== null;\n }\n\n /**\n * Get the parsed template slots.\n * Throws if template hasn't been parsed yet.\n */\n public getSlots(): TemplateSlots {\n if (!this.slots) {\n throw new AlephaError(\n \"Template not parsed. Call parseTemplate() during configuration.\",\n );\n }\n return this.slots;\n }\n\n /**\n * Parse an HTML template into logical slots for efficient streaming.\n *\n * This should be called once during server startup/configuration.\n * The parsed slots are cached and reused for all requests.\n *\n * @param template - The HTML template string (typically index.html)\n */\n public parseTemplate(template: string): TemplateSlots {\n this.log.debug(\"Parsing template into slots\");\n\n const rootId = this.rootId;\n\n // Extract doctype\n const doctypeMatch = template.match(/<!DOCTYPE[^>]*>/i);\n const doctype = doctypeMatch?.[0] ?? \"<!DOCTYPE html>\";\n let remaining = doctypeMatch\n ? template.slice(doctypeMatch.index! + doctypeMatch[0].length)\n : template;\n\n // Extract <html> tag and attributes\n const htmlMatch = remaining.match(/<html([^>]*)>/i);\n const htmlAttrsStr = htmlMatch?.[1]?.trim() ?? \"\";\n const htmlOriginalAttrs = this.parseAttributes(htmlAttrsStr);\n remaining = htmlMatch\n ? remaining.slice(htmlMatch.index! + htmlMatch[0].length)\n : remaining;\n\n // Extract <head> content\n const headMatch = remaining.match(/<head([^>]*)>([\\s\\S]*?)<\\/head>/i);\n const headOriginalContent = headMatch?.[2]?.trim() ?? \"\";\n remaining = headMatch\n ? remaining.slice(headMatch.index! + headMatch[0].length)\n : remaining;\n\n // Extract <body> tag and attributes\n const bodyMatch = remaining.match(/<body([^>]*)>/i);\n const bodyAttrsStr = bodyMatch?.[1]?.trim() ?? \"\";\n const bodyOriginalAttrs = this.parseAttributes(bodyAttrsStr);\n const bodyStartIndex = bodyMatch\n ? bodyMatch.index! + bodyMatch[0].length\n : 0;\n remaining = remaining.slice(bodyStartIndex);\n\n // Find root div\n const rootDivRegex = new RegExp(\n `<div([^>]*)\\\\s+id=[\"']${rootId}[\"']([^>]*)>([\\\\s\\\\S]*?)<\\\\/div>`,\n \"i\",\n );\n const rootMatch = remaining.match(rootDivRegex);\n\n let beforeRoot = \"\";\n let afterRoot = \"\";\n let rootAttrs = \"\";\n\n if (rootMatch) {\n beforeRoot = remaining.slice(0, rootMatch.index!).trim();\n const rootEndIndex = rootMatch.index! + rootMatch[0].length;\n // Find </body> for afterRoot\n const bodyCloseIndex = remaining.indexOf(\"</body>\");\n afterRoot =\n bodyCloseIndex > rootEndIndex\n ? remaining.slice(rootEndIndex, bodyCloseIndex).trim()\n : \"\";\n rootAttrs = `${rootMatch[1] ?? \"\"}${rootMatch[2] ?? \"\"}`.trim();\n } else {\n // No root div found - will inject one\n const bodyCloseIndex = remaining.indexOf(\"</body>\");\n if (bodyCloseIndex > 0) {\n beforeRoot = remaining.slice(0, bodyCloseIndex).trim();\n }\n }\n\n // Build the root div opening tag\n const rootOpenTag = rootAttrs\n ? `<div ${rootAttrs} id=\"${rootId}\">`\n : `<div id=\"${rootId}\">`;\n\n this.slots = {\n // Pre-encoded static parts\n doctype: this.encoder.encode(doctype + \"\\n\"),\n htmlOpen: this.encoder.encode(\"<html\"),\n htmlClose: this.encoder.encode(\">\\n\"),\n headOpen: this.encoder.encode(\"<head>\"),\n headClose: this.encoder.encode(\"</head>\\n\"),\n bodyOpen: this.encoder.encode(\"<body\"),\n bodyClose: this.encoder.encode(\">\\n\"),\n rootOpen: this.encoder.encode(rootOpenTag),\n rootClose: this.encoder.encode(\"</div>\\n\"),\n scriptClose: this.encoder.encode(\"</body>\\n</html>\"),\n\n // Original content for merging\n htmlOriginalAttrs,\n bodyOriginalAttrs,\n headOriginalContent,\n beforeRoot,\n afterRoot,\n };\n\n this.log.debug(\"Template parsed successfully\", {\n hasHtmlAttrs: Object.keys(htmlOriginalAttrs).length > 0,\n hasBodyAttrs: Object.keys(bodyOriginalAttrs).length > 0,\n hasHeadContent: headOriginalContent.length > 0,\n hasBeforeRoot: beforeRoot.length > 0,\n hasAfterRoot: afterRoot.length > 0,\n });\n\n return this.slots;\n }\n\n /**\n * Parse HTML attributes string into a record.\n *\n * Handles: key=\"value\", key='value', key=value, and boolean key\n */\n protected parseAttributes(attrStr: string): Record<string, string> {\n const attrs: Record<string, string> = {};\n if (!attrStr) return attrs;\n\n // Match: key=\"value\", key='value', key=value, or just key (boolean)\n const attrRegex = /([^\\s=]+)(?:=(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+)))?/g;\n let match: RegExpExecArray | null;\n\n while ((match = attrRegex.exec(attrStr))) {\n const key = match[1];\n const value = match[2] ?? match[3] ?? match[4] ?? \"\";\n attrs[key] = value;\n }\n\n return attrs;\n }\n\n /**\n * Render attributes record to HTML string.\n *\n * @param attrs - Attributes to render\n * @returns HTML attribute string like ` lang=\"en\" class=\"dark\"`\n */\n public renderAttributes(attrs: Record<string, string>): string {\n const entries = Object.entries(attrs);\n if (entries.length === 0) return \"\";\n\n return entries\n .map(([key, value]) => ` ${key}=\"${this.escapeHtml(value)}\"`)\n .join(\"\");\n }\n\n /**\n * Render merged HTML attributes (original + dynamic).\n */\n public renderMergedHtmlAttrs(dynamicAttrs?: Record<string, string>): string {\n const slots = this.getSlots();\n const merged = { ...slots.htmlOriginalAttrs, ...dynamicAttrs };\n return this.renderAttributes(merged);\n }\n\n /**\n * Render merged body attributes (original + dynamic).\n */\n public renderMergedBodyAttrs(dynamicAttrs?: Record<string, string>): string {\n const slots = this.getSlots();\n const merged = { ...slots.bodyOriginalAttrs, ...dynamicAttrs };\n return this.renderAttributes(merged);\n }\n\n /**\n * Render head content (title, meta, link, script tags).\n *\n * @param head - Head data to render\n * @param includeOriginal - Whether to include original head content\n * @returns HTML string with head content\n */\n public renderHeadContent(head?: SimpleHead, includeOriginal = true): string {\n const slots = this.getSlots();\n let content = \"\";\n\n // Include original head content first\n if (includeOriginal && slots.headOriginalContent) {\n content += slots.headOriginalContent;\n }\n\n if (!head) return content;\n\n // Title - check if already exists in original content\n if (head.title) {\n if (content.includes(\"<title>\")) {\n // Replace existing title\n content = content.replace(\n /<title>.*?<\\/title>/i,\n `<title>${this.escapeHtml(head.title)}</title>`,\n );\n } else {\n content += `<title>${this.escapeHtml(head.title)}</title>\\n`;\n }\n }\n\n // Meta tags\n if (head.meta) {\n for (const meta of head.meta) {\n content += this.renderMetaTag(meta);\n }\n }\n\n // Link tags\n if (head.link) {\n for (const link of head.link) {\n content += this.renderLinkTag(link);\n }\n }\n\n // Script tags\n if (head.script) {\n for (const script of head.script) {\n content += this.renderScriptTag(script);\n }\n }\n\n return content;\n }\n\n /**\n * Render a meta tag.\n */\n protected renderMetaTag(meta: {\n name?: string;\n property?: string;\n content: string;\n }): string {\n if (meta.property) {\n return `<meta property=\"${this.escapeHtml(meta.property)}\" content=\"${this.escapeHtml(meta.content)}\">\\n`;\n }\n if (meta.name) {\n return `<meta name=\"${this.escapeHtml(meta.name)}\" content=\"${this.escapeHtml(meta.content)}\">\\n`;\n }\n return \"\";\n }\n\n /**\n * Render a link tag.\n */\n protected renderLinkTag(link: {\n rel: string;\n href: string;\n as?: string;\n crossorigin?: string;\n }): string {\n let tag = `<link rel=\"${this.escapeHtml(link.rel)}\" href=\"${this.escapeHtml(link.href)}\"`;\n if (link.as) {\n tag += ` as=\"${this.escapeHtml(link.as)}\"`;\n }\n if (link.crossorigin != null) {\n tag += ' crossorigin=\"\"';\n }\n tag += \">\\n\";\n return tag;\n }\n\n /**\n * Render a script tag.\n */\n protected renderScriptTag(script: Record<string, string | boolean>): string {\n const attrs = Object.entries(script)\n .filter(([, value]) => value !== false)\n .map(([key, value]) => {\n if (value === true) return key;\n return `${key}=\"${this.escapeHtml(String(value))}\"`;\n })\n .join(\" \");\n return `<script ${attrs}></script>\\n`;\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 * Escapes characters that could break out of script tags.\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 * This creates the data structure that will be serialized to window.__ssr\n * for client-side rehydration.\n */\n public buildHydrationData(state: ReactRouterState): HydrationData {\n const { request, context, ...store } =\n this.alepha.context.als?.getStore() ?? {};\n\n return {\n ...store,\n \"alepha.react.router.state\": undefined,\n layers: state.layers.map((layer) => ({\n ...layer,\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 // Remove non-serializable properties\n index: undefined,\n path: undefined,\n element: undefined,\n route: undefined,\n })),\n };\n }\n\n /**\n * Encode a string to Uint8Array using the shared encoder.\n */\n public encode(str: string): Uint8Array {\n return this.encoder.encode(str);\n }\n\n /**\n * Get the pre-encoded hydration script prefix.\n */\n public get hydrationPrefix(): Uint8Array {\n return this.ENCODED.HYDRATION_PREFIX;\n }\n\n /**\n * Get the pre-encoded hydration script suffix.\n */\n public get hydrationSuffix(): Uint8Array {\n return this.ENCODED.HYDRATION_SUFFIX;\n }\n\n /**\n * Create a ReadableStream that streams the HTML template with React content.\n *\n * This is the main entry point for SSR streaming. It:\n * 1. Sends <head> immediately (browser starts downloading assets)\n * 2. Streams React content as it renders\n * 3. Appends hydration script and closing tags\n *\n * @param reactStream - ReadableStream from renderToReadableStream\n * @param state - Router state with head data\n * @param options - Streaming options\n */\n public createHtmlStream(\n reactStream: ReadableStream<Uint8Array>,\n state: ReactRouterState,\n options: {\n hydration?: boolean;\n onError?: (error: unknown) => void;\n } = {},\n ): ReadableStream<Uint8Array> {\n const { hydration = true, onError } = options;\n const slots = this.getSlots();\n const head = state.head;\n const encoder = this.encoder;\n\n return new ReadableStream<Uint8Array>({\n start: async (controller) => {\n try {\n // 1. DOCTYPE\n controller.enqueue(slots.doctype);\n\n // 2. <html ...>\n controller.enqueue(slots.htmlOpen);\n controller.enqueue(\n encoder.encode(this.renderMergedHtmlAttrs(head?.htmlAttributes)),\n );\n controller.enqueue(slots.htmlClose);\n\n // 3. <head>...</head>\n controller.enqueue(slots.headOpen);\n // Include early head content (entry.js, CSS) if set\n if (this.earlyHeadContent) {\n controller.enqueue(encoder.encode(this.earlyHeadContent));\n }\n controller.enqueue(encoder.encode(this.renderHeadContent(head)));\n controller.enqueue(slots.headClose);\n\n // 4. <body ...>\n controller.enqueue(slots.bodyOpen);\n controller.enqueue(\n encoder.encode(this.renderMergedBodyAttrs(head?.bodyAttributes)),\n );\n controller.enqueue(slots.bodyClose);\n\n // 5. Content before root (if any)\n if (slots.beforeRoot) {\n controller.enqueue(encoder.encode(slots.beforeRoot));\n }\n\n // 6. <div id=\"root\">\n controller.enqueue(slots.rootOpen);\n\n // 7. Stream React content\n const reader = reactStream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n controller.enqueue(value);\n }\n } finally {\n reader.releaseLock();\n }\n\n // 8. </div>\n controller.enqueue(slots.rootClose);\n\n // 9. Content after root (if any)\n if (slots.afterRoot) {\n controller.enqueue(encoder.encode(slots.afterRoot));\n }\n\n // 10. Hydration script\n if (hydration) {\n const hydrationData = this.buildHydrationData(state);\n controller.enqueue(this.ENCODED.HYDRATION_PREFIX);\n controller.enqueue(\n encoder.encode(this.safeJsonSerialize(hydrationData)),\n );\n controller.enqueue(this.ENCODED.HYDRATION_SUFFIX);\n }\n\n // 11. </body></html>\n controller.enqueue(slots.scriptClose);\n\n controller.close();\n } catch (error) {\n onError?.(error);\n controller.error(error);\n }\n },\n });\n }\n\n /**\n * Early head content for preloading.\n *\n * Contains entry assets (JS + CSS) that are always required and can be\n * sent before page loaders run.\n */\n protected earlyHeadContent: string = \"\";\n\n /**\n * Set the early head content (entry script + CSS).\n *\n * Also strips these assets from the original head content to avoid duplicates,\n * since we're moving them to the early phase.\n *\n * @param content - HTML string with entry assets\n * @param entryAssets - Entry asset paths to strip from original head\n */\n public setEarlyHeadContent(\n content: string,\n entryAssets?: { js?: string; css: string[] },\n ): void {\n this.earlyHeadContent = content;\n\n // Strip entry assets from original head content to avoid duplicates\n if (entryAssets && this.slots) {\n let headContent = this.slots.headOriginalContent;\n\n // Remove entry script tag\n if (entryAssets.js) {\n // Match script tag with this src (handles various attribute orders)\n const scriptPattern = new RegExp(\n `<script[^>]*\\\\ssrc=[\"']${this.escapeRegExp(entryAssets.js)}[\"'][^>]*>\\\\s*</script>\\\\s*`,\n \"gi\",\n );\n headContent = headContent.replace(scriptPattern, \"\");\n }\n\n // Remove entry CSS link tags\n for (const css of entryAssets.css) {\n const linkPattern = new RegExp(\n `<link[^>]*\\\\shref=[\"']${this.escapeRegExp(css)}[\"'][^>]*>\\\\s*`,\n \"gi\",\n );\n headContent = headContent.replace(linkPattern, \"\");\n }\n\n this.slots.headOriginalContent = headContent.trim();\n }\n }\n\n /**\n * Escape special regex characters in a string.\n */\n protected escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n }\n\n /**\n * Create an optimized HTML stream with early head streaming.\n *\n * This version sends critical assets (entry.js, CSS) BEFORE page loaders run,\n * allowing the browser to start downloading them immediately.\n *\n * Flow:\n * 1. Send DOCTYPE, <html>, <head> open, entry preloads (IMMEDIATE)\n * 2. Run async work (createLayers, etc.)\n * 3. Send rest of head, body, React content, hydration\n *\n * @param globalHead - Global head with htmlAttributes (from $head primitives)\n * @param asyncWork - Async function to run between early head and rest of stream\n * @param options - Streaming options\n */\n public createEarlyHtmlStream(\n globalHead: SimpleHead,\n asyncWork: () => Promise<{\n state: ReactRouterState;\n reactStream: ReadableStream<Uint8Array>;\n } | null>,\n options: {\n hydration?: boolean;\n onError?: (error: unknown) => void;\n onRedirect?: (url: string) => void;\n } = {},\n ): ReadableStream<Uint8Array> {\n const { hydration = true, onError, onRedirect } = options;\n const slots = this.getSlots();\n const encoder = this.encoder;\n\n return new ReadableStream<Uint8Array>({\n start: async (controller) => {\n try {\n // === EARLY PHASE (before async work) ===\n\n // 1. DOCTYPE\n controller.enqueue(slots.doctype);\n\n // 2. <html ...> with global htmlAttributes only\n controller.enqueue(slots.htmlOpen);\n controller.enqueue(\n encoder.encode(\n this.renderMergedHtmlAttrs(globalHead?.htmlAttributes),\n ),\n );\n controller.enqueue(slots.htmlClose);\n\n // 3. <head> open + entry preloads\n controller.enqueue(slots.headOpen);\n if (this.earlyHeadContent) {\n controller.enqueue(encoder.encode(this.earlyHeadContent));\n }\n\n // === ASYNC WORK (createLayers, etc.) ===\n const result = await asyncWork();\n\n // Handle redirect - can't undo what we've sent, but caller handles it\n if (!result) {\n // Redirect happened - close with minimal valid HTML\n controller.enqueue(slots.headClose);\n controller.enqueue(encoder.encode(\"<body></body></html>\"));\n controller.close();\n return;\n }\n\n const { state, reactStream } = result;\n const head = state.head;\n\n // === LATE PHASE (after async work) ===\n\n // 4. Rest of head content (title, meta, links from loaders)\n controller.enqueue(encoder.encode(this.renderHeadContent(head)));\n controller.enqueue(slots.headClose);\n\n // 5. <body ...> with merged bodyAttributes\n controller.enqueue(slots.bodyOpen);\n controller.enqueue(\n encoder.encode(this.renderMergedBodyAttrs(head?.bodyAttributes)),\n );\n controller.enqueue(slots.bodyClose);\n\n // 6. Content before root (if any)\n if (slots.beforeRoot) {\n controller.enqueue(encoder.encode(slots.beforeRoot));\n }\n\n // 7. <div id=\"root\">\n controller.enqueue(slots.rootOpen);\n\n // 8. Stream React content\n const reader = reactStream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n controller.enqueue(value);\n }\n } finally {\n reader.releaseLock();\n }\n\n // 9. </div>\n controller.enqueue(slots.rootClose);\n\n // 10. Content after root (if any)\n if (slots.afterRoot) {\n controller.enqueue(encoder.encode(slots.afterRoot));\n }\n\n // 11. Hydration script\n if (hydration) {\n const hydrationData = this.buildHydrationData(state);\n controller.enqueue(this.ENCODED.HYDRATION_PREFIX);\n controller.enqueue(\n encoder.encode(this.safeJsonSerialize(hydrationData)),\n );\n controller.enqueue(this.ENCODED.HYDRATION_SUFFIX);\n }\n\n // 12. </body></html>\n controller.enqueue(slots.scriptClose);\n\n controller.close();\n } catch (error) {\n onError?.(error);\n controller.error(error);\n }\n },\n });\n }\n}\n\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Template slots - the template split into logical parts for efficient streaming.\n *\n * Static parts are pre-encoded as Uint8Array for zero-copy streaming.\n * Dynamic parts (attributes, head content) are kept as strings/objects for merging.\n */\nexport interface TemplateSlots {\n // Pre-encoded static parts\n doctype: Uint8Array;\n htmlOpen: Uint8Array; // \"<html\"\n htmlClose: Uint8Array; // \">\"\n headOpen: Uint8Array; // \"<head>\"\n headClose: Uint8Array; // \"</head>\"\n bodyOpen: Uint8Array; // \"<body\"\n bodyClose: Uint8Array; // \">\"\n rootOpen: Uint8Array; // '<div id=\"root\">'\n rootClose: Uint8Array; // \"</div>\"\n scriptClose: Uint8Array; // \"</body></html>\"\n\n // Original content (kept for merging)\n htmlOriginalAttrs: Record<string, string>;\n bodyOriginalAttrs: Record<string, string>;\n headOriginalContent: string;\n beforeRoot: string; // content between <body> and root div\n afterRoot: string; // content between root div and </body>\n}\n\n/**\n * Hydration state that gets serialized to window.__ssr\n */\nexport interface HydrationData {\n layers: Array<{\n data?: unknown;\n error?: {\n name: string;\n message: string;\n stack?: string;\n };\n }>;\n [key: string]: unknown;\n}\n","import { $atom, t } from \"alepha\";\n\n/**\n * Schema for the SSR manifest atom.\n */\nexport const ssrManifestAtomSchema = t.object({\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 * SSR manifest mapping source files to their required chunks.\n */\n ssr: t.optional(t.record(t.string(), t.array(t.string()))),\n\n /**\n * Client manifest mapping source files to their output information.\n */\n client: t.optional(\n t.record(\n t.string(),\n t.object({\n file: t.string(),\n src: t.optional(t.string()),\n isEntry: t.optional(t.boolean()),\n isDynamicEntry: t.optional(t.boolean()),\n imports: t.optional(t.array(t.string())),\n dynamicImports: t.optional(t.array(t.string())),\n css: t.optional(t.array(t.string())),\n assets: t.optional(t.array(t.string())),\n }),\n ),\n ),\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 * - ssr: Maps source files to their required chunks\n * - client: Maps source files to their output info including 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 ssrManifestAtom,\n type SsrManifestAtomSchema,\n} from \"../atoms/ssrManifestAtom.ts\";\nimport type { PageRoute } from \"./ReactPageProvider.ts\";\nimport { PAGE_PRELOAD_KEY } from \"../constants/PAGE_PRELOAD_KEY.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 * - ssr-manifest.json (SSR 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 (this.alepha.store.get(ssrManifestAtom) as Static<SsrManifestAtomSchema>) ?? {};\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 SSR manifest.\n */\n protected get ssrManifest(): SSRManifest | undefined {\n return this.manifest.ssr;\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 * not just the direct chunks from the SSR manifest.\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 // Fallback to SSR manifest if client manifest not available\n return this.getChunksFromSSRManifest(sourcePath);\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 // Add main chunk file (with leading slash for URL)\n if (entry.file) {\n chunks.add(\"/\" + entry.file);\n }\n\n // Add CSS files\n if (entry.css) {\n for (const css of entry.css) {\n chunks.add(\"/\" + 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 * Fallback to SSR manifest for chunk lookup.\n */\n protected getChunksFromSSRManifest(sourcePath: string): string[] {\n if (!this.ssrManifest) {\n return [];\n }\n\n // Try exact match\n if (this.ssrManifest[sourcePath]) {\n return this.ssrManifest[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.ssrManifest[pathWithExt]) {\n return this.ssrManifest[pathWithExt];\n }\n }\n\n return [];\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 =\n 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 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 manifests are loaded and available.\n */\n public isAvailable(): boolean {\n return this.clientManifest !== undefined || this.ssrManifest !== 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 // 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: \"/\" + entry.file,\n css: entry.css?.map((css) => \"/\" + 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/**\n * Entry assets structure containing the main entry JS and associated CSS files.\n */\nexport interface EntryAssets {\n /** Main entry JavaScript file (e.g., \"/assets/entry.abc123.js\") */\n js?: string;\n /** Associated CSS files (e.g., [\"/assets/style.abc123.css\"]) */\n css: string[];\n}\n\n/**\n * SSR Manifest structure from Vite.\n * Maps source file paths to their required chunks/assets.\n */\nexport type SSRManifest = Record<string, string[]>;\n\n/**\n * Client manifest structure from Vite.\n * Maps source files to their output information.\n */\nexport interface ClientManifest {\n [key: string]: {\n file: string;\n src?: string;\n isEntry?: boolean;\n isDynamicEntry?: boolean;\n imports?: string[];\n dynamicImports?: string[];\n css?: string[];\n assets?: 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 { join } from \"node:path\";\nimport { $atom, $env, $hook, $inject, $use, Alepha, AlephaError, type Static, t, } from \"alepha\";\nimport { FileSystemProvider } from \"alepha/file\";\nimport { $logger } from \"alepha/logger\";\nimport { type ServerHandler, ServerRouterProvider, ServerTimingProvider, } from \"alepha/server\";\nimport { ServerLinksProvider } from \"alepha/server/links\";\nimport { ServerStaticProvider } from \"alepha/server/static\";\nimport { renderToReadableStream } from \"react-dom/server\";\nimport { ServerHeadProvider } from \"@alepha/react/head\";\nimport { Redirection } from \"../errors/Redirection.ts\";\nimport { $page, type PagePrimitiveRenderOptions, type PagePrimitiveRenderResult, } from \"../primitives/$page.ts\";\nimport { type PageRoute, ReactPageProvider, type ReactRouterState, } 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 serverTimingProvider = $inject(ServerTimingProvider);\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 = $use(reactServerOptions);\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 if (ssrEnabled) {\n this.log.info(\"SSR streaming enabled\");\n }\n\n // development mode\n if (this.alepha.isViteDev()) {\n await this.configureVite(ssrEnabled);\n return;\n }\n\n // production mode\n let root = \"\";\n\n // non-serverless mode only -> serve static files\n if (!this.alepha.isServerless()) {\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 await this.registerPages(async () => this.template);\n this.log.info(\"SSR OK\");\n return;\n }\n\n // no SSR enabled, serve index.html for all unmatched routes\n this.log.info(\"SSR is disabled, use History API fallback\");\n this.serverRouterProvider.createRoute({\n path: \"*\",\n handler: async ({ url, reply }) => {\n if (url.pathname.includes(\".\")) {\n // If the request is for a file (e.g., /style.css), do not fallback\n reply.headers[\"content-type\"] = \"text/plain\";\n reply.body = \"Not Found\";\n reply.status = 404;\n return;\n }\n\n reply.headers[\"content-type\"] = \"text/html\";\n\n // serve index.html for all unmatched routes\n return this.template;\n },\n });\n },\n });\n\n /**\n * Get the current HTML template.\n */\n public get template() {\n return (\n this.alepha.store.get(\"alepha.react.server.template\") ??\n \"<!DOCTYPE html><html lang='en'><head></head><body><div id='root'></div></body></html>\"\n );\n }\n\n /**\n * Register all pages as server routes.\n */\n protected async registerPages(templateLoader: TemplateLoader) {\n // Parse template once at startup\n const template = await templateLoader();\n if (template) {\n this.templateProvider.parseTemplate(template);\n }\n\n // Set up early head content (entry assets preloads)\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) {\n this.log.debug(`+ ${page.match} -> ${page.name}`);\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: this.createHandler(page, templateLoader),\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 * Uses <script type=\"module\"> instead of <link rel=\"modulepreload\"> for JS\n * because the script needs to execute anyway - this way the browser starts\n * downloading, parsing, AND will execute as soon as ready.\n *\n * Also strips these assets from the original template head to avoid duplicates.\n */\n protected setupEarlyHeadContent(): void {\n const assets = this.ssrManifestProvider.getEntryAssets();\n if (!assets) {\n return;\n }\n\n const parts: string[] = [];\n\n // Add CSS stylesheets (critical for rendering)\n for (const css of assets.css) {\n parts.push(`<link rel=\"stylesheet\" href=\"${css}\" crossorigin=\"\">`);\n }\n\n // Add entry JS as script module (not just modulepreload)\n // This starts download, parse, AND execution immediately\n if (assets.js) {\n parts.push(\n `<script type=\"module\" crossorigin=\"\" src=\"${assets.js}\"></script>`,\n );\n }\n\n if (parts.length > 0) {\n // Pass assets so they get stripped from original head content\n this.templateProvider.setEarlyHeadContent(\n parts.join(\"\\n\") + \"\\n\",\n assets,\n );\n this.log.debug(\"Early head content set\", {\n css: assets.css.length,\n js: assets.js ? 1 : 0,\n });\n }\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 * Configure Vite for SSR in development mode.\n */\n protected async configureVite(ssrEnabled: boolean) {\n if (!ssrEnabled) {\n // do nothing, vite will handle everything for us\n return;\n }\n\n const url = `http://localhost:${this.alepha.env.SERVER_PORT ?? \"5173\"}`;\n\n this.log.info(\"SSR (dev) OK\", { url });\n\n await this.registerPages(() =>\n fetch(`${url}/index.html`)\n .then((it) => it.text())\n .catch(() => undefined),\n );\n }\n\n /**\n * Create the request handler for a page route.\n */\n protected createHandler(\n route: PageRoute,\n templateLoader: TemplateLoader,\n ): ServerHandler {\n return async (serverRequest) => {\n const { url, reply, query, params } = serverRequest;\n\n // Ensure template is parsed (handles dev mode where template may change)\n if (!this.templateProvider.isReady()) {\n const template = await templateLoader();\n if (!template) {\n throw new AlephaError(\"Missing template for SSR rendering\");\n }\n this.templateProvider.parseTemplate(template);\n this.setupEarlyHeadContent();\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\n let target: PageRoute | undefined = route;\n while (target) {\n if (route.can && !route.can()) {\n this.log.warn(\n `Access to page '${route.name}' is forbidden by can() check`,\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 // 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 // Note: redirect happens after early head is sent, handled by stream\n reply.redirect(result.redirect);\n return null;\n }\n\n return { state, reactStream: result.reactStream! };\n },\n {\n hydration: true,\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 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;\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 this.serverTimingProvider.beginTiming(\"createLayers\");\n const { redirect } = await this.pageApi.createLayers(route, state);\n this.serverTimingProvider.endTiming(\"createLayers\");\n\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 this.serverTimingProvider.beginTiming(\"renderToStream\");\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 this.log.error(\"Streaming render error\", error);\n }\n },\n });\n\n this.serverTimingProvider.endTiming(\"renderToStream\");\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 // Ensure template is parsed with early head content (entry.js, CSS)\n if (!this.templateProvider.isReady()) {\n this.templateProvider.parseTemplate(this.template);\n this.setupEarlyHeadContent();\n }\n\n // Use shared rendering logic\n const result = await this.renderPage(page, state);\n\n if (result.redirect) {\n return { state, html: \"\", redirect: result.redirect };\n }\n\n const reactStream = result.reactStream!;\n\n // If full HTML page not requested, collect just the React content\n if (!options.html) {\n const html = await this.streamToString(reactStream);\n return { state, html };\n }\n\n // Create full HTML stream and collect to string\n const htmlStream = this.templateProvider.createHtmlStream(\n reactStream,\n state,\n { hydration: options.hydration ?? true },\n );\n\n const html = await this.streamToString(htmlStream);\n\n await this.alepha.events.emit(\"react:server:render:end\", { state, html });\n\n return { state, 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\ntype TemplateLoader = () => Promise<string | undefined>;\n\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst envSchema = t.object({\n REACT_SSR_ENABLED: t.optional(t.boolean()),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n interface State {\n \"alepha.react.server.ssr\"?: boolean;\n \"alepha.react.server.template\"?: string;\n }\n}\n\n/**\n * React server provider configuration atom\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 { AlephaReact } from \"@alepha/react\";\nimport { $module } from \"alepha\";\nimport { $page, type PageAnimation } from \"./primitives/$page.ts\";\nimport { ReactRouter } from \"./services/ReactRouter.ts\";\nimport { ReactPageProvider, type ReactRouterState } from \"./providers/ReactPageProvider.ts\";\nimport { AlephaServer, type ServerRequest } from \"alepha/server\";\nimport type { ReactNode } from \"react\";\nimport type { ReactHydrationState } from \"./providers/ReactBrowserProvider.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 { AlephaServerCache } from \"alepha/server/cache\";\nimport { AlephaServerLinks } from \"alepha/server/links\";\nimport { ReactPageService } from \"./services/ReactPageService.ts\";\nimport { AlephaDateTime } from \"alepha/datetime\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./index.shared.ts\";\nexport * from \"./providers/ReactPageProvider.ts\";\nexport * from \"./providers/ReactBrowserProvider.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 ReactRouter,\n ReactServerProvider,\n ReactServerTemplateProvider,\n SSRManifestProvider,\n ReactPageServerService,\n ],\n register: (alepha) =>\n alepha\n .with(AlephaReact)\n .with(AlephaDateTime)\n .with(AlephaServer)\n .with(AlephaServerCache)\n .with(AlephaServerLinks)\n .with({\n provide: ReactPageService,\n use: ReactPageServerService,\n })\n .with(SSRManifestProvider)\n .with(ReactServerTemplateProvider)\n .with(ReactServerProvider)\n .with(ReactPageProvider)\n .with(ReactRouter),\n});\n","import { ReactBrowserProvider, Redirection } from \"@alepha/react/router\";\nimport { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type { UserAccountToken } from \"alepha/security\";\nimport { HttpClient } from \"alepha/server\";\nimport { alephaServerAuthRoutes, tokenResponseSchema, type Tokens, userinfoResponseSchema } from \"alepha/server/auth\";\nimport { LinkProvider } from \"alepha/server/links\";\n\n/**\n * Browser, SSR friendly, service to handle authentication.\n */\nexport class ReactAuth {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly httpClient = $inject(HttpClient);\n protected readonly linkProvider = $inject(LinkProvider);\n\n protected readonly onBeginTransition = $hook({\n on: \"react:transition:begin\",\n handler: async (event) => {\n if (this.alepha.isBrowser()) {\n Object.defineProperty(event.state, \"user\", {\n get: () => this.user,\n });\n }\n },\n });\n\n protected readonly onFetchRequest = $hook({\n on: \"client:onRequest\",\n handler: async ({ request }) => {\n if (this.alepha.isBrowser() && this.user) {\n // ensure cookies are sent with requests and refresh-able\n request.credentials ??= \"include\";\n }\n },\n });\n\n /**\n * Get the current authenticated user.\n *\n * Alias for `alepha.state.get(\"user\")`\n */\n public get user(): UserAccountToken | undefined {\n return this.alepha.store.get(\"alepha.server.request.user\");\n }\n\n public async ping() {\n const { data } = await this.httpClient.fetch(alephaServerAuthRoutes.userinfo, {\n schema: { response: userinfoResponseSchema },\n });\n\n this.alepha.store.set(\"alepha.server.request.apiLinks\", data.api);\n this.alepha.store.set(\"alepha.server.request.user\", data.user);\n\n return data.user;\n }\n\n public can(action: string): boolean {\n if (!this.user) {\n return false;\n }\n\n return this.linkProvider.can(action);\n }\n\n public async login(\n provider: string,\n options: {\n hostname?: string;\n username?: string;\n password?: string;\n redirect?: string;\n realm?: string;\n [extra: string]: any;\n },\n ): Promise<Tokens> {\n const realmParam = options.realm ? `&realm=${encodeURIComponent(options.realm)}` : \"\";\n\n if (options.username || options.password) {\n const { data } = await this.httpClient.fetch(\n `${options.hostname || \"\"}${alephaServerAuthRoutes.token}?provider=${provider}${realmParam}`,\n {\n method: \"POST\",\n body: JSON.stringify({\n username: options.username,\n password: options.password,\n }),\n schema: { response: tokenResponseSchema },\n },\n );\n\n this.alepha.store.set(\"alepha.server.request.apiLinks\", data.api);\n this.alepha.store.set(\"alepha.server.request.user\", data.user);\n\n return data;\n }\n\n if (this.alepha.isBrowser()) {\n const browser = this.alepha.inject(ReactBrowserProvider);\n const redirect =\n options.redirect ||\n (browser.transitioning\n ? window.location.origin + browser.transitioning.to\n : window.location.href);\n\n const href = `${window.location.origin}${alephaServerAuthRoutes.login}?provider=${provider}${realmParam}&redirect_uri=${encodeURIComponent(redirect)}`;\n\n if (browser.transitioning) {\n throw new Redirection(href);\n } else {\n window.location.href = href;\n return {} as Tokens;\n }\n }\n\n throw new Redirection(\n `${alephaServerAuthRoutes.login}?provider=${provider}${realmParam}&redirect_uri=${options.redirect || \"/\"}`,\n );\n }\n\n public logout() {\n window.location.href = `${alephaServerAuthRoutes.logout}?post_logout_redirect_uri=${encodeURIComponent(window.location.origin)}`;\n }\n}\n","import { useAlepha, useStore } from \"@alepha/react\";\nimport { type HttpVirtualClient, LinkProvider } from \"alepha/server/links\";\nimport { ReactAuth } from \"../services/ReactAuth.ts\";\n\nexport const useAuth = <T extends object = any>() => {\n const alepha = useAlepha();\n const [user] = useStore(\"alepha.server.request.user\");\n\n return {\n user,\n logout: () => {\n alepha.inject(ReactAuth).logout();\n },\n login: async (\n provider: keyof T,\n options: {\n username?: string;\n password?: string;\n redirect?: string;\n realm?: string;\n [extra: string]: any;\n } = {},\n ) => {\n await alepha.inject(ReactAuth).login(provider as string, options);\n },\n can: <Api extends object = any>(\n name: keyof HttpVirtualClient<Api>,\n ): boolean => {\n return alepha.inject(LinkProvider).can(name as string);\n },\n };\n};\n","import { AlephaReact } from \"@alepha/react\";\nimport { $module } from \"alepha\";\nimport type { UserAccount } from \"alepha/security\";\nimport { ReactAuthProvider } from \"./providers/ReactAuthProvider.ts\";\nimport { ReactAuth } from \"./services/ReactAuth.ts\";\nimport { $auth, AlephaServerAuth } from \"alepha/server/auth\";\nimport { AlephaServerLinks } from \"alepha/server/links\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./index.shared.ts\";\nexport * from \"./providers/ReactAuthProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"@alepha/react/router\" {\n interface ReactRouterState {\n user?: UserAccount;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * The ReactAuthModule provides authentication services for React applications.\n *\n * @see {@link ReactAuthProvider}\n * @module alepha.react.auth\n */\nexport const AlephaReactAuth = $module({\n name: \"alepha.react.auth\",\n primitives: [$auth],\n services: [AlephaReact, AlephaServerLinks, AlephaServerAuth, ReactAuthProvider, ReactAuth],\n});\n"],"mappings":"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"}