@tramvai/module-router 1.15.2 → 1.25.1
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.en.md +359 -0
- package/package.json +13 -13
package/README.en.md
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# @tramvai/module-router
|
|
2
|
+
|
|
3
|
+
Module for routing in the application.
|
|
4
|
+
Exports two sub-modules: with client SPA transitions, and no-SPA.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
You need to install `@tramvai/module-router`:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
yarn add @tramvai/module-router
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
And connect in the project:
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { createApp } from '@tramvai/core';
|
|
18
|
+
import { NoSpaRouterModule, SpaRouterModule } from '@tramvai/module-router';
|
|
19
|
+
|
|
20
|
+
createApp({
|
|
21
|
+
name: 'tincoin',
|
|
22
|
+
modules: [SpaRouterModule],
|
|
23
|
+
// modules: [ NoSpaRouterModule ], if you want to disable client SPA transitions
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Explanation
|
|
28
|
+
|
|
29
|
+
The module is based on the library [@tinkoff/router](../libs/router)
|
|
30
|
+
|
|
31
|
+
### Navigation flow on the server
|
|
32
|
+
|
|
33
|
+

|
|
34
|
+
|
|
35
|
+
### Flow of the first navigation on the client
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
### Flow of navigation on the client without SPA transitions
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
### Flow of navigation on the client with SPA transitions
|
|
44
|
+
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+
## API
|
|
48
|
+
|
|
49
|
+
### Static routes in the application
|
|
50
|
+
|
|
51
|
+
Route description format:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
const routes = [
|
|
55
|
+
{
|
|
56
|
+
// the name of the route is required
|
|
57
|
+
name: 'route1',
|
|
58
|
+
// the path of the route is required
|
|
59
|
+
path: '/route/a/',
|
|
60
|
+
// additional configs for the route
|
|
61
|
+
config: {
|
|
62
|
+
// layout component name
|
|
63
|
+
layoutComponent: 'layout',
|
|
64
|
+
// page component name
|
|
65
|
+
pageComponent: 'page',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
You can explicitly transfer a list of routes to routing when adding a router module:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { createApp } from '@tramvai/core';
|
|
75
|
+
import { SpaRouterModule } from '@tramvai/module-router';
|
|
76
|
+
|
|
77
|
+
const routes = [
|
|
78
|
+
// ...
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
createApp({
|
|
82
|
+
modules: [
|
|
83
|
+
// ...,
|
|
84
|
+
SpaRouterModule.forRoot(routes),
|
|
85
|
+
],
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Or separately with the `ROUTES_TOKEN` token (you can set it several times):
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { ROUTES_TOKEN } from '@tramvai/module-router';
|
|
93
|
+
import { provide } from '@tramvai/core';
|
|
94
|
+
|
|
95
|
+
const routesCommon = [
|
|
96
|
+
// ...
|
|
97
|
+
];
|
|
98
|
+
const routesSpecific = [
|
|
99
|
+
// ...
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
const providers = [
|
|
103
|
+
// ...,
|
|
104
|
+
provide({
|
|
105
|
+
provide: ROUTES_TOKEN,
|
|
106
|
+
multi: true,
|
|
107
|
+
useValue: routesCommon,
|
|
108
|
+
}),
|
|
109
|
+
provide({
|
|
110
|
+
provide: ROUTES_TOKEN,
|
|
111
|
+
multi: true,
|
|
112
|
+
useValue: routesSpecific,
|
|
113
|
+
}),
|
|
114
|
+
];
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### PAGE_SERVICE_TOKEN
|
|
118
|
+
|
|
119
|
+
Service wrapper for working with routing. Serves to hide routing work and is the preferred way of routing work.
|
|
120
|
+
|
|
121
|
+
Методы:
|
|
122
|
+
|
|
123
|
+
- `getCurrentRoute()` - get the current route,
|
|
124
|
+
- `getCurrentUrl()` - object-result of parsing the current url
|
|
125
|
+
- `getConfig()` - get the config of the current page
|
|
126
|
+
- `getContent()` - get content for the current page
|
|
127
|
+
- `getMeta()` - get the meta for the current page
|
|
128
|
+
- `navigate(options)` - navigation to a new page [more](references/libs/router.md)
|
|
129
|
+
- `updateCurrentRoute(options)` - update the current route with new parameters [more](references/libs/router.md)
|
|
130
|
+
- `back()` - go back through history
|
|
131
|
+
- `forward()` - go forward through history
|
|
132
|
+
- `go(to)` - go to the specified delta by history
|
|
133
|
+
|
|
134
|
+
### RouterStore
|
|
135
|
+
|
|
136
|
+
Store that stores information about the current and previous routes.
|
|
137
|
+
|
|
138
|
+
Properties:
|
|
139
|
+
|
|
140
|
+
- `currentRoute` - current route
|
|
141
|
+
- `currentUrl` - current url
|
|
142
|
+
- `previousRoute` - previous route
|
|
143
|
+
- `previousUrl` - previous url
|
|
144
|
+
|
|
145
|
+
### ROUTER_GUARD_TOKEN
|
|
146
|
+
|
|
147
|
+
Allows you to block or redirect the transition to the page under certain conditions. See [@tinkoff/router](/references/libs/router.md)
|
|
148
|
+
|
|
149
|
+
### Redirects
|
|
150
|
+
|
|
151
|
+
Redirects can be done via [guards](#ROUTER_GUARD_TOKEN) or explicitly via the `redirect` property in the route.
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
const routes = [
|
|
155
|
+
// ...,
|
|
156
|
+
{
|
|
157
|
+
name: 'redirect',
|
|
158
|
+
path: '/from/',
|
|
159
|
+
redirect: '/to/',
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Not Found route
|
|
165
|
+
|
|
166
|
+
The route used if no matches were found for the current page, can be specified in a special way in the list of routes.
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
const route = [
|
|
170
|
+
// ...other routes,
|
|
171
|
+
{
|
|
172
|
+
name: 'not-found',
|
|
173
|
+
path: '*',
|
|
174
|
+
config: {
|
|
175
|
+
pageComponent: 'notfoundComponentName',
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### ROUTE_RESOLVE_TOKEN
|
|
182
|
+
|
|
183
|
+
Allows you to define an asynchronous function that returns a route object that will be called if no suitable static route was found in the application.
|
|
184
|
+
|
|
185
|
+
### ROUTE_TRANSFORM_TOKEN
|
|
186
|
+
|
|
187
|
+
Transformer function for application routes (set statically and those that will be loaded via ROUTE_RESOLVE_TOKEN)
|
|
188
|
+
|
|
189
|
+
### Method of setting when actions should be performed during SPA transitions
|
|
190
|
+
|
|
191
|
+
By default, SPA transitions execute actions after defining the next route, but before the actual transition, which allows the page to be displayed immediately with new data, but can cause a noticeable visual lag if the actions are taken long enough.
|
|
192
|
+
|
|
193
|
+
It is possible to change the behavior and make the execution of actions after the transition itself. Then, when developing components, you will need to take into account that data will be loaded as it becomes available.
|
|
194
|
+
|
|
195
|
+
Configurable explicitly when using the routing module:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import { createApp } from '@tramvai/core';
|
|
199
|
+
import { SpaRouterModule } from '@tramvai/module-router';
|
|
200
|
+
|
|
201
|
+
createApp({
|
|
202
|
+
modules: [
|
|
203
|
+
// ...,
|
|
204
|
+
SpaRouterModule.forRoot([], {
|
|
205
|
+
spaActionsMode: 'after', // default is 'before'
|
|
206
|
+
}),
|
|
207
|
+
],
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
or through token `ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN`:
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
import { ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN } from '@tramvai/module-router';
|
|
215
|
+
import { provide } from '@tramvai/core';
|
|
216
|
+
|
|
217
|
+
const providers = [
|
|
218
|
+
// ...,
|
|
219
|
+
provide({
|
|
220
|
+
provide: ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN,
|
|
221
|
+
useValue: 'after',
|
|
222
|
+
}),
|
|
223
|
+
];
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## How to
|
|
227
|
+
|
|
228
|
+
### Working with navigation in providers and actions
|
|
229
|
+
|
|
230
|
+
In this case, it is best to use the [PAGE_SERVICE_TOKEN](#page_service_token)
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
import { provide, createAction } from '@tramvai/core';
|
|
234
|
+
import { PAGE_SERVICE_TOKEN } from '@tramvai/module-router';
|
|
235
|
+
|
|
236
|
+
const provider = provide({
|
|
237
|
+
provide: 'token',
|
|
238
|
+
useFactory: ({ pageService }) => {
|
|
239
|
+
if (pageService().getCurrentUrl().pathname === '/test/') {
|
|
240
|
+
return pageService.navigate({ url: '/redirect/', replace: true });
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
deps: {
|
|
244
|
+
pageService: PAGE_SERVICE_TOKEN,
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
const action = createAction({
|
|
249
|
+
name: 'action',
|
|
250
|
+
fn: (_, __, { pageService }) => {
|
|
251
|
+
if (pageService.getConfig().pageComponent === 'pageComponent') {
|
|
252
|
+
return page.updateCurrentRoute({ query: { test: 'true' } });
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
deps: {
|
|
256
|
+
pageService: PAGE_SERVICE_TOKEN,
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Working with navigation in React components
|
|
262
|
+
|
|
263
|
+
You can work with routing inside React components using hooks and components - `useNavigate`, `useRoute`, `Link` from the [@tinkoff/router](references/libs/router.md#интеграция-с-react)
|
|
264
|
+
|
|
265
|
+
<p>
|
|
266
|
+
<details>
|
|
267
|
+
<summary>An example of working with navigation in the application</summary>
|
|
268
|
+
|
|
269
|
+
@inline ../../../examples/how-to/router-navigate/index.tsx
|
|
270
|
+
|
|
271
|
+
</details>
|
|
272
|
+
</p>
|
|
273
|
+
|
|
274
|
+
### How to set static routes
|
|
275
|
+
|
|
276
|
+
[RouterModule](references/modules/router.md) allows you to add new routes when configuring your application.
|
|
277
|
+
The second way is to pass static routes to DI via the `ROUTES_TOKEN` token.
|
|
278
|
+
|
|
279
|
+
<p>
|
|
280
|
+
<details>
|
|
281
|
+
<summary>An example of adding static routes to an application</summary>
|
|
282
|
+
|
|
283
|
+
@inline ../../../examples/how-to/router-static-routes/index.tsx
|
|
284
|
+
|
|
285
|
+
</details>
|
|
286
|
+
</p>
|
|
287
|
+
|
|
288
|
+
### How to set Route Guard
|
|
289
|
+
|
|
290
|
+
[ROUTER_GUARD_TOKEN](references/modules/router.md#router_guard_token) is set as an asynchronous function, which allows you to perform various actions and influence the routing behavior.
|
|
291
|
+
|
|
292
|
+
<p>
|
|
293
|
+
<details>
|
|
294
|
+
<summary>Example router guards job in application</summary>
|
|
295
|
+
|
|
296
|
+
@inline ../../../examples/how-to/router-guards/index.tsx
|
|
297
|
+
|
|
298
|
+
</details>
|
|
299
|
+
</p>
|
|
300
|
+
|
|
301
|
+
### How to set the Not found route
|
|
302
|
+
|
|
303
|
+
The Not found route is used if the corresponding route is not found for the url.
|
|
304
|
+
|
|
305
|
+
Such a route is specified in the list of routes with the special `*` character in the `path` property.
|
|
306
|
+
|
|
307
|
+
<p>
|
|
308
|
+
<details>
|
|
309
|
+
<summary>An example of setting a Not Found route in an application</summary>
|
|
310
|
+
|
|
311
|
+
@inline ../../../examples/how-to/router-not-found/index.tsx
|
|
312
|
+
|
|
313
|
+
</details>
|
|
314
|
+
</p>
|
|
315
|
+
|
|
316
|
+
### Testing
|
|
317
|
+
|
|
318
|
+
#### Testing ROUTER_GUARD_TOKEN extensions
|
|
319
|
+
|
|
320
|
+
If you have a module or providers that define `ROUTER_GUARD_TOKEN`, then it will be convenient to use special utilities to test them separately
|
|
321
|
+
|
|
322
|
+
```ts
|
|
323
|
+
import { ROUTER_GUARD_TOKEN } from '@tramvai/tokens-router';
|
|
324
|
+
import { testGuard } from '@tramvai/module-router/tests';
|
|
325
|
+
import { CustomModule } from './module';
|
|
326
|
+
import { providers } from './providers';
|
|
327
|
+
|
|
328
|
+
describe('router guards', () => {
|
|
329
|
+
it('should redirect from guard', async () => {
|
|
330
|
+
const { router } = testGuard({
|
|
331
|
+
providers,
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
await router.navigate('/test/');
|
|
335
|
+
|
|
336
|
+
expect(router.getCurrentUrl()).toMatchObject({
|
|
337
|
+
path: '/redirect/',
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it('should block navigation', async () => {
|
|
342
|
+
const { router } = testGuard({
|
|
343
|
+
modules: [CustomModule],
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
expect(router.getCurrentUrl()).toMatchObject({ path: '/' });
|
|
347
|
+
|
|
348
|
+
await router.navigate('/test/').catch(() => null);
|
|
349
|
+
|
|
350
|
+
expect(router.getCurrentUrl()).toMatchObject({
|
|
351
|
+
path: '/',
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Exported tokens
|
|
358
|
+
|
|
359
|
+
[link](references/tokens/router-tokens.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tramvai/module-router",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"browser": {
|
|
@@ -23,22 +23,22 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@tinkoff/errors": "0.2.18",
|
|
26
|
-
"@tinkoff/router": "0.1.
|
|
26
|
+
"@tinkoff/router": "0.1.59",
|
|
27
27
|
"@tinkoff/url": "0.7.36",
|
|
28
|
-
"@tramvai/tokens-render": "1.
|
|
29
|
-
"@tramvai/tokens-router": "1.
|
|
30
|
-
"@tramvai/tokens-server": "1.
|
|
28
|
+
"@tramvai/tokens-render": "1.25.1",
|
|
29
|
+
"@tramvai/tokens-router": "1.25.1",
|
|
30
|
+
"@tramvai/tokens-server": "1.25.1"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@tinkoff/utils": "^2.1.2",
|
|
34
|
-
"@tramvai/core": "1.
|
|
35
|
-
"@tramvai/module-log": "1.
|
|
36
|
-
"@tramvai/module-server": "1.
|
|
37
|
-
"@tramvai/papi": "1.
|
|
38
|
-
"@tramvai/state": "1.
|
|
39
|
-
"@tramvai/test-helpers": "1.
|
|
40
|
-
"@tramvai/test-mocks": "1.
|
|
41
|
-
"@tramvai/tokens-common": "1.
|
|
34
|
+
"@tramvai/core": "1.25.1",
|
|
35
|
+
"@tramvai/module-log": "1.25.1",
|
|
36
|
+
"@tramvai/module-server": "1.25.1",
|
|
37
|
+
"@tramvai/papi": "1.25.1",
|
|
38
|
+
"@tramvai/state": "1.25.1",
|
|
39
|
+
"@tramvai/test-helpers": "1.25.1",
|
|
40
|
+
"@tramvai/test-mocks": "1.25.1",
|
|
41
|
+
"@tramvai/tokens-common": "1.25.1",
|
|
42
42
|
"@tinkoff/dippy": "0.7.35",
|
|
43
43
|
"react": "*",
|
|
44
44
|
"tslib": "^2.0.3"
|