@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,17 +1,17 @@
1
1
  import { ClientOnlyProps } from "@alepha/react";
2
- import * as alepha12 from "alepha";
2
+ import * as alepha1 from "alepha";
3
3
  import { Alepha, AlephaError, Async, KIND, Primitive, Static, TObject, TSchema } from "alepha";
4
4
  import { DateTimeProvider } from "alepha/datetime";
5
5
  import * as alepha_logger0 from "alepha/logger";
6
6
  import { LinkProvider } from "alepha/server/links";
7
+ import { BrowserHeadProvider, Head, ServerHeadProvider, SimpleHead } from "@alepha/react/head";
7
8
  import { Route, RouterProvider } from "alepha/router";
8
9
  import * as react0 from "react";
9
10
  import { AnchorHTMLAttributes, CSSProperties, FC, ReactNode } from "react";
10
11
  import * as react_jsx_runtime0 from "react/jsx-runtime";
11
- import * as alepha_server0 from "alepha/server";
12
12
  import { ServerHandler, ServerRequest, ServerRouterProvider, ServerTimingProvider } from "alepha/server";
13
+ import { FileSystemProvider } from "alepha/file";
13
14
  import { ServerStaticProvider } from "alepha/server/static";
14
- import * as alepha_server_cache0 from "alepha/server/cache";
15
15
  import { ServerRouteCache } from "alepha/server/cache";
16
16
 
17
17
  //#region ../../src/router/errors/Redirection.d.ts
@@ -26,7 +26,7 @@ import { ServerRouteCache } from "alepha/server/cache";
26
26
  * import { Redirection } from "@alepha/react";
27
27
  *
28
28
  * const MyPage = $page({
29
- * resolve: async () => {
29
+ * loader: async () => {
30
30
  * if (needRedirect) {
31
31
  * throw new Redirection("/new-path");
32
32
  * }
@@ -40,11 +40,11 @@ declare class Redirection extends AlephaError {
40
40
  }
41
41
  //#endregion
42
42
  //#region ../../src/router/providers/ReactPageProvider.d.ts
43
- declare const envSchema$2: alepha12.TObject<{
44
- REACT_STRICT_MODE: alepha12.TBoolean;
43
+ declare const envSchema$1: alepha1.TObject<{
44
+ REACT_STRICT_MODE: alepha1.TBoolean;
45
45
  }>;
46
46
  declare module "alepha" {
47
- interface Env extends Partial<Static<typeof envSchema$2>> {}
47
+ interface Env extends Partial<Static<typeof envSchema$1>> {}
48
48
  }
49
49
  /**
50
50
  * Handle page routes for React applications. (Browser and Server)
@@ -86,7 +86,7 @@ declare class ReactPageProvider {
86
86
  }, params?: Record<string, any>): string;
87
87
  compile(path: string, params?: Record<string, string>): string;
88
88
  protected renderView(index: number, path: string, view: ReactNode | undefined, page: PageRoute): ReactNode;
89
- protected readonly configure: alepha12.HookPrimitive<"configure">;
89
+ protected readonly configure: alepha1.HookPrimitive<"configure">;
90
90
  protected map(pages: Array<PagePrimitive>, target: PagePrimitive): PageRouteEntry;
91
91
  add(entry: PageRouteEntry): void;
92
92
  protected createMatch(page: PageRoute): string;
@@ -157,6 +157,11 @@ interface ReactRouterState {
157
157
  * Optional meta information associated with the current page.
158
158
  */
159
159
  meta: Record<string, any>;
160
+ /**
161
+ * Head configuration for the current page (title, meta tags, etc.).
162
+ * Populated by HeadProvider during SSR.
163
+ */
164
+ head: Head;
160
165
  name?: string;
161
166
  }
162
167
  interface RouterStackItem {
@@ -186,6 +191,14 @@ declare abstract class ReactPageService {
186
191
  render(name: string, options?: PagePrimitiveRenderOptions): Promise<PagePrimitiveRenderResult>;
187
192
  }
188
193
  //#endregion
194
+ //#region ../../src/router/constants/PAGE_PRELOAD_KEY.d.ts
195
+ /**
196
+ * Symbol key for SSR module preloading path.
197
+ * Using Symbol.for() allows the Vite plugin to inject this at build time.
198
+ * @internal
199
+ */
200
+ declare const PAGE_PRELOAD_KEY: unique symbol;
201
+ //#endregion
189
202
  //#region ../../src/router/primitives/$page.d.ts
190
203
  /**
191
204
  * Main primitive for defining a React route in the application.
@@ -199,7 +212,7 @@ declare abstract class ReactPageService {
199
212
  * - Type-safe URL parameter and query string validation
200
213
  *
201
214
  * **Data Loading**
202
- * - Server-side data fetching with the `resolve` function
215
+ * - Server-side data fetching with the `loader` function
203
216
  * - Automatic serialization and hydration for SSR
204
217
  * - Access to request context, URL params, and parent data
205
218
  *
@@ -236,7 +249,7 @@ declare abstract class ReactPageService {
236
249
  * params: t.object({ id: t.integer() }),
237
250
  * query: t.object({ tab: t.optional(t.text()) })
238
251
  * },
239
- * resolve: async ({ params }) => {
252
+ * loader: async ({ params }) => {
240
253
  * const user = await userApi.getUser(params.id);
241
254
  * return { user };
242
255
  * },
@@ -249,7 +262,7 @@ declare abstract class ReactPageService {
249
262
  * const projectSection = $page({
250
263
  * path: "/projects/:id",
251
264
  * children: () => [projectBoard, projectSettings],
252
- * resolve: async ({ params }) => {
265
+ * loader: async ({ params }) => {
253
266
  * const project = await projectApi.get(params.id);
254
267
  * return { project };
255
268
  * },
@@ -268,7 +281,7 @@ declare abstract class ReactPageService {
268
281
  * static: {
269
282
  * entries: posts.map(p => ({ params: { slug: p.slug } }))
270
283
  * },
271
- * resolve: async ({ params }) => {
284
+ * loader: async ({ params }) => {
272
285
  * const post = await loadPost(params.slug);
273
286
  * return { post };
274
287
  * }
@@ -309,12 +322,12 @@ interface PagePrimitiveOptions<TConfig extends PageConfigSchema = PageConfigSche
309
322
  *
310
323
  * > In SSR, the returned data will be serialized and sent to the client, then reused during the client-side hydration.
311
324
  *
312
- * Resolve can be stopped by throwing an error, which will be handled by the `errorHandler` function.
325
+ * Loader can be stopped by throwing an error, which will be handled by the `errorHandler` function.
313
326
  * It's common to throw a `NotFoundError` to display a 404 page.
314
327
  *
315
328
  * RedirectError can be thrown to redirect the user to another page.
316
329
  */
317
- resolve?: (context: PageResolve<TConfig, TPropsParent>) => Async<TProps>;
330
+ loader?: (context: PageLoader<TConfig, TPropsParent>) => Async<TProps>;
318
331
  /**
319
332
  * Default props to pass to the component when rendering the page.
320
333
  *
@@ -354,7 +367,7 @@ interface PagePrimitiveOptions<TConfig extends PageConfigSchema = PageConfigSche
354
367
  */
355
368
  can?: () => boolean;
356
369
  /**
357
- * Catch any error from the `resolve` function or during `rendering`.
370
+ * Catch any error from the `loader` function or during `rendering`.
358
371
  *
359
372
  * Expected to return one of the following:
360
373
  * - a ReactNode to render an error page
@@ -366,7 +379,7 @@ interface PagePrimitiveOptions<TConfig extends PageConfigSchema = PageConfigSche
366
379
  *
367
380
  * @example Catch a 404 from API and render a custom not found component:
368
381
  * ```ts
369
- * resolve: async ({ params, query }) => {
382
+ * loader: async ({ params, query }) => {
370
383
  * api.fetch("/api/resource", { params, query });
371
384
  * },
372
385
  * errorHandler: (error, context) => {
@@ -378,7 +391,7 @@ interface PagePrimitiveOptions<TConfig extends PageConfigSchema = PageConfigSche
378
391
  *
379
392
  * @example Catch an 401 error and redirect the user to the login page:
380
393
  * ```ts
381
- * resolve: async ({ params, query }) => {
394
+ * loader: async ({ params, query }) => {
382
395
  * // but the user is not authenticated
383
396
  * api.fetch("/api/resource", { params, query });
384
397
  * },
@@ -459,6 +472,37 @@ interface PagePrimitiveOptions<TConfig extends PageConfigSchema = PageConfigSche
459
472
  * ```
460
473
  */
461
474
  animation?: PageAnimation;
475
+ /**
476
+ * Head configuration for the page (title, meta tags, etc.).
477
+ *
478
+ * Can be a static object or a function that receives resolved props.
479
+ *
480
+ * @example Static head
481
+ * ```ts
482
+ * head: {
483
+ * title: "My Page",
484
+ * description: "Page description",
485
+ * }
486
+ * ```
487
+ *
488
+ * @example Dynamic head based on props
489
+ * ```ts
490
+ * head: (props) => ({
491
+ * title: props.user.name,
492
+ * description: `Profile of ${props.user.name}`,
493
+ * })
494
+ * ```
495
+ */
496
+ head?: Head | ((props: TProps, previous?: Head) => Head);
497
+ /**
498
+ * Source path for SSR module preloading.
499
+ *
500
+ * This is automatically injected by the viteAlephaPreload plugin.
501
+ * It maps to the source file path used in Vite's SSR manifest.
502
+ *
503
+ * @internal
504
+ */
505
+ [PAGE_PRELOAD_KEY]?: string;
462
506
  }
463
507
  type ErrorHandler = (error: Error, state: ReactRouterState) => ReactNode | Redirection | undefined;
464
508
  declare class PagePrimitive<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> extends Primitive<PagePrimitiveOptions<TConfig, TProps, TPropsParent>> {
@@ -506,7 +550,7 @@ interface PageRequestConfig<TConfig extends PageConfigSchema = PageConfigSchema>
506
550
  params: TConfig["params"] extends TSchema ? Static<TConfig["params"]> : Record<string, string>;
507
551
  query: TConfig["query"] extends TSchema ? Static<TConfig["query"]> : Record<string, string>;
508
552
  }
509
- type PageResolve<TConfig extends PageConfigSchema = PageConfigSchema, TPropsParent extends object = TPropsParentDefault> = PageRequestConfig<TConfig> & TPropsParent & Omit<ReactRouterState, "layers" | "onError">;
553
+ type PageLoader<TConfig extends PageConfigSchema = PageConfigSchema, TPropsParent extends object = TPropsParentDefault> = PageRequestConfig<TConfig> & TPropsParent & Omit<ReactRouterState, "layers" | "onError">;
510
554
  type PageAnimation = PageAnimationObject | ((state: ReactRouterState) => PageAnimationObject | undefined);
511
555
  type PageAnimationObject = CssAnimationName | {
512
556
  enter?: CssAnimation | CssAnimationName;
@@ -530,67 +574,13 @@ declare class ReactBrowserRouterProvider extends RouterProvider<BrowserRoute> {
530
574
  protected readonly log: alepha_logger0.Logger;
531
575
  protected readonly alepha: Alepha;
532
576
  protected readonly pageApi: ReactPageProvider;
577
+ protected readonly browserHeadProvider: BrowserHeadProvider;
533
578
  add(entry: PageRouteEntry): void;
534
- protected readonly configure: alepha12.HookPrimitive<"configure">;
579
+ protected readonly configure: alepha1.HookPrimitive<"configure">;
535
580
  transition(url: URL, previous?: PreviousLayerData[], meta?: {}): Promise<string | void>;
536
581
  root(state: ReactRouterState): ReactNode;
537
582
  }
538
583
  //#endregion
539
- //#region ../../src/core/components/ClientOnly.d.ts
540
- interface ClientOnlyProps$1 {
541
- fallback?: ReactNode;
542
- disabled?: boolean;
543
- }
544
- //#endregion
545
- //#region ../../src/core/index.d.ts
546
- declare module "alepha" {
547
- interface Hooks {
548
- /**
549
- * Fires when a user action is starting.
550
- * Action can be a form submission, a route transition, or a custom action.
551
- */
552
- "react:action:begin": {
553
- type: string;
554
- id?: string;
555
- };
556
- /**
557
- * Fires when a user action has succeeded.
558
- * Action can be a form submission, a route transition, or a custom action.
559
- */
560
- "react:action:success": {
561
- type: string;
562
- id?: string;
563
- };
564
- /**
565
- * Fires when a user action has failed.
566
- * Action can be a form submission, a route transition, or a custom action.
567
- */
568
- "react:action:error": {
569
- type: string;
570
- id?: string;
571
- error: Error;
572
- };
573
- /**
574
- * Fires when a user action has completed, regardless of success or failure.
575
- * Action can be a form submission, a route transition, or a custom action.
576
- */
577
- "react:action:end": {
578
- type: string;
579
- id?: string;
580
- };
581
- }
582
- }
583
- /**
584
- * Provides full-stack React development with declarative routing, server-side rendering, and client-side hydration.
585
- *
586
- * The React module enables building modern React applications using the `$page` primitive on class properties.
587
- * It delivers seamless server-side rendering, automatic code splitting, and client-side navigation with full
588
- * type safety and schema validation for route parameters and data.
589
- *
590
- * @see {@link $page}
591
- * @module alepha.react
592
- */
593
- //#endregion
594
584
  //#region ../../src/router/services/ReactRouter.d.ts
595
585
  interface RouterGoOptions {
596
586
  replace?: boolean;
@@ -607,7 +597,7 @@ interface RouterGoOptions {
607
597
  *
608
598
  * Can be safely used server-side, but most methods will be no-op.
609
599
  */
610
- declare class ReactRouter<T$1 extends object> {
600
+ declare class ReactRouter<T extends object> {
611
601
  protected readonly alepha: Alepha;
612
602
  protected readonly pageApi: ReactPageProvider;
613
603
  get state(): ReactRouterState;
@@ -617,62 +607,11 @@ declare class ReactRouter<T$1 extends object> {
617
607
  isActive(href: string, options?: {
618
608
  startWith?: boolean;
619
609
  }): boolean;
620
- node(name: keyof VirtualRouter<T$1> | string, config?: {
610
+ node(name: keyof VirtualRouter<T> | string, config?: {
621
611
  params?: Record<string, any>;
622
612
  query?: Record<string, any>;
623
- }): {
624
- label: any;
625
- children: undefined;
626
- type: "page";
627
- name: string;
628
- parent?: PageRoute;
629
- match: string;
630
- path?: string | undefined;
631
- schema?: PageConfigSchema | undefined;
632
- resolve?: ((context: PageResolve<PageConfigSchema, TPropsParentDefault>) => any) | undefined;
633
- props?: (() => Partial<any>) | undefined;
634
- component?: react0.FC<any> | undefined;
635
- lazy?: (() => Promise<{
636
- default: react0.FC<any>;
637
- }>) | undefined;
638
- can?: (() => boolean) | undefined;
639
- errorHandler?: ErrorHandler | undefined;
640
- static?: boolean | {
641
- entries?: Partial<PageRequestConfig<PageConfigSchema>>[] | undefined;
642
- } | undefined;
643
- cache?: alepha_server_cache0.ServerRouteCache | undefined;
644
- client?: (boolean | ClientOnlyProps$1) | undefined;
645
- onServerResponse?: ((request: alepha_server0.ServerRequest) => unknown) | undefined;
646
- onLeave?: (() => void) | undefined;
647
- animation?: PageAnimation | undefined;
648
- } | {
649
- label: any;
650
- href: string;
651
- children: undefined;
652
- type: "page";
653
- name: string;
654
- parent?: PageRoute;
655
- match: string;
656
- path?: string | undefined;
657
- schema?: PageConfigSchema | undefined;
658
- resolve?: ((context: PageResolve<PageConfigSchema, TPropsParentDefault>) => any) | undefined;
659
- props?: (() => Partial<any>) | undefined;
660
- component?: react0.FC<any> | undefined;
661
- lazy?: (() => Promise<{
662
- default: react0.FC<any>;
663
- }>) | undefined;
664
- can?: (() => boolean) | undefined;
665
- errorHandler?: ErrorHandler | undefined;
666
- static?: boolean | {
667
- entries?: Partial<PageRequestConfig<PageConfigSchema>>[] | undefined;
668
- } | undefined;
669
- cache?: alepha_server_cache0.ServerRouteCache | undefined;
670
- client?: (boolean | ClientOnlyProps$1) | undefined;
671
- onServerResponse?: ((request: alepha_server0.ServerRequest) => unknown) | undefined;
672
- onLeave?: (() => void) | undefined;
673
- animation?: PageAnimation | undefined;
674
- };
675
- path(name: keyof VirtualRouter<T$1> | string, config?: {
613
+ }): any;
614
+ path(name: keyof VirtualRouter<T> | string, config?: {
676
615
  params?: Record<string, any>;
677
616
  query?: Record<string, any>;
678
617
  }): string;
@@ -690,9 +629,9 @@ declare class ReactRouter<T$1 extends object> {
690
629
  forward(): Promise<void>;
691
630
  invalidate(props?: Record<string, any>): Promise<void>;
692
631
  go(path: string, options?: RouterGoOptions): Promise<void>;
693
- go(path: keyof VirtualRouter<T$1>, options?: RouterGoOptions): Promise<void>;
632
+ go(path: keyof VirtualRouter<T>, options?: RouterGoOptions): Promise<void>;
694
633
  anchor(path: string, options?: RouterGoOptions): AnchorProps;
695
- anchor(path: keyof VirtualRouter<T$1>, options?: RouterGoOptions): AnchorProps;
634
+ anchor(path: keyof VirtualRouter<T>, options?: RouterGoOptions): AnchorProps;
696
635
  base(path: string): string;
697
636
  /**
698
637
  * Set query params.
@@ -707,20 +646,14 @@ declare class ReactRouter<T$1 extends object> {
707
646
  push?: boolean;
708
647
  }): void;
709
648
  }
710
- type VirtualRouter<T$1> = { [K in keyof T$1 as T$1[K] extends PagePrimitive ? K : never]: T$1[K] };
649
+ type VirtualRouter<T> = { [K in keyof T as T[K] extends PagePrimitive ? K : never]: T[K] };
711
650
  //#endregion
712
651
  //#region ../../src/router/providers/ReactBrowserProvider.d.ts
713
- declare const envSchema$1: alepha12.TObject<{
714
- REACT_ROOT_ID: alepha12.TString;
715
- }>;
716
- declare module "alepha" {
717
- interface Env extends Partial<Static<typeof envSchema$1>> {}
718
- }
719
652
  /**
720
653
  * React browser renderer configuration atom
721
654
  */
722
- declare const reactBrowserOptions: alepha12.Atom<alepha12.TObject<{
723
- scrollRestoration: alepha12.TUnsafe<"top" | "manual">;
655
+ declare const reactBrowserOptions: alepha1.Atom<alepha1.TObject<{
656
+ scrollRestoration: alepha1.TUnsafe<"top" | "manual">;
724
657
  }>, "alepha.react.browser.options">;
725
658
  type ReactBrowserRendererOptions = Static<typeof reactBrowserOptions.schema>;
726
659
  declare module "alepha" {
@@ -729,17 +662,16 @@ declare module "alepha" {
729
662
  }
730
663
  }
731
664
  declare class ReactBrowserProvider {
732
- protected readonly env: {
733
- REACT_ROOT_ID: string;
734
- };
735
665
  protected readonly log: alepha_logger0.Logger;
736
666
  protected readonly client: LinkProvider;
737
667
  protected readonly alepha: Alepha;
738
668
  protected readonly router: ReactBrowserRouterProvider;
739
669
  protected readonly dateTimeProvider: DateTimeProvider;
670
+ protected readonly browserHeadProvider: BrowserHeadProvider;
740
671
  protected readonly options: Readonly<{
741
672
  scrollRestoration: "top" | "manual";
742
673
  }>;
674
+ get rootId(): string;
743
675
  protected getRootElement(): HTMLElement;
744
676
  transitioning?: {
745
677
  to: string;
@@ -768,8 +700,8 @@ declare class ReactBrowserProvider {
768
700
  * Get embedded layers from the server.
769
701
  */
770
702
  protected getHydrationState(): ReactHydrationState | undefined;
771
- protected readonly onTransitionEnd: alepha12.HookPrimitive<"react:transition:end">;
772
- readonly ready: alepha12.HookPrimitive<"ready">;
703
+ protected readonly onTransitionEnd: alepha1.HookPrimitive<"react:transition:end">;
704
+ readonly ready: alepha1.HookPrimitive<"ready">;
773
705
  }
774
706
  type ReactHydrationState = {
775
707
  layers?: Array<PreviousLayerData>;
@@ -1138,7 +1070,7 @@ interface UseActiveHook {
1138
1070
  /**
1139
1071
  * Hook to manage query parameters in the URL using a defined schema.
1140
1072
  */
1141
- declare const useQueryParams: <T$1 extends TObject>(schema: T$1, options?: UseQueryParamsHookOptions) => [Partial<Static<T$1>>, (data: Static<T$1>) => void];
1073
+ declare const useQueryParams: <T extends TObject>(schema: T, options?: UseQueryParamsHookOptions) => [Partial<Static<T>>, (data: Static<T>) => void];
1142
1074
  interface UseQueryParamsHookOptions {
1143
1075
  format?: "base64" | "querystring";
1144
1076
  key?: string;
@@ -1160,57 +1092,483 @@ interface UseQueryParamsHookOptions {
1160
1092
  * const router = useRouter<App>();
1161
1093
  * router.go("home"); // typesafe
1162
1094
  */
1163
- declare const useRouter: <T$1 extends object = any>() => ReactRouter<T$1>;
1095
+ declare const useRouter: <T extends object = any>() => ReactRouter<T>;
1164
1096
  //#endregion
1165
1097
  //#region ../../src/router/hooks/useRouterState.d.ts
1166
1098
  declare const useRouterState: () => ReactRouterState;
1167
1099
  //#endregion
1168
- //#region ../../src/router/providers/ReactServerProvider.d.ts
1169
- declare const envSchema: alepha12.TObject<{
1170
- REACT_SSR_ENABLED: alepha12.TOptional<alepha12.TBoolean>;
1171
- REACT_ROOT_ID: alepha12.TString;
1172
- }>;
1173
- declare module "alepha" {
1174
- interface Env extends Partial<Static<typeof envSchema>> {}
1175
- interface State {
1176
- "alepha.react.server.ssr"?: boolean;
1177
- "alepha.react.server.template"?: string;
1178
- }
1100
+ //#region ../../src/router/providers/ReactServerTemplateProvider.d.ts
1101
+ /**
1102
+ * Handles HTML template parsing, preprocessing, and streaming for SSR.
1103
+ *
1104
+ * Responsibilities:
1105
+ * - Parse template once at startup into logical slots
1106
+ * - Pre-encode static parts as Uint8Array for zero-copy streaming
1107
+ * - Render dynamic parts (attributes, head content) efficiently
1108
+ * - Build hydration data for client-side rehydration
1109
+ *
1110
+ * This provider is injected into ReactServerProvider to handle all
1111
+ * template-related operations, keeping ReactServerProvider focused
1112
+ * on request handling and React rendering coordination.
1113
+ */
1114
+ declare class ReactServerTemplateProvider {
1115
+ protected readonly log: alepha_logger0.Logger;
1116
+ protected readonly alepha: Alepha;
1117
+ /**
1118
+ * Shared TextEncoder instance - reused across all requests.
1119
+ */
1120
+ protected readonly encoder: TextEncoder;
1121
+ /**
1122
+ * Pre-encoded common strings for streaming.
1123
+ */
1124
+ protected readonly ENCODED: {
1125
+ readonly HYDRATION_PREFIX: Uint8Array<ArrayBuffer>;
1126
+ readonly HYDRATION_SUFFIX: Uint8Array<ArrayBuffer>;
1127
+ readonly EMPTY: Uint8Array<ArrayBuffer>;
1128
+ };
1129
+ /**
1130
+ * Cached template slots - parsed once, reused for all requests.
1131
+ */
1132
+ protected slots: TemplateSlots | null;
1133
+ /**
1134
+ * Root element ID for React mounting.
1135
+ */
1136
+ get rootId(): string;
1137
+ /**
1138
+ * Regex pattern for matching the root div and extracting its content.
1139
+ */
1140
+ get rootDivRegex(): RegExp;
1141
+ /**
1142
+ * Extract the content inside the root div from HTML.
1143
+ *
1144
+ * @param html - Full HTML string
1145
+ * @returns The content inside the root div, or undefined if not found
1146
+ */
1147
+ extractRootContent(html: string): string | undefined;
1148
+ /**
1149
+ * Check if template has been parsed and slots are available.
1150
+ */
1151
+ isReady(): boolean;
1152
+ /**
1153
+ * Get the parsed template slots.
1154
+ * Throws if template hasn't been parsed yet.
1155
+ */
1156
+ getSlots(): TemplateSlots;
1157
+ /**
1158
+ * Parse an HTML template into logical slots for efficient streaming.
1159
+ *
1160
+ * This should be called once during server startup/configuration.
1161
+ * The parsed slots are cached and reused for all requests.
1162
+ *
1163
+ * @param template - The HTML template string (typically index.html)
1164
+ */
1165
+ parseTemplate(template: string): TemplateSlots;
1166
+ /**
1167
+ * Parse HTML attributes string into a record.
1168
+ *
1169
+ * Handles: key="value", key='value', key=value, and boolean key
1170
+ */
1171
+ protected parseAttributes(attrStr: string): Record<string, string>;
1172
+ /**
1173
+ * Render attributes record to HTML string.
1174
+ *
1175
+ * @param attrs - Attributes to render
1176
+ * @returns HTML attribute string like ` lang="en" class="dark"`
1177
+ */
1178
+ renderAttributes(attrs: Record<string, string>): string;
1179
+ /**
1180
+ * Render merged HTML attributes (original + dynamic).
1181
+ */
1182
+ renderMergedHtmlAttrs(dynamicAttrs?: Record<string, string>): string;
1183
+ /**
1184
+ * Render merged body attributes (original + dynamic).
1185
+ */
1186
+ renderMergedBodyAttrs(dynamicAttrs?: Record<string, string>): string;
1187
+ /**
1188
+ * Render head content (title, meta, link, script tags).
1189
+ *
1190
+ * @param head - Head data to render
1191
+ * @param includeOriginal - Whether to include original head content
1192
+ * @returns HTML string with head content
1193
+ */
1194
+ renderHeadContent(head?: SimpleHead, includeOriginal?: boolean): string;
1195
+ /**
1196
+ * Render a meta tag.
1197
+ */
1198
+ protected renderMetaTag(meta: {
1199
+ name?: string;
1200
+ property?: string;
1201
+ content: string;
1202
+ }): string;
1203
+ /**
1204
+ * Render a link tag.
1205
+ */
1206
+ protected renderLinkTag(link: {
1207
+ rel: string;
1208
+ href: string;
1209
+ as?: string;
1210
+ crossorigin?: string;
1211
+ }): string;
1212
+ /**
1213
+ * Render a script tag.
1214
+ */
1215
+ protected renderScriptTag(script: Record<string, string | boolean>): string;
1216
+ /**
1217
+ * Escape HTML special characters.
1218
+ */
1219
+ escapeHtml(str: string): string;
1220
+ /**
1221
+ * Safely serialize data to JSON for embedding in HTML.
1222
+ * Escapes characters that could break out of script tags.
1223
+ */
1224
+ safeJsonSerialize(data: unknown): string;
1225
+ /**
1226
+ * Build hydration data from router state.
1227
+ *
1228
+ * This creates the data structure that will be serialized to window.__ssr
1229
+ * for client-side rehydration.
1230
+ */
1231
+ buildHydrationData(state: ReactRouterState): HydrationData;
1232
+ /**
1233
+ * Encode a string to Uint8Array using the shared encoder.
1234
+ */
1235
+ encode(str: string): Uint8Array;
1236
+ /**
1237
+ * Get the pre-encoded hydration script prefix.
1238
+ */
1239
+ get hydrationPrefix(): Uint8Array;
1240
+ /**
1241
+ * Get the pre-encoded hydration script suffix.
1242
+ */
1243
+ get hydrationSuffix(): Uint8Array;
1244
+ /**
1245
+ * Create a ReadableStream that streams the HTML template with React content.
1246
+ *
1247
+ * This is the main entry point for SSR streaming. It:
1248
+ * 1. Sends <head> immediately (browser starts downloading assets)
1249
+ * 2. Streams React content as it renders
1250
+ * 3. Appends hydration script and closing tags
1251
+ *
1252
+ * @param reactStream - ReadableStream from renderToReadableStream
1253
+ * @param state - Router state with head data
1254
+ * @param options - Streaming options
1255
+ */
1256
+ createHtmlStream(reactStream: ReadableStream<Uint8Array>, state: ReactRouterState, options?: {
1257
+ hydration?: boolean;
1258
+ onError?: (error: unknown) => void;
1259
+ }): ReadableStream<Uint8Array>;
1260
+ /**
1261
+ * Early head content for preloading.
1262
+ *
1263
+ * Contains entry assets (JS + CSS) that are always required and can be
1264
+ * sent before page loaders run.
1265
+ */
1266
+ protected earlyHeadContent: string;
1267
+ /**
1268
+ * Set the early head content (entry script + CSS).
1269
+ *
1270
+ * Also strips these assets from the original head content to avoid duplicates,
1271
+ * since we're moving them to the early phase.
1272
+ *
1273
+ * @param content - HTML string with entry assets
1274
+ * @param entryAssets - Entry asset paths to strip from original head
1275
+ */
1276
+ setEarlyHeadContent(content: string, entryAssets?: {
1277
+ js?: string;
1278
+ css: string[];
1279
+ }): void;
1280
+ /**
1281
+ * Escape special regex characters in a string.
1282
+ */
1283
+ protected escapeRegExp(str: string): string;
1284
+ /**
1285
+ * Create an optimized HTML stream with early head streaming.
1286
+ *
1287
+ * This version sends critical assets (entry.js, CSS) BEFORE page loaders run,
1288
+ * allowing the browser to start downloading them immediately.
1289
+ *
1290
+ * Flow:
1291
+ * 1. Send DOCTYPE, <html>, <head> open, entry preloads (IMMEDIATE)
1292
+ * 2. Run async work (createLayers, etc.)
1293
+ * 3. Send rest of head, body, React content, hydration
1294
+ *
1295
+ * @param globalHead - Global head with htmlAttributes (from $head primitives)
1296
+ * @param asyncWork - Async function to run between early head and rest of stream
1297
+ * @param options - Streaming options
1298
+ */
1299
+ createEarlyHtmlStream(globalHead: SimpleHead, asyncWork: () => Promise<{
1300
+ state: ReactRouterState;
1301
+ reactStream: ReadableStream<Uint8Array>;
1302
+ } | null>, options?: {
1303
+ hydration?: boolean;
1304
+ onError?: (error: unknown) => void;
1305
+ onRedirect?: (url: string) => void;
1306
+ }): ReadableStream<Uint8Array>;
1179
1307
  }
1180
1308
  /**
1181
- * React server provider configuration atom
1309
+ * Template slots - the template split into logical parts for efficient streaming.
1310
+ *
1311
+ * Static parts are pre-encoded as Uint8Array for zero-copy streaming.
1312
+ * Dynamic parts (attributes, head content) are kept as strings/objects for merging.
1313
+ */
1314
+ interface TemplateSlots {
1315
+ doctype: Uint8Array;
1316
+ htmlOpen: Uint8Array;
1317
+ htmlClose: Uint8Array;
1318
+ headOpen: Uint8Array;
1319
+ headClose: Uint8Array;
1320
+ bodyOpen: Uint8Array;
1321
+ bodyClose: Uint8Array;
1322
+ rootOpen: Uint8Array;
1323
+ rootClose: Uint8Array;
1324
+ scriptClose: Uint8Array;
1325
+ htmlOriginalAttrs: Record<string, string>;
1326
+ bodyOriginalAttrs: Record<string, string>;
1327
+ headOriginalContent: string;
1328
+ beforeRoot: string;
1329
+ afterRoot: string;
1330
+ }
1331
+ /**
1332
+ * Hydration state that gets serialized to window.__ssr
1182
1333
  */
1183
- declare const reactServerOptions: alepha12.Atom<alepha12.TObject<{
1184
- publicDir: alepha12.TString;
1185
- staticServer: alepha12.TObject<{
1186
- disabled: alepha12.TBoolean;
1187
- path: alepha12.TString;
1334
+ interface HydrationData {
1335
+ layers: Array<{
1336
+ data?: unknown;
1337
+ error?: {
1338
+ name: string;
1339
+ message: string;
1340
+ stack?: string;
1341
+ };
1342
+ }>;
1343
+ [key: string]: unknown;
1344
+ }
1345
+ //#endregion
1346
+ //#region ../../src/router/atoms/ssrManifestAtom.d.ts
1347
+ /**
1348
+ * Schema for the SSR manifest atom.
1349
+ */
1350
+ declare const ssrManifestAtomSchema: alepha1.TObject<{
1351
+ /**
1352
+ * Preload manifest mapping short keys to source paths.
1353
+ * Generated by viteAlephaSsrPreload plugin at build time.
1354
+ */
1355
+ preload: alepha1.TOptional<alepha1.TRecord<"^.*$", alepha1.TString>>;
1356
+ /**
1357
+ * SSR manifest mapping source files to their required chunks.
1358
+ */
1359
+ ssr: alepha1.TOptional<alepha1.TRecord<"^.*$", alepha1.TArray<alepha1.TString>>>;
1360
+ /**
1361
+ * Client manifest mapping source files to their output information.
1362
+ */
1363
+ client: alepha1.TOptional<alepha1.TRecord<"^.*$", alepha1.TObject<{
1364
+ file: alepha1.TString;
1365
+ src: alepha1.TOptional<alepha1.TString>;
1366
+ isEntry: alepha1.TOptional<alepha1.TBoolean>;
1367
+ isDynamicEntry: alepha1.TOptional<alepha1.TBoolean>;
1368
+ imports: alepha1.TOptional<alepha1.TArray<alepha1.TString>>;
1369
+ dynamicImports: alepha1.TOptional<alepha1.TArray<alepha1.TString>>;
1370
+ css: alepha1.TOptional<alepha1.TArray<alepha1.TString>>;
1371
+ assets: alepha1.TOptional<alepha1.TArray<alepha1.TString>>;
1372
+ }>>>;
1373
+ }>;
1374
+ /**
1375
+ * Type for the SSR manifest schema.
1376
+ */
1377
+ type SsrManifestAtomSchema = typeof ssrManifestAtomSchema;
1378
+ //#endregion
1379
+ //#region ../../src/router/providers/SSRManifestProvider.d.ts
1380
+ /**
1381
+ * Provider for SSR manifest data used for module preloading.
1382
+ *
1383
+ * The manifest is populated at build time by embedding data into the
1384
+ * generated index.js via the ssrManifestAtom. This eliminates filesystem
1385
+ * reads at runtime, making it optimal for serverless deployments.
1386
+ *
1387
+ * Manifest files are generated during `vite build`:
1388
+ * - manifest.json (client manifest)
1389
+ * - ssr-manifest.json (SSR manifest)
1390
+ * - preload-manifest.json (from viteAlephaSsrPreload plugin)
1391
+ */
1392
+ declare class SSRManifestProvider {
1393
+ protected readonly alepha: Alepha;
1394
+ /**
1395
+ * Get the manifest from the store at runtime.
1396
+ * This ensures the manifest is available even when set after module load.
1397
+ */
1398
+ protected get manifest(): Static<SsrManifestAtomSchema>;
1399
+ /**
1400
+ * Get the preload manifest.
1401
+ */
1402
+ protected get preloadManifest(): PreloadManifest | undefined;
1403
+ /**
1404
+ * Get the SSR manifest.
1405
+ */
1406
+ protected get ssrManifest(): SSRManifest | undefined;
1407
+ /**
1408
+ * Get the client manifest.
1409
+ */
1410
+ protected get clientManifest(): ClientManifest | undefined;
1411
+ /**
1412
+ * Resolve a preload key to its source path.
1413
+ *
1414
+ * The key is a short hash injected by viteAlephaSsrPreload plugin,
1415
+ * which maps to the full source path in the preload manifest.
1416
+ *
1417
+ * @param key - Short hash key (e.g., "a1b2c3d4")
1418
+ * @returns Source path (e.g., "src/pages/UserDetail.tsx") or undefined
1419
+ */
1420
+ resolvePreloadKey(key: string): string | undefined;
1421
+ /**
1422
+ * Get all chunks required for a source file, including transitive dependencies.
1423
+ *
1424
+ * Uses the client manifest to recursively resolve all imported chunks,
1425
+ * not just the direct chunks from the SSR manifest.
1426
+ *
1427
+ * @param sourcePath - Source file path (e.g., "src/pages/Home.tsx")
1428
+ * @returns Array of chunk URLs to preload, or empty array if not found
1429
+ */
1430
+ getChunks(sourcePath: string): string[];
1431
+ /**
1432
+ * Find manifest entry for a source path, trying different extensions.
1433
+ */
1434
+ protected findManifestEntry(sourcePath: string): {
1435
+ file: string;
1436
+ src?: string;
1437
+ isEntry?: boolean;
1438
+ isDynamicEntry?: boolean;
1439
+ imports?: string[];
1440
+ dynamicImports?: string[];
1441
+ css?: string[];
1442
+ assets?: string[];
1443
+ } | undefined;
1444
+ /**
1445
+ * Recursively collect all chunk URLs for a manifest entry.
1446
+ */
1447
+ protected collectChunksRecursive(key: string, chunks: Set<string>, visited: Set<string>): void;
1448
+ /**
1449
+ * Fallback to SSR manifest for chunk lookup.
1450
+ */
1451
+ protected getChunksFromSSRManifest(sourcePath: string): string[];
1452
+ /**
1453
+ * Collect modulepreload links for a route and its parent chain.
1454
+ */
1455
+ collectPreloadLinks(route: PageRoute): Array<{
1456
+ rel: string;
1457
+ href: string;
1458
+ as?: string;
1459
+ crossorigin?: string;
1460
+ }>;
1461
+ /**
1462
+ * Get all chunks for multiple source files.
1463
+ *
1464
+ * @param sourcePaths - Array of source file paths
1465
+ * @returns Deduplicated array of chunk URLs
1466
+ */
1467
+ getChunksForMultiple(sourcePaths: string[]): string[];
1468
+ /**
1469
+ * Check if manifests are loaded and available.
1470
+ */
1471
+ isAvailable(): boolean;
1472
+ /**
1473
+ * Cached entry assets - computed once at first access.
1474
+ */
1475
+ protected cachedEntryAssets: EntryAssets | null;
1476
+ /**
1477
+ * Get the entry point assets (main entry.js and associated CSS files).
1478
+ *
1479
+ * These assets are always required for all pages and can be preloaded
1480
+ * before page-specific loaders run.
1481
+ *
1482
+ * @returns Entry assets with js and css paths, or null if manifest unavailable
1483
+ */
1484
+ getEntryAssets(): EntryAssets | null;
1485
+ /**
1486
+ * Build preload link tags for entry assets.
1487
+ *
1488
+ * @returns Array of link objects ready to be rendered
1489
+ */
1490
+ getEntryPreloadLinks(): Array<{
1491
+ rel: string;
1492
+ href: string;
1493
+ as?: string;
1494
+ crossorigin?: string;
1188
1495
  }>;
1189
- }>, "alepha.react.server.options">;
1190
- type ReactServerProviderOptions = Static<typeof reactServerOptions.schema>;
1191
- declare module "alepha" {
1192
- interface State {
1193
- [reactServerOptions.key]: ReactServerProviderOptions;
1194
- }
1195
1496
  }
1497
+ /**
1498
+ * Entry assets structure containing the main entry JS and associated CSS files.
1499
+ */
1500
+ interface EntryAssets {
1501
+ /** Main entry JavaScript file (e.g., "/assets/entry.abc123.js") */
1502
+ js?: string;
1503
+ /** Associated CSS files (e.g., ["/assets/style.abc123.css"]) */
1504
+ css: string[];
1505
+ }
1506
+ /**
1507
+ * SSR Manifest structure from Vite.
1508
+ * Maps source file paths to their required chunks/assets.
1509
+ */
1510
+ type SSRManifest = Record<string, string[]>;
1511
+ /**
1512
+ * Client manifest structure from Vite.
1513
+ * Maps source files to their output information.
1514
+ */
1515
+ interface ClientManifest {
1516
+ [key: string]: {
1517
+ file: string;
1518
+ src?: string;
1519
+ isEntry?: boolean;
1520
+ isDynamicEntry?: boolean;
1521
+ imports?: string[];
1522
+ dynamicImports?: string[];
1523
+ css?: string[];
1524
+ assets?: string[];
1525
+ };
1526
+ }
1527
+ /**
1528
+ * Preload manifest mapping short keys to source paths.
1529
+ * Generated by viteAlephaSsrPreload plugin at build time.
1530
+ */
1531
+ type PreloadManifest = Record<string, string>;
1532
+ //#endregion
1533
+ //#region ../../src/router/providers/ReactServerProvider.d.ts
1196
1534
  /**
1197
1535
  * React server provider responsible for SSR and static file serving.
1198
1536
  *
1199
- * Use `react-dom/server` under the hood.
1537
+ * Coordinates between:
1538
+ * - ReactPageProvider: Page routing and layer resolution
1539
+ * - ReactServerTemplateProvider: HTML template parsing and streaming
1540
+ * - ServerHeadProvider: Head content management
1541
+ * - SSRManifestProvider: Module preload link collection
1542
+ *
1543
+ * Uses `react-dom/server` under the hood.
1200
1544
  */
1201
1545
  declare class ReactServerProvider {
1546
+ /**
1547
+ * SSR response headers - pre-allocated to avoid object creation per request.
1548
+ */
1549
+ protected readonly SSR_HEADERS: {
1550
+ readonly "content-type": "text/html";
1551
+ readonly "cache-control": "no-store, no-cache, must-revalidate, proxy-revalidate";
1552
+ readonly pragma: "no-cache";
1553
+ readonly expires: "0";
1554
+ };
1555
+ protected readonly fs: FileSystemProvider;
1202
1556
  protected readonly log: alepha_logger0.Logger;
1203
1557
  protected readonly alepha: Alepha;
1204
1558
  protected readonly env: {
1205
1559
  REACT_SSR_ENABLED?: boolean | undefined;
1206
- REACT_ROOT_ID: string;
1207
1560
  };
1208
1561
  protected readonly pageApi: ReactPageProvider;
1562
+ protected readonly templateProvider: ReactServerTemplateProvider;
1563
+ protected readonly serverHeadProvider: ServerHeadProvider;
1209
1564
  protected readonly serverStaticProvider: ServerStaticProvider;
1210
1565
  protected readonly serverRouterProvider: ServerRouterProvider;
1211
1566
  protected readonly serverTimingProvider: ServerTimingProvider;
1212
- readonly ROOT_DIV_REGEX: RegExp;
1213
- protected preprocessedTemplate: PreprocessedTemplate | null;
1567
+ protected readonly ssrManifestProvider: SSRManifestProvider;
1568
+ /**
1569
+ * Cached check for ServerLinksProvider - avoids has() lookup per request.
1570
+ */
1571
+ protected hasServerLinksProvider: boolean;
1214
1572
  protected readonly options: Readonly<{
1215
1573
  publicDir: string;
1216
1574
  staticServer: {
@@ -1221,38 +1579,101 @@ declare class ReactServerProvider {
1221
1579
  /**
1222
1580
  * Configure the React server provider.
1223
1581
  */
1224
- readonly onConfigure: alepha12.HookPrimitive<"configure">;
1582
+ readonly onConfigure: alepha1.HookPrimitive<"configure">;
1583
+ /**
1584
+ * Get the current HTML template.
1585
+ */
1225
1586
  get template(): string;
1587
+ /**
1588
+ * Register all pages as server routes.
1589
+ */
1226
1590
  protected registerPages(templateLoader: TemplateLoader): Promise<void>;
1591
+ /**
1592
+ * Set up early head content with entry assets.
1593
+ *
1594
+ * This content is sent immediately when streaming starts, before page loaders run,
1595
+ * allowing the browser to start downloading entry.js and CSS files early.
1596
+ *
1597
+ * Uses <script type="module"> instead of <link rel="modulepreload"> for JS
1598
+ * because the script needs to execute anyway - this way the browser starts
1599
+ * downloading, parsing, AND will execute as soon as ready.
1600
+ *
1601
+ * Also strips these assets from the original template head to avoid duplicates.
1602
+ */
1603
+ protected setupEarlyHeadContent(): void;
1227
1604
  /**
1228
1605
  * Get the public directory path where static files are located.
1229
1606
  */
1230
- protected getPublicDirectory(): string;
1607
+ protected getPublicDirectory(): Promise<string>;
1231
1608
  /**
1232
1609
  * Configure the static file server to serve files from the given root directory.
1233
1610
  */
1234
1611
  protected configureStaticServer(root: string): Promise<void>;
1235
1612
  /**
1236
- * Configure Vite for SSR.
1613
+ * Configure Vite for SSR in development mode.
1237
1614
  */
1238
1615
  protected configureVite(ssrEnabled: boolean): Promise<void>;
1239
1616
  /**
1240
- * For testing purposes, creates a render function that can be used.
1617
+ * Create the request handler for a page route.
1241
1618
  */
1242
- render(name: string, options?: PagePrimitiveRenderOptions): Promise<PagePrimitiveRenderResult>;
1243
1619
  protected createHandler(route: PageRoute, templateLoader: TemplateLoader): ServerHandler;
1244
- renderToHtml(template: string, state: ReactRouterState, hydration?: boolean): string | Redirection;
1245
- protected preprocessTemplate(template: string): PreprocessedTemplate;
1246
- protected fillTemplate(response: {
1247
- html: string;
1248
- }, app: string, script: string): void;
1620
+ /**
1621
+ * Core page rendering logic shared between SSR handler and static prerendering.
1622
+ *
1623
+ * Handles:
1624
+ * - Layer resolution (loaders)
1625
+ * - Redirect detection
1626
+ * - Head content filling
1627
+ * - Preload link collection
1628
+ * - React stream rendering
1629
+ *
1630
+ * @param route - The page route to render
1631
+ * @param state - The router state
1632
+ * @returns Render result with redirect or React stream
1633
+ */
1634
+ protected renderPage(route: PageRoute, state: ReactRouterState): Promise<{
1635
+ redirect?: string;
1636
+ reactStream?: ReadableStream<Uint8Array>;
1637
+ }>;
1638
+ /**
1639
+ * For testing purposes, renders a page to HTML string.
1640
+ * Uses the same streaming code path as production, then collects to string.
1641
+ *
1642
+ * @param name - Page name to render
1643
+ * @param options - Render options (params, query, html, hydration)
1644
+ */
1645
+ render(name: string, options?: PagePrimitiveRenderOptions): Promise<PagePrimitiveRenderResult>;
1646
+ /**
1647
+ * Collect a ReadableStream into a string.
1648
+ */
1649
+ protected streamToString(stream: ReadableStream<Uint8Array>): Promise<string>;
1249
1650
  }
1250
1651
  type TemplateLoader = () => Promise<string | undefined>;
1251
- interface PreprocessedTemplate {
1252
- beforeApp: string;
1253
- afterApp: string;
1254
- beforeScript: string;
1255
- afterScript: string;
1652
+ declare const envSchema: alepha1.TObject<{
1653
+ REACT_SSR_ENABLED: alepha1.TOptional<alepha1.TBoolean>;
1654
+ }>;
1655
+ declare module "alepha" {
1656
+ interface Env extends Partial<Static<typeof envSchema>> {}
1657
+ interface State {
1658
+ "alepha.react.server.ssr"?: boolean;
1659
+ "alepha.react.server.template"?: string;
1660
+ }
1661
+ }
1662
+ /**
1663
+ * React server provider configuration atom
1664
+ */
1665
+ declare const reactServerOptions: alepha1.Atom<alepha1.TObject<{
1666
+ publicDir: alepha1.TString;
1667
+ staticServer: alepha1.TObject<{
1668
+ disabled: alepha1.TBoolean;
1669
+ path: alepha1.TString;
1670
+ }>;
1671
+ }>, "alepha.react.server.options">;
1672
+ type ReactServerProviderOptions = Static<typeof reactServerOptions.schema>;
1673
+ declare module "alepha" {
1674
+ interface State {
1675
+ [reactServerOptions.key]: ReactServerProviderOptions;
1676
+ }
1256
1677
  }
1257
1678
  //#endregion
1258
1679
  //#region ../../src/router/index.d.ts
@@ -1278,6 +1699,9 @@ declare module "alepha" {
1278
1699
  };
1279
1700
  /**
1280
1701
  * Fires when the React application is being rendered on the browser.
1702
+ *
1703
+ * Note: this one is not really necessary, it's a hack because we need to isolate renderer from server code in order
1704
+ * to avoid including react-dom/client in server bundles.
1281
1705
  */
1282
1706
  "react:browser:render": {
1283
1707
  root: HTMLElement;
@@ -1321,14 +1745,14 @@ declare module "alepha" {
1321
1745
  * - URL pattern matching with parameters (e.g., `/users/:id`)
1322
1746
  * - Nested routing with parent-child relationships
1323
1747
  * - Type-safe URL parameter and query string validation
1324
- * - Server-side data fetching with the `resolve` function
1748
+ * - Server-side data fetching with the `loader` function
1325
1749
  * - Lazy loading and code splitting
1326
1750
  * - Page animations and error handling
1327
1751
  *
1328
1752
  * @see {@link $page}
1329
1753
  * @module alepha.react.router
1330
1754
  */
1331
- declare const AlephaReactRouter: alepha12.Service<alepha12.Module>;
1755
+ declare const AlephaReactRouter: alepha1.Service<alepha1.Module>;
1332
1756
  //#endregion
1333
- export { $page, AlephaReactRouter, AnchorProps, ConcretePageRoute, CreateLayersResult, ErrorHandler, ErrorViewer, Layer, Link, type LinkProps, _default as NestedView, NestedViewProps, NotFound, PageAnimation, PageConfigSchema, PagePrimitive, PagePrimitiveOptions, PagePrimitiveRenderOptions, PagePrimitiveRenderResult, PageRequestConfig, PageResolve, PageRoute, PageRouteEntry, PreviousLayerData, ReactBrowserProvider, ReactBrowserRendererOptions, ReactHydrationState, ReactPageProvider, ReactPageService, ReactRouter, ReactRouterState, ReactServerProvider, ReactServerProviderOptions, Redirection, type RouterGoOptions, RouterLayerContext, RouterLayerContextValue, RouterRenderOptions, RouterStackItem, TPropsDefault, TPropsParentDefault, TransitionOptions, UseActiveHook, UseActiveOptions, UseQueryParamsHookOptions, VirtualRouter, isPageRoute, reactBrowserOptions, reactServerOptions, useActive, useQueryParams, useRouter, useRouterState };
1757
+ export { $page, AlephaReactRouter, AnchorProps, ClientManifest, ConcretePageRoute, CreateLayersResult, EntryAssets, ErrorHandler, ErrorViewer, HydrationData, Layer, Link, type LinkProps, _default as NestedView, NestedViewProps, NotFound, PAGE_PRELOAD_KEY, PageAnimation, PageConfigSchema, PageLoader, PagePrimitive, PagePrimitiveOptions, PagePrimitiveRenderOptions, PagePrimitiveRenderResult, PageRequestConfig, PageRoute, PageRouteEntry, PreloadManifest, PreviousLayerData, ReactBrowserProvider, ReactBrowserRendererOptions, ReactHydrationState, ReactPageProvider, ReactPageService, ReactRouter, ReactRouterState, ReactServerProvider, ReactServerProviderOptions, ReactServerTemplateProvider, Redirection, type RouterGoOptions, RouterLayerContext, RouterLayerContextValue, RouterRenderOptions, RouterStackItem, SSRManifest, SSRManifestProvider, TPropsDefault, TPropsParentDefault, TemplateSlots, TransitionOptions, UseActiveHook, UseActiveOptions, UseQueryParamsHookOptions, VirtualRouter, isPageRoute, reactBrowserOptions, reactServerOptions, useActive, useQueryParams, useRouter, useRouterState };
1334
1758
  //# sourceMappingURL=index.d.ts.map