Skip to content

Commit fba22bc

Browse files
devversionmmalerba
authored andcommitted
fix(material): ng-add should always install matching CDK version (#18076)
Currently ng-add for Angular Material determines the version name of the CDK and Angular Material by looking for `@angular/cdk/package.json` and `@angular/material/package.json` in the node modules. This is incorrect because other installed packages could rely on older CDK versions being installed. In those cases, we don't want to add that transitively installed CDK version to the `package.json` file. Instead, we always want to add the CDK version that matches Angular Material. We can do this by just relying on the version placeholder we use in other locations too. Also in the issue ticket (#18020) it was mentioned that we might want to warn if a lower CDK version is transitively installed. This seems unnecessary since we explicitly add a project-scoped dependency on the CDK and transitive CDK dependencies are nothing we should bother about. In general, if someone runs `ng add @angular/material` it's _only_ right to always install a working/matching version of the CDK. Fixes #18020
1 parent fad8d24 commit fba22bc

File tree

5 files changed

+24
-35
lines changed

5 files changed

+24
-35
lines changed

src/cdk/schematics/ng-add/index.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ describe('CDK ng-add', () => {
1616
const packageJson = JSON.parse(getFileContent(tree, '/package.json'));
1717
const dependencies = packageJson.dependencies;
1818

19-
expect(dependencies['@angular/cdk']).toBeDefined();
19+
expect(dependencies['@angular/cdk']).toBe('~0.0.0-PLACEHOLDER');
2020
expect(Object.keys(dependencies))
2121
.toEqual(
2222
Object.keys(dependencies).sort(),
2323
'Expected the modified "dependencies" to be sorted alphabetically.');
24+
expect(runner.tasks.some(task => task.name === 'node-package')).toBe(true,
25+
'Expected the package manager to be scheduled in order to update lock files.');
2426
});
2527
});

src/cdk/schematics/ng-add/index.ts

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Rule, Tree} from '@angular-devkit/schematics';
9+
import {Rule, SchematicContext, Tree} from '@angular-devkit/schematics';
10+
import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks';
1011
import {addPackageToPackageJson} from './package-config';
1112

12-
/** Name of the Angular CDK version that is shipped together with the schematics. */
13-
export const cdkVersion = loadPackageVersionGracefully('@angular/cdk');
14-
1513
/**
1614
* Schematic factory entry-point for the `ng-add` schematic. The ng-add schematic will be
1715
* automatically executed if developers run `ng add @angular/cdk`.
@@ -21,18 +19,14 @@ export const cdkVersion = loadPackageVersionGracefully('@angular/cdk');
2119
* this ensures that there will be no error that says that the CDK does not support `ng add`.
2220
*/
2321
export default function(): Rule {
24-
return (host: Tree) => {
25-
// In order to align the CDK version with the other Angular dependencies, we use tilde
26-
// instead of caret. This is default for Angular dependencies in new CLI projects.
27-
addPackageToPackageJson(host, '@angular/cdk', `~${cdkVersion}`);
28-
};
29-
}
22+
return (host: Tree, context: SchematicContext) => {
23+
// In order to align the CDK version with other Angular dependencies that are setup
24+
// by "@schematics/angular", we use tilde instead of caret. This is default for Angular
25+
// dependencies in new CLI projects.
26+
addPackageToPackageJson(host, '@angular/cdk', `~0.0.0-PLACEHOLDER`);
3027

31-
/** Loads the full version from the given Angular package gracefully. */
32-
function loadPackageVersionGracefully(packageName: string): string|null {
33-
try {
34-
return require(`${packageName}/package.json`).version;
35-
} catch {
36-
return null;
37-
}
28+
// Add a task to run the package manager. This is necessary because we updated the
29+
// workspace "package.json" file and we want lock files to reflect the new version range.
30+
context.addTask(new NodePackageInstallTask());
31+
};
3832
}

src/material/schematics/ng-add/index.spec.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ describe('ng-add schematic', () => {
5757
const dependencies = packageJson.dependencies;
5858
const angularCoreVersion = dependencies['@angular/core'];
5959

60-
expect(dependencies['@angular/material']).toBeDefined();
61-
expect(dependencies['@angular/cdk']).toBeDefined();
60+
expect(dependencies['@angular/material']).toBe('~0.0.0-PLACEHOLDER');
61+
expect(dependencies['@angular/cdk']).toBe('~0.0.0-PLACEHOLDER');
6262
expect(dependencies['@angular/forms'])
6363
.toBe(
6464
angularCoreVersion,
@@ -73,7 +73,10 @@ describe('ng-add schematic', () => {
7373
Object.keys(dependencies).sort(),
7474
'Expected the modified "dependencies" to be sorted alphabetically.');
7575

76-
expect(runner.tasks.some(task => task.name === 'run-schematic')).toBe(true);
76+
expect(runner.tasks.some(task => task.name === 'node-package')).toBe(true,
77+
'Expected the package manager to be scheduled in order to update lock files.');
78+
expect(runner.tasks.some(task => task.name === 'run-schematic')).toBe(true,
79+
'Expected the setup-project schematic to be scheduled.');
7780
});
7881

7982
it('should add default theme', async () => {

src/material/schematics/ng-add/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ export default function(options: Schema): Rule {
2727
const ngCoreVersionTag = getPackageVersionFromPackageJson(host, '@angular/core');
2828
const angularDependencyVersion = ngCoreVersionTag || requiredAngularVersionRange;
2929

30-
// In order to align the Material and CDK version with the other Angular dependencies,
31-
// we use tilde instead of caret. This is default for Angular dependencies in new CLI projects.
30+
// In order to align the Material and CDK version with other Angular dependencies that
31+
// are setup by "@schematics/angular", we use tilde instead of caret. This is default for
32+
// Angular dependencies in new CLI projects.
3233
addPackageToPackageJson(host, '@angular/cdk', `~${materialVersion}`);
3334
addPackageToPackageJson(host, '@angular/material', `~${materialVersion}`);
3435
addPackageToPackageJson(host, '@angular/forms', angularDependencyVersion);

src/material/schematics/ng-add/version-names.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,10 @@
77
*/
88

99
/** Name of the Material version that is shipped together with the schematics. */
10-
export const materialVersion =
11-
loadPackageVersionGracefully('@angular/cdk') ||
12-
loadPackageVersionGracefully('@angular/material');
10+
export const materialVersion = '0.0.0-PLACEHOLDER';
1311

1412
/**
1513
* Range of Angular versions that can be used together with the Angular Material version
1614
* that provides these schematics.
1715
*/
1816
export const requiredAngularVersionRange = '0.0.0-NG';
19-
20-
/** Loads the full version from the given Angular package gracefully. */
21-
function loadPackageVersionGracefully(packageName: string): string | null {
22-
try {
23-
return require(`${packageName}/package.json`).version;
24-
} catch {
25-
return null;
26-
}
27-
}

0 commit comments

Comments
 (0)