@alepha/react 0.7.6 → 0.7.7

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
@@ -28,6 +28,7 @@ const react = __toESM(require("react"));
28
28
  const react_jsx_runtime = __toESM(require("react/jsx-runtime"));
29
29
  const node_fs = __toESM(require("node:fs"));
30
30
  const node_path = __toESM(require("node:path"));
31
+ const __alepha_server_links = __toESM(require("@alepha/server-links"));
31
32
  const __alepha_server_static = __toESM(require("@alepha/server-static"));
32
33
  const react_dom_server = __toESM(require("react-dom/server"));
33
34
  const __alepha_router = __toESM(require("@alepha/router"));
@@ -480,10 +481,6 @@ var PageDescriptorProvider = class {
480
481
  const props = it.props ?? {};
481
482
  const params = { ...it.config?.params };
482
483
  for (const key of Object.keys(params)) params[key] = String(params[key]);
483
- if (it.route.head && !it.error) this.fillHead(it.route, request, {
484
- ...props,
485
- ...context
486
- });
487
484
  acc += "/";
488
485
  acc += it.route.path ? this.compile(it.route.path, params) : "";
489
486
  const path = acc.replace(/\/+/, "/");
@@ -500,7 +497,8 @@ var PageDescriptorProvider = class {
500
497
  config: it.config,
501
498
  element: this.renderView(i + 1, path, element$1, it.route),
502
499
  index: i + 1,
503
- path
500
+ path,
501
+ route
504
502
  });
505
503
  break;
506
504
  }
@@ -515,7 +513,8 @@ var PageDescriptorProvider = class {
515
513
  config: it.config,
516
514
  element: this.renderView(i + 1, path, element, it.route),
517
515
  index: i + 1,
518
- path
516
+ path,
517
+ route
519
518
  });
520
519
  }
521
520
  return {
@@ -540,26 +539,6 @@ var PageDescriptorProvider = class {
540
539
  if (page.component) return (0, react.createElement)(page.component, props);
541
540
  return void 0;
542
541
  }
543
- fillHead(page, ctx, props) {
544
- if (!page.head) return;
545
- ctx.head ??= {};
546
- const head = typeof page.head === "function" ? page.head(props, ctx.head) : page.head;
547
- if (head.title) {
548
- ctx.head ??= {};
549
- if (ctx.head.titleSeparator) ctx.head.title = `${head.title}${ctx.head.titleSeparator}${ctx.head.title}`;
550
- else ctx.head.title = head.title;
551
- ctx.head.titleSeparator = head.titleSeparator;
552
- }
553
- if (head.htmlAttributes) ctx.head.htmlAttributes = {
554
- ...ctx.head.htmlAttributes,
555
- ...head.htmlAttributes
556
- };
557
- if (head.bodyAttributes) ctx.head.bodyAttributes = {
558
- ...ctx.head.bodyAttributes,
559
- ...head.bodyAttributes
560
- };
561
- if (head.meta) ctx.head.meta = [...ctx.head.meta ?? [], ...head.meta ?? []];
562
- }
563
542
  renderError(error) {
564
543
  return (0, react.createElement)(ErrorViewer_default, { error });
565
544
  }
@@ -652,46 +631,6 @@ const isPageRoute = (it) => {
652
631
  return it && typeof it === "object" && typeof it.path === "string" && typeof it.page === "object";
653
632
  };
654
633
 
655
- //#endregion
656
- //#region src/providers/ServerHeadProvider.ts
657
- var ServerHeadProvider = class {
658
- renderHead(template, head) {
659
- let result = template;
660
- const htmlAttributes = head.htmlAttributes;
661
- if (htmlAttributes) result = result.replace(/<html([^>]*)>/i, (_, existingAttrs) => `<html${this.mergeAttributes(existingAttrs, htmlAttributes)}>`);
662
- const bodyAttributes = head.bodyAttributes;
663
- if (bodyAttributes) result = result.replace(/<body([^>]*)>/i, (_, existingAttrs) => `<body${this.mergeAttributes(existingAttrs, bodyAttributes)}>`);
664
- let headContent = "";
665
- const title = head.title;
666
- if (title) if (template.includes("<title>")) result = result.replace(/<title>(.*?)<\/title>/i, () => `<title>${this.escapeHtml(title)}</title>`);
667
- else headContent += `<title>${this.escapeHtml(title)}</title>\n`;
668
- if (head.meta) for (const meta of head.meta) headContent += `<meta name="${this.escapeHtml(meta.name)}" content="${this.escapeHtml(meta.content)}">\n`;
669
- result = result.replace(/<head([^>]*)>(.*?)<\/head>/is, (_, existingAttrs, existingHead) => `<head${existingAttrs}>${existingHead}${headContent}</head>`);
670
- return result.trim();
671
- }
672
- mergeAttributes(existing, attrs) {
673
- const existingAttrs = this.parseAttributes(existing);
674
- const merged = {
675
- ...existingAttrs,
676
- ...attrs
677
- };
678
- return Object.entries(merged).map(([k, v]) => ` ${k}="${this.escapeHtml(v)}"`).join("");
679
- }
680
- parseAttributes(attrStr) {
681
- const attrs = {};
682
- const attrRegex = /([^\s=]+)(?:="([^"]*)")?/g;
683
- let match = attrRegex.exec(attrStr);
684
- while (match) {
685
- attrs[match[1]] = match[2] ?? "";
686
- match = attrRegex.exec(attrStr);
687
- }
688
- return attrs;
689
- }
690
- escapeHtml(str) {
691
- return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
692
- }
693
- };
694
-
695
634
  //#endregion
696
635
  //#region src/providers/ReactServerProvider.ts
697
636
  const envSchema = __alepha_core.t.object({
@@ -706,7 +645,6 @@ var ReactServerProvider = class {
706
645
  pageDescriptorProvider = (0, __alepha_core.$inject)(PageDescriptorProvider);
707
646
  serverStaticProvider = (0, __alepha_core.$inject)(__alepha_server_static.ServerStaticProvider);
708
647
  serverRouterProvider = (0, __alepha_core.$inject)(__alepha_server.ServerRouterProvider);
709
- headProvider = (0, __alepha_core.$inject)(ServerHeadProvider);
710
648
  serverTimingProvider = (0, __alepha_core.$inject)(__alepha_server.ServerTimingProvider);
711
649
  env = (0, __alepha_core.$inject)(envSchema);
712
650
  ROOT_DIV_REGEX = new RegExp(`<div([^>]*)\\s+id=["']${this.env.REACT_ROOT_ID}["']([^>]*)>(.*?)<\\/div>`, "is");
@@ -718,8 +656,7 @@ var ReactServerProvider = class {
718
656
  this.alepha.state("ReactServerProvider.ssr", ssrEnabled);
719
657
  for (const { key, instance, value } of pages) {
720
658
  const name = value[__alepha_core.OPTIONS].name ?? key;
721
- instance[key].prerender = this.createRenderFunction(name, true);
722
- if (this.alepha.isTest()) instance[key].render = this.createRenderFunction(name);
659
+ instance[key].render = this.createRenderFunction(name);
723
660
  }
724
661
  if (this.alepha.isServerless() === "vite") {
725
662
  await this.configureVite(ssrEnabled);
@@ -756,7 +693,7 @@ var ReactServerProvider = class {
756
693
  }
757
694
  });
758
695
  get template() {
759
- return this.alepha.state("ReactServerProvider.template");
696
+ return this.alepha.state("ReactServerProvider.template") ?? "<!DOCTYPE html><html lang='en'><head></head><body></body></html>";
760
697
  }
761
698
  async registerPages(templateLoader) {
762
699
  for (const page of this.pageDescriptorProvider.getPages()) {
@@ -802,15 +739,20 @@ var ReactServerProvider = class {
802
739
  head: {},
803
740
  onError: () => null
804
741
  };
742
+ await this.alepha.emit("react:server:render:begin", { context });
805
743
  const state = await this.pageDescriptorProvider.createLayers(page, context);
806
- if (!withIndex) return {
744
+ if (!withIndex && !options.html) return {
807
745
  context,
808
746
  html: (0, react_dom_server.renderToString)(this.pageDescriptorProvider.root(state, context))
809
747
  };
810
- return {
748
+ const html = this.renderToHtml(this.template ?? "", state, context, options.hydration);
749
+ const result = {
811
750
  context,
812
- html: this.renderToHtml(this.template ?? "", state, context)
751
+ state,
752
+ html
813
753
  };
754
+ await this.alepha.emit("react:server:render:end", result);
755
+ return result;
814
756
  };
815
757
  }
816
758
  createHandler(page, templateLoader) {
@@ -825,8 +767,8 @@ var ReactServerProvider = class {
825
767
  head: {},
826
768
  onError: () => null
827
769
  };
828
- if (this.alepha.has(__alepha_server.ServerLinksProvider)) {
829
- const srv = this.alepha.get(__alepha_server.ServerLinksProvider);
770
+ if (this.alepha.has(__alepha_server_links.ServerLinksProvider)) {
771
+ const srv = this.alepha.get(__alepha_server_links.ServerLinksProvider);
830
772
  const schema = __alepha_server.apiLinksResponseSchema;
831
773
  context.links = this.alepha.parse(schema, await srv.getLinks({
832
774
  user: serverRequest.user,
@@ -843,10 +785,10 @@ var ReactServerProvider = class {
843
785
  }
844
786
  target = target.parent;
845
787
  }
846
- await this.alepha.emit("react:server:render", {
788
+ await this.alepha.emit("react:server:render:begin", {
847
789
  request: serverRequest,
848
- pageRequest: context
849
- }, { log: false });
790
+ context
791
+ });
850
792
  this.serverTimingProvider.beginTiming("createLayers");
851
793
  const state = await this.pageDescriptorProvider.createLayers(page, context);
852
794
  this.serverTimingProvider.endTiming("createLayers");
@@ -857,11 +799,17 @@ var ReactServerProvider = class {
857
799
  reply.headers.expires = "0";
858
800
  if (page.cache && serverRequest.user) delete context.links;
859
801
  const html = this.renderToHtml(template, state, context);
802
+ await this.alepha.emit("react:server:render:end", {
803
+ request: serverRequest,
804
+ context,
805
+ state,
806
+ html
807
+ });
860
808
  page.afterHandler?.(serverRequest);
861
809
  return html;
862
810
  };
863
811
  }
864
- renderToHtml(template, state, context) {
812
+ renderToHtml(template, state, context, hydration = true) {
865
813
  const element = this.pageDescriptorProvider.root(state, context);
866
814
  this.serverTimingProvider.beginTiming("renderToString");
867
815
  let app = "";
@@ -872,25 +820,27 @@ var ReactServerProvider = class {
872
820
  app = (0, react_dom_server.renderToString)(context.onError(error));
873
821
  }
874
822
  this.serverTimingProvider.endTiming("renderToString");
875
- const hydrationData = {
876
- links: context.links,
877
- layers: state.layers.map((it) => ({
878
- ...it,
879
- error: it.error ? {
880
- ...it.error,
881
- name: it.error.name,
882
- message: it.error.message,
883
- stack: it.error.stack
884
- } : void 0,
885
- index: void 0,
886
- path: void 0,
887
- element: void 0
888
- }))
889
- };
890
- const script = `<script>window.__ssr=${JSON.stringify(hydrationData)}</script>`;
891
823
  const response = { html: template };
892
- this.fillTemplate(response, app, script);
893
- if (context.head) response.html = this.headProvider.renderHead(response.html, context.head);
824
+ if (hydration) {
825
+ const hydrationData = {
826
+ links: context.links,
827
+ layers: state.layers.map((it) => ({
828
+ ...it,
829
+ error: it.error ? {
830
+ ...it.error,
831
+ name: it.error.name,
832
+ message: it.error.message,
833
+ stack: it.error.stack
834
+ } : void 0,
835
+ index: void 0,
836
+ path: void 0,
837
+ element: void 0,
838
+ route: void 0
839
+ }))
840
+ };
841
+ const script = `<script>window.__ssr=${JSON.stringify(hydrationData)}</script>`;
842
+ this.fillTemplate(response, app, script);
843
+ }
894
844
  return response.html;
895
845
  }
896
846
  fillTemplate(response, app, script) {
@@ -908,28 +858,6 @@ var ReactServerProvider = class {
908
858
  }
909
859
  };
910
860
 
911
- //#endregion
912
- //#region src/providers/BrowserHeadProvider.ts
913
- var BrowserHeadProvider = class {
914
- renderHead(document, head) {
915
- if (head.title) document.title = head.title;
916
- if (head.bodyAttributes) for (const [key, value] of Object.entries(head.bodyAttributes)) if (value) document.body.setAttribute(key, value);
917
- else document.body.removeAttribute(key);
918
- if (head.htmlAttributes) for (const [key, value] of Object.entries(head.htmlAttributes)) if (value) document.documentElement.setAttribute(key, value);
919
- else document.documentElement.removeAttribute(key);
920
- if (head.meta) for (const [key, value] of Object.entries(head.meta)) {
921
- const meta = document.querySelector(`meta[name="${key}"]`);
922
- if (meta) meta.setAttribute("content", value.content);
923
- else {
924
- const newMeta = document.createElement("meta");
925
- newMeta.setAttribute("name", key);
926
- newMeta.setAttribute("content", value.content);
927
- document.head.appendChild(newMeta);
928
- }
929
- }
930
- }
931
- };
932
-
933
861
  //#endregion
934
862
  //#region src/providers/BrowserRouterProvider.ts
935
863
  var BrowserRouterProvider = class extends __alepha_router.RouterProvider {
@@ -959,7 +887,6 @@ var BrowserRouterProvider = class extends __alepha_router.RouterProvider {
959
887
  url,
960
888
  query: {},
961
889
  params: {},
962
- head: {},
963
890
  onError: () => null,
964
891
  ...options.context ?? {}
965
892
  };
@@ -990,7 +917,10 @@ var BrowserRouterProvider = class extends __alepha_router.RouterProvider {
990
917
  index: 0,
991
918
  path: "/"
992
919
  });
993
- await this.alepha.emit("react:transition:success", { state });
920
+ await this.alepha.emit("react:transition:success", {
921
+ state,
922
+ context
923
+ });
994
924
  } catch (e) {
995
925
  this.log.error(e);
996
926
  state.layers = [{
@@ -1028,10 +958,9 @@ var BrowserRouterProvider = class extends __alepha_router.RouterProvider {
1028
958
  //#region src/providers/ReactBrowserProvider.ts
1029
959
  var ReactBrowserProvider = class {
1030
960
  log = (0, __alepha_core.$logger)();
1031
- client = (0, __alepha_core.$inject)(__alepha_server.HttpClient);
961
+ client = (0, __alepha_core.$inject)(__alepha_server_links.LinkProvider);
1032
962
  alepha = (0, __alepha_core.$inject)(__alepha_core.Alepha);
1033
963
  router = (0, __alepha_core.$inject)(BrowserRouterProvider);
1034
- headProvider = (0, __alepha_core.$inject)(BrowserHeadProvider);
1035
964
  root;
1036
965
  transitioning;
1037
966
  state = {
@@ -1110,7 +1039,6 @@ var ReactBrowserProvider = class {
1110
1039
  const previous = hydration?.layers ?? [];
1111
1040
  if (hydration?.links) for (const link of hydration.links.links) this.client.pushLink(link);
1112
1041
  const { context } = await this.render({ previous });
1113
- if (context.head) this.headProvider.renderHead(this.document, context.head);
1114
1042
  await this.alepha.emit("react:browser:render", {
1115
1043
  state: this.state,
1116
1044
  context,
@@ -1121,12 +1049,6 @@ var ReactBrowserProvider = class {
1121
1049
  });
1122
1050
  }
1123
1051
  });
1124
- onTransitionEnd = (0, __alepha_core.$hook)({
1125
- name: "react:transition:end",
1126
- handler: async ({ context }) => {
1127
- this.headProvider.renderHead(this.document, context.head);
1128
- }
1129
- });
1130
1052
  };
1131
1053
 
1132
1054
  //#endregion
@@ -1285,7 +1207,7 @@ const useInject = (clazz) => {
1285
1207
  //#endregion
1286
1208
  //#region src/hooks/useClient.ts
1287
1209
  const useClient = (_scope) => {
1288
- return useInject(__alepha_server.HttpClient).of();
1210
+ return useInject(__alepha_server_links.LinkProvider).client();
1289
1211
  };
1290
1212
 
1291
1213
  //#endregion