@tramvai/module-router 2.70.1 → 2.72.0
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/lib/components/link.browser.js +55 -0
- package/lib/components/link.es.js +49 -0
- package/lib/components/link.js +53 -0
- package/lib/hooks/usePageService.browser.js +10 -0
- package/lib/hooks/usePageService.es.js +10 -0
- package/lib/hooks/usePageService.js +14 -0
- package/lib/hooks/usePrefetch.browser.browser.js +42 -0
- package/lib/index.browser.js +7 -918
- package/lib/index.es.js +6 -764
- package/lib/index.js +34 -788
- package/lib/modules/child-app.browser.js +31 -0
- package/lib/modules/child-app.es.js +31 -0
- package/lib/modules/child-app.js +33 -0
- package/lib/modules/clientCommon.browser.js +70 -0
- package/lib/modules/common.browser.js +137 -0
- package/lib/modules/common.es.js +137 -0
- package/lib/modules/common.js +145 -0
- package/lib/modules/fileSystemPages.browser.js +27 -0
- package/lib/modules/fileSystemPages.es.js +27 -0
- package/lib/modules/fileSystemPages.js +31 -0
- package/lib/modules/guards/common/index.browser.js +32 -0
- package/lib/modules/guards/common/index.es.js +32 -0
- package/lib/modules/guards/common/index.js +36 -0
- package/lib/modules/guards/common/internalError.browser.js +14 -0
- package/lib/modules/guards/common/internalError.es.js +14 -0
- package/lib/modules/guards/common/internalError.js +18 -0
- package/lib/modules/guards/common/loadBundle.browser.js +67 -0
- package/lib/modules/guards/common/loadBundle.es.js +67 -0
- package/lib/modules/guards/common/loadBundle.js +75 -0
- package/lib/modules/guards/server/httpMethod.es.js +20 -0
- package/lib/modules/guards/server/httpMethod.js +24 -0
- package/lib/modules/guards/server/index.es.js +18 -0
- package/lib/modules/guards/server/index.js +22 -0
- package/lib/modules/hooks/common/fillRouterStore.browser.js +9 -0
- package/lib/modules/hooks/common/fillRouterStore.es.js +9 -0
- package/lib/modules/hooks/common/fillRouterStore.js +13 -0
- package/lib/modules/hooks/common/index.browser.js +16 -0
- package/lib/modules/hooks/common/index.es.js +16 -0
- package/lib/modules/hooks/common/index.js +20 -0
- package/lib/modules/hooks/runActions.browser.js +34 -0
- package/lib/modules/hooks/runActions.es.js +34 -0
- package/lib/modules/hooks/runActions.js +42 -0
- package/lib/modules/hooks/server/httpStatus.es.js +7 -0
- package/lib/modules/hooks/server/httpStatus.js +11 -0
- package/lib/modules/hooks/server/index.es.js +17 -0
- package/lib/modules/hooks/server/index.js +21 -0
- package/lib/modules/hooks/spa/index.browser.js +70 -0
- package/lib/modules/hooks/spa/runCommands.browser.js +12 -0
- package/lib/modules/no-spa.browser.js +21 -0
- package/lib/modules/server.es.js +59 -0
- package/lib/modules/server.js +63 -0
- package/lib/modules/spa.browser.js +23 -0
- package/lib/modules/tokens/browser/index.browser.js +5 -0
- package/lib/modules/tokens/browser/prefetch.browser.js +112 -0
- package/lib/modules/tokens/common/index.browser.js +40 -0
- package/lib/modules/tokens/common/index.es.js +40 -0
- package/lib/modules/tokens/common/index.js +44 -0
- package/lib/modules/tokens/common/render.browser.js +14 -0
- package/lib/modules/tokens/common/render.es.js +14 -0
- package/lib/modules/tokens/common/render.js +18 -0
- package/lib/modules/tokens/common/routeNormalize.browser.js +10 -0
- package/lib/modules/tokens/common/routeNormalize.es.js +10 -0
- package/lib/modules/tokens/common/routeNormalize.js +18 -0
- package/lib/modules/tokens/common/routeSetDefaults.browser.js +13 -0
- package/lib/modules/tokens/common/routeSetDefaults.es.js +13 -0
- package/lib/modules/tokens/common/routeSetDefaults.js +17 -0
- package/lib/modules/tokens/common/routeTransform.browser.js +12 -0
- package/lib/modules/tokens/common/routeTransform.es.js +12 -0
- package/lib/modules/tokens/common/routeTransform.js +22 -0
- package/lib/modules/tokens/server/bundleInfo.es.js +35 -0
- package/lib/modules/tokens/server/bundleInfo.js +44 -0
- package/lib/modules/tokens/server/index.es.js +25 -0
- package/lib/modules/tokens/server/index.js +29 -0
- package/lib/modules/tokens/server/prefetch.es.js +15 -0
- package/lib/modules/tokens/server/prefetch.js +19 -0
- package/lib/modules/tokens/server/routerOptions.es.js +37 -0
- package/lib/modules/tokens/server/routerOptions.js +41 -0
- package/lib/modules/tokens.browser.js +22 -0
- package/lib/modules/tokens.es.js +22 -0
- package/lib/modules/tokens.js +35 -0
- package/lib/modules/utils/forRoot.browser.js +22 -0
- package/lib/modules/utils/forRoot.es.js +22 -0
- package/lib/modules/utils/forRoot.js +26 -0
- package/lib/services/page.browser.js +63 -0
- package/lib/services/page.es.js +63 -0
- package/lib/services/page.js +67 -0
- package/lib/stores/RouterStore.browser.js +29 -0
- package/lib/stores/RouterStore.es.js +29 -0
- package/lib/stores/RouterStore.js +35 -0
- package/lib/utils/requestIdleCallback.browser.js +10 -0
- package/package.json +22 -23
package/lib/index.browser.js
CHANGED
|
@@ -1,920 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export { NoSpaRouterModule } from './modules/no-spa.browser.js';
|
|
2
|
+
export { SpaRouterModule } from './modules/spa.browser.js';
|
|
3
|
+
export { RouterChildAppModule } from './modules/child-app.browser.js';
|
|
3
4
|
export { Provider, useNavigate, useRoute, useRouter, useUrl } from '@tinkoff/router';
|
|
4
|
-
|
|
5
|
-
import { LOGGER_TOKEN, BUNDLE_MANAGER_TOKEN, ACTION_REGISTRY_TOKEN, RESPONSE_MANAGER_TOKEN, DISPATCHER_TOKEN, DISPATCHER_CONTEXT_TOKEN, CONTEXT_TOKEN, COMPONENT_REGISTRY_TOKEN, COMBINE_REDUCERS, STORE_TOKEN, ACTION_PAGE_RUNNER_TOKEN } from '@tramvai/tokens-common';
|
|
6
|
-
import { ROUTER_GUARD_TOKEN, PAGE_SERVICE_TOKEN, ROUTE_TRANSFORM_TOKEN, ROUTER_TOKEN, ROUTES_TOKEN, ROUTE_RESOLVE_TOKEN, ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN, LINK_PREFETCH_MANAGER_TOKEN } from '@tramvai/tokens-router';
|
|
5
|
+
export { Link } from './components/link.browser.js';
|
|
7
6
|
export * from '@tramvai/tokens-router';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import { createToken, optional } from '@tinkoff/dippy';
|
|
12
|
-
import isArray from '@tinkoff/utils/is/array';
|
|
13
|
-
import { resolveLazyComponent, useDi } from '@tramvai/react';
|
|
14
|
-
import identity from '@tinkoff/utils/function/identity';
|
|
15
|
-
import compose from '@tinkoff/utils/function/compose';
|
|
16
|
-
import replace from '@tinkoff/utils/string/replace';
|
|
17
|
-
import { jsx } from 'react/jsx-runtime';
|
|
18
|
-
import { isFileSystemPageComponent, fileSystemPagesEnabled, getStaticFileSystemPages, fileSystemPageToRoute } from '@tramvai/experiments';
|
|
19
|
-
import { addQuery } from '@tinkoff/url';
|
|
20
|
-
import uniq from '@tinkoff/utils/array/uniq';
|
|
21
|
-
import { isRedirectFoundError, isNotFoundError } from '@tinkoff/errors';
|
|
22
|
-
import { __decorate } from 'tslib';
|
|
23
|
-
import { CHILD_APP_INTERNAL_ROOT_STATE_ALLOWED_STORE_TOKEN } from '@tramvai/tokens-child-app';
|
|
24
|
-
import { useEffect, useState, useCallback, isValidElement, cloneElement } from 'react';
|
|
25
|
-
|
|
26
|
-
const setCurrentNavigation = createEvent('SET_CURRENT_ROUTE');
|
|
27
|
-
const setUrlOnRehydrate = createEvent('SET_URL_ON_REHYDRATE');
|
|
28
|
-
const initialState = {
|
|
29
|
-
currentRoute: null,
|
|
30
|
-
previousRoute: null,
|
|
31
|
-
currentUrl: null,
|
|
32
|
-
previousUrl: null,
|
|
33
|
-
};
|
|
34
|
-
const RouterStore = createReducer('router', initialState)
|
|
35
|
-
.on(setCurrentNavigation, (state, { to, from, url, fromUrl, replace }) => {
|
|
36
|
-
// TODO: убедиться что все данные нам нужны из роутинга,
|
|
37
|
-
// возможно всякие meta, content не нужны при дегидрации
|
|
38
|
-
return {
|
|
39
|
-
currentRoute: to,
|
|
40
|
-
previousRoute: replace ? state.previousRoute : from,
|
|
41
|
-
currentUrl: url,
|
|
42
|
-
previousUrl: replace ? state.previousUrl : fromUrl,
|
|
43
|
-
};
|
|
44
|
-
})
|
|
45
|
-
.on(setUrlOnRehydrate, (state, url) => {
|
|
46
|
-
return {
|
|
47
|
-
...state,
|
|
48
|
-
currentUrl: url,
|
|
49
|
-
};
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const routerClassToken = createToken('router routerClassToken');
|
|
53
|
-
const additionalRouterParameters = createToken('router additionalParameters');
|
|
54
|
-
const onChangeHooksToken = createToken('router onChangeHooks', {
|
|
55
|
-
multi: true,
|
|
56
|
-
});
|
|
57
|
-
const beforeResolveHooksToken = createToken('router beforeResolveHooks', {
|
|
58
|
-
multi: true,
|
|
59
|
-
});
|
|
60
|
-
const beforeNavigateHooksToken = createToken('router beforeNavigateHooks', {
|
|
61
|
-
multi: true,
|
|
62
|
-
});
|
|
63
|
-
const afterNavigateHooksToken = createToken('router afterNavigateHooks', {
|
|
64
|
-
multi: true,
|
|
65
|
-
});
|
|
66
|
-
const beforeUpdateCurrentHooksToken = createToken('router beforeUpdateCurrentHooks', { multi: true });
|
|
67
|
-
const afterUpdateCurrentHooksToken = createToken('router afterUpdateCurrentHooks', { multi: true });
|
|
68
|
-
const routeTransformToken = createToken('router finalRouteTransform');
|
|
69
|
-
createToken('router bundleInfoAdditional');
|
|
70
|
-
|
|
71
|
-
const loadBundle = ({ bundleManager, logger, actionRegistry, responseManager, dispatcher, dispatcherContext, pageService, }) => {
|
|
72
|
-
const log = logger('route:load-bundles');
|
|
73
|
-
return async ({ to }) => {
|
|
74
|
-
var _a;
|
|
75
|
-
log.debug({
|
|
76
|
-
event: 'load-bundle',
|
|
77
|
-
route: to,
|
|
78
|
-
});
|
|
79
|
-
const { bundle, pageComponent, nestedLayoutComponent } = to.config;
|
|
80
|
-
if (!bundleManager.has(bundle, pageComponent)) {
|
|
81
|
-
log.info({
|
|
82
|
-
event: 'load-bundle-not-found',
|
|
83
|
-
bundle,
|
|
84
|
-
pageComponent,
|
|
85
|
-
});
|
|
86
|
-
// если бандл не найден, то всё ок и мы должны вернуть 404 на сервере,
|
|
87
|
-
// а на клиенте просто загрузить новую страницу
|
|
88
|
-
responseManager.setStatus(404);
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
// Пытаемся загрузить и в случае инициализации на клиенте, т.к.
|
|
92
|
-
// несмотря на наличие бандла в разметке, все равно мы должны дождаться
|
|
93
|
-
// его загрузки перед рендером
|
|
94
|
-
try {
|
|
95
|
-
const promises = [];
|
|
96
|
-
// for file-system pages bundle is virtual, so it will be loaded in parallel with nested layout
|
|
97
|
-
// for classic bundles, page component will be loaded after bundle loading
|
|
98
|
-
promises.push(bundleManager.get(bundle, pageComponent));
|
|
99
|
-
if (nestedLayoutComponent) {
|
|
100
|
-
promises.push(resolveLazyComponent(pageService.resolveComponentFromConfig('nestedLayout')));
|
|
101
|
-
}
|
|
102
|
-
const [resolvedBundle, resolvedLayout] = await Promise.all(promises);
|
|
103
|
-
const { components, reducers } = resolvedBundle;
|
|
104
|
-
const component = components[pageComponent];
|
|
105
|
-
// pageComponent should have required fields even if it is lazy,
|
|
106
|
-
// thanks to `git log 9466cb32bfb71ba49144ef839d3d5bce246e213c -L90,103:packages/modules/common/src/bundleManager/bundleManager.ts`
|
|
107
|
-
(_a = component === null || component === void 0 ? void 0 : component.reducers) === null || _a === void 0 ? void 0 : _a.forEach((reducer) => dispatcherContext.getStore(reducer));
|
|
108
|
-
reducers === null || reducers === void 0 ? void 0 : reducers.forEach((reducer) => dispatcherContext.getStore(reducer));
|
|
109
|
-
// @todo: reuse logic from bundleManager?
|
|
110
|
-
// register nested layout actions and reducers for current page
|
|
111
|
-
if (resolvedLayout) {
|
|
112
|
-
if ('actions' in resolvedLayout && isArray(resolvedLayout.actions)) {
|
|
113
|
-
actionRegistry.add(pageComponent, resolvedLayout.actions);
|
|
114
|
-
}
|
|
115
|
-
if ('reducers' in resolvedLayout && isArray(resolvedLayout.reducers)) {
|
|
116
|
-
resolvedLayout.reducers.forEach((reducer) => {
|
|
117
|
-
dispatcher.registerStore(reducer);
|
|
118
|
-
dispatcherContext.getStore(reducer);
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
catch (error) {
|
|
124
|
-
log.error({
|
|
125
|
-
event: 'load-bundle-failed',
|
|
126
|
-
error,
|
|
127
|
-
});
|
|
128
|
-
// блокируем переход если не удалось загрузить бандл
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const internalError = ({ responseManager, logger, }) => {
|
|
135
|
-
const log = logger('route:guard-check-error');
|
|
136
|
-
return async () => {
|
|
137
|
-
if (responseManager.getStatus() >= 500) {
|
|
138
|
-
log.error({
|
|
139
|
-
event: 'status-is-error',
|
|
140
|
-
status: responseManager.getStatus(),
|
|
141
|
-
});
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
const commonGuards = [
|
|
148
|
-
{
|
|
149
|
-
provide: ROUTER_GUARD_TOKEN,
|
|
150
|
-
multi: true,
|
|
151
|
-
useFactory: loadBundle,
|
|
152
|
-
deps: {
|
|
153
|
-
logger: LOGGER_TOKEN,
|
|
154
|
-
bundleManager: BUNDLE_MANAGER_TOKEN,
|
|
155
|
-
actionRegistry: ACTION_REGISTRY_TOKEN,
|
|
156
|
-
responseManager: RESPONSE_MANAGER_TOKEN,
|
|
157
|
-
dispatcher: DISPATCHER_TOKEN,
|
|
158
|
-
dispatcherContext: DISPATCHER_CONTEXT_TOKEN,
|
|
159
|
-
pageService: PAGE_SERVICE_TOKEN,
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
provide: ROUTER_GUARD_TOKEN,
|
|
164
|
-
multi: true,
|
|
165
|
-
useFactory: internalError,
|
|
166
|
-
deps: {
|
|
167
|
-
logger: LOGGER_TOKEN,
|
|
168
|
-
responseManager: RESPONSE_MANAGER_TOKEN,
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
];
|
|
172
|
-
|
|
173
|
-
const fillRouterStore = ({ context, }) => {
|
|
174
|
-
return (navigation) => {
|
|
175
|
-
context.dispatch(setCurrentNavigation(navigation));
|
|
176
|
-
};
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const commonHooks = [
|
|
180
|
-
{
|
|
181
|
-
provide: onChangeHooksToken,
|
|
182
|
-
multi: true,
|
|
183
|
-
useFactory: fillRouterStore,
|
|
184
|
-
deps: {
|
|
185
|
-
context: CONTEXT_TOKEN,
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
];
|
|
189
|
-
|
|
190
|
-
const routeTransform = ({ transformers, }) => {
|
|
191
|
-
if (!transformers || transformers.length === 0) {
|
|
192
|
-
return identity;
|
|
193
|
-
}
|
|
194
|
-
return compose(...flatten(transformers));
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
const routeSetDefaults = (route) => {
|
|
198
|
-
const config = {
|
|
199
|
-
bundle: 'mainDefault',
|
|
200
|
-
pageComponent: 'pageDefault',
|
|
201
|
-
...route.config,
|
|
202
|
-
};
|
|
203
|
-
return {
|
|
204
|
-
...route,
|
|
205
|
-
config,
|
|
206
|
-
};
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
const routeNormalize = (route) => {
|
|
210
|
-
return {
|
|
211
|
-
...route,
|
|
212
|
-
path: replace(/\/?$/, '/', route.path),
|
|
213
|
-
};
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
const provideRouter = ({ router }) => {
|
|
217
|
-
const serverState = {
|
|
218
|
-
currentRoute: router.getCurrentRoute(),
|
|
219
|
-
currentUrl: router.getCurrentUrl(),
|
|
220
|
-
};
|
|
221
|
-
return (render) => {
|
|
222
|
-
return (jsx(Provider, { router: router, serverState: serverState, children: render }));
|
|
223
|
-
};
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
const commonTokens = [
|
|
227
|
-
{
|
|
228
|
-
provide: routeTransformToken,
|
|
229
|
-
useFactory: routeTransform,
|
|
230
|
-
deps: {
|
|
231
|
-
transformers: {
|
|
232
|
-
token: ROUTE_TRANSFORM_TOKEN,
|
|
233
|
-
optional: true,
|
|
234
|
-
},
|
|
235
|
-
},
|
|
236
|
-
},
|
|
237
|
-
{
|
|
238
|
-
provide: ROUTE_TRANSFORM_TOKEN,
|
|
239
|
-
multi: true,
|
|
240
|
-
useValue: routeSetDefaults,
|
|
241
|
-
},
|
|
242
|
-
{
|
|
243
|
-
provide: ROUTE_TRANSFORM_TOKEN,
|
|
244
|
-
multi: true,
|
|
245
|
-
useValue: routeNormalize,
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
provide: EXTEND_RENDER,
|
|
249
|
-
multi: true,
|
|
250
|
-
useFactory: provideRouter,
|
|
251
|
-
deps: {
|
|
252
|
-
router: ROUTER_TOKEN,
|
|
253
|
-
},
|
|
254
|
-
},
|
|
255
|
-
];
|
|
256
|
-
|
|
257
|
-
class PageService {
|
|
258
|
-
constructor({ router, componentRegistry }) {
|
|
259
|
-
this.router = router;
|
|
260
|
-
this.componentRegistry = componentRegistry;
|
|
261
|
-
}
|
|
262
|
-
getCurrentRoute() {
|
|
263
|
-
return this.router.getCurrentRoute();
|
|
264
|
-
}
|
|
265
|
-
getCurrentUrl() {
|
|
266
|
-
return this.router.getCurrentUrl();
|
|
267
|
-
}
|
|
268
|
-
getConfig() {
|
|
269
|
-
var _a, _b;
|
|
270
|
-
return (_b = (_a = this.getCurrentRoute()) === null || _a === void 0 ? void 0 : _a.config) !== null && _b !== void 0 ? _b : {};
|
|
271
|
-
}
|
|
272
|
-
getContent() {
|
|
273
|
-
var _a;
|
|
274
|
-
return (_a = this.getConfig().content) !== null && _a !== void 0 ? _a : {};
|
|
275
|
-
}
|
|
276
|
-
getMeta() {
|
|
277
|
-
var _a;
|
|
278
|
-
return (_a = this.getConfig().meta) !== null && _a !== void 0 ? _a : {};
|
|
279
|
-
}
|
|
280
|
-
navigate(options) {
|
|
281
|
-
return this.router.navigate(options);
|
|
282
|
-
}
|
|
283
|
-
updateCurrentRoute(options) {
|
|
284
|
-
return this.router.updateCurrentRoute(options);
|
|
285
|
-
}
|
|
286
|
-
back(options) {
|
|
287
|
-
return this.router.back(options);
|
|
288
|
-
}
|
|
289
|
-
forward() {
|
|
290
|
-
return this.router.forward();
|
|
291
|
-
}
|
|
292
|
-
go(to, options) {
|
|
293
|
-
return this.router.go(to, options);
|
|
294
|
-
}
|
|
295
|
-
addComponent(name, component) {
|
|
296
|
-
const group = this.getComponentsGroupName();
|
|
297
|
-
return this.componentRegistry.add(name, component, group);
|
|
298
|
-
}
|
|
299
|
-
getComponent(name) {
|
|
300
|
-
const group = this.getComponentsGroupName();
|
|
301
|
-
return this.componentRegistry.get(name, group);
|
|
302
|
-
}
|
|
303
|
-
resolveComponentFromConfig(property) {
|
|
304
|
-
var _a;
|
|
305
|
-
const configName = `${property}Component`;
|
|
306
|
-
const defaultComponent = `${property}Default`;
|
|
307
|
-
const componentName = (_a = this.getConfig()[configName]) !== null && _a !== void 0 ? _a : defaultComponent;
|
|
308
|
-
return this.getComponent(componentName) || this.getComponent(defaultComponent);
|
|
309
|
-
}
|
|
310
|
-
getComponentsGroupName() {
|
|
311
|
-
const { bundle, pageComponent } = this.getConfig();
|
|
312
|
-
const group = isFileSystemPageComponent(pageComponent) ? pageComponent : bundle;
|
|
313
|
-
return group;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const providers$2 = [
|
|
318
|
-
fileSystemPagesEnabled() &&
|
|
319
|
-
provide({
|
|
320
|
-
provide: ROUTES_TOKEN,
|
|
321
|
-
multi: true,
|
|
322
|
-
useFactory: ({ logger }) => {
|
|
323
|
-
const log = logger('file-system-pages:route');
|
|
324
|
-
const pagesNames = Object.keys(getStaticFileSystemPages());
|
|
325
|
-
const routes = pagesNames.map(fileSystemPageToRoute);
|
|
326
|
-
log.debug({
|
|
327
|
-
event: 'create static routes from file-system pages',
|
|
328
|
-
routes,
|
|
329
|
-
});
|
|
330
|
-
return routes;
|
|
331
|
-
},
|
|
332
|
-
deps: {
|
|
333
|
-
logger: LOGGER_TOKEN,
|
|
334
|
-
},
|
|
335
|
-
}),
|
|
336
|
-
].filter(Boolean);
|
|
337
|
-
|
|
338
|
-
const providers$1 = [
|
|
339
|
-
...commonGuards,
|
|
340
|
-
...commonHooks,
|
|
341
|
-
...commonTokens,
|
|
342
|
-
...providers$2,
|
|
343
|
-
{
|
|
344
|
-
provide: ROUTER_TOKEN,
|
|
345
|
-
useFactory: ({ RouterClass, routes, routeTransform, routeResolve, additionalParameters, }) => {
|
|
346
|
-
const router = new RouterClass({
|
|
347
|
-
...additionalParameters,
|
|
348
|
-
trailingSlash: true,
|
|
349
|
-
mergeSlashes: true,
|
|
350
|
-
routes: flatten(routes !== null && routes !== void 0 ? routes : []).map(routeTransform),
|
|
351
|
-
});
|
|
352
|
-
if (routeResolve) {
|
|
353
|
-
router.registerHook('beforeResolve', async (navigation) => {
|
|
354
|
-
if (!router.resolve(navigation.url.href)) {
|
|
355
|
-
const route = await routeResolve(navigation);
|
|
356
|
-
if (route) {
|
|
357
|
-
router.addRoute(routeTransform(route));
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
return router;
|
|
363
|
-
},
|
|
364
|
-
deps: {
|
|
365
|
-
RouterClass: routerClassToken,
|
|
366
|
-
additionalParameters: {
|
|
367
|
-
token: additionalRouterParameters,
|
|
368
|
-
optional: true,
|
|
369
|
-
},
|
|
370
|
-
routes: {
|
|
371
|
-
token: ROUTES_TOKEN,
|
|
372
|
-
optional: true,
|
|
373
|
-
},
|
|
374
|
-
routeTransform: routeTransformToken,
|
|
375
|
-
routeResolve: {
|
|
376
|
-
token: ROUTE_RESOLVE_TOKEN,
|
|
377
|
-
optional: true,
|
|
378
|
-
},
|
|
379
|
-
},
|
|
380
|
-
},
|
|
381
|
-
{
|
|
382
|
-
provide: commandLineListTokens.customerStart,
|
|
383
|
-
multi: true,
|
|
384
|
-
useFactory: ({ router, guards, onChange, beforeResolve, beforeNavigate, afterNavigate, beforeUpdateCurrent, afterUpdateCurrent, }) => {
|
|
385
|
-
return function routerInit() {
|
|
386
|
-
flatten(guards !== null && guards !== void 0 ? guards : []).forEach((guard) => router.registerGuard(guard));
|
|
387
|
-
flatten(onChange !== null && onChange !== void 0 ? onChange : []).forEach((hook) => router.registerSyncHook('change', hook));
|
|
388
|
-
flatten(beforeResolve !== null && beforeResolve !== void 0 ? beforeResolve : []).forEach((hook) => router.registerHook('beforeResolve', hook));
|
|
389
|
-
flatten(beforeNavigate !== null && beforeNavigate !== void 0 ? beforeNavigate : []).forEach((hook) => router.registerHook('beforeNavigate', hook));
|
|
390
|
-
flatten(afterNavigate !== null && afterNavigate !== void 0 ? afterNavigate : []).forEach((hook) => router.registerHook('afterNavigate', hook));
|
|
391
|
-
flatten(beforeUpdateCurrent !== null && beforeUpdateCurrent !== void 0 ? beforeUpdateCurrent : []).forEach((hook) => router.registerHook('beforeUpdateCurrent', hook));
|
|
392
|
-
flatten(afterUpdateCurrent !== null && afterUpdateCurrent !== void 0 ? afterUpdateCurrent : []).forEach((hook) => router.registerHook('afterUpdateCurrent', hook));
|
|
393
|
-
};
|
|
394
|
-
},
|
|
395
|
-
deps: {
|
|
396
|
-
router: ROUTER_TOKEN,
|
|
397
|
-
guards: {
|
|
398
|
-
token: ROUTER_GUARD_TOKEN,
|
|
399
|
-
optional: true,
|
|
400
|
-
},
|
|
401
|
-
onChange: {
|
|
402
|
-
token: onChangeHooksToken,
|
|
403
|
-
optional: true,
|
|
404
|
-
},
|
|
405
|
-
beforeResolve: {
|
|
406
|
-
token: beforeResolveHooksToken,
|
|
407
|
-
optional: true,
|
|
408
|
-
},
|
|
409
|
-
beforeNavigate: {
|
|
410
|
-
token: beforeNavigateHooksToken,
|
|
411
|
-
optional: true,
|
|
412
|
-
},
|
|
413
|
-
afterNavigate: {
|
|
414
|
-
token: afterNavigateHooksToken,
|
|
415
|
-
optional: true,
|
|
416
|
-
},
|
|
417
|
-
beforeUpdateCurrent: {
|
|
418
|
-
token: beforeUpdateCurrentHooksToken,
|
|
419
|
-
optional: true,
|
|
420
|
-
},
|
|
421
|
-
afterUpdateCurrent: {
|
|
422
|
-
token: afterUpdateCurrentHooksToken,
|
|
423
|
-
optional: true,
|
|
424
|
-
},
|
|
425
|
-
},
|
|
426
|
-
},
|
|
427
|
-
{
|
|
428
|
-
provide: commandLineListTokens.init,
|
|
429
|
-
multi: true,
|
|
430
|
-
useFactory: ({ logger }) => {
|
|
431
|
-
return function routerSetLogger() {
|
|
432
|
-
setLogger(logger('route:router'));
|
|
433
|
-
};
|
|
434
|
-
},
|
|
435
|
-
deps: {
|
|
436
|
-
logger: LOGGER_TOKEN,
|
|
437
|
-
},
|
|
438
|
-
},
|
|
439
|
-
{
|
|
440
|
-
provide: ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN,
|
|
441
|
-
// TODO: пока делаем after т.к. на это рассчитывает большинство приложений и у нас пока нет механизма контроля выполнения экшенов, чтобы
|
|
442
|
-
// избежать случаев зависания перехода из-за долгих экшенов
|
|
443
|
-
// рассмотреть возможность замены после доработок экшенов
|
|
444
|
-
useValue: 'after',
|
|
445
|
-
},
|
|
446
|
-
provide({
|
|
447
|
-
provide: PAGE_SERVICE_TOKEN,
|
|
448
|
-
useClass: PageService,
|
|
449
|
-
deps: {
|
|
450
|
-
router: ROUTER_TOKEN,
|
|
451
|
-
componentRegistry: COMPONENT_REGISTRY_TOKEN,
|
|
452
|
-
},
|
|
453
|
-
}),
|
|
454
|
-
{
|
|
455
|
-
provide: COMBINE_REDUCERS,
|
|
456
|
-
multi: true,
|
|
457
|
-
useValue: RouterStore,
|
|
458
|
-
},
|
|
459
|
-
];
|
|
460
|
-
|
|
461
|
-
const PREFETCHED_LINKS_CACHE_TOKEN = createToken$1();
|
|
462
|
-
const PREFETCHED_LINKS_QUEUE_TOKEN = createToken$1();
|
|
463
|
-
const prefetchProviders = [
|
|
464
|
-
provide({
|
|
465
|
-
provide: PREFETCHED_LINKS_CACHE_TOKEN,
|
|
466
|
-
useValue: new Set(),
|
|
467
|
-
}),
|
|
468
|
-
provide({
|
|
469
|
-
provide: PREFETCHED_LINKS_QUEUE_TOKEN,
|
|
470
|
-
useFactory: () => {
|
|
471
|
-
let queue = Promise.resolve();
|
|
472
|
-
return {
|
|
473
|
-
add(run) {
|
|
474
|
-
queue = queue.then(run);
|
|
475
|
-
return queue;
|
|
476
|
-
},
|
|
477
|
-
};
|
|
478
|
-
},
|
|
479
|
-
}),
|
|
480
|
-
provide({
|
|
481
|
-
provide: LINK_PREFETCH_MANAGER_TOKEN,
|
|
482
|
-
useFactory: ({ router, routeTransform, routeResolve, componentRegistry, bundleManager, logger, prefetchedLinksCache, prefetchedLinksQueue, }) => {
|
|
483
|
-
const log = logger('link-prefetch-manager');
|
|
484
|
-
const prefetch = async (url) => {
|
|
485
|
-
// prefetch needed for cache assets by browser, so we want to prefetch resources for any page only once.
|
|
486
|
-
// cache will work only for SPA-router, but anyway resources loading deduplication logic already included in @loadable
|
|
487
|
-
if (prefetchedLinksCache.has(url)) {
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
prefetchedLinksCache.add(url);
|
|
491
|
-
log.info({ event: 'prefetch-route-init', url });
|
|
492
|
-
// first, try to find static or resolved dynamic route
|
|
493
|
-
let route = router.resolve(url);
|
|
494
|
-
// if route not found, try to resolve dynamic route,
|
|
495
|
-
// logic from `ROUTER_TOKEN` provider factory, without `router.addRoute` method call
|
|
496
|
-
if (!route && routeResolve) {
|
|
497
|
-
// add query `prefetchRoute` to indicate to any `routeResolve` implementation
|
|
498
|
-
// that this route request no need to be cached or have any personalization
|
|
499
|
-
const parsedUrl = addQuery(url, { prefetchRoute: 'true' });
|
|
500
|
-
route = await routeResolve({
|
|
501
|
-
url: parsedUrl,
|
|
502
|
-
type: 'navigate',
|
|
503
|
-
});
|
|
504
|
-
if (route) {
|
|
505
|
-
route = routeTransform(route);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
if (!route) {
|
|
509
|
-
log.info({ event: 'prefetch-route-not-found', url });
|
|
510
|
-
return;
|
|
511
|
-
}
|
|
512
|
-
// @todo: очередь запросов!
|
|
513
|
-
// get name of everything what we need to prefetch,
|
|
514
|
-
// @loadable will load all scripts and styles for us
|
|
515
|
-
const { config: { pageComponent, bundle, nestedLayoutComponent }, } = route;
|
|
516
|
-
const promises = [];
|
|
517
|
-
// no need for bundle and page component actions amd reducers initialization,
|
|
518
|
-
// so copy only part of `modules/guards/common/loadBundle.ts` logic,
|
|
519
|
-
// all relative assets will be fetched
|
|
520
|
-
if (bundleManager.has(bundle, pageComponent)) {
|
|
521
|
-
promises.push(bundleManager.get(bundle, pageComponent));
|
|
522
|
-
}
|
|
523
|
-
// no need for nestedLayoutComponent actions amd reducers initialization,
|
|
524
|
-
// so copy only part of `modules/guards/common/loadBundle.ts` logic,
|
|
525
|
-
// all relative assets will be fetched
|
|
526
|
-
if (nestedLayoutComponent) {
|
|
527
|
-
promises.push(resolveLazyComponent(componentRegistry.get(nestedLayoutComponent, isFileSystemPageComponent(pageComponent) ? '__default' : bundle)));
|
|
528
|
-
}
|
|
529
|
-
await Promise.all(promises)
|
|
530
|
-
.then(() => {
|
|
531
|
-
log.info({ event: 'prefetch-route-success', url });
|
|
532
|
-
})
|
|
533
|
-
.catch((error) => {
|
|
534
|
-
log.warn({
|
|
535
|
-
event: 'prefetch-fail',
|
|
536
|
-
url,
|
|
537
|
-
error,
|
|
538
|
-
});
|
|
539
|
-
});
|
|
540
|
-
};
|
|
541
|
-
return {
|
|
542
|
-
prefetch: (url) => {
|
|
543
|
-
// fetch assets sequentially
|
|
544
|
-
return prefetchedLinksQueue.add(() => prefetch(url));
|
|
545
|
-
},
|
|
546
|
-
};
|
|
547
|
-
},
|
|
548
|
-
deps: {
|
|
549
|
-
router: ROUTER_TOKEN,
|
|
550
|
-
routeTransform: routeTransformToken,
|
|
551
|
-
routeResolve: {
|
|
552
|
-
token: ROUTE_RESOLVE_TOKEN,
|
|
553
|
-
optional: true,
|
|
554
|
-
},
|
|
555
|
-
componentRegistry: COMPONENT_REGISTRY_TOKEN,
|
|
556
|
-
bundleManager: BUNDLE_MANAGER_TOKEN,
|
|
557
|
-
logger: LOGGER_TOKEN,
|
|
558
|
-
prefetchedLinksCache: PREFETCHED_LINKS_CACHE_TOKEN,
|
|
559
|
-
prefetchedLinksQueue: PREFETCHED_LINKS_QUEUE_TOKEN,
|
|
560
|
-
},
|
|
561
|
-
}),
|
|
562
|
-
];
|
|
563
|
-
|
|
564
|
-
const clientTokens = [...prefetchProviders];
|
|
565
|
-
|
|
566
|
-
const stopRunAtError = (error) => {
|
|
567
|
-
if (isNotFoundError(error) || isRedirectFoundError(error)) {
|
|
568
|
-
return true;
|
|
569
|
-
}
|
|
570
|
-
};
|
|
571
|
-
const runActionsFactory = ({ store, router, actionRegistry, actionPageRunner, }) => {
|
|
572
|
-
return function runActions() {
|
|
573
|
-
const route = router.getCurrentRoute();
|
|
574
|
-
const { config: { bundle, pageComponent } = {} } = route;
|
|
575
|
-
if (!bundle || !pageComponent) {
|
|
576
|
-
throw new Error(`bundle and pageComponent should be defined, but got ${route}`);
|
|
577
|
-
}
|
|
578
|
-
const actions = uniq([
|
|
579
|
-
...(actionRegistry.getGlobal() || []),
|
|
580
|
-
...(actionRegistry.get(bundle) || []),
|
|
581
|
-
...(actionRegistry.get(pageComponent) || []),
|
|
582
|
-
]);
|
|
583
|
-
return actionPageRunner.runActions(actions, stopRunAtError).catch((err) => {
|
|
584
|
-
if (isRedirectFoundError(err)) {
|
|
585
|
-
return router.navigate({
|
|
586
|
-
url: err.nextUrl,
|
|
587
|
-
replace: true,
|
|
588
|
-
code: err.httpStatus,
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
throw err.error || err;
|
|
592
|
-
});
|
|
593
|
-
};
|
|
594
|
-
};
|
|
595
|
-
|
|
596
|
-
const providers = [
|
|
597
|
-
...clientTokens,
|
|
598
|
-
...providers$1,
|
|
599
|
-
provide({
|
|
600
|
-
provide: commandLineListTokens.customerStart,
|
|
601
|
-
multi: true,
|
|
602
|
-
useFactory: ({ router, store }) => {
|
|
603
|
-
return async function routerInit() {
|
|
604
|
-
const currentRoute = store.getState(RouterStore).currentRoute;
|
|
605
|
-
return router.rehydrate({
|
|
606
|
-
to: currentRoute,
|
|
607
|
-
});
|
|
608
|
-
};
|
|
609
|
-
},
|
|
610
|
-
deps: {
|
|
611
|
-
router: ROUTER_TOKEN,
|
|
612
|
-
store: STORE_TOKEN,
|
|
613
|
-
},
|
|
614
|
-
}),
|
|
615
|
-
provide({
|
|
616
|
-
// после выполнения надо включить исполнение роутинга, чтобы регидрация рендера реакта прошла успешно
|
|
617
|
-
// после этого уже можно будет делать переходы и т.д.
|
|
618
|
-
provide: commandLineListTokens.clear,
|
|
619
|
-
multi: true,
|
|
620
|
-
useFactory: ({ router, store }) => {
|
|
621
|
-
return function routerStart() {
|
|
622
|
-
const routerState = store.getState().router;
|
|
623
|
-
if (routerState.currentUrl.href !== window.location.href) {
|
|
624
|
-
store.dispatch(setUrlOnRehydrate(router.getCurrentUrl()));
|
|
625
|
-
}
|
|
626
|
-
return router.start();
|
|
627
|
-
};
|
|
628
|
-
},
|
|
629
|
-
deps: {
|
|
630
|
-
router: ROUTER_TOKEN,
|
|
631
|
-
store: STORE_TOKEN,
|
|
632
|
-
},
|
|
633
|
-
}),
|
|
634
|
-
provide({
|
|
635
|
-
// при первой загрузке страницы мы должны выполнить экшены уже после того произошла регидрация
|
|
636
|
-
// рендера реакта, т.к. экшены могут повлиять на рендер
|
|
637
|
-
provide: commandLineListTokens.clear,
|
|
638
|
-
multi: true,
|
|
639
|
-
useFactory: (deps) => {
|
|
640
|
-
const currentRoute = deps.store.getState(RouterStore).currentRoute;
|
|
641
|
-
// in client-side rendering mode, action will be executed on first navigation
|
|
642
|
-
if (deps.renderMode === 'client' &&
|
|
643
|
-
(!currentRoute || (currentRoute && currentRoute.actualPath !== window.location.pathname))) {
|
|
644
|
-
return noop;
|
|
645
|
-
}
|
|
646
|
-
return runActionsFactory(deps);
|
|
647
|
-
},
|
|
648
|
-
deps: {
|
|
649
|
-
store: STORE_TOKEN,
|
|
650
|
-
router: ROUTER_TOKEN,
|
|
651
|
-
actionRegistry: ACTION_REGISTRY_TOKEN,
|
|
652
|
-
actionPageRunner: ACTION_PAGE_RUNNER_TOKEN,
|
|
653
|
-
renderMode: TRAMVAI_RENDER_MODE,
|
|
654
|
-
},
|
|
655
|
-
}),
|
|
656
|
-
provide({
|
|
657
|
-
provide: commandLineListTokens.clear,
|
|
658
|
-
multi: true,
|
|
659
|
-
useFactory: ({ store, router, renderMode }) => {
|
|
660
|
-
return async function csrFirstNavigation() {
|
|
661
|
-
const currentRoute = store.getState(RouterStore).currentRoute;
|
|
662
|
-
// in client-side rendering mode, if current route inconsistent with current location,
|
|
663
|
-
// run navigation to current location.
|
|
664
|
-
if (renderMode === 'client' &&
|
|
665
|
-
(!currentRoute || (currentRoute && currentRoute.actualPath !== window.location.pathname))) {
|
|
666
|
-
// replace because otherwice we will push in the history the same url twice,
|
|
667
|
-
// and history.back will return to the same url
|
|
668
|
-
return router.navigate({ url: window.location.href, replace: true });
|
|
669
|
-
}
|
|
670
|
-
};
|
|
671
|
-
},
|
|
672
|
-
deps: {
|
|
673
|
-
store: STORE_TOKEN,
|
|
674
|
-
router: ROUTER_TOKEN,
|
|
675
|
-
renderMode: TRAMVAI_RENDER_MODE,
|
|
676
|
-
},
|
|
677
|
-
}),
|
|
678
|
-
];
|
|
679
|
-
|
|
680
|
-
const generateForRoot = (mainModule) => {
|
|
681
|
-
return (routes, options = {}) => {
|
|
682
|
-
return {
|
|
683
|
-
mainModule,
|
|
684
|
-
providers: [
|
|
685
|
-
{
|
|
686
|
-
provide: ROUTES_TOKEN,
|
|
687
|
-
multi: true,
|
|
688
|
-
useValue: routes,
|
|
689
|
-
},
|
|
690
|
-
options.spaActionsMode && {
|
|
691
|
-
provide: ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN,
|
|
692
|
-
useValue: options.spaActionsMode,
|
|
693
|
-
},
|
|
694
|
-
].filter(Boolean),
|
|
695
|
-
};
|
|
696
|
-
};
|
|
697
|
-
};
|
|
698
|
-
|
|
699
|
-
var _a$1;
|
|
700
|
-
const NoSpaRouterModule = /* @__PURE__ */ Module({
|
|
701
|
-
providers: [
|
|
702
|
-
...providers,
|
|
703
|
-
{
|
|
704
|
-
provide: routerClassToken,
|
|
705
|
-
useValue: NoSpaRouter,
|
|
706
|
-
},
|
|
707
|
-
],
|
|
708
|
-
})((_a$1 = class NoSpaRouterModule {
|
|
709
|
-
},
|
|
710
|
-
_a$1.forRoot = generateForRoot(_a$1),
|
|
711
|
-
_a$1));
|
|
712
|
-
|
|
713
|
-
const runCommandsSpa = ({ commandLineRunner, di, }) => {
|
|
714
|
-
return async () => {
|
|
715
|
-
await commandLineRunner.run('client', 'spa', [], di);
|
|
716
|
-
};
|
|
717
|
-
};
|
|
718
|
-
const runCommandsAfterSpa = ({ commandLineRunner, di, }) => {
|
|
719
|
-
return async () => {
|
|
720
|
-
await commandLineRunner.run('client', 'afterSpa', [], di);
|
|
721
|
-
};
|
|
722
|
-
};
|
|
723
|
-
|
|
724
|
-
const spaHooks = [
|
|
725
|
-
{
|
|
726
|
-
provide: beforeNavigateHooksToken,
|
|
727
|
-
multi: true,
|
|
728
|
-
useFactory: runCommandsSpa,
|
|
729
|
-
deps: {
|
|
730
|
-
di: DI_TOKEN,
|
|
731
|
-
commandLineRunner: COMMAND_LINE_RUNNER_TOKEN,
|
|
732
|
-
},
|
|
733
|
-
},
|
|
734
|
-
{
|
|
735
|
-
provide: afterNavigateHooksToken,
|
|
736
|
-
multi: true,
|
|
737
|
-
useFactory: runCommandsAfterSpa,
|
|
738
|
-
deps: {
|
|
739
|
-
di: DI_TOKEN,
|
|
740
|
-
commandLineRunner: COMMAND_LINE_RUNNER_TOKEN,
|
|
741
|
-
},
|
|
742
|
-
},
|
|
743
|
-
{
|
|
744
|
-
provide: commandLineListTokens.spaTransition,
|
|
745
|
-
multi: true,
|
|
746
|
-
useFactory: ({ spaMode, ...deps }) => {
|
|
747
|
-
if (spaMode !== 'after') {
|
|
748
|
-
return runActionsFactory(deps);
|
|
749
|
-
}
|
|
750
|
-
return noop;
|
|
751
|
-
},
|
|
752
|
-
deps: {
|
|
753
|
-
store: STORE_TOKEN,
|
|
754
|
-
router: ROUTER_TOKEN,
|
|
755
|
-
actionRegistry: ACTION_REGISTRY_TOKEN,
|
|
756
|
-
actionPageRunner: ACTION_PAGE_RUNNER_TOKEN,
|
|
757
|
-
spaMode: {
|
|
758
|
-
token: ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN,
|
|
759
|
-
optional: true,
|
|
760
|
-
},
|
|
761
|
-
},
|
|
762
|
-
},
|
|
763
|
-
{
|
|
764
|
-
provide: commandLineListTokens.afterSpaTransition,
|
|
765
|
-
multi: true,
|
|
766
|
-
useFactory: ({ spaMode, ...deps }) => {
|
|
767
|
-
if (spaMode === 'after') {
|
|
768
|
-
return runActionsFactory(deps);
|
|
769
|
-
}
|
|
770
|
-
return noop;
|
|
771
|
-
},
|
|
772
|
-
deps: {
|
|
773
|
-
store: STORE_TOKEN,
|
|
774
|
-
router: ROUTER_TOKEN,
|
|
775
|
-
actionRegistry: ACTION_REGISTRY_TOKEN,
|
|
776
|
-
actionPageRunner: ACTION_PAGE_RUNNER_TOKEN,
|
|
777
|
-
spaMode: {
|
|
778
|
-
token: ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN,
|
|
779
|
-
optional: true,
|
|
780
|
-
},
|
|
781
|
-
},
|
|
782
|
-
},
|
|
783
|
-
];
|
|
784
|
-
|
|
785
|
-
var _a;
|
|
786
|
-
const SpaRouterModule = /* @__PURE__ */ Module({
|
|
787
|
-
providers: [
|
|
788
|
-
...providers,
|
|
789
|
-
...spaHooks,
|
|
790
|
-
{
|
|
791
|
-
provide: routerClassToken,
|
|
792
|
-
useValue: Router,
|
|
793
|
-
},
|
|
794
|
-
],
|
|
795
|
-
})((_a = class SpaRouterModule {
|
|
796
|
-
},
|
|
797
|
-
_a.forRoot = generateForRoot(_a),
|
|
798
|
-
_a));
|
|
799
|
-
|
|
800
|
-
let RouterChildAppModule = class RouterChildAppModule {
|
|
801
|
-
};
|
|
802
|
-
RouterChildAppModule = __decorate([
|
|
803
|
-
Module({
|
|
804
|
-
providers: [
|
|
805
|
-
provide({
|
|
806
|
-
provide: EXTEND_RENDER,
|
|
807
|
-
multi: true,
|
|
808
|
-
useFactory: provideRouter,
|
|
809
|
-
deps: {
|
|
810
|
-
router: ROUTER_TOKEN,
|
|
811
|
-
},
|
|
812
|
-
}),
|
|
813
|
-
{
|
|
814
|
-
provide: CHILD_APP_INTERNAL_ROOT_STATE_ALLOWED_STORE_TOKEN,
|
|
815
|
-
multi: true,
|
|
816
|
-
useValue: RouterStore,
|
|
817
|
-
},
|
|
818
|
-
],
|
|
819
|
-
})
|
|
820
|
-
], RouterChildAppModule);
|
|
821
|
-
|
|
822
|
-
const requestIdleCallback = window.requestIdleCallback ||
|
|
823
|
-
function (callback) {
|
|
824
|
-
return window.setTimeout(callback, 1);
|
|
825
|
-
};
|
|
826
|
-
const cancelIdleCallback = window.cancelIdleCallback ||
|
|
827
|
-
function (timer) {
|
|
828
|
-
return window.clearTimeout(timer);
|
|
829
|
-
};
|
|
830
|
-
|
|
831
|
-
const isUserNetworkConditionsSuitableForPrefetch = () => {
|
|
832
|
-
var _a;
|
|
833
|
-
const { saveData, effectiveType = '' } = (_a = navigator.connection) !== null && _a !== void 0 ? _a : {};
|
|
834
|
-
return !saveData && !(effectiveType === '2g' || effectiveType === 'slow-2g');
|
|
835
|
-
};
|
|
836
|
-
const usePrefetch = ({ url, target, prefetch, }) => {
|
|
837
|
-
const linkPrefetchManager = useDi(optional(LINK_PREFETCH_MANAGER_TOKEN));
|
|
838
|
-
useEffect(() => {
|
|
839
|
-
if (!target || !prefetch || !linkPrefetchManager) {
|
|
840
|
-
return;
|
|
841
|
-
}
|
|
842
|
-
let idleId = null;
|
|
843
|
-
const observer = new IntersectionObserver((entries) => {
|
|
844
|
-
entries.forEach((entry) => {
|
|
845
|
-
// when `Link` element in viewport
|
|
846
|
-
if (entry.isIntersecting && entry.intersectionRatio > 0) {
|
|
847
|
-
// only once
|
|
848
|
-
observer.disconnect();
|
|
849
|
-
if (isUserNetworkConditionsSuitableForPrefetch()) {
|
|
850
|
-
// trigger prefetching when browser is idle
|
|
851
|
-
idleId = requestIdleCallback(() => {
|
|
852
|
-
linkPrefetchManager.prefetch(url);
|
|
853
|
-
});
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
});
|
|
857
|
-
});
|
|
858
|
-
observer.observe(target);
|
|
859
|
-
return () => {
|
|
860
|
-
observer.disconnect();
|
|
861
|
-
cancelIdleCallback(idleId);
|
|
862
|
-
};
|
|
863
|
-
}, [url, target, prefetch, linkPrefetchManager]);
|
|
864
|
-
};
|
|
865
|
-
|
|
866
|
-
function Link(props) {
|
|
867
|
-
const { children, onClick, url, query, replace, target, navigateOptions, prefetch = true, ...otherProps } = props;
|
|
868
|
-
const navigate = useNavigate({ url, query, replace, ...navigateOptions });
|
|
869
|
-
const [linkElement, setLinkElement] = useState(null);
|
|
870
|
-
usePrefetch({
|
|
871
|
-
url,
|
|
872
|
-
prefetch,
|
|
873
|
-
target: linkElement,
|
|
874
|
-
});
|
|
875
|
-
const handleClick = useCallback((event) => {
|
|
876
|
-
// ignores the navigation when clicked using right mouse button or
|
|
877
|
-
// by holding a special modifier key: ctrl, command, win, alt, shift
|
|
878
|
-
if (target ||
|
|
879
|
-
event.ctrlKey ||
|
|
880
|
-
event.metaKey ||
|
|
881
|
-
event.altKey ||
|
|
882
|
-
event.shiftKey ||
|
|
883
|
-
event.button !== 0) {
|
|
884
|
-
return;
|
|
885
|
-
}
|
|
886
|
-
event.preventDefault();
|
|
887
|
-
navigate();
|
|
888
|
-
onClick && onClick(event);
|
|
889
|
-
}, [navigate, target, onClick]);
|
|
890
|
-
const extraProps = { href: url, onClick: handleClick, target };
|
|
891
|
-
if (isValidElement(children)) {
|
|
892
|
-
return cloneElement(children, {
|
|
893
|
-
// @ts-expect-error
|
|
894
|
-
ref: (element) => {
|
|
895
|
-
// @ts-expect-error
|
|
896
|
-
const { ref } = children;
|
|
897
|
-
// preserve original ref
|
|
898
|
-
if (typeof ref === 'function') {
|
|
899
|
-
ref(element);
|
|
900
|
-
}
|
|
901
|
-
else if (typeof ref === 'object' && ref !== null) {
|
|
902
|
-
ref.current = element;
|
|
903
|
-
}
|
|
904
|
-
setLinkElement(element);
|
|
905
|
-
},
|
|
906
|
-
...extraProps,
|
|
907
|
-
});
|
|
908
|
-
}
|
|
909
|
-
return (
|
|
910
|
-
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
911
|
-
jsx("a", { ref: (element) => setLinkElement(element), ...otherProps, ...extraProps, children: children }));
|
|
912
|
-
}
|
|
913
|
-
Link.displayName = 'Link';
|
|
914
|
-
|
|
915
|
-
const usePageService = () => {
|
|
916
|
-
useRoute();
|
|
917
|
-
return useDi(PAGE_SERVICE_TOKEN);
|
|
918
|
-
};
|
|
919
|
-
|
|
920
|
-
export { Link, NoSpaRouterModule, RouterChildAppModule, RouterStore, SpaRouterModule, generateForRoot, setCurrentNavigation, setUrlOnRehydrate, usePageService };
|
|
7
|
+
export { generateForRoot } from './modules/utils/forRoot.browser.js';
|
|
8
|
+
export { RouterStore, setCurrentNavigation, setUrlOnRehydrate } from './stores/RouterStore.browser.js';
|
|
9
|
+
export { usePageService } from './hooks/usePageService.browser.js';
|