From 96f5c971baae2ffac1de2b995cda8fdb73247069 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Fri, 4 Feb 2022 10:51:45 -0800 Subject: [PATCH] refactor(router): Move runCanLoadGuards to same location as similar functions (#46021) This commit moves the runCanLoadGuards to the same location as other guard execution functions PR Close #46021 --- packages/router/src/apply_redirects.ts | 36 +----------- packages/router/src/operators/check_guards.ts | 57 +++++++++++++++++-- 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/packages/router/src/apply_redirects.ts b/packages/router/src/apply_redirects.ts index ffd4bdd9540..78a287a647b 100644 --- a/packages/router/src/apply_redirects.ts +++ b/packages/router/src/apply_redirects.ts @@ -11,6 +11,7 @@ import {EmptyError, from, Observable, of, throwError} from 'rxjs'; import {catchError, concatMap, first, last, map, mergeMap, scan, tap} from 'rxjs/operators'; import {CanLoadFn, LoadedRouterConfig, Route, Routes} from './models'; +import {runCanLoadGuards} from './operators/check_guards'; import {prioritizedGuardValue} from './operators/prioritized_guard_value'; import {RouterConfigLoader} from './router_config_loader'; import {navigationCancelingError, Params, PRIMARY_OUTLET} from './shared'; @@ -335,7 +336,7 @@ class ApplyRedirects { return of({routes: route._loadedRoutes, injector: route._loadedInjector}); } - return this.runCanLoadGuards(injector, route, segments) + return runCanLoadGuards(injector, route, segments, this.urlSerializer) .pipe(mergeMap((shouldLoadResult: boolean) => { if (shouldLoadResult) { return this.configLoader.loadChildren(injector, route) @@ -351,39 +352,6 @@ class ApplyRedirects { return of({routes: [], injector}); } - private runCanLoadGuards(injector: EnvironmentInjector, route: Route, segments: UrlSegment[]): - Observable { - const canLoad = route.canLoad; - if (!canLoad || canLoad.length === 0) return of(true); - - const canLoadObservables = canLoad.map((injectionToken: any) => { - const guard = injector.get(injectionToken); - let guardVal; - if (isCanLoad(guard)) { - guardVal = guard.canLoad(route, segments); - } else if (isFunction(guard)) { - guardVal = guard(route, segments); - } else { - throw new Error('Invalid CanLoad guard'); - } - return wrapIntoObservable(guardVal); - }); - - return of(canLoadObservables) - .pipe( - prioritizedGuardValue(), - tap((result: UrlTree|boolean) => { - if (!isUrlTree(result)) return; - - const error: Error&{url?: UrlTree} = navigationCancelingError( - `Redirecting to "${this.urlSerializer.serialize(result)}"`); - error.url = result; - throw error; - }), - map(result => result === true), - ); - } - private lineralizeSegments(route: Route, urlTree: UrlTree): Observable { let res: UrlSegment[] = []; let c = urlTree.root; diff --git a/packages/router/src/operators/check_guards.ts b/packages/router/src/operators/check_guards.ts index a0698ba78c8..60f73905a0c 100644 --- a/packages/router/src/operators/check_guards.ts +++ b/packages/router/src/operators/check_guards.ts @@ -6,18 +6,19 @@ * found in the LICENSE file at https://angular.io/license */ -import {Injector} from '@angular/core'; -import {concat, defer, from, MonoTypeOperatorFunction, Observable, of} from 'rxjs'; -import {concatMap, first, map, mergeMap} from 'rxjs/operators'; +import {EnvironmentInjector, Injector} from '@angular/core'; +import {concat, defer, from, MonoTypeOperatorFunction, Observable, of, OperatorFunction, pipe} from 'rxjs'; +import {concatMap, first, map, mergeMap, tap} from 'rxjs/operators'; import {ActivationStart, ChildActivationStart, Event} from '../events'; -import {CanActivateChildFn, CanActivateFn, CanDeactivateFn} from '../models'; +import {CanActivateChildFn, CanActivateFn, CanDeactivateFn, CanLoadFn, Route} from '../models'; import {NavigationTransition} from '../router'; import {ActivatedRouteSnapshot, RouterStateSnapshot} from '../router_state'; -import {UrlTree} from '../url_tree'; +import {navigationCancelingError} from '../shared'; +import {UrlSegment, UrlSerializer, UrlTree} from '../url_tree'; import {wrapIntoObservable} from '../utils/collection'; import {CanActivate, CanDeactivate, getCanActivateChild, getToken} from '../utils/preactivation'; -import {isBoolean, isCanActivate, isCanActivateChild, isCanDeactivate, isFunction} from '../utils/type_guards'; +import {isBoolean, isCanActivate, isCanActivateChild, isCanDeactivate, isCanLoad, isFunction, isUrlTree} from '../utils/type_guards'; import {prioritizedGuardValue} from './prioritized_guard_value'; @@ -176,3 +177,47 @@ function runCanDeactivate( }); return of(canDeactivateObservables).pipe(prioritizedGuardValue()); } + + +export function runCanLoadGuards( + injector: EnvironmentInjector, route: Route, segments: UrlSegment[], + urlSerializer: UrlSerializer): Observable { + const canLoad = route.canLoad; + if (canLoad === undefined || canLoad.length === 0) { + return of(true); + } + + const canLoadObservables = canLoad.map((injectionToken: any) => { + const guard = injector.get(injectionToken); + let guardVal; + if (isCanLoad(guard)) { + guardVal = guard.canLoad(route, segments); + } else if (isFunction(guard)) { + guardVal = guard(route, segments); + } else { + throw new Error('Invalid CanLoad guard'); + } + return wrapIntoObservable(guardVal); + }); + + return of(canLoadObservables) + .pipe( + prioritizedGuardValue(), + redirectIfUrlTree(urlSerializer), + ); +} + +function redirectIfUrlTree(urlSerializer: UrlSerializer): + OperatorFunction { + return pipe( + tap((result: UrlTree|boolean) => { + if (!isUrlTree(result)) return; + + const error: Error&{url?: UrlTree} = + navigationCancelingError(`Redirecting to "${urlSerializer.serialize(result)}"`); + error.url = result; + throw error; + }), + map(result => result === true), + ); +} \ No newline at end of file