@tinkoff/router 0.1.61 → 0.1.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  # @tinkoff/router
2
2
 
3
- Библиотека роутинга. Может работать как на сервере, так и на клиенте. Предназначена прежде всего для построения изморфных приложений.
3
+ Routing library. It can work both on the server and on the client. Designed primarily for building isomorphic applications.
4
4
 
5
- ## Подключение
5
+ ## Installation
6
6
 
7
- Необходимо установить `@tinkoff/router`
7
+ You need to install `@tinkoff/router`:
8
8
 
9
9
  ```bash
10
10
  yarn add @tinkoff/router
11
11
  ```
12
12
 
13
- И подключить в проекте
13
+ And connect it to the project:
14
14
 
15
15
  ```tsx
16
16
  import { Router } from '@tinkoff/router';
@@ -20,25 +20,25 @@ const router = new Router();
20
20
 
21
21
  ## Explanation
22
22
 
23
- Основные функции:
23
+ Features:
24
24
 
25
- - Библиотека поддерживает варианты работы как на сервере, так и на клиенте.
26
- - Есть возможность использовать ралзичные варианты клиентского перехода: со спа-переходами или без.
27
- - Для проверки доступности роута при конкретных условиях есть Guards.
28
- - Можно подписываться на разные этапы перехода через хуки
29
- - Компоненты и хуки для простой работы с роутингом из реакт
25
+ - The library supports options for working both on the server and on the client.
26
+ - It is possible to use different client transition options: with or without SPA transitions.
27
+ - There are Guards to check the availability of a route under specific conditions.
28
+ - You can subscribe to different stages of the transition through hooks
29
+ - Components and hooks for easy routing from react
30
30
 
31
- ### Версия для сервера и клиента
31
+ ### Server and client version
32
32
 
33
- Достачно просто импортировать роутинг из самой библиотеки и уже на основании настроек в package.json вернётся необходимая версия для сервера или клиента
33
+ It is enough just to import routing from the library itself and, based on the settings in package.json, the required version for the server or client will be returned
34
34
 
35
35
  ```ts
36
36
  import { Router } from '@tinkoff/router';
37
37
  ```
38
38
 
39
- ### Клиентский роутинг с\без спа-переходов
39
+ ### Client routing with/without SPA transitions
40
40
 
41
- По умолчанию на клиенте эскпортируется роутинг с включенными спа-переходами. Если необходимо спа-переходы отключить, то нужно импортировать специальную версию роутинга
41
+ By default, routing with SPA transitions is enabled on the client. If you need to disable SPA transitions, you need to import a special version of the routing
42
42
 
43
43
  ```ts
44
44
  import { Router, SpaHistory } from '@tinkoff/router';
@@ -50,27 +50,27 @@ const noSpaRouter = new NoSpaRouter();
50
50
 
51
51
  ### Router Guards
52
52
 
53
- Гуарды позволяют контроллировать доступность того или иного роута для конретного перехода. Из гуарда можно заблокировать переход или иницировать редирект.
53
+ Guards allow you to control the availability of a particular route for a specific transition. From the guard, you can block the transition or initiate a redirect.
54
54
 
55
55
  ```ts
56
56
  import { NavigationGuard } from '@tinkoff/router';
57
57
 
58
58
  export const myGuard: NavigationGuard = async ({ to }) => {
59
59
  if (to.config.blocked) {
60
- return false; // заблокировать данный переход
60
+ return false; // block this transition
61
61
  }
62
62
 
63
63
  if (to.config.redirect) {
64
- return '/login/'; // вызвать редирект на указанную страницу
64
+ return '/login/'; // call a redirect to the specified page
65
65
  }
66
66
 
67
- // если ничего не вернуть переход будет совершен как обычно
67
+ // if nothing is returned, the transition will be performed as usual
68
68
  };
69
69
  ```
70
70
 
71
- ### Хуки переходов
71
+ ### Transitions hooks
72
72
 
73
- Хуки перехода позволяют выполнить свои асинхронные действия на разные этапы перехода.
73
+ Transition hooks allow you to perform your asynchronous actions at different stages of the transition.
74
74
 
75
75
  ```ts
76
76
  import { NavigationHook } from '@tinkoff/router';
@@ -82,27 +82,27 @@ export const myHook: NavigationHook = async ({ from, to, url, fromUrl }) => {
82
82
 
83
83
  ## API
84
84
 
85
- ### Получение данных о текущем роуте или урле
85
+ ### Getting data about the current route or url
86
86
 
87
87
  ```ts
88
- router.getCurrentRoute(); // вернет текущий роут
89
- router.getCurrentUrl(); // вернёт распаршенную версию урла текущей страницы
88
+ router.getCurrentRoute(); // will return the current route
89
+ router.getCurrentUrl(); // will return the parsed version of the url of the current page
90
90
  ```
91
91
 
92
- ### Иницилизация перехода
92
+ ### Transition initiation
93
93
 
94
- Есть два метода для иницилизации перехода и обновления адресной строки в браузере. Главное отличие этих двух методов, что один из них должен запускать полноценный переход с обновлением данных и запуском тяжеловесных действий по загрузке данных. Второй же метод служит в основном для обновления состояния для текущего роута: чтобы обновить query-параметры на странице или изменить динамические параметры самого роута.
94
+ There are two methods for initializing the navigation and updating the address bar in the browser. The main difference between these two methods is that one of them will launch a full-fledged transition with data updating and starting heavy data loading actions. The second method is mainly used to update the state for the current route: to update the query parameters on the page or change the dynamic parameters of the route itself.
95
95
 
96
96
  #### navigate
97
97
 
98
- Инициирует полноценный переход, с определением следующего роута и обновлением состояния в браузере.
98
+ Initiates a full transition, defining the next route and updating the state in the browser.
99
99
 
100
100
  ```ts
101
101
  router.navigate('/test');
102
102
  router.navigate({ url: './test', query: { a: '1' } });
103
103
  ```
104
104
 
105
- Хуки перехода:
105
+ Transition hooks:
106
106
 
107
107
  - beforeResolve
108
108
  - beforeNavigate
@@ -110,23 +110,23 @@ router.navigate({ url: './test', query: { a: '1' } });
110
110
 
111
111
  #### updateCurrentRoute
112
112
 
113
- Переход основывается на текущем роуте (поэтому этот метод нельзя вызывать на сервере) и позволяет просто обновить некоторые данные для текущей страницы
113
+ The transition is based on the current route (therefore this method cannot be called on the server) and allows you to simply update some data for the current page
114
114
 
115
115
  ```ts
116
116
  router.updateCurrentRoute({ params: { id: 'abc' } });
117
117
  router.updateCurrentRoute({ query: { a: '1' } });
118
118
  ```
119
119
 
120
- Хуки:
120
+ Hooks:
121
121
 
122
122
  - beforeUpdateCurrent
123
123
  - afterUpdateCurrent
124
124
 
125
- ### Работа с query
125
+ ### Working with query
126
126
 
127
- #### Опция query
127
+ #### query option
128
128
 
129
- Позволяет задать search-строку для урла в виде объекта через опцию `query` при переходе. Предыдущее значение query при этом будет очищено
129
+ Allows you to set a search string for an url as an object via the `query` option when navigating. The previous query value will be cleared
130
130
 
131
131
  ```ts
132
132
  router.getCurrentUrl().query; // { с: 'c' }
@@ -139,7 +139,7 @@ router.getCurrentUrl().query; // { a: 'a', b: 'b' }
139
139
 
140
140
  #### preserveQuery
141
141
 
142
- Позволяет сохранить значение query от текущей навигации и использовать их в новом переходе
142
+ Allows you to keep the query value from the current navigation and use them in a new transition
143
143
 
144
144
  ```ts
145
145
  router.getCurrentUrl().query; // { с: 'c' }
@@ -150,7 +150,7 @@ router.updateCurrentRoute({ query: { a: 'a' }, preserveQuery: true });
150
150
  router.getCurrentUrl().query; // { a: 'a', c: 'c' }
151
151
  ```
152
152
 
153
- Если в качестве значения для конкретного ключа query передать undefined, то это значение очистится в новом query:
153
+ If you pass undefined as the value for a specific query key, then this value will be cleared in a new query:
154
154
 
155
155
  ```ts
156
156
  router.getCurrentUrl().query; // { a: 'a', b: 'b' }
@@ -161,13 +161,13 @@ router.updateCurrentRoute({ query: { a: undefined, c: 'c' }, preserveQuery: true
161
161
  router.getCurrentUrl().query; // { b: 'b', c: 'c' }
162
162
  ```
163
163
 
164
- ### Интеграция с React
164
+ ### Integration with React
165
165
 
166
- Если несколько полезных React-хуков и компонентов для работы с роутингом
166
+ Library has some useful React hooks and components for working with routing
167
167
 
168
168
  #### useRoute
169
169
 
170
- Позволяет получить текущий активный роут приложения
170
+ Returns current active route of the application
171
171
 
172
172
  ```ts
173
173
  import React from 'react';
@@ -182,7 +182,7 @@ export const Component = () => {
182
182
 
183
183
  #### useUrl
184
184
 
185
- Позволяет получить текущий активный URL приложения
185
+ Returns current active URL of the application
186
186
 
187
187
  ```ts
188
188
  import React from 'react';
@@ -197,7 +197,7 @@ export const Component = () => {
197
197
 
198
198
  #### useNavigate
199
199
 
200
- Создаёт колбек с вызовом навигации, который можно передать в дочерние компоненты или повесить как обработчик событий
200
+ Creates a callback with a navigation call that can be passed to child components or used as an event handler
201
201
 
202
202
  ```ts
203
203
  export const Cmp = () => {
@@ -209,9 +209,9 @@ export const Cmp = () => {
209
209
 
210
210
  #### Link
211
211
 
212
- Обёртка для реакт-компонента, которая делает его кликабельным
212
+ A wrapper for a react component that makes it clickable
213
213
 
214
- > Если в качестве children передать в Link реакт-компонент, то будет отрендерен этот переданный компонент и в него будут переданы пропсы `href`, `onClick` которые нужно использовать для вызова навигации. В других случаях будет отрендерен `<a>` тег с children в качестве дочернего элемента
214
+ > If the react component is passed to the Link as children, then this passed component will be rendered and the `href`, `onClick` props will be passed as props to that component and they should be used to make the navigation. Otherwise, the `<a>` tag will be rendered with children as a child.
215
215
 
216
216
  ```ts
217
217
  import { Link } from '@tinkoff/router';
@@ -183,6 +183,7 @@ class AbstractRouter {
183
183
  }
184
184
  this.runSyncHooks('change', navigation);
185
185
  this.lastNavigation = navigation;
186
+ this.currentNavigation = null;
186
187
  }
187
188
  async updateCurrentRoute(updateRouteOptions) {
188
189
  return this.internalUpdateCurrentRoute(updateRouteOptions, {});
@@ -276,7 +277,6 @@ class AbstractRouter {
276
277
  if (navigation.type === 'updateCurrentRoute') {
277
278
  await this.runUpdateCurrentRoute(navigation);
278
279
  }
279
- this.currentNavigation = null;
280
280
  }
281
281
  resolve(resolveOptions, options) {
282
282
  const opts = typeof resolveOptions === 'string' ? { url: resolveOptions } : resolveOptions;
package/lib/index.es.js CHANGED
@@ -183,6 +183,7 @@ class AbstractRouter {
183
183
  }
184
184
  this.runSyncHooks('change', navigation);
185
185
  this.lastNavigation = navigation;
186
+ this.currentNavigation = null;
186
187
  }
187
188
  async updateCurrentRoute(updateRouteOptions) {
188
189
  return this.internalUpdateCurrentRoute(updateRouteOptions, {});
@@ -276,7 +277,6 @@ class AbstractRouter {
276
277
  if (navigation.type === 'updateCurrentRoute') {
277
278
  await this.runUpdateCurrentRoute(navigation);
278
279
  }
279
- this.currentNavigation = null;
280
280
  }
281
281
  resolve(resolveOptions, options) {
282
282
  const opts = typeof resolveOptions === 'string' ? { url: resolveOptions } : resolveOptions;
@@ -668,9 +668,11 @@ class RouteTree {
668
668
 
669
669
  class Router extends AbstractRouter {
670
670
  constructor(options) {
671
+ var _a;
671
672
  super(options);
672
673
  this.blocked = false;
673
674
  this.tree = new RouteTree(options.routes);
675
+ this.defaultRedirectCode = (_a = options.defaultRedirectCode) !== null && _a !== void 0 ? _a : 308;
674
676
  this.history = new ServerHistory();
675
677
  }
676
678
  async dehydrate() {
@@ -713,13 +715,13 @@ class Router extends AbstractRouter {
713
715
  normalizePathname(pathname) {
714
716
  const normalized = super.normalizePathname(pathname);
715
717
  if (normalized !== pathname) {
716
- this.redirectCode = 308;
718
+ this.redirectCode = this.defaultRedirectCode;
717
719
  }
718
720
  return normalized;
719
721
  }
720
722
  resolveUrl(options) {
721
723
  if (options.url && isInvalidUrl(options.url)) {
722
- this.redirectCode = 308;
724
+ this.redirectCode = this.defaultRedirectCode;
723
725
  }
724
726
  return super.resolveUrl(options);
725
727
  }
package/lib/index.js CHANGED
@@ -199,6 +199,7 @@ class AbstractRouter {
199
199
  }
200
200
  this.runSyncHooks('change', navigation);
201
201
  this.lastNavigation = navigation;
202
+ this.currentNavigation = null;
202
203
  }
203
204
  async updateCurrentRoute(updateRouteOptions) {
204
205
  return this.internalUpdateCurrentRoute(updateRouteOptions, {});
@@ -292,7 +293,6 @@ class AbstractRouter {
292
293
  if (navigation.type === 'updateCurrentRoute') {
293
294
  await this.runUpdateCurrentRoute(navigation);
294
295
  }
295
- this.currentNavigation = null;
296
296
  }
297
297
  resolve(resolveOptions, options) {
298
298
  const opts = typeof resolveOptions === 'string' ? { url: resolveOptions } : resolveOptions;
@@ -684,9 +684,11 @@ class RouteTree {
684
684
 
685
685
  class Router extends AbstractRouter {
686
686
  constructor(options) {
687
+ var _a;
687
688
  super(options);
688
689
  this.blocked = false;
689
690
  this.tree = new RouteTree(options.routes);
691
+ this.defaultRedirectCode = (_a = options.defaultRedirectCode) !== null && _a !== void 0 ? _a : 308;
690
692
  this.history = new ServerHistory();
691
693
  }
692
694
  async dehydrate() {
@@ -729,13 +731,13 @@ class Router extends AbstractRouter {
729
731
  normalizePathname(pathname) {
730
732
  const normalized = super.normalizePathname(pathname);
731
733
  if (normalized !== pathname) {
732
- this.redirectCode = 308;
734
+ this.redirectCode = this.defaultRedirectCode;
733
735
  }
734
736
  return normalized;
735
737
  }
736
738
  resolveUrl(options) {
737
739
  if (options.url && url.isInvalidUrl(options.url)) {
738
- this.redirectCode = 308;
740
+ this.redirectCode = this.defaultRedirectCode;
739
741
  }
740
742
  return super.resolveUrl(options);
741
743
  }
@@ -16,6 +16,7 @@ export interface Options {
16
16
  afterUpdateCurrent?: NavigationHook[];
17
17
  guards?: NavigationGuard[];
18
18
  onChange?: NavigationSyncHook[];
19
+ defaultRedirectCode?: number;
19
20
  }
20
21
  interface InternalOptions {
21
22
  history?: boolean;
@@ -1,14 +1,11 @@
1
1
  import type { Options } from './abstract';
2
2
  import { AbstractRouter } from './abstract';
3
- import type { Navigation, NavigateOptions, HookName, NavigationHook } from '../types';
3
+ import type { Navigation, NavigateOptions, HookName } from '../types';
4
4
  export declare class Router extends AbstractRouter {
5
+ protected defaultRedirectCode: number;
5
6
  protected blocked: boolean;
6
7
  protected redirectCode?: number;
7
- constructor(options: Options & {
8
- onRedirect: (navigation: Navigation) => Promise<void>;
9
- onNotFound: NavigationHook;
10
- onBlock: NavigationHook;
11
- });
8
+ constructor(options: Options);
12
9
  protected onRedirect: (navigation: Navigation) => Promise<void>;
13
10
  dehydrate(): Promise<Navigation>;
14
11
  protected run(navigation: Navigation): Promise<void>;
package/lib/types.d.ts CHANGED
@@ -13,8 +13,8 @@ export interface NavigationRoute extends Route {
13
13
  navigateState?: any;
14
14
  }
15
15
  export interface BaseNavigateOptions {
16
- params?: Params;
17
- query?: Query;
16
+ params?: Partial<Params>;
17
+ query?: Partial<Query>;
18
18
  preserveQuery?: boolean;
19
19
  replace?: boolean;
20
20
  hash?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinkoff/router",
3
- "version": "0.1.61",
3
+ "version": "0.1.65",
4
4
  "description": "router",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
package/README.en.md DELETED
@@ -1,233 +0,0 @@
1
- # @tinkoff/router
2
-
3
- Routing library. It can work both on the server and on the client. Designed primarily for building ismorphic applications.
4
-
5
- ## Installation
6
-
7
- You need to install `@tinkoff/router`:
8
-
9
- ```bash
10
- yarn add @tinkoff/router
11
- ```
12
-
13
- And connect in the project:
14
-
15
- ```tsx
16
- import { Router } from '@tinkoff/router';
17
-
18
- const router = new Router();
19
- ```
20
-
21
- ## Explanation
22
-
23
- Features:
24
-
25
- - The library supports options for working both on the server and on the client.
26
- - It is possible to use different client transition options: with or without SPA transitions.
27
- - There are Guards to check the availability of a route under specific conditions.
28
- - You can subscribe to different stages of the transition through hooks
29
- - Components and hooks for easy routing from react
30
-
31
- ### Server and client version
32
-
33
- It is enough just to import routing from the library itself and, based on the settings, the required version for the server or client will be returned to package.json
34
-
35
- ```ts
36
- import { Router } from '@tinkoff/router';
37
- ```
38
-
39
- ### Client routing with/without SPA transitions
40
-
41
- By default, routing with SPA transitions enabled is exported on the client.
42
- If you need to disable SPA transitions, you need to import a special version of the routing
43
-
44
- ```ts
45
- import { Router, SpaHistory } from '@tinkoff/router';
46
- import { NoSpaRouter } from '@tinkoff/router';
47
-
48
- const spaRouter = new Router({ history: new SpaHistory() });
49
- const noSpaRouter = new NoSpaRouter();
50
- ```
51
-
52
- ### Router Guards
53
-
54
- Guards allow you to control the availability of a particular route for a specific transition.
55
- From the guard, you can block the transition or initiate a redirect.
56
-
57
- ```ts
58
- import { NavigationGuard } from '@tinkoff/router';
59
-
60
- export const myGuard: NavigationGuard = async ({ to }) => {
61
- if (to.config.blocked) {
62
- return false; // block this transition
63
- }
64
-
65
- if (to.config.redirect) {
66
- return '/login/'; // call a redirect to the specified page
67
- }
68
-
69
- // if nothing is returned, the transition will be performed as usual
70
- };
71
- ```
72
-
73
- ### Transitions hooks
74
-
75
- Transition hooks allow you to perform your asynchronous actions at different stages of the transition.
76
-
77
- ```ts
78
- import { NavigationHook } from '@tinkoff/router';
79
-
80
- export const myHook: NavigationHook = async ({ from, to, url, fromUrl }) => {
81
- console.log(`navigating from ${from} to route ${to}`);
82
- };
83
- ```
84
-
85
- ## API
86
-
87
- ### Getting data about the current route or url
88
-
89
- ```ts
90
- router.getCurrentRoute(); // will return the current route
91
- router.getCurrentUrl(); // will return the parsed version of the url of the current page
92
- ```
93
-
94
- ### Transition initiation
95
-
96
- There are two methods for initializing the navigation and updating the address bar in the browser. The main difference between these two methods is that one of them must launch a full-fledged transition with data updating and starting heavy data loading actions. The second method is mainly used to update the state for the current route: to update the query parameters on the page or change the dynamic parameters of the route itself.
97
-
98
- #### navigate
99
-
100
- Initiates a full transition, defining the next route and updating the state in the browser.
101
-
102
- ```ts
103
- router.navigate('/test');
104
- router.navigate({ url: './test', query: { a: '1' } });
105
- ```
106
-
107
- Transition hooks:
108
-
109
- - beforeResolve
110
- - beforeNavigate
111
- - afterNavigate
112
-
113
- #### updateCurrentRoute
114
-
115
- The transition is based on the current route (therefore this method cannot be called on the server) and allows you to simply update some data for the current page
116
-
117
- ```ts
118
- router.updateCurrentRoute({ params: { id: 'abc' } });
119
- router.updateCurrentRoute({ query: { a: '1' } });
120
- ```
121
-
122
- Hooks:
123
-
124
- - beforeUpdateCurrent
125
- - afterUpdateCurrent
126
-
127
- ### Working with query
128
-
129
- #### query option
130
-
131
- Allows you to set a search string for an url as an object via the `query` option when navigating. The previous query value will be cleared
132
-
133
- ```ts
134
- router.getCurrentUrl().query; // { с: 'c' }
135
-
136
- router.navigate({ query: { a: 'a', b: 'b' } });
137
- router.updateCurrentRoute({ query: { a: 'a', b: 'b' } });
138
-
139
- router.getCurrentUrl().query; // { a: 'a', b: 'b' }
140
- ```
141
-
142
- #### preserveQuery
143
-
144
- Allows you to keep the query value from the current navigation and use them in a new transition
145
-
146
- ```ts
147
- router.getCurrentUrl().query; // { с: 'c' }
148
-
149
- router.navigate({ query: { a: 'a' }, preserveQuery: true });
150
- router.updateCurrentRoute({ query: { a: 'a' }, preserveQuery: true });
151
-
152
- router.getCurrentUrl().query; // { a: 'a', c: 'c' }
153
- ```
154
-
155
- If you pass undefined as the value for a specific query key, then this value will be cleared in a new query:
156
-
157
- ```ts
158
- router.getCurrentUrl().query; // { a: 'a', b: 'b' }
159
-
160
- router.navigate({ query: { a: undefined, c: 'c' }, preserveQuery: true });
161
- router.updateCurrentRoute({ query: { a: undefined, c: 'c' }, preserveQuery: true });
162
-
163
- router.getCurrentUrl().query; // { b: 'b', c: 'c' }
164
- ```
165
-
166
- ### Integration with React
167
-
168
- Has some useful React hooks and components for working with routing
169
-
170
- #### useRoute
171
-
172
- Allows you to get the current active route of the application
173
-
174
- ```ts
175
- import React from 'react';
176
- import { useRoute } from '@tinkoff/router';
177
-
178
- export const Component = () => {
179
- const route = useRoute();
180
-
181
- return <div>Route path: {route.actualPath}</div>;
182
- };
183
- ```
184
-
185
- #### useUrl
186
-
187
- Lets get the current active URL of the application
188
-
189
- ```ts
190
- import React from 'react';
191
- import { useUrl } from '@tinkoff/router';
192
-
193
- export const Component = () => {
194
- const url = useUrl();
195
-
196
- return <div>Url query: {JSON.stringify(url.query)}</div>;
197
- };
198
- ```
199
-
200
- #### useNavigate
201
-
202
- Creates a callback with a navigation call that can be passed to child components or hung as an event handler
203
-
204
- ```ts
205
- export const Cmp = () => {
206
- const navigate = useNavigate('/test/');
207
-
208
- return <div onClick={navigate}>Test</div>;
209
- };
210
- ```
211
-
212
- #### Link
213
-
214
- A wrapper for a react component that makes it clickable
215
-
216
- > If the react component is passed to the Link as children, then this passed component will be rendered and the `href`, `onClick` props that need to be used to call the navigation will be passed to it. Otherwise, the `<a>` tag will be rendered with children as a child.
217
-
218
- ```ts
219
- import { Link } from '@tinkoff/router';
220
- import CustomLink from '@custom-scope/link';
221
-
222
- export const Component = () => {
223
- return (
224
- <Link url="/test/">
225
- <CustomLink />
226
- </Link>
227
- );
228
- };
229
-
230
- export const WrapLink = () => {
231
- return <Link url="/test/">Click me</Link>;
232
- };
233
- ```