55* Use of this source code is governed by an MIT-style license that can be
66* found in the LICENSE file at https://angular.io/license
77*/
8- import { normalize , strings } from '@angular-devkit/core' ;
8+ import { Path , normalize , strings } from '@angular-devkit/core' ;
99import {
1010 Rule ,
1111 SchematicsException ,
@@ -17,17 +17,28 @@ import {
1717 mergeWith ,
1818 move ,
1919 noop ,
20+ schematic ,
2021 url ,
2122} from '@angular-devkit/schematics' ;
2223import * as ts from '../third_party/github.com/Microsoft/TypeScript/lib/typescript' ;
23- import { addImportToModule } from '../utility/ast-utils' ;
24+ import { addImportToModule , addRouteDeclarationToModule } from '../utility/ast-utils' ;
2425import { InsertChange } from '../utility/change' ;
2526import { buildRelativePath , findModuleFromOptions } from '../utility/find-module' ;
2627import { applyLintFix } from '../utility/lint-fix' ;
2728import { parseName } from '../utility/parse-name' ;
2829import { createDefaultPath } from '../utility/workspace' ;
29- import { Schema as ModuleOptions } from './schema' ;
30+ import { RoutingScope , Schema as ModuleOptions } from './schema' ;
3031
32+ function buildRelativeModulePath ( options : ModuleOptions , modulePath : string ) : string {
33+ const importModulePath = normalize (
34+ `/${ options . path } /`
35+ + ( options . flat ? '' : strings . dasherize ( options . name ) + '/' )
36+ + strings . dasherize ( options . name )
37+ + '.module' ,
38+ ) ;
39+
40+ return buildRelativePath ( modulePath , importModulePath ) ;
41+ }
3142
3243function addDeclarationToNgModule ( options : ModuleOptions ) : Rule {
3344 return ( host : Tree ) => {
@@ -41,16 +52,10 @@ function addDeclarationToNgModule(options: ModuleOptions): Rule {
4152 if ( text === null ) {
4253 throw new SchematicsException ( `File ${ modulePath } does not exist.` ) ;
4354 }
44- const sourceText = text . toString ( 'utf-8' ) ;
55+ const sourceText = text . toString ( ) ;
4556 const source = ts . createSourceFile ( modulePath , sourceText , ts . ScriptTarget . Latest , true ) ;
4657
47- const importModulePath = normalize (
48- `/${ options . path } /`
49- + ( options . flat ? '' : strings . dasherize ( options . name ) + '/' )
50- + strings . dasherize ( options . name )
51- + '.module' ,
52- ) ;
53- const relativePath = buildRelativePath ( modulePath , importModulePath ) ;
58+ const relativePath = buildRelativeModulePath ( options , modulePath ) ;
5459 const changes = addImportToModule ( source ,
5560 modulePath ,
5661 strings . classify ( `${ options . name } Module` ) ,
@@ -68,6 +73,66 @@ function addDeclarationToNgModule(options: ModuleOptions): Rule {
6873 } ;
6974}
7075
76+ function addRouteDeclarationToNgModule (
77+ options : ModuleOptions ,
78+ routingModulePath : Path | undefined ,
79+ ) : Rule {
80+ return ( host : Tree ) => {
81+ if ( ! options . route ) {
82+ return host ;
83+ }
84+ if ( ! options . module ) {
85+ throw new Error ( 'Module option required when creating a lazy loaded routing module.' ) ;
86+ }
87+
88+ let path : string ;
89+ if ( routingModulePath ) {
90+ path = routingModulePath ;
91+ } else {
92+ path = options . module ;
93+ }
94+
95+ const text = host . read ( path ) ;
96+ if ( ! text ) {
97+ throw new Error ( `Couldn't find the module nor its routing module.` ) ;
98+ }
99+
100+ const sourceText = text . toString ( ) ;
101+ const addDeclaration = addRouteDeclarationToModule (
102+ ts . createSourceFile ( path , sourceText , ts . ScriptTarget . Latest , true ) ,
103+ path ,
104+ buildRoute ( options , options . module ) ,
105+ ) as InsertChange ;
106+
107+ const recorder = host . beginUpdate ( path ) ;
108+ recorder . insertLeft ( addDeclaration . pos , addDeclaration . toAdd ) ;
109+ host . commitUpdate ( recorder ) ;
110+
111+ return host ;
112+ } ;
113+ }
114+
115+ function getRoutingModulePath ( host : Tree , options : ModuleOptions ) : Path | undefined {
116+ let path : Path | undefined ;
117+ const modulePath = options . module as string ;
118+ const routingModuleName = modulePath . split ( '.' ) [ 0 ] + '-routing' ;
119+ const { module, ...rest } = options ;
120+
121+ try {
122+ path = findModuleFromOptions ( host , { module : routingModuleName , ...rest } ) ;
123+ } catch { }
124+
125+ return path ;
126+ }
127+
128+ function buildRoute ( options : ModuleOptions , modulePath : string ) {
129+ const relativeModulePath = buildRelativeModulePath ( options , modulePath ) ;
130+ const moduleName = `${ strings . classify ( options . name ) } Module` ;
131+ const loadChildren = `() => import('${ relativeModulePath } ').then(m => m.${ moduleName } )` ;
132+
133+ return `{ path: '${ options . route } ', loadChildren: ${ loadChildren } }` ;
134+ }
135+
71136export default function ( options : ModuleOptions ) : Rule {
72137 return async ( host : Tree ) => {
73138 if ( options . path === undefined ) {
@@ -82,19 +147,41 @@ export default function (options: ModuleOptions): Rule {
82147 options . name = parsedPath . name ;
83148 options . path = parsedPath . path ;
84149
150+ let routingModulePath : Path | undefined ;
151+ const isLazyLoadedModuleGen = options . route && options . module ;
152+ if ( isLazyLoadedModuleGen ) {
153+ options . routingScope = RoutingScope . Child ;
154+ routingModulePath = getRoutingModulePath ( host , options ) ;
155+ }
156+
85157 const templateSource = apply ( url ( './files' ) , [
86- options . routing ? noop ( ) : filter ( path => ! path . endsWith ( '-routing.module.ts.template' ) ) ,
158+ options . routing || isLazyLoadedModuleGen && ! ! routingModulePath
159+ ? noop ( )
160+ : filter ( path => ! path . endsWith ( '-routing.module.ts.template' ) ) ,
87161 applyTemplates ( {
88162 ...strings ,
89163 'if-flat' : ( s : string ) => options . flat ? '' : s ,
164+ lazyRoute : isLazyLoadedModuleGen ,
165+ lazyRouteWithoutRouteModule : isLazyLoadedModuleGen && ! routingModulePath ,
166+ lazyRouteWithRouteModule : isLazyLoadedModuleGen && routingModulePath ,
90167 ...options ,
91168 } ) ,
92169 move ( parsedPath . path ) ,
93170 ] ) ;
171+ const moduleDasherized = strings . dasherize ( options . name ) ;
172+ const modulePath =
173+ `${ ! options . flat ? moduleDasherized + '/' : '' } ${ moduleDasherized } .module.ts` ;
94174
95175 return chain ( [
96- addDeclarationToNgModule ( options ) ,
176+ ! isLazyLoadedModuleGen ? addDeclarationToNgModule ( options ) : noop ( ) ,
177+ addRouteDeclarationToNgModule ( options , routingModulePath ) ,
97178 mergeWith ( templateSource ) ,
179+ isLazyLoadedModuleGen
180+ ? schematic ( 'component' , {
181+ ...options ,
182+ module : modulePath ,
183+ } )
184+ : noop ( ) ,
98185 options . lintFix ? applyLintFix ( options . path ) : noop ( ) ,
99186 ] ) ;
100187 } ;
0 commit comments