Socket
Socket
Sign inDemoInstall

cac

Package Overview
Dependencies
Maintainers
3
Versions
120
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cac - npm Package Compare versions

Comparing version 6.5.8 to 6.5.9

dist/index.d.ts

964

dist/index.js

@@ -119,613 +119,483 @@ 'use strict';

const removeBrackets = (v) => v.replace(/[<[].+/, '').trim();
const removeBrackets = (v) => v.replace(/[<[].+/, "").trim();
const findAllBrackets = (v) => {
const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
const res = [];
const parse = (match) => {
let variadic = false;
let value = match[1];
if (value.startsWith('...')) {
value = value.slice(3);
variadic = true;
}
return {
required: match[0].startsWith('<'),
value,
variadic
};
const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
const res = [];
const parse = (match) => {
let variadic = false;
let value = match[1];
if (value.startsWith("...")) {
value = value.slice(3);
variadic = true;
}
return {
required: match[0].startsWith("<"),
value,
variadic
};
let angledMatch;
while ((angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v))) {
res.push(parse(angledMatch));
}
let squareMatch;
while ((squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v))) {
res.push(parse(squareMatch));
}
return res;
};
let angledMatch;
while (angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v)) {
res.push(parse(angledMatch));
}
let squareMatch;
while (squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v)) {
res.push(parse(squareMatch));
}
return res;
};
const getMriOptions = (options) => {
const result = { alias: {}, boolean: [] };
for (const [index, option] of options.entries()) {
// We do not set default values in mri options
// Since its type (typeof) will be used to cast parsed arguments.
// Which mean `--foo foo` will be parsed as `{foo: true}` if we have `{default:{foo: true}}`
// Set alias
if (option.names.length > 1) {
result.alias[option.names[0]] = option.names.slice(1);
const result = {
alias: {},
boolean: []
};
for (const [index, option] of options.entries()) {
if (option.names.length > 1) {
result.alias[option.names[0]] = option.names.slice(1);
}
if (option.isBoolean) {
if (option.negated) {
const hasStringTypeOption = options.some((o, i) => {
return i !== index && o.names.some((name) => option.names.includes(name)) && typeof o.required === "boolean";
});
if (!hasStringTypeOption) {
result.boolean.push(option.names[0]);
}
// Set boolean
if (option.isBoolean) {
if (option.negated) {
// For negated option
// We only set it to `boolean` type when there's no string-type option with the same name
const hasStringTypeOption = options.some((o, i) => {
return (i !== index &&
o.names.some(name => option.names.includes(name)) &&
typeof o.required === 'boolean');
});
if (!hasStringTypeOption) {
result.boolean.push(option.names[0]);
}
}
else {
result.boolean.push(option.names[0]);
}
}
} else {
result.boolean.push(option.names[0]);
}
}
return result;
}
return result;
};
const findLongest = (arr) => {
return arr.sort((a, b) => {
return a.length > b.length ? -1 : 1;
})[0];
return arr.sort((a, b) => {
return a.length > b.length ? -1 : 1;
})[0];
};
const padRight = (str, length) => {
return str.length >= length ? str : `${str}${' '.repeat(length - str.length)}`;
return str.length >= length ? str : `${str}${" ".repeat(length - str.length)}`;
};
const camelcase = (input) => {
return input.replace(/([a-z])-([a-z])/g, (_, p1, p2) => {
return p1 + p2.toUpperCase();
});
return input.replace(/([a-z])-([a-z])/g, (_, p1, p2) => {
return p1 + p2.toUpperCase();
});
};
const setDotProp = (obj, keys, val) => {
let i = 0;
let length = keys.length;
let t = obj;
let x;
for (; i < length; ++i) {
x = t[keys[i]];
t = t[keys[i]] =
i === length - 1
? val
: x != null
? x
: !!~keys[i + 1].indexOf('.') || !(+keys[i + 1] > -1)
? {}
: [];
}
let i = 0;
let length = keys.length;
let t = obj;
let x;
for (; i < length; ++i) {
x = t[keys[i]];
t = t[keys[i]] = i === length - 1 ? val : x != null ? x : !!~keys[i + 1].indexOf(".") || !(+keys[i + 1] > -1) ? {} : [];
}
};
const setByType = (obj, transforms) => {
for (const key of Object.keys(transforms)) {
const transform = transforms[key];
if (transform.shouldTransform) {
obj[key] = Array.prototype.concat.call([], obj[key]);
if (typeof transform.transformFunction === 'function') {
obj[key] = obj[key].map(transform.transformFunction);
}
}
for (const key of Object.keys(transforms)) {
const transform = transforms[key];
if (transform.shouldTransform) {
obj[key] = Array.prototype.concat.call([], obj[key]);
if (typeof transform.transformFunction === "function") {
obj[key] = obj[key].map(transform.transformFunction);
}
}
}
};
const getFileName = (input) => {
const m = /([^\\\/]+)$/.exec(input);
return m ? m[1] : '';
const m = /([^\\\/]+)$/.exec(input);
return m ? m[1] : "";
};
const camelcaseOptionName = (name) => {
// Camelcase the option name
// Don't camelcase anything after the dot `.`
return name
.split('.')
.map((v, i) => {
return i === 0 ? camelcase(v) : v;
})
.join('.');
return name.split(".").map((v, i) => {
return i === 0 ? camelcase(v) : v;
}).join(".");
};
class CACError extends Error {
constructor(message) {
super(message);
this.name = this.constructor.name;
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
}
else {
this.stack = new Error(message).stack;
}
constructor(message) {
super(message);
this.name = this.constructor.name;
if (typeof Error.captureStackTrace === "function") {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = new Error(message).stack;
}
}
}
class Option {
constructor(rawName, description, config) {
this.rawName = rawName;
this.description = description;
this.config = Object.assign({}, config);
// You may use cli.option('--env.* [value]', 'desc') to denote a dot-nested option
rawName = rawName.replace(/\.\*/g, '');
this.negated = false;
this.names = removeBrackets(rawName)
.split(',')
.map((v) => {
let name = v.trim().replace(/^-{1,2}/, '');
if (name.startsWith('no-')) {
this.negated = true;
name = name.replace(/^no-/, '');
}
return camelcaseOptionName(name);
})
.sort((a, b) => (a.length > b.length ? 1 : -1)); // Sort names
// Use the longest name (last one) as actual option name
this.name = this.names[this.names.length - 1];
if (this.negated) {
this.config.default = true;
}
if (rawName.includes('<')) {
this.required = true;
}
else if (rawName.includes('[')) {
this.required = false;
}
else {
// No arg needed, it's boolean flag
this.isBoolean = true;
}
constructor(rawName, description, config) {
this.rawName = rawName;
this.description = description;
this.config = Object.assign({}, config);
rawName = rawName.replace(/\.\*/g, "");
this.negated = false;
this.names = removeBrackets(rawName).split(",").map((v) => {
let name = v.trim().replace(/^-{1,2}/, "");
if (name.startsWith("no-")) {
this.negated = true;
name = name.replace(/^no-/, "");
}
return camelcaseOptionName(name);
}).sort((a, b) => a.length > b.length ? 1 : -1);
this.name = this.names[this.names.length - 1];
if (this.negated) {
this.config.default = true;
}
if (rawName.includes("<")) {
this.required = true;
} else if (rawName.includes("[")) {
this.required = false;
} else {
this.isBoolean = true;
}
}
}
const deno = typeof window !== 'undefined' && window.Deno;
const denoScriptPath = deno && typeof window !== 'undefined' && window.location.pathname;
// Adds deno executable and script path to processArgs as "compatibility" layer for node
// See https://github.com/cacjs/cac/issues/69
const processArgs = deno
? ['deno', denoScriptPath].concat(Deno.args)
: process.argv;
const platformInfo = deno
? `${Deno.build.os}-${Deno.build.arch} deno-${Deno.version.deno}`
: `${process.platform}-${process.arch} node-${process.version}`;
const deno = typeof window !== "undefined" && window.Deno;
const processArgs = deno ? ["deno", "cli"].concat(Deno.args) : process.argv;
const platformInfo = deno ? `${Deno.build.os}-${Deno.build.arch} deno-${Deno.version.deno}` : `${process.platform}-${process.arch} node-${process.version}`;
class Command {
constructor(rawName, description, config = {}, cli) {
this.rawName = rawName;
this.description = description;
this.config = config;
this.cli = cli;
this.options = [];
this.aliasNames = [];
this.name = removeBrackets(rawName);
this.args = findAllBrackets(rawName);
this.examples = [];
constructor(rawName, description, config = {}, cli) {
this.rawName = rawName;
this.description = description;
this.config = config;
this.cli = cli;
this.options = [];
this.aliasNames = [];
this.name = removeBrackets(rawName);
this.args = findAllBrackets(rawName);
this.examples = [];
}
usage(text) {
this.usageText = text;
return this;
}
allowUnknownOptions() {
this.config.allowUnknownOptions = true;
return this;
}
ignoreOptionDefaultValue() {
this.config.ignoreOptionDefaultValue = true;
return this;
}
version(version, customFlags = "-v, --version") {
this.versionNumber = version;
this.option(customFlags, "Display version number");
return this;
}
example(example) {
this.examples.push(example);
return this;
}
option(rawName, description, config) {
const option = new Option(rawName, description, config);
this.options.push(option);
return this;
}
alias(name) {
this.aliasNames.push(name);
return this;
}
action(callback) {
this.commandAction = callback;
return this;
}
isMatched(name) {
return this.name === name || this.aliasNames.includes(name);
}
get isDefaultCommand() {
return this.name === "" || this.aliasNames.includes("!");
}
get isGlobalCommand() {
return this instanceof GlobalCommand;
}
hasOption(name) {
name = name.split(".")[0];
return this.options.find((option) => {
return option.names.includes(name);
});
}
outputHelp() {
const {name, commands} = this.cli;
const {versionNumber, options: globalOptions, helpCallback} = this.cli.globalCommand;
const sections = [{
body: `${name}${versionNumber ? ` v${versionNumber}` : ""}`
}];
sections.push({
title: "Usage",
body: ` $ ${name} ${this.usageText || this.rawName}`
});
const showCommands = (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0;
if (showCommands) {
const longestCommandName = findLongest(commands.map((command) => command.rawName));
sections.push({
title: "Commands",
body: commands.map((command) => {
return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
}).join("\n")
});
sections.push({
title: `For more info, run any command with the \`--help\` flag`,
body: commands.map((command) => ` $ ${name}${command.name === "" ? "" : ` ${command.name}`} --help`).join("\n")
});
}
usage(text) {
this.usageText = text;
return this;
const options = this.isGlobalCommand ? globalOptions : [...this.options, ...globalOptions || []];
if (options.length > 0) {
const longestOptionName = findLongest(options.map((option) => option.rawName));
sections.push({
title: "Options",
body: options.map((option) => {
return ` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === void 0 ? "" : `(default: ${option.config.default})`}`;
}).join("\n")
});
}
allowUnknownOptions() {
this.config.allowUnknownOptions = true;
return this;
if (this.examples.length > 0) {
sections.push({
title: "Examples",
body: this.examples.map((example) => {
if (typeof example === "function") {
return example(name);
}
return example;
}).join("\n")
});
}
ignoreOptionDefaultValue() {
this.config.ignoreOptionDefaultValue = true;
return this;
if (helpCallback) {
helpCallback(sections);
}
version(version, customFlags = '-v, --version') {
this.versionNumber = version;
this.option(customFlags, 'Display version number');
return this;
console.log(sections.map((section) => {
return section.title ? `${section.title}:
${section.body}` : section.body;
}).join("\n\n"));
}
outputVersion() {
const {name} = this.cli;
const {versionNumber} = this.cli.globalCommand;
if (versionNumber) {
console.log(`${name}/${versionNumber} ${platformInfo}`);
}
example(example) {
this.examples.push(example);
return this;
}
checkRequiredArgs() {
const minimalArgsCount = this.args.filter((arg) => arg.required).length;
if (this.cli.args.length < minimalArgsCount) {
throw new CACError(`missing required args for command \`${this.rawName}\``);
}
/**
* Add a option for this command
* @param rawName Raw option name(s)
* @param description Option description
* @param config Option config
*/
option(rawName, description, config) {
const option = new Option(rawName, description, config);
this.options.push(option);
return this;
}
alias(name) {
this.aliasNames.push(name);
return this;
}
action(callback) {
this.commandAction = callback;
return this;
}
/**
* Check if a command name is matched by this command
* @param name Command name
*/
isMatched(name) {
return this.name === name || this.aliasNames.includes(name);
}
get isDefaultCommand() {
return this.name === '' || this.aliasNames.includes('!');
}
get isGlobalCommand() {
return this instanceof GlobalCommand;
}
/**
* Check if an option is registered in this command
* @param name Option name
*/
hasOption(name) {
name = name.split('.')[0];
return this.options.find(option => {
return option.names.includes(name);
});
}
outputHelp() {
const { name, commands } = this.cli;
const { versionNumber, options: globalOptions, helpCallback } = this.cli.globalCommand;
const sections = [
{
body: `${name}${versionNumber ? ` v${versionNumber}` : ''}`
}
];
sections.push({
title: 'Usage',
body: ` $ ${name} ${this.usageText || this.rawName}`
});
const showCommands = (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0;
if (showCommands) {
const longestCommandName = findLongest(commands.map(command => command.rawName));
sections.push({
title: 'Commands',
body: commands
.map(command => {
return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
})
.join('\n')
});
sections.push({
title: `For more info, run any command with the \`--help\` flag`,
body: commands
.map(command => ` $ ${name}${command.name === '' ? '' : ` ${command.name}`} --help`)
.join('\n')
});
}
checkUnknownOptions() {
const {options, globalCommand} = this.cli;
if (!this.config.allowUnknownOptions) {
for (const name of Object.keys(options)) {
if (name !== "--" && !this.hasOption(name) && !globalCommand.hasOption(name)) {
throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
}
const options = this.isGlobalCommand
? globalOptions
: [...this.options, ...(globalOptions || [])];
if (options.length > 0) {
const longestOptionName = findLongest(options.map(option => option.rawName));
sections.push({
title: 'Options',
body: options
.map(option => {
return ` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === undefined
? ''
: `(default: ${option.config.default})`}`;
})
.join('\n')
});
}
if (this.examples.length > 0) {
sections.push({
title: 'Examples',
body: this.examples
.map(example => {
if (typeof example === 'function') {
return example(name);
}
return example;
})
.join('\n')
});
}
if (helpCallback) {
helpCallback(sections);
}
console.log(sections
.map(section => {
return section.title
? `${section.title}:\n${section.body}`
: section.body;
})
.join('\n\n'));
}
}
outputVersion() {
const { name } = this.cli;
const { versionNumber } = this.cli.globalCommand;
if (versionNumber) {
console.log(`${name}/${versionNumber} ${platformInfo}`);
}
checkOptionValue() {
const {options: parsedOptions, globalCommand} = this.cli;
const options = [...globalCommand.options, ...this.options];
for (const option of options) {
const value = parsedOptions[option.name.split(".")[0]];
if (option.required) {
const hasNegated = options.some((o) => o.negated && o.names.includes(option.name));
if (value === true || value === false && !hasNegated) {
throw new CACError(`option \`${option.rawName}\` value is missing`);
}
}
}
checkRequiredArgs() {
const minimalArgsCount = this.args.filter(arg => arg.required).length;
if (this.cli.args.length < minimalArgsCount) {
throw new CACError(`missing required args for command \`${this.rawName}\``);
}
}
/**
* Check if the parsed options contain any unknown options
*
* Exit and output error when true
*/
checkUnknownOptions() {
const { options, globalCommand } = this.cli;
if (!this.config.allowUnknownOptions) {
for (const name of Object.keys(options)) {
if (name !== '--' &&
!this.hasOption(name) &&
!globalCommand.hasOption(name)) {
throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
}
}
}
}
/**
* Check if the required string-type options exist
*/
checkOptionValue() {
const { options: parsedOptions, globalCommand } = this.cli;
const options = [...globalCommand.options, ...this.options];
for (const option of options) {
const value = parsedOptions[option.name.split('.')[0]];
// Check required option value
if (option.required) {
const hasNegated = options.some(o => o.negated && o.names.includes(option.name));
if (value === true || (value === false && !hasNegated)) {
throw new CACError(`option \`${option.rawName}\` value is missing`);
}
}
}
}
}
}
class GlobalCommand extends Command {
constructor(cli) {
super('@@global@@', '', {}, cli);
}
constructor(cli) {
super("@@global@@", "", {}, cli);
}
}
let __assign = Object.assign;
class CAC extends events.EventEmitter {
/**
* @param name The program name to display in help and version message
*/
constructor(name = '') {
super();
this.name = name;
this.commands = [];
this.globalCommand = new GlobalCommand(this);
this.globalCommand.usage('<command> [options]');
constructor(name = "") {
super();
this.name = name;
this.commands = [];
this.globalCommand = new GlobalCommand(this);
this.globalCommand.usage("<command> [options]");
}
usage(text) {
this.globalCommand.usage(text);
return this;
}
command(rawName, description, config) {
const command = new Command(rawName, description || "", config, this);
command.globalCommand = this.globalCommand;
this.commands.push(command);
return command;
}
option(rawName, description, config) {
this.globalCommand.option(rawName, description, config);
return this;
}
help(callback) {
this.globalCommand.option("-h, --help", "Display this message");
this.globalCommand.helpCallback = callback;
this.showHelpOnExit = true;
return this;
}
version(version, customFlags = "-v, --version") {
this.globalCommand.version(version, customFlags);
this.showVersionOnExit = true;
return this;
}
example(example) {
this.globalCommand.example(example);
return this;
}
outputHelp() {
if (this.matchedCommand) {
this.matchedCommand.outputHelp();
} else {
this.globalCommand.outputHelp();
}
/**
* Add a global usage text.
*
* This is not used by sub-commands.
*/
usage(text) {
this.globalCommand.usage(text);
return this;
}
outputVersion() {
this.globalCommand.outputVersion();
}
setParsedInfo({args, options}, matchedCommand, matchedCommandName) {
this.args = args;
this.options = options;
if (matchedCommand) {
this.matchedCommand = matchedCommand;
}
/**
* Add a sub-command
*/
command(rawName, description, config) {
const command = new Command(rawName, description || '', config, this);
command.globalCommand = this.globalCommand;
this.commands.push(command);
return command;
if (matchedCommandName) {
this.matchedCommandName = matchedCommandName;
}
/**
* Add a global CLI option.
*
* Which is also applied to sub-commands.
*/
option(rawName, description, config) {
this.globalCommand.option(rawName, description, config);
return this;
return this;
}
parse(argv = processArgs, {run = true} = {}) {
this.rawArgs = argv;
if (!this.name) {
this.name = argv[1] ? getFileName(argv[1]) : "cli";
}
/**
* Show help message when `-h, --help` flags appear.
*
*/
help(callback) {
this.globalCommand.option('-h, --help', 'Display this message');
this.globalCommand.helpCallback = callback;
this.showHelpOnExit = true;
return this;
let shouldParse = true;
for (const command of this.commands) {
const parsed = this.mri(argv.slice(2), command);
const commandName = parsed.args[0];
if (command.isMatched(commandName)) {
shouldParse = false;
const parsedInfo = __assign(__assign({}, parsed), {
args: parsed.args.slice(1)
});
this.setParsedInfo(parsedInfo, command, commandName);
this.emit(`command:${commandName}`, command);
}
}
/**
* Show version number when `-v, --version` flags appear.
*
*/
version(version, customFlags = '-v, --version') {
this.globalCommand.version(version, customFlags);
this.showVersionOnExit = true;
return this;
if (shouldParse) {
for (const command of this.commands) {
if (command.name === "") {
shouldParse = false;
const parsed = this.mri(argv.slice(2), command);
this.setParsedInfo(parsed, command);
this.emit(`command:!`, command);
}
}
}
/**
* Add a global example.
*
* This example added here will not be used by sub-commands.
*/
example(example) {
this.globalCommand.example(example);
return this;
if (shouldParse) {
const parsed = this.mri(argv.slice(2));
this.setParsedInfo(parsed);
}
/**
* Output the corresponding help message
* When a sub-command is matched, output the help message for the command
* Otherwise output the global one.
*
*/
outputHelp() {
if (this.matchedCommand) {
this.matchedCommand.outputHelp();
}
else {
this.globalCommand.outputHelp();
}
if (this.options.help && this.showHelpOnExit) {
this.outputHelp();
run = false;
}
/**
* Output the version number.
*
*/
outputVersion() {
this.globalCommand.outputVersion();
if (this.options.version && this.showVersionOnExit) {
this.outputVersion();
run = false;
}
setParsedInfo({ args, options }, matchedCommand, matchedCommandName) {
this.args = args;
this.options = options;
if (matchedCommand) {
this.matchedCommand = matchedCommand;
}
if (matchedCommandName) {
this.matchedCommandName = matchedCommandName;
}
return this;
const parsedArgv = {
args: this.args,
options: this.options
};
if (run) {
this.runMatchedCommand();
}
/**
* Parse argv
*/
parse(argv = processArgs, {
/** Whether to run the action for matched command */
run = true } = {}) {
this.rawArgs = argv;
if (!this.name) {
this.name = argv[1] ? getFileName(argv[1]) : 'cli';
}
let shouldParse = true;
// Search sub-commands
for (const command of this.commands) {
const parsed = this.mri(argv.slice(2), command);
const commandName = parsed.args[0];
if (command.isMatched(commandName)) {
shouldParse = false;
const parsedInfo = Object.assign({}, parsed, { args: parsed.args.slice(1) });
this.setParsedInfo(parsedInfo, command, commandName);
this.emit(`command:${commandName}`, command);
}
}
if (shouldParse) {
// Search the default command
for (const command of this.commands) {
if (command.name === '') {
shouldParse = false;
const parsed = this.mri(argv.slice(2), command);
this.setParsedInfo(parsed, command);
this.emit(`command:!`, command);
}
}
}
if (shouldParse) {
const parsed = this.mri(argv.slice(2));
this.setParsedInfo(parsed);
}
if (this.options.help && this.showHelpOnExit) {
this.outputHelp();
run = false;
}
if (this.options.version && this.showVersionOnExit) {
this.outputVersion();
run = false;
}
const parsedArgv = { args: this.args, options: this.options };
if (run) {
this.runMatchedCommand();
}
if (!this.matchedCommand && this.args[0]) {
this.emit('command:*');
}
return parsedArgv;
if (!this.matchedCommand && this.args[0]) {
this.emit("command:*");
}
mri(argv,
/** Matched command */ command) {
// All added options
const cliOptions = [
...this.globalCommand.options,
...(command ? command.options : [])
];
const mriOptions = getMriOptions(cliOptions);
// Extract everything after `--` since mri doesn't support it
let argsAfterDoubleDashes = [];
const doubleDashesIndex = argv.indexOf('--');
if (doubleDashesIndex > -1) {
argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
argv = argv.slice(0, doubleDashesIndex);
return parsedArgv;
}
mri(argv, command) {
const cliOptions = [...this.globalCommand.options, ...command ? command.options : []];
const mriOptions = getMriOptions(cliOptions);
let argsAfterDoubleDashes = [];
const doubleDashesIndex = argv.indexOf("--");
if (doubleDashesIndex > -1) {
argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
argv = argv.slice(0, doubleDashesIndex);
}
let parsed = lib(argv, mriOptions);
parsed = Object.keys(parsed).reduce((res, name) => {
return __assign(__assign({}, res), {
[camelcaseOptionName(name)]: parsed[name]
});
}, {
_: []
});
const args = parsed._;
delete parsed._;
const options = {
"--": argsAfterDoubleDashes
};
const ignoreDefault = command && command.config.ignoreOptionDefaultValue ? command.config.ignoreOptionDefaultValue : this.globalCommand.config.ignoreOptionDefaultValue;
let transforms = Object.create(null);
for (const cliOption of cliOptions) {
if (!ignoreDefault && cliOption.config.default !== void 0) {
for (const name of cliOption.names) {
options[name] = cliOption.config.default;
}
let parsed = lib(argv, mriOptions);
parsed = Object.keys(parsed).reduce((res, name) => {
return Object.assign({}, res, { [camelcaseOptionName(name)]: parsed[name] });
}, { _: [] });
const args = parsed._;
delete parsed._;
const options = {
'--': argsAfterDoubleDashes
};
// Set option default value
const ignoreDefault = command && command.config.ignoreOptionDefaultValue
? command.config.ignoreOptionDefaultValue
: this.globalCommand.config.ignoreOptionDefaultValue;
let transforms = Object.create(null);
for (const cliOption of cliOptions) {
if (!ignoreDefault && cliOption.config.default !== undefined) {
for (const name of cliOption.names) {
options[name] = cliOption.config.default;
}
}
// If options type is defined
if (Array.isArray(cliOption.config.type)) {
if (transforms[cliOption.name] === undefined) {
transforms[cliOption.name] = Object.create(null);
transforms[cliOption.name]['shouldTransform'] = true;
transforms[cliOption.name]['transformFunction'] =
cliOption.config.type[0];
}
}
}
if (Array.isArray(cliOption.config.type)) {
if (transforms[cliOption.name] === void 0) {
transforms[cliOption.name] = Object.create(null);
transforms[cliOption.name]["shouldTransform"] = true;
transforms[cliOption.name]["transformFunction"] = cliOption.config.type[0];
}
// Set dot nested option values
for (const key of Object.keys(parsed)) {
const keys = key.split('.');
setDotProp(options, keys, parsed[key]);
setByType(options, transforms);
}
return {
args,
options
};
}
}
runMatchedCommand() {
const { args, options, matchedCommand: command } = this;
if (!command || !command.commandAction)
return;
command.checkUnknownOptions();
command.checkOptionValue();
command.checkRequiredArgs();
const actionArgs = [];
command.args.forEach((arg, index) => {
if (arg.variadic) {
actionArgs.push(args.slice(index));
}
else {
actionArgs.push(args[index]);
}
});
actionArgs.push(options);
return command.commandAction.apply(this, actionArgs);
for (const key of Object.keys(parsed)) {
const keys = key.split(".");
setDotProp(options, keys, parsed[key]);
setByType(options, transforms);
}
return {
args,
options
};
}
runMatchedCommand() {
const {args, options, matchedCommand: command} = this;
if (!command || !command.commandAction)
return;
command.checkUnknownOptions();
command.checkOptionValue();
command.checkRequiredArgs();
const actionArgs = [];
command.args.forEach((arg, index) => {
if (arg.variadic) {
actionArgs.push(args.slice(index));
} else {
actionArgs.push(args[index]);
}
});
actionArgs.push(options);
return command.commandAction.apply(this, actionArgs);
}
}
/**
* @param name The program name to display in help and version message
*/
const cac = (name = '') => new CAC(name);
if (typeof module !== 'undefined') {
module.exports = cac;
module.exports.default = cac;
module.exports.cac = cac;
const cac = (name = "") => new CAC(name);
if (typeof module !== "undefined") {
module.exports = cac;
module.exports.default = cac;
module.exports.cac = cac;
}

@@ -732,0 +602,0 @@

@@ -542,613 +542,483 @@ // Copyright Joyent, Inc. and other Node contributors.

const removeBrackets = (v) => v.replace(/[<[].+/, '').trim();
const removeBrackets = (v) => v.replace(/[<[].+/, "").trim();
const findAllBrackets = (v) => {
const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
const res = [];
const parse = (match) => {
let variadic = false;
let value = match[1];
if (value.startsWith('...')) {
value = value.slice(3);
variadic = true;
}
return {
required: match[0].startsWith('<'),
value,
variadic
};
const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
const res = [];
const parse = (match) => {
let variadic = false;
let value = match[1];
if (value.startsWith("...")) {
value = value.slice(3);
variadic = true;
}
return {
required: match[0].startsWith("<"),
value,
variadic
};
let angledMatch;
while ((angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v))) {
res.push(parse(angledMatch));
}
let squareMatch;
while ((squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v))) {
res.push(parse(squareMatch));
}
return res;
};
let angledMatch;
while (angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v)) {
res.push(parse(angledMatch));
}
let squareMatch;
while (squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v)) {
res.push(parse(squareMatch));
}
return res;
};
const getMriOptions = (options) => {
const result = { alias: {}, boolean: [] };
for (const [index, option] of options.entries()) {
// We do not set default values in mri options
// Since its type (typeof) will be used to cast parsed arguments.
// Which mean `--foo foo` will be parsed as `{foo: true}` if we have `{default:{foo: true}}`
// Set alias
if (option.names.length > 1) {
result.alias[option.names[0]] = option.names.slice(1);
const result = {
alias: {},
boolean: []
};
for (const [index, option] of options.entries()) {
if (option.names.length > 1) {
result.alias[option.names[0]] = option.names.slice(1);
}
if (option.isBoolean) {
if (option.negated) {
const hasStringTypeOption = options.some((o, i) => {
return i !== index && o.names.some((name) => option.names.includes(name)) && typeof o.required === "boolean";
});
if (!hasStringTypeOption) {
result.boolean.push(option.names[0]);
}
// Set boolean
if (option.isBoolean) {
if (option.negated) {
// For negated option
// We only set it to `boolean` type when there's no string-type option with the same name
const hasStringTypeOption = options.some((o, i) => {
return (i !== index &&
o.names.some(name => option.names.includes(name)) &&
typeof o.required === 'boolean');
});
if (!hasStringTypeOption) {
result.boolean.push(option.names[0]);
}
}
else {
result.boolean.push(option.names[0]);
}
}
} else {
result.boolean.push(option.names[0]);
}
}
return result;
}
return result;
};
const findLongest = (arr) => {
return arr.sort((a, b) => {
return a.length > b.length ? -1 : 1;
})[0];
return arr.sort((a, b) => {
return a.length > b.length ? -1 : 1;
})[0];
};
const padRight = (str, length) => {
return str.length >= length ? str : `${str}${' '.repeat(length - str.length)}`;
return str.length >= length ? str : `${str}${" ".repeat(length - str.length)}`;
};
const camelcase = (input) => {
return input.replace(/([a-z])-([a-z])/g, (_, p1, p2) => {
return p1 + p2.toUpperCase();
});
return input.replace(/([a-z])-([a-z])/g, (_, p1, p2) => {
return p1 + p2.toUpperCase();
});
};
const setDotProp = (obj, keys, val) => {
let i = 0;
let length = keys.length;
let t = obj;
let x;
for (; i < length; ++i) {
x = t[keys[i]];
t = t[keys[i]] =
i === length - 1
? val
: x != null
? x
: !!~keys[i + 1].indexOf('.') || !(+keys[i + 1] > -1)
? {}
: [];
}
let i = 0;
let length = keys.length;
let t = obj;
let x;
for (; i < length; ++i) {
x = t[keys[i]];
t = t[keys[i]] = i === length - 1 ? val : x != null ? x : !!~keys[i + 1].indexOf(".") || !(+keys[i + 1] > -1) ? {} : [];
}
};
const setByType = (obj, transforms) => {
for (const key of Object.keys(transforms)) {
const transform = transforms[key];
if (transform.shouldTransform) {
obj[key] = Array.prototype.concat.call([], obj[key]);
if (typeof transform.transformFunction === 'function') {
obj[key] = obj[key].map(transform.transformFunction);
}
}
for (const key of Object.keys(transforms)) {
const transform = transforms[key];
if (transform.shouldTransform) {
obj[key] = Array.prototype.concat.call([], obj[key]);
if (typeof transform.transformFunction === "function") {
obj[key] = obj[key].map(transform.transformFunction);
}
}
}
};
const getFileName = (input) => {
const m = /([^\\\/]+)$/.exec(input);
return m ? m[1] : '';
const m = /([^\\\/]+)$/.exec(input);
return m ? m[1] : "";
};
const camelcaseOptionName = (name) => {
// Camelcase the option name
// Don't camelcase anything after the dot `.`
return name
.split('.')
.map((v, i) => {
return i === 0 ? camelcase(v) : v;
})
.join('.');
return name.split(".").map((v, i) => {
return i === 0 ? camelcase(v) : v;
}).join(".");
};
class CACError extends Error {
constructor(message) {
super(message);
this.name = this.constructor.name;
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
}
else {
this.stack = new Error(message).stack;
}
constructor(message) {
super(message);
this.name = this.constructor.name;
if (typeof Error.captureStackTrace === "function") {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = new Error(message).stack;
}
}
}
class Option {
constructor(rawName, description, config) {
this.rawName = rawName;
this.description = description;
this.config = Object.assign({}, config);
// You may use cli.option('--env.* [value]', 'desc') to denote a dot-nested option
rawName = rawName.replace(/\.\*/g, '');
this.negated = false;
this.names = removeBrackets(rawName)
.split(',')
.map((v) => {
let name = v.trim().replace(/^-{1,2}/, '');
if (name.startsWith('no-')) {
this.negated = true;
name = name.replace(/^no-/, '');
}
return camelcaseOptionName(name);
})
.sort((a, b) => (a.length > b.length ? 1 : -1)); // Sort names
// Use the longest name (last one) as actual option name
this.name = this.names[this.names.length - 1];
if (this.negated) {
this.config.default = true;
}
if (rawName.includes('<')) {
this.required = true;
}
else if (rawName.includes('[')) {
this.required = false;
}
else {
// No arg needed, it's boolean flag
this.isBoolean = true;
}
constructor(rawName, description, config) {
this.rawName = rawName;
this.description = description;
this.config = Object.assign({}, config);
rawName = rawName.replace(/\.\*/g, "");
this.negated = false;
this.names = removeBrackets(rawName).split(",").map((v) => {
let name = v.trim().replace(/^-{1,2}/, "");
if (name.startsWith("no-")) {
this.negated = true;
name = name.replace(/^no-/, "");
}
return camelcaseOptionName(name);
}).sort((a, b) => a.length > b.length ? 1 : -1);
this.name = this.names[this.names.length - 1];
if (this.negated) {
this.config.default = true;
}
if (rawName.includes("<")) {
this.required = true;
} else if (rawName.includes("[")) {
this.required = false;
} else {
this.isBoolean = true;
}
}
}
const deno = typeof window !== 'undefined' && window.Deno;
const denoScriptPath = deno && typeof window !== 'undefined' && window.location.pathname;
// Adds deno executable and script path to processArgs as "compatibility" layer for node
// See https://github.com/cacjs/cac/issues/69
const processArgs = deno
? ['deno', denoScriptPath].concat(Deno.args)
: process.argv;
const platformInfo = deno
? `${Deno.build.os}-${Deno.build.arch} deno-${Deno.version.deno}`
: `${process.platform}-${process.arch} node-${process.version}`;
const deno = typeof window !== "undefined" && window.Deno;
const processArgs = deno ? ["deno", "cli"].concat(Deno.args) : process.argv;
const platformInfo = deno ? `${Deno.build.os}-${Deno.build.arch} deno-${Deno.version.deno}` : `${process.platform}-${process.arch} node-${process.version}`;
class Command {
constructor(rawName, description, config = {}, cli) {
this.rawName = rawName;
this.description = description;
this.config = config;
this.cli = cli;
this.options = [];
this.aliasNames = [];
this.name = removeBrackets(rawName);
this.args = findAllBrackets(rawName);
this.examples = [];
constructor(rawName, description, config = {}, cli) {
this.rawName = rawName;
this.description = description;
this.config = config;
this.cli = cli;
this.options = [];
this.aliasNames = [];
this.name = removeBrackets(rawName);
this.args = findAllBrackets(rawName);
this.examples = [];
}
usage(text) {
this.usageText = text;
return this;
}
allowUnknownOptions() {
this.config.allowUnknownOptions = true;
return this;
}
ignoreOptionDefaultValue() {
this.config.ignoreOptionDefaultValue = true;
return this;
}
version(version, customFlags = "-v, --version") {
this.versionNumber = version;
this.option(customFlags, "Display version number");
return this;
}
example(example) {
this.examples.push(example);
return this;
}
option(rawName, description, config) {
const option = new Option(rawName, description, config);
this.options.push(option);
return this;
}
alias(name) {
this.aliasNames.push(name);
return this;
}
action(callback) {
this.commandAction = callback;
return this;
}
isMatched(name) {
return this.name === name || this.aliasNames.includes(name);
}
get isDefaultCommand() {
return this.name === "" || this.aliasNames.includes("!");
}
get isGlobalCommand() {
return this instanceof GlobalCommand;
}
hasOption(name) {
name = name.split(".")[0];
return this.options.find((option) => {
return option.names.includes(name);
});
}
outputHelp() {
const {name, commands} = this.cli;
const {versionNumber, options: globalOptions, helpCallback} = this.cli.globalCommand;
const sections = [{
body: `${name}${versionNumber ? ` v${versionNumber}` : ""}`
}];
sections.push({
title: "Usage",
body: ` $ ${name} ${this.usageText || this.rawName}`
});
const showCommands = (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0;
if (showCommands) {
const longestCommandName = findLongest(commands.map((command) => command.rawName));
sections.push({
title: "Commands",
body: commands.map((command) => {
return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
}).join("\n")
});
sections.push({
title: `For more info, run any command with the \`--help\` flag`,
body: commands.map((command) => ` $ ${name}${command.name === "" ? "" : ` ${command.name}`} --help`).join("\n")
});
}
usage(text) {
this.usageText = text;
return this;
const options = this.isGlobalCommand ? globalOptions : [...this.options, ...globalOptions || []];
if (options.length > 0) {
const longestOptionName = findLongest(options.map((option) => option.rawName));
sections.push({
title: "Options",
body: options.map((option) => {
return ` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === void 0 ? "" : `(default: ${option.config.default})`}`;
}).join("\n")
});
}
allowUnknownOptions() {
this.config.allowUnknownOptions = true;
return this;
if (this.examples.length > 0) {
sections.push({
title: "Examples",
body: this.examples.map((example) => {
if (typeof example === "function") {
return example(name);
}
return example;
}).join("\n")
});
}
ignoreOptionDefaultValue() {
this.config.ignoreOptionDefaultValue = true;
return this;
if (helpCallback) {
helpCallback(sections);
}
version(version, customFlags = '-v, --version') {
this.versionNumber = version;
this.option(customFlags, 'Display version number');
return this;
console.log(sections.map((section) => {
return section.title ? `${section.title}:
${section.body}` : section.body;
}).join("\n\n"));
}
outputVersion() {
const {name} = this.cli;
const {versionNumber} = this.cli.globalCommand;
if (versionNumber) {
console.log(`${name}/${versionNumber} ${platformInfo}`);
}
example(example) {
this.examples.push(example);
return this;
}
checkRequiredArgs() {
const minimalArgsCount = this.args.filter((arg) => arg.required).length;
if (this.cli.args.length < minimalArgsCount) {
throw new CACError(`missing required args for command \`${this.rawName}\``);
}
/**
* Add a option for this command
* @param rawName Raw option name(s)
* @param description Option description
* @param config Option config
*/
option(rawName, description, config) {
const option = new Option(rawName, description, config);
this.options.push(option);
return this;
}
alias(name) {
this.aliasNames.push(name);
return this;
}
action(callback) {
this.commandAction = callback;
return this;
}
/**
* Check if a command name is matched by this command
* @param name Command name
*/
isMatched(name) {
return this.name === name || this.aliasNames.includes(name);
}
get isDefaultCommand() {
return this.name === '' || this.aliasNames.includes('!');
}
get isGlobalCommand() {
return this instanceof GlobalCommand;
}
/**
* Check if an option is registered in this command
* @param name Option name
*/
hasOption(name) {
name = name.split('.')[0];
return this.options.find(option => {
return option.names.includes(name);
});
}
outputHelp() {
const { name, commands } = this.cli;
const { versionNumber, options: globalOptions, helpCallback } = this.cli.globalCommand;
const sections = [
{
body: `${name}${versionNumber ? ` v${versionNumber}` : ''}`
}
];
sections.push({
title: 'Usage',
body: ` $ ${name} ${this.usageText || this.rawName}`
});
const showCommands = (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0;
if (showCommands) {
const longestCommandName = findLongest(commands.map(command => command.rawName));
sections.push({
title: 'Commands',
body: commands
.map(command => {
return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
})
.join('\n')
});
sections.push({
title: `For more info, run any command with the \`--help\` flag`,
body: commands
.map(command => ` $ ${name}${command.name === '' ? '' : ` ${command.name}`} --help`)
.join('\n')
});
}
checkUnknownOptions() {
const {options, globalCommand} = this.cli;
if (!this.config.allowUnknownOptions) {
for (const name of Object.keys(options)) {
if (name !== "--" && !this.hasOption(name) && !globalCommand.hasOption(name)) {
throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
}
const options = this.isGlobalCommand
? globalOptions
: [...this.options, ...(globalOptions || [])];
if (options.length > 0) {
const longestOptionName = findLongest(options.map(option => option.rawName));
sections.push({
title: 'Options',
body: options
.map(option => {
return ` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === undefined
? ''
: `(default: ${option.config.default})`}`;
})
.join('\n')
});
}
if (this.examples.length > 0) {
sections.push({
title: 'Examples',
body: this.examples
.map(example => {
if (typeof example === 'function') {
return example(name);
}
return example;
})
.join('\n')
});
}
if (helpCallback) {
helpCallback(sections);
}
console.log(sections
.map(section => {
return section.title
? `${section.title}:\n${section.body}`
: section.body;
})
.join('\n\n'));
}
}
outputVersion() {
const { name } = this.cli;
const { versionNumber } = this.cli.globalCommand;
if (versionNumber) {
console.log(`${name}/${versionNumber} ${platformInfo}`);
}
checkOptionValue() {
const {options: parsedOptions, globalCommand} = this.cli;
const options = [...globalCommand.options, ...this.options];
for (const option of options) {
const value = parsedOptions[option.name.split(".")[0]];
if (option.required) {
const hasNegated = options.some((o) => o.negated && o.names.includes(option.name));
if (value === true || value === false && !hasNegated) {
throw new CACError(`option \`${option.rawName}\` value is missing`);
}
}
}
checkRequiredArgs() {
const minimalArgsCount = this.args.filter(arg => arg.required).length;
if (this.cli.args.length < minimalArgsCount) {
throw new CACError(`missing required args for command \`${this.rawName}\``);
}
}
/**
* Check if the parsed options contain any unknown options
*
* Exit and output error when true
*/
checkUnknownOptions() {
const { options, globalCommand } = this.cli;
if (!this.config.allowUnknownOptions) {
for (const name of Object.keys(options)) {
if (name !== '--' &&
!this.hasOption(name) &&
!globalCommand.hasOption(name)) {
throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
}
}
}
}
/**
* Check if the required string-type options exist
*/
checkOptionValue() {
const { options: parsedOptions, globalCommand } = this.cli;
const options = [...globalCommand.options, ...this.options];
for (const option of options) {
const value = parsedOptions[option.name.split('.')[0]];
// Check required option value
if (option.required) {
const hasNegated = options.some(o => o.negated && o.names.includes(option.name));
if (value === true || (value === false && !hasNegated)) {
throw new CACError(`option \`${option.rawName}\` value is missing`);
}
}
}
}
}
}
class GlobalCommand extends Command {
constructor(cli) {
super('@@global@@', '', {}, cli);
}
constructor(cli) {
super("@@global@@", "", {}, cli);
}
}
let __assign = Object.assign;
class CAC extends events_1 {
/**
* @param name The program name to display in help and version message
*/
constructor(name = '') {
super();
this.name = name;
this.commands = [];
this.globalCommand = new GlobalCommand(this);
this.globalCommand.usage('<command> [options]');
constructor(name = "") {
super();
this.name = name;
this.commands = [];
this.globalCommand = new GlobalCommand(this);
this.globalCommand.usage("<command> [options]");
}
usage(text) {
this.globalCommand.usage(text);
return this;
}
command(rawName, description, config) {
const command = new Command(rawName, description || "", config, this);
command.globalCommand = this.globalCommand;
this.commands.push(command);
return command;
}
option(rawName, description, config) {
this.globalCommand.option(rawName, description, config);
return this;
}
help(callback) {
this.globalCommand.option("-h, --help", "Display this message");
this.globalCommand.helpCallback = callback;
this.showHelpOnExit = true;
return this;
}
version(version, customFlags = "-v, --version") {
this.globalCommand.version(version, customFlags);
this.showVersionOnExit = true;
return this;
}
example(example) {
this.globalCommand.example(example);
return this;
}
outputHelp() {
if (this.matchedCommand) {
this.matchedCommand.outputHelp();
} else {
this.globalCommand.outputHelp();
}
/**
* Add a global usage text.
*
* This is not used by sub-commands.
*/
usage(text) {
this.globalCommand.usage(text);
return this;
}
outputVersion() {
this.globalCommand.outputVersion();
}
setParsedInfo({args, options}, matchedCommand, matchedCommandName) {
this.args = args;
this.options = options;
if (matchedCommand) {
this.matchedCommand = matchedCommand;
}
/**
* Add a sub-command
*/
command(rawName, description, config) {
const command = new Command(rawName, description || '', config, this);
command.globalCommand = this.globalCommand;
this.commands.push(command);
return command;
if (matchedCommandName) {
this.matchedCommandName = matchedCommandName;
}
/**
* Add a global CLI option.
*
* Which is also applied to sub-commands.
*/
option(rawName, description, config) {
this.globalCommand.option(rawName, description, config);
return this;
return this;
}
parse(argv = processArgs, {run = true} = {}) {
this.rawArgs = argv;
if (!this.name) {
this.name = argv[1] ? getFileName(argv[1]) : "cli";
}
/**
* Show help message when `-h, --help` flags appear.
*
*/
help(callback) {
this.globalCommand.option('-h, --help', 'Display this message');
this.globalCommand.helpCallback = callback;
this.showHelpOnExit = true;
return this;
let shouldParse = true;
for (const command of this.commands) {
const parsed = this.mri(argv.slice(2), command);
const commandName = parsed.args[0];
if (command.isMatched(commandName)) {
shouldParse = false;
const parsedInfo = __assign(__assign({}, parsed), {
args: parsed.args.slice(1)
});
this.setParsedInfo(parsedInfo, command, commandName);
this.emit(`command:${commandName}`, command);
}
}
/**
* Show version number when `-v, --version` flags appear.
*
*/
version(version, customFlags = '-v, --version') {
this.globalCommand.version(version, customFlags);
this.showVersionOnExit = true;
return this;
if (shouldParse) {
for (const command of this.commands) {
if (command.name === "") {
shouldParse = false;
const parsed = this.mri(argv.slice(2), command);
this.setParsedInfo(parsed, command);
this.emit(`command:!`, command);
}
}
}
/**
* Add a global example.
*
* This example added here will not be used by sub-commands.
*/
example(example) {
this.globalCommand.example(example);
return this;
if (shouldParse) {
const parsed = this.mri(argv.slice(2));
this.setParsedInfo(parsed);
}
/**
* Output the corresponding help message
* When a sub-command is matched, output the help message for the command
* Otherwise output the global one.
*
*/
outputHelp() {
if (this.matchedCommand) {
this.matchedCommand.outputHelp();
}
else {
this.globalCommand.outputHelp();
}
if (this.options.help && this.showHelpOnExit) {
this.outputHelp();
run = false;
}
/**
* Output the version number.
*
*/
outputVersion() {
this.globalCommand.outputVersion();
if (this.options.version && this.showVersionOnExit) {
this.outputVersion();
run = false;
}
setParsedInfo({ args, options }, matchedCommand, matchedCommandName) {
this.args = args;
this.options = options;
if (matchedCommand) {
this.matchedCommand = matchedCommand;
}
if (matchedCommandName) {
this.matchedCommandName = matchedCommandName;
}
return this;
const parsedArgv = {
args: this.args,
options: this.options
};
if (run) {
this.runMatchedCommand();
}
/**
* Parse argv
*/
parse(argv = processArgs, {
/** Whether to run the action for matched command */
run = true } = {}) {
this.rawArgs = argv;
if (!this.name) {
this.name = argv[1] ? getFileName(argv[1]) : 'cli';
}
let shouldParse = true;
// Search sub-commands
for (const command of this.commands) {
const parsed = this.mri(argv.slice(2), command);
const commandName = parsed.args[0];
if (command.isMatched(commandName)) {
shouldParse = false;
const parsedInfo = Object.assign({}, parsed, { args: parsed.args.slice(1) });
this.setParsedInfo(parsedInfo, command, commandName);
this.emit(`command:${commandName}`, command);
}
}
if (shouldParse) {
// Search the default command
for (const command of this.commands) {
if (command.name === '') {
shouldParse = false;
const parsed = this.mri(argv.slice(2), command);
this.setParsedInfo(parsed, command);
this.emit(`command:!`, command);
}
}
}
if (shouldParse) {
const parsed = this.mri(argv.slice(2));
this.setParsedInfo(parsed);
}
if (this.options.help && this.showHelpOnExit) {
this.outputHelp();
run = false;
}
if (this.options.version && this.showVersionOnExit) {
this.outputVersion();
run = false;
}
const parsedArgv = { args: this.args, options: this.options };
if (run) {
this.runMatchedCommand();
}
if (!this.matchedCommand && this.args[0]) {
this.emit('command:*');
}
return parsedArgv;
if (!this.matchedCommand && this.args[0]) {
this.emit("command:*");
}
mri(argv,
/** Matched command */ command) {
// All added options
const cliOptions = [
...this.globalCommand.options,
...(command ? command.options : [])
];
const mriOptions = getMriOptions(cliOptions);
// Extract everything after `--` since mri doesn't support it
let argsAfterDoubleDashes = [];
const doubleDashesIndex = argv.indexOf('--');
if (doubleDashesIndex > -1) {
argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
argv = argv.slice(0, doubleDashesIndex);
return parsedArgv;
}
mri(argv, command) {
const cliOptions = [...this.globalCommand.options, ...command ? command.options : []];
const mriOptions = getMriOptions(cliOptions);
let argsAfterDoubleDashes = [];
const doubleDashesIndex = argv.indexOf("--");
if (doubleDashesIndex > -1) {
argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
argv = argv.slice(0, doubleDashesIndex);
}
let parsed = lib(argv, mriOptions);
parsed = Object.keys(parsed).reduce((res, name) => {
return __assign(__assign({}, res), {
[camelcaseOptionName(name)]: parsed[name]
});
}, {
_: []
});
const args = parsed._;
delete parsed._;
const options = {
"--": argsAfterDoubleDashes
};
const ignoreDefault = command && command.config.ignoreOptionDefaultValue ? command.config.ignoreOptionDefaultValue : this.globalCommand.config.ignoreOptionDefaultValue;
let transforms = Object.create(null);
for (const cliOption of cliOptions) {
if (!ignoreDefault && cliOption.config.default !== void 0) {
for (const name of cliOption.names) {
options[name] = cliOption.config.default;
}
let parsed = lib(argv, mriOptions);
parsed = Object.keys(parsed).reduce((res, name) => {
return Object.assign({}, res, { [camelcaseOptionName(name)]: parsed[name] });
}, { _: [] });
const args = parsed._;
delete parsed._;
const options = {
'--': argsAfterDoubleDashes
};
// Set option default value
const ignoreDefault = command && command.config.ignoreOptionDefaultValue
? command.config.ignoreOptionDefaultValue
: this.globalCommand.config.ignoreOptionDefaultValue;
let transforms = Object.create(null);
for (const cliOption of cliOptions) {
if (!ignoreDefault && cliOption.config.default !== undefined) {
for (const name of cliOption.names) {
options[name] = cliOption.config.default;
}
}
// If options type is defined
if (Array.isArray(cliOption.config.type)) {
if (transforms[cliOption.name] === undefined) {
transforms[cliOption.name] = Object.create(null);
transforms[cliOption.name]['shouldTransform'] = true;
transforms[cliOption.name]['transformFunction'] =
cliOption.config.type[0];
}
}
}
if (Array.isArray(cliOption.config.type)) {
if (transforms[cliOption.name] === void 0) {
transforms[cliOption.name] = Object.create(null);
transforms[cliOption.name]["shouldTransform"] = true;
transforms[cliOption.name]["transformFunction"] = cliOption.config.type[0];
}
// Set dot nested option values
for (const key of Object.keys(parsed)) {
const keys = key.split('.');
setDotProp(options, keys, parsed[key]);
setByType(options, transforms);
}
return {
args,
options
};
}
}
runMatchedCommand() {
const { args, options, matchedCommand: command } = this;
if (!command || !command.commandAction)
return;
command.checkUnknownOptions();
command.checkOptionValue();
command.checkRequiredArgs();
const actionArgs = [];
command.args.forEach((arg, index) => {
if (arg.variadic) {
actionArgs.push(args.slice(index));
}
else {
actionArgs.push(args[index]);
}
});
actionArgs.push(options);
return command.commandAction.apply(this, actionArgs);
for (const key of Object.keys(parsed)) {
const keys = key.split(".");
setDotProp(options, keys, parsed[key]);
setByType(options, transforms);
}
return {
args,
options
};
}
runMatchedCommand() {
const {args, options, matchedCommand: command} = this;
if (!command || !command.commandAction)
return;
command.checkUnknownOptions();
command.checkOptionValue();
command.checkRequiredArgs();
const actionArgs = [];
command.args.forEach((arg, index) => {
if (arg.variadic) {
actionArgs.push(args.slice(index));
} else {
actionArgs.push(args[index]);
}
});
actionArgs.push(options);
return command.commandAction.apply(this, actionArgs);
}
}
/**
* @param name The program name to display in help and version message
*/
const cac = (name = '') => new CAC(name);
if (typeof module !== 'undefined') {
module.exports = cac;
module.exports.default = cac;
module.exports.cac = cac;
const cac = (name = "") => new CAC(name);
if (typeof module !== "undefined") {
module.exports = cac;
module.exports.default = cac;
module.exports.cac = cac;
}

@@ -1155,0 +1025,0 @@

{
"name": "cac",
"version": "6.5.8",
"version": "6.5.9",
"description": "Simple yet powerful framework for building command-line apps.",

@@ -10,8 +10,8 @@ "repository": {

"main": "dist/index.js",
"types": "types/index.d.ts",
"types": "dist/index.d.ts",
"files": [
"dist",
"types",
"!**/__test__/**",
"/mod.js"
"/mod.js",
"/mod.d.ts"
],

@@ -21,3 +21,3 @@ "scripts": {

"test:cov": "jest --coverage",
"build": "tsc -m ESNext && rollup -c",
"build": "rollup -c",
"toc": "markdown-toc -i README.md",

@@ -30,2 +30,4 @@ "prepublishOnly": "npm run build",

"devDependencies": {
"@rollup/plugin-commonjs": "^11.1.0",
"@rollup/plugin-node-resolve": "^7.1.3",
"@types/execa": "^0.9.0",

@@ -44,10 +46,10 @@ "@types/jest": "^23.3.9",

"prettier": "^1.15.2",
"rollup": "^1.32.0",
"@rollup/plugin-commonjs": "^11.0.2",
"@rollup/plugin-node-resolve": "^7.1.1",
"rollup": "^2.10.0",
"rollup-plugin-dts": "^1.4.3",
"rollup-plugin-esbuild": "^1.4.1",
"semantic-release": "^15.12.1",
"ts-jest": "^23.10.5",
"ts-node": "^7.0.1",
"typedoc": "^0.13.0",
"typescript": "^3.1.6"
"typedoc": "^0.17.6",
"typescript": "^3.9.2"
},

@@ -54,0 +56,0 @@ "engines": {

@@ -284,5 +284,6 @@ <img width="945" alt="2017-07-26 9 27 05" src="https://user-images.githubusercontent.com/8784712/28623641-373450f4-7249-11e7-854d-1b076dab274d.png">

```ts
// deno-types="https://unpkg.com/cac/mod.d.ts"
import { cac } from 'https://unpkg.com/cac/mod.js'
// ...
const cli = cac('my-program')
```

@@ -461,3 +462,3 @@

cli.on('command:*', () => {
console.error('Invalid command: %', cli.args.join(' '))
console.error('Invalid command: %s', cli.args.join(' '))
process.exit(1)

@@ -464,0 +465,0 @@ })

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc