@alepha/react 0.6.2 → 0.6.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 +1 -28
- package/dist/index.browser.cjs +20 -23
- package/dist/index.browser.cjs.map +1 -0
- package/dist/index.browser.js +8 -7
- package/dist/index.browser.js.map +1 -0
- package/dist/index.cjs +234 -542
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +218 -682
- package/dist/index.js +219 -522
- package/dist/index.js.map +1 -0
- package/dist/{useAuth-B9ypF48n.cjs → useActive-BGtt_RNQ.cjs} +310 -475
- package/dist/useActive-BGtt_RNQ.cjs.map +1 -0
- package/dist/{useAuth-Ps01oe8e.js → useActive-QkvcaSmu.js} +309 -471
- package/dist/useActive-QkvcaSmu.js.map +1 -0
- package/package.json +12 -10
- package/src/components/Link.tsx +35 -0
- package/src/components/NestedView.tsx +36 -0
- package/src/contexts/RouterContext.ts +18 -0
- package/src/contexts/RouterLayerContext.ts +10 -0
- package/src/descriptors/$page.ts +143 -0
- package/src/errors/RedirectionError.ts +7 -0
- package/src/hooks/RouterHookApi.ts +156 -0
- package/src/hooks/useActive.ts +57 -0
- package/src/hooks/useClient.ts +6 -0
- package/src/hooks/useInject.ts +14 -0
- package/src/hooks/useQueryParams.ts +59 -0
- package/src/hooks/useRouter.ts +25 -0
- package/src/hooks/useRouterEvents.ts +43 -0
- package/src/hooks/useRouterState.ts +23 -0
- package/src/index.browser.ts +21 -0
- package/src/index.shared.ts +15 -0
- package/src/index.ts +48 -0
- package/src/providers/BrowserHeadProvider.ts +43 -0
- package/src/providers/BrowserRouterProvider.ts +146 -0
- package/src/providers/PageDescriptorProvider.ts +534 -0
- package/src/providers/ReactBrowserProvider.ts +223 -0
- package/src/providers/ReactServerProvider.ts +278 -0
- package/src/providers/ServerHeadProvider.ts +91 -0
|
@@ -1,43 +1,49 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var core = require('@alepha/core');
|
|
4
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
4
|
var React = require('react');
|
|
6
5
|
var server = require('@alepha/server');
|
|
6
|
+
var core = require('@alepha/core');
|
|
7
7
|
var client = require('react-dom/client');
|
|
8
|
-
var
|
|
8
|
+
var router = require('@alepha/router');
|
|
9
9
|
|
|
10
|
-
const KEY = "
|
|
11
|
-
const $
|
|
10
|
+
const KEY = "PAGE";
|
|
11
|
+
const $page = (options) => {
|
|
12
12
|
core.__descriptor(KEY);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
if (options.children) {
|
|
14
|
+
for (const child of options.children) {
|
|
15
|
+
child.options.parent = {
|
|
16
|
+
options
|
|
17
|
+
};
|
|
18
18
|
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
}
|
|
20
|
+
if (options.parent) {
|
|
21
|
+
options.parent.options.children ??= [];
|
|
22
|
+
options.parent.options.children.push({
|
|
23
|
+
options
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
26
|
return {
|
|
27
|
-
[core.KIND]:
|
|
27
|
+
[core.KIND]: KEY,
|
|
28
28
|
options,
|
|
29
29
|
render: () => {
|
|
30
|
-
throw new core.NotImplementedError(
|
|
30
|
+
throw new core.NotImplementedError(KEY);
|
|
31
31
|
},
|
|
32
32
|
go: () => {
|
|
33
|
-
throw new core.NotImplementedError(
|
|
33
|
+
throw new core.NotImplementedError(KEY);
|
|
34
34
|
},
|
|
35
35
|
createAnchorProps: () => {
|
|
36
|
-
throw new core.NotImplementedError(
|
|
36
|
+
throw new core.NotImplementedError(KEY);
|
|
37
|
+
},
|
|
38
|
+
can: () => {
|
|
39
|
+
if (options.can) {
|
|
40
|
+
return options.can();
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
37
43
|
}
|
|
38
44
|
};
|
|
39
45
|
};
|
|
40
|
-
$page[core.KIND] =
|
|
46
|
+
$page[core.KIND] = KEY;
|
|
41
47
|
|
|
42
48
|
const RouterContext = React.createContext(
|
|
43
49
|
void 0
|
|
@@ -54,7 +60,7 @@ const NestedView = (props) => {
|
|
|
54
60
|
);
|
|
55
61
|
React.useEffect(() => {
|
|
56
62
|
if (app?.alepha.isBrowser()) {
|
|
57
|
-
return app?.
|
|
63
|
+
return app?.events.on("end", (state) => {
|
|
58
64
|
setView(state.layers[index]?.element);
|
|
59
65
|
});
|
|
60
66
|
}
|
|
@@ -69,159 +75,37 @@ class RedirectionError extends Error {
|
|
|
69
75
|
}
|
|
70
76
|
}
|
|
71
77
|
|
|
72
|
-
class
|
|
78
|
+
class PageDescriptorProvider {
|
|
73
79
|
log = core.$logger();
|
|
74
80
|
alepha = core.$inject(core.Alepha);
|
|
75
81
|
pages = [];
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
*
|
|
80
|
-
* @param name - Page name
|
|
81
|
-
* @return PageRoute
|
|
82
|
-
*/
|
|
82
|
+
getPages() {
|
|
83
|
+
return this.pages;
|
|
84
|
+
}
|
|
83
85
|
page(name) {
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
for (const page of this.pages) {
|
|
87
|
+
if (page.name === name) {
|
|
88
|
+
return page;
|
|
89
|
+
}
|
|
87
90
|
}
|
|
88
|
-
|
|
91
|
+
throw new Error(`Page ${name} not found`);
|
|
89
92
|
}
|
|
90
|
-
|
|
91
|
-
*
|
|
92
|
-
*/
|
|
93
|
-
root(state, context = {}) {
|
|
93
|
+
root(state, context = {}, events) {
|
|
94
94
|
return React.createElement(
|
|
95
95
|
RouterContext.Provider,
|
|
96
96
|
{
|
|
97
97
|
value: {
|
|
98
|
-
state,
|
|
99
|
-
router: this,
|
|
100
98
|
alepha: this.alepha,
|
|
101
|
-
|
|
99
|
+
state,
|
|
100
|
+
context,
|
|
101
|
+
events: events ?? new core.EventEmitter()
|
|
102
102
|
}
|
|
103
103
|
},
|
|
104
|
-
state.layers[0]?.element
|
|
104
|
+
React.createElement(NestedView, {}, state.layers[0]?.element)
|
|
105
105
|
);
|
|
106
106
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
* @param url
|
|
110
|
-
* @param options
|
|
111
|
-
*/
|
|
112
|
-
async render(url, options = {}) {
|
|
113
|
-
const [pathname, search = ""] = url.split("?");
|
|
114
|
-
const state = {
|
|
115
|
-
pathname,
|
|
116
|
-
search,
|
|
117
|
-
layers: [],
|
|
118
|
-
context: {}
|
|
119
|
-
};
|
|
120
|
-
await this.emit("begin", void 0);
|
|
121
|
-
try {
|
|
122
|
-
let layers = await this.match(url, options, state.context);
|
|
123
|
-
if (layers.length === 0) {
|
|
124
|
-
if (this.notFoundPageRoute) {
|
|
125
|
-
layers = await this.createLayers(url, this.notFoundPageRoute);
|
|
126
|
-
} else {
|
|
127
|
-
layers.push({
|
|
128
|
-
name: "not-found",
|
|
129
|
-
element: "Not Found",
|
|
130
|
-
index: 0,
|
|
131
|
-
path: "/"
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
state.layers = layers;
|
|
136
|
-
await this.emit("success", void 0);
|
|
137
|
-
} catch (e) {
|
|
138
|
-
if (e instanceof RedirectionError) {
|
|
139
|
-
return {
|
|
140
|
-
element: null,
|
|
141
|
-
layers: [],
|
|
142
|
-
redirect: typeof e.page === "string" ? e.page : this.href(e.page),
|
|
143
|
-
context: state.context
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
this.log.error(e);
|
|
147
|
-
state.layers = [
|
|
148
|
-
{
|
|
149
|
-
name: "error",
|
|
150
|
-
element: this.renderError(e),
|
|
151
|
-
index: 0,
|
|
152
|
-
path: "/"
|
|
153
|
-
}
|
|
154
|
-
];
|
|
155
|
-
await this.emit("error", e);
|
|
156
|
-
}
|
|
157
|
-
if (options.state) {
|
|
158
|
-
options.state.layers = state.layers;
|
|
159
|
-
options.state.pathname = state.pathname;
|
|
160
|
-
options.state.search = state.search;
|
|
161
|
-
options.state.context = state.context;
|
|
162
|
-
await this.emit("end", options.state);
|
|
163
|
-
return {
|
|
164
|
-
element: this.root(options.state, options.args),
|
|
165
|
-
layers: options.state.layers,
|
|
166
|
-
context: state.context
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
await this.emit("end", state);
|
|
170
|
-
return {
|
|
171
|
-
element: this.root(state, options.args),
|
|
172
|
-
layers: state.layers,
|
|
173
|
-
context: state.context
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
*
|
|
178
|
-
* @param url
|
|
179
|
-
* @param options
|
|
180
|
-
* @param context
|
|
181
|
-
* @protected
|
|
182
|
-
*/
|
|
183
|
-
async match(url, options = {}, context = {}) {
|
|
184
|
-
const pages = this.pages;
|
|
185
|
-
const previous = options.previous;
|
|
186
|
-
const [pathname, search] = url.split("?");
|
|
187
|
-
for (const route of pages) {
|
|
188
|
-
if (route.children?.find((it) => !it.path || it.path === "/")) continue;
|
|
189
|
-
if (!route.match) continue;
|
|
190
|
-
const match2 = route.match.exec(pathname);
|
|
191
|
-
if (match2) {
|
|
192
|
-
const params = match2.params ?? {};
|
|
193
|
-
const query = {};
|
|
194
|
-
if (search) {
|
|
195
|
-
for (const [key, value] of new URLSearchParams(search).entries()) {
|
|
196
|
-
query[key] = String(value);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return await this.createLayers(
|
|
200
|
-
url,
|
|
201
|
-
route,
|
|
202
|
-
params,
|
|
203
|
-
query,
|
|
204
|
-
previous,
|
|
205
|
-
options.args,
|
|
206
|
-
context
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return [];
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Create layers for the given route.
|
|
214
|
-
*
|
|
215
|
-
* @param url
|
|
216
|
-
* @param route
|
|
217
|
-
* @param params
|
|
218
|
-
* @param query
|
|
219
|
-
* @param previous
|
|
220
|
-
* @param args
|
|
221
|
-
* @param renderContext
|
|
222
|
-
* @protected
|
|
223
|
-
*/
|
|
224
|
-
async createLayers(url, route, params = {}, query = {}, previous = [], args, renderContext) {
|
|
107
|
+
async createLayers(route, request) {
|
|
108
|
+
const { pathname, search } = request.url;
|
|
225
109
|
const layers = [];
|
|
226
110
|
let context = {};
|
|
227
111
|
const stack = [{ route }];
|
|
@@ -236,13 +120,13 @@ class Router extends core.EventEmitter {
|
|
|
236
120
|
const route2 = it.route;
|
|
237
121
|
const config = {};
|
|
238
122
|
try {
|
|
239
|
-
config.query = route2.schema?.query ? this.alepha.parse(route2.schema.query, query) : query;
|
|
123
|
+
config.query = route2.schema?.query ? this.alepha.parse(route2.schema.query, request.query) : request.query;
|
|
240
124
|
} catch (e) {
|
|
241
125
|
it.error = e;
|
|
242
126
|
break;
|
|
243
127
|
}
|
|
244
128
|
try {
|
|
245
|
-
config.params = route2.schema?.params ? this.alepha.parse(route2.schema.params, params) : params;
|
|
129
|
+
config.params = route2.schema?.params ? this.alepha.parse(route2.schema.params, request.params) : request.params;
|
|
246
130
|
} catch (e) {
|
|
247
131
|
it.error = e;
|
|
248
132
|
break;
|
|
@@ -253,14 +137,15 @@ class Router extends core.EventEmitter {
|
|
|
253
137
|
if (!route2.resolve) {
|
|
254
138
|
continue;
|
|
255
139
|
}
|
|
140
|
+
const previous = request.previous;
|
|
256
141
|
if (previous?.[i] && !forceRefresh && previous[i].name === route2.name) {
|
|
257
|
-
const
|
|
142
|
+
const url = (str) => str ? str.replace(/\/\/+/g, "/") : "/";
|
|
258
143
|
const prev = JSON.stringify({
|
|
259
|
-
part:
|
|
144
|
+
part: url(previous[i].part),
|
|
260
145
|
params: previous[i].config?.params ?? {}
|
|
261
146
|
});
|
|
262
147
|
const curr = JSON.stringify({
|
|
263
|
-
part:
|
|
148
|
+
part: url(route2.path),
|
|
264
149
|
params: config.params ?? {}
|
|
265
150
|
});
|
|
266
151
|
if (prev === curr) {
|
|
@@ -275,15 +160,14 @@ class Router extends core.EventEmitter {
|
|
|
275
160
|
forceRefresh = true;
|
|
276
161
|
}
|
|
277
162
|
try {
|
|
278
|
-
const props = await route2.resolve?.(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
) ?? {};
|
|
163
|
+
const props = await route2.resolve?.({
|
|
164
|
+
...request,
|
|
165
|
+
// request
|
|
166
|
+
...config,
|
|
167
|
+
// params, query
|
|
168
|
+
...context
|
|
169
|
+
// previous props
|
|
170
|
+
}) ?? {};
|
|
287
171
|
it.props = {
|
|
288
172
|
...props
|
|
289
173
|
};
|
|
@@ -293,7 +177,13 @@ class Router extends core.EventEmitter {
|
|
|
293
177
|
};
|
|
294
178
|
} catch (e) {
|
|
295
179
|
if (e instanceof RedirectionError) {
|
|
296
|
-
|
|
180
|
+
return {
|
|
181
|
+
layers: [],
|
|
182
|
+
redirect: typeof e.page === "string" ? e.page : this.href(e.page),
|
|
183
|
+
head: request.head,
|
|
184
|
+
pathname,
|
|
185
|
+
search
|
|
186
|
+
};
|
|
297
187
|
}
|
|
298
188
|
this.log.error(e);
|
|
299
189
|
it.error = e;
|
|
@@ -304,25 +194,25 @@ class Router extends core.EventEmitter {
|
|
|
304
194
|
for (let i = 0; i < stack.length; i++) {
|
|
305
195
|
const it = stack[i];
|
|
306
196
|
const props = it.props ?? {};
|
|
307
|
-
const
|
|
308
|
-
for (const key of Object.keys(
|
|
309
|
-
|
|
197
|
+
const params = { ...it.config?.params };
|
|
198
|
+
for (const key of Object.keys(params)) {
|
|
199
|
+
params[key] = String(params[key]);
|
|
310
200
|
}
|
|
311
|
-
if (it.route.head &&
|
|
312
|
-
this.
|
|
201
|
+
if (it.route.head && !it.error) {
|
|
202
|
+
this.fillHead(it.route, request, {
|
|
313
203
|
...props,
|
|
314
204
|
...context
|
|
315
205
|
});
|
|
316
206
|
}
|
|
317
207
|
acc += "/";
|
|
318
|
-
acc += it.route.path ?
|
|
208
|
+
acc += it.route.path ? this.compile(it.route.path, params) : "";
|
|
319
209
|
const path = acc.replace(/\/+/, "/");
|
|
320
210
|
if (it.error) {
|
|
321
211
|
const errorHandler = this.getErrorHandler(it.route);
|
|
322
212
|
const element = await (errorHandler ? errorHandler({
|
|
323
213
|
...it.config,
|
|
324
214
|
error: it.error,
|
|
325
|
-
url
|
|
215
|
+
url: ""
|
|
326
216
|
}) : this.renderError(it.error));
|
|
327
217
|
layers.push({
|
|
328
218
|
props,
|
|
@@ -350,13 +240,8 @@ class Router extends core.EventEmitter {
|
|
|
350
240
|
path
|
|
351
241
|
});
|
|
352
242
|
}
|
|
353
|
-
return layers;
|
|
243
|
+
return { layers, head: request.head, pathname, search };
|
|
354
244
|
}
|
|
355
|
-
/**
|
|
356
|
-
*
|
|
357
|
-
* @param route
|
|
358
|
-
* @protected
|
|
359
|
-
*/
|
|
360
245
|
getErrorHandler(route) {
|
|
361
246
|
if (route.errorHandler) return route.errorHandler;
|
|
362
247
|
let parent = route.parent;
|
|
@@ -365,12 +250,6 @@ class Router extends core.EventEmitter {
|
|
|
365
250
|
parent = parent.parent;
|
|
366
251
|
}
|
|
367
252
|
}
|
|
368
|
-
/**
|
|
369
|
-
*
|
|
370
|
-
* @param page
|
|
371
|
-
* @param props
|
|
372
|
-
* @protected
|
|
373
|
-
*/
|
|
374
253
|
async createElement(page, props) {
|
|
375
254
|
if (page.lazy) {
|
|
376
255
|
const component = await page.lazy();
|
|
@@ -381,65 +260,43 @@ class Router extends core.EventEmitter {
|
|
|
381
260
|
}
|
|
382
261
|
return void 0;
|
|
383
262
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
*/
|
|
392
|
-
mergeRenderContext(page, ctx, props) {
|
|
393
|
-
if (page.head) {
|
|
263
|
+
fillHead(page, ctx, props) {
|
|
264
|
+
if (!page.head) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
ctx.head ??= {};
|
|
268
|
+
const head = typeof page.head === "function" ? page.head(props, ctx.head) : page.head;
|
|
269
|
+
if (head.title) {
|
|
394
270
|
ctx.head ??= {};
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
ctx.head.title = `${head.title}${ctx.head.titleSeparator}${ctx.head.title}`;
|
|
400
|
-
} else {
|
|
401
|
-
ctx.head.title = head.title;
|
|
402
|
-
}
|
|
403
|
-
ctx.head.titleSeparator = head.titleSeparator;
|
|
404
|
-
}
|
|
405
|
-
if (head.htmlAttributes) {
|
|
406
|
-
ctx.head.htmlAttributes = {
|
|
407
|
-
...ctx.head.htmlAttributes,
|
|
408
|
-
...head.htmlAttributes
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
if (head.bodyAttributes) {
|
|
412
|
-
ctx.head.bodyAttributes = {
|
|
413
|
-
...ctx.head.bodyAttributes,
|
|
414
|
-
...head.bodyAttributes
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
if (head.meta) {
|
|
418
|
-
ctx.head.meta = [...ctx.head.meta ?? [], ...head.meta ?? []];
|
|
271
|
+
if (ctx.head.titleSeparator) {
|
|
272
|
+
ctx.head.title = `${head.title}${ctx.head.titleSeparator}${ctx.head.title}`;
|
|
273
|
+
} else {
|
|
274
|
+
ctx.head.title = head.title;
|
|
419
275
|
}
|
|
276
|
+
ctx.head.titleSeparator = head.titleSeparator;
|
|
277
|
+
}
|
|
278
|
+
if (head.htmlAttributes) {
|
|
279
|
+
ctx.head.htmlAttributes = {
|
|
280
|
+
...ctx.head.htmlAttributes,
|
|
281
|
+
...head.htmlAttributes
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
if (head.bodyAttributes) {
|
|
285
|
+
ctx.head.bodyAttributes = {
|
|
286
|
+
...ctx.head.bodyAttributes,
|
|
287
|
+
...head.bodyAttributes
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
if (head.meta) {
|
|
291
|
+
ctx.head.meta = [...ctx.head.meta ?? [], ...head.meta ?? []];
|
|
420
292
|
}
|
|
421
293
|
}
|
|
422
|
-
/**
|
|
423
|
-
*
|
|
424
|
-
* @param e
|
|
425
|
-
* @protected
|
|
426
|
-
*/
|
|
427
294
|
renderError(e) {
|
|
428
295
|
return React.createElement("pre", { style: { overflow: "auto" } }, `${e.stack}`);
|
|
429
296
|
}
|
|
430
|
-
/**
|
|
431
|
-
* Render an empty view.
|
|
432
|
-
*
|
|
433
|
-
* @protected
|
|
434
|
-
*/
|
|
435
297
|
renderEmptyView() {
|
|
436
298
|
return React.createElement(NestedView, {});
|
|
437
299
|
}
|
|
438
|
-
/**
|
|
439
|
-
* Create a valid href for the given page.
|
|
440
|
-
* @param page
|
|
441
|
-
* @param params
|
|
442
|
-
*/
|
|
443
300
|
href(page, params = {}) {
|
|
444
301
|
const found = this.pages.find((it) => it.name === page.options.name);
|
|
445
302
|
if (!found) {
|
|
@@ -451,16 +308,15 @@ class Router extends core.EventEmitter {
|
|
|
451
308
|
url = `${parent.path ?? ""}/${url}`;
|
|
452
309
|
parent = parent.parent;
|
|
453
310
|
}
|
|
454
|
-
url =
|
|
311
|
+
url = this.compile(url, params);
|
|
455
312
|
return url.replace(/\/\/+/g, "/") || "/";
|
|
456
313
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
*/
|
|
314
|
+
compile(path, params = {}) {
|
|
315
|
+
for (const [key, value] of Object.entries(params)) {
|
|
316
|
+
path = path.replace(`:${key}`, value);
|
|
317
|
+
}
|
|
318
|
+
return path;
|
|
319
|
+
}
|
|
464
320
|
renderView(index, path, view = this.renderEmptyView()) {
|
|
465
321
|
return React.createElement(
|
|
466
322
|
RouterLayerContext.Provider,
|
|
@@ -473,23 +329,39 @@ class Router extends core.EventEmitter {
|
|
|
473
329
|
view
|
|
474
330
|
);
|
|
475
331
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
332
|
+
configure = core.$hook({
|
|
333
|
+
name: "configure",
|
|
334
|
+
handler: () => {
|
|
335
|
+
const pages = this.alepha.getDescriptorValues($page);
|
|
336
|
+
for (const { value, key } of pages) {
|
|
337
|
+
value.options.name ??= key;
|
|
338
|
+
if (value.options.parent) {
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
this.add(this.map(pages, value));
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
map(pages, target) {
|
|
346
|
+
const children = target.options.children ?? [];
|
|
347
|
+
for (const it of pages) {
|
|
348
|
+
if (it.value.options.parent === target) {
|
|
349
|
+
children.push(it.value);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return {
|
|
353
|
+
...target.options,
|
|
354
|
+
parent: void 0,
|
|
355
|
+
children: children.map((it) => this.map(pages, it))
|
|
356
|
+
};
|
|
357
|
+
}
|
|
480
358
|
add(entry) {
|
|
481
359
|
if (this.alepha.isReady()) {
|
|
482
360
|
throw new Error("Router is already initialized");
|
|
483
361
|
}
|
|
484
|
-
if (entry.notFoundHandler) {
|
|
485
|
-
this.notFoundPageRoute = {
|
|
486
|
-
name: "not-found",
|
|
487
|
-
component: entry.notFoundHandler
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
362
|
entry.name ??= this.nextId();
|
|
491
363
|
const page = entry;
|
|
492
|
-
page.match = this.
|
|
364
|
+
page.match = this.createMatch(page);
|
|
493
365
|
this.pages.push(page);
|
|
494
366
|
if (page.children) {
|
|
495
367
|
for (const child of page.children) {
|
|
@@ -498,13 +370,7 @@ class Router extends core.EventEmitter {
|
|
|
498
370
|
}
|
|
499
371
|
}
|
|
500
372
|
}
|
|
501
|
-
|
|
502
|
-
* Create a match function for the given page.
|
|
503
|
-
*
|
|
504
|
-
* @param page
|
|
505
|
-
* @protected
|
|
506
|
-
*/
|
|
507
|
-
createMatchFunction(page) {
|
|
373
|
+
createMatch(page) {
|
|
508
374
|
let url = page.path ?? "/";
|
|
509
375
|
let target = page.parent;
|
|
510
376
|
while (target) {
|
|
@@ -512,76 +378,166 @@ class Router extends core.EventEmitter {
|
|
|
512
378
|
target = target.parent;
|
|
513
379
|
}
|
|
514
380
|
let path = url.replace(/\/\/+/g, "/");
|
|
515
|
-
if (path.endsWith("/")) {
|
|
381
|
+
if (path.endsWith("/") && path !== "/") {
|
|
516
382
|
path = path.slice(0, -1);
|
|
517
383
|
}
|
|
518
|
-
|
|
519
|
-
return {
|
|
520
|
-
exec: pathToRegexp.match(path.split("?")[0]),
|
|
521
|
-
path
|
|
522
|
-
};
|
|
523
|
-
}
|
|
524
|
-
return {
|
|
525
|
-
exec: pathToRegexp.match(path),
|
|
526
|
-
path
|
|
527
|
-
};
|
|
384
|
+
return path;
|
|
528
385
|
}
|
|
529
|
-
/**
|
|
530
|
-
*
|
|
531
|
-
*/
|
|
532
|
-
empty() {
|
|
533
|
-
return this.pages.length === 0;
|
|
534
|
-
}
|
|
535
|
-
/**
|
|
536
|
-
*
|
|
537
|
-
* @protected
|
|
538
|
-
*/
|
|
539
386
|
_next = 0;
|
|
540
|
-
/**
|
|
541
|
-
*
|
|
542
|
-
* @protected
|
|
543
|
-
*/
|
|
544
387
|
nextId() {
|
|
545
388
|
this._next += 1;
|
|
546
389
|
return `P${this._next}`;
|
|
547
390
|
}
|
|
548
391
|
}
|
|
392
|
+
const isPageRoute = (it) => {
|
|
393
|
+
return it && typeof it === "object" && typeof it.path === "string" && typeof it.page === "object";
|
|
394
|
+
};
|
|
549
395
|
|
|
550
|
-
class
|
|
396
|
+
class BrowserHeadProvider {
|
|
397
|
+
renderHead(document, head) {
|
|
398
|
+
if (head.title) {
|
|
399
|
+
document.title = head.title;
|
|
400
|
+
}
|
|
401
|
+
if (head.bodyAttributes) {
|
|
402
|
+
for (const [key, value] of Object.entries(head.bodyAttributes)) {
|
|
403
|
+
if (value) {
|
|
404
|
+
document.body.setAttribute(key, value);
|
|
405
|
+
} else {
|
|
406
|
+
document.body.removeAttribute(key);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (head.htmlAttributes) {
|
|
411
|
+
for (const [key, value] of Object.entries(head.htmlAttributes)) {
|
|
412
|
+
if (value) {
|
|
413
|
+
document.documentElement.setAttribute(key, value);
|
|
414
|
+
} else {
|
|
415
|
+
document.documentElement.removeAttribute(key);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
if (head.meta) {
|
|
420
|
+
for (const [key, value] of Object.entries(head.meta)) {
|
|
421
|
+
const meta = document.querySelector(`meta[name="${key}"]`);
|
|
422
|
+
if (meta) {
|
|
423
|
+
meta.setAttribute("content", value.content);
|
|
424
|
+
} else {
|
|
425
|
+
const newMeta = document.createElement("meta");
|
|
426
|
+
newMeta.setAttribute("name", key);
|
|
427
|
+
newMeta.setAttribute("content", value.content);
|
|
428
|
+
document.head.appendChild(newMeta);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
class BrowserRouterProvider extends router.RouterProvider {
|
|
436
|
+
log = core.$logger();
|
|
551
437
|
alepha = core.$inject(core.Alepha);
|
|
552
|
-
|
|
438
|
+
pageDescriptorProvider = core.$inject(PageDescriptorProvider);
|
|
439
|
+
events = new core.EventEmitter();
|
|
440
|
+
add(entry) {
|
|
441
|
+
this.pageDescriptorProvider.add(entry);
|
|
442
|
+
}
|
|
553
443
|
configure = core.$hook({
|
|
554
444
|
name: "configure",
|
|
555
|
-
handler: () => {
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
445
|
+
handler: async () => {
|
|
446
|
+
for (const page of this.pageDescriptorProvider.getPages()) {
|
|
447
|
+
if (page.component || page.lazy) {
|
|
448
|
+
this.push({
|
|
449
|
+
path: page.match,
|
|
450
|
+
page
|
|
451
|
+
});
|
|
561
452
|
}
|
|
562
|
-
this.router.add(this.map(pages, value));
|
|
563
453
|
}
|
|
564
454
|
}
|
|
565
455
|
});
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
456
|
+
async transition(url, options = {}) {
|
|
457
|
+
const { pathname, search } = url;
|
|
458
|
+
const state = {
|
|
459
|
+
pathname,
|
|
460
|
+
search,
|
|
461
|
+
layers: [],
|
|
462
|
+
head: {}
|
|
463
|
+
};
|
|
464
|
+
await this.events.emit("begin", void 0);
|
|
465
|
+
try {
|
|
466
|
+
const previous = options.previous;
|
|
467
|
+
const { route, params } = this.match(pathname);
|
|
468
|
+
const query = {};
|
|
469
|
+
if (search) {
|
|
470
|
+
for (const [key, value] of new URLSearchParams(search).entries()) {
|
|
471
|
+
query[key] = String(value);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (isPageRoute(route)) {
|
|
475
|
+
const result = await this.pageDescriptorProvider.createLayers(
|
|
476
|
+
route.page,
|
|
477
|
+
{
|
|
478
|
+
url,
|
|
479
|
+
params: params ?? {},
|
|
480
|
+
query,
|
|
481
|
+
previous,
|
|
482
|
+
...state,
|
|
483
|
+
head: state.head,
|
|
484
|
+
...options.context ?? {}
|
|
485
|
+
}
|
|
486
|
+
);
|
|
487
|
+
if (result.redirect) {
|
|
488
|
+
return {
|
|
489
|
+
element: null,
|
|
490
|
+
layers: [],
|
|
491
|
+
redirect: result.redirect,
|
|
492
|
+
head: state.head
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
state.layers = result.layers;
|
|
496
|
+
state.head = result.head;
|
|
577
497
|
}
|
|
498
|
+
if (state.layers.length === 0) {
|
|
499
|
+
state.layers.push({
|
|
500
|
+
name: "not-found",
|
|
501
|
+
element: "Not Found",
|
|
502
|
+
index: 0,
|
|
503
|
+
path: "/"
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
await this.events.emit("success", void 0);
|
|
507
|
+
} catch (e) {
|
|
508
|
+
this.log.error(e);
|
|
509
|
+
state.layers = [
|
|
510
|
+
{
|
|
511
|
+
name: "error",
|
|
512
|
+
element: this.pageDescriptorProvider.renderError(e),
|
|
513
|
+
index: 0,
|
|
514
|
+
path: "/"
|
|
515
|
+
}
|
|
516
|
+
];
|
|
517
|
+
await this.events.emit("error", e);
|
|
578
518
|
}
|
|
519
|
+
if (!options.state) {
|
|
520
|
+
await this.events.emit("end", state);
|
|
521
|
+
return {
|
|
522
|
+
element: this.root(state, options.context),
|
|
523
|
+
layers: state.layers,
|
|
524
|
+
head: state.head
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
options.state.layers = state.layers;
|
|
528
|
+
options.state.pathname = state.pathname;
|
|
529
|
+
options.state.search = state.search;
|
|
530
|
+
options.state.head = state.head;
|
|
531
|
+
await this.events.emit("end", options.state);
|
|
579
532
|
return {
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
533
|
+
element: this.root(state, options.context),
|
|
534
|
+
layers: options.state.layers,
|
|
535
|
+
head: state.head
|
|
583
536
|
};
|
|
584
537
|
}
|
|
538
|
+
root(state, context = {}) {
|
|
539
|
+
return this.pageDescriptorProvider.root(state, context, this.events);
|
|
540
|
+
}
|
|
585
541
|
}
|
|
586
542
|
|
|
587
543
|
const envSchema = core.t.object({
|
|
@@ -590,7 +546,9 @@ const envSchema = core.t.object({
|
|
|
590
546
|
class ReactBrowserProvider {
|
|
591
547
|
log = core.$logger();
|
|
592
548
|
client = core.$inject(server.HttpClient);
|
|
593
|
-
|
|
549
|
+
alepha = core.$inject(core.Alepha);
|
|
550
|
+
router = core.$inject(BrowserRouterProvider);
|
|
551
|
+
headProvider = core.$inject(BrowserHeadProvider);
|
|
594
552
|
env = core.$inject(envSchema);
|
|
595
553
|
root;
|
|
596
554
|
transitioning;
|
|
@@ -598,30 +556,17 @@ class ReactBrowserProvider {
|
|
|
598
556
|
layers: [],
|
|
599
557
|
pathname: "",
|
|
600
558
|
search: "",
|
|
601
|
-
|
|
559
|
+
head: {}
|
|
602
560
|
};
|
|
603
|
-
/**
|
|
604
|
-
*
|
|
605
|
-
*/
|
|
606
561
|
get document() {
|
|
607
562
|
return window.document;
|
|
608
563
|
}
|
|
609
|
-
/**
|
|
610
|
-
*
|
|
611
|
-
*/
|
|
612
564
|
get history() {
|
|
613
565
|
return window.history;
|
|
614
566
|
}
|
|
615
|
-
/**
|
|
616
|
-
*
|
|
617
|
-
*/
|
|
618
567
|
get url() {
|
|
619
568
|
return window.location.pathname + window.location.search;
|
|
620
569
|
}
|
|
621
|
-
/**
|
|
622
|
-
*
|
|
623
|
-
* @param props
|
|
624
|
-
*/
|
|
625
570
|
async invalidate(props) {
|
|
626
571
|
const previous = [];
|
|
627
572
|
if (props) {
|
|
@@ -662,66 +607,22 @@ class ReactBrowserProvider {
|
|
|
662
607
|
}
|
|
663
608
|
this.history.pushState({}, "", url);
|
|
664
609
|
}
|
|
665
|
-
/**
|
|
666
|
-
*
|
|
667
|
-
* @param options
|
|
668
|
-
* @protected
|
|
669
|
-
*/
|
|
670
610
|
async render(options = {}) {
|
|
671
611
|
const previous = options.previous ?? this.state.layers;
|
|
672
612
|
const url = options.url ?? this.url;
|
|
673
613
|
this.transitioning = { to: url };
|
|
674
|
-
const result = await this.router.
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
614
|
+
const result = await this.router.transition(
|
|
615
|
+
new URL(`http://localhost${url}`),
|
|
616
|
+
{
|
|
617
|
+
previous,
|
|
618
|
+
state: this.state
|
|
619
|
+
}
|
|
620
|
+
);
|
|
678
621
|
if (result.redirect) {
|
|
679
622
|
return await this.render({ url: result.redirect });
|
|
680
623
|
}
|
|
681
624
|
this.transitioning = void 0;
|
|
682
|
-
return { url,
|
|
683
|
-
}
|
|
684
|
-
/**
|
|
685
|
-
* Render the helmet context.
|
|
686
|
-
*
|
|
687
|
-
* @param ctx
|
|
688
|
-
* @protected
|
|
689
|
-
*/
|
|
690
|
-
renderHeadContext(ctx) {
|
|
691
|
-
if (ctx.title) {
|
|
692
|
-
this.document.title = ctx.title;
|
|
693
|
-
}
|
|
694
|
-
if (ctx.bodyAttributes) {
|
|
695
|
-
for (const [key, value] of Object.entries(ctx.bodyAttributes)) {
|
|
696
|
-
if (value) {
|
|
697
|
-
this.document.body.setAttribute(key, value);
|
|
698
|
-
} else {
|
|
699
|
-
this.document.body.removeAttribute(key);
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
if (ctx.htmlAttributes) {
|
|
704
|
-
for (const [key, value] of Object.entries(ctx.htmlAttributes)) {
|
|
705
|
-
if (value) {
|
|
706
|
-
this.document.documentElement.setAttribute(key, value);
|
|
707
|
-
} else {
|
|
708
|
-
this.document.documentElement.removeAttribute(key);
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
if (ctx.meta) {
|
|
713
|
-
for (const [key, value] of Object.entries(ctx.meta)) {
|
|
714
|
-
const meta = this.document.querySelector(`meta[name="${key}"]`);
|
|
715
|
-
if (meta) {
|
|
716
|
-
meta.setAttribute("content", value.content);
|
|
717
|
-
} else {
|
|
718
|
-
const newMeta = this.document.createElement("meta");
|
|
719
|
-
newMeta.setAttribute("name", key);
|
|
720
|
-
newMeta.setAttribute("content", value.content);
|
|
721
|
-
this.document.head.appendChild(newMeta);
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
}
|
|
625
|
+
return { url, head: result.head };
|
|
725
626
|
}
|
|
726
627
|
/**
|
|
727
628
|
* Get embedded layers from the server.
|
|
@@ -751,18 +652,6 @@ class ReactBrowserProvider {
|
|
|
751
652
|
this.document.body.prepend(div);
|
|
752
653
|
return div;
|
|
753
654
|
}
|
|
754
|
-
getUserFromCookies() {
|
|
755
|
-
const cookies = this.document.cookie.split("; ");
|
|
756
|
-
const userCookie = cookies.find((cookie) => cookie.startsWith("user="));
|
|
757
|
-
try {
|
|
758
|
-
if (userCookie) {
|
|
759
|
-
return JSON.parse(decodeURIComponent(userCookie.split("=")[1]));
|
|
760
|
-
}
|
|
761
|
-
} catch (error) {
|
|
762
|
-
this.log.warn(error, "Failed to parse user cookie");
|
|
763
|
-
}
|
|
764
|
-
return void 0;
|
|
765
|
-
}
|
|
766
655
|
// -------------------------------------------------------------------------------------------------------------------
|
|
767
656
|
/**
|
|
768
657
|
*
|
|
@@ -771,18 +660,21 @@ class ReactBrowserProvider {
|
|
|
771
660
|
ready = core.$hook({
|
|
772
661
|
name: "ready",
|
|
773
662
|
handler: async () => {
|
|
774
|
-
const
|
|
775
|
-
const previous =
|
|
776
|
-
if (
|
|
777
|
-
this.client.links =
|
|
778
|
-
}
|
|
779
|
-
const {
|
|
780
|
-
if (
|
|
781
|
-
this.
|
|
782
|
-
}
|
|
783
|
-
const
|
|
784
|
-
|
|
663
|
+
const hydration = this.getHydrationState();
|
|
664
|
+
const previous = hydration?.layers ?? [];
|
|
665
|
+
if (hydration?.links) {
|
|
666
|
+
this.client.links = hydration.links;
|
|
667
|
+
}
|
|
668
|
+
const { head } = await this.render({ previous });
|
|
669
|
+
if (head) {
|
|
670
|
+
this.headProvider.renderHead(this.document, head);
|
|
671
|
+
}
|
|
672
|
+
const context = {};
|
|
673
|
+
await this.alepha.emit("react:browser:render", {
|
|
674
|
+
context,
|
|
675
|
+
hydration
|
|
785
676
|
});
|
|
677
|
+
const element = this.router.root(this.state, context);
|
|
786
678
|
if (previous.length > 0) {
|
|
787
679
|
this.root = client.hydrateRoot(this.getRootElement(), element);
|
|
788
680
|
this.log.info("Hydrated root element");
|
|
@@ -794,48 +686,11 @@ class ReactBrowserProvider {
|
|
|
794
686
|
window.addEventListener("popstate", () => {
|
|
795
687
|
this.render();
|
|
796
688
|
});
|
|
797
|
-
this.router.on("end", ({
|
|
798
|
-
|
|
799
|
-
this.renderHeadContext(context2.head);
|
|
800
|
-
}
|
|
801
|
-
});
|
|
802
|
-
}
|
|
803
|
-
});
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
class Auth {
|
|
807
|
-
alepha = core.$inject(core.Alepha);
|
|
808
|
-
log = core.$logger();
|
|
809
|
-
client = core.$inject(server.HttpClient);
|
|
810
|
-
slugs = {
|
|
811
|
-
login: "/api/_oauth/login",
|
|
812
|
-
logout: "/api/_oauth/logout"
|
|
813
|
-
};
|
|
814
|
-
start = core.$hook({
|
|
815
|
-
name: "start",
|
|
816
|
-
handler: async () => {
|
|
817
|
-
this.client.on("onError", (err) => {
|
|
818
|
-
if (err.statusCode === 401) {
|
|
819
|
-
this.login();
|
|
820
|
-
}
|
|
689
|
+
this.router.events.on("end", ({ head: head2 }) => {
|
|
690
|
+
this.headProvider.renderHead(this.document, head2);
|
|
821
691
|
});
|
|
822
692
|
}
|
|
823
693
|
});
|
|
824
|
-
login = (provider) => {
|
|
825
|
-
if (this.alepha.isBrowser()) {
|
|
826
|
-
const browser = this.alepha.get(ReactBrowserProvider);
|
|
827
|
-
const redirect = browser.transitioning ? window.location.origin + browser.transitioning.to : window.location.href;
|
|
828
|
-
window.location.href = `${this.slugs.login}?redirect=${redirect}`;
|
|
829
|
-
if (browser.transitioning) {
|
|
830
|
-
throw new RedirectionError(browser.state.pathname);
|
|
831
|
-
}
|
|
832
|
-
return;
|
|
833
|
-
}
|
|
834
|
-
throw new RedirectionError(this.slugs.login);
|
|
835
|
-
};
|
|
836
|
-
logout = () => {
|
|
837
|
-
window.location.href = `${this.slugs.logout}?redirect=${encodeURIComponent(window.location.origin)}`;
|
|
838
|
-
};
|
|
839
694
|
}
|
|
840
695
|
|
|
841
696
|
class RouterHookApi {
|
|
@@ -958,7 +813,7 @@ const useRouter = () => {
|
|
|
958
813
|
layer,
|
|
959
814
|
ctx.alepha.isBrowser() ? ctx.alepha.get(ReactBrowserProvider) : void 0
|
|
960
815
|
),
|
|
961
|
-
[
|
|
816
|
+
[layer]
|
|
962
817
|
);
|
|
963
818
|
};
|
|
964
819
|
|
|
@@ -970,7 +825,6 @@ const Link = (props) => {
|
|
|
970
825
|
}
|
|
971
826
|
const can = typeof props.to === "string" ? void 0 : props.to.options.can;
|
|
972
827
|
if (can && !can()) {
|
|
973
|
-
console.log("I cannot go to", to);
|
|
974
828
|
return null;
|
|
975
829
|
}
|
|
976
830
|
const name = typeof props.to === "string" ? void 0 : props.to.options.name;
|
|
@@ -1042,13 +896,13 @@ const useRouterEvents = (opts = {}) => {
|
|
|
1042
896
|
const onEnd = opts.onEnd;
|
|
1043
897
|
const onError = opts.onError;
|
|
1044
898
|
if (onBegin) {
|
|
1045
|
-
subs.push(ctx.
|
|
899
|
+
subs.push(ctx.events.on("begin", onBegin));
|
|
1046
900
|
}
|
|
1047
901
|
if (onEnd) {
|
|
1048
|
-
subs.push(ctx.
|
|
902
|
+
subs.push(ctx.events.on("end", onEnd));
|
|
1049
903
|
}
|
|
1050
904
|
if (onError) {
|
|
1051
|
-
subs.push(ctx.
|
|
905
|
+
subs.push(ctx.events.on("error", onError));
|
|
1052
906
|
}
|
|
1053
907
|
return () => {
|
|
1054
908
|
for (const sub of subs) {
|
|
@@ -1066,7 +920,7 @@ const useRouterState = () => {
|
|
|
1066
920
|
}
|
|
1067
921
|
const [state, setState] = React.useState(ctx.state);
|
|
1068
922
|
React.useEffect(
|
|
1069
|
-
() => ctx.
|
|
923
|
+
() => ctx.events.on("end", (it) => {
|
|
1070
924
|
setState({ ...it });
|
|
1071
925
|
}),
|
|
1072
926
|
[]
|
|
@@ -1090,7 +944,7 @@ const useActive = (path) => {
|
|
|
1090
944
|
const [isPending, setPending] = React.useState(false);
|
|
1091
945
|
const isActive = current === href;
|
|
1092
946
|
React.useEffect(
|
|
1093
|
-
() => ctx.
|
|
947
|
+
() => ctx.events.on("end", ({ pathname }) => setCurrent(pathname)),
|
|
1094
948
|
[]
|
|
1095
949
|
);
|
|
1096
950
|
return {
|
|
@@ -1113,41 +967,22 @@ const useActive = (path) => {
|
|
|
1113
967
|
};
|
|
1114
968
|
};
|
|
1115
969
|
|
|
1116
|
-
const useAuth = () => {
|
|
1117
|
-
const ctx = React.useContext(RouterContext);
|
|
1118
|
-
if (!ctx) {
|
|
1119
|
-
throw new Error("useAuth must be used within a RouterContext");
|
|
1120
|
-
}
|
|
1121
|
-
const args = ctx.args ?? {};
|
|
1122
|
-
return {
|
|
1123
|
-
user: args.user,
|
|
1124
|
-
logout: () => {
|
|
1125
|
-
ctx.alepha.get(Auth).logout();
|
|
1126
|
-
},
|
|
1127
|
-
login: (provider) => {
|
|
1128
|
-
ctx.alepha.get(Auth).login();
|
|
1129
|
-
}
|
|
1130
|
-
};
|
|
1131
|
-
};
|
|
1132
|
-
|
|
1133
|
-
exports.$auth = $auth;
|
|
1134
970
|
exports.$page = $page;
|
|
1135
|
-
exports.
|
|
971
|
+
exports.BrowserRouterProvider = BrowserRouterProvider;
|
|
1136
972
|
exports.Link = Link;
|
|
1137
973
|
exports.NestedView = NestedView;
|
|
1138
974
|
exports.PageDescriptorProvider = PageDescriptorProvider;
|
|
1139
975
|
exports.ReactBrowserProvider = ReactBrowserProvider;
|
|
1140
976
|
exports.RedirectionError = RedirectionError;
|
|
1141
|
-
exports.Router = Router;
|
|
1142
977
|
exports.RouterContext = RouterContext;
|
|
1143
978
|
exports.RouterHookApi = RouterHookApi;
|
|
1144
979
|
exports.RouterLayerContext = RouterLayerContext;
|
|
1145
|
-
exports.
|
|
980
|
+
exports.isPageRoute = isPageRoute;
|
|
1146
981
|
exports.useActive = useActive;
|
|
1147
|
-
exports.useAuth = useAuth;
|
|
1148
982
|
exports.useClient = useClient;
|
|
1149
983
|
exports.useInject = useInject;
|
|
1150
984
|
exports.useQueryParams = useQueryParams;
|
|
1151
985
|
exports.useRouter = useRouter;
|
|
1152
986
|
exports.useRouterEvents = useRouterEvents;
|
|
1153
987
|
exports.useRouterState = useRouterState;
|
|
988
|
+
//# sourceMappingURL=useActive-BGtt_RNQ.cjs.map
|