@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.
- package/README.md +46 -0
- package/dist/index.browser.js +315 -320
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +496 -457
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +276 -258
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +274 -256
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +494 -460
- package/dist/index.js.map +1 -1
- package/package.json +13 -10
- package/src/components/NestedView.tsx +15 -13
- package/src/components/NotFound.tsx +1 -1
- package/src/descriptors/$page.ts +16 -4
- package/src/errors/Redirection.ts +8 -5
- package/src/hooks/useActive.ts +25 -34
- package/src/hooks/useAlepha.ts +16 -2
- package/src/hooks/useClient.ts +7 -4
- package/src/hooks/useInject.ts +4 -1
- package/src/hooks/useQueryParams.ts +9 -6
- package/src/hooks/useRouter.ts +18 -31
- package/src/hooks/useRouterEvents.ts +7 -7
- package/src/hooks/useRouterState.ts +8 -20
- package/src/hooks/useSchema.ts +10 -15
- package/src/hooks/useStore.ts +0 -7
- package/src/index.browser.ts +11 -11
- package/src/index.shared.ts +2 -3
- package/src/index.ts +21 -30
- package/src/providers/ReactBrowserProvider.ts +149 -65
- package/src/providers/ReactBrowserRouterProvider.ts +132 -0
- package/src/providers/{PageDescriptorProvider.ts → ReactPageProvider.ts} +84 -112
- package/src/providers/ReactServerProvider.ts +69 -74
- package/src/{hooks/RouterHookApi.ts → services/ReactRouter.ts} +44 -54
- package/src/contexts/RouterContext.ts +0 -14
- package/src/providers/BrowserRouterProvider.ts +0 -155
- package/src/providers/ReactBrowserRenderer.ts +0 -93
package/dist/index.browser.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { $env, $hook, $inject, $
|
|
1
|
+
import { $env, $hook, $inject, $module, Alepha, AlephaError, Descriptor, KIND, createDescriptor, t } from "@alepha/core";
|
|
2
2
|
import { AlephaServer, HttpClient } from "@alepha/server";
|
|
3
3
|
import { AlephaServerLinks, LinkProvider } from "@alepha/server-links";
|
|
4
|
+
import { DateTimeProvider } from "@alepha/datetime";
|
|
5
|
+
import { $logger } from "@alepha/logger";
|
|
6
|
+
import { createRoot, hydrateRoot } from "react-dom/client";
|
|
4
7
|
import { RouterProvider } from "@alepha/router";
|
|
5
8
|
import React, { StrictMode, createContext, createElement, useContext, useEffect, useMemo, useState } from "react";
|
|
6
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
-
import { createRoot, hydrateRoot } from "react-dom/client";
|
|
8
10
|
|
|
9
11
|
//#region src/descriptors/$page.ts
|
|
10
12
|
/**
|
|
@@ -30,6 +32,12 @@ var PageDescriptor = class extends Descriptor {
|
|
|
30
32
|
async render(options) {
|
|
31
33
|
throw new Error("render method is not implemented in this environment");
|
|
32
34
|
}
|
|
35
|
+
match(url) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
pathname(config) {
|
|
39
|
+
return this.options.path || "";
|
|
40
|
+
}
|
|
33
41
|
};
|
|
34
42
|
$page[KIND] = PageDescriptor;
|
|
35
43
|
|
|
@@ -53,7 +61,7 @@ function NotFoundPage(props) {
|
|
|
53
61
|
fontSize: "1rem",
|
|
54
62
|
marginBottom: "0.5rem"
|
|
55
63
|
},
|
|
56
|
-
children: "This page does not exist"
|
|
64
|
+
children: "404 - This page does not exist"
|
|
57
65
|
})
|
|
58
66
|
});
|
|
59
67
|
}
|
|
@@ -226,28 +234,54 @@ const ErrorViewerProduction = () => {
|
|
|
226
234
|
});
|
|
227
235
|
};
|
|
228
236
|
|
|
229
|
-
//#endregion
|
|
230
|
-
//#region src/contexts/RouterContext.ts
|
|
231
|
-
const RouterContext = createContext(void 0);
|
|
232
|
-
|
|
233
237
|
//#endregion
|
|
234
238
|
//#region src/contexts/RouterLayerContext.ts
|
|
235
239
|
const RouterLayerContext = createContext(void 0);
|
|
236
240
|
|
|
241
|
+
//#endregion
|
|
242
|
+
//#region src/errors/Redirection.ts
|
|
243
|
+
/**
|
|
244
|
+
* Used for Redirection during the page loading.
|
|
245
|
+
*
|
|
246
|
+
* Depends on the context, it can be thrown or just returned.
|
|
247
|
+
*/
|
|
248
|
+
var Redirection = class extends Error {
|
|
249
|
+
redirect;
|
|
250
|
+
constructor(redirect) {
|
|
251
|
+
super("Redirection");
|
|
252
|
+
this.redirect = redirect;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
|
|
237
256
|
//#endregion
|
|
238
257
|
//#region src/contexts/AlephaContext.ts
|
|
239
258
|
const AlephaContext = createContext(void 0);
|
|
240
259
|
|
|
241
260
|
//#endregion
|
|
242
261
|
//#region src/hooks/useAlepha.ts
|
|
262
|
+
/**
|
|
263
|
+
* Main Alepha hook.
|
|
264
|
+
*
|
|
265
|
+
* It provides access to the Alepha instance within a React component.
|
|
266
|
+
*
|
|
267
|
+
* With Alepha, you can access the core functionalities of the framework:
|
|
268
|
+
*
|
|
269
|
+
* - alepha.state() for state management
|
|
270
|
+
* - alepha.inject() for dependency injection
|
|
271
|
+
* - alepha.emit() for event handling
|
|
272
|
+
* etc...
|
|
273
|
+
*/
|
|
243
274
|
const useAlepha = () => {
|
|
244
275
|
const alepha = useContext(AlephaContext);
|
|
245
|
-
if (!alepha) throw new
|
|
276
|
+
if (!alepha) throw new AlephaError("Hook 'useAlepha()' must be used within an AlephaContext.Provider");
|
|
246
277
|
return alepha;
|
|
247
278
|
};
|
|
248
279
|
|
|
249
280
|
//#endregion
|
|
250
281
|
//#region src/hooks/useRouterEvents.ts
|
|
282
|
+
/**
|
|
283
|
+
* Subscribe to various router events.
|
|
284
|
+
*/
|
|
251
285
|
const useRouterEvents = (opts = {}, deps = []) => {
|
|
252
286
|
const alepha = useAlepha();
|
|
253
287
|
useEffect(() => {
|
|
@@ -320,19 +354,21 @@ var ErrorBoundary_default = ErrorBoundary;
|
|
|
320
354
|
* ```
|
|
321
355
|
*/
|
|
322
356
|
const NestedView = (props) => {
|
|
323
|
-
const app = useContext(RouterContext);
|
|
324
357
|
const layer = useContext(RouterLayerContext);
|
|
325
358
|
const index = layer?.index ?? 0;
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
359
|
+
const alepha = useAlepha();
|
|
360
|
+
const state = alepha.state("react.router.state");
|
|
361
|
+
if (!state) throw new Error("<NestedView/> must be used inside a RouterLayerContext.");
|
|
362
|
+
const [view, setView] = useState(state.layers[index]?.element);
|
|
363
|
+
useRouterEvents({ onEnd: ({ state: state$1 }) => {
|
|
364
|
+
if (!state$1.layers[index]?.cache) setView(state$1.layers[index]?.element);
|
|
365
|
+
} }, []);
|
|
332
366
|
const element = view ?? props.children ?? null;
|
|
333
367
|
return /* @__PURE__ */ jsx(ErrorBoundary_default, {
|
|
334
368
|
fallback: (error) => {
|
|
335
|
-
|
|
369
|
+
const result = state.onError(error, state);
|
|
370
|
+
if (result instanceof Redirection) return "Redirection inside ErrorBoundary is not allowed.";
|
|
371
|
+
return result;
|
|
336
372
|
},
|
|
337
373
|
children: element
|
|
338
374
|
});
|
|
@@ -340,19 +376,9 @@ const NestedView = (props) => {
|
|
|
340
376
|
var NestedView_default = NestedView;
|
|
341
377
|
|
|
342
378
|
//#endregion
|
|
343
|
-
//#region src/
|
|
344
|
-
var Redirection = class extends Error {
|
|
345
|
-
page;
|
|
346
|
-
constructor(page) {
|
|
347
|
-
super("Redirection");
|
|
348
|
-
this.page = page;
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
//#endregion
|
|
353
|
-
//#region src/providers/PageDescriptorProvider.ts
|
|
379
|
+
//#region src/providers/ReactPageProvider.ts
|
|
354
380
|
const envSchema$1 = t.object({ REACT_STRICT_MODE: t.boolean({ default: true }) });
|
|
355
|
-
var
|
|
381
|
+
var ReactPageProvider = class {
|
|
356
382
|
log = $logger();
|
|
357
383
|
env = $env(envSchema$1);
|
|
358
384
|
alepha = $inject(Alepha);
|
|
@@ -381,22 +407,21 @@ var PageDescriptorProvider = class {
|
|
|
381
407
|
return url.replace(/\/\/+/g, "/") || "/";
|
|
382
408
|
}
|
|
383
409
|
url(name, options = {}) {
|
|
384
|
-
return new URL(this.pathname(name, options), options.
|
|
410
|
+
return new URL(this.pathname(name, options), options.host ?? `http://localhost`);
|
|
385
411
|
}
|
|
386
|
-
root(state
|
|
387
|
-
const root = createElement(AlephaContext.Provider, { value: this.alepha }, createElement(
|
|
388
|
-
state,
|
|
389
|
-
context
|
|
390
|
-
} }, createElement(NestedView_default, {}, state.layers[0]?.element)));
|
|
412
|
+
root(state) {
|
|
413
|
+
const root = createElement(AlephaContext.Provider, { value: this.alepha }, createElement(NestedView_default, {}, state.layers[0]?.element));
|
|
391
414
|
if (this.env.REACT_STRICT_MODE) return createElement(StrictMode, {}, root);
|
|
392
415
|
return root;
|
|
393
416
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
417
|
+
/**
|
|
418
|
+
* Create a new RouterState based on a given route and request.
|
|
419
|
+
* This method resolves the layers for the route, applying any query and params schemas defined in the route.
|
|
420
|
+
* It also handles errors and redirects.
|
|
421
|
+
*/
|
|
422
|
+
async createLayers(route, state, previous = []) {
|
|
397
423
|
let context = {};
|
|
398
424
|
const stack = [{ route }];
|
|
399
|
-
request.onError = (error) => this.renderError(error);
|
|
400
425
|
let parent = route.parent;
|
|
401
426
|
while (parent) {
|
|
402
427
|
stack.unshift({ route: parent });
|
|
@@ -408,19 +433,18 @@ var PageDescriptorProvider = class {
|
|
|
408
433
|
const route$1 = it.route;
|
|
409
434
|
const config = {};
|
|
410
435
|
try {
|
|
411
|
-
config.query = route$1.schema?.query ? this.alepha.parse(route$1.schema.query,
|
|
436
|
+
config.query = route$1.schema?.query ? this.alepha.parse(route$1.schema.query, state.query) : {};
|
|
412
437
|
} catch (e) {
|
|
413
438
|
it.error = e;
|
|
414
439
|
break;
|
|
415
440
|
}
|
|
416
441
|
try {
|
|
417
|
-
config.params = route$1.schema?.params ? this.alepha.parse(route$1.schema.params,
|
|
442
|
+
config.params = route$1.schema?.params ? this.alepha.parse(route$1.schema.params, state.params) : {};
|
|
418
443
|
} catch (e) {
|
|
419
444
|
it.error = e;
|
|
420
445
|
break;
|
|
421
446
|
}
|
|
422
447
|
it.config = { ...config };
|
|
423
|
-
const previous = request.previous;
|
|
424
448
|
if (previous?.[i] && !forceRefresh && previous[i].name === route$1.name) {
|
|
425
449
|
const url = (str) => str ? str.replace(/\/\/+/g, "/") : "/";
|
|
426
450
|
const prev = JSON.stringify({
|
|
@@ -446,7 +470,7 @@ var PageDescriptorProvider = class {
|
|
|
446
470
|
if (!route$1.resolve) continue;
|
|
447
471
|
try {
|
|
448
472
|
const props = await route$1.resolve?.({
|
|
449
|
-
...
|
|
473
|
+
...state,
|
|
450
474
|
...config,
|
|
451
475
|
...context
|
|
452
476
|
}) ?? {};
|
|
@@ -456,11 +480,8 @@ var PageDescriptorProvider = class {
|
|
|
456
480
|
...props
|
|
457
481
|
};
|
|
458
482
|
} catch (e) {
|
|
459
|
-
if (e instanceof Redirection) return
|
|
460
|
-
|
|
461
|
-
search
|
|
462
|
-
});
|
|
463
|
-
this.log.error(e);
|
|
483
|
+
if (e instanceof Redirection) return { redirect: e.redirect };
|
|
484
|
+
this.log.error("Page resolver has failed", e);
|
|
464
485
|
it.error = e;
|
|
465
486
|
break;
|
|
466
487
|
}
|
|
@@ -476,69 +497,58 @@ var PageDescriptorProvider = class {
|
|
|
476
497
|
const path = acc.replace(/\/+/, "/");
|
|
477
498
|
const localErrorHandler = this.getErrorHandler(it.route);
|
|
478
499
|
if (localErrorHandler) {
|
|
479
|
-
const onErrorParent =
|
|
480
|
-
|
|
500
|
+
const onErrorParent = state.onError;
|
|
501
|
+
state.onError = (error, context$1) => {
|
|
481
502
|
const result = localErrorHandler(error, context$1);
|
|
482
503
|
if (result === void 0) return onErrorParent(error, context$1);
|
|
483
504
|
return result;
|
|
484
505
|
};
|
|
485
506
|
}
|
|
486
|
-
if (it.error) try {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
507
|
+
if (!it.error) try {
|
|
508
|
+
const element = await this.createElement(it.route, {
|
|
509
|
+
...props,
|
|
510
|
+
...context
|
|
511
|
+
});
|
|
512
|
+
state.layers.push({
|
|
513
|
+
name: it.route.name,
|
|
514
|
+
props,
|
|
515
|
+
part: it.route.path,
|
|
516
|
+
config: it.config,
|
|
517
|
+
element: this.renderView(i + 1, path, element, it.route),
|
|
518
|
+
index: i + 1,
|
|
519
|
+
path,
|
|
520
|
+
route: it.route,
|
|
521
|
+
cache: it.cache
|
|
492
522
|
});
|
|
493
|
-
|
|
494
|
-
|
|
523
|
+
} catch (e) {
|
|
524
|
+
it.error = e;
|
|
525
|
+
}
|
|
526
|
+
if (it.error) try {
|
|
527
|
+
let element = await state.onError(it.error, state);
|
|
528
|
+
if (element === void 0) throw it.error;
|
|
529
|
+
if (element instanceof Redirection) return { redirect: element.redirect };
|
|
530
|
+
if (element === null) element = this.renderError(it.error);
|
|
531
|
+
state.layers.push({
|
|
495
532
|
props,
|
|
496
533
|
error: it.error,
|
|
497
534
|
name: it.route.name,
|
|
498
535
|
part: it.route.path,
|
|
499
536
|
config: it.config,
|
|
500
|
-
element: this.renderView(i + 1, path, element
|
|
537
|
+
element: this.renderView(i + 1, path, element, it.route),
|
|
501
538
|
index: i + 1,
|
|
502
539
|
path,
|
|
503
540
|
route: it.route
|
|
504
541
|
});
|
|
505
542
|
break;
|
|
506
543
|
} catch (e) {
|
|
507
|
-
if (e instanceof Redirection) return
|
|
508
|
-
pathname,
|
|
509
|
-
search
|
|
510
|
-
});
|
|
544
|
+
if (e instanceof Redirection) return { redirect: e.redirect };
|
|
511
545
|
throw e;
|
|
512
546
|
}
|
|
513
|
-
const element = await this.createElement(it.route, {
|
|
514
|
-
...props,
|
|
515
|
-
...context
|
|
516
|
-
});
|
|
517
|
-
layers.push({
|
|
518
|
-
name: it.route.name,
|
|
519
|
-
props,
|
|
520
|
-
part: it.route.path,
|
|
521
|
-
config: it.config,
|
|
522
|
-
element: this.renderView(i + 1, path, element, it.route),
|
|
523
|
-
index: i + 1,
|
|
524
|
-
path,
|
|
525
|
-
route: it.route,
|
|
526
|
-
cache: it.cache
|
|
527
|
-
});
|
|
528
547
|
}
|
|
529
|
-
return {
|
|
530
|
-
layers,
|
|
531
|
-
pathname,
|
|
532
|
-
search
|
|
533
|
-
};
|
|
548
|
+
return { state };
|
|
534
549
|
}
|
|
535
|
-
createRedirectionLayer(
|
|
536
|
-
return {
|
|
537
|
-
layers: [],
|
|
538
|
-
redirect: typeof href === "string" ? href : this.href(href),
|
|
539
|
-
pathname: context.pathname,
|
|
540
|
-
search: context.search
|
|
541
|
-
};
|
|
550
|
+
createRedirectionLayer(redirect) {
|
|
551
|
+
return { redirect };
|
|
542
552
|
}
|
|
543
553
|
getErrorHandler(route) {
|
|
544
554
|
if (route.errorHandler) return route.errorHandler;
|
|
@@ -665,57 +675,43 @@ const isPageRoute = (it) => {
|
|
|
665
675
|
};
|
|
666
676
|
|
|
667
677
|
//#endregion
|
|
668
|
-
//#region src/providers/
|
|
669
|
-
var
|
|
678
|
+
//#region src/providers/ReactBrowserRouterProvider.ts
|
|
679
|
+
var ReactBrowserRouterProvider = class extends RouterProvider {
|
|
670
680
|
log = $logger();
|
|
671
681
|
alepha = $inject(Alepha);
|
|
672
|
-
|
|
682
|
+
pageApi = $inject(ReactPageProvider);
|
|
673
683
|
add(entry) {
|
|
674
|
-
this.
|
|
684
|
+
this.pageApi.add(entry);
|
|
675
685
|
}
|
|
676
686
|
configure = $hook({
|
|
677
687
|
on: "configure",
|
|
678
688
|
handler: async () => {
|
|
679
|
-
for (const page of this.
|
|
689
|
+
for (const page of this.pageApi.getPages()) if (page.component || page.lazy) this.push({
|
|
680
690
|
path: page.match,
|
|
681
691
|
page
|
|
682
692
|
});
|
|
683
693
|
}
|
|
684
694
|
});
|
|
685
|
-
async transition(url,
|
|
695
|
+
async transition(url, previous = []) {
|
|
686
696
|
const { pathname, search } = url;
|
|
687
|
-
const
|
|
688
|
-
pathname,
|
|
689
|
-
search,
|
|
690
|
-
layers: []
|
|
691
|
-
};
|
|
692
|
-
const context = {
|
|
697
|
+
const entry = {
|
|
693
698
|
url,
|
|
694
699
|
query: {},
|
|
695
700
|
params: {},
|
|
696
|
-
|
|
697
|
-
|
|
701
|
+
layers: [],
|
|
702
|
+
onError: () => null
|
|
698
703
|
};
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
context
|
|
702
|
-
});
|
|
704
|
+
const state = entry;
|
|
705
|
+
await this.alepha.emit("react:transition:begin", { state });
|
|
703
706
|
try {
|
|
704
|
-
const previous = options.previous;
|
|
705
707
|
const { route, params } = this.match(pathname);
|
|
706
708
|
const query = {};
|
|
707
709
|
if (search) for (const [key, value] of new URLSearchParams(search).entries()) query[key] = String(value);
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
context.previous = previous;
|
|
710
|
+
state.query = query;
|
|
711
|
+
state.params = params ?? {};
|
|
711
712
|
if (isPageRoute(route)) {
|
|
712
|
-
const
|
|
713
|
-
if (
|
|
714
|
-
redirect: result.redirect,
|
|
715
|
-
state,
|
|
716
|
-
context
|
|
717
|
-
};
|
|
718
|
-
state.layers = result.layers;
|
|
713
|
+
const { redirect } = await this.pageApi.createLayers(route.page, state, previous);
|
|
714
|
+
if (redirect) return redirect;
|
|
719
715
|
}
|
|
720
716
|
if (state.layers.length === 0) state.layers.push({
|
|
721
717
|
name: "not-found",
|
|
@@ -723,86 +719,92 @@ var BrowserRouterProvider = class extends RouterProvider {
|
|
|
723
719
|
index: 0,
|
|
724
720
|
path: "/"
|
|
725
721
|
});
|
|
726
|
-
await this.alepha.emit("react:transition:success", {
|
|
727
|
-
state,
|
|
728
|
-
context
|
|
729
|
-
});
|
|
722
|
+
await this.alepha.emit("react:transition:success", { state });
|
|
730
723
|
} catch (e) {
|
|
731
|
-
this.log.error(e);
|
|
724
|
+
this.log.error("Transition has failed", e);
|
|
732
725
|
state.layers = [{
|
|
733
726
|
name: "error",
|
|
734
|
-
element: this.
|
|
727
|
+
element: this.pageApi.renderError(e),
|
|
735
728
|
index: 0,
|
|
736
729
|
path: "/"
|
|
737
730
|
}];
|
|
738
731
|
await this.alepha.emit("react:transition:error", {
|
|
739
732
|
error: e,
|
|
740
|
-
state
|
|
741
|
-
context
|
|
733
|
+
state
|
|
742
734
|
});
|
|
743
735
|
}
|
|
744
|
-
if (
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
options.state.search = state.search;
|
|
736
|
+
if (previous) for (let i = 0; i < previous.length; i++) {
|
|
737
|
+
const layer = previous[i];
|
|
738
|
+
if (state.layers[i]?.name !== layer.name) this.pageApi.page(layer.name)?.onLeave?.();
|
|
748
739
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
if (state.layers[i]?.name !== layer.name) this.pageDescriptorProvider.page(layer.name)?.onLeave?.();
|
|
752
|
-
}
|
|
753
|
-
await this.alepha.emit("react:transition:end", {
|
|
754
|
-
state: options.state,
|
|
755
|
-
context
|
|
756
|
-
});
|
|
757
|
-
return {
|
|
758
|
-
context,
|
|
759
|
-
state
|
|
760
|
-
};
|
|
740
|
+
await this.alepha.emit("react:transition:end", { state });
|
|
741
|
+
this.alepha.state("react.router.state", state);
|
|
761
742
|
}
|
|
762
|
-
root(state
|
|
763
|
-
return this.
|
|
743
|
+
root(state) {
|
|
744
|
+
return this.pageApi.root(state);
|
|
764
745
|
}
|
|
765
746
|
};
|
|
766
747
|
|
|
767
748
|
//#endregion
|
|
768
749
|
//#region src/providers/ReactBrowserProvider.ts
|
|
750
|
+
const envSchema = t.object({ REACT_ROOT_ID: t.string({ default: "root" }) });
|
|
769
751
|
var ReactBrowserProvider = class {
|
|
752
|
+
env = $env(envSchema);
|
|
770
753
|
log = $logger();
|
|
771
754
|
client = $inject(LinkProvider);
|
|
772
755
|
alepha = $inject(Alepha);
|
|
773
|
-
router = $inject(
|
|
756
|
+
router = $inject(ReactBrowserRouterProvider);
|
|
757
|
+
dateTimeProvider = $inject(DateTimeProvider);
|
|
774
758
|
root;
|
|
759
|
+
options = { scrollRestoration: "top" };
|
|
760
|
+
getRootElement() {
|
|
761
|
+
const root = this.document.getElementById(this.env.REACT_ROOT_ID);
|
|
762
|
+
if (root) return root;
|
|
763
|
+
const div = this.document.createElement("div");
|
|
764
|
+
div.id = this.env.REACT_ROOT_ID;
|
|
765
|
+
this.document.body.prepend(div);
|
|
766
|
+
return div;
|
|
767
|
+
}
|
|
775
768
|
transitioning;
|
|
776
|
-
state
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
769
|
+
get state() {
|
|
770
|
+
return this.alepha.state("react.router.state");
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Accessor for Document DOM API.
|
|
774
|
+
*/
|
|
781
775
|
get document() {
|
|
782
776
|
return window.document;
|
|
783
777
|
}
|
|
778
|
+
/**
|
|
779
|
+
* Accessor for History DOM API.
|
|
780
|
+
*/
|
|
784
781
|
get history() {
|
|
785
782
|
return window.history;
|
|
786
783
|
}
|
|
784
|
+
/**
|
|
785
|
+
* Accessor for Location DOM API.
|
|
786
|
+
*/
|
|
787
787
|
get location() {
|
|
788
788
|
return window.location;
|
|
789
789
|
}
|
|
790
|
+
get base() {
|
|
791
|
+
const base = import.meta.env?.BASE_URL;
|
|
792
|
+
if (!base || base === "/") return "";
|
|
793
|
+
return base;
|
|
794
|
+
}
|
|
790
795
|
get url() {
|
|
791
|
-
|
|
792
|
-
if (
|
|
793
|
-
url = url.replace(import.meta.env?.BASE_URL, "");
|
|
794
|
-
if (!url.startsWith("/")) url = `/${url}`;
|
|
795
|
-
}
|
|
796
|
+
const url = this.location.pathname + this.location.search;
|
|
797
|
+
if (this.base) return url.replace(this.base, "");
|
|
796
798
|
return url;
|
|
797
799
|
}
|
|
798
|
-
pushState(
|
|
799
|
-
|
|
800
|
-
if (
|
|
801
|
-
|
|
802
|
-
else this.history.pushState({}, "", path);
|
|
800
|
+
pushState(path, replace) {
|
|
801
|
+
const url = this.base + path;
|
|
802
|
+
if (replace) this.history.replaceState({}, "", url);
|
|
803
|
+
else this.history.pushState({}, "", url);
|
|
803
804
|
}
|
|
804
805
|
async invalidate(props) {
|
|
805
806
|
const previous = [];
|
|
807
|
+
this.log.trace("Invalidating layers");
|
|
806
808
|
if (props) {
|
|
807
809
|
const [key] = Object.keys(props);
|
|
808
810
|
const value = props[key];
|
|
@@ -823,9 +825,16 @@ var ReactBrowserProvider = class {
|
|
|
823
825
|
await this.render({ previous });
|
|
824
826
|
}
|
|
825
827
|
async go(url, options = {}) {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
828
|
+
this.log.trace(`Going to ${url}`, {
|
|
829
|
+
url,
|
|
830
|
+
options
|
|
831
|
+
});
|
|
832
|
+
await this.render({
|
|
833
|
+
url,
|
|
834
|
+
previous: options.force ? [] : this.state.layers
|
|
835
|
+
});
|
|
836
|
+
if (this.state.url.pathname + this.state.url.search !== url) {
|
|
837
|
+
this.pushState(this.state.url.pathname + this.state.url.search);
|
|
829
838
|
return;
|
|
830
839
|
}
|
|
831
840
|
this.pushState(url, options.replace);
|
|
@@ -833,14 +842,20 @@ var ReactBrowserProvider = class {
|
|
|
833
842
|
async render(options = {}) {
|
|
834
843
|
const previous = options.previous ?? this.state.layers;
|
|
835
844
|
const url = options.url ?? this.url;
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
}
|
|
841
|
-
|
|
845
|
+
const start = this.dateTimeProvider.now();
|
|
846
|
+
this.transitioning = {
|
|
847
|
+
to: url,
|
|
848
|
+
from: this.state?.url.pathname
|
|
849
|
+
};
|
|
850
|
+
this.log.debug("Transitioning...", { to: url });
|
|
851
|
+
const redirect = await this.router.transition(new URL(`http://localhost${url}`), previous);
|
|
852
|
+
if (redirect) {
|
|
853
|
+
this.log.info("Redirecting to", { redirect });
|
|
854
|
+
return await this.render({ url: redirect });
|
|
855
|
+
}
|
|
856
|
+
const ms = this.dateTimeProvider.now().diff(start);
|
|
857
|
+
this.log.info(`Transition OK [${ms}ms]`, this.transitioning);
|
|
842
858
|
this.transitioning = void 0;
|
|
843
|
-
return result;
|
|
844
859
|
}
|
|
845
860
|
/**
|
|
846
861
|
* Get embedded layers from the server.
|
|
@@ -852,54 +867,25 @@ var ReactBrowserProvider = class {
|
|
|
852
867
|
console.error(error);
|
|
853
868
|
}
|
|
854
869
|
}
|
|
870
|
+
onTransitionEnd = $hook({
|
|
871
|
+
on: "react:transition:end",
|
|
872
|
+
handler: () => {
|
|
873
|
+
if (this.options.scrollRestoration === "top" && typeof window !== "undefined") {
|
|
874
|
+
this.log.trace("Restoring scroll position to top");
|
|
875
|
+
window.scrollTo(0, 0);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
});
|
|
855
879
|
ready = $hook({
|
|
856
880
|
on: "ready",
|
|
857
881
|
handler: async () => {
|
|
858
882
|
const hydration = this.getHydrationState();
|
|
859
883
|
const previous = hydration?.layers ?? [];
|
|
860
884
|
if (hydration) {
|
|
861
|
-
for (const [key, value] of Object.entries(hydration)) if (key !== "layers"
|
|
885
|
+
for (const [key, value] of Object.entries(hydration)) if (key !== "layers") this.alepha.state(key, value);
|
|
862
886
|
}
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
prefix: hydration.links.prefix
|
|
866
|
-
});
|
|
867
|
-
const { context } = await this.render({ previous });
|
|
868
|
-
await this.alepha.emit("react:browser:render", {
|
|
869
|
-
state: this.state,
|
|
870
|
-
context,
|
|
871
|
-
hydration
|
|
872
|
-
});
|
|
873
|
-
window.addEventListener("popstate", () => {
|
|
874
|
-
if (this.state.pathname === this.url) return;
|
|
875
|
-
this.render();
|
|
876
|
-
});
|
|
877
|
-
}
|
|
878
|
-
});
|
|
879
|
-
};
|
|
880
|
-
|
|
881
|
-
//#endregion
|
|
882
|
-
//#region src/providers/ReactBrowserRenderer.ts
|
|
883
|
-
const envSchema = t.object({ REACT_ROOT_ID: t.string({ default: "root" }) });
|
|
884
|
-
var ReactBrowserRenderer = class {
|
|
885
|
-
browserProvider = $inject(ReactBrowserProvider);
|
|
886
|
-
browserRouterProvider = $inject(BrowserRouterProvider);
|
|
887
|
-
env = $env(envSchema);
|
|
888
|
-
log = $logger();
|
|
889
|
-
root;
|
|
890
|
-
options = { scrollRestoration: "top" };
|
|
891
|
-
getRootElement() {
|
|
892
|
-
const root = this.browserProvider.document.getElementById(this.env.REACT_ROOT_ID);
|
|
893
|
-
if (root) return root;
|
|
894
|
-
const div = this.browserProvider.document.createElement("div");
|
|
895
|
-
div.id = this.env.REACT_ROOT_ID;
|
|
896
|
-
this.browserProvider.document.body.prepend(div);
|
|
897
|
-
return div;
|
|
898
|
-
}
|
|
899
|
-
ready = $hook({
|
|
900
|
-
on: "react:browser:render",
|
|
901
|
-
handler: async ({ state, context, hydration }) => {
|
|
902
|
-
const element = this.browserRouterProvider.root(state, context);
|
|
887
|
+
await this.render({ previous });
|
|
888
|
+
const element = this.router.root(this.state);
|
|
903
889
|
if (hydration?.layers) {
|
|
904
890
|
this.root = hydrateRoot(this.getRootElement(), element);
|
|
905
891
|
this.log.info("Hydrated root element");
|
|
@@ -908,38 +894,41 @@ var ReactBrowserRenderer = class {
|
|
|
908
894
|
this.root.render(element);
|
|
909
895
|
this.log.info("Created root element");
|
|
910
896
|
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
if (this.options.scrollRestoration === "top" && typeof window !== "undefined") window.scrollTo(0, 0);
|
|
897
|
+
window.addEventListener("popstate", () => {
|
|
898
|
+
if (this.base + this.state.url.pathname === this.location.pathname) return;
|
|
899
|
+
this.log.debug("Popstate event triggered - rendering new state", { url: this.location.pathname + this.location.search });
|
|
900
|
+
this.render();
|
|
901
|
+
});
|
|
917
902
|
}
|
|
918
903
|
});
|
|
919
904
|
};
|
|
920
905
|
|
|
921
906
|
//#endregion
|
|
922
|
-
//#region src/
|
|
923
|
-
var
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
this.state
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
this.
|
|
907
|
+
//#region src/services/ReactRouter.ts
|
|
908
|
+
var ReactRouter = class {
|
|
909
|
+
alepha = $inject(Alepha);
|
|
910
|
+
pageApi = $inject(ReactPageProvider);
|
|
911
|
+
get state() {
|
|
912
|
+
return this.alepha.state("react.router.state");
|
|
913
|
+
}
|
|
914
|
+
get pages() {
|
|
915
|
+
return this.pageApi.getPages();
|
|
916
|
+
}
|
|
917
|
+
get browser() {
|
|
918
|
+
if (this.alepha.isBrowser()) return this.alepha.inject(ReactBrowserProvider);
|
|
919
|
+
return void 0;
|
|
931
920
|
}
|
|
932
921
|
path(name, config = {}) {
|
|
933
922
|
return this.pageApi.pathname(name, {
|
|
934
923
|
params: {
|
|
935
|
-
...this.
|
|
924
|
+
...this.state.params,
|
|
936
925
|
...config.params
|
|
937
926
|
},
|
|
938
927
|
query: config.query
|
|
939
928
|
});
|
|
940
929
|
}
|
|
941
930
|
getURL() {
|
|
942
|
-
if (!this.browser) return this.
|
|
931
|
+
if (!this.browser) return this.state.url;
|
|
943
932
|
return new URL(this.location.href);
|
|
944
933
|
}
|
|
945
934
|
get location() {
|
|
@@ -950,11 +939,11 @@ var RouterHookApi = class {
|
|
|
950
939
|
return this.state;
|
|
951
940
|
}
|
|
952
941
|
get pathname() {
|
|
953
|
-
return this.state.pathname;
|
|
942
|
+
return this.state.url.pathname;
|
|
954
943
|
}
|
|
955
944
|
get query() {
|
|
956
945
|
const query = {};
|
|
957
|
-
for (const [key, value] of new URLSearchParams(this.state.search).entries()) query[key] = String(value);
|
|
946
|
+
for (const [key, value] of new URLSearchParams(this.state.url.search).entries()) query[key] = String(value);
|
|
958
947
|
return query;
|
|
959
948
|
}
|
|
960
949
|
async back() {
|
|
@@ -966,17 +955,6 @@ var RouterHookApi = class {
|
|
|
966
955
|
async invalidate(props) {
|
|
967
956
|
await this.browser?.invalidate(props);
|
|
968
957
|
}
|
|
969
|
-
/**
|
|
970
|
-
* Create a valid href for the given pathname.
|
|
971
|
-
*
|
|
972
|
-
* @param pathname
|
|
973
|
-
* @param layer
|
|
974
|
-
*/
|
|
975
|
-
createHref(pathname, layer = this.layer, options = {}) {
|
|
976
|
-
if (typeof pathname === "object") pathname = pathname.options.path ?? "";
|
|
977
|
-
if (options.params) for (const [key, value] of Object.entries(options.params)) pathname = pathname.replace(`:${key}`, String(value));
|
|
978
|
-
return pathname.startsWith("/") ? pathname : `${layer.path}/${pathname}`.replace(/\/\/+/g, "/");
|
|
979
|
-
}
|
|
980
958
|
async go(path, options) {
|
|
981
959
|
for (const page of this.pages) if (page.name === path) {
|
|
982
960
|
await this.browser?.go(this.path(path, options), options);
|
|
@@ -991,7 +969,7 @@ var RouterHookApi = class {
|
|
|
991
969
|
break;
|
|
992
970
|
}
|
|
993
971
|
return {
|
|
994
|
-
href,
|
|
972
|
+
href: this.base(href),
|
|
995
973
|
onClick: (ev) => {
|
|
996
974
|
ev.stopPropagation();
|
|
997
975
|
ev.preventDefault();
|
|
@@ -999,6 +977,11 @@ var RouterHookApi = class {
|
|
|
999
977
|
}
|
|
1000
978
|
};
|
|
1001
979
|
}
|
|
980
|
+
base(path) {
|
|
981
|
+
const base = import.meta.env?.BASE_URL;
|
|
982
|
+
if (!base || base === "/") return path;
|
|
983
|
+
return base + path;
|
|
984
|
+
}
|
|
1002
985
|
/**
|
|
1003
986
|
* Set query params.
|
|
1004
987
|
*
|
|
@@ -1014,17 +997,35 @@ var RouterHookApi = class {
|
|
|
1014
997
|
}
|
|
1015
998
|
};
|
|
1016
999
|
|
|
1000
|
+
//#endregion
|
|
1001
|
+
//#region src/hooks/useInject.ts
|
|
1002
|
+
/**
|
|
1003
|
+
* Hook to inject a service instance.
|
|
1004
|
+
* It's a wrapper of `useAlepha().inject(service)` with a memoization.
|
|
1005
|
+
*/
|
|
1006
|
+
const useInject = (service) => {
|
|
1007
|
+
const alepha = useAlepha();
|
|
1008
|
+
return useMemo(() => alepha.inject(service), []);
|
|
1009
|
+
};
|
|
1010
|
+
|
|
1017
1011
|
//#endregion
|
|
1018
1012
|
//#region src/hooks/useRouter.ts
|
|
1013
|
+
/**
|
|
1014
|
+
* Use this hook to access the React Router instance.
|
|
1015
|
+
*
|
|
1016
|
+
* You can add a type parameter to specify the type of your application.
|
|
1017
|
+
* This will allow you to use the router in a typesafe way.
|
|
1018
|
+
*
|
|
1019
|
+
* @example
|
|
1020
|
+
* class App {
|
|
1021
|
+
* home = $page();
|
|
1022
|
+
* }
|
|
1023
|
+
*
|
|
1024
|
+
* const router = useRouter<App>();
|
|
1025
|
+
* router.go("home"); // typesafe
|
|
1026
|
+
*/
|
|
1019
1027
|
const useRouter = () => {
|
|
1020
|
-
|
|
1021
|
-
const ctx = useContext(RouterContext);
|
|
1022
|
-
const layer = useContext(RouterLayerContext);
|
|
1023
|
-
if (!ctx || !layer) throw new Error("useRouter must be used within a RouterProvider");
|
|
1024
|
-
const pages = useMemo(() => {
|
|
1025
|
-
return alepha.inject(PageDescriptorProvider).getPages();
|
|
1026
|
-
}, []);
|
|
1027
|
-
return useMemo(() => new RouterHookApi(pages, ctx.context, ctx.state, layer, alepha.inject(PageDescriptorProvider), alepha.isBrowser() ? alepha.inject(ReactBrowserProvider) : void 0), [layer]);
|
|
1028
|
+
return useInject(ReactRouter);
|
|
1028
1029
|
};
|
|
1029
1030
|
|
|
1030
1031
|
//#endregion
|
|
@@ -1040,46 +1041,6 @@ const Link = (props) => {
|
|
|
1040
1041
|
};
|
|
1041
1042
|
var Link_default = Link;
|
|
1042
1043
|
|
|
1043
|
-
//#endregion
|
|
1044
|
-
//#region src/hooks/useActive.ts
|
|
1045
|
-
const useActive = (path) => {
|
|
1046
|
-
const router = useRouter();
|
|
1047
|
-
const ctx = useContext(RouterContext);
|
|
1048
|
-
const layer = useContext(RouterLayerContext);
|
|
1049
|
-
if (!ctx || !layer) throw new Error("useRouter must be used within a RouterProvider");
|
|
1050
|
-
const [current, setCurrent] = useState(ctx.state.pathname);
|
|
1051
|
-
const href = useMemo(() => router.createHref(path ?? "", layer), [path, layer]);
|
|
1052
|
-
const [isPending, setPending] = useState(false);
|
|
1053
|
-
const isActive = current === href || current === `${href}/` || `${current}/` === href;
|
|
1054
|
-
useRouterEvents({ onEnd: ({ state }) => {
|
|
1055
|
-
path && setCurrent(state.pathname);
|
|
1056
|
-
} }, [path]);
|
|
1057
|
-
return {
|
|
1058
|
-
isPending,
|
|
1059
|
-
isActive,
|
|
1060
|
-
anchorProps: {
|
|
1061
|
-
href,
|
|
1062
|
-
onClick: (ev) => {
|
|
1063
|
-
ev?.stopPropagation();
|
|
1064
|
-
ev?.preventDefault();
|
|
1065
|
-
if (isActive) return;
|
|
1066
|
-
if (isPending) return;
|
|
1067
|
-
setPending(true);
|
|
1068
|
-
router.go(href).then(() => {
|
|
1069
|
-
setPending(false);
|
|
1070
|
-
});
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
};
|
|
1074
|
-
};
|
|
1075
|
-
|
|
1076
|
-
//#endregion
|
|
1077
|
-
//#region src/hooks/useInject.ts
|
|
1078
|
-
const useInject = (service) => {
|
|
1079
|
-
const alepha = useAlepha();
|
|
1080
|
-
return useMemo(() => alepha.inject(service), []);
|
|
1081
|
-
};
|
|
1082
|
-
|
|
1083
1044
|
//#endregion
|
|
1084
1045
|
//#region src/hooks/useStore.ts
|
|
1085
1046
|
/**
|
|
@@ -1097,24 +1058,70 @@ const useStore = (key, defaultValue) => {
|
|
|
1097
1058
|
if (ev.key === key) setState(ev.value);
|
|
1098
1059
|
});
|
|
1099
1060
|
}, []);
|
|
1100
|
-
if (!alepha.isBrowser()) {
|
|
1101
|
-
const value = alepha.context.get(key);
|
|
1102
|
-
if (value !== null) return [value, (_) => {}];
|
|
1103
|
-
}
|
|
1104
1061
|
return [state, (value) => {
|
|
1105
1062
|
alepha.state(key, value);
|
|
1106
1063
|
}];
|
|
1107
1064
|
};
|
|
1108
1065
|
|
|
1066
|
+
//#endregion
|
|
1067
|
+
//#region src/hooks/useRouterState.ts
|
|
1068
|
+
const useRouterState = () => {
|
|
1069
|
+
const [state] = useStore("react.router.state");
|
|
1070
|
+
if (!state) throw new AlephaError("Missing react router state");
|
|
1071
|
+
return state;
|
|
1072
|
+
};
|
|
1073
|
+
|
|
1074
|
+
//#endregion
|
|
1075
|
+
//#region src/hooks/useActive.ts
|
|
1076
|
+
const useActive = (args) => {
|
|
1077
|
+
const router = useRouter();
|
|
1078
|
+
const [isPending, setPending] = useState(false);
|
|
1079
|
+
const state = useRouterState();
|
|
1080
|
+
const current = state.url.pathname;
|
|
1081
|
+
const options = typeof args === "string" ? { href: args } : {
|
|
1082
|
+
...args,
|
|
1083
|
+
href: args.href
|
|
1084
|
+
};
|
|
1085
|
+
const href = options.href;
|
|
1086
|
+
let isActive = current === href || current === `${href}/` || `${current}/` === href;
|
|
1087
|
+
if (options.startWith && !isActive) isActive = current.startsWith(href);
|
|
1088
|
+
return {
|
|
1089
|
+
isPending,
|
|
1090
|
+
isActive,
|
|
1091
|
+
anchorProps: {
|
|
1092
|
+
href: router.base(href),
|
|
1093
|
+
onClick: async (ev) => {
|
|
1094
|
+
ev?.stopPropagation();
|
|
1095
|
+
ev?.preventDefault();
|
|
1096
|
+
if (isActive) return;
|
|
1097
|
+
if (isPending) return;
|
|
1098
|
+
setPending(true);
|
|
1099
|
+
try {
|
|
1100
|
+
await router.go(href);
|
|
1101
|
+
} finally {
|
|
1102
|
+
setPending(false);
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
};
|
|
1107
|
+
};
|
|
1108
|
+
|
|
1109
1109
|
//#endregion
|
|
1110
1110
|
//#region src/hooks/useClient.ts
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1111
|
+
/**
|
|
1112
|
+
* Hook to get a virtual client for the specified scope.
|
|
1113
|
+
*
|
|
1114
|
+
* It's the React-hook version of `$client()`, from `AlephaServerLinks` module.
|
|
1115
|
+
*/
|
|
1116
|
+
const useClient = (scope) => {
|
|
1117
|
+
return useInject(LinkProvider).client(scope);
|
|
1114
1118
|
};
|
|
1115
1119
|
|
|
1116
1120
|
//#endregion
|
|
1117
1121
|
//#region src/hooks/useQueryParams.ts
|
|
1122
|
+
/**
|
|
1123
|
+
* Not well tested. Use with caution.
|
|
1124
|
+
*/
|
|
1118
1125
|
const useQueryParams = (schema, options = {}) => {
|
|
1119
1126
|
const alepha = useAlepha();
|
|
1120
1127
|
const key = options.key ?? "q";
|
|
@@ -1145,29 +1152,17 @@ const decode = (alepha, schema, data) => {
|
|
|
1145
1152
|
}
|
|
1146
1153
|
};
|
|
1147
1154
|
|
|
1148
|
-
//#endregion
|
|
1149
|
-
//#region src/hooks/useRouterState.ts
|
|
1150
|
-
const useRouterState = () => {
|
|
1151
|
-
const router = useContext(RouterContext);
|
|
1152
|
-
const layer = useContext(RouterLayerContext);
|
|
1153
|
-
if (!router || !layer) throw new Error("useRouterState must be used within a RouterContext.Provider");
|
|
1154
|
-
const [state, setState] = useState(router.state);
|
|
1155
|
-
useRouterEvents({ onEnd: ({ state: state$1 }) => setState({ ...state$1 }) });
|
|
1156
|
-
return state;
|
|
1157
|
-
};
|
|
1158
|
-
|
|
1159
1155
|
//#endregion
|
|
1160
1156
|
//#region src/hooks/useSchema.ts
|
|
1161
1157
|
const useSchema = (action) => {
|
|
1162
1158
|
const name = action.name;
|
|
1163
1159
|
const alepha = useAlepha();
|
|
1164
1160
|
const httpClient = useInject(HttpClient);
|
|
1165
|
-
const linkProvider = useInject(LinkProvider);
|
|
1166
1161
|
const [schema, setSchema] = useState(ssrSchemaLoading(alepha, name));
|
|
1167
1162
|
useEffect(() => {
|
|
1168
1163
|
if (!schema.loading) return;
|
|
1169
1164
|
const opts = { cache: true };
|
|
1170
|
-
httpClient.fetch(`${
|
|
1165
|
+
httpClient.fetch(`${LinkProvider.path.apiLinks}/${name}/schema`, {}, opts).then((it) => setSchema(it.data));
|
|
1171
1166
|
}, [name]);
|
|
1172
1167
|
return schema;
|
|
1173
1168
|
};
|
|
@@ -1176,10 +1171,10 @@ const useSchema = (action) => {
|
|
|
1176
1171
|
*/
|
|
1177
1172
|
const ssrSchemaLoading = (alepha, name) => {
|
|
1178
1173
|
if (!alepha.isBrowser()) {
|
|
1179
|
-
const
|
|
1180
|
-
const can =
|
|
1174
|
+
const linkProvider = alepha.inject(LinkProvider);
|
|
1175
|
+
const can = linkProvider.getServerLinks().find((link) => link.name === name);
|
|
1181
1176
|
if (can) {
|
|
1182
|
-
const schema$1 =
|
|
1177
|
+
const schema$1 = linkProvider.links.find((it) => it.name === name)?.schema;
|
|
1183
1178
|
if (schema$1) {
|
|
1184
1179
|
can.schema = schema$1;
|
|
1185
1180
|
return schema$1;
|
|
@@ -1187,7 +1182,7 @@ const ssrSchemaLoading = (alepha, name) => {
|
|
|
1187
1182
|
}
|
|
1188
1183
|
return { loading: true };
|
|
1189
1184
|
}
|
|
1190
|
-
const schema = alepha.inject(LinkProvider).links
|
|
1185
|
+
const schema = alepha.inject(LinkProvider).links.find((it) => it.name === name)?.schema;
|
|
1191
1186
|
if (schema) return schema;
|
|
1192
1187
|
return { loading: true };
|
|
1193
1188
|
};
|
|
@@ -1198,14 +1193,14 @@ const AlephaReact = $module({
|
|
|
1198
1193
|
name: "alepha.react",
|
|
1199
1194
|
descriptors: [$page],
|
|
1200
1195
|
services: [
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1196
|
+
ReactPageProvider,
|
|
1197
|
+
ReactBrowserRouterProvider,
|
|
1198
|
+
ReactBrowserProvider,
|
|
1199
|
+
ReactRouter
|
|
1205
1200
|
],
|
|
1206
|
-
register: (alepha) => alepha.with(AlephaServer).with(AlephaServerLinks).with(
|
|
1201
|
+
register: (alepha) => alepha.with(AlephaServer).with(AlephaServerLinks).with(ReactPageProvider).with(ReactBrowserProvider).with(ReactBrowserRouterProvider).with(ReactRouter)
|
|
1207
1202
|
});
|
|
1208
1203
|
|
|
1209
1204
|
//#endregion
|
|
1210
|
-
export { $page, AlephaContext, AlephaReact,
|
|
1205
|
+
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, PageDescriptor, ReactBrowserProvider, ReactBrowserRouterProvider, ReactPageProvider, ReactRouter, Redirection, RouterLayerContext, isPageRoute, ssrSchemaLoading, useActive, useAlepha, useClient, useInject, useQueryParams, useRouter, useRouterEvents, useRouterState, useSchema, useStore };
|
|
1211
1206
|
//# sourceMappingURL=index.browser.js.map
|