Skip to content

Commit

Permalink
feat(@schematics/angular): drop @angular/http from dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
filipesilva authored and alexeagle committed Apr 23, 2019
1 parent a464c00 commit fea7117
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 2 deletions.
2 changes: 2 additions & 0 deletions packages/schematics/angular/migrations/update-8/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { updatePackageJson, updateTsLintConfig } from './codelyzer-5';
import { updateES5Projects } from './differential-loading';
import { dropES2015Polyfills } from './drop-es6-polyfills';
import { removeAngularHttp } from './remove-angular-http';
import { updateBuilders } from './update-builders';

export { updateLazyModulePaths } from './update-lazy-module-paths';
Expand All @@ -25,6 +26,7 @@ export default function(): Rule {
dropES2015Polyfills(),
updateES5Projects(),
updateBuilders(),
removeAngularHttp(),
]);
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @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 { SchematicContext, Tree } from '@angular-devkit/schematics';
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
import { removePackageJsonDependency } from '../../utility/dependencies';

export const removeAngularHttp = () => {
return (host: Tree, context: SchematicContext) => {
removePackageJsonDependency(host, '@angular/http');
context.addTask(new NodePackageInstallTask());

return host;
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* @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
*/
// tslint:disable:no-big-function
import { EmptyTree } from '@angular-devkit/schematics';
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';


describe('Migration to version 8', () => {
const schematicRunner = new SchematicTestRunner(
'migrations',
require.resolve('../migration-collection.json'),
);

let tree: UnitTestTree;
const defaultOptions = {};
const packageJsonPath = '/package.json';
const packageJson = {
dependencies: {
'@angular/http': '7.0.0',
},
devDependencies: {
'@angular/http': '7.0.0',
},
};

describe('Migration to version 8', () => {
beforeEach(() => {
tree = new UnitTestTree(new EmptyTree());
tree.create(packageJsonPath, JSON.stringify(packageJson, null, 2));
});

it('should remove all dependencies on @angular/http', () => {
tree = schematicRunner.runSchematic('migration-07', defaultOptions, tree);
const packageJson = JSON.parse(tree.readContent(packageJsonPath));
expect(packageJson.dependencies['@angular/http']).toBe(undefined);
expect(packageJson.devDependencies['@angular/http']).toBe(undefined);
});
});
});
21 changes: 20 additions & 1 deletion packages/schematics/angular/utility/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
appendPropertyInAstObject,
findPropertyInAstObject,
insertPropertyInAstObjectInOrder,
} from './json-utils';
removePropertyInAstObject,
} from './json-utils';


const pkgJsonPath = '/package.json';
Expand Down Expand Up @@ -62,6 +63,24 @@ export function addPackageJsonDependency(tree: Tree, dependency: NodeDependency)
tree.commitUpdate(recorder);
}

export function removePackageJsonDependency(tree: Tree, name: string): void {
const packageJson = _readPackageJson(tree);
const recorder = tree.beginUpdate(pkgJsonPath);
[
NodeDependencyType.Default,
NodeDependencyType.Dev,
NodeDependencyType.Optional,
NodeDependencyType.Peer,
].forEach(depType => {
const depsNode = findPropertyInAstObject(packageJson, depType);
if (depsNode !== null && depsNode.kind === 'object') {
removePropertyInAstObject(recorder, depsNode, name);
}
});

tree.commitUpdate(recorder);
}

export function getPackageJsonDependency(tree: Tree, name: string): NodeDependency | null {
const packageJson = _readPackageJson(tree);
let dep: NodeDependency | null = null;
Expand Down
57 changes: 56 additions & 1 deletion packages/schematics/angular/utility/json-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function appendPropertyInAstObject(
if (node.properties.length > 0) {
// Insert comma.
const last = node.properties[node.properties.length - 1];
const {text, end} = last;
const { text, end } = last;
const commaIndex = text.endsWith('\n') ? end.offset - 1 : end.offset;
recorder.insertRight(commaIndex, ',');
index = end.offset;
Expand Down Expand Up @@ -93,6 +93,61 @@ export function insertPropertyInAstObjectInOrder(
);
}

export function removePropertyInAstObject(
recorder: UpdateRecorder,
node: JsonAstObject,
propertyName: string,
) {
// Find the property inside the object.
const propIdx = node.properties.findIndex(prop => prop.key.value === propertyName);

if (propIdx === -1) {
// There's nothing to remove.
return;
}

if (node.properties.length === 1) {
// This is a special case. Everything should be removed, including indentation.
recorder.remove(node.start.offset, node.end.offset - node.start.offset);
recorder.insertRight(node.start.offset, '{}');

return;
}

// The AST considers commas and indentation to be part of the preceding property.
// To get around messy comma and identation management, we can work over the range between
// two properties instead.
const previousProp = node.properties[propIdx - 1];
const targetProp = node.properties[propIdx];
const nextProp = node.properties[propIdx + 1];

let start, end;
if (previousProp) {
// Given the object below, and intending to remove the `m` property:
// "{\n \"a\": \"a\",\n \"m\": \"m\",\n \"z\": \"z\"\n}"
// ^---------------^
// Removing the range above results in:
// "{\n \"a\": \"a\",\n \"z\": \"z\"\n}"
start = previousProp.end;
end = targetProp.end;
} else {
// If there's no previousProp there is a nextProp, since we've specialcased the 1 length case.
// Given the object below, and intending to remove the `a` property:
// "{\n \"a\": \"a\",\n \"m\": \"m\",\n \"z\": \"z\"\n}"
// ^---------------^
// Removing the range above results in:
// "{\n \"m\": \"m\",\n \"z\": \"z\"\n}"
start = targetProp.start;
end = nextProp.start;
}

recorder.remove(start.offset, end.offset - start.offset);
if (!nextProp) {

recorder.insertRight(start.offset, '\n');
}
}


export function appendValueInAstArray(
recorder: UpdateRecorder,
Expand Down
43 changes: 43 additions & 0 deletions packages/schematics/angular/utility/json-utils_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
appendPropertyInAstObject,
appendValueInAstArray,
insertPropertyInAstObjectInOrder,
removePropertyInAstObject,
} from './json-utils';

describe('json-utils', () => {
Expand Down Expand Up @@ -129,6 +130,48 @@ describe('json-utils', () => {
});
});

describe('removePropertyInAstObject', () => {
it('should remove a first prop', () => {
const indent = 2;
const result = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
expect(ast.kind).toBe('object');
removePropertyInAstObject(rec, ast, a);
}, {a, m, z}, indent);
expect(result).toBe(JSON.stringify({m, z}, null, indent));
expect(JSON.parse(result)).toEqual({m, z});
});

it('should remove a middle prop', () => {
const indent = 2;
const result = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
expect(ast.kind).toBe('object');
removePropertyInAstObject(rec, ast, m);
}, {a, m, z}, indent);
expect(result).toBe(JSON.stringify({a, z}, null, indent));
expect(JSON.parse(result)).toEqual({a, z});
});

it('should remove a last prop', () => {
const indent = 2;
const result = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
expect(ast.kind).toBe('object');
removePropertyInAstObject(rec, ast, z);
}, {a, m, z}, indent);
expect(result).toBe(JSON.stringify({a, m}, null, indent));
expect(JSON.parse(result)).toEqual({a, m});
});

it('should remove only prop', () => {
const indent = 2;
const result = runTest((rec: UpdateRecorder, ast: JsonAstObject) => {
expect(ast.kind).toBe('object');
removePropertyInAstObject(rec, ast, a);
}, {a}, indent);
expect(result).toBe(JSON.stringify({}, null, indent));
expect(JSON.parse(result)).toEqual({});
});
});

describe('appendValueInAstArray', () => {
it('should insert multiple props with different indentations', () => {
const cases: Array<[string[], string, {}, number]> = [
Expand Down

0 comments on commit fea7117

Please sign in to comment.