@alepha/react 0.14.4 → 0.15.1

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 (82) hide show
  1. package/README.md +10 -0
  2. package/dist/auth/index.browser.js +603 -242
  3. package/dist/auth/index.browser.js.map +1 -1
  4. package/dist/auth/index.d.ts +2 -2
  5. package/dist/auth/index.d.ts.map +1 -1
  6. package/dist/auth/index.js +1317 -952
  7. package/dist/auth/index.js.map +1 -1
  8. package/dist/core/index.d.ts +17 -17
  9. package/dist/core/index.d.ts.map +1 -1
  10. package/dist/core/index.js +20 -20
  11. package/dist/core/index.js.map +1 -1
  12. package/dist/form/index.d.ts +9 -10
  13. package/dist/form/index.d.ts.map +1 -1
  14. package/dist/form/index.js +15 -15
  15. package/dist/form/index.js.map +1 -1
  16. package/dist/head/index.browser.js +20 -0
  17. package/dist/head/index.browser.js.map +1 -1
  18. package/dist/head/index.d.ts +62 -64
  19. package/dist/head/index.d.ts.map +1 -1
  20. package/dist/head/index.js +20 -0
  21. package/dist/head/index.js.map +1 -1
  22. package/dist/i18n/index.d.ts +9 -9
  23. package/dist/i18n/index.d.ts.map +1 -1
  24. package/dist/i18n/index.js.map +1 -1
  25. package/dist/router/index.browser.js +605 -244
  26. package/dist/router/index.browser.js.map +1 -1
  27. package/dist/router/index.d.ts +100 -111
  28. package/dist/router/index.d.ts.map +1 -1
  29. package/dist/router/index.js +1317 -952
  30. package/dist/router/index.js.map +1 -1
  31. package/dist/websocket/index.d.ts +0 -1
  32. package/dist/websocket/index.d.ts.map +1 -1
  33. package/package.json +6 -6
  34. package/src/auth/__tests__/$auth.spec.ts +164 -150
  35. package/src/auth/index.ts +9 -3
  36. package/src/auth/services/ReactAuth.ts +15 -5
  37. package/src/core/hooks/useAction.ts +1 -2
  38. package/src/core/index.ts +4 -4
  39. package/src/form/errors/FormValidationError.ts +4 -6
  40. package/src/form/hooks/useFormState.ts +1 -1
  41. package/src/form/index.ts +1 -1
  42. package/src/form/services/FormModel.ts +31 -25
  43. package/src/head/helpers/SeoExpander.ts +2 -1
  44. package/src/head/hooks/useHead.spec.tsx +2 -2
  45. package/src/head/index.browser.ts +2 -2
  46. package/src/head/index.ts +4 -4
  47. package/src/head/interfaces/Head.ts +15 -3
  48. package/src/head/primitives/$head.ts +2 -5
  49. package/src/head/providers/BrowserHeadProvider.ts +55 -0
  50. package/src/head/providers/HeadProvider.ts +4 -1
  51. package/src/i18n/__tests__/integration.spec.tsx +1 -1
  52. package/src/i18n/components/Localize.spec.tsx +2 -2
  53. package/src/i18n/hooks/useI18n.browser.spec.tsx +2 -2
  54. package/src/i18n/index.ts +1 -1
  55. package/src/i18n/primitives/$dictionary.ts +1 -1
  56. package/src/i18n/providers/I18nProvider.spec.ts +1 -1
  57. package/src/i18n/providers/I18nProvider.ts +1 -1
  58. package/src/router/__tests__/page-head-browser.browser.spec.ts +5 -1
  59. package/src/router/__tests__/page-head.spec.ts +11 -7
  60. package/src/router/__tests__/seo-head.spec.ts +7 -3
  61. package/src/router/atoms/ssrManifestAtom.ts +2 -11
  62. package/src/router/components/ErrorViewer.tsx +626 -167
  63. package/src/router/components/Link.tsx +4 -2
  64. package/src/router/components/NestedView.tsx +7 -9
  65. package/src/router/components/NotFound.tsx +2 -2
  66. package/src/router/hooks/useQueryParams.ts +1 -1
  67. package/src/router/hooks/useRouter.ts +1 -1
  68. package/src/router/hooks/useRouterState.ts +1 -1
  69. package/src/router/index.browser.ts +10 -11
  70. package/src/router/index.shared.ts +7 -7
  71. package/src/router/index.ts +10 -7
  72. package/src/router/primitives/$page.browser.spec.tsx +6 -1
  73. package/src/router/primitives/$page.spec.tsx +7 -1
  74. package/src/router/primitives/$page.ts +5 -9
  75. package/src/router/providers/ReactBrowserProvider.ts +17 -6
  76. package/src/router/providers/ReactBrowserRouterProvider.ts +1 -1
  77. package/src/router/providers/ReactPageProvider.ts +4 -3
  78. package/src/router/providers/ReactServerProvider.ts +32 -50
  79. package/src/router/providers/ReactServerTemplateProvider.ts +336 -155
  80. package/src/router/providers/SSRManifestProvider.ts +17 -60
  81. package/src/router/services/ReactPageService.ts +4 -1
  82. package/src/router/services/ReactRouter.ts +6 -5
@@ -14,8 +14,10 @@ const Link = (props: LinkProps) => {
14
14
  const router = useRouter();
15
15
 
16
16
  return createElement(
17
- "a", { ...props, ...router.anchor(props.href) }, props.children
18
- )
17
+ "a",
18
+ { ...props, ...router.anchor(props.href) },
19
+ props.children,
20
+ );
19
21
  };
20
22
 
21
23
  export default Link;
@@ -1,11 +1,11 @@
1
+ import { ErrorBoundary, useAlepha, useEvents } from "@alepha/react";
1
2
  import { memo, type ReactNode, use, useRef, useState } from "react";
2
- import type { ReactRouterState } from "../providers/ReactPageProvider.ts";
3
3
  import { RouterLayerContext } from "../contexts/RouterLayerContext.ts";
4
4
  import { Redirection } from "../errors/Redirection.ts";
5
5
  import { useRouterState } from "../hooks/useRouterState.ts";
6
6
  import type { PageAnimation } from "../primitives/$page.ts";
7
+ import type { ReactRouterState } from "../providers/ReactPageProvider.ts";
7
8
  import ErrorViewer from "./ErrorViewer.tsx";
8
- import { ErrorBoundary, useAlepha, useEvents } from "@alepha/react";
9
9
 
10
10
  export interface NestedViewProps {
11
11
  children?: ReactNode;
@@ -152,18 +152,16 @@ const NestedView = (props: NestedViewProps) => {
152
152
  }
153
153
 
154
154
  const fallback = (error: Error) => {
155
- const result = onError?.(error, state) ?? <ErrorViewer error={error} alepha={alepha}/>;
155
+ const result = onError?.(error, state) ?? (
156
+ <ErrorViewer error={error} alepha={alepha} />
157
+ );
156
158
  if (result instanceof Redirection) {
157
159
  return "Redirection inside ErrorBoundary is not allowed.";
158
160
  }
159
161
  return result as ReactNode;
160
- }
162
+ };
161
163
 
162
- return (
163
- <ErrorBoundary fallback={fallback}>
164
- {element}
165
- </ErrorBoundary>
166
- );
164
+ return <ErrorBoundary fallback={fallback}>{element}</ErrorBoundary>;
167
165
  };
168
166
 
169
167
  export default memo(NestedView);
@@ -3,7 +3,7 @@ import type { CSSProperties } from "react";
3
3
  /**
4
4
  * Default 404 Not Found page component.
5
5
  */
6
- const NotFound = (props: { style?: CSSProperties }) => (
6
+ const NotFound = (props: { style?: CSSProperties }) => (
7
7
  <div
8
8
  style={{
9
9
  width: "100%",
@@ -25,6 +25,6 @@ import type { CSSProperties } from "react";
25
25
  Page not found
26
26
  </div>
27
27
  </div>
28
- )
28
+ );
29
29
 
30
30
  export default NotFound;
@@ -1,6 +1,6 @@
1
+ import { useAlepha } from "@alepha/react";
1
2
  import type { Alepha, Static, TObject } from "alepha";
2
3
  import { useEffect, useState } from "react";
3
- import { useAlepha } from "@alepha/react";
4
4
  import { useRouter } from "./useRouter.ts";
5
5
 
6
6
  /**
@@ -1,5 +1,5 @@
1
- import { ReactRouter } from "../services/ReactRouter.ts";
2
1
  import { useInject } from "@alepha/react";
2
+ import { ReactRouter } from "../services/ReactRouter.ts";
3
3
 
4
4
  /**
5
5
  * Use this hook to access the React Router instance.
@@ -1,6 +1,6 @@
1
+ import { useStore } from "@alepha/react";
1
2
  import { AlephaError } from "alepha";
2
3
  import type { ReactRouterState } from "../providers/ReactPageProvider.ts";
3
- import { useStore } from "@alepha/react";
4
4
 
5
5
  export const useRouterState = (): ReactRouterState => {
6
6
  const [state] = useStore("alepha.react.router.state");
@@ -1,22 +1,22 @@
1
+ import { AlephaReact } from "@alepha/react";
1
2
  import { $module } from "alepha";
3
+ import { AlephaDateTime } from "alepha/datetime";
4
+ import { AlephaServer } from "alepha/server";
5
+ import { AlephaServerLinks } from "alepha/server/links";
2
6
  import { $page } from "./primitives/$page.ts";
3
- import { ReactRouter } from "./services/ReactRouter.ts";
7
+ import { ReactBrowserProvider } from "./providers/ReactBrowserProvider.ts";
4
8
  import { ReactBrowserRendererProvider } from "./providers/ReactBrowserRendererProvider.ts";
5
9
  import { ReactBrowserRouterProvider } from "./providers/ReactBrowserRouterProvider.ts";
6
- import { ReactPageService } from "./services/ReactPageService.ts";
7
10
  import { ReactPageProvider } from "./providers/ReactPageProvider.ts";
8
- import { ReactBrowserProvider } from "./providers/ReactBrowserProvider.ts";
9
- import { AlephaDateTime } from "alepha/datetime";
10
- import { AlephaServer } from "alepha/server";
11
- import { AlephaServerLinks } from "alepha/server/links";
12
- import { AlephaReact } from "@alepha/react";
11
+ import { ReactPageService } from "./services/ReactPageService.ts";
12
+ import { ReactRouter } from "./services/ReactRouter.ts";
13
13
 
14
14
  // ---------------------------------------------------------------------------------------------------------------------
15
15
 
16
16
  export * from "./index.shared.ts";
17
- export * from "./providers/ReactBrowserProvider.ts"
18
- export * from "./providers/ReactBrowserRouterProvider.ts"
19
- export * from "./providers/ReactBrowserRendererProvider.ts"
17
+ export * from "./providers/ReactBrowserProvider.ts";
18
+ export * from "./providers/ReactBrowserRendererProvider.ts";
19
+ export * from "./providers/ReactBrowserRouterProvider.ts";
20
20
 
21
21
  // ---------------------------------------------------------------------------------------------------------------------
22
22
 
@@ -43,4 +43,3 @@ export const AlephaReactRouter = $module({
43
43
  .with(ReactBrowserRendererProvider)
44
44
  .with(ReactRouter),
45
45
  });
46
-
@@ -1,19 +1,19 @@
1
- export { default as ErrorViewer } from "./components/ErrorViewer.tsx";
2
1
  export type * from "./components/ErrorViewer.tsx";
2
+ export { default as ErrorViewer } from "./components/ErrorViewer.tsx";
3
+ export type * from "./components/Link.tsx";
3
4
  export { default as Link, type LinkProps } from "./components/Link.tsx";
4
- export type * from "./components/Link.tsx";
5
+ export type * from "./components/NestedView.tsx";
5
6
  export { default as NestedView } from "./components/NestedView.tsx";
6
- export type * from "./components/NestedView.tsx";
7
- export { default as NotFound } from "./components/NotFound.tsx";
8
7
  export type * from "./components/NotFound.tsx";
8
+ export { default as NotFound } from "./components/NotFound.tsx";
9
9
  export * from "./constants/PAGE_PRELOAD_KEY.ts";
10
10
  export * from "./contexts/RouterLayerContext.ts";
11
- export * from "./primitives/$page.ts";
12
11
  export * from "./errors/Redirection.ts";
13
12
  export * from "./hooks/useActive.ts";
14
13
  export * from "./hooks/useQueryParams.ts";
15
14
  export * from "./hooks/useRouter.ts";
16
15
  export * from "./hooks/useRouterState.ts";
17
- export * from "./services/ReactRouter.ts";
18
- export * from "./services/ReactPageService.ts"
16
+ export * from "./primitives/$page.ts";
19
17
  export * from "./providers/ReactPageProvider.ts";
18
+ export * from "./services/ReactPageService.ts";
19
+ export * from "./services/ReactRouter.ts";
@@ -1,25 +1,28 @@
1
1
  import { AlephaReact } from "@alepha/react";
2
2
  import { $module } from "alepha";
3
- import { $page, type PageAnimation } from "./primitives/$page.ts";
4
- import { ReactRouter } from "./services/ReactRouter.ts";
5
- import { ReactPageProvider, type ReactRouterState } from "./providers/ReactPageProvider.ts";
3
+ import { AlephaDateTime } from "alepha/datetime";
6
4
  import { AlephaServer, type ServerRequest } from "alepha/server";
5
+ import { AlephaServerCache } from "alepha/server/cache";
6
+ import { AlephaServerLinks } from "alepha/server/links";
7
7
  import type { ReactNode } from "react";
8
+ import { $page, type PageAnimation } from "./primitives/$page.ts";
8
9
  import type { ReactHydrationState } from "./providers/ReactBrowserProvider.ts";
10
+ import {
11
+ ReactPageProvider,
12
+ type ReactRouterState,
13
+ } from "./providers/ReactPageProvider.ts";
9
14
  import { ReactServerProvider } from "./providers/ReactServerProvider.ts";
10
15
  import { ReactServerTemplateProvider } from "./providers/ReactServerTemplateProvider.ts";
11
16
  import { SSRManifestProvider } from "./providers/SSRManifestProvider.ts";
12
17
  import { ReactPageServerService } from "./services/ReactPageServerService.ts";
13
- import { AlephaServerCache } from "alepha/server/cache";
14
- import { AlephaServerLinks } from "alepha/server/links";
15
18
  import { ReactPageService } from "./services/ReactPageService.ts";
16
- import { AlephaDateTime } from "alepha/datetime";
19
+ import { ReactRouter } from "./services/ReactRouter.ts";
17
20
 
18
21
  // ---------------------------------------------------------------------------------------------------------------------
19
22
 
20
23
  export * from "./index.shared.ts";
21
- export * from "./providers/ReactPageProvider.ts";
22
24
  export * from "./providers/ReactBrowserProvider.ts";
25
+ export * from "./providers/ReactPageProvider.ts";
23
26
  export * from "./providers/ReactServerProvider.ts";
24
27
  export * from "./providers/ReactServerTemplateProvider.ts";
25
28
  export * from "./providers/SSRManifestProvider.ts";
@@ -1,9 +1,14 @@
1
1
  import { AlephaReact } from "@alepha/react";
2
- import { $page, NestedView, Redirection, ReactRouter } from "../index.browser.ts";
3
2
  import { waitFor } from "@testing-library/dom";
4
3
  import { Alepha, t } from "alepha";
5
4
  import { act } from "react";
6
5
  import { beforeEach, describe, expect, it, vi } from "vitest";
6
+ import {
7
+ $page,
8
+ NestedView,
9
+ ReactRouter,
10
+ Redirection,
11
+ } from "../index.browser.ts";
7
12
 
8
13
  describe("$page browser tests", () => {
9
14
  let alepha: Alepha;
@@ -1,7 +1,13 @@
1
- import { $page, PagePrimitive, Redirection, NestedView, type ReactRouterState } from "../index.ts";
2
1
  import { Alepha, t } from "alepha";
3
2
  import type { FC } from "react";
4
3
  import { beforeEach, describe, test, vi } from "vitest";
4
+ import {
5
+ $page,
6
+ NestedView,
7
+ PagePrimitive,
8
+ type ReactRouterState,
9
+ Redirection,
10
+ } from "../index.ts";
5
11
 
6
12
  describe("$page primitive tests", () => {
7
13
  let alepha: Alepha;
@@ -1,22 +1,21 @@
1
+ import type { ClientOnlyProps } from "@alepha/react";
2
+ import type { Head } from "@alepha/react/head";
1
3
  import {
2
4
  $inject,
3
5
  type Async,
4
6
  createPrimitive,
5
- Primitive,
6
7
  KIND,
8
+ Primitive,
7
9
  type Static,
8
10
  type TSchema,
9
11
  } from "alepha";
10
12
  import type { ServerRequest } from "alepha/server";
11
13
  import type { ServerRouteCache } from "alepha/server/cache";
12
14
  import type { FC, ReactNode } from "react";
15
+ import { PAGE_PRELOAD_KEY } from "../constants/PAGE_PRELOAD_KEY.ts";
13
16
  import type { Redirection } from "../errors/Redirection.ts";
14
17
  import type { ReactRouterState } from "../providers/ReactPageProvider.ts";
15
18
  import { ReactPageService } from "../services/ReactPageService.ts";
16
- import type { ClientOnlyProps } from "@alepha/react";
17
- import type { Head } from "@alepha/react/head";
18
- import { PAGE_PRELOAD_KEY } from "../constants/PAGE_PRELOAD_KEY.ts";
19
-
20
19
 
21
20
  /**
22
21
  * Main primitive for defining a React route in the application.
@@ -113,10 +112,7 @@ export const $page = <
113
112
  >(
114
113
  options: PagePrimitiveOptions<TConfig, TProps, TPropsParent>,
115
114
  ): PagePrimitive<TConfig, TProps, TPropsParent> => {
116
- return createPrimitive(
117
- PagePrimitive<TConfig, TProps, TPropsParent>,
118
- options,
119
- );
115
+ return createPrimitive(PagePrimitive<TConfig, TProps, TPropsParent>, options);
120
116
  };
121
117
 
122
118
  // ---------------------------------------------------------------------------------------------------------------------
@@ -1,15 +1,26 @@
1
- import { $atom, $env, $hook, $inject, $use, Alepha, type State, type Static, t, } from "alepha";
1
+ import { BrowserHeadProvider } from "@alepha/react/head";
2
+ import {
3
+ $atom,
4
+ $hook,
5
+ $inject,
6
+ $use,
7
+ Alepha,
8
+ type State,
9
+ type Static,
10
+ t,
11
+ } from "alepha";
2
12
  import { DateTimeProvider } from "alepha/datetime";
3
13
  import { $logger } from "alepha/logger";
4
14
  import { LinkProvider } from "alepha/server/links";
5
- import { BrowserHeadProvider } from "@alepha/react/head";
6
- import { ReactBrowserRouterProvider } from "./ReactBrowserRouterProvider.ts";
7
- import type { PreviousLayerData, ReactRouterState, } from "./ReactPageProvider.ts";
8
15
  import type { RouterGoOptions } from "../services/ReactRouter.ts";
16
+ import { ReactBrowserRouterProvider } from "./ReactBrowserRouterProvider.ts";
17
+ import type {
18
+ PreviousLayerData,
19
+ ReactRouterState,
20
+ } from "./ReactPageProvider.ts";
9
21
 
10
22
  export type { RouterGoOptions } from "../services/ReactRouter.ts";
11
23
 
12
-
13
24
  /**
14
25
  * React browser renderer configuration atom
15
26
  */
@@ -247,7 +258,7 @@ export class ReactBrowserProvider {
247
258
  // low budget, but works for now
248
259
  for (const [key, value] of Object.entries(hydration)) {
249
260
  if (key !== "layers") {
250
- this.alepha.store.set(key as keyof State, value);
261
+ this.alepha.set(key as keyof State, value);
251
262
  }
252
263
  }
253
264
  }
@@ -1,8 +1,8 @@
1
+ import { BrowserHeadProvider } from "@alepha/react/head";
1
2
  import { $hook, $inject, Alepha } from "alepha";
2
3
  import { $logger } from "alepha/logger";
3
4
  import { type Route, RouterProvider } from "alepha/router";
4
5
  import { createElement, type ReactNode } from "react";
5
- import { BrowserHeadProvider } from "@alepha/react/head";
6
6
  import NotFoundPage from "../components/NotFound.tsx";
7
7
  import {
8
8
  isPageRoute,
@@ -1,3 +1,5 @@
1
+ import { AlephaContext, ClientOnly } from "@alepha/react";
2
+ import type { Head } from "@alepha/react/head";
1
3
  import {
2
4
  $env,
3
5
  $hook,
@@ -10,7 +12,6 @@ import {
10
12
  } from "alepha";
11
13
  import { $logger } from "alepha/logger";
12
14
  import { createElement, type ReactNode, StrictMode } from "react";
13
- import { AlephaContext, ClientOnly } from "@alepha/react";
14
15
  import ErrorViewer from "../components/ErrorViewer.tsx";
15
16
  import NestedView from "../components/NestedView.tsx";
16
17
  import NotFoundPage from "../components/NotFound.tsx";
@@ -22,7 +23,6 @@ import {
22
23
  type PagePrimitive,
23
24
  type PagePrimitiveOptions,
24
25
  } from "../primitives/$page.ts";
25
- import type { Head } from "@alepha/react/head";
26
26
 
27
27
  const envSchema = t.object({
28
28
  REACT_STRICT_MODE: t.boolean({ default: true }),
@@ -476,7 +476,8 @@ export class ReactPageProvider {
476
476
  value: {
477
477
  index,
478
478
  path,
479
- onError: this.getErrorHandler(page) ?? ((error) => this.renderError(error)),
479
+ onError:
480
+ this.getErrorHandler(page) ?? ((error) => this.renderError(error)),
480
481
  },
481
482
  },
482
483
  element,
@@ -1,15 +1,33 @@
1
1
  import { join } from "node:path";
2
- import { $atom, $env, $hook, $inject, $use, Alepha, AlephaError, type Static, t, } from "alepha";
2
+ import { ServerHeadProvider } from "@alepha/react/head";
3
+ import {
4
+ $atom,
5
+ $env,
6
+ $hook,
7
+ $inject,
8
+ $use,
9
+ Alepha,
10
+ AlephaError,
11
+ type Static,
12
+ t,
13
+ } from "alepha";
3
14
  import { FileSystemProvider } from "alepha/file";
4
15
  import { $logger } from "alepha/logger";
5
- import { type ServerHandler, ServerRouterProvider, ServerTimingProvider, } from "alepha/server";
16
+ import { type ServerHandler, ServerRouterProvider } from "alepha/server";
6
17
  import { ServerLinksProvider } from "alepha/server/links";
7
18
  import { ServerStaticProvider } from "alepha/server/static";
8
19
  import { renderToReadableStream } from "react-dom/server";
9
- import { ServerHeadProvider } from "@alepha/react/head";
10
20
  import { Redirection } from "../errors/Redirection.ts";
11
- import { $page, type PagePrimitiveRenderOptions, type PagePrimitiveRenderResult, } from "../primitives/$page.ts";
12
- import { type PageRoute, ReactPageProvider, type ReactRouterState, } from "./ReactPageProvider.ts";
21
+ import {
22
+ $page,
23
+ type PagePrimitiveRenderOptions,
24
+ type PagePrimitiveRenderResult,
25
+ } from "../primitives/$page.ts";
26
+ import {
27
+ type PageRoute,
28
+ ReactPageProvider,
29
+ type ReactRouterState,
30
+ } from "./ReactPageProvider.ts";
13
31
  import { ReactServerTemplateProvider } from "./ReactServerTemplateProvider.ts";
14
32
  import { SSRManifestProvider } from "./SSRManifestProvider.ts";
15
33
 
@@ -44,7 +62,6 @@ export class ReactServerProvider {
44
62
  protected readonly serverHeadProvider = $inject(ServerHeadProvider);
45
63
  protected readonly serverStaticProvider = $inject(ServerStaticProvider);
46
64
  protected readonly serverRouterProvider = $inject(ServerRouterProvider);
47
- protected readonly serverTimingProvider = $inject(ServerTimingProvider);
48
65
  protected readonly ssrManifestProvider = $inject(SSRManifestProvider);
49
66
 
50
67
  /**
@@ -67,21 +84,11 @@ export class ReactServerProvider {
67
84
 
68
85
  this.alepha.store.set("alepha.react.server.ssr", ssrEnabled);
69
86
 
70
- if (ssrEnabled) {
71
- this.log.info("SSR streaming enabled");
72
- }
73
-
74
- // development mode
75
- if (this.alepha.isViteDev()) {
76
- await this.configureVite(ssrEnabled);
77
- return;
78
- }
79
-
80
87
  // production mode
81
88
  let root = "";
82
89
 
83
90
  // non-serverless mode only -> serve static files
84
- if (!this.alepha.isServerless()) {
91
+ if (!this.alepha.isServerless() && !this.alepha.isViteDev()) {
85
92
  root = await this.getPublicDirectory();
86
93
  if (!root) {
87
94
  this.log.warn(
@@ -198,7 +205,7 @@ export class ReactServerProvider {
198
205
  if (parts.length > 0) {
199
206
  // Pass assets so they get stripped from original head content
200
207
  this.templateProvider.setEarlyHeadContent(
201
- parts.join("\n") + "\n",
208
+ `${parts.join("\n")}\n`,
202
209
  assets,
203
210
  );
204
211
  this.log.debug("Early head content set", {
@@ -240,26 +247,6 @@ export class ReactServerProvider {
240
247
  });
241
248
  }
242
249
 
243
- /**
244
- * Configure Vite for SSR in development mode.
245
- */
246
- protected async configureVite(ssrEnabled: boolean) {
247
- if (!ssrEnabled) {
248
- // do nothing, vite will handle everything for us
249
- return;
250
- }
251
-
252
- const url = `http://localhost:${this.alepha.env.SERVER_PORT ?? "5173"}`;
253
-
254
- this.log.info("SSR (dev) OK", { url });
255
-
256
- await this.registerPages(() =>
257
- fetch(`${url}/index.html`)
258
- .then((it) => it.text())
259
- .catch(() => undefined),
260
- );
261
- }
262
-
263
250
  /**
264
251
  * Create the request handler for a page route.
265
252
  */
@@ -338,9 +325,9 @@ export class ReactServerProvider {
338
325
  const result = await this.renderPage(route, state);
339
326
 
340
327
  if (result.redirect) {
341
- // Note: redirect happens after early head is sent, handled by stream
342
- reply.redirect(result.redirect);
343
- return null;
328
+ // Return redirect URL - template provider will inject meta refresh
329
+ // since HTTP headers have already been sent
330
+ return { redirect: result.redirect };
344
331
  }
345
332
 
346
333
  return { state, reactStream: result.reactStream! };
@@ -354,7 +341,8 @@ export class ReactServerProvider {
354
341
  });
355
342
  // Can't do redirect after streaming started - already handled above
356
343
  } else {
357
- this.log.error("HTML stream error", error);
344
+ // disable logging here, it's noisy and duplicate
345
+ // this.log.error("HTML stream error", error);
358
346
  }
359
347
  },
360
348
  },
@@ -389,10 +377,7 @@ export class ReactServerProvider {
389
377
  state: ReactRouterState,
390
378
  ): Promise<{ redirect?: string; reactStream?: ReadableStream<Uint8Array> }> {
391
379
  // Resolve page layers (loaders)
392
- this.serverTimingProvider.beginTiming("createLayers");
393
380
  const { redirect } = await this.pageApi.createLayers(route, state);
394
- this.serverTimingProvider.endTiming("createLayers");
395
-
396
381
  if (redirect) {
397
382
  this.log.debug("Resolver resulted in redirection", { redirect });
398
383
  return { redirect };
@@ -409,7 +394,6 @@ export class ReactServerProvider {
409
394
  }
410
395
 
411
396
  // Render React to stream
412
- this.serverTimingProvider.beginTiming("renderToStream");
413
397
 
414
398
  const element = this.pageApi.root(state);
415
399
  this.alepha.store.set("alepha.react.router.state", state);
@@ -421,13 +405,12 @@ export class ReactServerProvider {
421
405
  redirect: error.redirect,
422
406
  });
423
407
  } else {
424
- this.log.error("Streaming render error", error);
408
+ // disable logging here, it's noisy and duplicate
409
+ // this.log.error("Streaming render error", error);
425
410
  }
426
411
  },
427
412
  });
428
413
 
429
- this.serverTimingProvider.endTiming("renderToStream");
430
-
431
414
  return { reactStream };
432
415
  }
433
416
 
@@ -526,7 +509,6 @@ export class ReactServerProvider {
526
509
 
527
510
  type TemplateLoader = () => Promise<string | undefined>;
528
511
 
529
-
530
512
  // ---------------------------------------------------------------------------------------------------------------------
531
513
 
532
514
  const envSchema = t.object({