Skip to content

Commit

Permalink
fix(material): ng-add should always install matching CDK version (#18076
Browse files Browse the repository at this point in the history
)

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
  • Loading branch information
devversion authored and mmalerba committed Jan 10, 2020
1 parent fad8d24 commit fba22bc
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 35 deletions.
4 changes: 3 additions & 1 deletion src/cdk/schematics/ng-add/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ describe('CDK ng-add', () => {
const packageJson = JSON.parse(getFileContent(tree, '/package.json'));
const dependencies = packageJson.dependencies;

expect(dependencies['@angular/cdk']).toBeDefined();
expect(dependencies['@angular/cdk']).toBe('~0.0.0-PLACEHOLDER');
expect(Object.keys(dependencies))
.toEqual(
Object.keys(dependencies).sort(),
'Expected the modified "dependencies" to be sorted alphabetically.');
expect(runner.tasks.some(task => task.name === 'node-package')).toBe(true,
'Expected the package manager to be scheduled in order to update lock files.');
});
});
28 changes: 11 additions & 17 deletions src/cdk/schematics/ng-add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/

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

/** Name of the Angular CDK version that is shipped together with the schematics. */
export const cdkVersion = loadPackageVersionGracefully('@angular/cdk');

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

/** Loads the full version from the given Angular package gracefully. */
function loadPackageVersionGracefully(packageName: string): string|null {
try {
return require(`${packageName}/package.json`).version;
} catch {
return null;
}
// Add a task to run the package manager. This is necessary because we updated the
// workspace "package.json" file and we want lock files to reflect the new version range.
context.addTask(new NodePackageInstallTask());
};
}
9 changes: 6 additions & 3 deletions src/material/schematics/ng-add/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ describe('ng-add schematic', () => {
const dependencies = packageJson.dependencies;
const angularCoreVersion = dependencies['@angular/core'];

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

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

it('should add default theme', async () => {
Expand Down
5 changes: 3 additions & 2 deletions src/material/schematics/ng-add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ export default function(options: Schema): Rule {
const ngCoreVersionTag = getPackageVersionFromPackageJson(host, '@angular/core');
const angularDependencyVersion = ngCoreVersionTag || requiredAngularVersionRange;

// In order to align the Material and CDK version with the other Angular dependencies,
// we use tilde instead of caret. This is default for Angular dependencies in new CLI projects.
// In order to align the Material and CDK version with other Angular dependencies that
// are setup by "@schematics/angular", we use tilde instead of caret. This is default for
// Angular dependencies in new CLI projects.
addPackageToPackageJson(host, '@angular/cdk', `~${materialVersion}`);
addPackageToPackageJson(host, '@angular/material', `~${materialVersion}`);
addPackageToPackageJson(host, '@angular/forms', angularDependencyVersion);
Expand Down
13 changes: 1 addition & 12 deletions src/material/schematics/ng-add/version-names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,10 @@
*/

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

/**
* Range of Angular versions that can be used together with the Angular Material version
* that provides these schematics.
*/
export const requiredAngularVersionRange = '0.0.0-NG';

/** Loads the full version from the given Angular package gracefully. */
function loadPackageVersionGracefully(packageName: string): string | null {
try {
return require(`${packageName}/package.json`).version;
} catch {
return null;
}
}

0 comments on commit fba22bc

Please sign in to comment.