UNPKG

7.83 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const core_1 = require("@angular-devkit/core");
4const fs_1 = require("fs");
5const command_1 = require("../models/command");
6const config_1 = require("../utilities/config");
7const SilentError = require('silent-error');
8const validCliPaths = new Map([
9 ['cli.warnings.versionMismatch', 'boolean'],
10 ['cli.warnings.typescriptMismatch', 'boolean'],
11 ['cli.defaultCollection', 'string'],
12 ['cli.packageManager', 'string'],
13]);
14/**
15 * Splits a JSON path string into fragments. Fragments can be used to get the value referenced
16 * by the path. For example, a path of "a[3].foo.bar[2]" would give you a fragment array of
17 * ["a", 3, "foo", "bar", 2].
18 * @param path The JSON string to parse.
19 * @returns {string[]} The fragments for the string.
20 * @private
21 */
22function parseJsonPath(path) {
23 const fragments = (path || '').split(/\./g);
24 const result = [];
25 while (fragments.length > 0) {
26 const fragment = fragments.shift();
27 const match = fragment.match(/([^\[]+)((\[.*\])*)/);
28 if (!match) {
29 throw new Error('Invalid JSON path.');
30 }
31 result.push(match[1]);
32 if (match[2]) {
33 const indices = match[2].slice(1, -1).split('][');
34 result.push(...indices);
35 }
36 }
37 return result.filter(fragment => !!fragment);
38}
39function getValueFromPath(root, path) {
40 const fragments = parseJsonPath(path);
41 try {
42 return fragments.reduce((value, current) => {
43 if (value == undefined || typeof value != 'object') {
44 return undefined;
45 }
46 else if (typeof current == 'string' && !Array.isArray(value)) {
47 return value[current];
48 }
49 else if (typeof current == 'number' && Array.isArray(value)) {
50 return value[current];
51 }
52 else {
53 return undefined;
54 }
55 }, root);
56 }
57 catch (_a) {
58 return undefined;
59 }
60}
61function setValueFromPath(root, path, newValue) {
62 const fragments = parseJsonPath(path);
63 try {
64 return fragments.reduce((value, current, index) => {
65 if (value == undefined || typeof value != 'object') {
66 return undefined;
67 }
68 else if (typeof current == 'string' && !Array.isArray(value)) {
69 if (index === fragments.length - 1) {
70 value[current] = newValue;
71 }
72 else if (value[current] == undefined) {
73 if (typeof fragments[index + 1] == 'number') {
74 value[current] = [];
75 }
76 else if (typeof fragments[index + 1] == 'string') {
77 value[current] = {};
78 }
79 }
80 return value[current];
81 }
82 else if (typeof current == 'number' && Array.isArray(value)) {
83 if (index === fragments.length - 1) {
84 value[current] = newValue;
85 }
86 else if (value[current] == undefined) {
87 if (typeof fragments[index + 1] == 'number') {
88 value[current] = [];
89 }
90 else if (typeof fragments[index + 1] == 'string') {
91 value[current] = {};
92 }
93 }
94 return value[current];
95 }
96 else {
97 return undefined;
98 }
99 }, root);
100 }
101 catch (_a) {
102 return undefined;
103 }
104}
105function normalizeValue(value, path) {
106 const cliOptionType = validCliPaths.get(path);
107 if (cliOptionType) {
108 switch (cliOptionType) {
109 case 'boolean':
110 if (value.trim() === 'true') {
111 return true;
112 }
113 else if (value.trim() === 'false') {
114 return false;
115 }
116 break;
117 case 'number':
118 const numberValue = Number(value);
119 if (!Number.isNaN(numberValue)) {
120 return numberValue;
121 }
122 break;
123 case 'string':
124 return value;
125 }
126 throw new Error(`Invalid value type; expected a ${cliOptionType}.`);
127 }
128 if (typeof value === 'string') {
129 try {
130 return core_1.parseJson(value, core_1.JsonParseMode.Loose);
131 }
132 catch (e) {
133 if (e instanceof core_1.InvalidJsonCharacterException && !value.startsWith('{')) {
134 return value;
135 }
136 else {
137 throw e;
138 }
139 }
140 }
141 return value;
142}
143class ConfigCommand extends command_1.Command {
144 constructor() {
145 super(...arguments);
146 this.name = 'config';
147 this.description = 'Get/set configuration values.';
148 this.arguments = ['jsonPath', 'value'];
149 this.options = [
150 {
151 name: 'global',
152 type: Boolean,
153 'default': false,
154 aliases: ['g'],
155 description: 'Get/set the value in the global configuration (in your home directory).'
156 }
157 ];
158 }
159 run(options) {
160 const level = options.global ? 'global' : 'local';
161 let config = config_1.getWorkspace(level);
162 if (options.global && !config) {
163 try {
164 if (config_1.migrateLegacyGlobalConfig()) {
165 config =
166 config_1.getWorkspace(level);
167 this.logger.info(core_1.tags.oneLine `
168 We found a global configuration that was used in Angular CLI 1.
169 It has been automatically migrated.`);
170 }
171 }
172 catch (_a) { }
173 }
174 if (options.value == undefined) {
175 if (!config) {
176 throw new SilentError('No config found.');
177 }
178 this.get(config._workspace, options);
179 }
180 else {
181 this.set(options);
182 }
183 }
184 get(config, options) {
185 const value = options.jsonPath ? getValueFromPath(config, options.jsonPath) : config;
186 if (value === undefined) {
187 throw new SilentError('Value cannot be found.');
188 }
189 else if (typeof value == 'object') {
190 this.logger.info(JSON.stringify(value, null, 2));
191 }
192 else {
193 this.logger.info(value.toString());
194 }
195 }
196 set(options) {
197 if (!options.jsonPath || !options.jsonPath.trim()) {
198 throw new Error('Invalid Path.');
199 }
200 if (options.global
201 && !options.jsonPath.startsWith('schematics.')
202 && !validCliPaths.has(options.jsonPath)) {
203 throw new Error('Invalid Path.');
204 }
205 const [config, configPath] = config_1.getWorkspaceRaw(options.global ? 'global' : 'local');
206 // TODO: Modify & save without destroying comments
207 const configValue = config.value;
208 const value = normalizeValue(options.value, options.jsonPath);
209 const result = setValueFromPath(configValue, options.jsonPath, value);
210 if (result === undefined) {
211 throw new SilentError('Value cannot be found.');
212 }
213 try {
214 config_1.validateWorkspace(configValue);
215 }
216 catch (error) {
217 this.logger.error(error.message);
218 throw new SilentError();
219 }
220 const output = JSON.stringify(configValue, null, 2);
221 fs_1.writeFileSync(configPath, output);
222 }
223}
224exports.default = ConfigCommand;
225//# sourceMappingURL=/Users/hansl/Sources/hansl/angular-cli/commands/config.js.map
\No newline at end of file