| 
									
										
										
										
											2016-06-23 09:47:54 -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-04-05 02:00:40 +03:00
										 |  |  | import {NgModuleFactory, NgModuleRef, Type} from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2018-02-27 17:06:06 -05:00
										 |  |  | import {Observable} from 'rxjs'; | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | import {EmptyOutletComponent} from './components/empty_outlet'; | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  | import {PRIMARY_OUTLET} from './shared'; | 
					
						
							| 
									
										
										
										
											2016-11-09 15:25:47 -08:00
										 |  |  | import {UrlSegment, UrlSegmentGroup} from './url_tree'; | 
					
						
							| 
									
										
										
										
											2016-08-19 17:48:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-27 12:27:23 -07:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2016-09-10 16:52:21 -07:00
										 |  |  |  * @description | 
					
						
							| 
									
										
										
										
											2018-04-05 11:51:21 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Represents router configuration. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * `Routes` is an array of route configurations. Each one has the following properties: | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-09-10 16:52:21 -07:00
										 |  |  |  * - `path` is a string that uses the route matcher DSL. | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * - `pathMatch` is a string that specifies the matching strategy. | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  * - `matcher` defines a custom strategy for path matching and supersedes `path` and `pathMatch`. | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * - `component` is a component type. | 
					
						
							|  |  |  |  * - `redirectTo` is the url fragment which will replace the current matched segment. | 
					
						
							|  |  |  |  * - `outlet` is the name of the outlet the component should be placed into. | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  * - `canActivate` is an array of DI tokens used to look up CanActivate handlers. See | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  *   `CanActivate` for more info. | 
					
						
							| 
									
										
										
										
											2016-07-13 15:25:48 -07:00
										 |  |  |  * - `canActivateChild` is an array of DI tokens used to look up CanActivateChild handlers. See | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  *   `CanActivateChild` for more info. | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  * - `canDeactivate` is an array of DI tokens used to look up CanDeactivate handlers. See | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  *   `CanDeactivate` for more info. | 
					
						
							| 
									
										
										
										
											2017-05-10 19:34:34 -04:00
										 |  |  |  * - `canLoad` is an array of DI tokens used to look up CanLoad handlers. See | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  *   `CanLoad` for more info. | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * - `data` is additional data provided to the component via `ActivatedRoute`. | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  * - `resolve` is a map of DI tokens used to look up data resolvers. See `Resolve` for more | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  *   info. | 
					
						
							| 
									
										
										
										
											2017-06-04 23:32:46 -03:00
										 |  |  |  * - `runGuardsAndResolvers` defines when guards and resolvers will be run. By default they run only | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  |  *    when the matrix parameters of the route change. When set to `paramsOrQueryParamsChange` they | 
					
						
							|  |  |  |  *    will also run when query params change. And when set to `always`, they will run every time. | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * - `children` is an array of child route definitions. | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  * - `loadChildren` is a reference to lazy loaded child routes. See `LoadChildren` for more | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  *   info. | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-09-20 14:50:32 +01:00
										 |  |  |  * @usageNotes | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * ### Simple Configuration | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * [{ | 
					
						
							|  |  |  |  *   path: 'team/:id', | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |   *  component: Team, | 
					
						
							|  |  |  |  *   children: [{ | 
					
						
							|  |  |  |  *     path: 'user/:name', | 
					
						
							|  |  |  |  *     component: User | 
					
						
							|  |  |  |  *   }] | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * }] | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * When navigating to `/team/11/user/bob`, the router will create the team component with the user | 
					
						
							|  |  |  |  * component in it. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ### Multiple Outlets | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * [{ | 
					
						
							|  |  |  |  *   path: 'team/:id', | 
					
						
							|  |  |  |  *   component: Team | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  * }, { | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  *   path: 'chat/:user', | 
					
						
							|  |  |  |  *   component: Chat | 
					
						
							| 
									
										
										
										
											2016-09-28 01:10:12 +08:00
										 |  |  |  *   outlet: 'aux' | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * }] | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * When navigating to `/team/11(aux:chat/jim)`, the router will create the team component next to | 
					
						
							|  |  |  |  * the chat component. The chat component will be placed into the aux outlet. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ### Wild Cards | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * [{ | 
					
						
							|  |  |  |  *   path: '**', | 
					
						
							|  |  |  |  *   component: Sink | 
					
						
							|  |  |  |  * }] | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Regardless of where you navigate to, the router will instantiate the sink component. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ### Redirects | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * [{ | 
					
						
							|  |  |  |  *   path: 'team/:id', | 
					
						
							|  |  |  |  *   component: Team, | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  *   children: [{ | 
					
						
							|  |  |  |  *     path: 'legacy/user/:name', | 
					
						
							|  |  |  |  *     redirectTo: 'user/:name' | 
					
						
							|  |  |  |  *   }, { | 
					
						
							|  |  |  |  *     path: 'user/:name', | 
					
						
							|  |  |  |  *     component: User | 
					
						
							|  |  |  |  *   }] | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * }] | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * When navigating to '/team/11/legacy/user/jim', the router will change the url to | 
					
						
							|  |  |  |  * '/team/11/user/jim', and then will instantiate the team component with the user component | 
					
						
							|  |  |  |  * in it. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * If the `redirectTo` value starts with a '/', then it is an absolute redirect. E.g., if in the | 
					
						
							|  |  |  |  * example above we change the `redirectTo` to `/user/:name`, the result url will be '/user/jim'. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ### Empty Path | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-09-10 16:52:21 -07:00
										 |  |  |  * Empty-path route configurations can be used to instantiate components that do not 'consume' | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * any url segments. Let's look at the following configuration: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * [{ | 
					
						
							|  |  |  |  *   path: 'team/:id', | 
					
						
							|  |  |  |  *   component: Team, | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  *   children: [{ | 
					
						
							|  |  |  |  *     path: '', | 
					
						
							|  |  |  |  *     component: AllUsers | 
					
						
							|  |  |  |  *   }, { | 
					
						
							|  |  |  |  *     path: 'user/:name', | 
					
						
							|  |  |  |  *     component: User | 
					
						
							|  |  |  |  *   }] | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * }] | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * When navigating to `/team/11`, the router will instantiate the AllUsers component. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Empty-path routes can have children. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * [{ | 
					
						
							|  |  |  |  *   path: 'team/:id', | 
					
						
							|  |  |  |  *   component: Team, | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  *   children: [{ | 
					
						
							|  |  |  |  *     path: '', | 
					
						
							|  |  |  |  *     component: WrapperCmp, | 
					
						
							|  |  |  |  *     children: [{ | 
					
						
							|  |  |  |  *       path: 'user/:name', | 
					
						
							|  |  |  |  *       component: User | 
					
						
							|  |  |  |  *     }] | 
					
						
							|  |  |  |  *   }] | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * }] | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * When navigating to `/team/11/user/jim`, the router will instantiate the wrapper component with | 
					
						
							|  |  |  |  * the user component in it. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-11-15 19:00:20 -08:00
										 |  |  |  * An empty path route inherits its parent's params and data. This is because it cannot have its | 
					
						
							|  |  |  |  * own params, and, as a result, it often uses its parent's params and data as its own. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * ### Matching Strategy | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * By default the router will look at what is left in the url, and check if it starts with | 
					
						
							|  |  |  |  * the specified path (e.g., `/team/11/user` starts with `team/:id`). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * We can change the matching strategy to make sure that the path covers the whole unconsumed url, | 
					
						
							|  |  |  |  * which is akin to `unconsumedUrl === path` or `$` regular expressions. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This is particularly important when redirecting empty-path routes. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * [{ | 
					
						
							|  |  |  |  *   path: '', | 
					
						
							|  |  |  |  *   pathMatch: 'prefix', //default
 | 
					
						
							|  |  |  |  *   redirectTo: 'main' | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  * }, { | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  *   path: 'main', | 
					
						
							|  |  |  |  *   component: Main | 
					
						
							|  |  |  |  * }] | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Since an empty path is a prefix of any url, even when navigating to '/main', the router will | 
					
						
							|  |  |  |  * still apply the redirect. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * If `pathMatch: full` is provided, the router will apply the redirect if and only if navigating to | 
					
						
							|  |  |  |  * '/'. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * [{ | 
					
						
							|  |  |  |  *   path: '', | 
					
						
							|  |  |  |  *   pathMatch: 'full', | 
					
						
							|  |  |  |  *   redirectTo: 'main' | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  * }, { | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  *   path: 'main', | 
					
						
							|  |  |  |  *   component: Main | 
					
						
							|  |  |  |  * }] | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ### Componentless Routes | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * It is useful at times to have the ability to share parameters between sibling components. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Say we have two components--ChildCmp and AuxCmp--that we want to put next to each other and both | 
					
						
							|  |  |  |  * of them require some id parameter. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * One way to do that would be to have a bogus parent component, so both the siblings can get the id | 
					
						
							|  |  |  |  * parameter from it. This is not ideal. Instead, you can use a componentless route. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * [{ | 
					
						
							|  |  |  |  *    path: 'parent/:id', | 
					
						
							|  |  |  |  *    children: [ | 
					
						
							|  |  |  |  *      { path: 'a', component: MainChild }, | 
					
						
							|  |  |  |  *      { path: 'b', component: AuxChild, outlet: 'aux' } | 
					
						
							|  |  |  |  *    ] | 
					
						
							|  |  |  |  * }] | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * So when navigating to `parent/10/(a//aux:b)`, the route will instantiate the main child and aux | 
					
						
							|  |  |  |  * child components next to each other. In this example, the application component | 
					
						
							|  |  |  |  * has to have the primary and aux outlets defined. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The router will also merge the `params`, `data`, and `resolve` of the componentless parent into | 
					
						
							| 
									
										
										
										
											2016-11-15 19:00:20 -08:00
										 |  |  |  * the `params`, `data`, and `resolve` of the children. This is done because there is no component | 
					
						
							|  |  |  |  * that can inject the activated route of the componentless parent. | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This is especially useful when child components are defined as follows: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * [{ | 
					
						
							|  |  |  |  *    path: 'parent/:id', | 
					
						
							|  |  |  |  *    children: [ | 
					
						
							|  |  |  |  *      { path: '', component: MainChild }, | 
					
						
							|  |  |  |  *      { path: '', component: AuxChild, outlet: 'aux' } | 
					
						
							|  |  |  |  *    ] | 
					
						
							|  |  |  |  * }] | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * With this configuration in place, navigating to '/parent/10' will create the main child and aux | 
					
						
							|  |  |  |  * components. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-09-10 16:52:21 -07:00
										 |  |  |  * ### Lazy Loading | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Lazy loading speeds up our application load time by splitting it into multiple bundles, and | 
					
						
							|  |  |  |  * loading them on demand. The router is designed to make lazy loading simple and easy. Instead of | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  * providing the children property, you can provide the `loadChildren` property, as follows: | 
					
						
							| 
									
										
										
										
											2016-09-10 16:52:21 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * [{ | 
					
						
							|  |  |  |  *   path: 'team/:id', | 
					
						
							|  |  |  |  *   component: Team, | 
					
						
							|  |  |  |  *   loadChildren: 'team' | 
					
						
							|  |  |  |  * }] | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The router will use registered NgModuleFactoryLoader to fetch an NgModule associated with 'team'. | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |  * Then it will extract the set of routes defined in that NgModule, and will transparently add | 
					
						
							|  |  |  |  * those routes to the main configuration. | 
					
						
							| 
									
										
										
										
											2016-09-10 16:52:21 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | export type Routes = Route[]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-09 15:25:47 -08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 11:51:21 +01:00
										 |  |  |  * @description Represents the results of the URL matching. | 
					
						
							| 
									
										
										
										
											2016-11-09 15:25:47 -08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * * `consumed` is an array of the consumed URL segments. | 
					
						
							|  |  |  |  * * `posParams` is a map of positional parameters. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @experimental | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export type UrlMatchResult = { | 
					
						
							|  |  |  |   consumed: UrlSegment[]; posParams?: {[name: string]: UrlSegment}; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @description | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-04-05 11:51:21 +01:00
										 |  |  |  * A function matching URLs | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-11-09 15:25:47 -08:00
										 |  |  |  * A custom URL matcher can be provided when a combination of `path` and `pathMatch` isn't | 
					
						
							|  |  |  |  * expressive enough. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * For instance, the following matcher matches html files. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							| 
									
										
										
										
											2017-12-19 15:53:22 -08:00
										 |  |  |  * export function htmlFiles(url: UrlSegment[]) { | 
					
						
							|  |  |  |  *   return url.length === 1 && url[0].path.endsWith('.html') ? ({consumed: url}) : null; | 
					
						
							| 
									
										
										
										
											2016-11-09 15:25:47 -08:00
										 |  |  |  * } | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2017-12-19 15:53:22 -08:00
										 |  |  |  * export const routes = [{ matcher: htmlFiles, component: AnyComponent }]; | 
					
						
							| 
									
										
										
										
											2016-11-09 15:25:47 -08:00
										 |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @experimental | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export type UrlMatcher = (segments: UrlSegment[], group: UrlSegmentGroup, route: Route) => | 
					
						
							|  |  |  |     UrlMatchResult; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 16:19:52 -07:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 11:51:21 +01:00
										 |  |  |  * @description | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Represents the static data associated with a particular route. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  * See `Routes` for more details. | 
					
						
							| 
									
										
										
										
											2018-04-05 22:31:44 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-06-27 12:27:23 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-06-27 14:00:07 -07:00
										 |  |  | export type Data = { | 
					
						
							|  |  |  |   [name: string]: any | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2016-06-27 12:27:23 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 11:51:21 +01:00
										 |  |  |  * @description | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Represents the resolved data associated with a particular route. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  * See `Routes` for more details. | 
					
						
							| 
									
										
										
										
											2018-04-05 22:31:44 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-06-27 12:27:23 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-06-27 14:00:07 -07:00
										 |  |  | export type ResolveData = { | 
					
						
							|  |  |  |   [name: string]: any | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2016-05-23 16:14:23 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 21:11:09 -07:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 11:51:21 +01:00
										 |  |  |  * @description | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The type of `loadChildren`. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  * See `Routes` for more details. | 
					
						
							| 
									
										
										
										
											2018-04-05 22:31:44 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-08-15 21:11:09 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-01-19 02:56:34 +03:00
										 |  |  | export type LoadChildrenCallback = () => | 
					
						
							|  |  |  |     Type<any>| NgModuleFactory<any>| Promise<Type<any>>| Observable<Type<any>>; | 
					
						
							| 
									
										
										
										
											2016-08-15 21:11:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 11:51:21 +01:00
										 |  |  |  * @description | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The type of `loadChildren`. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  * See `Routes` for more details. | 
					
						
							| 
									
										
										
										
											2018-04-05 22:31:44 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-08-15 21:11:09 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | export type LoadChildren = string | LoadChildrenCallback; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 17:33:13 +08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 11:51:21 +01:00
										 |  |  |  * @description | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The type of `queryParamsHandling`. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  * See `RouterLink` for more details. | 
					
						
							| 
									
										
										
										
											2018-04-05 22:31:44 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2017-01-25 17:33:13 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | export type QueryParamsHandling = 'merge' | 'preserve' | ''; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 11:51:21 +01:00
										 |  |  |  * @description | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The type of `runGuardsAndResolvers`. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  * See `Routes` for more details. | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  |  * @experimental | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export type RunGuardsAndResolvers = 'paramsChange' | 'paramsOrQueryParamsChange' | 'always'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-27 12:27:23 -07:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 11:53:57 +01:00
										 |  |  |  * See `Routes` for more details. | 
					
						
							| 
									
										
										
										
											2018-04-05 22:31:44 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-06-27 12:27:23 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-05-23 16:14:23 -07:00
										 |  |  | export interface Route { | 
					
						
							|  |  |  |   path?: string; | 
					
						
							| 
									
										
										
										
											2016-07-28 12:15:07 -07:00
										 |  |  |   pathMatch?: string; | 
					
						
							| 
									
										
										
										
											2016-11-09 15:25:47 -08:00
										 |  |  |   matcher?: UrlMatcher; | 
					
						
							| 
									
										
										
										
											2016-08-16 13:40:28 -07:00
										 |  |  |   component?: Type<any>; | 
					
						
							| 
									
										
										
										
											2016-06-28 14:49:29 -07:00
										 |  |  |   redirectTo?: string; | 
					
						
							| 
									
										
										
										
											2016-05-23 16:14:23 -07:00
										 |  |  |   outlet?: string; | 
					
						
							| 
									
										
										
										
											2016-06-07 09:50:35 -07:00
										 |  |  |   canActivate?: any[]; | 
					
						
							| 
									
										
										
										
											2016-07-13 15:15:20 -07:00
										 |  |  |   canActivateChild?: any[]; | 
					
						
							| 
									
										
										
										
											2016-06-07 09:50:35 -07:00
										 |  |  |   canDeactivate?: any[]; | 
					
						
							| 
									
										
										
										
											2016-07-26 14:39:02 -07:00
										 |  |  |   canLoad?: any[]; | 
					
						
							| 
									
										
										
										
											2016-06-27 14:00:07 -07:00
										 |  |  |   data?: Data; | 
					
						
							|  |  |  |   resolve?: ResolveData; | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |   children?: Routes; | 
					
						
							| 
									
										
										
										
											2016-08-15 21:11:09 -07:00
										 |  |  |   loadChildren?: LoadChildren; | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  |   runGuardsAndResolvers?: RunGuardsAndResolvers; | 
					
						
							| 
									
										
										
										
											2017-04-11 08:34:58 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Filled for routes with `loadChildren` once the module has been loaded | 
					
						
							|  |  |  |    * @internal | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-05 02:00:40 +03:00
										 |  |  |   _loadedConfig?: LoadedRouterConfig; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export class LoadedRouterConfig { | 
					
						
							|  |  |  |   constructor(public routes: Route[], public module: NgModuleRef<any>) {} | 
					
						
							| 
									
										
										
										
											2016-06-16 14:36:51 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  | export function validateConfig(config: Routes, parentPath: string = ''): void { | 
					
						
							| 
									
										
										
										
											2016-11-11 01:55:10 +03:00
										 |  |  |   // forEach doesn't iterate undefined values
 | 
					
						
							|  |  |  |   for (let i = 0; i < config.length; i++) { | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |     const route: Route = config[i]; | 
					
						
							|  |  |  |     const fullPath: string = getFullPath(parentPath, route); | 
					
						
							|  |  |  |     validateNode(route, fullPath); | 
					
						
							| 
									
										
										
										
											2016-11-11 01:55:10 +03:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-16 14:36:51 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  | function validateNode(route: Route, fullPath: string): void { | 
					
						
							| 
									
										
										
										
											2016-11-11 01:55:10 +03:00
										 |  |  |   if (!route) { | 
					
						
							|  |  |  |     throw new Error(`
 | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |       Invalid configuration of route '${fullPath}': Encountered undefined route. | 
					
						
							| 
									
										
										
										
											2016-11-11 01:55:10 +03:00
										 |  |  |       The reason might be an extra comma. | 
					
						
							| 
									
										
										
										
											2017-02-23 22:12:30 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       Example: | 
					
						
							| 
									
										
										
										
											2016-11-11 01:55:10 +03:00
										 |  |  |       const routes: Routes = [ | 
					
						
							|  |  |  |         { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, | 
					
						
							|  |  |  |         { path: 'dashboard',  component: DashboardComponent },, << two commas | 
					
						
							|  |  |  |         { path: 'detail/:id', component: HeroDetailComponent } | 
					
						
							|  |  |  |       ]; | 
					
						
							|  |  |  |     `);
 | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-07-15 00:28:31 +09:00
										 |  |  |   if (Array.isArray(route)) { | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |     throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`); | 
					
						
							| 
									
										
										
										
											2016-07-15 00:28:31 +09:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  |   if (!route.component && !route.children && !route.loadChildren && | 
					
						
							|  |  |  |       (route.outlet && route.outlet !== PRIMARY_OUTLET)) { | 
					
						
							| 
									
										
										
										
											2016-10-20 15:00:15 -07:00
										 |  |  |     throw new Error( | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  |         `Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`); | 
					
						
							| 
									
										
										
										
											2016-10-20 15:00:15 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |   if (route.redirectTo && route.children) { | 
					
						
							| 
									
										
										
										
											2016-06-16 14:36:51 -07:00
										 |  |  |     throw new Error( | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |         `Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`); | 
					
						
							| 
									
										
										
										
											2016-06-16 14:36:51 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |   if (route.redirectTo && route.loadChildren) { | 
					
						
							| 
									
										
										
										
											2016-07-06 11:02:16 -07:00
										 |  |  |     throw new Error( | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |         `Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`); | 
					
						
							| 
									
										
										
										
											2016-07-06 11:02:16 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |   if (route.children && route.loadChildren) { | 
					
						
							| 
									
										
										
										
											2016-07-06 11:02:16 -07:00
										 |  |  |     throw new Error( | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |         `Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`); | 
					
						
							| 
									
										
										
										
											2016-07-06 11:02:16 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |   if (route.redirectTo && route.component) { | 
					
						
							| 
									
										
										
										
											2016-06-16 14:36:51 -07:00
										 |  |  |     throw new Error( | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |         `Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`); | 
					
						
							| 
									
										
										
										
											2016-06-16 14:36:51 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |   if (route.path && route.matcher) { | 
					
						
							| 
									
										
										
										
											2016-11-09 15:25:47 -08:00
										 |  |  |     throw new Error( | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |         `Invalid configuration of route '${fullPath}': path and matcher cannot be used together`); | 
					
						
							| 
									
										
										
										
											2016-11-09 15:25:47 -08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |   if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) { | 
					
						
							| 
									
										
										
										
											2016-06-19 14:44:20 -07:00
										 |  |  |     throw new Error( | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |         `Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`); | 
					
						
							| 
									
										
										
										
											2016-06-19 14:44:20 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-02 14:17:27 -08:00
										 |  |  |   if (route.path === void 0 && route.matcher === void 0) { | 
					
						
							|  |  |  |     throw new Error( | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |         `Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`); | 
					
						
							| 
									
										
										
										
											2016-06-16 14:36:51 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-02 14:17:27 -08:00
										 |  |  |   if (typeof route.path === 'string' && route.path.charAt(0) === '/') { | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |     throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`); | 
					
						
							| 
									
										
										
										
											2016-06-16 14:36:51 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |   if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) { | 
					
						
							| 
									
										
										
										
											2016-06-27 20:10:36 -07:00
										 |  |  |     const exp = | 
					
						
							|  |  |  |         `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`; | 
					
						
							|  |  |  |     throw new Error( | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |         `Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`); | 
					
						
							| 
									
										
										
										
											2016-06-27 20:10:36 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-02 14:09:09 -08:00
										 |  |  |   if (route.pathMatch !== void 0 && route.pathMatch !== 'full' && route.pathMatch !== 'prefix') { | 
					
						
							| 
									
										
										
										
											2016-07-29 09:59:50 -07:00
										 |  |  |     throw new Error( | 
					
						
							| 
									
										
										
										
											2016-12-06 21:41:01 +03:00
										 |  |  |         `Invalid configuration of route '${fullPath}': pathMatch can only be set to 'prefix' or 'full'`); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (route.children) { | 
					
						
							|  |  |  |     validateConfig(route.children, fullPath); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function getFullPath(parentPath: string, currentRoute: Route): string { | 
					
						
							|  |  |  |   if (!currentRoute) { | 
					
						
							|  |  |  |     return parentPath; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (!parentPath && !currentRoute.path) { | 
					
						
							|  |  |  |     return ''; | 
					
						
							|  |  |  |   } else if (parentPath && !currentRoute.path) { | 
					
						
							|  |  |  |     return `${parentPath}/`; | 
					
						
							|  |  |  |   } else if (!parentPath && currentRoute.path) { | 
					
						
							|  |  |  |     return currentRoute.path; | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     return `${parentPath}/${currentRoute.path}`; | 
					
						
							| 
									
										
										
										
											2016-07-29 09:59:50 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-27 12:27:23 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-02-21 10:21:47 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-06 15:56:36 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Makes a copy of the config and adds any default required properties. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export function standardizeConfig(r: Route): Route { | 
					
						
							|  |  |  |   const children = r.children && r.children.map(standardizeConfig); | 
					
						
							|  |  |  |   const c = children ? {...r, children} : {...r}; | 
					
						
							|  |  |  |   if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) { | 
					
						
							|  |  |  |     c.component = EmptyOutletComponent; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return c; | 
					
						
							| 
									
										
										
										
											2018-02-27 17:06:06 -05:00
										 |  |  | } |