@alepha/react 0.9.1 → 0.9.2
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/README.md +7 -0
- package/dist/index.browser.js +93 -33
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +95 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -29
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +51 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +93 -33
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/contexts/AlephaContext.ts +4 -0
- package/src/contexts/RouterContext.ts +0 -2
- package/src/hooks/useAlepha.ts +5 -5
- package/src/hooks/useInject.ts +5 -8
- package/src/hooks/useQueryParams.ts +6 -9
- package/src/hooks/useRouter.ts +4 -4
- package/src/hooks/useRouterEvents.ts +7 -10
- package/src/hooks/useRouterState.ts +6 -4
- package/src/hooks/useSchema.ts +93 -0
- package/src/hooks/useStore.ts +39 -0
- package/src/index.shared.ts +3 -0
- package/src/providers/PageDescriptorProvider.ts +12 -8
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ Alternatively, you can install it individually:
|
|
|
15
15
|
```bash
|
|
16
16
|
npm install @alepha/core @alepha/react
|
|
17
17
|
```
|
|
18
|
+
|
|
18
19
|
## Module
|
|
19
20
|
|
|
20
21
|
Provides full-stack React development with declarative routing, server-side rendering, and client-side hydration.
|
|
@@ -30,3 +31,9 @@ type safety and schema validation for route parameters and data.
|
|
|
30
31
|
#### $page()
|
|
31
32
|
|
|
32
33
|
Main descriptor for defining a React route in the application.
|
|
34
|
+
|
|
35
|
+
### Hooks
|
|
36
|
+
|
|
37
|
+
#### useStore()
|
|
38
|
+
|
|
39
|
+
Hook to access and mutate the Alepha state.
|
package/dist/index.browser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { $env, $hook, $inject, $logger, $module, Alepha, Descriptor, KIND, NotImplementedError, createDescriptor, t } from "@alepha/core";
|
|
2
|
-
import { AlephaServer } from "@alepha/server";
|
|
2
|
+
import { AlephaServer, HttpClient } from "@alepha/server";
|
|
3
3
|
import { AlephaServerLinks, LinkProvider } from "@alepha/server-links";
|
|
4
4
|
import { RouterProvider } from "@alepha/router";
|
|
5
5
|
import React, { StrictMode, createContext, createElement, useContext, useEffect, useMemo, useState } from "react";
|
|
@@ -227,20 +227,31 @@ const RouterContext = createContext(void 0);
|
|
|
227
227
|
//#region src/contexts/RouterLayerContext.ts
|
|
228
228
|
const RouterLayerContext = createContext(void 0);
|
|
229
229
|
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/contexts/AlephaContext.ts
|
|
232
|
+
const AlephaContext = createContext(void 0);
|
|
233
|
+
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/hooks/useAlepha.ts
|
|
236
|
+
const useAlepha = () => {
|
|
237
|
+
const alepha = useContext(AlephaContext);
|
|
238
|
+
if (!alepha) throw new Error("useAlepha must be used within an AlephaContext.Provider");
|
|
239
|
+
return alepha;
|
|
240
|
+
};
|
|
241
|
+
|
|
230
242
|
//#endregion
|
|
231
243
|
//#region src/hooks/useRouterEvents.ts
|
|
232
244
|
const useRouterEvents = (opts = {}, deps = []) => {
|
|
233
|
-
const
|
|
234
|
-
if (!ctx) throw new Error("useRouter must be used within a RouterProvider");
|
|
245
|
+
const alepha = useAlepha();
|
|
235
246
|
useEffect(() => {
|
|
236
|
-
if (!
|
|
247
|
+
if (!alepha.isBrowser()) return;
|
|
237
248
|
const subs = [];
|
|
238
249
|
const onBegin = opts.onBegin;
|
|
239
250
|
const onEnd = opts.onEnd;
|
|
240
251
|
const onError = opts.onError;
|
|
241
|
-
if (onBegin) subs.push(
|
|
242
|
-
if (onEnd) subs.push(
|
|
243
|
-
if (onError) subs.push(
|
|
252
|
+
if (onBegin) subs.push(alepha.on("react:transition:begin", { callback: onBegin }));
|
|
253
|
+
if (onEnd) subs.push(alepha.on("react:transition:end", { callback: onEnd }));
|
|
254
|
+
if (onError) subs.push(alepha.on("react:transition:error", { callback: onError }));
|
|
244
255
|
return () => {
|
|
245
256
|
for (const sub of subs) sub();
|
|
246
257
|
};
|
|
@@ -356,11 +367,10 @@ var PageDescriptorProvider = class {
|
|
|
356
367
|
return new URL(url.replace(/\/\/+/g, "/") || "/", options.base ?? `http://localhost`);
|
|
357
368
|
}
|
|
358
369
|
root(state, context) {
|
|
359
|
-
const root = createElement(RouterContext.Provider, { value: {
|
|
360
|
-
alepha: this.alepha,
|
|
370
|
+
const root = createElement(AlephaContext.Provider, { value: this.alepha }, createElement(RouterContext.Provider, { value: {
|
|
361
371
|
state,
|
|
362
372
|
context
|
|
363
|
-
} }, createElement(NestedView_default, {}, state.layers[0]?.element));
|
|
373
|
+
} }, createElement(NestedView_default, {}, state.layers[0]?.element)));
|
|
364
374
|
if (this.env.REACT_STRICT_MODE) return createElement(StrictMode, {}, root);
|
|
365
375
|
return root;
|
|
366
376
|
}
|
|
@@ -943,13 +953,14 @@ var RouterHookApi = class {
|
|
|
943
953
|
//#endregion
|
|
944
954
|
//#region src/hooks/useRouter.ts
|
|
945
955
|
const useRouter = () => {
|
|
956
|
+
const alepha = useAlepha();
|
|
946
957
|
const ctx = useContext(RouterContext);
|
|
947
958
|
const layer = useContext(RouterLayerContext);
|
|
948
959
|
if (!ctx || !layer) throw new Error("useRouter must be used within a RouterProvider");
|
|
949
960
|
const pages = useMemo(() => {
|
|
950
|
-
return
|
|
961
|
+
return alepha.inject(PageDescriptorProvider).getPages();
|
|
951
962
|
}, []);
|
|
952
|
-
return useMemo(() => new RouterHookApi(pages, ctx.context, ctx.state, layer,
|
|
963
|
+
return useMemo(() => new RouterHookApi(pages, ctx.context, ctx.state, layer, alepha.isBrowser() ? alepha.inject(ReactBrowserProvider) : void 0), [layer]);
|
|
953
964
|
};
|
|
954
965
|
|
|
955
966
|
//#endregion
|
|
@@ -1008,20 +1019,11 @@ const useActive = (path) => {
|
|
|
1008
1019
|
};
|
|
1009
1020
|
};
|
|
1010
1021
|
|
|
1011
|
-
//#endregion
|
|
1012
|
-
//#region src/hooks/useAlepha.ts
|
|
1013
|
-
const useAlepha = () => {
|
|
1014
|
-
const routerContext = useContext(RouterContext);
|
|
1015
|
-
if (!routerContext) throw new Error("useAlepha must be used within a RouterProvider");
|
|
1016
|
-
return routerContext.alepha;
|
|
1017
|
-
};
|
|
1018
|
-
|
|
1019
1022
|
//#endregion
|
|
1020
1023
|
//#region src/hooks/useInject.ts
|
|
1021
|
-
const useInject = (
|
|
1022
|
-
const
|
|
1023
|
-
|
|
1024
|
-
return useMemo(() => ctx.alepha.inject(clazz), []);
|
|
1024
|
+
const useInject = (service) => {
|
|
1025
|
+
const alepha = useAlepha();
|
|
1026
|
+
return useMemo(() => alepha.inject(service), []);
|
|
1025
1027
|
};
|
|
1026
1028
|
|
|
1027
1029
|
//#endregion
|
|
@@ -1033,21 +1035,20 @@ const useClient = (_scope) => {
|
|
|
1033
1035
|
//#endregion
|
|
1034
1036
|
//#region src/hooks/useQueryParams.ts
|
|
1035
1037
|
const useQueryParams = (schema, options = {}) => {
|
|
1036
|
-
const
|
|
1037
|
-
if (!ctx) throw new Error("useQueryParams must be used within a RouterProvider");
|
|
1038
|
+
const alepha = useAlepha();
|
|
1038
1039
|
const key = options.key ?? "q";
|
|
1039
1040
|
const router = useRouter();
|
|
1040
1041
|
const querystring = router.query[key];
|
|
1041
|
-
const [queryParams, setQueryParams] = useState(decode(
|
|
1042
|
+
const [queryParams, setQueryParams] = useState(decode(alepha, schema, router.query[key]));
|
|
1042
1043
|
useEffect(() => {
|
|
1043
|
-
setQueryParams(decode(
|
|
1044
|
+
setQueryParams(decode(alepha, schema, querystring));
|
|
1044
1045
|
}, [querystring]);
|
|
1045
1046
|
return [queryParams, (queryParams$1) => {
|
|
1046
1047
|
setQueryParams(queryParams$1);
|
|
1047
1048
|
router.setQueryParams((data) => {
|
|
1048
1049
|
return {
|
|
1049
1050
|
...data,
|
|
1050
|
-
[key]: encode(
|
|
1051
|
+
[key]: encode(alepha, schema, queryParams$1)
|
|
1051
1052
|
};
|
|
1052
1053
|
});
|
|
1053
1054
|
}];
|
|
@@ -1066,14 +1067,73 @@ const decode = (alepha, schema, data) => {
|
|
|
1066
1067
|
//#endregion
|
|
1067
1068
|
//#region src/hooks/useRouterState.ts
|
|
1068
1069
|
const useRouterState = () => {
|
|
1069
|
-
const
|
|
1070
|
+
const router = useContext(RouterContext);
|
|
1070
1071
|
const layer = useContext(RouterLayerContext);
|
|
1071
|
-
if (!
|
|
1072
|
-
const [state, setState] = useState(
|
|
1072
|
+
if (!router || !layer) throw new Error("useRouterState must be used within a RouterContext.Provider");
|
|
1073
|
+
const [state, setState] = useState(router.state);
|
|
1073
1074
|
useRouterEvents({ onEnd: ({ state: state$1 }) => setState({ ...state$1 }) });
|
|
1074
1075
|
return state;
|
|
1075
1076
|
};
|
|
1076
1077
|
|
|
1078
|
+
//#endregion
|
|
1079
|
+
//#region src/hooks/useSchema.ts
|
|
1080
|
+
const useSchema = (action) => {
|
|
1081
|
+
const name = action.name;
|
|
1082
|
+
const alepha = useAlepha();
|
|
1083
|
+
const httpClient = useInject(HttpClient);
|
|
1084
|
+
const linkProvider = useInject(LinkProvider);
|
|
1085
|
+
const [schema, setSchema] = useState(ssrSchemaLoading(alepha, name));
|
|
1086
|
+
useEffect(() => {
|
|
1087
|
+
if (!schema.loading) return;
|
|
1088
|
+
const opts = { cache: true };
|
|
1089
|
+
httpClient.fetch(`${linkProvider.URL_LINKS}/${name}/schema`, {}, opts).then((it) => setSchema(it.data));
|
|
1090
|
+
}, [name]);
|
|
1091
|
+
return schema;
|
|
1092
|
+
};
|
|
1093
|
+
/**
|
|
1094
|
+
* Get an action schema during server-side rendering (SSR) or client-side rendering (CSR).
|
|
1095
|
+
*/
|
|
1096
|
+
const ssrSchemaLoading = (alepha, name) => {
|
|
1097
|
+
if (!alepha.isBrowser()) {
|
|
1098
|
+
const links = alepha.context.get("links")?.links ?? [];
|
|
1099
|
+
const can = links.find((it) => it.name === name);
|
|
1100
|
+
if (can) {
|
|
1101
|
+
const schema$1 = alepha.inject(LinkProvider).links?.find((it) => it.name === name)?.schema;
|
|
1102
|
+
if (schema$1) {
|
|
1103
|
+
can.schema = schema$1;
|
|
1104
|
+
return schema$1;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
return { loading: true };
|
|
1108
|
+
}
|
|
1109
|
+
const schema = alepha.inject(LinkProvider).links?.find((it) => it.name === name)?.schema;
|
|
1110
|
+
if (schema) return schema;
|
|
1111
|
+
return { loading: true };
|
|
1112
|
+
};
|
|
1113
|
+
|
|
1114
|
+
//#endregion
|
|
1115
|
+
//#region src/hooks/useStore.ts
|
|
1116
|
+
/**
|
|
1117
|
+
* Hook to access and mutate the Alepha state.
|
|
1118
|
+
*/
|
|
1119
|
+
const useStore = (key) => {
|
|
1120
|
+
const alepha = useAlepha();
|
|
1121
|
+
const [state, setState] = useState(alepha.state(key));
|
|
1122
|
+
useEffect(() => {
|
|
1123
|
+
if (!alepha.isBrowser()) return;
|
|
1124
|
+
return alepha.on("state:mutate", (ev) => {
|
|
1125
|
+
if (ev.key === key) setState(ev.value);
|
|
1126
|
+
});
|
|
1127
|
+
}, []);
|
|
1128
|
+
if (!alepha.isBrowser()) {
|
|
1129
|
+
const value = alepha.context.get(key);
|
|
1130
|
+
if (value !== null) return [value, (_) => {}];
|
|
1131
|
+
}
|
|
1132
|
+
return [state, (value) => {
|
|
1133
|
+
alepha.state(key, value);
|
|
1134
|
+
}];
|
|
1135
|
+
};
|
|
1136
|
+
|
|
1077
1137
|
//#endregion
|
|
1078
1138
|
//#region src/index.browser.ts
|
|
1079
1139
|
const AlephaReact = $module({
|
|
@@ -1089,5 +1149,5 @@ const AlephaReact = $module({
|
|
|
1089
1149
|
});
|
|
1090
1150
|
|
|
1091
1151
|
//#endregion
|
|
1092
|
-
export { $page, AlephaReact, BrowserRouterProvider, ClientOnly_default as ClientOnly, ErrorBoundary_default as ErrorBoundary, Link_default as Link, NestedView_default as NestedView, NotFoundPage as NotFound, PageDescriptor, PageDescriptorProvider, ReactBrowserProvider, RedirectionError, RouterContext, RouterHookApi, RouterLayerContext, isPageRoute, useActive, useAlepha, useClient, useInject, useQueryParams, useRouter, useRouterEvents, useRouterState };
|
|
1152
|
+
export { $page, AlephaContext, AlephaReact, BrowserRouterProvider, ClientOnly_default as ClientOnly, ErrorBoundary_default as ErrorBoundary, Link_default as Link, NestedView_default as NestedView, NotFoundPage as NotFound, PageDescriptor, PageDescriptorProvider, ReactBrowserProvider, RedirectionError, RouterContext, RouterHookApi, RouterLayerContext, isPageRoute, ssrSchemaLoading, useActive, useAlepha, useClient, useInject, useQueryParams, useRouter, useRouterEvents, useRouterState, useSchema, useStore };
|
|
1093
1153
|
//# sourceMappingURL=index.browser.js.map
|