1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | Object.defineProperty(exports, "__esModule", { value: true });
|
10 | const core_1 = require("@angular-devkit/core");
|
11 | const fs_1 = require("fs");
|
12 | const uuid_1 = require("uuid");
|
13 | const command_1 = require("../models/command");
|
14 | const interface_1 = require("../models/interface");
|
15 | const config_1 = require("../utilities/config");
|
16 | function _validateBoolean(value) {
|
17 | if (('' + value).trim() === 'true') {
|
18 | return true;
|
19 | }
|
20 | else if (('' + value).trim() === 'false') {
|
21 | return false;
|
22 | }
|
23 | else {
|
24 | throw new Error(`Invalid value type; expected Boolean, received ${JSON.stringify(value)}.`);
|
25 | }
|
26 | }
|
27 | function _validateNumber(value) {
|
28 | const numberValue = Number(value);
|
29 | if (!Number.isFinite(numberValue)) {
|
30 | return numberValue;
|
31 | }
|
32 | throw new Error(`Invalid value type; expected Number, received ${JSON.stringify(value)}.`);
|
33 | }
|
34 | function _validateString(value) {
|
35 | return value;
|
36 | }
|
37 | function _validateAnalytics(value) {
|
38 | if (value === '') {
|
39 |
|
40 | return null;
|
41 | }
|
42 | else {
|
43 | return value;
|
44 | }
|
45 | }
|
46 | function _validateAnalyticsSharingUuid(value) {
|
47 | if (value == '') {
|
48 | return uuid_1.v4();
|
49 | }
|
50 | else {
|
51 | return value;
|
52 | }
|
53 | }
|
54 | function _validateAnalyticsSharingTracking(value) {
|
55 | if (!value.match(/^GA-\d+-\d+$/)) {
|
56 | throw new Error(`Invalid GA property ID: ${JSON.stringify(value)}.`);
|
57 | }
|
58 | return value;
|
59 | }
|
60 | const validCliPaths = new Map([
|
61 | ['cli.warnings.versionMismatch', _validateBoolean],
|
62 | ['cli.defaultCollection', _validateString],
|
63 | ['cli.packageManager', _validateString],
|
64 | ['cli.analytics', _validateAnalytics],
|
65 | ['cli.analyticsSharing.tracking', _validateAnalyticsSharingTracking],
|
66 | ['cli.analyticsSharing.uuid', _validateAnalyticsSharingUuid],
|
67 | ]);
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 | function parseJsonPath(path) {
|
77 | const fragments = (path || '').split(/\./g);
|
78 | const result = [];
|
79 | while (fragments.length > 0) {
|
80 | const fragment = fragments.shift();
|
81 | if (fragment == undefined) {
|
82 | break;
|
83 | }
|
84 | const match = fragment.match(/([^\[]+)((\[.*\])*)/);
|
85 | if (!match) {
|
86 | throw new Error('Invalid JSON path.');
|
87 | }
|
88 | result.push(match[1]);
|
89 | if (match[2]) {
|
90 | const indices = match[2]
|
91 | .slice(1, -1)
|
92 | .split('][')
|
93 | .map(x => (/^\d$/.test(x) ? +x : x.replace(/\"|\'/g, '')));
|
94 | result.push(...indices);
|
95 | }
|
96 | }
|
97 | return result.filter(fragment => fragment != null);
|
98 | }
|
99 | function getValueFromPath(root, path) {
|
100 | const fragments = parseJsonPath(path);
|
101 | try {
|
102 | return fragments.reduce((value, current) => {
|
103 | if (value == undefined || typeof value != 'object') {
|
104 | return undefined;
|
105 | }
|
106 | else if (typeof current == 'string' && !Array.isArray(value)) {
|
107 | return value[current];
|
108 | }
|
109 | else if (typeof current == 'number' && Array.isArray(value)) {
|
110 | return value[current];
|
111 | }
|
112 | else {
|
113 | return undefined;
|
114 | }
|
115 | }, root);
|
116 | }
|
117 | catch (_a) {
|
118 | return undefined;
|
119 | }
|
120 | }
|
121 | function setValueFromPath(root, path, newValue) {
|
122 | const fragments = parseJsonPath(path);
|
123 | try {
|
124 | return fragments.reduce((value, current, index) => {
|
125 | if (value == undefined || typeof value != 'object') {
|
126 | return undefined;
|
127 | }
|
128 | else if (typeof current == 'string' && !Array.isArray(value)) {
|
129 | if (index === fragments.length - 1) {
|
130 | value[current] = newValue;
|
131 | }
|
132 | else if (value[current] == undefined) {
|
133 | if (typeof fragments[index + 1] == 'number') {
|
134 | value[current] = [];
|
135 | }
|
136 | else if (typeof fragments[index + 1] == 'string') {
|
137 | value[current] = {};
|
138 | }
|
139 | }
|
140 | return value[current];
|
141 | }
|
142 | else if (typeof current == 'number' && Array.isArray(value)) {
|
143 | if (index === fragments.length - 1) {
|
144 | value[current] = newValue;
|
145 | }
|
146 | else if (value[current] == undefined) {
|
147 | if (typeof fragments[index + 1] == 'number') {
|
148 | value[current] = [];
|
149 | }
|
150 | else if (typeof fragments[index + 1] == 'string') {
|
151 | value[current] = {};
|
152 | }
|
153 | }
|
154 | return value[current];
|
155 | }
|
156 | else {
|
157 | return undefined;
|
158 | }
|
159 | }, root);
|
160 | }
|
161 | catch (_a) {
|
162 | return undefined;
|
163 | }
|
164 | }
|
165 | function normalizeValue(value, path) {
|
166 | const cliOptionType = validCliPaths.get(path);
|
167 | if (cliOptionType) {
|
168 | return cliOptionType('' + value);
|
169 | }
|
170 | if (typeof value === 'string') {
|
171 | try {
|
172 | return core_1.parseJson(value, core_1.JsonParseMode.Loose);
|
173 | }
|
174 | catch (e) {
|
175 | if (e instanceof core_1.InvalidJsonCharacterException && !value.startsWith('{')) {
|
176 | return value;
|
177 | }
|
178 | else {
|
179 | throw e;
|
180 | }
|
181 | }
|
182 | }
|
183 | return value;
|
184 | }
|
185 | class ConfigCommand extends command_1.Command {
|
186 | async run(options) {
|
187 | const level = options.global ? 'global' : 'local';
|
188 | if (!options.global) {
|
189 | await this.validateScope(interface_1.CommandScope.InProject);
|
190 | }
|
191 | let config = await config_1.getWorkspace(level);
|
192 | if (options.global && !config) {
|
193 | try {
|
194 | if (config_1.migrateLegacyGlobalConfig()) {
|
195 | config = await config_1.getWorkspace(level);
|
196 | this.logger.info(core_1.tags.oneLine `
|
197 | We found a global configuration that was used in Angular CLI 1.
|
198 | It has been automatically migrated.`);
|
199 | }
|
200 | }
|
201 | catch (_a) { }
|
202 | }
|
203 | if (options.value == undefined) {
|
204 | if (!config) {
|
205 | this.logger.error('No config found.');
|
206 | return 1;
|
207 | }
|
208 | const workspace = config
|
209 | ._workspace;
|
210 | return this.get(workspace, options);
|
211 | }
|
212 | else {
|
213 | return this.set(options);
|
214 | }
|
215 | }
|
216 | get(config, options) {
|
217 | let value;
|
218 | if (options.jsonPath) {
|
219 | if (options.jsonPath === 'cli.warnings.typescriptMismatch') {
|
220 |
|
221 | this.logger.warn('The "typescriptMismatch" warning has been removed in 8.0.');
|
222 |
|
223 | this.logger.info('false');
|
224 | return 0;
|
225 | }
|
226 | value = getValueFromPath(config, options.jsonPath);
|
227 | }
|
228 | else {
|
229 | value = config;
|
230 | }
|
231 | if (value === undefined) {
|
232 | this.logger.error('Value cannot be found.');
|
233 | return 1;
|
234 | }
|
235 | else if (typeof value == 'object') {
|
236 | this.logger.info(JSON.stringify(value, null, 2));
|
237 | }
|
238 | else {
|
239 | this.logger.info(value.toString());
|
240 | }
|
241 | return 0;
|
242 | }
|
243 | async set(options) {
|
244 | if (!options.jsonPath || !options.jsonPath.trim()) {
|
245 | throw new Error('Invalid Path.');
|
246 | }
|
247 | if (options.jsonPath === 'cli.warnings.typescriptMismatch') {
|
248 |
|
249 | this.logger.warn('The "typescriptMismatch" warning has been removed in 8.0.');
|
250 | return 0;
|
251 | }
|
252 | if (options.global &&
|
253 | !options.jsonPath.startsWith('schematics.') &&
|
254 | !validCliPaths.has(options.jsonPath)) {
|
255 | throw new Error('Invalid Path.');
|
256 | }
|
257 | const [config, configPath] = config_1.getWorkspaceRaw(options.global ? 'global' : 'local');
|
258 | if (!config || !configPath) {
|
259 | this.logger.error('Confguration file cannot be found.');
|
260 | return 1;
|
261 | }
|
262 |
|
263 | const configValue = config.value;
|
264 | const value = normalizeValue(options.value || '', options.jsonPath);
|
265 | const result = setValueFromPath(configValue, options.jsonPath, value);
|
266 | if (result === undefined) {
|
267 | this.logger.error('Value cannot be found.');
|
268 | return 1;
|
269 | }
|
270 | try {
|
271 | await config_1.validateWorkspace(configValue);
|
272 | }
|
273 | catch (error) {
|
274 | this.logger.fatal(error.message);
|
275 | return 1;
|
276 | }
|
277 | const output = JSON.stringify(configValue, null, 2);
|
278 | fs_1.writeFileSync(configPath, output);
|
279 | return 0;
|
280 | }
|
281 | }
|
282 | exports.ConfigCommand = ConfigCommand;
|