@alepha/react 0.8.1 → 0.9.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.
package/dist/index.cjs CHANGED
@@ -27,28 +27,32 @@ const __alepha_server_cache = __toESM(require("@alepha/server-cache"));
27
27
  const __alepha_server_links = __toESM(require("@alepha/server-links"));
28
28
  const react = __toESM(require("react"));
29
29
  const react_jsx_runtime = __toESM(require("react/jsx-runtime"));
30
+ const __alepha_router = __toESM(require("@alepha/router"));
30
31
  const node_fs = __toESM(require("node:fs"));
31
32
  const node_path = __toESM(require("node:path"));
32
33
  const __alepha_server_static = __toESM(require("@alepha/server-static"));
33
34
  const react_dom_server = __toESM(require("react-dom/server"));
34
- const __alepha_router = __toESM(require("@alepha/router"));
35
35
 
36
36
  //#region src/descriptors/$page.ts
37
- const KEY = "PAGE";
38
37
  /**
39
38
  * Main descriptor for defining a React route in the application.
40
39
  */
41
40
  const $page = (options) => {
42
- (0, __alepha_core.__descriptor)(KEY);
43
- return {
44
- [__alepha_core.KIND]: KEY,
45
- [__alepha_core.OPTIONS]: options,
46
- render: () => {
47
- throw new __alepha_core.NotImplementedError(KEY);
48
- }
49
- };
41
+ return (0, __alepha_core.createDescriptor)(PageDescriptor, options);
42
+ };
43
+ var PageDescriptor = class extends __alepha_core.Descriptor {
44
+ get name() {
45
+ return this.options.name ?? this.config.propertyKey;
46
+ }
47
+ /**
48
+ * For testing or build purposes, this will render the page (with or without the HTML layout) and return the HTML and context.
49
+ * Only valid for server-side rendering, it will throw an error if called on the client-side.
50
+ */
51
+ async render(options) {
52
+ throw new __alepha_core.NotImplementedError("");
53
+ }
50
54
  };
51
- $page[__alepha_core.KIND] = KEY;
55
+ $page[__alepha_core.KIND] = PageDescriptor;
52
56
 
53
57
  //#endregion
54
58
  //#region src/components/ClientOnly.tsx
@@ -364,7 +368,7 @@ var RedirectionError = class extends Error {
364
368
  const envSchema$1 = __alepha_core.t.object({ REACT_STRICT_MODE: __alepha_core.t.boolean({ default: true }) });
365
369
  var PageDescriptorProvider = class {
366
370
  log = (0, __alepha_core.$logger)();
367
- env = (0, __alepha_core.$inject)(envSchema$1);
371
+ env = (0, __alepha_core.$env)(envSchema$1);
368
372
  alepha = (0, __alepha_core.$inject)(__alepha_core.Alepha);
369
373
  pages = [];
370
374
  getPages() {
@@ -570,18 +574,17 @@ var PageDescriptorProvider = class {
570
574
  on: "configure",
571
575
  handler: () => {
572
576
  let hasNotFoundHandler = false;
573
- const pages = this.alepha.getDescriptorValues($page);
577
+ const pages = this.alepha.descriptors($page);
574
578
  const hasParent = (it) => {
575
579
  for (const page of pages) {
576
- const children = page.value[__alepha_core.OPTIONS].children ? Array.isArray(page.value[__alepha_core.OPTIONS].children) ? page.value[__alepha_core.OPTIONS].children : page.value[__alepha_core.OPTIONS].children() : [];
580
+ const children = page.options.children ? Array.isArray(page.options.children) ? page.options.children : page.options.children() : [];
577
581
  if (children.includes(it)) return true;
578
582
  }
579
583
  };
580
- for (const { value, key } of pages) value[__alepha_core.OPTIONS].name ??= key;
581
- for (const { value } of pages) {
582
- if (value[__alepha_core.OPTIONS].path === "/*") hasNotFoundHandler = true;
583
- if (hasParent(value)) continue;
584
- this.add(this.map(pages, value));
584
+ for (const page of pages) {
585
+ if (page.options.path === "/*") hasNotFoundHandler = true;
586
+ if (hasParent(page)) continue;
587
+ this.add(this.map(pages, page));
585
588
  }
586
589
  if (!hasNotFoundHandler && pages.length > 0) this.add({
587
590
  path: "/*",
@@ -595,9 +598,10 @@ var PageDescriptorProvider = class {
595
598
  }
596
599
  });
597
600
  map(pages, target) {
598
- const children = target[__alepha_core.OPTIONS].children ? Array.isArray(target[__alepha_core.OPTIONS].children) ? target[__alepha_core.OPTIONS].children : target[__alepha_core.OPTIONS].children() : [];
601
+ const children = target.options.children ? Array.isArray(target.options.children) ? target.options.children : target.options.children() : [];
599
602
  return {
600
- ...target[__alepha_core.OPTIONS],
603
+ ...target.options,
604
+ name: target.name,
601
605
  parent: void 0,
602
606
  children: children.map((it) => this.map(pages, it))
603
607
  };
@@ -634,6 +638,209 @@ const isPageRoute = (it) => {
634
638
  return it && typeof it === "object" && typeof it.path === "string" && typeof it.page === "object";
635
639
  };
636
640
 
641
+ //#endregion
642
+ //#region src/providers/BrowserRouterProvider.ts
643
+ var BrowserRouterProvider = class extends __alepha_router.RouterProvider {
644
+ log = (0, __alepha_core.$logger)();
645
+ alepha = (0, __alepha_core.$inject)(__alepha_core.Alepha);
646
+ pageDescriptorProvider = (0, __alepha_core.$inject)(PageDescriptorProvider);
647
+ add(entry) {
648
+ this.pageDescriptorProvider.add(entry);
649
+ }
650
+ configure = (0, __alepha_core.$hook)({
651
+ on: "configure",
652
+ handler: async () => {
653
+ for (const page of this.pageDescriptorProvider.getPages()) if (page.component || page.lazy) this.push({
654
+ path: page.match,
655
+ page
656
+ });
657
+ }
658
+ });
659
+ async transition(url, options = {}) {
660
+ const { pathname, search } = url;
661
+ const state = {
662
+ pathname,
663
+ search,
664
+ layers: []
665
+ };
666
+ const context = {
667
+ url,
668
+ query: {},
669
+ params: {},
670
+ onError: () => null,
671
+ ...options.context ?? {}
672
+ };
673
+ await this.alepha.emit("react:transition:begin", {
674
+ state,
675
+ context
676
+ });
677
+ try {
678
+ const previous = options.previous;
679
+ const { route, params } = this.match(pathname);
680
+ const query = {};
681
+ if (search) for (const [key, value] of new URLSearchParams(search).entries()) query[key] = String(value);
682
+ context.query = query;
683
+ context.params = params ?? {};
684
+ context.previous = previous;
685
+ if (isPageRoute(route)) {
686
+ const result = await this.pageDescriptorProvider.createLayers(route.page, context);
687
+ if (result.redirect) return {
688
+ redirect: result.redirect,
689
+ state,
690
+ context
691
+ };
692
+ state.layers = result.layers;
693
+ }
694
+ if (state.layers.length === 0) state.layers.push({
695
+ name: "not-found",
696
+ element: (0, react.createElement)(NotFoundPage),
697
+ index: 0,
698
+ path: "/"
699
+ });
700
+ await this.alepha.emit("react:transition:success", {
701
+ state,
702
+ context
703
+ });
704
+ } catch (e) {
705
+ this.log.error(e);
706
+ state.layers = [{
707
+ name: "error",
708
+ element: this.pageDescriptorProvider.renderError(e),
709
+ index: 0,
710
+ path: "/"
711
+ }];
712
+ await this.alepha.emit("react:transition:error", {
713
+ error: e,
714
+ state,
715
+ context
716
+ });
717
+ }
718
+ if (options.state) {
719
+ options.state.layers = state.layers;
720
+ options.state.pathname = state.pathname;
721
+ options.state.search = state.search;
722
+ }
723
+ await this.alepha.emit("react:transition:end", {
724
+ state: options.state,
725
+ context
726
+ });
727
+ return {
728
+ context,
729
+ state
730
+ };
731
+ }
732
+ root(state, context) {
733
+ return this.pageDescriptorProvider.root(state, context);
734
+ }
735
+ };
736
+
737
+ //#endregion
738
+ //#region src/providers/ReactBrowserProvider.ts
739
+ var ReactBrowserProvider = class {
740
+ log = (0, __alepha_core.$logger)();
741
+ client = (0, __alepha_core.$inject)(__alepha_server_links.LinkProvider);
742
+ alepha = (0, __alepha_core.$inject)(__alepha_core.Alepha);
743
+ router = (0, __alepha_core.$inject)(BrowserRouterProvider);
744
+ root;
745
+ transitioning;
746
+ state = {
747
+ layers: [],
748
+ pathname: "",
749
+ search: ""
750
+ };
751
+ get document() {
752
+ return window.document;
753
+ }
754
+ get history() {
755
+ return window.history;
756
+ }
757
+ get location() {
758
+ return window.location;
759
+ }
760
+ get url() {
761
+ let url = this.location.pathname + this.location.search;
762
+ return url;
763
+ }
764
+ pushState(url, replace) {
765
+ let path = url;
766
+ if (replace) this.history.replaceState({}, "", path);
767
+ else this.history.pushState({}, "", path);
768
+ }
769
+ async invalidate(props) {
770
+ const previous = [];
771
+ if (props) {
772
+ const [key] = Object.keys(props);
773
+ const value = props[key];
774
+ for (const layer of this.state.layers) {
775
+ if (layer.props?.[key]) {
776
+ previous.push({
777
+ ...layer,
778
+ props: {
779
+ ...layer.props,
780
+ [key]: value
781
+ }
782
+ });
783
+ break;
784
+ }
785
+ previous.push(layer);
786
+ }
787
+ }
788
+ await this.render({ previous });
789
+ }
790
+ async go(url, options = {}) {
791
+ const result = await this.render({ url });
792
+ if (result.context.url.pathname !== url) {
793
+ this.pushState(result.context.url.pathname);
794
+ return;
795
+ }
796
+ if (options.replace) {
797
+ this.pushState(url);
798
+ return;
799
+ }
800
+ this.pushState(url);
801
+ }
802
+ async render(options = {}) {
803
+ const previous = options.previous ?? this.state.layers;
804
+ const url = options.url ?? this.url;
805
+ this.transitioning = { to: url };
806
+ const result = await this.router.transition(new URL(`http://localhost${url}`), {
807
+ previous,
808
+ state: this.state
809
+ });
810
+ if (result.redirect) return await this.render({ url: result.redirect });
811
+ this.transitioning = void 0;
812
+ return result;
813
+ }
814
+ /**
815
+ * Get embedded layers from the server.
816
+ */
817
+ getHydrationState() {
818
+ try {
819
+ if ("__ssr" in window && typeof window.__ssr === "object") return window.__ssr;
820
+ } catch (error) {
821
+ console.error(error);
822
+ }
823
+ }
824
+ ready = (0, __alepha_core.$hook)({
825
+ on: "ready",
826
+ handler: async () => {
827
+ const hydration = this.getHydrationState();
828
+ const previous = hydration?.layers ?? [];
829
+ if (hydration?.links) for (const link of hydration.links.links) this.client.pushLink(link);
830
+ const { context } = await this.render({ previous });
831
+ await this.alepha.emit("react:browser:render", {
832
+ state: this.state,
833
+ context,
834
+ hydration
835
+ });
836
+ window.addEventListener("popstate", () => {
837
+ if (this.state.pathname === location.pathname) return;
838
+ this.render();
839
+ });
840
+ }
841
+ });
842
+ };
843
+
637
844
  //#endregion
638
845
  //#region src/providers/ReactServerProvider.ts
639
846
  const envSchema = __alepha_core.t.object({
@@ -649,18 +856,15 @@ var ReactServerProvider = class {
649
856
  serverStaticProvider = (0, __alepha_core.$inject)(__alepha_server_static.ServerStaticProvider);
650
857
  serverRouterProvider = (0, __alepha_core.$inject)(__alepha_server.ServerRouterProvider);
651
858
  serverTimingProvider = (0, __alepha_core.$inject)(__alepha_server.ServerTimingProvider);
652
- env = (0, __alepha_core.$inject)(envSchema);
859
+ env = (0, __alepha_core.$env)(envSchema);
653
860
  ROOT_DIV_REGEX = new RegExp(`<div([^>]*)\\s+id=["']${this.env.REACT_ROOT_ID}["']([^>]*)>(.*?)<\\/div>`, "is");
654
861
  onConfigure = (0, __alepha_core.$hook)({
655
862
  on: "configure",
656
863
  handler: async () => {
657
- const pages = this.alepha.getDescriptorValues($page);
864
+ const pages = this.alepha.descriptors($page);
658
865
  const ssrEnabled = pages.length > 0 && this.env.REACT_SSR_ENABLED !== false;
659
866
  this.alepha.state("react.server.ssr", ssrEnabled);
660
- for (const { key, instance, value } of pages) {
661
- const name = value[__alepha_core.OPTIONS].name ?? key;
662
- instance[key].render = this.createRenderFunction(name);
663
- }
867
+ for (const page of pages) page.render = this.createRenderFunction(page.name);
664
868
  if (this.alepha.isServerless() === "vite") {
665
869
  await this.configureVite(ssrEnabled);
666
870
  return;
@@ -680,7 +884,7 @@ var ReactServerProvider = class {
680
884
  return;
681
885
  }
682
886
  this.log.info("SSR is disabled, use History API fallback");
683
- await this.serverRouterProvider.route({
887
+ this.serverRouterProvider.createRoute({
684
888
  path: "*",
685
889
  handler: async ({ url, reply }) => {
686
890
  if (url.pathname.includes(".")) {
@@ -702,7 +906,7 @@ var ReactServerProvider = class {
702
906
  for (const page of this.pageDescriptorProvider.getPages()) {
703
907
  if (page.children?.length) continue;
704
908
  this.log.debug(`+ ${page.match} -> ${page.name}`);
705
- await this.serverRouterProvider.route({
909
+ this.serverRouterProvider.createRoute({
706
910
  ...page,
707
911
  schema: void 0,
708
912
  method: "GET",
@@ -717,7 +921,7 @@ var ReactServerProvider = class {
717
921
  return "";
718
922
  }
719
923
  async configureStaticServer(root) {
720
- await this.serverStaticProvider.serve({
924
+ await this.serverStaticProvider.createStaticServer({
721
925
  root,
722
926
  path: this.env.REACT_SERVER_PREFIX
723
927
  });
@@ -771,7 +975,7 @@ var ReactServerProvider = class {
771
975
  onError: () => null
772
976
  };
773
977
  if (this.alepha.has(__alepha_server_links.ServerLinksProvider)) {
774
- const srv = this.alepha.get(__alepha_server_links.ServerLinksProvider);
978
+ const srv = this.alepha.inject(__alepha_server_links.ServerLinksProvider);
775
979
  const schema = __alepha_server.apiLinksResponseSchema;
776
980
  context.links = this.alepha.parse(schema, await srv.getLinks({
777
981
  user: serverRequest.user,
@@ -861,209 +1065,6 @@ var ReactServerProvider = class {
861
1065
  }
862
1066
  };
863
1067
 
864
- //#endregion
865
- //#region src/providers/BrowserRouterProvider.ts
866
- var BrowserRouterProvider = class extends __alepha_router.RouterProvider {
867
- log = (0, __alepha_core.$logger)();
868
- alepha = (0, __alepha_core.$inject)(__alepha_core.Alepha);
869
- pageDescriptorProvider = (0, __alepha_core.$inject)(PageDescriptorProvider);
870
- add(entry) {
871
- this.pageDescriptorProvider.add(entry);
872
- }
873
- configure = (0, __alepha_core.$hook)({
874
- on: "configure",
875
- handler: async () => {
876
- for (const page of this.pageDescriptorProvider.getPages()) if (page.component || page.lazy) this.push({
877
- path: page.match,
878
- page
879
- });
880
- }
881
- });
882
- async transition(url, options = {}) {
883
- const { pathname, search } = url;
884
- const state = {
885
- pathname,
886
- search,
887
- layers: []
888
- };
889
- const context = {
890
- url,
891
- query: {},
892
- params: {},
893
- onError: () => null,
894
- ...options.context ?? {}
895
- };
896
- await this.alepha.emit("react:transition:begin", {
897
- state,
898
- context
899
- });
900
- try {
901
- const previous = options.previous;
902
- const { route, params } = this.match(pathname);
903
- const query = {};
904
- if (search) for (const [key, value] of new URLSearchParams(search).entries()) query[key] = String(value);
905
- context.query = query;
906
- context.params = params ?? {};
907
- context.previous = previous;
908
- if (isPageRoute(route)) {
909
- const result = await this.pageDescriptorProvider.createLayers(route.page, context);
910
- if (result.redirect) return {
911
- redirect: result.redirect,
912
- state,
913
- context
914
- };
915
- state.layers = result.layers;
916
- }
917
- if (state.layers.length === 0) state.layers.push({
918
- name: "not-found",
919
- element: (0, react.createElement)(NotFoundPage),
920
- index: 0,
921
- path: "/"
922
- });
923
- await this.alepha.emit("react:transition:success", {
924
- state,
925
- context
926
- });
927
- } catch (e) {
928
- this.log.error(e);
929
- state.layers = [{
930
- name: "error",
931
- element: this.pageDescriptorProvider.renderError(e),
932
- index: 0,
933
- path: "/"
934
- }];
935
- await this.alepha.emit("react:transition:error", {
936
- error: e,
937
- state,
938
- context
939
- });
940
- }
941
- if (options.state) {
942
- options.state.layers = state.layers;
943
- options.state.pathname = state.pathname;
944
- options.state.search = state.search;
945
- }
946
- await this.alepha.emit("react:transition:end", {
947
- state: options.state,
948
- context
949
- });
950
- return {
951
- context,
952
- state
953
- };
954
- }
955
- root(state, context) {
956
- return this.pageDescriptorProvider.root(state, context);
957
- }
958
- };
959
-
960
- //#endregion
961
- //#region src/providers/ReactBrowserProvider.ts
962
- var ReactBrowserProvider = class {
963
- log = (0, __alepha_core.$logger)();
964
- client = (0, __alepha_core.$inject)(__alepha_server_links.LinkProvider);
965
- alepha = (0, __alepha_core.$inject)(__alepha_core.Alepha);
966
- router = (0, __alepha_core.$inject)(BrowserRouterProvider);
967
- root;
968
- transitioning;
969
- state = {
970
- layers: [],
971
- pathname: "",
972
- search: ""
973
- };
974
- get document() {
975
- return window.document;
976
- }
977
- get history() {
978
- return window.history;
979
- }
980
- get location() {
981
- return window.location;
982
- }
983
- get url() {
984
- let url = this.location.pathname + this.location.search;
985
- return url;
986
- }
987
- pushState(url, replace) {
988
- let path = url;
989
- if (replace) this.history.replaceState({}, "", path);
990
- else this.history.pushState({}, "", path);
991
- }
992
- async invalidate(props) {
993
- const previous = [];
994
- if (props) {
995
- const [key] = Object.keys(props);
996
- const value = props[key];
997
- for (const layer of this.state.layers) {
998
- if (layer.props?.[key]) {
999
- previous.push({
1000
- ...layer,
1001
- props: {
1002
- ...layer.props,
1003
- [key]: value
1004
- }
1005
- });
1006
- break;
1007
- }
1008
- previous.push(layer);
1009
- }
1010
- }
1011
- await this.render({ previous });
1012
- }
1013
- async go(url, options = {}) {
1014
- const result = await this.render({ url });
1015
- if (result.context.url.pathname !== url) {
1016
- this.pushState(result.context.url.pathname);
1017
- return;
1018
- }
1019
- if (options.replace) {
1020
- this.pushState(url);
1021
- return;
1022
- }
1023
- this.pushState(url);
1024
- }
1025
- async render(options = {}) {
1026
- const previous = options.previous ?? this.state.layers;
1027
- const url = options.url ?? this.url;
1028
- this.transitioning = { to: url };
1029
- const result = await this.router.transition(new URL(`http://localhost${url}`), {
1030
- previous,
1031
- state: this.state
1032
- });
1033
- if (result.redirect) return await this.render({ url: result.redirect });
1034
- this.transitioning = void 0;
1035
- return result;
1036
- }
1037
- /**
1038
- * Get embedded layers from the server.
1039
- */
1040
- getHydrationState() {
1041
- try {
1042
- if ("__ssr" in window && typeof window.__ssr === "object") return window.__ssr;
1043
- } catch (error) {
1044
- console.error(error);
1045
- }
1046
- }
1047
- ready = (0, __alepha_core.$hook)({
1048
- on: "ready",
1049
- handler: async () => {
1050
- const hydration = this.getHydrationState();
1051
- const previous = hydration?.layers ?? [];
1052
- if (hydration?.links) for (const link of hydration.links.links) this.client.pushLink(link);
1053
- const { context } = await this.render({ previous });
1054
- await this.alepha.emit("react:browser:render", {
1055
- state: this.state,
1056
- context,
1057
- hydration
1058
- });
1059
- window.addEventListener("popstate", () => {
1060
- if (this.state.pathname === location.pathname) return;
1061
- this.render();
1062
- });
1063
- }
1064
- });
1065
- };
1066
-
1067
1068
  //#endregion
1068
1069
  //#region src/hooks/RouterHookApi.ts
1069
1070
  var RouterHookApi = class {
@@ -1157,9 +1158,9 @@ const useRouter = () => {
1157
1158
  const layer = (0, react.useContext)(RouterLayerContext);
1158
1159
  if (!ctx || !layer) throw new Error("useRouter must be used within a RouterProvider");
1159
1160
  const pages = (0, react.useMemo)(() => {
1160
- return ctx.alepha.get(PageDescriptorProvider).getPages();
1161
+ return ctx.alepha.inject(PageDescriptorProvider).getPages();
1161
1162
  }, []);
1162
- return (0, react.useMemo)(() => new RouterHookApi(pages, ctx.context, ctx.state, layer, ctx.alepha.isBrowser() ? ctx.alepha.get(ReactBrowserProvider) : void 0), [layer]);
1163
+ return (0, react.useMemo)(() => new RouterHookApi(pages, ctx.context, ctx.state, layer, ctx.alepha.isBrowser() ? ctx.alepha.inject(ReactBrowserProvider) : void 0), [layer]);
1163
1164
  };
1164
1165
 
1165
1166
  //#endregion
@@ -1167,11 +1168,11 @@ const useRouter = () => {
1167
1168
  const Link = (props) => {
1168
1169
  react.default.useContext(RouterContext);
1169
1170
  const router = useRouter();
1170
- const to = typeof props.to === "string" ? props.to : props.to[__alepha_core.OPTIONS].path;
1171
+ const to = typeof props.to === "string" ? props.to : props.to.options.path;
1171
1172
  if (!to) return null;
1172
- const can = typeof props.to === "string" ? void 0 : props.to[__alepha_core.OPTIONS].can;
1173
+ const can = typeof props.to === "string" ? void 0 : props.to.options.can;
1173
1174
  if (can && !can()) return null;
1174
- const name = typeof props.to === "string" ? void 0 : props.to[__alepha_core.OPTIONS].name;
1175
+ const name = typeof props.to === "string" ? void 0 : props.to.options.name;
1175
1176
  const anchorProps = {
1176
1177
  ...props,
1177
1178
  to: void 0
@@ -1223,7 +1224,7 @@ const useActive = (path) => {
1223
1224
  const useInject = (clazz) => {
1224
1225
  const ctx = (0, react.useContext)(RouterContext);
1225
1226
  if (!ctx) throw new Error("useRouter must be used within a <RouterProvider>");
1226
- return (0, react.useMemo)(() => ctx.alepha.get(clazz), []);
1227
+ return (0, react.useMemo)(() => ctx.alepha.inject(clazz), []);
1227
1228
  };
1228
1229
 
1229
1230
  //#endregion
@@ -1285,135 +1286,19 @@ const useRouterState = () => {
1285
1286
  * It delivers seamless server-side rendering, automatic code splitting, and client-side navigation with full
1286
1287
  * type safety and schema validation for route parameters and data.
1287
1288
  *
1288
- * **Key Features:**
1289
- * - Declarative page definition with `$page` descriptor
1290
- * - Server-side rendering (SSR) with automatic hydration
1291
- * - Type-safe routing with parameter validation
1292
- * - Schema-based data resolution and validation
1293
- * - SEO-friendly meta tag management
1294
- * - Automatic code splitting and lazy loading
1295
- * - Client-side navigation with browser history
1296
- *
1297
- * **Basic Usage:**
1298
- * ```ts
1299
- * import { Alepha, run, t } from "alepha";
1300
- * import { AlephaReact, $page } from "alepha/react";
1301
- *
1302
- * class AppRoutes {
1303
- * // Home page
1304
- * home = $page({
1305
- * path: "/",
1306
- * component: () => (
1307
- * <div>
1308
- * <h1>Welcome to Alepha</h1>
1309
- * <p>Build amazing React applications!</p>
1310
- * </div>
1311
- * ),
1312
- * });
1313
- *
1314
- * // About page with meta tags
1315
- * about = $page({
1316
- * path: "/about",
1317
- * head: {
1318
- * title: "About Us",
1319
- * description: "Learn more about our mission",
1320
- * },
1321
- * component: () => (
1322
- * <div>
1323
- * <h1>About Us</h1>
1324
- * <p>Learn more about our mission.</p>
1325
- * </div>
1326
- * ),
1327
- * });
1328
- * }
1329
- *
1330
- * const alepha = Alepha.create()
1331
- * .with(AlephaReact)
1332
- * .with(AppRoutes);
1333
- *
1334
- * run(alepha);
1335
- * ```
1336
- *
1337
- * **Dynamic Routes with Parameters:**
1338
- * ```tsx
1339
- * class UserRoutes {
1340
- * userProfile = $page({
1341
- * path: "/users/:id",
1342
- * schema: {
1343
- * params: t.object({
1344
- * id: t.string(),
1345
- * }),
1346
- * },
1347
- * resolve: async ({ params }) => {
1348
- * // Fetch user data server-side
1349
- * const user = await getUserById(params.id);
1350
- * return { user };
1351
- * },
1352
- * head: ({ user }) => ({
1353
- * title: `${user.name} - Profile`,
1354
- * description: `View ${user.name}'s profile`,
1355
- * }),
1356
- * component: ({ user }) => (
1357
- * <div>
1358
- * <h1>{user.name}</h1>
1359
- * <p>Email: {user.email}</p>
1360
- * </div>
1361
- * ),
1362
- * });
1363
- *
1364
- * userSettings = $page({
1365
- * path: "/users/:id/settings",
1366
- * schema: {
1367
- * params: t.object({
1368
- * id: t.string(),
1369
- * }),
1370
- * },
1371
- * component: ({ params }) => (
1372
- * <UserSettings userId={params.id} />
1373
- * ),
1374
- * });
1375
- * }
1376
- * ```
1377
- *
1378
- * **Static Generation:**
1379
- * ```tsx
1380
- * class BlogRoutes {
1381
- * blogPost = $page({
1382
- * path: "/blog/:slug",
1383
- * schema: {
1384
- * params: t.object({
1385
- * slug: t.string(),
1386
- * }),
1387
- * },
1388
- * static: {
1389
- * entries: [
1390
- * { params: { slug: "getting-started" } },
1391
- * { params: { slug: "advanced-features" } },
1392
- * { params: { slug: "deployment" } },
1393
- * ],
1394
- * },
1395
- * resolve: ({ params }) => {
1396
- * const post = getBlogPost(params.slug);
1397
- * return { post };
1398
- * },
1399
- * component: ({ post }) => (
1400
- * <article>
1401
- * <h1>{post.title}</h1>
1402
- * <div>{post.content}</div>
1403
- * </article>
1404
- * ),
1405
- * });
1406
- * }
1407
- * ```
1408
- *
1409
1289
  * @see {@link $page}
1410
1290
  * @module alepha.react
1411
1291
  */
1412
- var AlephaReact = class {
1413
- name = "alepha.react";
1414
- $services = (alepha) => alepha.with(__alepha_server.AlephaServer).with(__alepha_server_cache.AlephaServerCache).with(__alepha_server_links.AlephaServerLinks).with(ReactServerProvider).with(PageDescriptorProvider);
1415
- };
1416
- (0, __alepha_core.__bind)($page, AlephaReact);
1292
+ const AlephaReact = (0, __alepha_core.$module)({
1293
+ name: "alepha.react",
1294
+ descriptors: [$page],
1295
+ services: [
1296
+ ReactServerProvider,
1297
+ PageDescriptorProvider,
1298
+ ReactBrowserProvider
1299
+ ],
1300
+ register: (alepha) => alepha.with(__alepha_server.AlephaServer).with(__alepha_server_cache.AlephaServerCache).with(__alepha_server_links.AlephaServerLinks).with(ReactServerProvider).with(PageDescriptorProvider)
1301
+ });
1417
1302
 
1418
1303
  //#endregion
1419
1304
  exports.$page = $page;
@@ -1423,6 +1308,7 @@ exports.ErrorBoundary = ErrorBoundary_default;
1423
1308
  exports.Link = Link_default;
1424
1309
  exports.NestedView = NestedView_default;
1425
1310
  exports.NotFound = NotFoundPage;
1311
+ exports.PageDescriptor = PageDescriptor;
1426
1312
  exports.PageDescriptorProvider = PageDescriptorProvider;
1427
1313
  exports.ReactBrowserProvider = ReactBrowserProvider;
1428
1314
  exports.ReactServerProvider = ReactServerProvider;