mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-16 02:24:10 +08:00
refactor: Consolidate adding dependencies
This commit is contained in:
parent
04893ca343
commit
d3b49a5590
@ -29,6 +29,7 @@ import {
|
||||
addProjectToWorkspace,
|
||||
getWorkspace,
|
||||
} from '../utility/config';
|
||||
import { NodeDependencyType, addPackageJsonDependency } from '../utility/dependencies';
|
||||
import { latestVersions } from '../utility/latest-versions';
|
||||
import { validateProjectName } from '../utility/validation';
|
||||
import { Schema as ApplicationOptions } from './schema';
|
||||
@ -60,29 +61,23 @@ import { Schema as ApplicationOptions } from './schema';
|
||||
|
||||
function addDependenciesToPackageJson() {
|
||||
return (host: Tree) => {
|
||||
const packageJsonPath = 'package.json';
|
||||
|
||||
if (!host.exists('package.json')) { return host; }
|
||||
|
||||
const source = host.read('package.json');
|
||||
if (!source) { return host; }
|
||||
|
||||
const sourceText = source.toString('utf-8');
|
||||
const json = JSON.parse(sourceText);
|
||||
|
||||
if (!json['devDependencies']) {
|
||||
json['devDependencies'] = {};
|
||||
}
|
||||
|
||||
json.devDependencies = {
|
||||
'@angular/compiler-cli': latestVersions.Angular,
|
||||
'@angular-devkit/build-angular': latestVersions.DevkitBuildAngular,
|
||||
'typescript': latestVersions.TypeScript,
|
||||
// De-structure last keeps existing user dependencies.
|
||||
...json.devDependencies,
|
||||
};
|
||||
|
||||
host.overwrite(packageJsonPath, JSON.stringify(json, null, 2));
|
||||
[
|
||||
{
|
||||
type: NodeDependencyType.Dev,
|
||||
name: '@angular/compiler-cli',
|
||||
version: latestVersions.Angular,
|
||||
},
|
||||
{
|
||||
type: NodeDependencyType.Dev,
|
||||
name: '@angular-devkit/build-angular',
|
||||
version: latestVersions.DevkitBuildAngular,
|
||||
},
|
||||
{
|
||||
type: NodeDependencyType.Dev,
|
||||
name: 'typescript',
|
||||
version: latestVersions.TypeScript,
|
||||
},
|
||||
].forEach(dependency => addPackageJsonDependency(host, dependency));
|
||||
|
||||
return host;
|
||||
};
|
||||
|
@ -27,23 +27,15 @@ import {
|
||||
addProjectToWorkspace,
|
||||
getWorkspace,
|
||||
} from '../utility/config';
|
||||
import {
|
||||
NodeDependencyType,
|
||||
addPackageJsonDependency,
|
||||
} from '../utility/dependencies';
|
||||
import { latestVersions } from '../utility/latest-versions';
|
||||
import { validateProjectName } from '../utility/validation';
|
||||
import { Schema as LibraryOptions } from './schema';
|
||||
|
||||
|
||||
type PackageJsonPartialType = {
|
||||
scripts: {
|
||||
[key: string]: string;
|
||||
},
|
||||
dependencies: {
|
||||
[key: string]: string;
|
||||
},
|
||||
devDependencies: {
|
||||
[key: string]: string;
|
||||
},
|
||||
};
|
||||
|
||||
interface UpdateJsonFn<T> {
|
||||
(obj: T): T | void;
|
||||
}
|
||||
@ -96,39 +88,45 @@ function updateTsConfig(packageName: string, distRoot: string) {
|
||||
function addDependenciesToPackageJson() {
|
||||
|
||||
return (host: Tree) => {
|
||||
if (!host.exists('package.json')) { return host; }
|
||||
[
|
||||
{
|
||||
type: NodeDependencyType.Dev,
|
||||
name: '@angular/compiler-cli',
|
||||
version: latestVersions.Angular,
|
||||
},
|
||||
{
|
||||
type: NodeDependencyType.Dev,
|
||||
name: '@angular-devkit/build-ng-packagr',
|
||||
version: latestVersions.DevkitBuildNgPackagr,
|
||||
},
|
||||
{
|
||||
type: NodeDependencyType.Dev,
|
||||
name: '@angular-devkit/build-angular',
|
||||
version: latestVersions.DevkitBuildNgPackagr,
|
||||
},
|
||||
{
|
||||
type: NodeDependencyType.Dev,
|
||||
name: 'ng-packagr',
|
||||
version: '^3.0.0',
|
||||
},
|
||||
{
|
||||
type: NodeDependencyType.Dev,
|
||||
name: 'tsickle',
|
||||
version: '>=0.29.0',
|
||||
},
|
||||
{
|
||||
type: NodeDependencyType.Dev,
|
||||
name: 'tslib',
|
||||
version: '^1.9.0',
|
||||
},
|
||||
{
|
||||
type: NodeDependencyType.Dev,
|
||||
name: 'typescript',
|
||||
version: latestVersions.TypeScript,
|
||||
},
|
||||
].forEach(dependency => addPackageJsonDependency(host, dependency));
|
||||
|
||||
return updateJsonFile(host, 'package.json', (json: PackageJsonPartialType) => {
|
||||
|
||||
|
||||
if (!json['dependencies']) {
|
||||
json['dependencies'] = {};
|
||||
}
|
||||
|
||||
json.dependencies = {
|
||||
'@angular/common': latestVersions.Angular,
|
||||
'@angular/core': latestVersions.Angular,
|
||||
'@angular/compiler': latestVersions.Angular,
|
||||
// De-structure last keeps existing user dependencies.
|
||||
...json.dependencies,
|
||||
};
|
||||
|
||||
if (!json['devDependencies']) {
|
||||
json['devDependencies'] = {};
|
||||
}
|
||||
|
||||
json.devDependencies = {
|
||||
'@angular/compiler-cli': latestVersions.Angular,
|
||||
'@angular-devkit/build-ng-packagr': latestVersions.DevkitBuildNgPackagr,
|
||||
'@angular-devkit/build-angular': latestVersions.DevkitBuildNgPackagr,
|
||||
'ng-packagr': '^3.0.0',
|
||||
'tsickle': '>=0.29.0',
|
||||
'tslib': '^1.9.0',
|
||||
'typescript': latestVersions.TypeScript,
|
||||
// De-structure last keeps existing user dependencies.
|
||||
...json.devDependencies,
|
||||
};
|
||||
});
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -26,12 +26,16 @@ import {
|
||||
} from '@angular-devkit/schematics';
|
||||
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
|
||||
import { AppConfig, CliConfig } from '../../utility/config';
|
||||
import { latestVersions } from '../../utility/latest-versions';
|
||||
import {
|
||||
appendPropertyInAstObject,
|
||||
NodeDependency,
|
||||
NodeDependencyType,
|
||||
addPackageJsonDependency,
|
||||
} from '../../utility/dependencies';
|
||||
import {
|
||||
appendValueInAstArray,
|
||||
findPropertyInAstObject,
|
||||
} from './json-utils';
|
||||
} from '../../utility/json-utils';
|
||||
import { latestVersions } from '../../utility/latest-versions';
|
||||
|
||||
const defaults = {
|
||||
appRoot: 'src',
|
||||
@ -649,49 +653,13 @@ function updateSpecTsConfig(config: CliConfig): Rule {
|
||||
|
||||
function updatePackageJson(config: CliConfig) {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const pkgPath = '/package.json';
|
||||
const buffer = host.read(pkgPath);
|
||||
if (buffer == null) {
|
||||
throw new SchematicsException('Could not read package.json');
|
||||
}
|
||||
const pkgAst = parseJsonAst(buffer.toString(), JsonParseMode.Strict);
|
||||
|
||||
if (pkgAst.kind != 'object') {
|
||||
throw new SchematicsException('Error reading package.json');
|
||||
}
|
||||
|
||||
const devDependenciesNode = findPropertyInAstObject(pkgAst, 'devDependencies');
|
||||
if (devDependenciesNode && devDependenciesNode.kind != 'object') {
|
||||
throw new SchematicsException('Error reading package.json; devDependency is not an object.');
|
||||
}
|
||||
|
||||
const recorder = host.beginUpdate(pkgPath);
|
||||
const depName = '@angular-devkit/build-angular';
|
||||
if (!devDependenciesNode) {
|
||||
// Haven't found the devDependencies key, add it to the root of the package.json.
|
||||
appendPropertyInAstObject(recorder, pkgAst, 'devDependencies', {
|
||||
[depName]: latestVersions.DevkitBuildAngular,
|
||||
});
|
||||
} else {
|
||||
// Check if there's a build-angular key.
|
||||
const buildAngularNode = findPropertyInAstObject(devDependenciesNode, depName);
|
||||
|
||||
if (!buildAngularNode) {
|
||||
// No build-angular package, add it.
|
||||
appendPropertyInAstObject(
|
||||
recorder,
|
||||
devDependenciesNode,
|
||||
depName,
|
||||
latestVersions.DevkitBuildAngular,
|
||||
);
|
||||
} else {
|
||||
const { end, start } = buildAngularNode;
|
||||
recorder.remove(start.offset, end.offset - start.offset);
|
||||
recorder.insertRight(start.offset, JSON.stringify(latestVersions.DevkitBuildAngular));
|
||||
}
|
||||
}
|
||||
|
||||
host.commitUpdate(recorder);
|
||||
const dependency: NodeDependency = {
|
||||
type: NodeDependencyType.Dev,
|
||||
name: '@angular-devkit/build-angular',
|
||||
version: latestVersions.DevkitBuildAngular,
|
||||
overwrite: true,
|
||||
};
|
||||
addPackageJsonDependency(host, dependency);
|
||||
|
||||
context.addTask(new NodePackageInstallTask({
|
||||
packageManager: config.packageManager === 'default' ? undefined : config.packageManager,
|
||||
|
@ -26,11 +26,10 @@ import {
|
||||
getWorkspace,
|
||||
getWorkspacePath,
|
||||
} from '../utility/config';
|
||||
import { addPackageJsonDependency, getPackageJsonDependency } from '../utility/dependencies';
|
||||
import { getAppModulePath } from '../utility/ng-ast-utils';
|
||||
import { Schema as ServiceWorkerOptions } from './schema';
|
||||
|
||||
const packageJsonPath = '/package.json';
|
||||
|
||||
function updateConfigFile(options: ServiceWorkerOptions): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
context.logger.debug('updating config file.');
|
||||
@ -72,17 +71,15 @@ function addDependencies(): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const packageName = '@angular/service-worker';
|
||||
context.logger.debug(`adding dependency (${packageName})`);
|
||||
const buffer = host.read(packageJsonPath);
|
||||
if (buffer === null) {
|
||||
throw new SchematicsException('Could not find package.json');
|
||||
const coreDep = getPackageJsonDependency(host, '@angular/core');
|
||||
if (coreDep === null) {
|
||||
throw new SchematicsException('Could not find version.');
|
||||
}
|
||||
|
||||
const packageObject = JSON.parse(buffer.toString());
|
||||
|
||||
const ngCoreVersion = packageObject.dependencies['@angular/core'];
|
||||
packageObject.dependencies[packageName] = ngCoreVersion;
|
||||
|
||||
host.overwrite(packageJsonPath, JSON.stringify(packageObject, null, 2));
|
||||
const platformServerDep = {
|
||||
...coreDep,
|
||||
name: packageName,
|
||||
};
|
||||
addPackageJsonDependency(host, platformServerDep);
|
||||
|
||||
return host;
|
||||
};
|
||||
|
@ -34,6 +34,7 @@ import * as ts from 'typescript';
|
||||
import { findNode, getDecoratorMetadata } from '../utility/ast-utils';
|
||||
import { InsertChange } from '../utility/change';
|
||||
import { getWorkspace } from '../utility/config';
|
||||
import { addPackageJsonDependency, getPackageJsonDependency } from '../utility/dependencies';
|
||||
import { findBootstrapModuleCall, findBootstrapModulePath } from '../utility/ng-ast-utils';
|
||||
import { Schema as UniversalOptions } from './schema';
|
||||
|
||||
@ -172,18 +173,15 @@ function addServerTransition(options: UniversalOptions): Rule {
|
||||
|
||||
function addDependencies(): Rule {
|
||||
return (host: Tree) => {
|
||||
const pkgPath = '/package.json';
|
||||
const buffer = host.read(pkgPath);
|
||||
if (buffer === null) {
|
||||
throw new SchematicsException('Could not find package.json');
|
||||
const coreDep = getPackageJsonDependency(host, '@angular/core');
|
||||
if (coreDep === null) {
|
||||
throw new SchematicsException('Could not find version.');
|
||||
}
|
||||
|
||||
const pkg = JSON.parse(buffer.toString());
|
||||
|
||||
const ngCoreVersion = pkg.dependencies['@angular/core'];
|
||||
pkg.dependencies['@angular/platform-server'] = ngCoreVersion;
|
||||
|
||||
host.overwrite(pkgPath, JSON.stringify(pkg, null, 2));
|
||||
const platformServerDep = {
|
||||
...coreDep,
|
||||
name: '@angular/platform-server',
|
||||
};
|
||||
addPackageJsonDependency(host, platformServerDep);
|
||||
|
||||
return host;
|
||||
};
|
||||
|
107
packages/schematics/angular/utility/dependencies.ts
Normal file
107
packages/schematics/angular/utility/dependencies.ts
Normal file
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @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 { JsonAstObject, JsonParseMode, parseJsonAst } from '@angular-devkit/core';
|
||||
import { SchematicsException, Tree } from '@angular-devkit/schematics';
|
||||
import {
|
||||
appendPropertyInAstObject,
|
||||
findPropertyInAstObject,
|
||||
insertPropertyInAstObjectInOrder,
|
||||
} from './json-utils';
|
||||
|
||||
|
||||
const pkgJsonPath = '/package.json';
|
||||
export enum NodeDependencyType {
|
||||
Default = 'dependencies',
|
||||
Dev = 'devDependencies',
|
||||
Peer = 'peerDependencies',
|
||||
Optional = 'optionalDependencies',
|
||||
}
|
||||
|
||||
export interface NodeDependency {
|
||||
type: NodeDependencyType;
|
||||
name: string;
|
||||
version: string;
|
||||
overwrite?: boolean;
|
||||
}
|
||||
|
||||
export function addPackageJsonDependency(tree: Tree, dependency: NodeDependency): void {
|
||||
const packageJsonAst = _readPackageJson(tree);
|
||||
const depsNode = findPropertyInAstObject(packageJsonAst, dependency.type);
|
||||
const recorder = tree.beginUpdate(pkgJsonPath);
|
||||
if (!depsNode) {
|
||||
// Haven't found the dependencies key, add it to the root of the package.json.
|
||||
appendPropertyInAstObject(recorder, packageJsonAst, dependency.type, {
|
||||
[dependency.name]: dependency.version,
|
||||
}, 4);
|
||||
} else if (depsNode.kind === 'object') {
|
||||
// check if package already added
|
||||
const depNode = findPropertyInAstObject(depsNode, dependency.name);
|
||||
|
||||
if (!depNode) {
|
||||
// Package not found, add it.
|
||||
insertPropertyInAstObjectInOrder(
|
||||
recorder,
|
||||
depsNode,
|
||||
dependency.name,
|
||||
dependency.version,
|
||||
4,
|
||||
);
|
||||
} else if (dependency.overwrite) {
|
||||
// Package found, update version if overwrite.
|
||||
const { end, start } = depNode;
|
||||
recorder.remove(start.offset, end.offset - start.offset);
|
||||
recorder.insertRight(start.offset, JSON.stringify(dependency.version));
|
||||
}
|
||||
}
|
||||
|
||||
tree.commitUpdate(recorder);
|
||||
}
|
||||
|
||||
export function getPackageJsonDependency(tree: Tree, name: string): NodeDependency | null {
|
||||
const packageJson = _readPackageJson(tree);
|
||||
let dep: NodeDependency | null = null;
|
||||
[
|
||||
NodeDependencyType.Default,
|
||||
NodeDependencyType.Dev,
|
||||
NodeDependencyType.Optional,
|
||||
NodeDependencyType.Peer,
|
||||
].forEach(depType => {
|
||||
if (dep !== null) {
|
||||
return;
|
||||
}
|
||||
const depsNode = findPropertyInAstObject(packageJson, depType);
|
||||
if (depsNode !== null && depsNode.kind === 'object') {
|
||||
const depNode = findPropertyInAstObject(depsNode, name);
|
||||
if (depNode !== null && depNode.kind === 'string') {
|
||||
const version = depNode.value;
|
||||
dep = {
|
||||
type: depType,
|
||||
name: name,
|
||||
version: version,
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return dep;
|
||||
}
|
||||
|
||||
function _readPackageJson(tree: Tree): JsonAstObject {
|
||||
const buffer = tree.read(pkgJsonPath);
|
||||
if (buffer === null) {
|
||||
throw new SchematicsException('Could not read package.json.');
|
||||
}
|
||||
const content = buffer.toString();
|
||||
|
||||
const packageJson = parseJsonAst(content, JsonParseMode.Strict);
|
||||
if (packageJson.kind != 'object') {
|
||||
throw new SchematicsException('Invalid package.json. Was expecting an object');
|
||||
}
|
||||
|
||||
return packageJson;
|
||||
}
|
91
packages/schematics/angular/utility/dependencies_spec.ts
Normal file
91
packages/schematics/angular/utility/dependencies_spec.ts
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @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 { EmptyTree } from '@angular-devkit/schematics';
|
||||
import { UnitTestTree } from '@angular-devkit/schematics/testing';
|
||||
import {
|
||||
NodeDependency,
|
||||
NodeDependencyType,
|
||||
addPackageJsonDependency,
|
||||
getPackageJsonDependency,
|
||||
} from './dependencies';
|
||||
|
||||
|
||||
describe('dependencies', () => {
|
||||
describe('addDependency', () => {
|
||||
let tree: UnitTestTree;
|
||||
const pkgJsonPath = '/package.json';
|
||||
let dependency: NodeDependency;
|
||||
beforeEach(() => {
|
||||
tree = new UnitTestTree(new EmptyTree());
|
||||
tree.create(pkgJsonPath, '{}');
|
||||
|
||||
dependency = {
|
||||
type: NodeDependencyType.Default,
|
||||
name: 'my-pkg',
|
||||
version: '1.2.3',
|
||||
};
|
||||
});
|
||||
|
||||
[
|
||||
{ type: NodeDependencyType.Default, key: 'dependencies' },
|
||||
{ type: NodeDependencyType.Dev, key: 'devDependencies' },
|
||||
{ type: NodeDependencyType.Optional, key: 'optionalDependencies' },
|
||||
{ type: NodeDependencyType.Peer, key: 'peerDependencies' },
|
||||
].forEach(type => {
|
||||
describe(`Type: ${type.toString()}`, () => {
|
||||
beforeEach(() => {
|
||||
dependency.type = type.type;
|
||||
});
|
||||
|
||||
it('should add a dependency', () => {
|
||||
addPackageJsonDependency(tree, dependency);
|
||||
const pkgJson = JSON.parse(tree.readContent(pkgJsonPath));
|
||||
expect(pkgJson[type.key][dependency.name]).toEqual(dependency.version);
|
||||
});
|
||||
|
||||
it('should handle an existing dependency (update version)', () => {
|
||||
addPackageJsonDependency(tree, {...dependency, version: '0.0.0'});
|
||||
addPackageJsonDependency(tree, {...dependency, overwrite: true});
|
||||
const pkgJson = JSON.parse(tree.readContent(pkgJsonPath));
|
||||
expect(pkgJson[type.key][dependency.name]).toEqual(dependency.version);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw when missing package.json', () => {
|
||||
expect((() => addPackageJsonDependency(new EmptyTree(), dependency))).toThrow();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getDependency', () => {
|
||||
let tree: UnitTestTree;
|
||||
beforeEach(() => {
|
||||
const pkgJsonPath = '/package.json';
|
||||
const pkgJsonContent = JSON.stringify({
|
||||
dependencies: {
|
||||
'my-pkg': '1.2.3',
|
||||
},
|
||||
}, null, 2);
|
||||
tree = new UnitTestTree(new EmptyTree());
|
||||
tree.create(pkgJsonPath, pkgJsonContent);
|
||||
});
|
||||
|
||||
it('should get a dependency', () => {
|
||||
const dep = getPackageJsonDependency(tree, 'my-pkg') as NodeDependency;
|
||||
expect(dep.type).toEqual(NodeDependencyType.Default);
|
||||
expect(dep.name).toEqual('my-pkg');
|
||||
expect(dep.version).toEqual('1.2.3');
|
||||
});
|
||||
|
||||
it('should return null if dependency does not exist', () => {
|
||||
const dep = getPackageJsonDependency(tree, 'missing-pkg') as NodeDependency;
|
||||
expect(dep).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
@ -5,7 +5,13 @@
|
||||
* 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 { JsonAstArray, JsonAstNode, JsonAstObject, JsonValue } from '@angular-devkit/core';
|
||||
import {
|
||||
JsonAstArray,
|
||||
JsonAstKeyValue,
|
||||
JsonAstNode,
|
||||
JsonAstObject,
|
||||
JsonValue,
|
||||
} from '@angular-devkit/core';
|
||||
import { UpdateRecorder } from '@angular-devkit/schematics';
|
||||
|
||||
export function appendPropertyInAstObject(
|
||||
@ -13,9 +19,9 @@ export function appendPropertyInAstObject(
|
||||
node: JsonAstObject,
|
||||
propertyName: string,
|
||||
value: JsonValue,
|
||||
indent = 4,
|
||||
indent: number,
|
||||
) {
|
||||
const indentStr = '\n' + new Array(indent + 1).join(' ');
|
||||
const indentStr = _buildIndent(indent);
|
||||
|
||||
if (node.properties.length > 0) {
|
||||
// Insert comma.
|
||||
@ -31,6 +37,59 @@ export function appendPropertyInAstObject(
|
||||
);
|
||||
}
|
||||
|
||||
export function insertPropertyInAstObjectInOrder(
|
||||
recorder: UpdateRecorder,
|
||||
node: JsonAstObject,
|
||||
propertyName: string,
|
||||
value: JsonValue,
|
||||
indent: number,
|
||||
) {
|
||||
|
||||
if (node.properties.length === 0) {
|
||||
appendPropertyInAstObject(recorder, node, propertyName, value, indent);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Find insertion info.
|
||||
let insertAfterProp: JsonAstKeyValue | null = null;
|
||||
let prev: JsonAstKeyValue | null = null;
|
||||
let isLastProp = false;
|
||||
const last = node.properties[node.properties.length - 1];
|
||||
for (const prop of node.properties) {
|
||||
if (prop.key.value > propertyName) {
|
||||
if (prev) {
|
||||
insertAfterProp = prev;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (prop === last) {
|
||||
isLastProp = true;
|
||||
insertAfterProp = last;
|
||||
}
|
||||
prev = prop;
|
||||
}
|
||||
|
||||
if (isLastProp) {
|
||||
appendPropertyInAstObject(recorder, node, propertyName, value, indent);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const indentStr = _buildIndent(indent);
|
||||
|
||||
const insertIndex = insertAfterProp === null
|
||||
? node.start.offset + 1
|
||||
: insertAfterProp.end.offset + 1;
|
||||
|
||||
recorder.insertRight(
|
||||
insertIndex,
|
||||
`${indentStr}`
|
||||
+ `"${propertyName}": ${JSON.stringify(value, null, 2).replace(/\n/g, indentStr)}`
|
||||
+ ',',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export function appendValueInAstArray(
|
||||
recorder: UpdateRecorder,
|
||||
@ -38,7 +97,7 @@ export function appendValueInAstArray(
|
||||
value: JsonValue,
|
||||
indent = 4,
|
||||
) {
|
||||
const indentStr = '\n' + new Array(indent + 1).join(' ');
|
||||
const indentStr = _buildIndent(indent);
|
||||
|
||||
if (node.elements.length > 0) {
|
||||
// Insert comma.
|
||||
@ -68,3 +127,7 @@ export function findPropertyInAstObject(
|
||||
|
||||
return maybeNode;
|
||||
}
|
||||
|
||||
function _buildIndent(count: number): string {
|
||||
return '\n' + new Array(count + 1).join(' ');
|
||||
}
|
81
packages/schematics/angular/utility/json-utils_spec.ts
Normal file
81
packages/schematics/angular/utility/json-utils_spec.ts
Normal file
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @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 { parseJsonAst } from '@angular-devkit/core';
|
||||
import { HostTree } from '@angular-devkit/schematics';
|
||||
import { UnitTestTree } from '@angular-devkit/schematics/testing';
|
||||
import { insertPropertyInAstObjectInOrder } from './json-utils';
|
||||
|
||||
type Pojso = {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
describe('json-utils', () => {
|
||||
const filePath = '/temp';
|
||||
let tree: UnitTestTree;
|
||||
beforeEach(() => {
|
||||
tree = new UnitTestTree(new HostTree());
|
||||
});
|
||||
|
||||
describe('insertPropertyInAstObjectInOrder', () => {
|
||||
function runTest(obj: Pojso, prop: string, val: string): Pojso {
|
||||
const content = JSON.stringify(obj, null, 2);
|
||||
tree.create(filePath, content);
|
||||
const ast = parseJsonAst(content);
|
||||
const rec = tree.beginUpdate(filePath);
|
||||
if (ast.kind === 'object') {
|
||||
insertPropertyInAstObjectInOrder(rec, ast, prop, val, 2);
|
||||
}
|
||||
tree.commitUpdate(rec);
|
||||
|
||||
const result = JSON.parse(tree.readContent(filePath));
|
||||
// Clean up the tree by deleting the file.
|
||||
tree.delete(filePath);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
it('should insert a first prop', () => {
|
||||
const obj = {
|
||||
m: 'm',
|
||||
z: 'z',
|
||||
};
|
||||
const result = runTest(obj, 'a', 'val');
|
||||
expect(Object.keys(result)).toEqual(['a', 'm', 'z']);
|
||||
});
|
||||
|
||||
it('should insert a middle prop', () => {
|
||||
const obj = {
|
||||
a: 'a',
|
||||
z: 'z',
|
||||
};
|
||||
const result = runTest(obj, 'm', 'val');
|
||||
expect(Object.keys(result)).toEqual(['a', 'm', 'z']);
|
||||
});
|
||||
|
||||
it('should insert a last prop', () => {
|
||||
const obj = {
|
||||
a: 'a',
|
||||
m: 'm',
|
||||
};
|
||||
const result = runTest(obj, 'z', 'val');
|
||||
expect(Object.keys(result)).toEqual(['a', 'm', 'z']);
|
||||
});
|
||||
|
||||
it('should insert multiple props', () => {
|
||||
let obj = {};
|
||||
obj = runTest(obj, 'z', 'val');
|
||||
expect(Object.keys(obj)).toEqual(['z']);
|
||||
obj = runTest(obj, 'm', 'val');
|
||||
expect(Object.keys(obj)).toEqual(['m', 'z']);
|
||||
obj = runTest(obj, 'a', 'val');
|
||||
expect(Object.keys(obj)).toEqual(['a', 'm', 'z']);
|
||||
obj = runTest(obj, 'b', 'val');
|
||||
expect(Object.keys(obj)).toEqual(['a', 'b', 'm', 'z']);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user