177 lines
6.9 KiB
TypeScript

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { tags, terminal } from '@angular-devkit/core';
import { resolve } from '@angular-devkit/core/node';
import * as path from 'path';
import { SemVer, satisfies } from 'semver';
import { isWarningEnabled } from '../utilities/config';
export class Version {
private _semver: SemVer | null = null;
constructor(private _version: string | null = null) {
this._semver = _version ? new SemVer(_version) : null;
}
isAlpha() { return this.qualifier == 'alpha'; }
isBeta() { return this.qualifier == 'beta'; }
isReleaseCandidate() { return this.qualifier == 'rc'; }
isKnown() { return this._version !== null; }
isLocal() { return this.isKnown() && this._version && path.isAbsolute(this._version); }
isGreaterThanOrEqualTo(other: SemVer) {
return this._semver !== null && this._semver.compare(other) >= 0;
}
get major() { return this._semver ? this._semver.major : 0; }
get minor() { return this._semver ? this._semver.minor : 0; }
get patch() { return this._semver ? this._semver.patch : 0; }
get qualifier() { return this._semver ? this._semver.prerelease[0] : ''; }
get extra() { return this._semver ? this._semver.prerelease[1] : ''; }
toString() { return this._version; }
static assertCompatibleAngularVersion(projectRoot: string) {
let angularPkgJson;
let rxjsPkgJson;
try {
const resolveOptions = {
basedir: projectRoot,
checkGlobal: false,
checkLocal: true,
};
const angularPackagePath = resolve('@angular/core/package.json', resolveOptions);
const rxjsPackagePath = resolve('rxjs/package.json', resolveOptions);
angularPkgJson = require(angularPackagePath);
rxjsPkgJson = require(rxjsPackagePath);
} catch {
console.error(terminal.bold(terminal.red(tags.stripIndents`
You seem to not be depending on "@angular/core" and/or "rxjs". This is an error.
`)));
process.exit(2);
}
if (!(angularPkgJson && angularPkgJson['version'] && rxjsPkgJson && rxjsPkgJson['version'])) {
console.error(terminal.bold(terminal.red(tags.stripIndents`
Cannot determine versions of "@angular/core" and/or "rxjs".
This likely means your local installation is broken. Please reinstall your packages.
`)));
process.exit(2);
}
const angularVersion = new Version(angularPkgJson['version']);
const rxjsVersion = new Version(rxjsPkgJson['version']);
if (angularVersion.isLocal()) {
console.error(terminal.yellow('Using a local version of angular. Proceeding with care...'));
return;
}
if (!angularVersion.isGreaterThanOrEqualTo(new SemVer('5.0.0'))) {
console.error(terminal.bold(terminal.red(tags.stripIndents`
This version of CLI is only compatible with Angular version 5.0.0 or higher.
Please visit the link below to find instructions on how to update Angular.
https://angular-update-guide.firebaseapp.com/
` + '\n')));
process.exit(3);
} else if (
angularVersion.isGreaterThanOrEqualTo(new SemVer('6.0.0-rc.0'))
&& !rxjsVersion.isGreaterThanOrEqualTo(new SemVer('5.6.0-forward-compat.0'))
&& !rxjsVersion.isGreaterThanOrEqualTo(new SemVer('6.0.0-beta.0'))
) {
console.error(terminal.bold(terminal.red(tags.stripIndents`
This project uses version ${rxjsVersion} of RxJs, which is not supported by Angular v6.
The official RxJs version that is supported is 5.6.0-forward-compat.0 and greater.
Please visit the link below to find instructions on how to update RxJs.
https://docs.google.com/document/d/12nlLt71VLKb-z3YaSGzUfx6mJbc34nsMXtByPUN35cg/edit#
` + '\n')));
process.exit(3);
} else if (
angularVersion.isGreaterThanOrEqualTo(new SemVer('6.0.0-rc.0'))
&& !rxjsVersion.isGreaterThanOrEqualTo(new SemVer('6.0.0-beta.0'))
) {
console.warn(terminal.bold(terminal.red(tags.stripIndents`
This project uses a temporary compatibility version of RxJs (${rxjsVersion}).
Please visit the link below to find instructions on how to update RxJs.
https://docs.google.com/document/d/12nlLt71VLKb-z3YaSGzUfx6mJbc34nsMXtByPUN35cg/edit#
` + '\n')));
}
}
static assertTypescriptVersion(projectRoot: string) {
if (!isWarningEnabled('typescriptMismatch')) {
return;
}
let compilerVersion: string;
let tsVersion: string;
let compilerTypeScriptPeerVersion: string;
try {
const resolveOptions = {
basedir: projectRoot,
checkGlobal: false,
checkLocal: true,
};
const compilerPackagePath = resolve('@angular/compiler-cli/package.json', resolveOptions);
const typescriptProjectPath = resolve('typescript', resolveOptions);
const compilerPackageInfo = require(compilerPackagePath);
compilerVersion = compilerPackageInfo['version'];
compilerTypeScriptPeerVersion = compilerPackageInfo['peerDependencies']['typescript'];
tsVersion = require(typescriptProjectPath).version;
} catch {
console.error(terminal.bold(terminal.red(tags.stripIndents`
Versions of @angular/compiler-cli and typescript could not be determined.
The most common reason for this is a broken npm install.
Please make sure your package.json contains both @angular/compiler-cli and typescript in
devDependencies, then delete node_modules and package-lock.json (if you have one) and
run npm install again.
`)));
process.exit(2);
return;
}
// These versions do not have accurate typescript peer dependencies
const versionCombos = [
{ compiler: '>=2.3.1 <3.0.0', typescript: '>=2.0.2 <2.3.0' },
{ compiler: '>=4.0.0-beta.0 <5.0.0', typescript: '>=2.1.0 <2.4.0' },
{ compiler: '5.0.0-beta.0 - 5.0.0-rc.2', typescript: '>=2.4.2 <2.5.0' },
];
let currentCombo = versionCombos.find((combo) => satisfies(compilerVersion, combo.compiler));
if (!currentCombo && compilerTypeScriptPeerVersion) {
currentCombo = { compiler: compilerVersion, typescript: compilerTypeScriptPeerVersion };
}
if (currentCombo && !satisfies(tsVersion, currentCombo.typescript)) {
// First line of warning looks weird being split in two, disable tslint for it.
console.error((terminal.yellow('\n' + tags.stripIndent`
@angular/compiler-cli@${compilerVersion} requires typescript@'${
currentCombo.typescript}' but ${tsVersion} was found instead.
Using this version can result in undefined behaviour and difficult to debug problems.
Please run the following command to install a compatible version of TypeScript.
npm install typescript@"${currentCombo.typescript}"
To disable this warning run "ng config cli.warnings.typescriptMismatch false".
` + '\n')));
}
}
}