fix(bazel): don't rely on @angular/core being as a depedency to install @angular/bazel (#34181)
With this change we fix the logic to detect if a package is installed, removing a package and add a package by using the CLI schematic helpers. Also we save `@angular/bazel` package directly as a `devDependency` when doing `ng-add`. Closes #34164 PR Close #34181
This commit is contained in:
parent
755d2d572f
commit
0cd8431698
@ -51,6 +51,9 @@
|
|||||||
},
|
},
|
||||||
"builders": "./src/builders/builders.json",
|
"builders": "./src/builders/builders.json",
|
||||||
"schematics": "./src/schematics/collection.json",
|
"schematics": "./src/schematics/collection.json",
|
||||||
|
"ng-add": {
|
||||||
|
"save": "devDependencies"
|
||||||
|
},
|
||||||
"ng-update": {
|
"ng-update": {
|
||||||
"packageGroup": "NG_UPDATE_PACKAGE_GROUP"
|
"packageGroup": "NG_UPDATE_PACKAGE_GROUP"
|
||||||
},
|
},
|
||||||
|
@ -12,15 +12,17 @@ import {JsonAstObject, parseJsonAst} from '@angular-devkit/core';
|
|||||||
import {Rule, SchematicContext, SchematicsException, Tree, apply, applyTemplates, chain, mergeWith, url} from '@angular-devkit/schematics';
|
import {Rule, SchematicContext, SchematicsException, Tree, apply, applyTemplates, chain, mergeWith, url} from '@angular-devkit/schematics';
|
||||||
import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks';
|
import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks';
|
||||||
import {getWorkspace, getWorkspacePath} from '@schematics/angular/utility/config';
|
import {getWorkspace, getWorkspacePath} from '@schematics/angular/utility/config';
|
||||||
|
import {NodeDependencyType, addPackageJsonDependency, getPackageJsonDependency, removePackageJsonDependency} from '@schematics/angular/utility/dependencies';
|
||||||
import {findPropertyInAstObject, insertPropertyInAstObjectInOrder} from '@schematics/angular/utility/json-utils';
|
import {findPropertyInAstObject, insertPropertyInAstObjectInOrder} from '@schematics/angular/utility/json-utils';
|
||||||
import {validateProjectName} from '@schematics/angular/utility/validation';
|
import {validateProjectName} from '@schematics/angular/utility/validation';
|
||||||
|
|
||||||
import {isJsonAstObject, removeKeyValueInAstObject, replacePropertyInAstObject} from '../utility/json-utils';
|
import {isJsonAstObject, replacePropertyInAstObject} from '../utility/json-utils';
|
||||||
import {findE2eArchitect} from '../utility/workspace-utils';
|
import {findE2eArchitect} from '../utility/workspace-utils';
|
||||||
|
|
||||||
import {Schema} from './schema';
|
import {Schema} from './schema';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Packages that build under Bazel require additional dev dependencies. This
|
* Packages that build under Bazel require additional dev dependencies. This
|
||||||
* function adds those dependencies to "devDependencies" section in
|
* function adds those dependencies to "devDependencies" section in
|
||||||
@ -28,57 +30,41 @@ import {Schema} from './schema';
|
|||||||
*/
|
*/
|
||||||
function addDevDependenciesToPackageJson(options: Schema) {
|
function addDevDependenciesToPackageJson(options: Schema) {
|
||||||
return (host: Tree) => {
|
return (host: Tree) => {
|
||||||
const packageJson = 'package.json';
|
const angularCore = getPackageJsonDependency(host, '@angular/core');
|
||||||
if (!host.exists(packageJson)) {
|
if (!angularCore) {
|
||||||
throw new Error(`Could not find ${packageJson}`);
|
|
||||||
}
|
|
||||||
const packageJsonContent = host.read(packageJson);
|
|
||||||
if (!packageJsonContent) {
|
|
||||||
throw new Error('Failed to read package.json content');
|
|
||||||
}
|
|
||||||
const jsonAst = parseJsonAst(packageJsonContent.toString()) as JsonAstObject;
|
|
||||||
const deps = findPropertyInAstObject(jsonAst, 'dependencies') as JsonAstObject;
|
|
||||||
const devDeps = findPropertyInAstObject(jsonAst, 'devDependencies') as JsonAstObject;
|
|
||||||
|
|
||||||
const angularCoreNode = findPropertyInAstObject(deps, '@angular/core');
|
|
||||||
if (!angularCoreNode) {
|
|
||||||
throw new Error('@angular/core dependency not found in package.json');
|
throw new Error('@angular/core dependency not found in package.json');
|
||||||
}
|
}
|
||||||
const angularCoreVersion = angularCoreNode.value as string;
|
|
||||||
|
|
||||||
const devDependencies: {[k: string]: string} = {
|
// TODO: use a Record<string, string> when the tsc lib setting allows us
|
||||||
'@angular/bazel': angularCoreVersion,
|
const devDependencies: [string, string][] = [
|
||||||
'@bazel/bazel': '1.1.0',
|
['@angular/bazel', angularCore.version],
|
||||||
'@bazel/ibazel': '^0.10.2',
|
['@bazel/bazel', '1.1.0'],
|
||||||
'@bazel/karma': '0.40.0',
|
['@bazel/ibazel', '^0.10.2'],
|
||||||
'@bazel/protractor': '0.40.0',
|
['@bazel/karma', '0.40.0'],
|
||||||
'@bazel/rollup': '0.40.0',
|
['@bazel/protractor', '0.40.0'],
|
||||||
'@bazel/terser': '0.40.0',
|
['@bazel/rollup', '0.40.0'],
|
||||||
'@bazel/typescript': '0.40.0',
|
['@bazel/terser', '0.40.0'],
|
||||||
'history-server': '^1.3.1',
|
['@bazel/typescript', '0.40.0'],
|
||||||
'rollup': '^1.25.2',
|
['history-server', '^1.3.1'],
|
||||||
'rollup-plugin-commonjs': '^10.1.0',
|
['rollup', '^1.25.2'],
|
||||||
'rollup-plugin-node-resolve': '^5.2.0',
|
['rollup-plugin-commonjs', '^10.1.0'],
|
||||||
'terser': '^4.3.9',
|
['rollup-plugin-node-resolve', '^5.2.0'],
|
||||||
};
|
['terser', '^4.3.9'],
|
||||||
|
];
|
||||||
|
|
||||||
const recorder = host.beginUpdate(packageJson);
|
for (const [name, version] of devDependencies) {
|
||||||
for (const packageName of Object.keys(devDependencies)) {
|
const dep = getPackageJsonDependency(host, name);
|
||||||
const existingDep = findPropertyInAstObject(deps, packageName);
|
if (dep && dep.type !== NodeDependencyType.Dev) {
|
||||||
if (existingDep) {
|
removePackageJsonDependency(host, name);
|
||||||
const content = packageJsonContent.toString();
|
|
||||||
removeKeyValueInAstObject(recorder, content, deps, packageName);
|
|
||||||
}
|
|
||||||
const version = devDependencies[packageName];
|
|
||||||
const indent = 4;
|
|
||||||
if (findPropertyInAstObject(devDeps, packageName)) {
|
|
||||||
replacePropertyInAstObject(recorder, devDeps, packageName, version, indent);
|
|
||||||
} else {
|
|
||||||
insertPropertyInAstObjectInOrder(recorder, devDeps, packageName, version, indent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addPackageJsonDependency(host, {
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
type: NodeDependencyType.Dev,
|
||||||
|
overwrite: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
host.commitUpdate(recorder);
|
|
||||||
return host;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,38 +74,13 @@ function addDevDependenciesToPackageJson(options: Schema) {
|
|||||||
*/
|
*/
|
||||||
function removeObsoleteDependenciesFromPackageJson(options: Schema) {
|
function removeObsoleteDependenciesFromPackageJson(options: Schema) {
|
||||||
return (host: Tree) => {
|
return (host: Tree) => {
|
||||||
const packageJson = 'package.json';
|
|
||||||
if (!host.exists(packageJson)) {
|
|
||||||
throw new Error(`Could not find ${packageJson}`);
|
|
||||||
}
|
|
||||||
const buffer = host.read(packageJson);
|
|
||||||
if (!buffer) {
|
|
||||||
throw new Error('Failed to read package.json content');
|
|
||||||
}
|
|
||||||
const content = buffer.toString();
|
|
||||||
const jsonAst = parseJsonAst(content) as JsonAstObject;
|
|
||||||
const deps = findPropertyInAstObject(jsonAst, 'dependencies') as JsonAstObject;
|
|
||||||
const devDeps = findPropertyInAstObject(jsonAst, 'devDependencies') as JsonAstObject;
|
|
||||||
|
|
||||||
const depsToRemove = [
|
const depsToRemove = [
|
||||||
'@angular-devkit/build-angular',
|
'@angular-devkit/build-angular',
|
||||||
];
|
];
|
||||||
|
|
||||||
const recorder = host.beginUpdate(packageJson);
|
|
||||||
|
|
||||||
for (const packageName of depsToRemove) {
|
for (const packageName of depsToRemove) {
|
||||||
const depNode = findPropertyInAstObject(deps, packageName);
|
removePackageJsonDependency(host, packageName);
|
||||||
if (depNode) {
|
|
||||||
removeKeyValueInAstObject(recorder, content, deps, packageName);
|
|
||||||
}
|
|
||||||
const devDepNode = findPropertyInAstObject(devDeps, packageName);
|
|
||||||
if (devDepNode) {
|
|
||||||
removeKeyValueInAstObject(recorder, content, devDeps, packageName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
host.commitUpdate(recorder);
|
|
||||||
return host;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +127,7 @@ function updateGitignore() {
|
|||||||
* Change the architect in angular.json to use Bazel builder.
|
* Change the architect in angular.json to use Bazel builder.
|
||||||
*/
|
*/
|
||||||
function updateAngularJsonToUseBazelBuilder(options: Schema): Rule {
|
function updateAngularJsonToUseBazelBuilder(options: Schema): Rule {
|
||||||
return (host: Tree, context: SchematicContext) => {
|
return (host: Tree) => {
|
||||||
const name = options.name !;
|
const name = options.name !;
|
||||||
const workspacePath = getWorkspacePath(host);
|
const workspacePath = getWorkspacePath(host);
|
||||||
if (!workspacePath) {
|
if (!workspacePath) {
|
||||||
@ -277,39 +238,25 @@ function backupAngularJson(): Rule {
|
|||||||
*/
|
*/
|
||||||
function upgradeRxjs() {
|
function upgradeRxjs() {
|
||||||
return (host: Tree, context: SchematicContext) => {
|
return (host: Tree, context: SchematicContext) => {
|
||||||
const packageJson = 'package.json';
|
const rxjsNode = getPackageJsonDependency(host, 'rxjs');
|
||||||
if (!host.exists(packageJson)) {
|
if (!rxjsNode) {
|
||||||
throw new Error(`Could not find ${packageJson}`);
|
throw new Error(`Failed to find rxjs dependency.`);
|
||||||
}
|
}
|
||||||
const content = host.read(packageJson);
|
|
||||||
if (!content) {
|
const match = rxjsNode.version.match(/(\d)+\.(\d)+.(\d)+$/);
|
||||||
throw new Error('Failed to read package.json content');
|
|
||||||
}
|
|
||||||
const jsonAst = parseJsonAst(content.toString());
|
|
||||||
if (!isJsonAstObject(jsonAst)) {
|
|
||||||
throw new Error(`Failed to parse JSON for ${packageJson}`);
|
|
||||||
}
|
|
||||||
const deps = findPropertyInAstObject(jsonAst, 'dependencies');
|
|
||||||
if (!isJsonAstObject(deps)) {
|
|
||||||
throw new Error(`Failed to find dependencies in ${packageJson}`);
|
|
||||||
}
|
|
||||||
const rxjs = findPropertyInAstObject(deps, 'rxjs');
|
|
||||||
if (!rxjs) {
|
|
||||||
throw new Error(`Failed to find rxjs in dependencies of ${packageJson}`);
|
|
||||||
}
|
|
||||||
const value = rxjs.value as string; // value can be version or range
|
|
||||||
const match = value.match(/(\d)+\.(\d)+.(\d)+$/);
|
|
||||||
if (match) {
|
if (match) {
|
||||||
const [_, major, minor] = match;
|
const [_, major, minor] = match;
|
||||||
if (major < '6' || (major === '6' && minor < '4')) {
|
if (major < '6' || (major === '6' && minor < '5')) {
|
||||||
const recorder = host.beginUpdate(packageJson);
|
addPackageJsonDependency(host, {
|
||||||
replacePropertyInAstObject(recorder, deps, 'rxjs', '~6.4.0');
|
...rxjsNode,
|
||||||
host.commitUpdate(recorder);
|
version: '~6.5.3',
|
||||||
|
overwrite: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
context.logger.info(
|
context.logger.info(
|
||||||
'Could not determine version of rxjs. \n' +
|
'Could not determine version of rxjs. \n' +
|
||||||
'Please make sure that version is at least 6.4.0.');
|
'Please make sure that version is at least 6.5.3.');
|
||||||
}
|
}
|
||||||
return host;
|
return host;
|
||||||
};
|
};
|
||||||
|
@ -73,7 +73,7 @@ describe('ng-add schematic', () => {
|
|||||||
message = e.message;
|
message = e.message;
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(message).toBe('Could not find package.json');
|
expect(message).toBe('Could not read package.json.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws if angular.json is not found', async() => {
|
it('throws if angular.json is not found', async() => {
|
||||||
@ -104,7 +104,6 @@ describe('ng-add schematic', () => {
|
|||||||
expect(Object.keys(json)).toContain('devDependencies');
|
expect(Object.keys(json)).toContain('devDependencies');
|
||||||
expect(Object.keys(json.dependencies)).toContain(core);
|
expect(Object.keys(json.dependencies)).toContain(core);
|
||||||
expect(Object.keys(json.devDependencies)).toContain(bazel);
|
expect(Object.keys(json.devDependencies)).toContain(bazel);
|
||||||
expect(json.dependencies[core]).toBe(json.devDependencies[bazel]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add @bazel/* dev dependencies', async() => {
|
it('should add @bazel/* dev dependencies', async() => {
|
||||||
@ -273,9 +272,9 @@ describe('ng-add schematic', () => {
|
|||||||
['~6.3.3', true],
|
['~6.3.3', true],
|
||||||
['^6.3.3', true],
|
['^6.3.3', true],
|
||||||
['~6.3.11', true],
|
['~6.3.11', true],
|
||||||
['6.4.0', false],
|
['6.4.0', true],
|
||||||
['~6.4.0', false],
|
['~6.4.0', true],
|
||||||
['~6.4.1', false],
|
['~6.4.1', true],
|
||||||
['6.5.0', false],
|
['6.5.0', false],
|
||||||
['~6.5.0', false],
|
['~6.5.0', false],
|
||||||
['^6.5.0', false],
|
['^6.5.0', false],
|
||||||
@ -298,7 +297,7 @@ describe('ng-add schematic', () => {
|
|||||||
const content = host.readContent('/package.json');
|
const content = host.readContent('/package.json');
|
||||||
const json = JSON.parse(content);
|
const json = JSON.parse(content);
|
||||||
if (upgrade) {
|
if (upgrade) {
|
||||||
expect(json.dependencies.rxjs).toBe('~6.4.0');
|
expect(json.dependencies.rxjs).toBe('~6.5.3');
|
||||||
} else {
|
} else {
|
||||||
expect(json.dependencies.rxjs).toBe(version);
|
expect(json.dependencies.rxjs).toBe(version);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user