@alepha/react 0.13.1 → 0.13.3
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/auth/index.browser.js +10 -5
- package/dist/auth/index.browser.js.map +1 -1
- package/dist/auth/index.d.ts +401 -330
- package/dist/auth/index.js +12 -7
- package/dist/auth/index.js.map +1 -1
- package/dist/core/index.browser.js +50 -28
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +382 -344
- package/dist/core/index.js +65 -37
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +381 -0
- package/dist/core/index.native.js.map +1 -0
- package/dist/form/index.d.ts +2 -2
- package/dist/head/index.browser.js +28 -17
- package/dist/head/index.browser.js.map +1 -1
- package/dist/head/index.d.ts +270 -267
- package/dist/head/index.js +29 -17
- package/dist/head/index.js.map +1 -1
- package/dist/i18n/index.d.ts +20 -20
- package/dist/i18n/index.js +12 -12
- package/dist/i18n/index.js.map +1 -1
- package/dist/websocket/index.d.ts +7 -7
- package/dist/websocket/index.js.map +1 -1
- package/package.json +21 -12
- package/src/auth/index.ts +1 -1
- package/src/auth/providers/ReactAuthProvider.ts +1 -1
- package/src/auth/services/ReactAuth.ts +15 -5
- package/src/core/components/NestedView.tsx +6 -2
- package/src/core/components/NotFound.tsx +10 -6
- package/src/core/hooks/useStore.ts +4 -4
- package/src/core/index.browser.ts +2 -2
- package/src/core/index.native.ts +1 -1
- package/src/core/index.shared-router.ts +1 -1
- package/src/core/index.ts +3 -3
- package/src/core/{descriptors → primitives}/$page.ts +20 -20
- package/src/core/providers/ReactBrowserProvider.ts +2 -2
- package/src/core/providers/ReactBrowserRouterProvider.ts +3 -2
- package/src/core/providers/ReactPageProvider.ts +28 -11
- package/src/core/providers/ReactServerProvider.ts +34 -23
- package/src/core/services/ReactPageServerService.ts +6 -6
- package/src/core/services/ReactPageService.ts +6 -6
- package/src/core/services/ReactRouter.ts +19 -3
- package/src/head/index.browser.ts +3 -3
- package/src/head/index.ts +4 -4
- package/src/head/interfaces/Head.ts +1 -0
- package/src/head/{descriptors → primitives}/$head.ts +10 -7
- package/src/head/providers/BrowserHeadProvider.ts +13 -0
- package/src/head/providers/HeadProvider.ts +11 -9
- package/src/head/providers/ServerHeadProvider.ts +6 -0
- package/src/i18n/hooks/useI18n.ts +2 -2
- package/src/i18n/index.ts +3 -3
- package/src/i18n/{descriptors → primitives}/$dictionary.ts +8 -8
- package/src/i18n/providers/I18nProvider.ts +5 -5
- package/src/websocket/hooks/useRoom.tsx +3 -3
package/dist/core/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $atom, $env, $hook, $inject, $module, $use, Alepha, AlephaError, Atom,
|
|
1
|
+
import { $atom, $env, $hook, $inject, $module, $use, Alepha, AlephaError, Atom, KIND, Primitive, createPrimitive, t } from "alepha";
|
|
2
2
|
import { AlephaDateTime, DateTimeProvider } from "alepha/datetime";
|
|
3
3
|
import { AlephaServer, HttpClient, ServerProvider, ServerRouterProvider, ServerTimingProvider } from "alepha/server";
|
|
4
4
|
import { AlephaServerCache } from "alepha/server/cache";
|
|
@@ -23,11 +23,11 @@ var ReactPageService = class {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
//#endregion
|
|
26
|
-
//#region src/core/
|
|
26
|
+
//#region src/core/primitives/$page.ts
|
|
27
27
|
/**
|
|
28
|
-
* Main
|
|
28
|
+
* Main primitive for defining a React route in the application.
|
|
29
29
|
*
|
|
30
|
-
* The $page
|
|
30
|
+
* The $page primitive is the core building block for creating type-safe, SSR-enabled React routes.
|
|
31
31
|
* It provides a declarative way to define pages with powerful features:
|
|
32
32
|
*
|
|
33
33
|
* **Routing & Navigation**
|
|
@@ -113,9 +113,9 @@ var ReactPageService = class {
|
|
|
113
113
|
* ```
|
|
114
114
|
*/
|
|
115
115
|
const $page = (options) => {
|
|
116
|
-
return
|
|
116
|
+
return createPrimitive(PagePrimitive, options);
|
|
117
117
|
};
|
|
118
|
-
var
|
|
118
|
+
var PagePrimitive = class extends Primitive {
|
|
119
119
|
reactPageService = $inject(ReactPageService);
|
|
120
120
|
onInit() {
|
|
121
121
|
if (this.options.static) this.options.cache ??= { store: {
|
|
@@ -145,7 +145,7 @@ var PageDescriptor = class extends Descriptor {
|
|
|
145
145
|
return this.options.path || "";
|
|
146
146
|
}
|
|
147
147
|
};
|
|
148
|
-
$page[KIND] =
|
|
148
|
+
$page[KIND] = PagePrimitive;
|
|
149
149
|
|
|
150
150
|
//#endregion
|
|
151
151
|
//#region src/core/components/ClientOnly.tsx
|
|
@@ -400,9 +400,9 @@ const useEvents = (opts, deps) => {
|
|
|
400
400
|
function useStore(target, defaultValue) {
|
|
401
401
|
const alepha = useAlepha();
|
|
402
402
|
useMemo(() => {
|
|
403
|
-
if (defaultValue != null && alepha.
|
|
403
|
+
if (defaultValue != null && alepha.store.get(target) == null) alepha.store.set(target, defaultValue);
|
|
404
404
|
}, [defaultValue]);
|
|
405
|
-
const [state, setState] = useState(alepha.
|
|
405
|
+
const [state, setState] = useState(alepha.store.get(target));
|
|
406
406
|
useEffect(() => {
|
|
407
407
|
if (!alepha.isBrowser()) return;
|
|
408
408
|
const key = target instanceof Atom ? target.key : target;
|
|
@@ -411,7 +411,7 @@ function useStore(target, defaultValue) {
|
|
|
411
411
|
});
|
|
412
412
|
}, []);
|
|
413
413
|
return [state, (value) => {
|
|
414
|
-
alepha.
|
|
414
|
+
alepha.store.set(target, value);
|
|
415
415
|
}];
|
|
416
416
|
}
|
|
417
417
|
|
|
@@ -487,7 +487,8 @@ const NestedView = (props) => {
|
|
|
487
487
|
useEvents({
|
|
488
488
|
"react:transition:begin": async ({ previous, state: state$1 }) => {
|
|
489
489
|
const layer = previous.layers[index];
|
|
490
|
-
if (
|
|
490
|
+
if (!layer) return;
|
|
491
|
+
if (`${state$1.url.pathname}/`.startsWith(`${layer.path}/`)) return;
|
|
491
492
|
const animationExit = parseAnimation(layer.route?.animation, state$1, "exit");
|
|
492
493
|
if (animationExit) {
|
|
493
494
|
const duration = animationExit.duration || 200;
|
|
@@ -579,25 +580,35 @@ function parseAnimation(animationLike, state, type = "enter") {
|
|
|
579
580
|
//#endregion
|
|
580
581
|
//#region src/core/components/NotFound.tsx
|
|
581
582
|
function NotFoundPage(props) {
|
|
582
|
-
return /* @__PURE__ */
|
|
583
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
583
584
|
style: {
|
|
584
|
-
|
|
585
|
+
width: "100%",
|
|
586
|
+
minHeight: "90vh",
|
|
587
|
+
boxSizing: "border-box",
|
|
585
588
|
display: "flex",
|
|
586
589
|
flexDirection: "column",
|
|
587
590
|
justifyContent: "center",
|
|
588
591
|
alignItems: "center",
|
|
589
592
|
textAlign: "center",
|
|
590
|
-
fontFamily: "sans-serif",
|
|
591
|
-
padding: "
|
|
593
|
+
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif",
|
|
594
|
+
padding: "2rem",
|
|
592
595
|
...props.style
|
|
593
596
|
},
|
|
594
|
-
children: /* @__PURE__ */ jsx("
|
|
597
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
595
598
|
style: {
|
|
596
|
-
fontSize: "
|
|
597
|
-
|
|
599
|
+
fontSize: "6rem",
|
|
600
|
+
fontWeight: 200,
|
|
601
|
+
lineHeight: 1
|
|
598
602
|
},
|
|
599
|
-
children: "404
|
|
600
|
-
})
|
|
603
|
+
children: "404"
|
|
604
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
605
|
+
style: {
|
|
606
|
+
fontSize: "0.875rem",
|
|
607
|
+
marginTop: "1rem",
|
|
608
|
+
opacity: .6
|
|
609
|
+
},
|
|
610
|
+
children: "Page not found"
|
|
611
|
+
})]
|
|
601
612
|
});
|
|
602
613
|
}
|
|
603
614
|
|
|
@@ -626,6 +637,7 @@ var ReactPageProvider = class {
|
|
|
626
637
|
if (!path.includes(":") && !path.includes("*")) pages.push({
|
|
627
638
|
...page,
|
|
628
639
|
name: params[Object.keys(params)[0]],
|
|
640
|
+
staticName: page.name,
|
|
629
641
|
path,
|
|
630
642
|
...entry
|
|
631
643
|
});
|
|
@@ -856,7 +868,7 @@ var ReactPageProvider = class {
|
|
|
856
868
|
on: "configure",
|
|
857
869
|
handler: () => {
|
|
858
870
|
let hasNotFoundHandler = false;
|
|
859
|
-
const pages = this.alepha.
|
|
871
|
+
const pages = this.alepha.primitives($page);
|
|
860
872
|
const hasParent = (it) => {
|
|
861
873
|
if (it.options.parent) return true;
|
|
862
874
|
for (const page of pages) if ((page.options.children ? Array.isArray(page.options.children) ? page.options.children : page.options.children() : []).includes(it)) return true;
|
|
@@ -969,8 +981,8 @@ var ReactServerProvider = class {
|
|
|
969
981
|
onConfigure = $hook({
|
|
970
982
|
on: "configure",
|
|
971
983
|
handler: async () => {
|
|
972
|
-
const ssrEnabled = this.alepha.
|
|
973
|
-
this.alepha.
|
|
984
|
+
const ssrEnabled = this.alepha.primitives($page).length > 0 && this.env.REACT_SSR_ENABLED !== false;
|
|
985
|
+
this.alepha.store.set("alepha.react.server.ssr", ssrEnabled);
|
|
974
986
|
if (this.alepha.isViteDev()) {
|
|
975
987
|
await this.configureVite(ssrEnabled);
|
|
976
988
|
return;
|
|
@@ -1011,8 +1023,7 @@ var ReactServerProvider = class {
|
|
|
1011
1023
|
async registerPages(templateLoader) {
|
|
1012
1024
|
const template = await templateLoader();
|
|
1013
1025
|
if (template) this.preprocessedTemplate = this.preprocessTemplate(template);
|
|
1014
|
-
for (const page of this.pageApi.getPages()) {
|
|
1015
|
-
if (page.children?.length) continue;
|
|
1026
|
+
for (const page of this.pageApi.getPages()) if (page.component || page.lazy) {
|
|
1016
1027
|
this.log.debug(`+ ${page.match} -> ${page.name}`);
|
|
1017
1028
|
this.serverRouterProvider.createRoute({
|
|
1018
1029
|
...page,
|
|
@@ -1076,7 +1087,7 @@ var ReactServerProvider = class {
|
|
|
1076
1087
|
redirect
|
|
1077
1088
|
};
|
|
1078
1089
|
if (!options.html) {
|
|
1079
|
-
this.alepha.
|
|
1090
|
+
this.alepha.store.set("alepha.react.router.state", state);
|
|
1080
1091
|
return {
|
|
1081
1092
|
state,
|
|
1082
1093
|
html: renderToString(this.pageApi.root(state))
|
|
@@ -1109,13 +1120,15 @@ var ReactServerProvider = class {
|
|
|
1109
1120
|
onError: () => null,
|
|
1110
1121
|
layers: []
|
|
1111
1122
|
};
|
|
1112
|
-
|
|
1123
|
+
state.name = route.name;
|
|
1124
|
+
if (this.alepha.has(ServerLinksProvider)) this.alepha.store.set("alepha.server.request.apiLinks", await this.alepha.inject(ServerLinksProvider).getUserApiLinks({
|
|
1113
1125
|
user: serverRequest.user,
|
|
1114
1126
|
authorization: serverRequest.headers.authorization
|
|
1115
1127
|
}));
|
|
1116
1128
|
let target = route;
|
|
1117
1129
|
while (target) {
|
|
1118
1130
|
if (route.can && !route.can()) {
|
|
1131
|
+
this.log.warn(`Access to page '${route.name}' is forbidden by can() check`);
|
|
1119
1132
|
reply.status = 403;
|
|
1120
1133
|
reply.headers["content-type"] = "text/plain";
|
|
1121
1134
|
return "Forbidden";
|
|
@@ -1129,7 +1142,10 @@ var ReactServerProvider = class {
|
|
|
1129
1142
|
this.serverTimingProvider.beginTiming("createLayers");
|
|
1130
1143
|
const { redirect } = await this.pageApi.createLayers(route, state);
|
|
1131
1144
|
this.serverTimingProvider.endTiming("createLayers");
|
|
1132
|
-
if (redirect)
|
|
1145
|
+
if (redirect) {
|
|
1146
|
+
this.log.debug("Resolver resulted in redirection", { redirect });
|
|
1147
|
+
return reply.redirect(redirect);
|
|
1148
|
+
}
|
|
1133
1149
|
reply.headers["content-type"] = "text/html";
|
|
1134
1150
|
reply.headers["cache-control"] = "no-store, no-cache, must-revalidate, proxy-revalidate";
|
|
1135
1151
|
reply.headers.pragma = "no-cache";
|
|
@@ -1137,8 +1153,10 @@ var ReactServerProvider = class {
|
|
|
1137
1153
|
const html = this.renderToHtml(template, state);
|
|
1138
1154
|
if (html instanceof Redirection) {
|
|
1139
1155
|
reply.redirect(typeof html.redirect === "string" ? html.redirect : this.pageApi.href(html.redirect));
|
|
1156
|
+
this.log.debug("Rendering resulted in redirection", { redirect: html.redirect });
|
|
1140
1157
|
return;
|
|
1141
1158
|
}
|
|
1159
|
+
this.log.trace("Page rendered to HTML successfully");
|
|
1142
1160
|
const event = {
|
|
1143
1161
|
request: serverRequest,
|
|
1144
1162
|
state,
|
|
@@ -1152,7 +1170,7 @@ var ReactServerProvider = class {
|
|
|
1152
1170
|
}
|
|
1153
1171
|
renderToHtml(template, state, hydration = true) {
|
|
1154
1172
|
const element = this.pageApi.root(state);
|
|
1155
|
-
this.alepha.
|
|
1173
|
+
this.alepha.store.set("alepha.react.router.state", state);
|
|
1156
1174
|
this.serverTimingProvider.beginTiming("renderToString");
|
|
1157
1175
|
let app = "";
|
|
1158
1176
|
try {
|
|
@@ -1284,13 +1302,14 @@ var ReactBrowserRouterProvider = class extends RouterProvider {
|
|
|
1284
1302
|
};
|
|
1285
1303
|
await this.alepha.events.emit("react:action:begin", { type: "transition" });
|
|
1286
1304
|
await this.alepha.events.emit("react:transition:begin", {
|
|
1287
|
-
previous: this.alepha.
|
|
1305
|
+
previous: this.alepha.store.get("alepha.react.router.state"),
|
|
1288
1306
|
state
|
|
1289
1307
|
});
|
|
1290
1308
|
try {
|
|
1291
1309
|
const { route, params } = this.match(pathname);
|
|
1292
1310
|
const query = {};
|
|
1293
1311
|
if (search) for (const [key, value] of new URLSearchParams(search).entries()) query[key] = String(value);
|
|
1312
|
+
state.name = route?.page.name;
|
|
1294
1313
|
state.query = query;
|
|
1295
1314
|
state.params = params ?? {};
|
|
1296
1315
|
if (isPageRoute(route)) {
|
|
@@ -1326,7 +1345,7 @@ var ReactBrowserRouterProvider = class extends RouterProvider {
|
|
|
1326
1345
|
const layer = previous[i];
|
|
1327
1346
|
if (state.layers[i]?.name !== layer.name) this.pageApi.page(layer.name)?.onLeave?.();
|
|
1328
1347
|
}
|
|
1329
|
-
this.alepha.
|
|
1348
|
+
this.alepha.store.set("alepha.react.router.state", state);
|
|
1330
1349
|
await this.alepha.events.emit("react:action:end", { type: "transition" });
|
|
1331
1350
|
await this.alepha.events.emit("react:transition:end", { state });
|
|
1332
1351
|
}
|
|
@@ -1364,7 +1383,7 @@ var ReactBrowserProvider = class {
|
|
|
1364
1383
|
}
|
|
1365
1384
|
transitioning;
|
|
1366
1385
|
get state() {
|
|
1367
|
-
return this.alepha.
|
|
1386
|
+
return this.alepha.store.get("alepha.react.router.state");
|
|
1368
1387
|
}
|
|
1369
1388
|
/**
|
|
1370
1389
|
* Accessor for Document DOM API.
|
|
@@ -1481,7 +1500,7 @@ var ReactBrowserProvider = class {
|
|
|
1481
1500
|
const hydration = this.getHydrationState();
|
|
1482
1501
|
const previous = hydration?.layers ?? [];
|
|
1483
1502
|
if (hydration) {
|
|
1484
|
-
for (const [key, value] of Object.entries(hydration)) if (key !== "layers") this.alepha.
|
|
1503
|
+
for (const [key, value] of Object.entries(hydration)) if (key !== "layers") this.alepha.store.set(key, value);
|
|
1485
1504
|
}
|
|
1486
1505
|
await this.render({ previous });
|
|
1487
1506
|
const element = this.router.root(this.state);
|
|
@@ -1506,7 +1525,7 @@ var ReactRouter = class {
|
|
|
1506
1525
|
alepha = $inject(Alepha);
|
|
1507
1526
|
pageApi = $inject(ReactPageProvider);
|
|
1508
1527
|
get state() {
|
|
1509
|
-
return this.alepha.
|
|
1528
|
+
return this.alepha.store.get("alepha.react.router.state");
|
|
1510
1529
|
}
|
|
1511
1530
|
get pages() {
|
|
1512
1531
|
return this.pageApi.getPages();
|
|
@@ -1523,6 +1542,15 @@ var ReactRouter = class {
|
|
|
1523
1542
|
if (options.startWith && !isActive) isActive = current.startsWith(href);
|
|
1524
1543
|
return isActive;
|
|
1525
1544
|
}
|
|
1545
|
+
node(name, config = {}) {
|
|
1546
|
+
const page = this.pageApi.page(name);
|
|
1547
|
+
return {
|
|
1548
|
+
...page,
|
|
1549
|
+
label: page.label ?? page.name,
|
|
1550
|
+
href: this.path(name, config),
|
|
1551
|
+
children: void 0
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1526
1554
|
path(name, config = {}) {
|
|
1527
1555
|
return this.pageApi.pathname(name, {
|
|
1528
1556
|
params: {
|
|
@@ -2001,7 +2029,7 @@ const decode = (alepha, schema, data) => {
|
|
|
2001
2029
|
/**
|
|
2002
2030
|
* Provides full-stack React development with declarative routing, server-side rendering, and client-side hydration.
|
|
2003
2031
|
*
|
|
2004
|
-
* The React module enables building modern React applications using the `$page`
|
|
2032
|
+
* The React module enables building modern React applications using the `$page` primitive on class properties.
|
|
2005
2033
|
* It delivers seamless server-side rendering, automatic code splitting, and client-side navigation with full
|
|
2006
2034
|
* type safety and schema validation for route parameters and data.
|
|
2007
2035
|
*
|
|
@@ -2010,7 +2038,7 @@ const decode = (alepha, schema, data) => {
|
|
|
2010
2038
|
*/
|
|
2011
2039
|
const AlephaReact = $module({
|
|
2012
2040
|
name: "alepha.react",
|
|
2013
|
-
|
|
2041
|
+
primitives: [$page],
|
|
2014
2042
|
services: [
|
|
2015
2043
|
ReactServerProvider,
|
|
2016
2044
|
ReactPageProvider,
|
|
@@ -2025,5 +2053,5 @@ const AlephaReact = $module({
|
|
|
2025
2053
|
});
|
|
2026
2054
|
|
|
2027
2055
|
//#endregion
|
|
2028
|
-
export { $page, AlephaContext, AlephaReact, ClientOnly_default as ClientOnly, ErrorBoundary_default as ErrorBoundary, ErrorViewer_default as ErrorViewer, Link_default as Link, NestedView_default as NestedView, NotFoundPage as NotFound,
|
|
2056
|
+
export { $page, AlephaContext, AlephaReact, ClientOnly_default as ClientOnly, ErrorBoundary_default as ErrorBoundary, ErrorViewer_default as ErrorViewer, Link_default as Link, NestedView_default as NestedView, NotFoundPage as NotFound, PagePrimitive, ReactBrowserProvider, ReactPageProvider, ReactRouter, ReactServerProvider, Redirection, RouterLayerContext, isPageRoute, reactBrowserOptions, reactServerOptions, ssrSchemaLoading, useAction, useActive, useAlepha, useClient, useEvents, useInject, useQueryParams, useRouter, useRouterState, useSchema, useStore };
|
|
2029
2057
|
//# sourceMappingURL=index.js.map
|