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