diff --git a/docs/generated/packages/angular.json b/docs/generated/packages/angular.json index c2bbb98e3f..5934dc0822 100644 --- a/docs/generated/packages/angular.json +++ b/docs/generated/packages/angular.json @@ -839,7 +839,8 @@ }, "parentModule": { "type": "string", - "description": "Update the router configuration of the parent module using `loadChildren` or `children`, depending on what `lazy` is set to." + "description": "Update the router configuration of the parent module using `loadChildren` or `children`, depending on what `lazy` is set to.", + "alias": "parent" }, "tags": { "type": "string", diff --git a/packages/angular/src/generators/library/lib/add-children.ts b/packages/angular/src/generators/library/lib/add-children.ts index 7de77dad08..ef68b57955 100644 --- a/packages/angular/src/generators/library/lib/add-children.ts +++ b/packages/angular/src/generators/library/lib/add-children.ts @@ -6,13 +6,14 @@ import { addRoute, } from '../../../utils/nx-devkit/ast-utils'; import { NormalizedSchema } from './normalized-schema'; +import { addStandaloneRoute } from '../../../utils/nx-devkit/standalone-utils'; -export function addChildren(host: Tree, options: NormalizedSchema) { - if (!host.exists(options.parentModule)) { +export function addChildren(tree: Tree, options: NormalizedSchema) { + if (!tree.exists(options.parentModule)) { throw new Error(`Cannot find '${options.parentModule}'`); } - const moduleSource = host.read(options.parentModule, 'utf-8'); + const moduleSource = tree.read(options.parentModule, 'utf-8'); const constName = options.standalone ? `${names(options.name).className.toUpperCase()}_ROUTES` : `${names(options.fileName).propertyName}Routes`; @@ -26,24 +27,35 @@ export function addChildren(host: Tree, options: NormalizedSchema) { if (!options.standalone) { sourceFile = addImportToModule( - host, + tree, sourceFile, options.parentModule, options.moduleName ); } - sourceFile = addRoute( - host, - options.parentModule, - sourceFile, - `{ path: '${names(options.fileName).fileName}', children: ${constName} }` - ); sourceFile = insertImport( - host, + tree, sourceFile, options.parentModule, options.standalone ? constName : `${options.moduleName}, ${constName}`, importPath ); + + const route = `{ path: '${ + names(options.fileName).fileName + }', children: ${constName} }`; + + if (moduleSource.includes('@NgModule')) { + sourceFile = addRoute(tree, options.parentModule, sourceFile, route); + } else { + addStandaloneRoute( + tree, + options.parentModule, + route, + false, + constName, + importPath + ); + } } diff --git a/packages/angular/src/generators/library/lib/add-load-children.ts b/packages/angular/src/generators/library/lib/add-load-children.ts index 546f5ef3aa..3d28faf8f3 100644 --- a/packages/angular/src/generators/library/lib/add-load-children.ts +++ b/packages/angular/src/generators/library/lib/add-load-children.ts @@ -2,13 +2,14 @@ import { names, Tree } from '@nrwl/devkit'; import * as ts from 'typescript'; import { addRoute } from '../../../utils/nx-devkit/ast-utils'; import { NormalizedSchema } from './normalized-schema'; +import { addStandaloneRoute } from '../../../utils/nx-devkit/standalone-utils'; -export function addLoadChildren(host: Tree, options: NormalizedSchema) { - if (!host.exists(options.parentModule)) { +export function addLoadChildren(tree: Tree, options: NormalizedSchema) { + if (!tree.exists(options.parentModule)) { throw new Error(`Cannot find '${options.parentModule}'`); } - const moduleSource = host.read(options.parentModule)!.toString('utf-8'); + const moduleSource = tree.read(options.parentModule)!.toString('utf-8'); const sourceFile = ts.createSourceFile( options.parentModule, moduleSource, @@ -16,16 +17,17 @@ export function addLoadChildren(host: Tree, options: NormalizedSchema) { true ); - addRoute( - host, - options.parentModule, - sourceFile, - `{path: '${ - names(options.fileName).fileName - }', loadChildren: () => import('${options.importPath}').then(m => m.${ - options.standalone - ? `${names(options.name).className.toUpperCase()}_ROUTES` - : options.moduleName - })}` - ); + const route = `{path: '${ + names(options.fileName).fileName + }', loadChildren: () => import('${options.importPath}').then(m => m.${ + options.standalone + ? `${names(options.name).className.toUpperCase()}_ROUTES` + : options.moduleName + })}`; + + if (moduleSource.includes('@NgModule')) { + addRoute(tree, options.parentModule, sourceFile, route); + } else { + addStandaloneRoute(tree, options.parentModule, route); + } } diff --git a/packages/angular/src/generators/library/library.spec.ts b/packages/angular/src/generators/library/library.spec.ts index 875b2f1de9..ab02658e9d 100644 --- a/packages/angular/src/generators/library/library.spec.ts +++ b/packages/angular/src/generators/library/library.spec.ts @@ -1545,5 +1545,135 @@ describe('lib', () => { tree.read('apps/app1/src/app/app.module.ts', 'utf-8') ).toMatchSnapshot(); }); + + it('should generate a library with a standalone component as entry point with routing setup and attach it to standalone parent module as direct child', async () => { + // ARRANGE + await applicationGenerator(tree, { + name: 'app1', + routing: true, + standalone: true, + }); + + // ACT + await runLibraryGeneratorWithOpts({ + standalone: true, + routing: true, + parentModule: 'apps/app1/src/main.ts', + }); + + // ASSERT + expect(tree.read('apps/app1/src/main.ts', 'utf-8')) + .toMatchInlineSnapshot(` + "import { enableProdMode, importProvidersFrom } from '@angular/core'; + import { bootstrapApplication } from '@angular/platform-browser'; + import { RouterModule } from '@angular/router'; + import { AppComponent } from './app/app.component'; + import { environment } from './environments/environment'; + import { MYLIB_ROUTES } from '@proj/my-lib'; + + if (environment.production) { + enableProdMode(); + } + + bootstrapApplication(AppComponent, { + providers: [importProvidersFrom(RouterModule.forRoot([ + { path: 'my-lib', children: MYLIB_ROUTES },], {initialNavigation: 'enabledBlocking'}))], + }).catch((err) => console.error(err))" + `); + }); + + it('should generate a library with a standalone component as entry point with routing setup and attach it to standalone parent module as a lazy child', async () => { + // ARRANGE + await applicationGenerator(tree, { + name: 'app1', + routing: true, + standalone: true, + }); + + // ACT + await runLibraryGeneratorWithOpts({ + standalone: true, + routing: true, + lazy: true, + parentModule: 'apps/app1/src/main.ts', + }); + + // ASSERT + expect(tree.read('apps/app1/src/main.ts', 'utf-8')) + .toMatchInlineSnapshot(` + "import { enableProdMode, importProvidersFrom } from '@angular/core'; + import { bootstrapApplication } from '@angular/platform-browser'; + import { RouterModule } from '@angular/router'; + import { AppComponent } from './app/app.component'; + import { environment } from './environments/environment'; + + if (environment.production) { + enableProdMode(); + } + + bootstrapApplication(AppComponent, { + providers: [importProvidersFrom(RouterModule.forRoot([ + {path: 'my-lib', loadChildren: () => import('@proj/my-lib').then(m => m.MYLIB_ROUTES)},], {initialNavigation: 'enabledBlocking'}))], + }).catch((err) => console.error(err))" + `); + }); + + it('should generate a library with a standalone component as entry point with routing setup and attach it to standalone parent routes as direct child', async () => { + // ARRANGE + await runLibraryGeneratorWithOpts({ + standalone: true, + routing: true, + }); + + // ACT + await runLibraryGeneratorWithOpts({ + name: 'second', + standalone: true, + routing: true, + parentModule: 'libs/my-lib/src/lib/routes.ts', + }); + + // ASSERT + expect(tree.read('libs/my-lib/src/lib/routes.ts', 'utf-8')) + .toMatchInlineSnapshot(` + "import { Route } from '@angular/router'; + import { MyLibComponent } from './my-lib/my-lib.component'; + import { SECOND_ROUTES } from '@proj/second'; + + export const MYLIB_ROUTES: Route[] = [ + { path: 'second', children: SECOND_ROUTES }, + {path: '', component: MyLibComponent} + ]" + `); + }); + + it('should generate a library with a standalone component as entry point with routing setup and attach it to standalone parent routes as a lazy child', async () => { + // ARRANGE + await runLibraryGeneratorWithOpts({ + standalone: true, + routing: true, + }); + + // ACT + await runLibraryGeneratorWithOpts({ + name: 'second', + standalone: true, + routing: true, + lazy: true, + parentModule: 'libs/my-lib/src/lib/routes.ts', + }); + + // ASSERT + expect(tree.read('libs/my-lib/src/lib/routes.ts', 'utf-8')) + .toMatchInlineSnapshot(` + "import { Route } from '@angular/router'; + import { MyLibComponent } from './my-lib/my-lib.component'; + + export const MYLIB_ROUTES: Route[] = [ + {path: 'second', loadChildren: () => import('@proj/second').then(m => m.SECOND_ROUTES)}, + {path: '', component: MyLibComponent} + ]" + `); + }); }); }); diff --git a/packages/angular/src/generators/library/schema.json b/packages/angular/src/generators/library/schema.json index 8f701303ee..76416ebd02 100644 --- a/packages/angular/src/generators/library/schema.json +++ b/packages/angular/src/generators/library/schema.json @@ -78,7 +78,8 @@ }, "parentModule": { "type": "string", - "description": "Update the router configuration of the parent module using `loadChildren` or `children`, depending on what `lazy` is set to." + "description": "Update the router configuration of the parent module using `loadChildren` or `children`, depending on what `lazy` is set to.", + "alias": "parent" }, "tags": { "type": "string",