2016-07-06 11:02:16 -07:00
/ * *
* @license
* Copyright Google Inc . All Rights Reserved .
*
* Use of this source code is governed by an MIT - style license that can be
* found in the LICENSE file at https : //angular.io/license
* /
2017-03-08 11:36:09 +03:00
import { Compiler , InjectionToken , Injector , NgModuleFactory , NgModuleFactoryLoader , NgModuleRef , ɵ stringify as stringify } from '@angular/core' ;
2016-07-06 11:02:16 -07:00
import { Observable } from 'rxjs/Observable' ;
import { fromPromise } from 'rxjs/observable/fromPromise' ;
2016-08-15 21:11:09 -07:00
import { of } from 'rxjs/observable/of' ;
2016-08-30 14:25:46 -07:00
import { map } from 'rxjs/operator/map' ;
import { mergeMap } from 'rxjs/operator/mergeMap' ;
2017-04-05 02:00:40 +03:00
import { LoadChildren , LoadedRouterConfig , Route } from './config' ;
2016-08-15 21:11:09 -07:00
import { flatten , wrapIntoObservable } from './utils/collection' ;
2016-07-06 11:02:16 -07:00
2016-08-30 18:07:40 -07:00
/ * *
2017-02-15 13:30:40 -08:00
* @docsNotRequired
2016-08-30 18:07:40 -07:00
* @experimental
* /
2017-01-03 16:54:46 -08:00
export const ROUTES = new InjectionToken < Route [ ] [ ] > ( 'ROUTES' ) ;
2016-07-06 11:32:42 -07:00
2016-07-06 11:02:16 -07:00
export class RouterConfigLoader {
2017-02-02 00:13:57 +03:00
constructor (
private loader : NgModuleFactoryLoader , private compiler : Compiler ,
2017-02-15 10:57:03 -08:00
private onLoadStartListener ? : ( r : Route ) = > void ,
private onLoadEndListener ? : ( r : Route ) = > void ) { }
2017-02-02 00:13:57 +03:00
load ( parentInjector : Injector , route : Route ) : Observable < LoadedRouterConfig > {
2017-02-15 10:57:03 -08:00
if ( this . onLoadStartListener ) {
this . onLoadStartListener ( route ) ;
}
2017-04-17 11:13:13 -07:00
const moduleFactory $ = this . loadModuleFactory ( route . loadChildren ! ) ;
2017-02-15 10:57:03 -08:00
2017-02-02 00:13:57 +03:00
return map . call ( moduleFactory $ , ( factory : NgModuleFactory < any > ) = > {
2017-02-15 10:57:03 -08:00
if ( this . onLoadEndListener ) {
this . onLoadEndListener ( route ) ;
}
2017-02-02 00:13:57 +03:00
const module = factory . create ( parentInjector ) ;
2017-02-15 10:57:03 -08:00
2017-03-08 11:36:09 +03:00
const parentRoutes = new Set ( flatten ( parentInjector . get ( ROUTES ) ) ) ;
const moduleRoutes =
flatten ( module . injector . get ( ROUTES ) ) . filter ( route = > ! parentRoutes . has ( route ) ) ;
if ( moduleRoutes . length === 0 ) {
throw new Error (
` A lazy loaded module must define at least 1 route, but it seems like the ' ${ stringify ( factory . moduleType ) } ' module hasn't defined any. Have you imported RouterModule.forChild(ROUTES) in this module? ` ) ;
}
return new LoadedRouterConfig ( moduleRoutes , module ) ;
2016-08-15 21:11:09 -07:00
} ) ;
2016-07-06 11:02:16 -07:00
}
2016-08-15 21:11:09 -07:00
private loadModuleFactory ( loadChildren : LoadChildren ) : Observable < NgModuleFactory < any > > {
if ( typeof loadChildren === 'string' ) {
return fromPromise ( this . loader . load ( loadChildren ) ) ;
} else {
2017-03-07 17:27:20 -05:00
return mergeMap . call ( wrapIntoObservable ( loadChildren ( ) ) , ( t : any ) = > {
if ( t instanceof NgModuleFactory ) {
return of ( t ) ;
} else {
return fromPromise ( this . compiler . compileModuleAsync ( t ) ) ;
}
} ) ;
2016-08-15 21:11:09 -07:00
}
}
2016-08-30 18:07:40 -07:00
}