diff --git a/packages/angular/src/generators/add-linting/add-linting.ts b/packages/angular/src/generators/add-linting/add-linting.ts index a398e8a1c9ff5..e806a28811814 100755 --- a/packages/angular/src/generators/add-linting/add-linting.ts +++ b/packages/angular/src/generators/add-linting/add-linting.ts @@ -8,7 +8,7 @@ import { Linter, lintProjectGenerator } from '@nrwl/linter'; import { mapLintPattern } from '@nrwl/linter/src/generators/lint-project/lint-project'; import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial'; import { join } from 'path'; -import { getGeneratorDirectoryForInstalledAngularVersion } from '../utils/angular-version-utils'; +import { getGeneratorDirectoryForInstalledAngularVersion } from '../utils/version-utils'; import { addAngularEsLintDependencies } from './lib/add-angular-eslint-dependencies'; import { extendAngularEslintJson } from './lib/create-eslint-configuration'; import type { AddLintingGeneratorSchema } from './schema'; diff --git a/packages/angular/src/generators/application/application.ts b/packages/angular/src/generators/application/application.ts index 86439d18d9c97..da22f49fdf926 100644 --- a/packages/angular/src/generators/application/application.ts +++ b/packages/angular/src/generators/application/application.ts @@ -16,7 +16,7 @@ import { setupTailwindGenerator } from '../setup-tailwind/setup-tailwind'; import { getGeneratorDirectoryForInstalledAngularVersion, getInstalledAngularVersionInfo, -} from '../utils/angular-version-utils'; +} from '../utils/version-utils'; import { addE2e, addLinting, diff --git a/packages/angular/src/generators/component/component.ts b/packages/angular/src/generators/component/component.ts index 514f9e26568d1..f3c6a1bacd341 100644 --- a/packages/angular/src/generators/component/component.ts +++ b/packages/angular/src/generators/component/component.ts @@ -11,7 +11,7 @@ import { pathStartsWith } from '../utils/path'; import { exportComponentInEntryPoint } from './lib/component'; import { normalizeOptions } from './lib/normalize-options'; import type { NormalizedSchema, Schema } from './schema'; -import { getInstalledAngularVersionInfo } from '../utils/angular-version-utils'; +import { getInstalledAngularVersionInfo } from '../utils/version-utils'; import { lt } from 'semver'; export async function componentGenerator(tree: Tree, rawOptions: Schema) { diff --git a/packages/angular/src/generators/host/host.ts b/packages/angular/src/generators/host/host.ts index d2ca3edfa87b2..4de32f3f3414c 100644 --- a/packages/angular/src/generators/host/host.ts +++ b/packages/angular/src/generators/host/host.ts @@ -7,7 +7,7 @@ import { setupMf } from '../setup-mf/setup-mf'; import { E2eTestRunner } from '../../utils/test-runners'; import { addSsr } from './lib'; import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial'; -import { getInstalledAngularVersionInfo } from '../utils/angular-version-utils'; +import { getInstalledAngularVersionInfo } from '../utils/version-utils'; import { lt } from 'semver'; export async function host(tree: Tree, options: Schema) { diff --git a/packages/angular/src/generators/init/init.ts b/packages/angular/src/generators/init/init.ts index 929a7f326d900..215a8b4f14713 100755 --- a/packages/angular/src/generators/init/init.ts +++ b/packages/angular/src/generators/init/init.ts @@ -28,7 +28,7 @@ import { zoneJsVersion, } from '../../utils/versions'; import { karmaGenerator } from '../karma/karma'; -import { getGeneratorDirectoryForInstalledAngularVersion } from '../utils/angular-version-utils'; +import { getGeneratorDirectoryForInstalledAngularVersion } from '../utils/version-utils'; import { Schema } from './schema'; export async function angularInitGenerator( diff --git a/packages/angular/src/generators/karma/karma.ts b/packages/angular/src/generators/karma/karma.ts index 372644fd2e5a0..ed963c87dcc11 100644 --- a/packages/angular/src/generators/karma/karma.ts +++ b/packages/angular/src/generators/karma/karma.ts @@ -19,7 +19,7 @@ import { typesJasmineVersion, typesNodeVersion, } from '../../utils/versions'; -import { getGeneratorDirectoryForInstalledAngularVersion } from '../utils/angular-version-utils'; +import { getGeneratorDirectoryForInstalledAngularVersion } from '../utils/version-utils'; import { GeneratorOptions } from './schema'; function addTestInputs(tree: Tree) { diff --git a/packages/angular/src/generators/library/library.ts b/packages/angular/src/generators/library/library.ts index f9dddbae7efad..5e674c182de0e 100644 --- a/packages/angular/src/generators/library/library.ts +++ b/packages/angular/src/generators/library/library.ts @@ -17,7 +17,7 @@ import { getPkgVersionForAngularMajorVersion } from '../../utils/version-utils'; import addLintingGenerator from '../add-linting/add-linting'; import karmaProjectGenerator from '../karma-project/karma-project'; import setupTailwindGenerator from '../setup-tailwind/setup-tailwind'; -import { getInstalledAngularVersionInfo } from '../utils/angular-version-utils'; +import { getInstalledAngularVersionInfo } from '../utils/version-utils'; import { addBuildableLibrariesPostCssDependencies } from '../utils/dependencies'; import { addModule } from './lib/add-module'; import { addStandaloneComponent } from './lib/add-standalone-component'; diff --git a/packages/angular/src/generators/ngrx/lib/add-ngrx-to-package-json.ts b/packages/angular/src/generators/ngrx/lib/add-ngrx-to-package-json.ts index 51b910e6a5e95..aef3d2e2a3676 100644 --- a/packages/angular/src/generators/ngrx/lib/add-ngrx-to-package-json.ts +++ b/packages/angular/src/generators/ngrx/lib/add-ngrx-to-package-json.ts @@ -4,7 +4,7 @@ import { checkAndCleanWithSemver } from '@nrwl/workspace/src/utilities/version-u import { gte } from 'semver'; import { getPkgVersionForAngularMajorVersion } from '../../../utils/version-utils'; import { rxjsVersion as defaultRxjsVersion } from '../../../utils/versions'; -import { getInstalledAngularMajorVersion } from '../../utils/angular-version-utils'; +import { getInstalledAngularMajorVersion } from '../../utils/version-utils'; export function addNgRxToPackageJson(tree: Tree): GeneratorCallback { let rxjsVersion: string; diff --git a/packages/angular/src/generators/ngrx/lib/generate-files.ts b/packages/angular/src/generators/ngrx/lib/generate-files.ts index f5a6448f830d0..60c5dc0de59ce 100644 --- a/packages/angular/src/generators/ngrx/lib/generate-files.ts +++ b/packages/angular/src/generators/ngrx/lib/generate-files.ts @@ -1,7 +1,7 @@ import type { Tree } from '@nrwl/devkit'; import { generateFiles, joinPathFragments, names } from '@nrwl/devkit'; import { lt } from 'semver'; -import { getInstalledAngularVersion } from '../../utils/angular-version-utils'; +import { getInstalledAngularVersion } from '../../utils/version-utils'; import { NormalizedNgRxGeneratorOptions } from './normalize-options'; /** diff --git a/packages/angular/src/generators/ngrx/lib/normalize-options.ts b/packages/angular/src/generators/ngrx/lib/normalize-options.ts index 3b3f0a5a661fd..5470f32169514 100644 --- a/packages/angular/src/generators/ngrx/lib/normalize-options.ts +++ b/packages/angular/src/generators/ngrx/lib/normalize-options.ts @@ -16,7 +16,7 @@ export function normalizeOptions( : options.parent ? dirname(options.parent) : undefined, - route: options.route ?? "''", + route: options.route ?? '', directory: names(options.directory).fileName, }; } diff --git a/packages/angular/src/generators/ngrx/lib/validate-options.ts b/packages/angular/src/generators/ngrx/lib/validate-options.ts index 08ad22abc981a..dc1f3fdc2b6c8 100644 --- a/packages/angular/src/generators/ngrx/lib/validate-options.ts +++ b/packages/angular/src/generators/ngrx/lib/validate-options.ts @@ -1,8 +1,12 @@ import type { Tree } from '@nrwl/devkit'; import { tsquery } from '@phenomnomnominal/tsquery'; -import { lt } from 'semver'; -import { getInstalledAngularVersion } from '../../utils/angular-version-utils'; +import { coerce, lt, major } from 'semver'; +import { + getInstalledAngularVersionInfo, + getInstalledPackageVersionInfo, +} from '../../utils/version-utils'; import type { NgRxGeneratorOptions } from '../schema'; +import { getPkgVersionForAngularMajorVersion } from '../../../utils/version-utils'; export function validateOptions( tree: Tree, @@ -18,9 +22,19 @@ export function validateOptions( throw new Error(`Parent does not exist: ${options.parent}.`); } - const angularVersion = getInstalledAngularVersion(tree); - const parentPath = options.parent ?? options.module; - if (parentPath && lt(angularVersion, '14.1.0')) { + const angularVersionInfo = getInstalledAngularVersionInfo(tree); + const intendedNgRxVersionForAngularMajor = + getPkgVersionForAngularMajorVersion( + 'ngrxVersion', + angularVersionInfo.major + ); + + const ngrxMajorVersion = + getInstalledPackageVersionInfo(tree, '@ngrx/store')?.major ?? + major(coerce(intendedNgRxVersionForAngularMajor)); + + if (lt(angularVersionInfo.version, '14.1.0') || ngrxMajorVersion < 15) { + const parentPath = options.parent ?? options.module; const parentContent = tree.read(parentPath, 'utf-8'); const ast = tsquery.ast(parentContent); diff --git a/packages/angular/src/generators/ngrx/ngrx.spec.ts b/packages/angular/src/generators/ngrx/ngrx.spec.ts index f17614ac4385f..aaf41eacf7bb1 100644 --- a/packages/angular/src/generators/ngrx/ngrx.spec.ts +++ b/packages/angular/src/generators/ngrx/ngrx.spec.ts @@ -680,6 +680,63 @@ describe('ngrx', () => { ).toMatchSnapshot(); }); + it('should throw when Angular version < 14.1 and NgRx < 15 but path to routes file is provided', async () => { + const parentPath = 'apps/myapp/src/app/app.routes.ts'; + tree.write( + parentPath, + `import { Routes } from '@angular/router'; + import { NxWelcomeComponent } from './nx-welcome.component'; + export const appRoutes: Routes = [{ path: '', component: NxWelcomeComponent }];` + ); + + devkit.updateJson(tree, 'package.json', (json) => ({ + ...json, + dependencies: { + ...json.dependencies, + '@angular/core': '14.1.0', + '@ngrx/store': '14.1.0', + }, + })); + + // ACT & ASSERT + await expect( + ngrxGenerator(tree, { + ...defaultStandaloneOptions, + parent: parentPath, + }) + ).rejects.toThrowError( + `The provided parent path "${parentPath}" does not contain an "NgModule".` + ); + }); + + it('should throw when Angular version < 15 and NgRx is not currently installed but path to routes file is provided', async () => { + const parentPath = 'apps/myapp/src/app/app.routes.ts'; + tree.write( + parentPath, + `import { Routes } from '@angular/router'; + import { NxWelcomeComponent } from './nx-welcome.component'; + export const appRoutes: Routes = [{ path: '', component: NxWelcomeComponent }];` + ); + + devkit.updateJson(tree, 'package.json', (json) => ({ + ...json, + dependencies: { + ...json.dependencies, + '@angular/core': '14.2.0', + }, + })); + + // ACT & ASSERT + await expect( + ngrxGenerator(tree, { + ...defaultStandaloneOptions, + parent: parentPath, + }) + ).rejects.toThrowError( + `The provided parent path "${parentPath}" does not contain an "NgModule".` + ); + }); + it('should throw when the provided parent does not have an NgModule', async () => { const parentPath = 'apps/myapp/src/app/app.routes.ts'; tree.write( diff --git a/packages/angular/src/generators/remote/remote.ts b/packages/angular/src/generators/remote/remote.ts index 109508e22f148..e9eb917548d7c 100644 --- a/packages/angular/src/generators/remote/remote.ts +++ b/packages/angular/src/generators/remote/remote.ts @@ -6,7 +6,7 @@ import { setupMf } from '../setup-mf/setup-mf'; import { E2eTestRunner } from '../../utils/test-runners'; import { addSsr, findNextAvailablePort } from './lib'; import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial'; -import { getInstalledAngularVersionInfo } from '../utils/angular-version-utils'; +import { getInstalledAngularVersionInfo } from '../utils/version-utils'; import { lt } from 'semver'; export async function remote(tree: Tree, options: Schema) { diff --git a/packages/angular/src/generators/scam-to-standalone/scam-to-standalone.ts b/packages/angular/src/generators/scam-to-standalone/scam-to-standalone.ts index 4032514827bc5..2ad13d40661be 100644 --- a/packages/angular/src/generators/scam-to-standalone/scam-to-standalone.ts +++ b/packages/angular/src/generators/scam-to-standalone/scam-to-standalone.ts @@ -15,7 +15,7 @@ import { verifyIsInlineScam, verifyModuleIsScam, } from './lib'; -import { getInstalledAngularVersionInfo } from '../utils/angular-version-utils'; +import { getInstalledAngularVersionInfo } from '../utils/version-utils'; import { lt } from 'semver'; export async function scamToStandalone( diff --git a/packages/angular/src/generators/setup-mf/setup-mf.ts b/packages/angular/src/generators/setup-mf/setup-mf.ts index c97e2acc7351d..96fb80422a4ec 100644 --- a/packages/angular/src/generators/setup-mf/setup-mf.ts +++ b/packages/angular/src/generators/setup-mf/setup-mf.ts @@ -16,7 +16,7 @@ import { updateHostAppRoutes, updateTsConfigTarget, } from './lib'; -import { getInstalledAngularVersionInfo } from '../utils/angular-version-utils'; +import { getInstalledAngularVersionInfo } from '../utils/version-utils'; import { lt } from 'semver'; export async function setupMf(tree: Tree, options: Schema) { diff --git a/packages/angular/src/generators/setup-ssr/setup-ssr.ts b/packages/angular/src/generators/setup-ssr/setup-ssr.ts index a26e76d0fa1f4..27a820acb7130 100644 --- a/packages/angular/src/generators/setup-ssr/setup-ssr.ts +++ b/packages/angular/src/generators/setup-ssr/setup-ssr.ts @@ -5,7 +5,7 @@ import { installPackagesTask, } from '@nrwl/devkit'; import { getPkgVersionsForAngularMajorVersion } from '../../utils/version-utils'; -import { getInstalledAngularVersionInfo } from '../utils/angular-version-utils'; +import { getInstalledAngularVersionInfo } from '../utils/version-utils'; import { generateSSRFiles, normalizeOptions, diff --git a/packages/angular/src/generators/utils/create-ts-config.ts b/packages/angular/src/generators/utils/create-ts-config.ts index 5beb2a4eeb08f..7cf55f6593f18 100644 --- a/packages/angular/src/generators/utils/create-ts-config.ts +++ b/packages/angular/src/generators/utils/create-ts-config.ts @@ -1,7 +1,7 @@ import type { Tree } from '@nrwl/devkit'; import { writeJson } from '@nrwl/devkit'; import { tsConfigBaseOptions } from '@nrwl/workspace/src/utils/create-ts-config'; -import { getInstalledAngularMajorVersion } from './angular-version-utils'; +import { getInstalledAngularMajorVersion } from './version-utils'; export { extractTsConfigBase } from '@nrwl/workspace/src/utils/create-ts-config'; diff --git a/packages/angular/src/generators/utils/angular-version-utils.spec.ts b/packages/angular/src/generators/utils/version-utils.spec.ts similarity index 98% rename from packages/angular/src/generators/utils/angular-version-utils.spec.ts rename to packages/angular/src/generators/utils/version-utils.spec.ts index 5b7ae523ca4b5..6d43be89378f3 100644 --- a/packages/angular/src/generators/utils/angular-version-utils.spec.ts +++ b/packages/angular/src/generators/utils/version-utils.spec.ts @@ -4,7 +4,7 @@ import { getGeneratorDirectoryForInstalledAngularVersion, getInstalledAngularMajorVersion, getInstalledAngularVersion, -} from './angular-version-utils'; +} from './version-utils'; describe('angularVersionUtils', () => { test.each(['14.0.0', '~14.1.0', '^14.2.0', '~14.3.0-beta.0'])( diff --git a/packages/angular/src/generators/utils/angular-version-utils.ts b/packages/angular/src/generators/utils/version-utils.ts similarity index 80% rename from packages/angular/src/generators/utils/angular-version-utils.ts rename to packages/angular/src/generators/utils/version-utils.ts index 63e564b4d235b..c8024938dd843 100644 --- a/packages/angular/src/generators/utils/angular-version-utils.ts +++ b/packages/angular/src/generators/utils/version-utils.ts @@ -45,3 +45,15 @@ export function getInstalledAngularVersionInfo(tree: Tree) { major: major(installedVersion), }; } + +export function getInstalledPackageVersionInfo(tree: Tree, pkgName: string) { + try { + const version = + readJson(tree, 'package.json').dependencies?.[pkgName] ?? + readJson(tree, 'package.json').devDependencies?.[pkgName]; + + return { major: major(coerce(version)), version }; + } catch { + return null; + } +} diff --git a/packages/angular/src/utils/nx-devkit/route-utils.ts b/packages/angular/src/utils/nx-devkit/route-utils.ts index abad36e14cd1b..4c17999fbe7b4 100644 --- a/packages/angular/src/utils/nx-devkit/route-utils.ts +++ b/packages/angular/src/utils/nx-devkit/route-utils.ts @@ -109,7 +109,7 @@ export function addProviderToRoute( ); } - const ROUTE_SELECTOR = `ObjectLiteralExpression:has(PropertyAssignment:has(Identifier[name=path]) > StringLiteral[value=${routeToAddProviderTo}]):last-child`; + const ROUTE_SELECTOR = `ObjectLiteralExpression:has(PropertyAssignment:has(Identifier[name=path]) > StringLiteral[value='${routeToAddProviderTo}']):last-child`; const ROUTE_PATH_PROVIDERS_SELECTOR = 'ObjectLiteralExpression > PropertyAssignment:has(Identifier[name=providers])';