@alepha/react 0.9.3 → 0.9.4

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.
Files changed (37) hide show
  1. package/README.md +46 -0
  2. package/dist/index.browser.js +315 -320
  3. package/dist/index.browser.js.map +1 -1
  4. package/dist/index.cjs +496 -457
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.cts +276 -258
  7. package/dist/index.d.cts.map +1 -1
  8. package/dist/index.d.ts +274 -256
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +494 -460
  11. package/dist/index.js.map +1 -1
  12. package/package.json +13 -10
  13. package/src/components/NestedView.tsx +15 -13
  14. package/src/components/NotFound.tsx +1 -1
  15. package/src/descriptors/$page.ts +16 -4
  16. package/src/errors/Redirection.ts +8 -5
  17. package/src/hooks/useActive.ts +25 -34
  18. package/src/hooks/useAlepha.ts +16 -2
  19. package/src/hooks/useClient.ts +7 -4
  20. package/src/hooks/useInject.ts +4 -1
  21. package/src/hooks/useQueryParams.ts +9 -6
  22. package/src/hooks/useRouter.ts +18 -31
  23. package/src/hooks/useRouterEvents.ts +7 -7
  24. package/src/hooks/useRouterState.ts +8 -20
  25. package/src/hooks/useSchema.ts +10 -15
  26. package/src/hooks/useStore.ts +0 -7
  27. package/src/index.browser.ts +11 -11
  28. package/src/index.shared.ts +2 -3
  29. package/src/index.ts +21 -30
  30. package/src/providers/ReactBrowserProvider.ts +149 -65
  31. package/src/providers/ReactBrowserRouterProvider.ts +132 -0
  32. package/src/providers/{PageDescriptorProvider.ts → ReactPageProvider.ts} +84 -112
  33. package/src/providers/ReactServerProvider.ts +69 -74
  34. package/src/{hooks/RouterHookApi.ts → services/ReactRouter.ts} +44 -54
  35. package/src/contexts/RouterContext.ts +0 -14
  36. package/src/providers/BrowserRouterProvider.ts +0 -155
  37. package/src/providers/ReactBrowserRenderer.ts +0 -93
@@ -1,7 +1,8 @@
1
1
  import type { ReactNode } from "react";
2
2
  import { useContext, useState } from "react";
3
- import { RouterContext } from "../contexts/RouterContext.ts";
4
3
  import { RouterLayerContext } from "../contexts/RouterLayerContext.ts";
4
+ import { Redirection } from "../errors/Redirection.ts";
5
+ import { useAlepha } from "../hooks/useAlepha.ts";
5
6
  import { useRouterEvents } from "../hooks/useRouterEvents.ts";
6
7
  import ErrorBoundary from "./ErrorBoundary.tsx";
7
8
 
@@ -31,38 +32,39 @@ export interface NestedViewProps {
31
32
  * ```
32
33
  */
33
34
  const NestedView = (props: NestedViewProps) => {
34
- const app = useContext(RouterContext);
35
35
  const layer = useContext(RouterLayerContext);
36
36
  const index = layer?.index ?? 0;
37
+ const alepha = useAlepha();
38
+ const state = alepha.state("react.router.state");
39
+ if (!state) {
40
+ throw new Error("<NestedView/> must be used inside a RouterLayerContext.");
41
+ }
37
42
 
38
43
  const [view, setView] = useState<ReactNode | undefined>(
39
- app?.state.layers[index]?.element,
44
+ state.layers[index]?.element,
40
45
  );
41
46
 
42
47
  useRouterEvents(
43
48
  {
44
- onEnd: ({ state, context }) => {
45
- if (app) {
46
- app.context = context;
47
- }
49
+ onEnd: ({ state }) => {
48
50
  if (!state.layers[index]?.cache) {
49
51
  setView(state.layers[index]?.element);
50
52
  }
51
53
  },
52
54
  },
53
- [app],
55
+ [],
54
56
  );
55
57
 
56
- if (!app) {
57
- throw new Error("NestedView must be used within a RouterContext.");
58
- }
59
-
60
58
  const element = view ?? props.children ?? null;
61
59
 
62
60
  return (
63
61
  <ErrorBoundary
64
62
  fallback={(error) => {
65
- return app.context.onError?.(error, app.context) as ReactNode;
63
+ const result = state.onError(error, state); // TODO: onError is not refreshed
64
+ if (result instanceof Redirection) {
65
+ return "Redirection inside ErrorBoundary is not allowed.";
66
+ }
67
+ return result as ReactNode;
66
68
  }}
67
69
  >
68
70
  {element}
@@ -16,7 +16,7 @@ export default function NotFoundPage(props: { style?: CSSProperties }) {
16
16
  }}
17
17
  >
18
18
  <h1 style={{ fontSize: "1rem", marginBottom: "0.5rem" }}>
19
- This page does not exist
19
+ 404 - This page does not exist
20
20
  </h1>
21
21
  </div>
22
22
  );
@@ -11,7 +11,7 @@ import type { ServerRouteCache } from "@alepha/server-cache";
11
11
  import type { FC, ReactNode } from "react";
12
12
  import type { ClientOnlyProps } from "../components/ClientOnly.tsx";
13
13
  import type { Redirection } from "../errors/Redirection.ts";
14
- import type { PageReactContext } from "../providers/PageDescriptorProvider.ts";
14
+ import type { ReactRouterState } from "../providers/ReactPageProvider.ts";
15
15
 
16
16
  /**
17
17
  * Main descriptor for defining a React route in the application.
@@ -183,7 +183,7 @@ export interface PageDescriptorOptions<
183
183
 
184
184
  export type ErrorHandler = (
185
185
  error: Error,
186
- context: PageReactContext,
186
+ state: ReactRouterState,
187
187
  ) => ReactNode | Redirection | undefined;
188
188
 
189
189
  export class PageDescriptor<
@@ -213,6 +213,16 @@ export class PageDescriptor<
213
213
  ): Promise<PageDescriptorRenderResult> {
214
214
  throw new Error("render method is not implemented in this environment");
215
215
  }
216
+
217
+ public match(url: string): boolean {
218
+ // TODO: Implement a way to match the URL against the pathname
219
+ return false;
220
+ }
221
+
222
+ public pathname(config: any) {
223
+ // TODO: Implement a way to generate the pathname based on the config
224
+ return this.options.path || "";
225
+ }
216
226
  }
217
227
 
218
228
  $page[KIND] = PageDescriptor;
@@ -237,7 +247,7 @@ export interface PageDescriptorRenderOptions {
237
247
 
238
248
  export interface PageDescriptorRenderResult {
239
249
  html: string;
240
- context: PageReactContext;
250
+ state: ReactRouterState;
241
251
  }
242
252
 
243
253
  export interface PageRequestConfig<
@@ -255,4 +265,6 @@ export interface PageRequestConfig<
255
265
  export type PageResolve<
256
266
  TConfig extends PageConfigSchema = PageConfigSchema,
257
267
  TPropsParent extends object = TPropsParentDefault,
258
- > = PageRequestConfig<TConfig> & TPropsParent & PageReactContext;
268
+ > = PageRequestConfig<TConfig> &
269
+ TPropsParent &
270
+ Omit<ReactRouterState, "layers" | "onError">;
@@ -1,10 +1,13 @@
1
- import type { HrefLike } from "../hooks/RouterHookApi.ts";
2
-
1
+ /**
2
+ * Used for Redirection during the page loading.
3
+ *
4
+ * Depends on the context, it can be thrown or just returned.
5
+ */
3
6
  export class Redirection extends Error {
4
- public readonly page: HrefLike;
7
+ public readonly redirect: string;
5
8
 
6
- constructor(page: HrefLike) {
9
+ constructor(redirect: string) {
7
10
  super("Redirection");
8
- this.page = page;
11
+ this.redirect = redirect;
9
12
  }
10
13
  }
@@ -1,56 +1,47 @@
1
- import { useContext, useMemo, useState } from "react";
2
- import { RouterContext } from "../contexts/RouterContext.ts";
3
- import { RouterLayerContext } from "../contexts/RouterLayerContext.ts";
4
- import type { AnchorProps } from "../providers/PageDescriptorProvider.ts";
5
- import type { HrefLike } from "./RouterHookApi.ts";
1
+ import { useState } from "react";
2
+ import type { AnchorProps } from "../providers/ReactPageProvider.ts";
6
3
  import { useRouter } from "./useRouter.ts";
7
- import { useRouterEvents } from "./useRouterEvents.ts";
4
+ import { useRouterState } from "./useRouterState.ts";
8
5
 
9
- export const useActive = (path?: HrefLike): UseActiveHook => {
10
- const router = useRouter();
11
- const ctx = useContext(RouterContext);
12
- const layer = useContext(RouterLayerContext);
13
- if (!ctx || !layer) {
14
- throw new Error("useRouter must be used within a RouterProvider");
15
- }
16
-
17
- const [current, setCurrent] = useState(ctx.state.pathname);
18
- const href = useMemo(
19
- () => router.createHref(path ?? "", layer),
20
- [path, layer],
21
- );
6
+ export interface UseActiveOptions {
7
+ href: string;
8
+ startWith?: boolean;
9
+ }
22
10
 
11
+ export const useActive = (args: string | UseActiveOptions): UseActiveHook => {
12
+ const router = useRouter();
23
13
  const [isPending, setPending] = useState(false);
14
+ const state = useRouterState();
15
+ const current = state.url.pathname;
24
16
 
25
- // TODO: loose [default] or strict
26
- // TODO: startWith: true (e.g. /p/1 should match /p/1/2)
27
- const isActive =
17
+ const options: UseActiveOptions =
18
+ typeof args === "string" ? { href: args } : { ...args, href: args.href };
19
+ const href = options.href;
20
+
21
+ let isActive =
28
22
  current === href || current === `${href}/` || `${current}/` === href;
29
23
 
30
- useRouterEvents(
31
- {
32
- onEnd: ({ state }) => {
33
- path ? setCurrent(state.pathname) : undefined;
34
- },
35
- },
36
- [path],
37
- );
24
+ if (options.startWith && !isActive) {
25
+ isActive = current.startsWith(href);
26
+ }
38
27
 
39
28
  return {
40
29
  isPending,
41
30
  isActive,
42
31
  anchorProps: {
43
- href,
44
- onClick: (ev?: any) => {
32
+ href: router.base(href),
33
+ onClick: async (ev?: any) => {
45
34
  ev?.stopPropagation();
46
35
  ev?.preventDefault();
47
36
  if (isActive) return;
48
37
  if (isPending) return;
49
38
 
50
39
  setPending(true);
51
- router.go(href).then(() => {
40
+ try {
41
+ await router.go(href);
42
+ } finally {
52
43
  setPending(false);
53
- });
44
+ }
54
45
  },
55
46
  },
56
47
  };
@@ -1,11 +1,25 @@
1
- import type { Alepha } from "@alepha/core";
1
+ import { type Alepha, AlephaError } from "@alepha/core";
2
2
  import { useContext } from "react";
3
3
  import { AlephaContext } from "../contexts/AlephaContext.ts";
4
4
 
5
+ /**
6
+ * Main Alepha hook.
7
+ *
8
+ * It provides access to the Alepha instance within a React component.
9
+ *
10
+ * With Alepha, you can access the core functionalities of the framework:
11
+ *
12
+ * - alepha.state() for state management
13
+ * - alepha.inject() for dependency injection
14
+ * - alepha.emit() for event handling
15
+ * etc...
16
+ */
5
17
  export const useAlepha = (): Alepha => {
6
18
  const alepha = useContext(AlephaContext);
7
19
  if (!alepha) {
8
- throw new Error("useAlepha must be used within an AlephaContext.Provider");
20
+ throw new AlephaError(
21
+ "Hook 'useAlepha()' must be used within an AlephaContext.Provider",
22
+ );
9
23
  }
10
24
 
11
25
  return alepha;
@@ -4,11 +4,14 @@ import {
4
4
  LinkProvider,
5
5
  } from "@alepha/server-links";
6
6
  import { useInject } from "./useInject.ts";
7
- import { useStore } from "./useStore.ts";
8
7
 
8
+ /**
9
+ * Hook to get a virtual client for the specified scope.
10
+ *
11
+ * It's the React-hook version of `$client()`, from `AlephaServerLinks` module.
12
+ */
9
13
  export const useClient = <T extends object>(
10
- _scope?: ClientScope,
14
+ scope?: ClientScope,
11
15
  ): HttpVirtualClient<T> => {
12
- useStore("user" as any);
13
- return useInject(LinkProvider).client<T>();
16
+ return useInject(LinkProvider).client<T>(scope);
14
17
  };
@@ -2,8 +2,11 @@ import type { Service } from "@alepha/core";
2
2
  import { useMemo } from "react";
3
3
  import { useAlepha } from "./useAlepha.ts";
4
4
 
5
+ /**
6
+ * Hook to inject a service instance.
7
+ * It's a wrapper of `useAlepha().inject(service)` with a memoization.
8
+ */
5
9
  export const useInject = <T extends object>(service: Service<T>): T => {
6
10
  const alepha = useAlepha();
7
-
8
11
  return useMemo(() => alepha.inject(service), []);
9
12
  };
@@ -3,12 +3,9 @@ import { useEffect, useState } from "react";
3
3
  import { useAlepha } from "./useAlepha.ts";
4
4
  import { useRouter } from "./useRouter.ts";
5
5
 
6
- export interface UseQueryParamsHookOptions {
7
- format?: "base64" | "querystring";
8
- key?: string;
9
- push?: boolean;
10
- }
11
-
6
+ /**
7
+ * Not well tested. Use with caution.
8
+ */
12
9
  export const useQueryParams = <T extends TObject>(
13
10
  schema: T,
14
11
  options: UseQueryParamsHookOptions = {},
@@ -40,6 +37,12 @@ export const useQueryParams = <T extends TObject>(
40
37
 
41
38
  // ---------------------------------------------------------------------------------------------------------------------
42
39
 
40
+ export interface UseQueryParamsHookOptions {
41
+ format?: "base64" | "querystring";
42
+ key?: string;
43
+ push?: boolean;
44
+ }
45
+
43
46
  const encode = (alepha: Alepha, schema: TObject, data: any) => {
44
47
  return btoa(JSON.stringify(alepha.parse(schema, data)));
45
48
  };
@@ -1,33 +1,20 @@
1
- import { useContext, useMemo } from "react";
2
- import { RouterContext } from "../contexts/RouterContext.ts";
3
- import { RouterLayerContext } from "../contexts/RouterLayerContext.ts";
4
- import { PageDescriptorProvider } from "../providers/PageDescriptorProvider.ts";
5
- import { ReactBrowserProvider } from "../providers/ReactBrowserProvider.ts";
6
- import { RouterHookApi } from "./RouterHookApi.ts";
7
- import { useAlepha } from "./useAlepha.ts";
1
+ import { ReactRouter } from "../services/ReactRouter.ts";
2
+ import { useInject } from "./useInject.ts";
8
3
 
9
- export const useRouter = <T extends object>(): RouterHookApi<T> => {
10
- const alepha = useAlepha();
11
- const ctx = useContext(RouterContext);
12
- const layer = useContext(RouterLayerContext);
13
- if (!ctx || !layer) {
14
- throw new Error("useRouter must be used within a RouterProvider");
15
- }
16
-
17
- const pages = useMemo(() => {
18
- return alepha.inject(PageDescriptorProvider).getPages();
19
- }, []);
20
-
21
- return useMemo(
22
- () =>
23
- new RouterHookApi(
24
- pages,
25
- ctx.context,
26
- ctx.state,
27
- layer,
28
- alepha.inject(PageDescriptorProvider),
29
- alepha.isBrowser() ? alepha.inject(ReactBrowserProvider) : undefined,
30
- ),
31
- [layer],
32
- );
4
+ /**
5
+ * Use this hook to access the React Router instance.
6
+ *
7
+ * You can add a type parameter to specify the type of your application.
8
+ * This will allow you to use the router in a typesafe way.
9
+ *
10
+ * @example
11
+ * class App {
12
+ * home = $page();
13
+ * }
14
+ *
15
+ * const router = useRouter<App>();
16
+ * router.go("home"); // typesafe
17
+ */
18
+ export const useRouter = <T extends object = any>(): ReactRouter<T> => {
19
+ return useInject(ReactRouter<T>);
33
20
  };
@@ -1,15 +1,15 @@
1
1
  import { useEffect } from "react";
2
- import type {
3
- PageReactContext,
4
- RouterState,
5
- } from "../providers/PageDescriptorProvider.ts";
2
+ import type { ReactRouterState } from "../providers/ReactPageProvider.ts";
6
3
  import { useAlepha } from "./useAlepha.ts";
7
4
 
5
+ /**
6
+ * Subscribe to various router events.
7
+ */
8
8
  export const useRouterEvents = (
9
9
  opts: {
10
- onBegin?: (ev: { state: RouterState }) => void;
11
- onEnd?: (ev: { state: RouterState; context: PageReactContext }) => void;
12
- onError?: (ev: { state: RouterState; error: Error }) => void;
10
+ onBegin?: (ev: { state: ReactRouterState }) => void;
11
+ onEnd?: (ev: { state: ReactRouterState }) => void;
12
+ onError?: (ev: { state: ReactRouterState; error: Error }) => void;
13
13
  } = {},
14
14
  deps: any[] = [],
15
15
  ) => {
@@ -1,23 +1,11 @@
1
- import { useContext, useState } from "react";
2
- import { RouterContext } from "../contexts/RouterContext.ts";
3
- import { RouterLayerContext } from "../contexts/RouterLayerContext.ts";
4
- import type { RouterState } from "../providers/PageDescriptorProvider.ts";
5
- import { useRouterEvents } from "./useRouterEvents.ts";
6
-
7
- export const useRouterState = (): RouterState => {
8
- const router = useContext(RouterContext);
9
- const layer = useContext(RouterLayerContext);
10
- if (!router || !layer) {
11
- throw new Error(
12
- "useRouterState must be used within a RouterContext.Provider",
13
- );
1
+ import { AlephaError } from "@alepha/core";
2
+ import type { ReactRouterState } from "../providers/ReactPageProvider.ts";
3
+ import { useStore } from "./useStore.ts";
4
+
5
+ export const useRouterState = (): ReactRouterState => {
6
+ const [state] = useStore("react.router.state");
7
+ if (!state) {
8
+ throw new AlephaError("Missing react router state");
14
9
  }
15
-
16
- const [state, setState] = useState(router.state);
17
-
18
- useRouterEvents({
19
- onEnd: ({ state }) => setState({ ...state }),
20
- });
21
-
22
10
  return state;
23
11
  };
@@ -4,11 +4,7 @@ import {
4
4
  HttpClient,
5
5
  type RequestConfigSchema,
6
6
  } from "@alepha/server";
7
- import {
8
- type HttpClientLink,
9
- LinkProvider,
10
- type VirtualAction,
11
- } from "@alepha/server-links";
7
+ import { LinkProvider, type VirtualAction } from "@alepha/server-links";
12
8
  import { useEffect, useState } from "react";
13
9
  import { useAlepha } from "./useAlepha.ts";
14
10
  import { useInject } from "./useInject.ts";
@@ -19,7 +15,6 @@ export const useSchema = <TConfig extends RequestConfigSchema>(
19
15
  const name = action.name;
20
16
  const alepha = useAlepha();
21
17
  const httpClient = useInject(HttpClient);
22
- const linkProvider = useInject(LinkProvider);
23
18
  const [schema, setSchema] = useState<UseSchemaReturn<TConfig>>(
24
19
  ssrSchemaLoading(alepha, name) as UseSchemaReturn<TConfig>,
25
20
  );
@@ -34,7 +29,7 @@ export const useSchema = <TConfig extends RequestConfigSchema>(
34
29
  };
35
30
 
36
31
  httpClient
37
- .fetch(`${linkProvider.URL_LINKS}/${name}/schema`, {}, opts)
32
+ .fetch(`${LinkProvider.path.apiLinks}/${name}/schema`, {}, opts)
38
33
  .then((it) => setSchema(it.data as UseSchemaReturn<TConfig>));
39
34
  }, [name]);
40
35
 
@@ -54,26 +49,26 @@ export const ssrSchemaLoading = (alepha: Alepha, name: string) => {
54
49
  // server-side rendering (SSR) context
55
50
  if (!alepha.isBrowser()) {
56
51
  // get user links
57
- const links =
58
- alepha.context.get<{ links: HttpClientLink[] }>("links")?.links ?? [];
52
+ const linkProvider = alepha.inject(LinkProvider);
59
53
 
60
54
  // check if user can access the link
61
- const can = links.find((it) => it.name === name);
55
+ const can = linkProvider
56
+ .getServerLinks()
57
+ .find((link) => link.name === name);
62
58
 
63
59
  // yes!
64
60
  if (can) {
65
61
  // user-links have no schema, so we need to get it from the provider
66
- const schema = alepha
67
- .inject(LinkProvider)
68
- .links?.find((it) => it.name === name)?.schema;
62
+ const schema = linkProvider.links.find((it) => it.name === name)?.schema;
69
63
 
70
64
  // oh, we have a schema!
71
65
  if (schema) {
72
- // attach to user link, it will be used in the client during hydration :)
66
+ // attach to user link, it will be used in the client during hydration
73
67
  can.schema = schema;
74
68
  return schema;
75
69
  }
76
70
  }
71
+
77
72
  return { loading: true };
78
73
  }
79
74
 
@@ -81,7 +76,7 @@ export const ssrSchemaLoading = (alepha: Alepha, name: string) => {
81
76
  // check if we have the schema already loaded
82
77
  const schema = alepha
83
78
  .inject(LinkProvider)
84
- .links?.find((it) => it.name === name)?.schema;
79
+ .links.find((it) => it.name === name)?.schema;
85
80
 
86
81
  // yes!
87
82
  if (schema) {
@@ -31,13 +31,6 @@ export const useStore = <Key extends keyof State>(
31
31
  });
32
32
  }, []);
33
33
 
34
- if (!alepha.isBrowser()) {
35
- const value = alepha.context.get(key) as State[Key];
36
- if (value !== null) {
37
- return [value, (_: State[Key]) => {}] as const;
38
- }
39
- }
40
-
41
34
  return [
42
35
  state,
43
36
  (value: State[Key]) => {
@@ -2,17 +2,17 @@ import { $module } from "@alepha/core";
2
2
  import { AlephaServer } from "@alepha/server";
3
3
  import { AlephaServerLinks } from "@alepha/server-links";
4
4
  import { $page } from "./descriptors/$page.ts";
5
- import { BrowserRouterProvider } from "./providers/BrowserRouterProvider.ts";
6
- import { PageDescriptorProvider } from "./providers/PageDescriptorProvider.ts";
7
5
  import { ReactBrowserProvider } from "./providers/ReactBrowserProvider.ts";
8
- import { ReactBrowserRenderer } from "./providers/ReactBrowserRenderer.ts";
6
+ import { ReactBrowserRouterProvider } from "./providers/ReactBrowserRouterProvider.ts";
7
+ import { ReactPageProvider } from "./providers/ReactPageProvider.ts";
8
+ import { ReactRouter } from "./services/ReactRouter.ts";
9
9
 
10
10
  // ---------------------------------------------------------------------------------------------------------------------
11
11
 
12
12
  export * from "./index.shared.ts";
13
- export * from "./providers/BrowserRouterProvider.ts";
14
- export * from "./providers/PageDescriptorProvider.ts";
15
13
  export * from "./providers/ReactBrowserProvider.ts";
14
+ export * from "./providers/ReactBrowserRouterProvider.ts";
15
+ export * from "./providers/ReactPageProvider.ts";
16
16
 
17
17
  // ---------------------------------------------------------------------------------------------------------------------
18
18
 
@@ -20,17 +20,17 @@ export const AlephaReact = $module({
20
20
  name: "alepha.react",
21
21
  descriptors: [$page],
22
22
  services: [
23
- PageDescriptorProvider,
24
- ReactBrowserRenderer,
25
- BrowserRouterProvider,
23
+ ReactPageProvider,
24
+ ReactBrowserRouterProvider,
26
25
  ReactBrowserProvider,
26
+ ReactRouter,
27
27
  ],
28
28
  register: (alepha) =>
29
29
  alepha
30
30
  .with(AlephaServer)
31
31
  .with(AlephaServerLinks)
32
- .with(PageDescriptorProvider)
32
+ .with(ReactPageProvider)
33
33
  .with(ReactBrowserProvider)
34
- .with(BrowserRouterProvider)
35
- .with(ReactBrowserRenderer),
34
+ .with(ReactBrowserRouterProvider)
35
+ .with(ReactRouter),
36
36
  });
@@ -1,15 +1,13 @@
1
1
  export { default as ClientOnly } from "./components/ClientOnly.tsx";
2
2
  export { default as ErrorBoundary } from "./components/ErrorBoundary.tsx";
3
- export * from "./components/ErrorViewer.tsx";
3
+ export { default as ErrorViewer } from "./components/ErrorViewer.tsx";
4
4
  export { default as Link, type LinkProps } from "./components/Link.tsx";
5
5
  export { default as NestedView } from "./components/NestedView.tsx";
6
6
  export { default as NotFound } from "./components/NotFound.tsx";
7
7
  export * from "./contexts/AlephaContext.ts";
8
- export * from "./contexts/RouterContext.ts";
9
8
  export * from "./contexts/RouterLayerContext.ts";
10
9
  export * from "./descriptors/$page.ts";
11
10
  export * from "./errors/Redirection.ts";
12
- export * from "./hooks/RouterHookApi.ts";
13
11
  export * from "./hooks/useActive.ts";
14
12
  export * from "./hooks/useAlepha.ts";
15
13
  export * from "./hooks/useClient.ts";
@@ -20,3 +18,4 @@ export * from "./hooks/useRouterEvents.ts";
20
18
  export * from "./hooks/useRouterState.ts";
21
19
  export * from "./hooks/useSchema.ts";
22
20
  export * from "./hooks/useStore.ts";
21
+ export * from "./services/ReactRouter.ts";