@tinkoff/router 0.1.75 → 0.1.78

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.
@@ -221,17 +221,20 @@ class AbstractRouter {
221
221
  await this.runHooks('afterUpdateCurrent', navigation);
222
222
  }
223
223
  async navigate(navigateOptions) {
224
- return this.internalNavigate(typeof navigateOptions === 'string' ? { url: navigateOptions } : navigateOptions, {});
224
+ return this.internalNavigate(makeNavigateOptions(navigateOptions), {});
225
225
  }
226
- async internalNavigate(navigateOptions, { history }) {
226
+ async internalNavigate(navigateOptions, { history, redirect }) {
227
227
  var _a;
228
228
  const { url, replace, params, navigateState, code } = navigateOptions;
229
- const prevNavigation = (_a = this.currentNavigation) !== null && _a !== void 0 ? _a : this.lastNavigation;
229
+ const prevNavigation = redirect
230
+ ? this.lastNavigation
231
+ : (_a = this.currentNavigation) !== null && _a !== void 0 ? _a : this.lastNavigation;
230
232
  if (!url && !prevNavigation) {
231
233
  throw new Error('Navigate url should be specified and cannot be omitted for first navigation');
232
234
  }
233
235
  const resolvedUrl = this.resolveUrl(navigateOptions);
234
236
  const { to: from, url: fromUrl } = prevNavigation !== null && prevNavigation !== void 0 ? prevNavigation : {};
237
+ const redirectFrom = redirect ? this.currentNavigation.to : undefined;
235
238
  let navigation = {
236
239
  type: 'navigate',
237
240
  from,
@@ -241,6 +244,8 @@ class AbstractRouter {
241
244
  history,
242
245
  navigateState,
243
246
  code,
247
+ redirect,
248
+ redirectFrom,
244
249
  };
245
250
  await this.runHooks('beforeResolve', navigation);
246
251
  const to = this.resolveRoute({ url: resolvedUrl, params, navigateState }, { wildcard: true });
@@ -366,7 +371,9 @@ class AbstractRouter {
366
371
  pathname = makePath(currentRoute.path, { ...currentRoute.params, ...params });
367
372
  }
368
373
  }
369
- pathname = this.normalizePathname(pathname);
374
+ if (isSameHost(resultUrl)) {
375
+ pathname = this.normalizePathname(pathname);
376
+ }
370
377
  return convertRawUrl(rawAssignUrl(resultUrl, {
371
378
  pathname,
372
379
  search: url ? resultUrl.search : '',
@@ -556,7 +563,7 @@ const wrapHistory = ({ onNavigate }) => {
556
563
  const history = (delta) => {
557
564
  go(delta);
558
565
  };
559
- const browserNavigate = (replace) => {
566
+ const browserNavigate = (replace = false) => {
560
567
  return (navigateState, title, url) => {
561
568
  onNavigate({ url, replace, navigateState });
562
569
  };
@@ -770,8 +777,11 @@ class ClientRouter extends AbstractRouter {
770
777
  // in case we didn't find any matched route just force hard page navigation
771
778
  const prevUrl = (_b = (_a = navigation.fromUrl) === null || _a === void 0 ? void 0 : _a.href) !== null && _b !== void 0 ? _b : window.location.href;
772
779
  const nextUrl = navigation.url.href;
773
- // prevent redirect cycle on the same page
774
- if (prevUrl !== nextUrl) {
780
+ const isNoSpaNavigation = navigation.from && !navigation.to;
781
+ // prevent redirect cycle on the same page,
782
+ // except cases when we run no-spa navigations,
783
+ // because we need hard reload in this cases
784
+ if (isNoSpaNavigation ? true : prevUrl !== nextUrl) {
775
785
  if (navigation.replace) {
776
786
  window.location.replace(nextUrl);
777
787
  }
@@ -787,7 +797,12 @@ class ClientRouter extends AbstractRouter {
787
797
  }
788
798
  async redirect(navigation, target) {
789
799
  await super.redirect(navigation, target);
790
- return this.navigate({ ...target, replace: target.replace || navigation.replace });
800
+ return this.internalNavigate({
801
+ ...target,
802
+ replace: target.replace || navigation.replace,
803
+ }, {
804
+ redirect: true,
805
+ });
791
806
  }
792
807
  }
793
808
 
package/lib/index.es.js CHANGED
@@ -221,17 +221,20 @@ class AbstractRouter {
221
221
  await this.runHooks('afterUpdateCurrent', navigation);
222
222
  }
223
223
  async navigate(navigateOptions) {
224
- return this.internalNavigate(typeof navigateOptions === 'string' ? { url: navigateOptions } : navigateOptions, {});
224
+ return this.internalNavigate(makeNavigateOptions(navigateOptions), {});
225
225
  }
226
- async internalNavigate(navigateOptions, { history }) {
226
+ async internalNavigate(navigateOptions, { history, redirect }) {
227
227
  var _a;
228
228
  const { url, replace, params, navigateState, code } = navigateOptions;
229
- const prevNavigation = (_a = this.currentNavigation) !== null && _a !== void 0 ? _a : this.lastNavigation;
229
+ const prevNavigation = redirect
230
+ ? this.lastNavigation
231
+ : (_a = this.currentNavigation) !== null && _a !== void 0 ? _a : this.lastNavigation;
230
232
  if (!url && !prevNavigation) {
231
233
  throw new Error('Navigate url should be specified and cannot be omitted for first navigation');
232
234
  }
233
235
  const resolvedUrl = this.resolveUrl(navigateOptions);
234
236
  const { to: from, url: fromUrl } = prevNavigation !== null && prevNavigation !== void 0 ? prevNavigation : {};
237
+ const redirectFrom = redirect ? this.currentNavigation.to : undefined;
235
238
  let navigation = {
236
239
  type: 'navigate',
237
240
  from,
@@ -241,6 +244,8 @@ class AbstractRouter {
241
244
  history,
242
245
  navigateState,
243
246
  code,
247
+ redirect,
248
+ redirectFrom,
244
249
  };
245
250
  await this.runHooks('beforeResolve', navigation);
246
251
  const to = this.resolveRoute({ url: resolvedUrl, params, navigateState }, { wildcard: true });
@@ -366,7 +371,9 @@ class AbstractRouter {
366
371
  pathname = makePath(currentRoute.path, { ...currentRoute.params, ...params });
367
372
  }
368
373
  }
369
- pathname = this.normalizePathname(pathname);
374
+ if (isSameHost(resultUrl)) {
375
+ pathname = this.normalizePathname(pathname);
376
+ }
370
377
  return convertRawUrl(rawAssignUrl(resultUrl, {
371
378
  pathname,
372
379
  search: url ? resultUrl.search : '',
@@ -786,7 +793,7 @@ const wrapHistory = ({ onNavigate }) => {
786
793
  const history = (delta) => {
787
794
  go(delta);
788
795
  };
789
- const browserNavigate = (replace) => {
796
+ const browserNavigate = (replace = false) => {
790
797
  return (navigateState, title, url) => {
791
798
  onNavigate({ url, replace, navigateState });
792
799
  };
@@ -1000,8 +1007,11 @@ class ClientRouter extends AbstractRouter {
1000
1007
  // in case we didn't find any matched route just force hard page navigation
1001
1008
  const prevUrl = (_b = (_a = navigation.fromUrl) === null || _a === void 0 ? void 0 : _a.href) !== null && _b !== void 0 ? _b : window.location.href;
1002
1009
  const nextUrl = navigation.url.href;
1003
- // prevent redirect cycle on the same page
1004
- if (prevUrl !== nextUrl) {
1010
+ const isNoSpaNavigation = navigation.from && !navigation.to;
1011
+ // prevent redirect cycle on the same page,
1012
+ // except cases when we run no-spa navigations,
1013
+ // because we need hard reload in this cases
1014
+ if (isNoSpaNavigation ? true : prevUrl !== nextUrl) {
1005
1015
  if (navigation.replace) {
1006
1016
  window.location.replace(nextUrl);
1007
1017
  }
@@ -1017,7 +1027,12 @@ class ClientRouter extends AbstractRouter {
1017
1027
  }
1018
1028
  async redirect(navigation, target) {
1019
1029
  await super.redirect(navigation, target);
1020
- return this.navigate({ ...target, replace: target.replace || navigation.replace });
1030
+ return this.internalNavigate({
1031
+ ...target,
1032
+ replace: target.replace || navigation.replace,
1033
+ }, {
1034
+ redirect: true,
1035
+ });
1021
1036
  }
1022
1037
  }
1023
1038
 
package/lib/index.js CHANGED
@@ -236,17 +236,20 @@ class AbstractRouter {
236
236
  await this.runHooks('afterUpdateCurrent', navigation);
237
237
  }
238
238
  async navigate(navigateOptions) {
239
- return this.internalNavigate(typeof navigateOptions === 'string' ? { url: navigateOptions } : navigateOptions, {});
239
+ return this.internalNavigate(makeNavigateOptions(navigateOptions), {});
240
240
  }
241
- async internalNavigate(navigateOptions, { history }) {
241
+ async internalNavigate(navigateOptions, { history, redirect }) {
242
242
  var _a;
243
243
  const { url, replace, params, navigateState, code } = navigateOptions;
244
- const prevNavigation = (_a = this.currentNavigation) !== null && _a !== void 0 ? _a : this.lastNavigation;
244
+ const prevNavigation = redirect
245
+ ? this.lastNavigation
246
+ : (_a = this.currentNavigation) !== null && _a !== void 0 ? _a : this.lastNavigation;
245
247
  if (!url && !prevNavigation) {
246
248
  throw new Error('Navigate url should be specified and cannot be omitted for first navigation');
247
249
  }
248
250
  const resolvedUrl = this.resolveUrl(navigateOptions);
249
251
  const { to: from, url: fromUrl } = prevNavigation !== null && prevNavigation !== void 0 ? prevNavigation : {};
252
+ const redirectFrom = redirect ? this.currentNavigation.to : undefined;
250
253
  let navigation = {
251
254
  type: 'navigate',
252
255
  from,
@@ -256,6 +259,8 @@ class AbstractRouter {
256
259
  history,
257
260
  navigateState,
258
261
  code,
262
+ redirect,
263
+ redirectFrom,
259
264
  };
260
265
  await this.runHooks('beforeResolve', navigation);
261
266
  const to = this.resolveRoute({ url: resolvedUrl, params, navigateState }, { wildcard: true });
@@ -381,7 +386,9 @@ class AbstractRouter {
381
386
  pathname = makePath(currentRoute.path, { ...currentRoute.params, ...params });
382
387
  }
383
388
  }
384
- pathname = this.normalizePathname(pathname);
389
+ if (isSameHost(resultUrl)) {
390
+ pathname = this.normalizePathname(pathname);
391
+ }
385
392
  return url.convertRawUrl(url.rawAssignUrl(resultUrl, {
386
393
  pathname,
387
394
  search: url$1 ? resultUrl.search : '',
@@ -801,7 +808,7 @@ const wrapHistory = ({ onNavigate }) => {
801
808
  const history = (delta) => {
802
809
  go(delta);
803
810
  };
804
- const browserNavigate = (replace) => {
811
+ const browserNavigate = (replace = false) => {
805
812
  return (navigateState, title, url) => {
806
813
  onNavigate({ url, replace, navigateState });
807
814
  };
@@ -1015,8 +1022,11 @@ class ClientRouter extends AbstractRouter {
1015
1022
  // in case we didn't find any matched route just force hard page navigation
1016
1023
  const prevUrl = (_b = (_a = navigation.fromUrl) === null || _a === void 0 ? void 0 : _a.href) !== null && _b !== void 0 ? _b : window.location.href;
1017
1024
  const nextUrl = navigation.url.href;
1018
- // prevent redirect cycle on the same page
1019
- if (prevUrl !== nextUrl) {
1025
+ const isNoSpaNavigation = navigation.from && !navigation.to;
1026
+ // prevent redirect cycle on the same page,
1027
+ // except cases when we run no-spa navigations,
1028
+ // because we need hard reload in this cases
1029
+ if (isNoSpaNavigation ? true : prevUrl !== nextUrl) {
1020
1030
  if (navigation.replace) {
1021
1031
  window.location.replace(nextUrl);
1022
1032
  }
@@ -1032,7 +1042,12 @@ class ClientRouter extends AbstractRouter {
1032
1042
  }
1033
1043
  async redirect(navigation, target) {
1034
1044
  await super.redirect(navigation, target);
1035
- return this.navigate({ ...target, replace: target.replace || navigation.replace });
1045
+ return this.internalNavigate({
1046
+ ...target,
1047
+ replace: target.replace || navigation.replace,
1048
+ }, {
1049
+ redirect: true,
1050
+ });
1036
1051
  }
1037
1052
  }
1038
1053
 
@@ -20,6 +20,7 @@ export interface Options {
20
20
  }
21
21
  interface InternalOptions {
22
22
  history?: boolean;
23
+ redirect?: boolean;
23
24
  }
24
25
  export declare abstract class AbstractRouter {
25
26
  protected started: boolean;
@@ -45,7 +46,7 @@ export declare abstract class AbstractRouter {
45
46
  protected internalUpdateCurrentRoute(updateRouteOptions: UpdateCurrentRouteOptions, { history }: InternalOptions): Promise<void>;
46
47
  protected runUpdateCurrentRoute(navigation: Navigation): Promise<void>;
47
48
  navigate(navigateOptions: NavigateOptions | string): Promise<void>;
48
- protected internalNavigate(navigateOptions: NavigateOptions, { history }: InternalOptions): Promise<void>;
49
+ protected internalNavigate(navigateOptions: NavigateOptions, { history, redirect }: InternalOptions): Promise<void>;
49
50
  protected runNavigate(navigation: Navigation): Promise<void>;
50
51
  protected run(navigation: Navigation): Promise<void>;
51
52
  resolve(resolveOptions: NavigateOptions | string, options?: Parameters<AbstractRouter['resolveRoute']>[1]): import("../types").NavigationRoute;
package/lib/types.d.ts CHANGED
@@ -40,6 +40,8 @@ export interface Navigation {
40
40
  history?: boolean;
41
41
  cancelled?: boolean;
42
42
  code?: number;
43
+ redirect?: boolean;
44
+ redirectFrom?: NavigationRoute;
43
45
  }
44
46
  export declare type NavigationGuard = (navigation: Navigation) => Promise<void | NavigateOptions | string | boolean>;
45
47
  export declare type NavigationHook = (navigation: Navigation) => Promise<void>;
package/lib/utils.d.ts CHANGED
@@ -3,6 +3,6 @@ import type { NavigateOptions, NavigationHook, NavigationSyncHook, NavigationGua
3
3
  export declare const isFilePath: (pathname: string) => boolean;
4
4
  export declare const normalizeTrailingSlash: (pathname: string, trailingSlash?: boolean) => string;
5
5
  export declare const normalizeManySlashes: (hrefOrPath: string) => string;
6
- export declare const isSameHost: import("@tinkoff/utils/typings/types").Func<true> | ((url: Url) => boolean);
6
+ export declare const isSameHost: import("@tinkoff/utils/typings/types").Func<true> | ((url: Url | URL) => boolean);
7
7
  export declare const makeNavigateOptions: (options: string | NavigateOptions) => NavigateOptions;
8
8
  export declare const registerHook: <T extends NavigationHook | NavigationSyncHook | NavigationGuard>(hooksSet: Set<T>, hook: T) => () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinkoff/router",
3
- "version": "0.1.75",
3
+ "version": "0.1.78",
4
4
  "description": "router",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",