1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | const core_1 = require("@angular-devkit/core");
|
12 | const interface_1 = require("./interface");
|
13 | class ParseArgumentException extends core_1.BaseException {
|
14 | constructor(comments, parsed, ignored) {
|
15 | super(`One or more errors occurred while parsing arguments:\n ${comments.join('\n ')}`);
|
16 | this.comments = comments;
|
17 | this.parsed = parsed;
|
18 | this.ignored = ignored;
|
19 | }
|
20 | }
|
21 | exports.ParseArgumentException = ParseArgumentException;
|
22 | function _coerceType(str, type, v) {
|
23 | switch (type) {
|
24 | case interface_1.OptionType.Any:
|
25 | if (Array.isArray(v)) {
|
26 | return v.concat(str || '');
|
27 | }
|
28 | return _coerceType(str, interface_1.OptionType.Boolean, v) !== undefined
|
29 | ? _coerceType(str, interface_1.OptionType.Boolean, v)
|
30 | : _coerceType(str, interface_1.OptionType.Number, v) !== undefined
|
31 | ? _coerceType(str, interface_1.OptionType.Number, v)
|
32 | : _coerceType(str, interface_1.OptionType.String, v);
|
33 | case interface_1.OptionType.String:
|
34 | return str || '';
|
35 | case interface_1.OptionType.Boolean:
|
36 | switch (str) {
|
37 | case 'false':
|
38 | return false;
|
39 | case undefined:
|
40 | case '':
|
41 | case 'true':
|
42 | return true;
|
43 | default:
|
44 | return undefined;
|
45 | }
|
46 | case interface_1.OptionType.Number:
|
47 | if (str === undefined) {
|
48 | return 0;
|
49 | }
|
50 | else if (str === '') {
|
51 | return undefined;
|
52 | }
|
53 | else if (Number.isFinite(+str)) {
|
54 | return +str;
|
55 | }
|
56 | else {
|
57 | return undefined;
|
58 | }
|
59 | case interface_1.OptionType.Array:
|
60 | return Array.isArray(v)
|
61 | ? v.concat(str || '')
|
62 | : v === undefined
|
63 | ? [str || '']
|
64 | : [v + '', str || ''];
|
65 | default:
|
66 | return undefined;
|
67 | }
|
68 | }
|
69 | function _coerce(str, o, v) {
|
70 | if (!o) {
|
71 | return _coerceType(str, interface_1.OptionType.Any, v);
|
72 | }
|
73 | else {
|
74 | const types = o.types || [o.type];
|
75 |
|
76 |
|
77 | for (const type of types) {
|
78 | const maybeResult = _coerceType(str, type, v);
|
79 | if (maybeResult !== undefined && (!o.enum || o.enum.includes(maybeResult))) {
|
80 | return maybeResult;
|
81 | }
|
82 | }
|
83 | return undefined;
|
84 | }
|
85 | }
|
86 | function _getOptionFromName(name, options) {
|
87 | const camelName = /(-|_)/.test(name)
|
88 | ? core_1.strings.camelize(name)
|
89 | : name;
|
90 | for (const option of options) {
|
91 | if (option.name === name || option.name === camelName) {
|
92 | return option;
|
93 | }
|
94 | if (option.aliases.some(x => x === name || x === camelName)) {
|
95 | return option;
|
96 | }
|
97 | }
|
98 | return undefined;
|
99 | }
|
100 | function _removeLeadingDashes(key) {
|
101 | const from = key.startsWith('--') ? 2 : key.startsWith('-') ? 1 : 0;
|
102 | return key.substr(from);
|
103 | }
|
104 | function _assignOption(arg, nextArg, { options, parsedOptions, leftovers, ignored, errors, warnings }) {
|
105 | const from = arg.startsWith('--') ? 2 : 1;
|
106 | let consumedNextArg = false;
|
107 | let key = arg.substr(from);
|
108 | let option = null;
|
109 | let value = '';
|
110 | const i = arg.indexOf('=');
|
111 |
|
112 | if (i == -1) {
|
113 | if (key.startsWith('no')) {
|
114 |
|
115 | const from = key.startsWith('no-') ? 3 : 2;
|
116 | const maybeOption = _getOptionFromName(core_1.strings.camelize(key.substr(from)), options);
|
117 | if (maybeOption && maybeOption.type == 'boolean') {
|
118 | value = 'false';
|
119 | option = maybeOption;
|
120 | }
|
121 | }
|
122 | if (option === null) {
|
123 |
|
124 | const maybeOption = _getOptionFromName(key, options);
|
125 | if (maybeOption) {
|
126 | value = nextArg;
|
127 | let shouldShift = true;
|
128 | if (value && value.startsWith('-') && _coerce(undefined, maybeOption) !== undefined) {
|
129 |
|
130 | shouldShift = false;
|
131 | }
|
132 |
|
133 | if (shouldShift && _coerce(value, maybeOption) !== undefined) {
|
134 | consumedNextArg = true;
|
135 | }
|
136 | else {
|
137 | value = '';
|
138 | }
|
139 | option = maybeOption;
|
140 | }
|
141 | }
|
142 | }
|
143 | else {
|
144 | key = arg.substring(0, i);
|
145 | option = _getOptionFromName(_removeLeadingDashes(key), options) || null;
|
146 | if (option) {
|
147 | value = arg.substring(i + 1);
|
148 | }
|
149 | }
|
150 | if (option === null) {
|
151 | if (nextArg && !nextArg.startsWith('-')) {
|
152 | leftovers.push(arg, nextArg);
|
153 | consumedNextArg = true;
|
154 | }
|
155 | else {
|
156 | leftovers.push(arg);
|
157 | }
|
158 | }
|
159 | else {
|
160 | const v = _coerce(value, option, parsedOptions[option.name]);
|
161 | if (v !== undefined) {
|
162 | if (parsedOptions[option.name] !== v) {
|
163 | if (parsedOptions[option.name] !== undefined && option.type !== interface_1.OptionType.Array) {
|
164 | warnings.push(`Option ${JSON.stringify(option.name)} was already specified with value `
|
165 | + `${JSON.stringify(parsedOptions[option.name])}. The new value ${JSON.stringify(v)} `
|
166 | + `will override it.`);
|
167 | }
|
168 | parsedOptions[option.name] = v;
|
169 | if (option.deprecated !== undefined && option.deprecated !== false) {
|
170 | warnings.push(`Option ${JSON.stringify(option.name)} is deprecated${typeof option.deprecated == 'string' ? ': ' + option.deprecated : '.'}`);
|
171 | }
|
172 | }
|
173 | }
|
174 | else {
|
175 | let error = `Argument ${key} could not be parsed using value ${JSON.stringify(value)}.`;
|
176 | if (option.enum) {
|
177 | error += ` Valid values are: ${option.enum.map(x => JSON.stringify(x)).join(', ')}.`;
|
178 | }
|
179 | else {
|
180 | error += `Valid type(s) is: ${(option.types || [option.type]).join(', ')}`;
|
181 | }
|
182 | errors.push(error);
|
183 | ignored.push(arg);
|
184 | }
|
185 | }
|
186 | return consumedNextArg;
|
187 | }
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 | function parseFreeFormArguments(args) {
|
199 | const parsedOptions = {};
|
200 | const leftovers = [];
|
201 | for (let arg = args.shift(); arg !== undefined; arg = args.shift()) {
|
202 | if (arg == '--') {
|
203 | leftovers.push(...args);
|
204 | break;
|
205 | }
|
206 | if (arg.startsWith('--')) {
|
207 | const eqSign = arg.indexOf('=');
|
208 | let name;
|
209 | let value;
|
210 | if (eqSign !== -1) {
|
211 | name = arg.substring(2, eqSign);
|
212 | value = arg.substring(eqSign + 1);
|
213 | }
|
214 | else {
|
215 | name = arg.substr(2);
|
216 | value = args.shift();
|
217 | }
|
218 | const v = _coerce(value, null, parsedOptions[name]);
|
219 | if (v !== undefined) {
|
220 | parsedOptions[name] = v;
|
221 | }
|
222 | }
|
223 | else if (arg.startsWith('-')) {
|
224 | arg.split('').forEach(x => parsedOptions[x] = true);
|
225 | }
|
226 | else {
|
227 | leftovers.push(arg);
|
228 | }
|
229 | }
|
230 | if (leftovers.length) {
|
231 | parsedOptions['--'] = leftovers;
|
232 | }
|
233 | return parsedOptions;
|
234 | }
|
235 | exports.parseFreeFormArguments = parseFreeFormArguments;
|
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 |
|
248 | function parseArguments(args, options, logger) {
|
249 | if (options === null) {
|
250 | options = [];
|
251 | }
|
252 | const leftovers = [];
|
253 | const positionals = [];
|
254 | const parsedOptions = {};
|
255 | const ignored = [];
|
256 | const errors = [];
|
257 | const warnings = [];
|
258 | const state = { options, parsedOptions, positionals, leftovers, ignored, errors, warnings };
|
259 | for (let argIndex = 0; argIndex < args.length; argIndex++) {
|
260 | const arg = args[argIndex];
|
261 | let consumedNextArg = false;
|
262 | if (arg == '--') {
|
263 |
|
264 | leftovers.push(...args.slice(argIndex + 1));
|
265 | break;
|
266 | }
|
267 | if (arg.startsWith('--')) {
|
268 | consumedNextArg = _assignOption(arg, args[argIndex + 1], state);
|
269 | }
|
270 | else if (arg.startsWith('-')) {
|
271 |
|
272 | for (let i = 1; i < arg.length; i++) {
|
273 | const flag = arg[i];
|
274 |
|
275 | if (arg[i + 1] == '=') {
|
276 | const f = '-' + flag + arg.slice(i + 1);
|
277 | consumedNextArg = _assignOption(f, args[argIndex + 1], state);
|
278 | break;
|
279 | }
|
280 |
|
281 |
|
282 | if (i == arg.length - 1) {
|
283 | const arg = '-' + flag;
|
284 | consumedNextArg = _assignOption(arg, args[argIndex + 1], state);
|
285 | }
|
286 | else {
|
287 | const maybeOption = _getOptionFromName(flag, options);
|
288 | if (maybeOption) {
|
289 | const v = _coerce(undefined, maybeOption, parsedOptions[maybeOption.name]);
|
290 | if (v !== undefined) {
|
291 | parsedOptions[maybeOption.name] = v;
|
292 | }
|
293 | }
|
294 | }
|
295 | }
|
296 | }
|
297 | else {
|
298 | positionals.push(arg);
|
299 | }
|
300 | if (consumedNextArg) {
|
301 | argIndex++;
|
302 | }
|
303 | }
|
304 |
|
305 |
|
306 |
|
307 | if (positionals.length > 0) {
|
308 | let pos = 0;
|
309 | for (let i = 0; i < positionals.length;) {
|
310 | let found = false;
|
311 | let incrementPos = false;
|
312 | let incrementI = true;
|
313 |
|
314 | for (const option of options) {
|
315 |
|
316 | if (option.positional === pos) {
|
317 | const coercedValue = _coerce(positionals[i], option, parsedOptions[option.name]);
|
318 | if (parsedOptions[option.name] === undefined && coercedValue !== undefined) {
|
319 | parsedOptions[option.name] = coercedValue;
|
320 | found = true;
|
321 | }
|
322 | else {
|
323 | incrementI = false;
|
324 | }
|
325 | incrementPos = true;
|
326 | }
|
327 | }
|
328 | if (found) {
|
329 | positionals.splice(i--, 1);
|
330 | }
|
331 | if (incrementPos) {
|
332 | pos++;
|
333 | }
|
334 | if (incrementI) {
|
335 | i++;
|
336 | }
|
337 | }
|
338 | }
|
339 | if (positionals.length > 0 || leftovers.length > 0) {
|
340 | parsedOptions['--'] = [...positionals, ...leftovers];
|
341 | }
|
342 | if (warnings.length > 0 && logger) {
|
343 | warnings.forEach(message => logger.warn(message));
|
344 | }
|
345 | if (errors.length > 0) {
|
346 | throw new ParseArgumentException(errors, parsedOptions, ignored);
|
347 | }
|
348 | return parsedOptions;
|
349 | }
|
350 | exports.parseArguments = parseArguments;
|