@alepha/react 0.14.3 → 0.15.0

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/README.md +10 -0
  2. package/dist/auth/index.browser.js +29 -14
  3. package/dist/auth/index.browser.js.map +1 -1
  4. package/dist/auth/index.d.ts +4 -4
  5. package/dist/auth/index.d.ts.map +1 -1
  6. package/dist/auth/index.js +950 -194
  7. package/dist/auth/index.js.map +1 -1
  8. package/dist/core/index.d.ts +118 -118
  9. package/dist/core/index.d.ts.map +1 -1
  10. package/dist/form/index.d.ts +27 -28
  11. package/dist/form/index.d.ts.map +1 -1
  12. package/dist/head/index.browser.js +59 -19
  13. package/dist/head/index.browser.js.map +1 -1
  14. package/dist/head/index.d.ts +105 -576
  15. package/dist/head/index.d.ts.map +1 -1
  16. package/dist/head/index.js +91 -87
  17. package/dist/head/index.js.map +1 -1
  18. package/dist/i18n/index.d.ts +33 -33
  19. package/dist/i18n/index.d.ts.map +1 -1
  20. package/dist/router/index.browser.js +30 -15
  21. package/dist/router/index.browser.js.map +1 -1
  22. package/dist/router/index.d.ts +827 -403
  23. package/dist/router/index.d.ts.map +1 -1
  24. package/dist/router/index.js +951 -195
  25. package/dist/router/index.js.map +1 -1
  26. package/dist/websocket/index.d.ts +38 -39
  27. package/dist/websocket/index.d.ts.map +1 -1
  28. package/package.json +5 -5
  29. package/src/auth/__tests__/$auth.spec.ts +10 -11
  30. package/src/core/__tests__/Router.spec.tsx +4 -4
  31. package/src/head/{__tests__/expandSeo.spec.ts → helpers/SeoExpander.spec.ts} +1 -1
  32. package/src/head/index.ts +10 -28
  33. package/src/head/providers/BrowserHeadProvider.browser.spec.ts +1 -76
  34. package/src/head/providers/BrowserHeadProvider.ts +25 -19
  35. package/src/head/providers/HeadProvider.ts +76 -10
  36. package/src/head/providers/ServerHeadProvider.ts +22 -138
  37. package/src/router/__tests__/page-head-browser.browser.spec.ts +91 -0
  38. package/src/router/__tests__/page-head.spec.ts +44 -0
  39. package/src/{head → router}/__tests__/seo-head.spec.ts +2 -2
  40. package/src/router/atoms/ssrManifestAtom.ts +60 -0
  41. package/src/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
  42. package/src/router/errors/Redirection.ts +1 -1
  43. package/src/router/index.shared.ts +1 -0
  44. package/src/router/index.ts +16 -2
  45. package/src/router/primitives/$page.browser.spec.tsx +15 -15
  46. package/src/router/primitives/$page.spec.tsx +18 -18
  47. package/src/router/primitives/$page.ts +46 -10
  48. package/src/router/providers/ReactBrowserProvider.ts +14 -29
  49. package/src/router/providers/ReactBrowserRouterProvider.ts +5 -0
  50. package/src/router/providers/ReactPageProvider.ts +11 -4
  51. package/src/router/providers/ReactServerProvider.ts +321 -316
  52. package/src/router/providers/ReactServerTemplateProvider.ts +793 -0
  53. package/src/router/providers/SSRManifestProvider.ts +365 -0
  54. package/src/router/services/ReactPageServerService.ts +5 -3
  55. package/src/router/services/ReactRouter.ts +3 -3
  56. package/src/head/__tests__/page-head.spec.ts +0 -39
  57. package/src/head/providers/ServerHeadProvider.spec.ts +0 -163
@@ -2,6 +2,7 @@ import { $atom, $env, $hook, $inject, $module, $use, Alepha, AlephaError, KIND,
2
2
  import { AlephaDateTime, DateTimeProvider } from "alepha/datetime";
3
3
  import { $logger } from "alepha/logger";
4
4
  import { AlephaServerLinks, LinkProvider } from "alepha/server/links";
5
+ import { BrowserHeadProvider } from "@alepha/react/head";
5
6
  import { RouterProvider } from "alepha/router";
6
7
  import { StrictMode, createContext, createElement, memo, use, useEffect, useRef, useState } from "react";
7
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -22,6 +23,15 @@ var ReactPageService = class {
22
23
  }
23
24
  };
24
25
 
26
+ //#endregion
27
+ //#region ../../src/router/constants/PAGE_PRELOAD_KEY.ts
28
+ /**
29
+ * Symbol key for SSR module preloading path.
30
+ * Using Symbol.for() allows the Vite plugin to inject this at build time.
31
+ * @internal
32
+ */
33
+ const PAGE_PRELOAD_KEY = Symbol.for("alepha.page.preload");
34
+
25
35
  //#endregion
26
36
  //#region ../../src/router/primitives/$page.ts
27
37
  /**
@@ -36,7 +46,7 @@ var ReactPageService = class {
36
46
  * - Type-safe URL parameter and query string validation
37
47
  *
38
48
  * **Data Loading**
39
- * - Server-side data fetching with the `resolve` function
49
+ * - Server-side data fetching with the `loader` function
40
50
  * - Automatic serialization and hydration for SSR
41
51
  * - Access to request context, URL params, and parent data
42
52
  *
@@ -73,7 +83,7 @@ var ReactPageService = class {
73
83
  * params: t.object({ id: t.integer() }),
74
84
  * query: t.object({ tab: t.optional(t.text()) })
75
85
  * },
76
- * resolve: async ({ params }) => {
86
+ * loader: async ({ params }) => {
77
87
  * const user = await userApi.getUser(params.id);
78
88
  * return { user };
79
89
  * },
@@ -86,7 +96,7 @@ var ReactPageService = class {
86
96
  * const projectSection = $page({
87
97
  * path: "/projects/:id",
88
98
  * children: () => [projectBoard, projectSettings],
89
- * resolve: async ({ params }) => {
99
+ * loader: async ({ params }) => {
90
100
  * const project = await projectApi.get(params.id);
91
101
  * return { project };
92
102
  * },
@@ -105,7 +115,7 @@ var ReactPageService = class {
105
115
  * static: {
106
116
  * entries: posts.map(p => ({ params: { slug: p.slug } }))
107
117
  * },
108
- * resolve: async ({ params }) => {
118
+ * loader: async ({ params }) => {
109
119
  * const post = await loadPost(params.slug);
110
120
  * return { post };
111
121
  * }
@@ -586,7 +596,7 @@ const RouterLayerContext = createContext(void 0);
586
596
  * import { Redirection } from "@alepha/react";
587
597
  *
588
598
  * const MyPage = $page({
589
- * resolve: async () => {
599
+ * loader: async () => {
590
600
  * if (needRedirect) {
591
601
  * throw new Redirection("/new-path");
592
602
  * }
@@ -742,13 +752,13 @@ function parseAnimation(animationLike, state, type = "enter") {
742
752
 
743
753
  //#endregion
744
754
  //#region ../../src/router/providers/ReactPageProvider.ts
745
- const envSchema$1 = t.object({ REACT_STRICT_MODE: t.boolean({ default: true }) });
755
+ const envSchema = t.object({ REACT_STRICT_MODE: t.boolean({ default: true }) });
746
756
  /**
747
757
  * Handle page routes for React applications. (Browser and Server)
748
758
  */
749
759
  var ReactPageProvider = class {
750
760
  log = $logger();
751
- env = $env(envSchema$1);
761
+ env = $env(envSchema);
752
762
  alepha = $inject(Alepha);
753
763
  pages = [];
754
764
  getPages() {
@@ -868,11 +878,11 @@ var ReactPageProvider = class {
868
878
  }
869
879
  forceRefresh = true;
870
880
  }
871
- if (!route$1.resolve) continue;
881
+ if (!route$1.loader) continue;
872
882
  try {
873
883
  const args = Object.create(state);
874
884
  Object.assign(args, config, context);
875
- const props = await route$1.resolve?.(args) ?? {};
885
+ const props = await route$1.loader?.(args) ?? {};
876
886
  it.props = { ...props };
877
887
  context = {
878
888
  ...context,
@@ -880,7 +890,7 @@ var ReactPageProvider = class {
880
890
  };
881
891
  } catch (e) {
882
892
  if (e instanceof Redirection) return { redirect: e.redirect };
883
- this.log.error("Page resolver has failed", e);
893
+ this.log.error("Page loader has failed", e);
884
894
  it.error = e;
885
895
  break;
886
896
  }
@@ -1075,6 +1085,7 @@ var ReactBrowserRouterProvider = class extends RouterProvider {
1075
1085
  log = $logger();
1076
1086
  alepha = $inject(Alepha);
1077
1087
  pageApi = $inject(ReactPageProvider);
1088
+ browserHeadProvider = $inject(BrowserHeadProvider);
1078
1089
  add(entry) {
1079
1090
  this.pageApi.add(entry);
1080
1091
  }
@@ -1145,6 +1156,7 @@ var ReactBrowserRouterProvider = class extends RouterProvider {
1145
1156
  this.alepha.store.set("alepha.react.router.state", state);
1146
1157
  await this.alepha.events.emit("react:action:end", { type: "transition" });
1147
1158
  await this.alepha.events.emit("react:transition:end", { state });
1159
+ this.browserHeadProvider.fillAndRenderHead(state);
1148
1160
  }
1149
1161
  root(state) {
1150
1162
  return this.pageApi.root(state);
@@ -1153,7 +1165,6 @@ var ReactBrowserRouterProvider = class extends RouterProvider {
1153
1165
 
1154
1166
  //#endregion
1155
1167
  //#region ../../src/router/providers/ReactBrowserProvider.ts
1156
- const envSchema = t.object({ REACT_ROOT_ID: t.text({ default: "root" }) });
1157
1168
  /**
1158
1169
  * React browser renderer configuration atom
1159
1170
  */
@@ -1163,18 +1174,21 @@ const reactBrowserOptions = $atom({
1163
1174
  default: { scrollRestoration: "top" }
1164
1175
  });
1165
1176
  var ReactBrowserProvider = class {
1166
- env = $env(envSchema);
1167
1177
  log = $logger();
1168
1178
  client = $inject(LinkProvider);
1169
1179
  alepha = $inject(Alepha);
1170
1180
  router = $inject(ReactBrowserRouterProvider);
1171
1181
  dateTimeProvider = $inject(DateTimeProvider);
1182
+ browserHeadProvider = $inject(BrowserHeadProvider);
1172
1183
  options = $use(reactBrowserOptions);
1184
+ get rootId() {
1185
+ return "root";
1186
+ }
1173
1187
  getRootElement() {
1174
- const root = this.document.getElementById(this.env.REACT_ROOT_ID);
1188
+ const root = this.document.getElementById(this.rootId);
1175
1189
  if (root) return root;
1176
1190
  const div = this.document.createElement("div");
1177
- div.id = this.env.REACT_ROOT_ID;
1191
+ div.id = this.rootId;
1178
1192
  this.document.body.prepend(div);
1179
1193
  return div;
1180
1194
  }
@@ -1307,6 +1321,7 @@ var ReactBrowserProvider = class {
1307
1321
  hydration,
1308
1322
  state: this.state
1309
1323
  });
1324
+ this.browserHeadProvider.fillAndRenderHead(this.state);
1310
1325
  window.addEventListener("popstate", () => {
1311
1326
  if (this.base + this.state.url.pathname === this.location.pathname) return;
1312
1327
  this.log.debug("Popstate event triggered - rendering new state", { url: this.location.pathname + this.location.search });
@@ -1596,5 +1611,5 @@ const AlephaReactRouter = $module({
1596
1611
  });
1597
1612
 
1598
1613
  //#endregion
1599
- export { $page, AlephaReactRouter, ErrorViewer_default as ErrorViewer, Link_default as Link, NestedView_default as NestedView, NotFound_default as NotFound, PagePrimitive, ReactBrowserProvider, ReactBrowserRendererProvider, ReactBrowserRouterProvider, ReactPageProvider, ReactPageService, ReactRouter, Redirection, RouterLayerContext, isPageRoute, reactBrowserOptions, useActive, useQueryParams, useRouter, useRouterState };
1614
+ export { $page, AlephaReactRouter, ErrorViewer_default as ErrorViewer, Link_default as Link, NestedView_default as NestedView, NotFound_default as NotFound, PAGE_PRELOAD_KEY, PagePrimitive, ReactBrowserProvider, ReactBrowserRendererProvider, ReactBrowserRouterProvider, ReactPageProvider, ReactPageService, ReactRouter, Redirection, RouterLayerContext, isPageRoute, reactBrowserOptions, useActive, useQueryParams, useRouter, useRouterState };
1600
1615
  //# sourceMappingURL=index.browser.js.map