feat(angular): support angular 19.2.0 (#30088)

Add support for Angular 19.2.0.

## Current Behavior

## Expected Behavior

## Related Issue(s)

Fixes #
This commit is contained in:
Leosvel Pérez Espinosa 2025-02-27 14:55:45 +01:00 committed by GitHub
parent 6d40b6a6ca
commit 811bac5cf7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 2555 additions and 843 deletions

View File

@ -435,6 +435,26 @@
}
},
"migrations": {
"/nx-api/angular/migrations/update-angular-cli-version-19-2-0": {
"description": "Update the @angular/cli package version to ~19.2.0.",
"file": "generated/packages/angular/migrations/update-angular-cli-version-19-2-0.json",
"hidden": false,
"name": "update-angular-cli-version-19-2-0",
"version": "20.5.0-beta.5",
"originalFilePath": "/packages/angular",
"path": "/nx-api/angular/migrations/update-angular-cli-version-19-2-0",
"type": "migration"
},
"/nx-api/angular/migrations/20.5.0-package-updates": {
"description": "",
"file": "generated/packages/angular/migrations/20.5.0-package-updates.json",
"hidden": false,
"name": "20.5.0-package-updates",
"version": "20.5.0-beta.5",
"originalFilePath": "/packages/angular",
"path": "/nx-api/angular/migrations/20.5.0-package-updates",
"type": "migration"
},
"/nx-api/angular/migrations/update-angular-cli-version-19-1-0": {
"description": "Update the @angular/cli package version to ~19.1.0.",
"file": "generated/packages/angular/migrations/update-angular-cli-version-19-1-0.json",

View File

@ -430,6 +430,26 @@
}
],
"migrations": [
{
"description": "Update the @angular/cli package version to ~19.2.0.",
"file": "generated/packages/angular/migrations/update-angular-cli-version-19-2-0.json",
"hidden": false,
"name": "update-angular-cli-version-19-2-0",
"version": "20.5.0-beta.5",
"originalFilePath": "/packages/angular",
"path": "angular/migrations/update-angular-cli-version-19-2-0",
"type": "migration"
},
{
"description": "",
"file": "generated/packages/angular/migrations/20.5.0-package-updates.json",
"hidden": false,
"name": "20.5.0-package-updates",
"version": "20.5.0-beta.5",
"originalFilePath": "/packages/angular",
"path": "angular/migrations/20.5.0-package-updates",
"type": "migration"
},
{
"description": "Update the @angular/cli package version to ~19.1.0.",
"file": "generated/packages/angular/migrations/update-angular-cli-version-19-1-0.json",

View File

@ -14,6 +14,7 @@ We provide a recommended version, and it is usually the latest minor version of
| Angular Version | **Nx Version _(recommended)_** | Nx Version _(range)_ |
| --------------- | ------------------------------ | ---------------------------------------- |
| ~19.2.0 | **latest** | >=20.5.0 <=latest |
| ~19.1.0 | **latest** | >=20.4.0 <=latest |
| ~19.0.0 | **latest** | >=20.2.0 <=latest |
| ~18.2.0 | **latest** | >=19.6.0 <=latest |

View File

@ -74,11 +74,11 @@
},
"publicHost": {
"type": "string",
"description": "The URL that the browser client (or live-reload client, if enabled) should use to connect to the development server. Use for a complex dev server setup, such as one with reverse proxies."
"description": "The URL that the browser client (or live-reload client, if enabled) should use to connect to the development server. Use for a complex dev server setup, such as one with reverse proxies. This option has no effect when using the 'application' or other esbuild-based builders."
},
"allowedHosts": {
"type": "array",
"description": "List of hosts that are allowed to access the dev server.",
"description": "List of hosts that are allowed to access the dev server. This option has no effect when using the 'application' or other esbuild-based builders in Angular versions lower than 19.2.0.",
"default": [],
"items": { "type": "string" }
},
@ -88,7 +88,7 @@
},
"disableHostCheck": {
"type": "boolean",
"description": "Don't verify connected clients are part of allowed hosts.",
"description": "Don't verify connected clients are part of allowed hosts. This option has no effect when using the 'application' or other esbuild-based builders in Angular versions lower than 19.2.0.",
"default": false
},
"hmr": {

View File

@ -0,0 +1,49 @@
{
"name": "20.5.0-package-updates",
"version": "20.5.0-beta.5",
"x-prompt": "Do you want to update the Angular version to v19.2?",
"requires": { "@angular/core": ">=19.2.0 <20.0.0-next.0" },
"packages": {
"@angular-devkit/build-angular": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
},
"@angular-devkit/core": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
},
"@angular-devkit/schematics": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
},
"@angular/build": { "version": "~19.2.0", "alwaysAddToPackageJson": false },
"@angular/pwa": { "version": "~19.2.0", "alwaysAddToPackageJson": false },
"@angular/ssr": { "version": "~19.2.0", "alwaysAddToPackageJson": false },
"@schematics/angular": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
},
"@angular-devkit/architect": {
"version": "~0.1902.0",
"alwaysAddToPackageJson": false
},
"@angular-devkit/build-webpack": {
"version": "~0.1902.0",
"alwaysAddToPackageJson": false
},
"@angular/core": { "version": "~19.2.0", "alwaysAddToPackageJson": true },
"@angular/material": {
"version": "~19.2.1",
"alwaysAddToPackageJson": false
},
"@angular/cdk": { "version": "~19.2.1", "alwaysAddToPackageJson": false },
"ng-packagr": { "version": "~19.2.0", "alwaysAddToPackageJson": false }
},
"aliases": [],
"description": "",
"hidden": false,
"implementation": "",
"path": "/packages/angular",
"schema": null,
"type": "migration"
}

View File

@ -0,0 +1,15 @@
{
"name": "update-angular-cli-version-19-2-0",
"cli": "nx",
"version": "20.5.0-beta.5",
"requires": { "@angular/core": ">=19.2.0" },
"description": "Update the @angular/cli package version to ~19.2.0.",
"factory": "./src/migrations/update-20-5-0/update-angular-cli",
"implementation": "/packages/angular/src/migrations/update-20-5-0/update-angular-cli.ts",
"aliases": [],
"hidden": false,
"path": "/packages/angular",
"schema": null,
"type": "migration",
"examplesFile": "#### Sample Code Changes\n\nUpdate the `@angular/cli` package version in the `package.json` file at the workspace root to **~19.2.0**.\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```json {% fileName=\"package.json\" %}\n{\n \"devDependencies\": {\n \"@angular/cli\": \"~19.1.0\"\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"After\" %}\n\n```json {% highlightLines=[3] fileName=\"package.json\" %}\n{\n \"devDependencies\": {\n \"@angular/cli\": \"~19.2.0\"\n }\n}\n```\n\n{% /tab %}\n\n{% /tabs %}\n"
}

View File

@ -14,6 +14,7 @@ We provide a recommended version, and it is usually the latest minor version of
| Angular Version | **Nx Version _(recommended)_** | Nx Version _(range)_ |
| --------------- | ------------------------------ | ---------------------------------------- |
| ~19.2.0 | **latest** | >=20.5.0 <=latest |
| ~19.1.0 | **latest** | >=20.4.0 <=latest |
| ~19.0.0 | **latest** | >=20.2.0 <=latest |
| ~18.2.0 | **latest** | >=19.6.0 <=latest |

View File

@ -27,19 +27,19 @@
},
"devDependencies": {
"@actions/core": "^1.10.0",
"@angular-devkit/architect": "~0.1901.0",
"@angular-devkit/build-angular": "~19.1.0",
"@angular-devkit/core": "~19.1.0",
"@angular-devkit/schematics": "~19.1.0",
"@angular-devkit/architect": "~0.1902.0",
"@angular-devkit/build-angular": "~19.2.0",
"@angular-devkit/core": "~19.2.0",
"@angular-devkit/schematics": "~19.2.0",
"@angular-eslint/eslint-plugin": "19.0.2",
"@angular-eslint/eslint-plugin-template": "19.0.2",
"@angular-eslint/template-parser": "19.0.2",
"@angular/cli": "~19.1.0",
"@angular/common": "~19.1.0",
"@angular/compiler": "~19.1.0",
"@angular/compiler-cli": "~19.1.0",
"@angular/core": "~19.1.0",
"@angular/router": "~19.1.0",
"@angular/cli": "~19.2.0",
"@angular/common": "~19.2.0",
"@angular/compiler": "~19.2.0",
"@angular/compiler-cli": "~19.2.0",
"@angular/core": "~19.2.0",
"@angular/router": "~19.2.0",
"@babel/core": "^7.23.2",
"@babel/helper-create-regexp-features-plugin": "^7.22.9",
"@babel/plugin-transform-runtime": "^7.23.2",
@ -108,7 +108,7 @@
"@rspack/dev-server": "1.0.9",
"@rspack/plugin-minify": "^0.7.5",
"@rspack/plugin-react-refresh": "^1.0.0",
"@schematics/angular": "~19.1.0",
"@schematics/angular": "~19.2.0",
"@storybook/addon-essentials": "8.4.6",
"@storybook/addon-interactions": "8.4.6",
"@storybook/core-server": "8.4.6",
@ -250,7 +250,7 @@
"mini-css-extract-plugin": "~2.4.7",
"minimatch": "9.0.3",
"next-sitemap": "^3.1.10",
"ng-packagr": "~19.1.0",
"ng-packagr": "~19.2.0",
"npm-package-arg": "11.0.1",
"nuxt": "^3.10.0",
"nx": "20.5.0-beta.2",

View File

@ -347,6 +347,15 @@
},
"description": "Update the @angular/cli package version to ~19.1.0.",
"factory": "./src/migrations/update-20-4-0/update-angular-cli"
},
"update-angular-cli-version-19-2-0": {
"cli": "nx",
"version": "20.5.0-beta.5",
"requires": {
"@angular/core": ">=19.2.0"
},
"description": "Update the @angular/cli package version to ~19.2.0.",
"factory": "./src/migrations/update-20-5-0/update-angular-cli"
}
},
"packageJsonUpdates": {
@ -1533,6 +1542,67 @@
"alwaysAddToPackageJson": false
}
}
},
"20.5.0": {
"version": "20.5.0-beta.5",
"x-prompt": "Do you want to update the Angular version to v19.2?",
"requires": {
"@angular/core": ">=19.2.0 <20.0.0-next.0"
},
"packages": {
"@angular-devkit/build-angular": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
},
"@angular-devkit/core": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
},
"@angular-devkit/schematics": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
},
"@angular/build": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
},
"@angular/pwa": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
},
"@angular/ssr": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
},
"@schematics/angular": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
},
"@angular-devkit/architect": {
"version": "~0.1902.0",
"alwaysAddToPackageJson": false
},
"@angular-devkit/build-webpack": {
"version": "~0.1902.0",
"alwaysAddToPackageJson": false
},
"@angular/core": {
"version": "~19.2.0",
"alwaysAddToPackageJson": true
},
"@angular/material": {
"version": "~19.2.1",
"alwaysAddToPackageJson": false
},
"@angular/cdk": {
"version": "~19.2.1",
"alwaysAddToPackageJson": false
},
"ng-packagr": {
"version": "~19.2.0",
"alwaysAddToPackageJson": false
}
}
}
}
}

View File

@ -78,11 +78,11 @@
},
"publicHost": {
"type": "string",
"description": "The URL that the browser client (or live-reload client, if enabled) should use to connect to the development server. Use for a complex dev server setup, such as one with reverse proxies."
"description": "The URL that the browser client (or live-reload client, if enabled) should use to connect to the development server. Use for a complex dev server setup, such as one with reverse proxies. This option has no effect when using the 'application' or other esbuild-based builders."
},
"allowedHosts": {
"type": "array",
"description": "List of hosts that are allowed to access the dev server.",
"description": "List of hosts that are allowed to access the dev server. This option has no effect when using the 'application' or other esbuild-based builders in Angular versions lower than 19.2.0.",
"default": [],
"items": {
"type": "string"
@ -94,7 +94,7 @@
},
"disableHostCheck": {
"type": "boolean",
"description": "Don't verify connected clients are part of allowed hosts.",
"description": "Don't verify connected clients are part of allowed hosts. This option has no effect when using the 'application' or other esbuild-based builders in Angular versions lower than 19.2.0.",
"default": false
},
"hmr": {

View File

@ -61,7 +61,6 @@ describe('app', () => {
// ASSERT
const { dependencies, devDependencies } = readJson(appTree, 'package.json');
expect(dependencies['@angular/animations']).toBe(angularVersion);
expect(dependencies['@angular/common']).toBe(angularVersion);
expect(dependencies['@angular/compiler']).toBe(angularVersion);
expect(dependencies['@angular/core']).toBe(angularVersion);

View File

@ -76,7 +76,6 @@ describe('lib', () => {
// ASSERT
const { dependencies, devDependencies } = readJson(tree, 'package.json');
expect(dependencies['@angular/animations']).toBe(angularVersion);
expect(dependencies['@angular/common']).toBe(angularVersion);
expect(dependencies['@angular/compiler']).toBe(angularVersion);
expect(dependencies['@angular/core']).toBe(angularVersion);

View File

@ -122,6 +122,8 @@ if (isMainModule(import.meta.url)) {
console.log(\`Node Express server listening on http://localhost:\${port}\`);
});
}
export default app;
"
`;
@ -247,6 +249,8 @@ if (isMainModule(import.meta.url)) {
console.log(\`Node Express server listening on http://localhost:\${port}\`);
});
}
export default app;
"
`;

View File

@ -63,3 +63,5 @@ if (isMainModule(import.meta.url)) {
console.log(`Node Express server listening on http://localhost:${port}`);
});
}
export default app;

View File

@ -1,13 +1,13 @@
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';<% if(serverRouting) { %>
import { provideServerRoutesConfig } from '@angular/ssr';<% } %>
import { <%= provideServerRoutingFn %> } from '@angular/ssr';<% } %>
import { AppComponent } from './app.component';
import { AppModule } from './app.module';<% if(serverRouting) { %>
import { serverRoutes } from './app.routes.server';<% } %>
@NgModule({
imports: [AppModule, ServerModule],<% if(serverRouting) { %>
providers: [provideServerRoutesConfig(serverRoutes)],<% } %>
providers: [<%= provideServerRoutingFn %>(serverRoutes)],<% } %>
bootstrap: [AppComponent],
})
export class <%= rootModuleClassName %> {}

View File

@ -61,6 +61,6 @@ if (isMainModule(import.meta.url)) {
}
/**
* The request handler used by the Angular CLI (dev-server and during build).
* Request handler used by the Angular CLI (for dev-server and during build) or Firebase Cloud Functions.
*/
export const reqHandler = createNodeRequestHandler(app);

View File

@ -1,13 +1,13 @@
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';<% if(serverRouting) { %>
import { provideServerRoutesConfig } from '@angular/ssr';<% } %>
import { <%= provideServerRoutingFn %> } from '@angular/ssr';<% } %>
import { appConfig } from './app.config';<% if(serverRouting) { %>
import { serverRoutes } from './app.routes.server';<% } %>
const serverConfig: ApplicationConfig = {
providers: [
provideServerRendering()<% if(serverRouting) { %>,
provideServerRoutesConfig(serverRoutes)<% } %>
<%= provideServerRoutingFn %>(serverRoutes)<% } %>
]
};

View File

@ -5,8 +5,12 @@ import {
readProjectConfiguration,
} from '@nx/devkit';
import { join } from 'path';
import { getInstalledAngularVersionInfo } from '../../utils/version-utils';
import {
getInstalledAngularVersionInfo,
getInstalledPackageVersion,
} from '../../utils/version-utils';
import type { NormalizedGeneratorOptions } from '../schema';
import { clean, coerce, gte } from 'semver';
export function generateSSRFiles(
tree: Tree,
@ -46,7 +50,19 @@ export function generateSSRFiles(
const sourceRoot =
project.sourceRoot ?? joinPathFragments(project.root, 'src');
generateFiles(tree, pathToFiles, sourceRoot, { ...options, tpl: '' });
const ssrVersion = getInstalledPackageVersion(tree, '@angular/ssr');
const cleanedSsrVersion = ssrVersion
? clean(ssrVersion) ?? coerce(ssrVersion).version
: null;
generateFiles(tree, pathToFiles, sourceRoot, {
...options,
provideServerRoutingFn:
!cleanedSsrVersion || gte(cleanedSsrVersion, '19.2.0')
? 'provideServerRouting'
: 'provideServerRoutesConfig',
tpl: '',
});
if (angularMajorVersion >= 19 && !options.serverRouting) {
tree.delete(joinPathFragments(sourceRoot, 'app/app.routes.server.ts'));

View File

@ -194,6 +194,86 @@ describe('setupSSR', () => {
server: 'node-server',
});
});
it('should setup server routing for NgModule apps when "serverRouting" is true', async () => {
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
await generateTestApplication(tree, {
directory: 'app1',
standalone: false,
skipFormat: true,
});
await setupSsr(tree, { project: 'app1', serverRouting: true });
expect(tree.read('app1/src/app/app.server.module.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { provideServerRouting } from '@angular/ssr';
import { AppComponent } from './app.component';
import { AppModule } from './app.module';
import { serverRoutes } from './app.routes.server';
@NgModule({
imports: [AppModule, ServerModule],
providers: [provideServerRouting(serverRoutes)],
bootstrap: [AppComponent],
})
export class AppServerModule {}
"
`);
expect(tree.read('app1/src/app/app.routes.server.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
{
path: '**',
renderMode: RenderMode.Prerender,
},
];
"
`);
});
it('should setup server routing for standalone apps when "serverRouting" is true', async () => {
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
await generateTestApplication(tree, {
directory: 'app1',
standalone: true,
skipFormat: true,
});
await setupSsr(tree, { project: 'app1', serverRouting: true });
expect(tree.read('app1/src/app/app.config.server.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';
import { provideServerRouting } from '@angular/ssr';
import { appConfig } from './app.config';
import { serverRoutes } from './app.routes.server';
const serverConfig: ApplicationConfig = {
providers: [provideServerRendering(), provideServerRouting(serverRoutes)],
};
export const config = mergeApplicationConfig(appConfig, serverConfig);
"
`);
expect(tree.read('app1/src/app/app.routes.server.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
{
path: '**',
renderMode: RenderMode.Prerender,
},
];
"
`);
});
});
describe('with browser builder', () => {
@ -707,5 +787,98 @@ describe('setupSSR', () => {
"
`);
});
it('should setup server routing using "provideServerRoutesConfig" for NgModule apps when "serverRouting" is true and @angular/ssr version is lower than 19.2.0', async () => {
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
updateJson(tree, 'package.json', (json) => ({
...json,
dependencies: { '@angular/core': '19.1.0', '@angular/ssr': '19.1.0' },
devDependencies: { '@angular-devkit/build-angular': '19.1.0' },
}));
await generateTestApplication(tree, {
directory: 'app1',
standalone: false,
skipFormat: true,
});
await setupSsr(tree, { project: 'app1', serverRouting: true });
expect(tree.read('app1/src/app/app.server.module.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { provideServerRoutesConfig } from '@angular/ssr';
import { AppComponent } from './app.component';
import { AppModule } from './app.module';
import { serverRoutes } from './app.routes.server';
@NgModule({
imports: [AppModule, ServerModule],
providers: [provideServerRoutesConfig(serverRoutes)],
bootstrap: [AppComponent],
})
export class AppServerModule {}
"
`);
expect(tree.read('app1/src/app/app.routes.server.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
{
path: '**',
renderMode: RenderMode.Prerender,
},
];
"
`);
});
it('should setup server routing using "provideServerRoutesConfig" for standalone apps when "serverRouting" is true and @angular/ssr version is lower than 19.2.0', async () => {
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
updateJson(tree, 'package.json', (json) => ({
...json,
dependencies: { '@angular/core': '19.1.0', '@angular/ssr': '19.1.0' },
devDependencies: { '@angular-devkit/build-angular': '19.1.0' },
}));
await generateTestApplication(tree, {
directory: 'app1',
standalone: true,
skipFormat: true,
});
await setupSsr(tree, { project: 'app1', serverRouting: true });
expect(tree.read('app1/src/app/app.config.server.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';
import { provideServerRoutesConfig } from '@angular/ssr';
import { appConfig } from './app.config';
import { serverRoutes } from './app.routes.server';
const serverConfig: ApplicationConfig = {
providers: [
provideServerRendering(),
provideServerRoutesConfig(serverRoutes),
],
};
export const config = mergeApplicationConfig(appConfig, serverConfig);
"
`);
expect(tree.read('app1/src/app/app.routes.server.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
{
path: '**',
renderMode: RenderMode.Prerender,
},
];
"
`);
});
});
});

View File

@ -17,7 +17,6 @@ describe('ensureAngularDependencies', () => {
// ASSERT
const { dependencies, devDependencies } = readJson(tree, 'package.json');
expect(dependencies['@angular/animations']).toBe(angularVersion);
expect(dependencies['@angular/common']).toBe(angularVersion);
expect(dependencies['@angular/compiler']).toBe(angularVersion);
expect(dependencies['@angular/core']).toBe(angularVersion);
@ -108,7 +107,6 @@ describe('ensureAngularDependencies', () => {
const { dependencies, devDependencies } = readJson(tree, 'package.json');
expect(dependencies['@angular/core']).toBe('~15.0.0');
expect(dependencies['@angular/animations']).toBeUndefined();
expect(dependencies['@angular/common']).toBeUndefined();
expect(dependencies['@angular/compiler']).toBeUndefined();
expect(dependencies['@angular/platform-browser']).toBeUndefined();

View File

@ -29,7 +29,6 @@ export function ensureAngularDependencies(tree: Tree): GeneratorCallback {
const zoneJsVersion =
getInstalledPackageVersion(tree, 'zone.js') ?? pkgVersions.zoneJsVersion;
dependencies['@angular/animations'] = angularVersion;
dependencies['@angular/common'] = angularVersion;
dependencies['@angular/compiler'] = angularVersion;
dependencies['@angular/core'] = angularVersion;

View File

@ -0,0 +1,29 @@
#### Sample Code Changes
Update the `@angular/cli` package version in the `package.json` file at the workspace root to **~19.2.0**.
{% tabs %}
{% tab label="Before" %}
```json {% fileName="package.json" %}
{
"devDependencies": {
"@angular/cli": "~19.1.0"
}
}
```
{% /tab %}
{% tab label="After" %}
```json {% highlightLines=[3] fileName="package.json" %}
{
"devDependencies": {
"@angular/cli": "~19.2.0"
}
}
```
{% /tab %}
{% /tabs %}

View File

@ -0,0 +1,42 @@
import { readJson, Tree, writeJson } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import updateAngularCli, { angularCliVersion } from './update-angular-cli';
describe('update-angular-cli migration', () => {
let tree: Tree;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
});
it('should update @angular/cli version when defined as a dev dependency', async () => {
writeJson(tree, 'package.json', {
devDependencies: { '@angular/cli': '~13.3.0' },
});
await updateAngularCli(tree);
const { devDependencies } = readJson(tree, 'package.json');
expect(devDependencies['@angular/cli']).toBe(angularCliVersion);
});
it('should update @angular/cli version when defined as a dependency', async () => {
writeJson(tree, 'package.json', {
dependencies: { '@angular/cli': '~13.3.0' },
});
await updateAngularCli(tree);
const { dependencies } = readJson(tree, 'package.json');
expect(dependencies['@angular/cli']).toBe(angularCliVersion);
});
it('should not add @angular/cli to package.json when it is not set', async () => {
const initialPackageJson = readJson(tree, 'package.json');
await updateAngularCli(tree);
const packageJson = readJson(tree, 'package.json');
expect(packageJson).toStrictEqual(initialPackageJson);
});
});

View File

@ -0,0 +1,23 @@
import { formatFiles, Tree, updateJson } from '@nx/devkit';
export const angularCliVersion = '~19.2.0';
export default async function (tree: Tree) {
let shouldFormat = false;
updateJson(tree, 'package.json', (json) => {
if (json.devDependencies?.['@angular/cli']) {
json.devDependencies['@angular/cli'] = angularCliVersion;
shouldFormat = true;
} else if (json.dependencies?.['@angular/cli']) {
json.dependencies['@angular/cli'] = angularCliVersion;
shouldFormat = true;
}
return json;
});
if (shouldFormat) {
await formatFiles(tree);
}
}

View File

@ -1,8 +1,8 @@
export const nxVersion = require('../../package.json').version;
export const angularVersion = '~19.1.0';
export const angularDevkitVersion = '~19.1.0';
export const ngPackagrVersion = '~19.1.0';
export const angularVersion = '~19.2.0';
export const angularDevkitVersion = '~19.2.0';
export const ngPackagrVersion = '~19.2.0';
export const ngrxVersion = '^19.0.0';
export const rxjsVersion = '~7.8.0';
export const zoneJsVersion = '~0.15.0';

View File

@ -4,4 +4,4 @@ export const typescriptVersion = '~5.7.2';
// TODO: remove when preset generation is reworked and
// deps are not installed from workspace
export const angularCliVersion = '~19.1.0';
export const angularCliVersion = '~19.2.0';

2870
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff