@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.
Files changed (2) hide show
  1. package/README.en.md +359 -0
  2. 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
+ ![Diagramm](/img/router/navigate-flow-server.drawio.svg)
34
+
35
+ ### Flow of the first navigation on the client
36
+
37
+ ![Diagramm](/img/router/rehydrate-client.drawio.svg)
38
+
39
+ ### Flow of navigation on the client without SPA transitions
40
+
41
+ ![Diagramm](/img/router/navigate-flow-client-no-spa.drawio.svg)
42
+
43
+ ### Flow of navigation on the client with SPA transitions
44
+
45
+ ![Diagramm](/img/router/navigate-flow-client-spa.drawio.svg)
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.15.2",
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.58",
26
+ "@tinkoff/router": "0.1.59",
27
27
  "@tinkoff/url": "0.7.36",
28
- "@tramvai/tokens-render": "1.15.2",
29
- "@tramvai/tokens-router": "1.15.2",
30
- "@tramvai/tokens-server": "1.15.2"
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.15.2",
35
- "@tramvai/module-log": "1.15.2",
36
- "@tramvai/module-server": "1.15.2",
37
- "@tramvai/papi": "1.15.2",
38
- "@tramvai/state": "1.15.2",
39
- "@tramvai/test-helpers": "1.15.2",
40
- "@tramvai/test-mocks": "1.15.2",
41
- "@tramvai/tokens-common": "1.15.2",
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"