UNPKG

23.1 kBJavaScriptView Raw
1'use strict';
2
3function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
4
5var events = _interopDefault(require('events'));
6var path = _interopDefault(require('path'));
7
8var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
9
10function unwrapExports (x) {
11 return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x.default : x;
12}
13
14function createCommonjsModule(fn, module) {
15 return module = { exports: {} }, fn(module, module.exports), module.exports;
16}
17
18const EQQ = /\s|=/;
19const FLAG = /^-{1,2}/;
20const PREFIX = /^--no-/i;
21
22function isBool(any) {
23 return typeof any === 'boolean';
24}
25
26function toArr(any) {
27 return Array.isArray(any) ? any : any == null ? [] : [any];
28}
29
30function toString(any) {
31 return any == null || any === true ? '' : String(any);
32}
33
34function toBool(any) {
35 return any === 'false' ? false : Boolean(any);
36}
37
38function toNum(any) {
39 let x = Number(any);
40 return !isBool(any) && (x * 0 === 0) ? x : any;
41}
42
43function getAlibi(names, arr) {
44 if (arr.length === 0) return arr;
45 let k, i = 0, len = arr.length, vals = [];
46 for (; i < len; i++) {
47 k = arr[i];
48 vals.push(k);
49 if (names[k] !== void 0) {
50 vals = vals.concat(names[k]);
51 }
52 }
53 return vals;
54}
55
56function typecast(key, val, strings, booleans) {
57 if (strings.indexOf(key) !== -1) return toString(val);
58 if (booleans.indexOf(key) !== -1) return toBool(val);
59 return toNum(val);
60}
61
62var lib = function(args, opts) {
63 args = args || [];
64 opts = opts || {};
65
66 opts.string = toArr(opts.string);
67 opts.boolean = toArr(opts.boolean);
68
69 const aliases = {};
70 let k, i, j, x, y, len, type;
71
72 if (opts.alias !== void 0) {
73 for (k in opts.alias) {
74 aliases[k] = toArr(opts.alias[k]);
75 len = aliases[k].length; // save length
76 for (i = 0; i < len; i++) {
77 x = aliases[k][i]; // alias's key name
78 aliases[x] = [k]; // set initial array
79 for (j = 0; j < len; j++) {
80 if (x !== aliases[k][j]) {
81 aliases[x].push(aliases[k][j]);
82 }
83 }
84 }
85 }
86 }
87
88 if (opts.default !== void 0) {
89 for (k in opts.default) {
90 type = typeof opts.default[k];
91 opts[type] = (opts[type] || []).concat(k);
92 }
93 }
94
95 // apply to all aliases
96 opts.string = getAlibi(aliases, opts.string);
97 opts.boolean = getAlibi(aliases, opts.boolean);
98
99 let idx = 0;
100 const out = { _: [] };
101
102 while (args[idx] !== void 0) {
103 let incr = 1;
104 const val = args[idx];
105
106 if (val === '--') {
107 out._ = out._.concat(args.slice(idx + 1));
108 break;
109 } else if (!FLAG.test(val)) {
110 out._.push(val);
111 } else if (PREFIX.test(val)) {
112 out[val.replace(PREFIX, '')] = false;
113 } else {
114 let tmp;
115 const segs = val.split(EQQ);
116 const isGroup = segs[0].charCodeAt(1) !== 45; // '-'
117
118 const flag = segs[0].substr(isGroup ? 1 : 2);
119 len = flag.length;
120 const key = isGroup ? flag[len - 1] : flag;
121
122 if (opts.unknown !== void 0 && aliases[key] === void 0) {
123 return opts.unknown(segs[0]);
124 }
125
126 if (segs.length > 1) {
127 tmp = segs[1];
128 } else {
129 tmp = args[idx + 1] || true;
130 FLAG.test(tmp) ? (tmp = true) : (incr = 2);
131 }
132
133 if (isGroup && len > 1) {
134 for (i = len - 1; i--; ) {
135 k = flag[i]; // all but last key
136 out[k] = typecast(k, true, opts.string, opts.boolean);
137 }
138 }
139
140 const value = typecast(key, tmp, opts.string, opts.boolean);
141 out[key] = out[key] !== void 0 ? toArr(out[key]).concat(value) : value;
142
143 // handle discarded args when dealing with booleans
144 if (isBool(value) && !isBool(tmp) && tmp !== 'true' && tmp !== 'false') {
145 out._.push(tmp);
146 }
147 }
148
149 idx += incr;
150 }
151
152 if (opts.default !== void 0) {
153 for (k in opts.default) {
154 if (out[k] === void 0) {
155 out[k] = opts.default[k];
156 }
157 }
158 }
159
160 for (k in out) {
161 if (aliases[k] === void 0) continue;
162 y = out[k];
163 len = aliases[k].length;
164 for (i = 0; i < len; i++) {
165 out[aliases[k][i]] = y; // assign value
166 }
167 }
168
169 return out;
170};
171
172var utils = createCommonjsModule(function (module, exports) {
173Object.defineProperty(exports, "__esModule", { value: true });
174exports.removeBrackets = (v) => v.replace(/[<[].+/, '').trim();
175exports.findAllBrackets = (v) => {
176 const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
177 const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
178 const res = [];
179 const parse = (match) => {
180 let variadic = false;
181 let value = match[1];
182 if (value.startsWith('...')) {
183 value = value.slice(3);
184 variadic = true;
185 }
186 return {
187 required: match[0].startsWith('<'),
188 value,
189 variadic
190 };
191 };
192 let angledMatch;
193 while ((angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v))) {
194 res.push(parse(angledMatch));
195 }
196 let squareMatch;
197 while ((squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v))) {
198 res.push(parse(squareMatch));
199 }
200 return res;
201};
202exports.getMriOptions = (globalCommand, subCommand) => {
203 const options = [
204 ...globalCommand.options,
205 ...(subCommand ? subCommand.options : [])
206 ];
207 const ignoreDefault = subCommand && subCommand.config.ignoreOptionDefaultValue
208 ? subCommand.config.ignoreOptionDefaultValue
209 : globalCommand.config.ignoreOptionDefaultValue;
210 return {
211 default: ignoreDefault
212 ? {}
213 : options.reduce((res, option) => {
214 if (option.config.default !== undefined) {
215 // Only need to set the default value of the first name
216 // Since mri will automatically do the rest for alias names
217 res[option.names[0]] = option.config.default;
218 }
219 return res;
220 }, {}),
221 boolean: options
222 .filter(option => option.isBoolean)
223 .reduce((res, option) => {
224 return res.concat(option.names);
225 }, []),
226 alias: options.reduce((res, option) => {
227 if (option.names.length > 1) {
228 res[option.names[0]] = option.names.slice(1);
229 }
230 return res;
231 }, {}),
232 string: options
233 .filter(option => typeof option.required === 'boolean')
234 .reduce((res, option) => {
235 return res.concat(option.names);
236 }, [])
237 };
238};
239exports.findLongest = (arr) => {
240 return arr.sort((a, b) => {
241 return a.length > b.length ? -1 : 1;
242 })[0];
243};
244exports.padRight = (str, length) => {
245 return str.length >= length ? str : `${str}${' '.repeat(length - str.length)}`;
246};
247exports.camelcase = (input) => {
248 return input.replace(/([a-z])-([a-z])/g, (_, p1, p2) => {
249 return p1 + p2.toUpperCase();
250 });
251};
252exports.setDotProp = (obj, keys, val) => {
253 let i = 0;
254 let length = keys.length;
255 let t = obj;
256 let x;
257 for (; i < length; ++i) {
258 x = t[keys[i]];
259 t = t[keys[i]] =
260 i === length - 1
261 ? val
262 : x != null
263 ? x
264 : !!~keys[i + 1].indexOf('.') || !(+keys[i + 1] > -1)
265 ? {}
266 : [];
267 }
268};
269});
270
271unwrapExports(utils);
272var utils_1 = utils.removeBrackets;
273var utils_2 = utils.findAllBrackets;
274var utils_3 = utils.getMriOptions;
275var utils_4 = utils.findLongest;
276var utils_5 = utils.padRight;
277var utils_6 = utils.camelcase;
278var utils_7 = utils.setDotProp;
279
280var Option_1 = createCommonjsModule(function (module, exports) {
281Object.defineProperty(exports, "__esModule", { value: true });
282
283class Option {
284 constructor(rawName, description, config) {
285 this.rawName = rawName;
286 this.description = description;
287 this.config = Object.assign({}, config);
288 let negated = false;
289 this.names = utils.removeBrackets(rawName)
290 .split(',')
291 .map((v) => {
292 let name = v.trim().replace(/^-{1,2}/, '');
293 if (name.startsWith('no-')) {
294 negated = true;
295 name = name.replace(/^no-/, '');
296 }
297 return name;
298 });
299 if (negated) {
300 this.config.default = true;
301 }
302 if (rawName.includes('<')) {
303 this.required = true;
304 }
305 else if (rawName.includes('[')) {
306 this.required = false;
307 }
308 else {
309 // No arg needed, it's boolean flag
310 this.isBoolean = true;
311 }
312 }
313}
314exports.default = Option;
315});
316
317unwrapExports(Option_1);
318
319var Command_1 = createCommonjsModule(function (module, exports) {
320var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
321 return (mod && mod.__esModule) ? mod : { "default": mod };
322};
323Object.defineProperty(exports, "__esModule", { value: true });
324const Option_1$$1 = __importDefault(Option_1);
325
326class Command {
327 constructor(rawName, description, config = {}, cli) {
328 this.rawName = rawName;
329 this.description = description;
330 this.config = config;
331 this.cli = cli;
332 this.options = [];
333 this.aliasNames = [];
334 this.name = utils.removeBrackets(rawName);
335 this.args = utils.findAllBrackets(rawName);
336 this.examples = [];
337 }
338 usage(text) {
339 this.usageText = text;
340 return this;
341 }
342 allowUnknownOptions() {
343 this.config.allowUnknownOptions = true;
344 return this;
345 }
346 ignoreOptionDefaultValue() {
347 this.config.ignoreOptionDefaultValue = true;
348 return this;
349 }
350 version(version, customFlags = '-v, --version') {
351 this.versionNumber = version;
352 this.option(customFlags, 'Display version number');
353 return this;
354 }
355 example(example) {
356 this.examples.push(example);
357 return this;
358 }
359 /**
360 * Add a option for this command
361 * @param rawName Raw option name(s)
362 * @param description Option description
363 * @param config Option config
364 */
365 option(rawName, description, config) {
366 const option = new Option_1$$1.default(rawName, description, config);
367 this.options.push(option);
368 return this;
369 }
370 alias(name) {
371 this.aliasNames.push(name);
372 return this;
373 }
374 action(callback) {
375 this.commandAction = callback;
376 return this;
377 }
378 /**
379 * Check if a command name is matched by this command
380 * @param name Command name
381 */
382 isMatched(name) {
383 return this.name === name || this.aliasNames.includes(name);
384 }
385 get isDefaultCommand() {
386 return this.name === '' || this.aliasNames.includes('!');
387 }
388 get isGlobalCommand() {
389 return this instanceof GlobalCommand;
390 }
391 /**
392 * Check if an option is registered in this command
393 * @param name Option name
394 */
395 hasOption(name) {
396 name = name.split('.')[0];
397 return this.options.find(option => {
398 return option.names.includes(name);
399 });
400 }
401 outputHelp() {
402 const { bin, commands } = this.cli;
403 const { versionNumber, options: globalOptions, helpCallback } = this.cli.globalCommand;
404 const sections = [
405 {
406 body: `${bin}${versionNumber ? ` v${versionNumber}` : ''}`
407 }
408 ];
409 sections.push({
410 title: 'Usage',
411 body: ` $ ${bin} ${this.usageText || this.rawName}`
412 });
413 const showCommands = (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0;
414 if (showCommands) {
415 const longestCommandName = utils.findLongest(commands.map(command => command.rawName));
416 sections.push({
417 title: 'Commands',
418 body: commands
419 .map(command => {
420 return ` ${utils.padRight(command.rawName, longestCommandName.length)} ${command.description}`;
421 })
422 .join('\n')
423 });
424 sections.push({
425 title: `For more info, run any command with the \`--help\` flag`,
426 body: commands
427 .map(command => ` $ ${bin}${command.name === '' ? '' : ` ${command.name}`} --help`)
428 .join('\n')
429 });
430 }
431 const options = this.isGlobalCommand
432 ? globalOptions
433 : [...this.options, ...(globalOptions || [])];
434 if (options.length > 0) {
435 const longestOptionName = utils.findLongest(options.map(option => option.rawName));
436 sections.push({
437 title: 'Options',
438 body: options
439 .map(option => {
440 return ` ${utils.padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === undefined
441 ? ''
442 : `(default: ${option.config.default})`}`;
443 })
444 .join('\n')
445 });
446 }
447 if (this.examples.length > 0) {
448 sections.push({
449 title: 'Examples',
450 body: this.examples
451 .map(example => {
452 if (typeof example === 'function') {
453 return example(bin);
454 }
455 return example;
456 })
457 .join('\n')
458 });
459 }
460 if (helpCallback) {
461 helpCallback(sections);
462 }
463 console.log(sections
464 .map(section => {
465 return section.title
466 ? `${section.title}:\n${section.body}`
467 : section.body;
468 })
469 .join('\n\n'));
470 process.exit(0);
471 }
472 outputVersion() {
473 const { bin } = this.cli;
474 const { versionNumber } = this.cli.globalCommand;
475 if (versionNumber) {
476 console.log(`${bin}/${versionNumber} ${process.platform}-${process.arch} node-${process.version}`);
477 }
478 process.exit(0);
479 }
480 /**
481 * Check if the parsed options contain any unknown options
482 *
483 * Exit and output error when true
484 */
485 checkUnknownOptions() {
486 const { rawOptions, globalCommand } = this.cli;
487 if (!this.config.allowUnknownOptions) {
488 for (const name of Object.keys(rawOptions)) {
489 if (name !== '--' &&
490 !this.hasOption(name) &&
491 !globalCommand.hasOption(name)) {
492 console.error(`error: Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
493 process.exit(1);
494 }
495 }
496 }
497 }
498 /**
499 * Check if the required string-type options exist
500 */
501 checkRequiredOptions() {
502 const { rawOptions, globalCommand } = this.cli;
503 const requiredOptions = [...globalCommand.options, ...this.options].filter(option => option.required);
504 for (const option of requiredOptions) {
505 const value = rawOptions[option.names[0].split('.')[0]];
506 if (typeof value === 'boolean') {
507 console.error(`error: option \`${option.rawName}\` argument is missing`);
508 process.exit(1);
509 }
510 }
511 }
512}
513class GlobalCommand extends Command {
514 constructor(cli) {
515 super('@@global@@', '', {}, cli);
516 }
517}
518exports.GlobalCommand = GlobalCommand;
519exports.default = Command;
520});
521
522unwrapExports(Command_1);
523var Command_2 = Command_1.GlobalCommand;
524
525var CAC_1 = createCommonjsModule(function (module, exports) {
526var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
527 return (mod && mod.__esModule) ? mod : { "default": mod };
528};
529var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) {
530 if (mod && mod.__esModule) return mod;
531 var result = {};
532 if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
533 result["default"] = mod;
534 return result;
535};
536Object.defineProperty(exports, "__esModule", { value: true });
537
538const path_1 = __importDefault(path);
539const mri_1 = __importDefault(lib);
540const Command_1$$1 = __importStar(Command_1);
541
542class CAC extends events.EventEmitter {
543 constructor() {
544 super();
545 this.commands = [];
546 this.globalCommand = new Command_1$$1.GlobalCommand(this);
547 this.globalCommand.usage('<command> [options]');
548 }
549 /**
550 * Add a global usage text.
551 *
552 * This is not used by sub-commands.
553 */
554 usage(text) {
555 this.globalCommand.usage(text);
556 return this;
557 }
558 /**
559 * Add a sub-command
560 */
561 command(rawName, description, config) {
562 const command = new Command_1$$1.default(rawName, description || '', config, this);
563 command.globalCommand = this.globalCommand;
564 this.commands.push(command);
565 return command;
566 }
567 /**
568 * Add a global CLI option.
569 *
570 * Which is also applied to sub-commands.
571 */
572 option(rawName, description, config) {
573 this.globalCommand.option(rawName, description, config);
574 return this;
575 }
576 /**
577 * Show help message when `-h, --help` flags appear.
578 *
579 */
580 help(callback) {
581 this.globalCommand.option('-h, --help', 'Display this message');
582 this.globalCommand.helpCallback = callback;
583 return this;
584 }
585 /**
586 * Show version number when `-v, --version` flags appear.
587 *
588 */
589 version(version, customFlags = '-v, --version') {
590 this.globalCommand.version(version, customFlags);
591 return this;
592 }
593 /**
594 * Add a global example.
595 *
596 * This example added here will not be used by sub-commands.
597 */
598 example(example) {
599 this.globalCommand.example(example);
600 return this;
601 }
602 /**
603 * Output the corresponding help message
604 * When a sub-command is matched, output the help message for the command
605 * Otherwise output the global one.
606 *
607 * This will also call `process.exit(0)` to quit the process.
608 */
609 outputHelp() {
610 if (this.matchedCommand) {
611 this.matchedCommand.outputHelp();
612 }
613 else {
614 this.globalCommand.outputHelp();
615 }
616 }
617 /**
618 * Output the version number.
619 *
620 * This will also call `process.exit(0)` to quit the process.
621 */
622 outputVersion() {
623 this.globalCommand.outputVersion();
624 }
625 setParsedInfo({ args, options, rawOptions }, matchedCommand) {
626 this.args = args;
627 this.options = options;
628 this.rawOptions = rawOptions;
629 if (matchedCommand) {
630 this.matchedCommand = matchedCommand;
631 }
632 return this;
633 }
634 /**
635 * Parse argv
636 */
637 parse(argv = process.argv, {
638 /** Whether to run the action for matched command */
639 run = true } = {}) {
640 this.rawArgs = argv;
641 this.bin = argv[1] ? path_1.default.basename(argv[1]) : 'cli';
642 let shouldParse = true;
643 // Search sub-commands
644 for (const command of this.commands) {
645 const mriOptions = utils.getMriOptions(this.globalCommand, command);
646 const mriResult = this.mri(argv.slice(2), mriOptions);
647 const commandName = mriResult.args[0];
648 if (command.isMatched(commandName)) {
649 shouldParse = false;
650 const parsedInfo = Object.assign({}, mriResult, { args: mriResult.args.slice(1) });
651 this.setParsedInfo(parsedInfo, command);
652 this.emit(`command:${commandName}`, command);
653 }
654 }
655 if (shouldParse) {
656 // Search the default command
657 for (const command of this.commands) {
658 if (command.name === '') {
659 shouldParse = false;
660 const mriOptions = utils.getMriOptions(this.globalCommand, command);
661 const mriResult = this.mri(argv.slice(2), mriOptions);
662 this.setParsedInfo(mriResult, command);
663 this.emit(`command:!`, command);
664 }
665 }
666 }
667 if (shouldParse) {
668 const globalMriOptions = utils.getMriOptions(this.globalCommand);
669 const mriResult = this.mri(argv.slice(2), globalMriOptions);
670 this.setParsedInfo(mriResult);
671 }
672 if (this.options.help && this.globalCommand.hasOption('help')) {
673 this.outputHelp();
674 }
675 if (this.options.version &&
676 this.globalCommand.hasOption('version') &&
677 this.globalCommand.versionNumber) {
678 this.outputVersion();
679 }
680 const parsedArgv = { args: this.args, options: this.options };
681 if (run) {
682 this.runMatchedCommand();
683 }
684 if (!this.matchedCommand && this.args[0]) {
685 this.emit('command:*');
686 }
687 return parsedArgv;
688 }
689 mri(argv, mriOptions) {
690 let argsAfterDoubleDashes = [];
691 const doubleDashesIndex = argv.indexOf('--');
692 if (doubleDashesIndex > -1) {
693 argsAfterDoubleDashes = argv.slice(0, doubleDashesIndex);
694 argv = argv.slice(doubleDashesIndex + 1);
695 }
696 const parsed = mri_1.default(argv, mriOptions);
697 const args = parsed._;
698 delete parsed._;
699 const options = {
700 '--': argsAfterDoubleDashes
701 };
702 for (const key of Object.keys(parsed)) {
703 const keys = key.split('.').map((v, i) => {
704 return i === 0 ? utils.camelcase(v) : v;
705 });
706 utils.setDotProp(options, keys, parsed[key]);
707 }
708 return {
709 args,
710 options,
711 rawOptions: parsed
712 };
713 }
714 runMatchedCommand() {
715 const { args, options, matchedCommand: command } = this;
716 if (!command || !command.commandAction)
717 return;
718 command.checkUnknownOptions();
719 command.checkRequiredOptions();
720 const minimalArgsCount = command.args.filter(arg => arg.required).length;
721 if (args.length < minimalArgsCount) {
722 console.error(`error: missing required args for command \`${command.rawName}\``);
723 process.exit(1);
724 }
725 const actionArgs = [];
726 command.args.forEach((arg, index) => {
727 if (arg.variadic) {
728 actionArgs.push(args.slice(index));
729 }
730 else {
731 actionArgs.push(args[index]);
732 }
733 });
734 actionArgs.push(options);
735 return command.commandAction.apply(this, actionArgs);
736 }
737}
738exports.default = CAC;
739});
740
741unwrapExports(CAC_1);
742
743var lib$1 = createCommonjsModule(function (module) {
744var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
745 return (mod && mod.__esModule) ? mod : { "default": mod };
746};
747const CAC_1$$1 = __importDefault(CAC_1);
748const cac = () => new CAC_1$$1.default();
749module.exports = cac;
750});
751
752var index = unwrapExports(lib$1);
753
754module.exports = index;