@tramvai/module-router 2.70.0 → 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.
Files changed (91) hide show
  1. package/lib/components/link.browser.js +55 -0
  2. package/lib/components/link.es.js +49 -0
  3. package/lib/components/link.js +53 -0
  4. package/lib/hooks/usePageService.browser.js +10 -0
  5. package/lib/hooks/usePageService.es.js +10 -0
  6. package/lib/hooks/usePageService.js +14 -0
  7. package/lib/hooks/usePrefetch.browser.browser.js +42 -0
  8. package/lib/index.browser.js +7 -906
  9. package/lib/index.es.js +6 -764
  10. package/lib/index.js +34 -788
  11. package/lib/modules/child-app.browser.js +31 -0
  12. package/lib/modules/child-app.es.js +31 -0
  13. package/lib/modules/child-app.js +33 -0
  14. package/lib/modules/clientCommon.browser.js +70 -0
  15. package/lib/modules/common.browser.js +137 -0
  16. package/lib/modules/common.es.js +137 -0
  17. package/lib/modules/common.js +145 -0
  18. package/lib/modules/fileSystemPages.browser.js +27 -0
  19. package/lib/modules/fileSystemPages.es.js +27 -0
  20. package/lib/modules/fileSystemPages.js +31 -0
  21. package/lib/modules/guards/common/index.browser.js +32 -0
  22. package/lib/modules/guards/common/index.es.js +32 -0
  23. package/lib/modules/guards/common/index.js +36 -0
  24. package/lib/modules/guards/common/internalError.browser.js +14 -0
  25. package/lib/modules/guards/common/internalError.es.js +14 -0
  26. package/lib/modules/guards/common/internalError.js +18 -0
  27. package/lib/modules/guards/common/loadBundle.browser.js +67 -0
  28. package/lib/modules/guards/common/loadBundle.es.js +67 -0
  29. package/lib/modules/guards/common/loadBundle.js +75 -0
  30. package/lib/modules/guards/server/httpMethod.es.js +20 -0
  31. package/lib/modules/guards/server/httpMethod.js +24 -0
  32. package/lib/modules/guards/server/index.es.js +18 -0
  33. package/lib/modules/guards/server/index.js +22 -0
  34. package/lib/modules/hooks/common/fillRouterStore.browser.js +9 -0
  35. package/lib/modules/hooks/common/fillRouterStore.es.js +9 -0
  36. package/lib/modules/hooks/common/fillRouterStore.js +13 -0
  37. package/lib/modules/hooks/common/index.browser.js +16 -0
  38. package/lib/modules/hooks/common/index.es.js +16 -0
  39. package/lib/modules/hooks/common/index.js +20 -0
  40. package/lib/modules/hooks/runActions.browser.js +34 -0
  41. package/lib/modules/hooks/runActions.es.js +34 -0
  42. package/lib/modules/hooks/runActions.js +42 -0
  43. package/lib/modules/hooks/server/httpStatus.es.js +7 -0
  44. package/lib/modules/hooks/server/httpStatus.js +11 -0
  45. package/lib/modules/hooks/server/index.es.js +17 -0
  46. package/lib/modules/hooks/server/index.js +21 -0
  47. package/lib/modules/hooks/spa/index.browser.js +70 -0
  48. package/lib/modules/hooks/spa/runCommands.browser.js +12 -0
  49. package/lib/modules/no-spa.browser.js +21 -0
  50. package/lib/modules/server.es.js +59 -0
  51. package/lib/modules/server.js +63 -0
  52. package/lib/modules/spa.browser.js +23 -0
  53. package/lib/modules/tokens/browser/index.browser.js +5 -0
  54. package/lib/modules/tokens/browser/prefetch.browser.js +112 -0
  55. package/lib/modules/tokens/common/index.browser.js +40 -0
  56. package/lib/modules/tokens/common/index.es.js +40 -0
  57. package/lib/modules/tokens/common/index.js +44 -0
  58. package/lib/modules/tokens/common/render.browser.js +14 -0
  59. package/lib/modules/tokens/common/render.es.js +14 -0
  60. package/lib/modules/tokens/common/render.js +18 -0
  61. package/lib/modules/tokens/common/routeNormalize.browser.js +10 -0
  62. package/lib/modules/tokens/common/routeNormalize.es.js +10 -0
  63. package/lib/modules/tokens/common/routeNormalize.js +18 -0
  64. package/lib/modules/tokens/common/routeSetDefaults.browser.js +13 -0
  65. package/lib/modules/tokens/common/routeSetDefaults.es.js +13 -0
  66. package/lib/modules/tokens/common/routeSetDefaults.js +17 -0
  67. package/lib/modules/tokens/common/routeTransform.browser.js +12 -0
  68. package/lib/modules/tokens/common/routeTransform.es.js +12 -0
  69. package/lib/modules/tokens/common/routeTransform.js +22 -0
  70. package/lib/modules/tokens/server/bundleInfo.es.js +35 -0
  71. package/lib/modules/tokens/server/bundleInfo.js +44 -0
  72. package/lib/modules/tokens/server/index.es.js +25 -0
  73. package/lib/modules/tokens/server/index.js +29 -0
  74. package/lib/modules/tokens/server/prefetch.es.js +15 -0
  75. package/lib/modules/tokens/server/prefetch.js +19 -0
  76. package/lib/modules/tokens/server/routerOptions.es.js +37 -0
  77. package/lib/modules/tokens/server/routerOptions.js +41 -0
  78. package/lib/modules/tokens.browser.js +22 -0
  79. package/lib/modules/tokens.es.js +22 -0
  80. package/lib/modules/tokens.js +35 -0
  81. package/lib/modules/utils/forRoot.browser.js +22 -0
  82. package/lib/modules/utils/forRoot.es.js +22 -0
  83. package/lib/modules/utils/forRoot.js +26 -0
  84. package/lib/services/page.browser.js +63 -0
  85. package/lib/services/page.es.js +63 -0
  86. package/lib/services/page.js +67 -0
  87. package/lib/stores/RouterStore.browser.js +29 -0
  88. package/lib/stores/RouterStore.es.js +29 -0
  89. package/lib/stores/RouterStore.js +35 -0
  90. package/lib/utils/requestIdleCallback.browser.js +10 -0
  91. package/package.json +22 -23
package/lib/index.es.js CHANGED
@@ -1,766 +1,8 @@
1
- import { __decorate } from 'tslib';
2
- import { provide, commandLineListTokens, Module } from '@tramvai/core';
3
- import { Provider, setLogger, isWildcard, isHistoryFallback, Router, useNavigate, useRoute } from '@tinkoff/router';
1
+ export { NoSpaRouterModule, SpaRouterModule } from './modules/server.es.js';
2
+ export { RouterChildAppModule } from './modules/child-app.es.js';
4
3
  export { Provider, useNavigate, useRoute, useRouter, useUrl } from '@tinkoff/router';
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, REQUEST_MANAGER_TOKEN, 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';
4
+ export { Link } from './components/link.es.js';
7
5
  export * from '@tramvai/tokens-router';
8
- import flatten from '@tinkoff/utils/array/flatten';
9
- import { createToken } from '@tinkoff/dippy';
10
- import { createEvent, createReducer } from '@tramvai/state';
11
- import isArray from '@tinkoff/utils/is/array';
12
- import { resolveLazyComponent, useDi } from '@tramvai/react';
13
- import { EXTEND_RENDER } from '@tramvai/tokens-render';
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 uniq from '@tinkoff/utils/array/uniq';
20
- import { isRedirectFoundError, isNotFoundError, RedirectFoundError, makeErrorSilent, HttpError } from '@tinkoff/errors';
21
- import { SERVER_MODULE_PAPI_PUBLIC_ROUTE } from '@tramvai/tokens-server';
22
- import prop from '@tinkoff/utils/object/prop';
23
- import { createPapiMethod } from '@tramvai/papi';
24
- import { CHILD_APP_INTERNAL_ROOT_STATE_ALLOWED_STORE_TOKEN } from '@tramvai/tokens-child-app';
25
- import { useState, useCallback, isValidElement, cloneElement } from 'react';
26
-
27
- const routerClassToken = createToken('router routerClassToken');
28
- const additionalRouterParameters = createToken('router additionalParameters');
29
- const onChangeHooksToken = createToken('router onChangeHooks', {
30
- multi: true,
31
- });
32
- const beforeResolveHooksToken = createToken('router beforeResolveHooks', {
33
- multi: true,
34
- });
35
- const beforeNavigateHooksToken = createToken('router beforeNavigateHooks', {
36
- multi: true,
37
- });
38
- const afterNavigateHooksToken = createToken('router afterNavigateHooks', {
39
- multi: true,
40
- });
41
- const beforeUpdateCurrentHooksToken = createToken('router beforeUpdateCurrentHooks', { multi: true });
42
- const afterUpdateCurrentHooksToken = createToken('router afterUpdateCurrentHooks', { multi: true });
43
- const routeTransformToken = createToken('router finalRouteTransform');
44
- const routerBundleInfoAdditionalToken = createToken('router bundleInfoAdditional');
45
-
46
- const setCurrentNavigation = createEvent('SET_CURRENT_ROUTE');
47
- const setUrlOnRehydrate = createEvent('SET_URL_ON_REHYDRATE');
48
- const initialState = {
49
- currentRoute: null,
50
- previousRoute: null,
51
- currentUrl: null,
52
- previousUrl: null,
53
- };
54
- const RouterStore = createReducer('router', initialState)
55
- .on(setCurrentNavigation, (state, { to, from, url, fromUrl, replace }) => {
56
- // TODO: убедиться что все данные нам нужны из роутинга,
57
- // возможно всякие meta, content не нужны при дегидрации
58
- return {
59
- currentRoute: to,
60
- previousRoute: replace ? state.previousRoute : from,
61
- currentUrl: url,
62
- previousUrl: replace ? state.previousUrl : fromUrl,
63
- };
64
- })
65
- .on(setUrlOnRehydrate, (state, url) => {
66
- return {
67
- ...state,
68
- currentUrl: url,
69
- };
70
- });
71
-
72
- const loadBundle = ({ bundleManager, logger, actionRegistry, responseManager, dispatcher, dispatcherContext, pageService, }) => {
73
- const log = logger('route:load-bundles');
74
- return async ({ to }) => {
75
- var _a;
76
- log.debug({
77
- event: 'load-bundle',
78
- route: to,
79
- });
80
- const { bundle, pageComponent, nestedLayoutComponent } = to.config;
81
- if (!bundleManager.has(bundle, pageComponent)) {
82
- log.info({
83
- event: 'load-bundle-not-found',
84
- bundle,
85
- pageComponent,
86
- });
87
- // если бандл не найден, то всё ок и мы должны вернуть 404 на сервере,
88
- // а на клиенте просто загрузить новую страницу
89
- responseManager.setStatus(404);
90
- return false;
91
- }
92
- // Пытаемся загрузить и в случае инициализации на клиенте, т.к.
93
- // несмотря на наличие бандла в разметке, все равно мы должны дождаться
94
- // его загрузки перед рендером
95
- try {
96
- const promises = [];
97
- // for file-system pages bundle is virtual, so it will be loaded in parallel with nested layout
98
- // for classic bundles, page component will be loaded after bundle loading
99
- promises.push(bundleManager.get(bundle, pageComponent));
100
- if (nestedLayoutComponent) {
101
- promises.push(resolveLazyComponent(pageService.resolveComponentFromConfig('nestedLayout')));
102
- }
103
- const [resolvedBundle, resolvedLayout] = await Promise.all(promises);
104
- const { components, reducers } = resolvedBundle;
105
- const component = components[pageComponent];
106
- // pageComponent should have required fields even if it is lazy,
107
- // thanks to `git log 9466cb32bfb71ba49144ef839d3d5bce246e213c -L90,103:packages/modules/common/src/bundleManager/bundleManager.ts`
108
- (_a = component === null || component === void 0 ? void 0 : component.reducers) === null || _a === void 0 ? void 0 : _a.forEach((reducer) => dispatcherContext.getStore(reducer));
109
- reducers === null || reducers === void 0 ? void 0 : reducers.forEach((reducer) => dispatcherContext.getStore(reducer));
110
- // @todo: reuse logic from bundleManager?
111
- // register nested layout actions and reducers for current page
112
- if (resolvedLayout) {
113
- if ('actions' in resolvedLayout && isArray(resolvedLayout.actions)) {
114
- actionRegistry.add(pageComponent, resolvedLayout.actions);
115
- }
116
- if ('reducers' in resolvedLayout && isArray(resolvedLayout.reducers)) {
117
- resolvedLayout.reducers.forEach((reducer) => {
118
- dispatcher.registerStore(reducer);
119
- dispatcherContext.getStore(reducer);
120
- });
121
- }
122
- }
123
- }
124
- catch (error) {
125
- log.error({
126
- event: 'load-bundle-failed',
127
- error,
128
- });
129
- // блокируем переход если не удалось загрузить бандл
130
- return false;
131
- }
132
- };
133
- };
134
-
135
- const internalError = ({ responseManager, logger, }) => {
136
- const log = logger('route:guard-check-error');
137
- return async () => {
138
- if (responseManager.getStatus() >= 500) {
139
- log.error({
140
- event: 'status-is-error',
141
- status: responseManager.getStatus(),
142
- });
143
- return false;
144
- }
145
- };
146
- };
147
-
148
- const commonGuards = [
149
- {
150
- provide: ROUTER_GUARD_TOKEN,
151
- multi: true,
152
- useFactory: loadBundle,
153
- deps: {
154
- logger: LOGGER_TOKEN,
155
- bundleManager: BUNDLE_MANAGER_TOKEN,
156
- actionRegistry: ACTION_REGISTRY_TOKEN,
157
- responseManager: RESPONSE_MANAGER_TOKEN,
158
- dispatcher: DISPATCHER_TOKEN,
159
- dispatcherContext: DISPATCHER_CONTEXT_TOKEN,
160
- pageService: PAGE_SERVICE_TOKEN,
161
- },
162
- },
163
- {
164
- provide: ROUTER_GUARD_TOKEN,
165
- multi: true,
166
- useFactory: internalError,
167
- deps: {
168
- logger: LOGGER_TOKEN,
169
- responseManager: RESPONSE_MANAGER_TOKEN,
170
- },
171
- },
172
- ];
173
-
174
- const fillRouterStore = ({ context, }) => {
175
- return (navigation) => {
176
- context.dispatch(setCurrentNavigation(navigation));
177
- };
178
- };
179
-
180
- const commonHooks = [
181
- {
182
- provide: onChangeHooksToken,
183
- multi: true,
184
- useFactory: fillRouterStore,
185
- deps: {
186
- context: CONTEXT_TOKEN,
187
- },
188
- },
189
- ];
190
-
191
- const routeTransform = ({ transformers, }) => {
192
- if (!transformers || transformers.length === 0) {
193
- return identity;
194
- }
195
- return compose(...flatten(transformers));
196
- };
197
-
198
- const routeSetDefaults = (route) => {
199
- const config = {
200
- bundle: 'mainDefault',
201
- pageComponent: 'pageDefault',
202
- ...route.config,
203
- };
204
- return {
205
- ...route,
206
- config,
207
- };
208
- };
209
-
210
- const routeNormalize = (route) => {
211
- return {
212
- ...route,
213
- path: replace(/\/?$/, '/', route.path),
214
- };
215
- };
216
-
217
- const provideRouter = ({ router }) => {
218
- const serverState = {
219
- currentRoute: router.getCurrentRoute(),
220
- currentUrl: router.getCurrentUrl(),
221
- };
222
- return (render) => {
223
- return (jsx(Provider, { router: router, serverState: serverState, children: render }));
224
- };
225
- };
226
-
227
- const commonTokens = [
228
- {
229
- provide: routeTransformToken,
230
- useFactory: routeTransform,
231
- deps: {
232
- transformers: {
233
- token: ROUTE_TRANSFORM_TOKEN,
234
- optional: true,
235
- },
236
- },
237
- },
238
- {
239
- provide: ROUTE_TRANSFORM_TOKEN,
240
- multi: true,
241
- useValue: routeSetDefaults,
242
- },
243
- {
244
- provide: ROUTE_TRANSFORM_TOKEN,
245
- multi: true,
246
- useValue: routeNormalize,
247
- },
248
- {
249
- provide: EXTEND_RENDER,
250
- multi: true,
251
- useFactory: provideRouter,
252
- deps: {
253
- router: ROUTER_TOKEN,
254
- },
255
- },
256
- ];
257
-
258
- class PageService {
259
- constructor({ router, componentRegistry }) {
260
- this.router = router;
261
- this.componentRegistry = componentRegistry;
262
- }
263
- getCurrentRoute() {
264
- return this.router.getCurrentRoute();
265
- }
266
- getCurrentUrl() {
267
- return this.router.getCurrentUrl();
268
- }
269
- getConfig() {
270
- var _a, _b;
271
- return (_b = (_a = this.getCurrentRoute()) === null || _a === void 0 ? void 0 : _a.config) !== null && _b !== void 0 ? _b : {};
272
- }
273
- getContent() {
274
- var _a;
275
- return (_a = this.getConfig().content) !== null && _a !== void 0 ? _a : {};
276
- }
277
- getMeta() {
278
- var _a;
279
- return (_a = this.getConfig().meta) !== null && _a !== void 0 ? _a : {};
280
- }
281
- navigate(options) {
282
- return this.router.navigate(options);
283
- }
284
- updateCurrentRoute(options) {
285
- return this.router.updateCurrentRoute(options);
286
- }
287
- back(options) {
288
- return this.router.back(options);
289
- }
290
- forward() {
291
- return this.router.forward();
292
- }
293
- go(to, options) {
294
- return this.router.go(to, options);
295
- }
296
- addComponent(name, component) {
297
- const group = this.getComponentsGroupName();
298
- return this.componentRegistry.add(name, component, group);
299
- }
300
- getComponent(name) {
301
- const group = this.getComponentsGroupName();
302
- return this.componentRegistry.get(name, group);
303
- }
304
- resolveComponentFromConfig(property) {
305
- var _a;
306
- const configName = `${property}Component`;
307
- const defaultComponent = `${property}Default`;
308
- const componentName = (_a = this.getConfig()[configName]) !== null && _a !== void 0 ? _a : defaultComponent;
309
- return this.getComponent(componentName) || this.getComponent(defaultComponent);
310
- }
311
- getComponentsGroupName() {
312
- const { bundle, pageComponent } = this.getConfig();
313
- const group = isFileSystemPageComponent(pageComponent) ? pageComponent : bundle;
314
- return group;
315
- }
316
- }
317
-
318
- const providers$1 = [
319
- fileSystemPagesEnabled() &&
320
- provide({
321
- provide: ROUTES_TOKEN,
322
- multi: true,
323
- useFactory: ({ logger }) => {
324
- const log = logger('file-system-pages:route');
325
- const pagesNames = Object.keys(getStaticFileSystemPages());
326
- const routes = pagesNames.map(fileSystemPageToRoute);
327
- log.debug({
328
- event: 'create static routes from file-system pages',
329
- routes,
330
- });
331
- return routes;
332
- },
333
- deps: {
334
- logger: LOGGER_TOKEN,
335
- },
336
- }),
337
- ].filter(Boolean);
338
-
339
- const providers = [
340
- ...commonGuards,
341
- ...commonHooks,
342
- ...commonTokens,
343
- ...providers$1,
344
- {
345
- provide: ROUTER_TOKEN,
346
- useFactory: ({ RouterClass, routes, routeTransform, routeResolve, additionalParameters, }) => {
347
- const router = new RouterClass({
348
- ...additionalParameters,
349
- trailingSlash: true,
350
- mergeSlashes: true,
351
- routes: flatten(routes !== null && routes !== void 0 ? routes : []).map(routeTransform),
352
- });
353
- if (routeResolve) {
354
- router.registerHook('beforeResolve', async (navigation) => {
355
- if (!router.resolve(navigation.url.href)) {
356
- const route = await routeResolve(navigation);
357
- if (route) {
358
- router.addRoute(routeTransform(route));
359
- }
360
- }
361
- });
362
- }
363
- return router;
364
- },
365
- deps: {
366
- RouterClass: routerClassToken,
367
- additionalParameters: {
368
- token: additionalRouterParameters,
369
- optional: true,
370
- },
371
- routes: {
372
- token: ROUTES_TOKEN,
373
- optional: true,
374
- },
375
- routeTransform: routeTransformToken,
376
- routeResolve: {
377
- token: ROUTE_RESOLVE_TOKEN,
378
- optional: true,
379
- },
380
- },
381
- },
382
- {
383
- provide: commandLineListTokens.customerStart,
384
- multi: true,
385
- useFactory: ({ router, guards, onChange, beforeResolve, beforeNavigate, afterNavigate, beforeUpdateCurrent, afterUpdateCurrent, }) => {
386
- return function routerInit() {
387
- flatten(guards !== null && guards !== void 0 ? guards : []).forEach((guard) => router.registerGuard(guard));
388
- flatten(onChange !== null && onChange !== void 0 ? onChange : []).forEach((hook) => router.registerSyncHook('change', hook));
389
- flatten(beforeResolve !== null && beforeResolve !== void 0 ? beforeResolve : []).forEach((hook) => router.registerHook('beforeResolve', hook));
390
- flatten(beforeNavigate !== null && beforeNavigate !== void 0 ? beforeNavigate : []).forEach((hook) => router.registerHook('beforeNavigate', hook));
391
- flatten(afterNavigate !== null && afterNavigate !== void 0 ? afterNavigate : []).forEach((hook) => router.registerHook('afterNavigate', hook));
392
- flatten(beforeUpdateCurrent !== null && beforeUpdateCurrent !== void 0 ? beforeUpdateCurrent : []).forEach((hook) => router.registerHook('beforeUpdateCurrent', hook));
393
- flatten(afterUpdateCurrent !== null && afterUpdateCurrent !== void 0 ? afterUpdateCurrent : []).forEach((hook) => router.registerHook('afterUpdateCurrent', hook));
394
- };
395
- },
396
- deps: {
397
- router: ROUTER_TOKEN,
398
- guards: {
399
- token: ROUTER_GUARD_TOKEN,
400
- optional: true,
401
- },
402
- onChange: {
403
- token: onChangeHooksToken,
404
- optional: true,
405
- },
406
- beforeResolve: {
407
- token: beforeResolveHooksToken,
408
- optional: true,
409
- },
410
- beforeNavigate: {
411
- token: beforeNavigateHooksToken,
412
- optional: true,
413
- },
414
- afterNavigate: {
415
- token: afterNavigateHooksToken,
416
- optional: true,
417
- },
418
- beforeUpdateCurrent: {
419
- token: beforeUpdateCurrentHooksToken,
420
- optional: true,
421
- },
422
- afterUpdateCurrent: {
423
- token: afterUpdateCurrentHooksToken,
424
- optional: true,
425
- },
426
- },
427
- },
428
- {
429
- provide: commandLineListTokens.init,
430
- multi: true,
431
- useFactory: ({ logger }) => {
432
- return function routerSetLogger() {
433
- setLogger(logger('route:router'));
434
- };
435
- },
436
- deps: {
437
- logger: LOGGER_TOKEN,
438
- },
439
- },
440
- {
441
- provide: ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN,
442
- // TODO: пока делаем after т.к. на это рассчитывает большинство приложений и у нас пока нет механизма контроля выполнения экшенов, чтобы
443
- // избежать случаев зависания перехода из-за долгих экшенов
444
- // рассмотреть возможность замены после доработок экшенов
445
- useValue: 'after',
446
- },
447
- provide({
448
- provide: PAGE_SERVICE_TOKEN,
449
- useClass: PageService,
450
- deps: {
451
- router: ROUTER_TOKEN,
452
- componentRegistry: COMPONENT_REGISTRY_TOKEN,
453
- },
454
- }),
455
- {
456
- provide: COMBINE_REDUCERS,
457
- multi: true,
458
- useValue: RouterStore,
459
- },
460
- ];
461
-
462
- const httpMethod = ({ requestManager, responseManager, logger, }) => {
463
- const log = logger('route:httpMethod');
464
- return async ({ to }) => {
465
- const { httpMethods } = to.config;
466
- if (httpMethods) {
467
- const currentMethod = requestManager.getMethod().toLowerCase();
468
- if (!httpMethods.split(',').includes(currentMethod)) {
469
- log.info({
470
- event: 'check-failed',
471
- currentMethod,
472
- route: to,
473
- });
474
- responseManager.setStatus(405);
475
- return false;
476
- }
477
- }
478
- };
479
- };
480
-
481
- const serverGuards = [
482
- {
483
- provide: ROUTER_GUARD_TOKEN,
484
- multi: true,
485
- useFactory: httpMethod,
486
- deps: {
487
- requestManager: REQUEST_MANAGER_TOKEN,
488
- responseManager: RESPONSE_MANAGER_TOKEN,
489
- logger: LOGGER_TOKEN,
490
- },
491
- },
492
- ];
493
-
494
- const stopRunAtError = (error) => {
495
- if (isNotFoundError(error) || isRedirectFoundError(error)) {
496
- return true;
497
- }
498
- };
499
- const runActionsFactory = ({ store, router, actionRegistry, actionPageRunner, }) => {
500
- return function runActions() {
501
- const route = router.getCurrentRoute();
502
- const { config: { bundle, pageComponent } = {} } = route;
503
- if (!bundle || !pageComponent) {
504
- throw new Error(`bundle and pageComponent should be defined, but got ${route}`);
505
- }
506
- const actions = uniq([
507
- ...(actionRegistry.getGlobal() || []),
508
- ...(actionRegistry.get(bundle) || []),
509
- ...(actionRegistry.get(pageComponent) || []),
510
- ]);
511
- return actionPageRunner.runActions(actions, stopRunAtError).catch((err) => {
512
- if (isRedirectFoundError(err)) {
513
- return router.navigate({
514
- url: err.nextUrl,
515
- replace: true,
516
- code: err.httpStatus,
517
- });
518
- }
519
- throw err.error || err;
520
- });
521
- };
522
- };
523
-
524
- const httpStatus = ({ responseManager }) => async ({ to }) => {
525
- if (to === null || to === void 0 ? void 0 : to.config.httpStatus) {
526
- responseManager.setStatus(to.config.httpStatus);
527
- }
528
- };
529
-
530
- const serverHooks = [
531
- {
532
- provide: afterNavigateHooksToken,
533
- multi: true,
534
- // проставляет httpStatus если задан в текущем роуте
535
- useFactory: httpStatus,
536
- deps: {
537
- responseManager: RESPONSE_MANAGER_TOKEN,
538
- },
539
- },
540
- ];
541
-
542
- const routerOptions = ({ requestManager, responseManager, }) => {
543
- const getUrl = (navigation) => { var _a, _b; return (_b = (_a = navigation.url) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : requestManager.getUrl(); };
544
- const throwError = ({ defaultStatus, url }) => {
545
- const error = new HttpError({
546
- url,
547
- httpStatus: responseManager.getStatus() >= 300 ? responseManager.getStatus() : defaultStatus,
548
- });
549
- makeErrorSilent(error);
550
- throw error;
551
- };
552
- return {
553
- onNotFound: async (navigation) => {
554
- // isSilent is used to prevent command line error logs,
555
- // because 404 errors is expected behavior
556
- throwError({ defaultStatus: 404, url: getUrl(navigation) });
557
- },
558
- onRedirect: async (navigation) => {
559
- const { fromUrl, url, code } = navigation;
560
- const error = new RedirectFoundError({
561
- url: getUrl(navigation),
562
- nextUrl: fromUrl.origin !== url.origin ? url.href : url.path,
563
- httpStatus: code,
564
- silent: true,
565
- });
566
- makeErrorSilent(error);
567
- throw error;
568
- },
569
- onBlock: async (navigation) => {
570
- throwError({ defaultStatus: 500, url: getUrl(navigation) });
571
- },
572
- defaultRedirectCode: requestManager.getMethod() === 'GET' ? 301 : 308,
573
- };
574
- };
575
-
576
- const deduplicateArray = (list) => {
577
- return Array.from(new Set(list));
578
- };
579
- const bundleInfoPapi = createPapiMethod({
580
- method: 'get',
581
- path: '/bundleInfo',
582
- async handler() {
583
- var _a;
584
- const { getAdditionalRoutes, routes, routeTransform } = this.deps;
585
- const loadAdditional = getAdditionalRoutes !== null && getAdditionalRoutes !== void 0 ? getAdditionalRoutes : (() => []);
586
- return deduplicateArray(flatten(routes || [])
587
- .concat((_a = (await loadAdditional())) !== null && _a !== void 0 ? _a : [])
588
- .map(routeTransform)
589
- .map(prop('path'))
590
- .filter((path) => !isWildcard(path) && !isHistoryFallback(path))
591
- .sort());
592
- },
593
- deps: {
594
- routes: {
595
- token: ROUTES_TOKEN,
596
- optional: true,
597
- },
598
- routeTransform: routeTransformToken,
599
- getAdditionalRoutes: { token: routerBundleInfoAdditionalToken, optional: true },
600
- },
601
- });
602
-
603
- // do nothing on server side
604
- const prefetchManager = {
605
- prefetch: async (url) => { },
606
- };
607
- const prefetchProviders = [
608
- provide({
609
- provide: LINK_PREFETCH_MANAGER_TOKEN,
610
- useValue: prefetchManager,
611
- }),
612
- ];
613
-
614
- const serverTokens = [
615
- {
616
- provide: additionalRouterParameters,
617
- useFactory: routerOptions,
618
- deps: {
619
- requestManager: REQUEST_MANAGER_TOKEN,
620
- responseManager: RESPONSE_MANAGER_TOKEN,
621
- },
622
- },
623
- {
624
- provide: SERVER_MODULE_PAPI_PUBLIC_ROUTE,
625
- multi: true,
626
- useValue: bundleInfoPapi,
627
- },
628
- ...prefetchProviders,
629
- ];
630
-
631
- const generateForRoot = (mainModule) => {
632
- return (routes, options = {}) => {
633
- return {
634
- mainModule,
635
- providers: [
636
- {
637
- provide: ROUTES_TOKEN,
638
- multi: true,
639
- useValue: routes,
640
- },
641
- options.spaActionsMode && {
642
- provide: ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN,
643
- useValue: options.spaActionsMode,
644
- },
645
- ].filter(Boolean),
646
- };
647
- };
648
- };
649
-
650
- var NoSpaRouterModule_1;
651
- let NoSpaRouterModule = NoSpaRouterModule_1 = class NoSpaRouterModule {
652
- };
653
- NoSpaRouterModule.forRoot = generateForRoot(NoSpaRouterModule_1);
654
- NoSpaRouterModule = NoSpaRouterModule_1 = __decorate([
655
- Module({
656
- providers: [
657
- ...providers,
658
- ...serverGuards,
659
- ...serverHooks,
660
- ...serverTokens,
661
- {
662
- provide: routerClassToken,
663
- useValue: Router,
664
- },
665
- {
666
- provide: commandLineListTokens.resolveUserDeps,
667
- multi: true,
668
- useFactory: ({ router, requestManager }) => {
669
- return function routerInit() {
670
- return router.navigate(requestManager.getUrl());
671
- };
672
- },
673
- deps: {
674
- router: ROUTER_TOKEN,
675
- requestManager: REQUEST_MANAGER_TOKEN,
676
- },
677
- },
678
- {
679
- // запускаем экшены отдельно от самого роутинга, чтобы распараллелить задачи
680
- provide: commandLineListTokens.resolvePageDeps,
681
- multi: true,
682
- useFactory: runActionsFactory,
683
- deps: {
684
- store: STORE_TOKEN,
685
- router: ROUTER_TOKEN,
686
- actionRegistry: ACTION_REGISTRY_TOKEN,
687
- actionPageRunner: ACTION_PAGE_RUNNER_TOKEN,
688
- },
689
- },
690
- ],
691
- })
692
- ], NoSpaRouterModule);
693
- const SpaRouterModule = NoSpaRouterModule;
694
-
695
- let RouterChildAppModule = class RouterChildAppModule {
696
- };
697
- RouterChildAppModule = __decorate([
698
- Module({
699
- providers: [
700
- provide({
701
- provide: EXTEND_RENDER,
702
- multi: true,
703
- useFactory: provideRouter,
704
- deps: {
705
- router: ROUTER_TOKEN,
706
- },
707
- }),
708
- {
709
- provide: CHILD_APP_INTERNAL_ROOT_STATE_ALLOWED_STORE_TOKEN,
710
- multi: true,
711
- useValue: RouterStore,
712
- },
713
- ],
714
- })
715
- ], RouterChildAppModule);
716
-
717
- function Link(props) {
718
- const { children, onClick, url, query, replace, target, navigateOptions, prefetch = true, ...otherProps } = props;
719
- const navigate = useNavigate({ url, query, replace, ...navigateOptions });
720
- const [linkElement, setLinkElement] = useState(null);
721
- const handleClick = useCallback((event) => {
722
- // ignores the navigation when clicked using right mouse button or
723
- // by holding a special modifier key: ctrl, command, win, alt, shift
724
- if (target ||
725
- event.ctrlKey ||
726
- event.metaKey ||
727
- event.altKey ||
728
- event.shiftKey ||
729
- event.button !== 0) {
730
- return;
731
- }
732
- event.preventDefault();
733
- navigate();
734
- onClick && onClick(event);
735
- }, [navigate, target, onClick]);
736
- const extraProps = { href: url, onClick: handleClick, target };
737
- if (isValidElement(children)) {
738
- return cloneElement(children, {
739
- // @ts-expect-error
740
- ref: (element) => {
741
- // @ts-expect-error
742
- const { ref } = children;
743
- // preserve original ref
744
- if (typeof ref === 'function') {
745
- ref(element);
746
- }
747
- else if (typeof ref === 'object' && ref !== null) {
748
- ref.current = element;
749
- }
750
- setLinkElement(element);
751
- },
752
- ...extraProps,
753
- });
754
- }
755
- return (
756
- // eslint-disable-next-line react/jsx-props-no-spreading
757
- jsx("a", { ref: (element) => setLinkElement(element), ...otherProps, ...extraProps, children: children }));
758
- }
759
- Link.displayName = 'Link';
760
-
761
- const usePageService = () => {
762
- useRoute();
763
- return useDi(PAGE_SERVICE_TOKEN);
764
- };
765
-
766
- export { Link, NoSpaRouterModule, RouterChildAppModule, RouterStore, SpaRouterModule, generateForRoot, setCurrentNavigation, setUrlOnRehydrate, usePageService };
6
+ export { generateForRoot } from './modules/utils/forRoot.es.js';
7
+ export { RouterStore, setCurrentNavigation, setUrlOnRehydrate } from './stores/RouterStore.es.js';
8
+ export { usePageService } from './hooks/usePageService.es.js';