@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.browser.d.ts +26 -81
- package/dist/index.browser.js +11 -61
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +53 -131
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -95
- package/dist/index.d.ts +54 -103
- package/dist/index.js +52 -130
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
- package/src/descriptors/$page.ts +2 -47
- package/src/hooks/useClient.ts +3 -3
- package/src/index.ts +16 -4
- package/src/providers/BrowserRouterProvider.ts +3 -4
- package/src/providers/PageDescriptorProvider.ts +10 -57
- package/src/providers/ReactBrowserProvider.ts +3 -14
- package/src/providers/ReactServerProvider.ts +66 -58
- package/src/providers/BrowserHeadProvider.ts +0 -43
- package/src/providers/ServerHeadProvider.ts +0 -91
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
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].
|
|
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
|
-
|
|
748
|
+
const html = this.renderToHtml(this.template ?? "", state, context, options.hydration);
|
|
749
|
+
const result = {
|
|
811
750
|
context,
|
|
812
|
-
|
|
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(
|
|
829
|
-
const srv = this.alepha.get(
|
|
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
|
-
|
|
849
|
-
}
|
|
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
|
-
|
|
893
|
-
|
|
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", {
|
|
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)(
|
|
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(
|
|
1210
|
+
return useInject(__alepha_server_links.LinkProvider).client();
|
|
1289
1211
|
};
|
|
1290
1212
|
|
|
1291
1213
|
//#endregion
|