@angular/cli
Version:
CLI tool for Angular
225 lines • 7.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@angular-devkit/core");
const fs_1 = require("fs");
const command_1 = require("../models/command");
const config_1 = require("../utilities/config");
const SilentError = require('silent-error');
const validCliPaths = new Map([
['cli.warnings.versionMismatch', 'boolean'],
['cli.warnings.typescriptMismatch', 'boolean'],
['cli.defaultCollection', 'string'],
['cli.packageManager', 'string'],
]);
/**
* Splits a JSON path string into fragments. Fragments can be used to get the value referenced
* by the path. For example, a path of "a[3].foo.bar[2]" would give you a fragment array of
* ["a", 3, "foo", "bar", 2].
* @param path The JSON string to parse.
* @returns {string[]} The fragments for the string.
* @private
*/
function parseJsonPath(path) {
const fragments = (path || '').split(/\./g);
const result = [];
while (fragments.length > 0) {
const fragment = fragments.shift();
const match = fragment.match(/([^\[]+)((\[.*\])*)/);
if (!match) {
throw new Error('Invalid JSON path.');
}
result.push(match[1]);
if (match[2]) {
const indices = match[2].slice(1, -1).split('][');
result.push(...indices);
}
}
return result.filter(fragment => !!fragment);
}
function getValueFromPath(root, path) {
const fragments = parseJsonPath(path);
try {
return fragments.reduce((value, current) => {
if (value == undefined || typeof value != 'object') {
return undefined;
}
else if (typeof current == 'string' && !Array.isArray(value)) {
return value[current];
}
else if (typeof current == 'number' && Array.isArray(value)) {
return value[current];
}
else {
return undefined;
}
}, root);
}
catch (_a) {
return undefined;
}
}
function setValueFromPath(root, path, newValue) {
const fragments = parseJsonPath(path);
try {
return fragments.reduce((value, current, index) => {
if (value == undefined || typeof value != 'object') {
return undefined;
}
else if (typeof current == 'string' && !Array.isArray(value)) {
if (index === fragments.length - 1) {
value[current] = newValue;
}
else if (value[current] == undefined) {
if (typeof fragments[index + 1] == 'number') {
value[current] = [];
}
else if (typeof fragments[index + 1] == 'string') {
value[current] = {};
}
}
return value[current];
}
else if (typeof current == 'number' && Array.isArray(value)) {
if (index === fragments.length - 1) {
value[current] = newValue;
}
else if (value[current] == undefined) {
if (typeof fragments[index + 1] == 'number') {
value[current] = [];
}
else if (typeof fragments[index + 1] == 'string') {
value[current] = {};
}
}
return value[current];
}
else {
return undefined;
}
}, root);
}
catch (_a) {
return undefined;
}
}
function normalizeValue(value, path) {
const cliOptionType = validCliPaths.get(path);
if (cliOptionType) {
switch (cliOptionType) {
case 'boolean':
if (value.trim() === 'true') {
return true;
}
else if (value.trim() === 'false') {
return false;
}
break;
case 'number':
const numberValue = Number(value);
if (!Number.isNaN(numberValue)) {
return numberValue;
}
break;
case 'string':
return value;
}
throw new Error(`Invalid value type; expected a ${cliOptionType}.`);
}
if (typeof value === 'string') {
try {
return core_1.parseJson(value, core_1.JsonParseMode.Loose);
}
catch (e) {
if (e instanceof core_1.InvalidJsonCharacterException && !value.startsWith('{')) {
return value;
}
else {
throw e;
}
}
}
return value;
}
class ConfigCommand extends command_1.Command {
constructor() {
super(...arguments);
this.name = 'config';
this.description = 'Get/set configuration values.';
this.arguments = ['jsonPath', 'value'];
this.options = [
{
name: 'global',
type: Boolean,
'default': false,
aliases: ['g'],
description: 'Get/set the value in the global configuration (in your home directory).'
}
];
}
run(options) {
const level = options.global ? 'global' : 'local';
let config = config_1.getWorkspace(level);
if (options.global && !config) {
try {
if (config_1.migrateLegacyGlobalConfig()) {
config =
config_1.getWorkspace(level);
this.logger.info(core_1.tags.oneLine `
We found a global configuration that was used in Angular CLI 1.
It has been automatically migrated.`);
}
}
catch (_a) { }
}
if (options.value == undefined) {
if (!config) {
throw new SilentError('No config found.');
}
this.get(config._workspace, options);
}
else {
this.set(options);
}
}
get(config, options) {
const value = options.jsonPath ? getValueFromPath(config, options.jsonPath) : config;
if (value === undefined) {
throw new SilentError('Value cannot be found.');
}
else if (typeof value == 'object') {
this.logger.info(JSON.stringify(value, null, 2));
}
else {
this.logger.info(value.toString());
}
}
set(options) {
if (!options.jsonPath || !options.jsonPath.trim()) {
throw new Error('Invalid Path.');
}
if (options.global
&& !options.jsonPath.startsWith('schematics.')
&& !validCliPaths.has(options.jsonPath)) {
throw new Error('Invalid Path.');
}
const [config, configPath] = config_1.getWorkspaceRaw(options.global ? 'global' : 'local');
// TODO: Modify & save without destroying comments
const configValue = config.value;
const value = normalizeValue(options.value, options.jsonPath);
const result = setValueFromPath(configValue, options.jsonPath, value);
if (result === undefined) {
throw new SilentError('Value cannot be found.');
}
try {
config_1.validateWorkspace(configValue);
}
catch (error) {
this.logger.error(error.message);
throw new SilentError();
}
const output = JSON.stringify(configValue, null, 2);
fs_1.writeFileSync(configPath, output);
}
}
exports.default = ConfigCommand;
//# sourceMappingURL=/Users/hansl/Sources/hansl/angular-cli/commands/config.js.map