Socket
Socket
Sign inDemoInstall

cmdln

Package Overview
Dependencies
5
Maintainers
1
Versions
50
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.4.0 to 5.0.0

67

CHANGES.md

@@ -7,2 +7,69 @@ # node-cmdln Changelog

## 5.0.0
- [Backward incompatible change, issue #12] Cmdln's dispatch to `do_*`
subcommand handler functions is no longer wrapped in a try/catch block, which
means that exceptions from programmer errors will no longer be swallowed.
Before this change a programmer error could not be distinguished from a
command calling back with a runtime error.
Take this example:
```javascript
var util = require('util');
var cmdln = require('.');
function CLI() {
cmdln.Cmdln.call(this, {name: 'boom'});
}
util.inherits(CLI, cmdln.Cmdln);
CLI.prototype.do_hi = function (subcmd, opts, args, cb) {
someMissingHelperFunction(); // OOPS
cb();
};
if (require.main === module) {
cmdln.main(new CLI());
}
```
Before cmdln v5:
```shell
$ node boom.js hi
boom: error: someMissingHelperFunction is not defined
$ echo $?
1
```
And as of this change:
```
$ node boom.js hi
/Users/trentm/tm/node-cmdln/boom.js:10
someMissingHelperFunction();
^
ReferenceError: someMissingHelperFunction is not defined
at CLI.do_hi (/Users/trentm/tm/node-cmdln/boom.js:10:5)
at CLI.dispatch (/Users/trentm/tm/node-cmdln/lib/cmdln.js:1315:17)
at mainInit (/Users/trentm/tm/node-cmdln/lib/cmdln.js:727:14)
at CLI.init (/Users/trentm/tm/node-cmdln/lib/cmdln.js:965:5)
at CLI.cmdlnMain [as main] (/Users/trentm/tm/node-cmdln/lib/cmdln.js:702:10)
at Object.main (/Users/trentm/tm/node-cmdln/lib/cmdln.js:1493:9)
at Object.<anonymous> (/Users/trentm/tm/node-cmdln/boom.js:15:11)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
$ echo $?
1
```
- Switch testing to node-tap (requires node v6 to run test suite).
- Drop "support" for node 0.8.
- Switch checking/formatting to eslint/prettier.
## 4.4.0

@@ -9,0 +76,0 @@

606

lib/cmdln.js
/*
* Copyright (c) 2018, Trent Mick
* Copyright (c) 2018, Joyent, Inc.
* Copyright 2019 Trent Mick
* Copyright 2019 Joyent, Inc.
*/

@@ -11,3 +11,3 @@

} else {
debug = function () {};
debug = function _internalDebug() {};
}

@@ -17,8 +17,2 @@

format = util.format;
var p = console.warn;
var child_process = require('child_process'),
spawn = child_process.spawn,
exec = child_process.exec;
var os = require('os');
var path = require('path');
var fs = require('fs');

@@ -32,4 +26,2 @@

// ---- globals

@@ -50,6 +42,5 @@

// ---- internal support stuff
function indent(s, indentation) {
function indentLines(s, indentation) {
if (!indentation) {

@@ -74,3 +65,3 @@ indentation = ' ';

}
Object.keys(obj).forEach(function (k) {
Object.keys(obj).forEach(function onKey(k) {
target[k] = obj[k];

@@ -100,6 +91,5 @@ });

// Replace {{variable}} in `s` with the template data in `d`.
function renderTemplate(s, d) {
return s.replace(/{{([a-zA-Z]+)}}/g, function (match, key) {
return s.replace(/{{([a-zA-Z]+)}}/g, function onVar(match, key) {
return d.hasOwnProperty(key) ? d[key] : match;

@@ -109,3 +99,2 @@ });

// ---- Errors

@@ -125,3 +114,5 @@

assert.optionalString(options.code, 'options.code');
if (!options.code) options.code = 'Cmdln';
if (!options.code) {
options.code = 'Cmdln';
}
assert.optionalObject(options.cause, 'options.cause');

@@ -131,9 +122,12 @@ var self = this;

var args = [];
if (options.cause) args.push(options.cause);
if (options.cause) {
args.push(options.cause);
}
args.push(options.message);
WError.apply(this, args);
var extra = Object.keys(options).filter(
function (k) { return ['cause', 'message'].indexOf(k) === -1; });
extra.forEach(function (k) {
var extra = Object.keys(options).filter(function onKey(k) {
return ['cause', 'message'].indexOf(k) === -1;
});
extra.forEach(function onExtra(k) {
self[k] = options[k];

@@ -145,3 +139,2 @@ });

/*

@@ -204,11 +197,9 @@ * An error returned when there is an error parsing a command or subcmd's

}
lines.push(line + ' ...'); // The "..." for the args.
lines.push(line + ' ...'); // The "..." for the args.
errHelp = lines.join('\n');
}
return errHelp;
};
/*

@@ -252,3 +243,4 @@ * An error returned when there is a subcmd usage error (wrong args).

var synopses = err._cmdlnInst.synopsesFromSubcmd(
err._cmdlnSubcmd || err._cmdlnInst);
err._cmdlnSubcmd || err._cmdlnInst
);
if (synopses.length === 1) {

@@ -262,3 +254,2 @@ errHelp = 'usage: ' + synopses[0];

function UnknownCommandError(cause, command) {

@@ -291,4 +282,5 @@ if (command === undefined) {

*/
UnknownCommandError.prototype.cmdlnErrHelpFromErr =
function ucErrHelpFromErr(err) {
UnknownCommandError.prototype.cmdlnErrHelpFromErr = function ucErrHelpFromErr(
err
) {
if (!err || !err._cmdlnInst) {

@@ -300,3 +292,4 @@ return '';

var FuzzySet = require('fuzzyset.js');
} catch (requireErr) {
} catch (_requireErr) {
// Silently provide no suggestions if don't have this dep.
return '';

@@ -309,7 +302,8 @@ }

var ge50 = [];
candidates && candidates.forEach(function (candidate) {
if (candidate[0] >= 0.3) {
ge50.push(candidate[1]);
}
});
candidates &&
candidates.forEach(function onCandidate(candidate) {
if (candidate[0] >= 0.3) {
ge50.push(candidate[1]);
}
});
if (ge50.length > 0) {

@@ -322,3 +316,2 @@ errHelp = 'Did you mean this?\n ' + ge50.join('\n ');

function NoCommandError() {

@@ -334,3 +327,2 @@ CmdlnError.call(this, {

/**

@@ -374,3 +366,3 @@ * # errHelp

* var cli = new MyCmdlnSubclass();
* cli.main(argv, function (err) {
* cli.main(argv, function finish(err) {
* if (err) {

@@ -398,10 +390,9 @@ * console.error('%s: error: %s', cli.name, err.message);

if (err && typeof (err.cmdlnErrHelpFromErr) === 'function') {
if (err && typeof err.cmdlnErrHelpFromErr === 'function') {
errHelp = err.cmdlnErrHelpFromErr(err);
}
return (errHelp || '');
};
return errHelp || '';
}
/**

@@ -416,3 +407,3 @@ * Return the full command name (e.g. 'triton instance list') at which the

if (err._cmdlnHandler) {
if (typeof (err._cmdlnHandler) === 'object') {
if (typeof err._cmdlnHandler === 'object') {
name = err._cmdlnHandler.name;

@@ -426,3 +417,2 @@ } else if (err._cmdlnSubcmd) {

// ---- Cmdln object

@@ -477,8 +467,8 @@

config = config || {};
assert.optionalString(config.name, 'config.name')
assert.optionalString(config.desc, 'config.desc')
assert.optionalString(config.name, 'config.name');
assert.optionalString(config.desc, 'config.desc');
assert.optionalArrayOfObject(config.options, 'config.options');
assert.optionalArrayOfString(config.synopses, 'config.synopses');
assert.optionalObject(config.helpOpts, 'config.helpOpts')
assert.optionalString(config.helpBody, 'config.helpBody')
assert.optionalObject(config.helpOpts, 'config.helpOpts');
assert.optionalString(config.helpBody, 'config.helpBody');
assert.optionalObject(config.helpSubcmds, 'config.helpSubcmds');

@@ -493,18 +483,27 @@

this.helpSubcmds = config.helpSubcmds || null;
if (!this.helpOpts.indent)
if (!this.helpOpts.indent) {
this.helpOpts.indent = space(4);
else if (typeof (this.helpOpts.indent) === 'number')
} else if (typeof this.helpOpts.indent === 'number') {
this.helpOpts.indent = space(this.helpOpts.indent);
}
if (!this.helpOpts.groupIndent) {
var gilen = Math.round(this.helpOpts.indent.length / 2);
this.helpOpts.groupIndent = space(gilen);
} else if (typeof (this.helpOpts.groupIndent) === 'number') {
} else if (typeof this.helpOpts.groupIndent === 'number') {
this.helpOpts.groupIndent = space(this.helpOpts.groupIndent);
}
if (!this.helpOpts.maxCol) this.helpOpts.maxCol = 80;
if (!this.helpOpts.minHelpCol) this.helpOpts.minHelpCol = 20;
if (!this.helpOpts.maxHelpCol) this.helpOpts.maxHelpCol = 40;
if (!this.helpOpts.maxCol) {
this.helpOpts.maxCol = 80;
}
if (!this.helpOpts.minHelpCol) {
this.helpOpts.minHelpCol = 20;
}
if (!this.helpOpts.maxHelpCol) {
this.helpOpts.maxHelpCol = 40;
}
this.optParser = new dashdash.Parser(
{options: this.options, interspersed: false});
this.optParser = new dashdash.Parser({
options: this.options,
interspersed: false
});

@@ -526,10 +525,12 @@ // Find the tree of constructors (typically just this and the Cmdln

this._nameFromAlias = {};
prototypes.forEach(function (proto) {
prototypes.forEach(function onProto(proto) {
Object.keys(proto)
.filter(function (funcname) { return /^do_/.test(funcname); })
.forEach(function (funcname) {
.filter(function onProp(funcname) {
return /^do_/.test(funcname);
})
.forEach(function onDoFunc(funcname) {
var name = self.subcmdFromFuncname(funcname);
var func = proto[funcname];
var allAliases;
if (func.prototype.__proto__ === Cmdln.prototype) {
if (func.prototype instanceof Cmdln) {
/**

@@ -552,8 +553,14 @@ * This is a `Cmdln` sub-class. Create the sub-Cmdln

*/
['options', 'help'].forEach(function (prop) {
['options', 'help'].forEach(function onProp(prop) {
if (func.hasOwnProperty(prop)) {
throw new Error(format(
'cannot set "%s.prototype.do_%s.%s" property '
+ 'because "do_%s" is a sub-Cmdln handler',
self.constructor.name, name, prop, name));
throw new Error(
format(
'cannot set "%s.prototype.do_%s.%s" property ' +
'because "do_%s" is a sub-Cmdln handler',
self.constructor.name,
name,
prop,
name
)
);
}

@@ -563,5 +570,6 @@ });

// Copy class properies like 'alias', 'hidden', etc.
for (prop in func) {
if (prop === 'super_')
for (var prop in func) {
if (prop === 'super_') {
continue;
}
handler[prop] = func[prop];

@@ -578,9 +586,16 @@ }

allAliases = func.aliases || [];
if (func.hiddenAliases)
if (func.hiddenAliases) {
allAliases = allAliases.concat(func.hiddenAliases);
allAliases.forEach(function (alias) {
}
allAliases.forEach(function onAlias(alias) {
if (self._nameFromAlias[alias]) {
throw new Error(format('ambiguous alias "%s": ' +
'refers to commands "%s" and "%s"', alias,
name, self._nameFromAlias[alias]));
throw new Error(
format(
'ambiguous alias "%s": ' +
'refers to commands "%s" and "%s"',
alias,
name,
self._nameFromAlias[alias]
)
);
}

@@ -599,3 +614,3 @@ self._nameFromAlias[alias] = name;

var matchedNames = [];
enumOrder.forEach(function (enumName) {
enumOrder.forEach(function onSubcmdName(enumName) {
if (self.helpSubcmds.indexOf(enumName) === -1) {

@@ -610,4 +625,4 @@ unmatchedNames.push(enumName);

self._subcmdOrder = [];
self.helpSubcmds.forEach(function (sc) {
if (typeof (sc) === 'object') {
self.helpSubcmds.forEach(function onHelpSubcmd(sc) {
if (typeof sc === 'object') {
assert.string(sc.group, 'helpSubcmds.*.group');

@@ -620,4 +635,9 @@ assert.optionalBool(sc.unmatched, 'helpSubcmds.*.unmatched');

if (++unmatchCount > 1) {
throw (new Error(format('"unmatched" directive used ' +
'more than once in "helpSubcmds" option: %j', sc)));
throw new Error(
format(
'"unmatched" directive used ' +
'more than once in "helpSubcmds" option: %j',
sc
)
);
}

@@ -641,4 +661,7 @@

if (matchedNames.indexOf(sc) === -1) {
throw (new Error('command handler included in help order ' +
'but not found: ' + sc));
throw new Error(
'command handler included in help order ' +
'but not found: ' +
sc
);
}

@@ -649,4 +672,8 @@ self._subcmdOrder.push(sc);

if (unmatchedNames.length > 0) {
throw (new Error('"helpSubcmds" error: unmatched command ' +
'handlers found: ' + unmatchedNames.join(', ') + '.'));
throw new Error(
'"helpSubcmds" error: unmatched command ' +
'handlers found: ' +
unmatchedNames.join(', ') +
'.'
);
}

@@ -656,9 +683,4 @@ } else {

}
// p('_subcmdOrder:', this._subcmdOrder);
// p('_handlerFromName: ', this._handlerFromName);
// p('_nameFromAlias: ', this._nameFromAlias);
}
/**

@@ -690,3 +712,3 @@ * Cmdln mainline.

var decoErrAndCb = function (err) {
var decoErrAndCb = function decoErrAndCb(err) {
if (err && !err._cmdlnInst) {

@@ -698,9 +720,9 @@ err._cmdlnInst = self;

var finiAndCb = function (err, subcmd) {
var finiAndCb = function finiAndCb(err, subcmd) {
debug('-> <%s>.fini(%j, err=%s)', self.name, subcmd, err);
self.fini(subcmd, err, function (finiErr) {
self.fini(subcmd, err, function mainFini(finiErr) {
debug('<- <%s>.fini: finiErr=%s', self.name, finiErr);
decoErrAndCb(finiErr || err);
});
}
};

@@ -716,4 +738,4 @@ try {

debug('-> <%s>.init(%j, %j)', self.name, this.opts, args);
self.init(this.opts, args, function (initErr) {
debug('<- <%s>.init: initErr=%s', self.name, initErr)
self.init(this.opts, args, function mainInit(initErr) {
debug('<- <%s>.init: initErr=%s', self.name, initErr);
if (initErr) {

@@ -726,3 +748,3 @@ finiAndCb(initErr);

finiAndCb();
return
return;
}

@@ -737,27 +759,24 @@

var subcmd = args.shift();
try {
debug('-> <%s>.dispatch({subcmd: %j, argv: %j})',
self.name, subcmd, subcmdArgv);
self.dispatch({subcmd: subcmd, argv: subcmdArgv},
function (dispErr) {
debug('<- <%s>.dispatch: dispErr=%s',
self.name, dispErr);
/*
* Do in nextTick to assure that we do not callback twice
* if (a) dispatch returns synchronously and (b) there is
* an exception raised during `finiAndCb`.
*/
process.nextTick(function () {
finiAndCb(dispErr, subcmd);
});
});
} catch (ex) {
debug('<- <%s>.dispatch crash: ex=%s', self.name, ex);
finiAndCb(ex, subcmd);
}
debug(
'-> <%s>.dispatch({subcmd: %j, argv: %j})',
self.name,
subcmd,
subcmdArgv
);
self.dispatch({subcmd: subcmd, argv: subcmdArgv}, function mainDispatch(
dispErr
) {
debug('<- <%s>.dispatch: dispErr=%s', self.name, dispErr);
/*
* Do in nextTick to assure that we do not callback twice
* if (a) dispatch returns synchronously and (b) there is
* an exception raised during `finiAndCb`.
*/
process.nextTick(function mainDispatchNextTick() {
finiAndCb(dispErr, subcmd);
});
});
});
};
/* BEGIN JSSTYLED */

@@ -825,32 +844,37 @@ /**

var context = opts.context || '';
var includeHidden = (opts.includeHidden === undefined
? false : opts.includeHidden);
var includeHidden =
opts.includeHidden === undefined ? false : opts.includeHidden;
// Top-level.
spec.push(dashdash.bashCompletionSpecFromOptions({
options: self.options,
context: context,
includeHidden: includeHidden
}));
spec.push(
dashdash.bashCompletionSpecFromOptions({
options: self.options,
context: context,
includeHidden: includeHidden
})
);
var aliases = [];
var allAliases = [];
Object.keys(this._nameFromAlias).sort().forEach(function (alias) {
if (alias === '?') {
// '?' as a Bash completion is painful. Also, '?' as a default
// alias for 'help' should die.
return;
}
Object.keys(this._nameFromAlias)
.sort()
.forEach(function onAlias(alias) {
if (alias === '?') {
// '?' as a Bash completion is painful. Also, '?' as a default
// alias for 'help' should die.
return;
}
var name = self._nameFromAlias[alias];
var handler = self._handlerFromName[name];
var name = self._nameFromAlias[alias];
var handler = self._handlerFromName[name];
if (includeHidden || !handler.hidden) {
aliases.push(alias);
}
allAliases.push(alias);
});
if (includeHidden || !handler.hidden) {
aliases.push(alias);
}
allAliases.push(alias);
});
spec.push(format('local cmd%s_subcmds="%s"', context, aliases.join(' ')));
spec.push(format('local cmd%s_allsubcmds="%s"', context,
allAliases.join(' ')));
spec.push(
format('local cmd%s_allsubcmds="%s"', context, allAliases.join(' '))
);

@@ -860,37 +884,48 @@ // Subcmds.

// one has specified a hidden subcmd you get full completion under it.
Object.keys(this._nameFromAlias).sort().forEach(function (alias) {
if (alias === '?') {
return;
}
spec.push('');
var context_ = context + '__' + alias.replace(/-/g, '_');
var name = self._nameFromAlias[alias];
var handler = self._handlerFromName[name];
Object.keys(this._nameFromAlias)
.sort()
.forEach(function onAlias(alias) {
if (alias === '?') {
return;
}
spec.push('');
var context_ = context + '__' + alias.replace(/-/g, '_');
var name = self._nameFromAlias[alias];
var handler = self._handlerFromName[name];
if (typeof (handler.bashCompletionSpec) === 'function') {
// This is a `Cmdln` subclass, i.e. a sub-CLI.
var subspec = handler.bashCompletionSpec({
context: context_,
includeHidden: opts.includeHidden
});
if (subspec) {
spec.push(subspec);
if (typeof handler.bashCompletionSpec === 'function') {
// This is a `Cmdln` subclass, i.e. a sub-CLI.
var subspec = handler.bashCompletionSpec({
context: context_,
includeHidden: opts.includeHidden
});
if (subspec) {
spec.push(subspec);
}
} else {
if (handler.completionArgtypes) {
assert.arrayOfString(
handler.completionArgtypes,
'do_' + name + '.completionArgtypes'
);
spec.push(
format(
'local cmd%s_argtypes="%s"',
context_,
handler.completionArgtypes.join(' ')
)
);
}
spec.push(
dashdash.bashCompletionSpecFromOptions({
options: handler.options || [],
context: context_,
includeHidden: includeHidden
})
);
}
} else {
if (handler.completionArgtypes) {
assert.arrayOfString(handler.completionArgtypes,
'do_' + name + '.completionArgtypes');
spec.push(format('local cmd%s_argtypes="%s"',
context_, handler.completionArgtypes.join(' ')));
}
spec.push(dashdash.bashCompletionSpecFromOptions({
options: handler.options || [],
context: context_,
includeHidden: includeHidden
}));
}
});
});
return spec.join('\n');
}
};

@@ -930,7 +965,8 @@ /**

var template = fs.readFileSync(
dashdash.BASH_COMPLETION_TEMPLATE_PATH, 'utf8');
dashdash.BASH_COMPLETION_TEMPLATE_PATH,
'utf8'
);
return renderTemplate(template, data);
};
/**

@@ -945,3 +981,3 @@ * Handler called for an empty line of input. By default this prints help

Cmdln.prototype.emptyLine = function emptyLine(callback) {
this.printHelp(function (helpErr) {
this.printHelp(function onFinish(helpErr) {
callback(helpErr || new NoCommandError());

@@ -951,3 +987,2 @@ });

/**

@@ -968,3 +1003,3 @@ * Post-option processing initialization of this Cmdln instance.

if (opts.help) {
this.do_help(args[0], opts, [], function (helpErr) {
this.do_help(args[0], opts, [], function onFinish(helpErr) {
callback(helpErr || false);

@@ -977,3 +1012,2 @@ });

/**

@@ -988,7 +1022,6 @@ * Hook run after the subcommand handler is run.

*/
Cmdln.prototype.fini = function fini(subcmd, err, callback) {
Cmdln.prototype.fini = function fini(_subcmd, _err, callback) {
callback();
};
/**

@@ -1014,6 +1047,3 @@ * Print top-level tool help.

lines = lines.concat([
this._renderHelp('{{usage}}', this),
''
]);
lines = lines.concat([this._renderHelp('{{usage}}', this), '']);
if (this.optParser.help) {

@@ -1024,11 +1054,12 @@ lines.push('Options:');

lines = lines.concat([
'Commands:'
]);
lines = lines.concat(['Commands:']);
// Automatic command line from `this._handlerFromName`.
// TODO: same helpCol as for the opts above, textwrap, etc.
var cmdTemplate = format('%s%%-%ds %s',
indent, helpOpts.minHelpCol - indent.length - 2);
this._subcmdOrder.forEach(function (name, idx) {
if (typeof (name) === 'object') {
var cmdTemplate = format(
'%s%%-%ds %s',
indent,
helpOpts.minHelpCol - indent.length - 2
);
this._subcmdOrder.forEach(function onSubcmdName(name, idx) {
if (typeof name === 'object') {
if (idx > 0) {

@@ -1063,4 +1094,5 @@ /*

}
var summary = handler.desc ||
(typeof (handler.help) === 'string' && handler.help) ||
var summary =
handler.desc ||
(typeof handler.help === 'string' && handler.help) ||
'';

@@ -1084,3 +1116,2 @@ summary = summary.split('\n', 1)[0]; // just leading line

Cmdln.prototype.subcmdFromFuncname = function subcmdFromFuncname(funcname) {

@@ -1090,3 +1121,2 @@ return funcname.slice(3).replace(/_/g, '-');

/**

@@ -1100,3 +1130,3 @@ * Return the handler function for the given sub-command string (aka the

if (!name) {
return;
return undefined;
}

@@ -1106,3 +1136,2 @@ return this._handlerFromName[name];

/**

@@ -1129,3 +1158,3 @@ * Return the help content for the given sub-command string (aka the

if (handler.help) {
if (typeof (handler.help) === 'function') {
if (typeof handler.help === 'function') {
return handler.help;

@@ -1137,7 +1166,9 @@ } else {

// This is likely a `Cmdln` subclass.
return function subCliHelp(subcmd, opts, args, cb) {
handler.do_help('help', opts, args.slice(1), function (helpErr) {
return function subCliHelp(_subcmd, opts, args, cb) {
handler.do_help('help', opts, args.slice(1), function onHelp(
helpErr
) {
cb(helpErr || false);
});
}
};
} else {

@@ -1148,3 +1179,2 @@ return null;

Cmdln.prototype._renderHelp = function _renderHelp(template, handler, alias) {

@@ -1158,4 +1188,6 @@ assert.string(template, 'template');

if (synopses.length) {
help = help.replace('{{usage}}',
'Usage:\n' + indent(synopses.join('\n')));
help = help.replace(
'{{usage}}',
'Usage:\n' + indentLines(synopses.join('\n'))
);
}

@@ -1165,7 +1197,9 @@ }

var parser = new dashdash.Parser({options: handler.options});
var helpOpts = (handler.helpOpts
var helpOpts = handler.helpOpts
? objMerge(this.helpOpts, handler.helpOpts)
: this.helpOpts);
help = help.replace('{{options}}',
'Options:\n' + parser.help(helpOpts));
: this.helpOpts;
help = help.replace(
'{{options}}',
'Options:\n' + parser.help(helpOpts)
);
}

@@ -1204,9 +1238,9 @@ help = help.trimRight();

Cmdln.prototype.synopsesFromSubcmd = function synopsesFromSubcmd(subcmd) {
assert.ok(['function', 'string', 'object'].indexOf(typeof (subcmd)) !== -1);
assert.ok(['function', 'string', 'object'].indexOf(typeof subcmd) !== -1);
var name, handler;
if (typeof (subcmd) === 'function') {
if (typeof subcmd === 'function') {
handler = subcmd;
name = this.subcmdFromFuncname(handler.name);
} else if (typeof (subcmd) === 'object') {
} else if (typeof subcmd === 'object') {
name = subcmd.name;

@@ -1232,3 +1266,2 @@ handler = subcmd;

/**

@@ -1260,3 +1293,3 @@ * Dispatch to the appropriate "do_SUBCMD" function.

var subcmd, argv, opts, args;
if (typeof (callback) === 'function') {
if (typeof callback === 'function') {
// New call signature.

@@ -1280,15 +1313,7 @@ assert.string(dispatchOpts.subcmd, 'dispatchOpts.subcmd');

assert.func(callback, 'callback');
assert.ok((argv && !opts && !args) || (!argv && opts && args),
'must specify only one of "argv" *or* "opts/args"');
var self = this;
assert.ok(
(argv && !opts && !args) || (!argv && opts && args),
'must specify only one of "argv" *or* "opts/args"'
);
var finish = function (err) {
if (err) {
if (!err._cmdlnInst) err._cmdlnInst = self;
if (!err._cmdlnSubcmd && subcmd) err._cmdlnSubcmd = subcmd;
if (!err._cmdlnHandler && handler) err._cmdlnHandler = handler;
}
callback(err);
}
if (argv) {

@@ -1299,3 +1324,19 @@ opts = {};

var self = this;
var handler = this.handlerFromSubcmd(subcmd);
var finish = function finish(err) {
if (err) {
if (!err._cmdlnInst) {
err._cmdlnInst = self;
}
if (!err._cmdlnSubcmd && subcmd) {
err._cmdlnSubcmd = subcmd;
}
if (!err._cmdlnHandler && handler) {
err._cmdlnHandler = handler;
}
}
callback(err);
};
if (!handler) {

@@ -1306,8 +1347,8 @@ this.defaultHandler(subcmd, opts, args, finish);

if (typeof (handler.main) === 'function') {
if (typeof handler.main === 'function') {
// This is likely a `Cmdln` subclass instance, i.e. a subcli.
(function callCmdlnHandler(subcmd, opts, args, cb) {
var argv = ['', ''].concat(args);
handler.main(argv, cb);
}).call(this, subcmd, opts, args, finish);
(function callCmdlnHandler(_subcmd, _opts, subArgs, subCb) {
var subArgv = ['', ''].concat(subArgs);
handler.main(subArgv, subCb);
}.call(this, subcmd, opts, args, finish));
} else {

@@ -1321,6 +1362,10 @@ // This is a vanilla `do_SUBCMD` function on the Cmdln class.

options: handler.options,
interspersed: (handler.interspersedOptions !== undefined
? handler.interspersedOptions : true),
allowUnknown: (handler.allowUnknownOptions !== undefined
? handler.allowUnknownOptions : false)
interspersed:
handler.interspersedOptions !== undefined
? handler.interspersedOptions
: true,
allowUnknown:
handler.allowUnknownOptions !== undefined
? handler.allowUnknownOptions
: false
});

@@ -1340,3 +1385,7 @@ opts = parser.parse(argv, 3);

Cmdln.prototype.defaultHandler = function defaultHandler(
subcmd, opts, args, cb) {
subcmd,
opts,
args,
cb
) {
assert.string(subcmd, 'subcmd');

@@ -1362,10 +1411,6 @@ assert.optionalObject(opts, 'opts');

try {
var help = this.helpFromSubcmd(alias);
} catch (e) {
callback(e);
}
var help = this.helpFromSubcmd(alias);
if (!help) {
callback(new CmdlnError({message: format('no help for "%s"', alias)}));
} else if (typeof (help) === 'function') {
} else if (typeof help === 'function') {
help(subcmd, opts, args, callback);

@@ -1380,4 +1425,2 @@ } else {

// ---- convenience main function for a script

@@ -1459,3 +1502,3 @@

*/
if (typeof (cli) === 'function') {
if (typeof cli === 'function') {
cli = new cli();

@@ -1498,6 +1541,11 @@ var argv = options;

if (options.hasOwnProperty('finale')) {
assert.ok(VALID_FINALES.indexOf(options.finale) !== -1,
format('invalid options.finale "%s": valid values are "%s"',
options.finale, VALID_FINALES.join('", "')));
finale = options.finale
assert.ok(
VALID_FINALES.indexOf(options.finale) !== -1,
format(
'invalid options.finale "%s": valid values are "%s"',
options.finale,
VALID_FINALES.join('", "')
)
);
finale = options.finale;
} else {

@@ -1508,16 +1556,23 @@ finale = 'softexit';

assert.func(options.callback, 'options.callback');
assert.equal(finale, 'callback',
'options.callback provided, but options.finale is not "callback"');
assert.equal(
finale,
'callback',
'options.callback provided, but options.finale is not "callback"'
);
}
cli.main(options.argv, function (err) {
var exitStatus = (err ? err.exitStatus || 1 : 0);
cli.main(options.argv, function mainFinish(err) {
var exitStatus = err ? err.exitStatus || 1 : 0;
// We show (i.e. console.error) an error by default, unless turned
// off via `options.showErr` or `cli.showErr`.
var showErr = (options.showErr !== undefined ? options.showErr
: (cli.showErr !== undefined ? cli.showErr : true));
var showErr =
options.showErr !== undefined
? options.showErr
: cli.showErr !== undefined
? cli.showErr
: true;
if (err && showErr) {
var code = (err.body ? err.body.code : err.code);
var code = err.body ? err.body.code : err.code;
if (code === 'NoCommand' && !options.showNoCommandErr) {

@@ -1535,4 +1590,6 @@ /* jsl:pass */

// collected error messages.
var showErrStack = (options.showErrStack === undefined
? cli.showErrStack : options.showErrStack);
var showErrStack =
options.showErrStack === undefined
? cli.showErrStack
: options.showErrStack;

@@ -1543,11 +1600,14 @@ var errDetails;

if (err.ase_errors.length === 1) {
errDetails = (showErrStack
errDetails = showErrStack
? VError.fullStack(err.ase_errors[0])
: err.ase_errors[0].message);
: err.ase_errors[0].message;
} else {
errDetails = err.ase_errors.length + ' errors:\n '
+ err.ase_errors.map(
function (e) {
errDetails =
err.ase_errors.length +
' errors:\n ' +
err.ase_errors
.map(function onError(e) {
return e.message;
}).join('\n ');
})
.join('\n ');
if (showErrStack) {

@@ -1558,4 +1618,5 @@ errDetails += '\n' + VError.fullStack(err);

} else {
errDetails = (showErrStack
? VError.fullStack(err): err.message);
errDetails = showErrStack
? VError.fullStack(err)
: err.message;
}

@@ -1566,14 +1627,19 @@

if (Object.keys(errInfo).length !== 0) {
errDetails += '\nerror info:\n'
+ indent(JSON.stringify(errInfo, null, 4));
errDetails +=
'\nerror info:\n' +
indentLines(JSON.stringify(errInfo, null, 4));
}
}
console.error('%s: error%s: %s',
console.error(
'%s: error%s: %s',
nameFromErr(err),
(options.showCode && code ? format(' (%s)', code) : ''),
errDetails);
options.showCode && code ? format(' (%s)', code) : '',
errDetails
);
var showErrHelp = (options.showErrHelp === undefined
? true : options.showErrHelp);
var showErrHelp =
options.showErrHelp === undefined
? true
: options.showErrHelp;
if (showErrHelp) {

@@ -1624,4 +1690,2 @@ var errHelp = errHelpFromErr(err);

// ---- exports

@@ -1628,0 +1692,0 @@

{
"name": "cmdln",
"version": "4.4.0",
"version": "5.0.0",
"description": "helper lib for creating CLI tools with subcommands; think `git`, `svn`, `zfs`",
"author": "Trent Mick (http://trentm.com)",
"main": "./lib/cmdln.js",
"repository": {

@@ -12,6 +11,16 @@ "type": "git",

},
"engines": ["node >=0.8.0"],
"keywords": ["cmdln", "cli", "tool", "bash", "completion"],
"engines": [
"node >=0.10.0"
],
"keywords": [
"cmdln",
"cli",
"tool",
"bash",
"completion"
],
"license": "MIT",
"files": [
"lib"
],
"dependencies": {

@@ -21,8 +30,15 @@ "assert-plus": "^1.0.0",

"verror": "^1.6.0",
"dashdash": "^1.14.1",
"dashdash": "^1.14.1"
},
"optionalDependencies": {
"fuzzyset.js": "^0.0.1"
},
"devDependencies": {
"nodeunit": "^0.9.0"
"eslint": "^4.19.1",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-joyent": "~2.0.0",
"eslint-plugin-prettier": "^2.6.0",
"prettier": "1.18.2",
"tap": "^12.7.0"
}
}
SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc