Socket
Socket
Sign inDemoInstall

sade

Package Overview
Dependencies
1
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.5.1 to 1.6.0

96

lib/index.js

@@ -8,11 +8,14 @@ const mri = require('mri');

class Sade {
constructor(name) {
this.tree = {};
this.name = name;
constructor(name, isOne) {
let [bin, ...rest] = name.split(/\s+/);
isOne = isOne || rest.length > 0;
this.bin = bin;
this.ver = '0.0.0';
this.default = '';
this.tree = {};
// set internal shapes;
this.command(ALL);
this.command(`${DEF} <command>`)
.option('-v, --version', 'Displays current version');
this.command([DEF].concat(isOne ? rest : '<command>').join(' '));
this.single = isOne;
this.curr = ''; // reset

@@ -22,4 +25,8 @@ }

command(str, desc, opts={}) {
if (this.single) {
throw new Error('Disable "single" mode to add commands');
}
// All non-([|<) are commands
let cmd=[], usage=[], rgx=/(\[|<)/;
// All non-([|<) are commands
str.split(/\s+/).forEach(x => {

@@ -36,8 +43,9 @@ (rgx.test(x.charAt(0)) ? usage : cmd).push(x);

// re-include `cmd` for commands
cmd.includes('__') || usage.unshift(cmd);
usage = usage.join(' '); // to string
this.curr = cmd;
if (opts.default) this.default=cmd;
!~cmd.indexOf('__') && usage.unshift(cmd); // re-include `cmd`
usage = usage.join(' '); // to string
this.tree[cmd] = { usage, options:[], alias:{}, default:{}, examples:[] };

@@ -58,3 +66,3 @@ if (desc) this.describe(desc);

let [flag, alias] = $.parse(str);
(alias && alias.length > 1) && ([flag, alias]=[alias, flag]);
if (alias && alias.length > 1) [flag, alias]=[alias, flag];

@@ -98,37 +106,39 @@ str = `--${flag}`;

let argv = mri(arr.slice(offset), { alias });
let bin = this.name;
let isSingle = this.single;
let bin = this.bin;
let tmp, name = '';
let isVoid, cmd;
// Loop thru possible command(s)
let tmp, name='';
let i=1, len=argv._.length + 1;
for (; i < len; i++) {
tmp = argv._.slice(0, i).join(' ');
if (this.tree[tmp] !== void 0) {
name=tmp; offset=(i + 2); // argv slicer
if (isSingle) {
cmd = this.tree[DEF];
} else {
// Loop thru possible command(s)
let i=1, len=argv._.length + 1;
for (; i < len; i++) {
tmp = argv._.slice(0, i).join(' ');
if (this.tree[tmp] !== void 0) {
name=tmp; offset=(i + 2); // argv slicer
}
}
}
let cmd = this.tree[name];
let isVoid = (cmd === void 0);
cmd = this.tree[name];
isVoid = (cmd === void 0);
if (isVoid) {
if (this.default) {
name = this.default;
cmd = this.tree[name];
arr.unshift(name);
offset++;
} else if (tmp) {
return $.error(bin, `Invalid command: ${tmp}`);
} //=> else: cmd not specified, wait for now...
if (isVoid) {
if (this.default) {
name = this.default;
cmd = this.tree[name];
arr.unshift(name);
offset++;
} else if (tmp) {
return $.error(bin, `Invalid command: ${tmp}`);
} //=> else: cmd not specified, wait for now...
}
}
if (argv.version) {
return console.log(`${bin}, ${this.ver}`);
}
// show main help if relied on "default" for multi-cmd
if (argv.help) return this.help(!isSingle && !isVoid && name);
if (argv.version) return this._version();
if (argv.help) {
return this.help(!isVoid && name);
}
if (cmd === void 0) {
if (!isSingle && cmd === void 0) {
return $.error(bin, 'No command specified.');

@@ -152,3 +162,3 @@ }

if (args.length < reqs.length) {
name && (bin += ` ${name}`); // for help text
if (name) bin += ` ${name}`; // for help text
return $.error(bin, 'Insufficient arguments!');

@@ -168,7 +178,11 @@ }

console.log(
$.help(this.name, this.tree, str || DEF)
$.help(this.bin, this.tree, str || DEF, this.single)
);
}
_version() {
console.log(`${this.bin}, ${this.ver}`);
}
}
module.exports = str => new Sade(str);
module.exports = (str, isOne) => new Sade(str, isOne);

@@ -39,12 +39,13 @@ const GAP = 4;

exports.help = function (bin, tree, key) {
exports.help = function (bin, tree, key, single) {
let out='', cmd=tree[key], pfx=`$ ${bin}`, all=tree[ALL];
let prefix = s => `${pfx} ${s}`;
let prefix = s => `${pfx} ${s}`.replace(/\s+/g, ' ');
// update ALL & CMD options
all.options.push(['-h, --help', 'Displays this message']);
cmd.options = (cmd.options || []).concat(all.options);
let tail = [['-h, --help', 'Displays this message']];
if (key === DEF) tail.unshift(['-v, --version', 'Displays current version']);
cmd.options = (cmd.options || []).concat(all.options, tail);
// write options placeholder
(cmd.options.length > 0) && (cmd.usage += ' [options]');
if (cmd.options.length > 0) cmd.usage += ' [options]';

@@ -55,3 +56,3 @@ // description ~> text only; usage ~> prefixed

if (key === DEF) {
if (!single && key === DEF) {
// General help :: print all non-internal commands & their 1st line of text

@@ -58,0 +59,0 @@ let cmds = Object.keys(tree).filter(k => !/__/.test(k));

{
"name": "sade",
"version": "1.5.1",
"version": "1.6.0",
"description": "Smooth (CLI) operator ๐ŸŽถ",

@@ -5,0 +5,0 @@ "repository": "lukeed/sade",

@@ -144,13 +144,91 @@ # sade [![Build Status](https://travis-ci.org/lukeed/sade.svg?branch=master)](https://travis-ci.org/lukeed/sade)

## Single Command Mode
In certain circumstances, you may only need `sade` for a single-command CLI application.
> **Note:** Until `v1.6.0`, this made for an awkward pairing.
To enable this, you may make use of the [`isSingle`](#issingle) argument. Doing so allows you to pass the program's entire [`usage` text](#usage-1) into the `name` argument.
With "Single Command Mode" enabled, your entire binary operates as one command. This means that any [`prog.command`](#progcommandusage-desc-opts) calls are disallowed & will instead throw an Error. Of course, you may still define a program version, a description, an example or two, and declare options. You are customizing the program's attributes as a whole.<sup>*</sup>
> <sup>*</sup> This is true for multi-command applications, too, up until your first `prog.command()` call!
***Example***
Let's reconstruct [`sirv-cli`](https://github.com/lukeed/sirv), which is a single-command application that (optionally) accepts a directory from which to serve files. It also offers a slew of option flags:
```js
sade('sirv [dir]', true)
.version('1.0.0')
.describe('Run a static file server')
.example('public -qeim 31536000')
.example('--port 8080 --etag')
.example('my-app --dev')
.option('-D, --dev', 'Enable "dev" mode')
.option('-e, --etag', 'Enable "Etag" header')
// There are a lot...
.option('-H, --host', 'Hostname to bind', 'localhost')
.option('-p, --port', 'Port to bind', 5000)
.action((dir, opts) => {
// Program handler
})
.parse(process.argv);
```
When `sirv --help` is run, the generated help text is trimmed, fully aware that there's only one command in this program:
```
Description
Run a static file server
Usage
$ sirv [dir] [options]
Options
-D, --dev Enable "dev" mode
-e, --etag Enable "Etag" header
-H, --host Hostname to bind (default localhost)
-p, --port Port to bind (default 5000)
-v, --version Displays current version
-h, --help Displays this message
Examples
$ sirv public -qeim 31536000
$ sirv --port 8080 --etag
$ sirv my-app --dev
```
## API
### sade(name)
### sade(name, isSingle)
Returns: `Program`
Returns your chainable Sade instance, aka your `Program`.
#### name
Type: `String`<br>
Returns: `Program`
Required: `true`
The name of your bin/program. Returns the `Program` itself, wherein all other methods are available.
The name of your `Program` / binary application.
#### isSingle
Type: `Boolean`<br>
Default: `name.includes(' ');`
If your `Program` is meant to have ***only one command***.<br>
When `true`, this simplifies your generated `--help` output such that:
* the "root-level help" is your _only_ help text
* the "root-level help" does not display an `Available Commands` section
* the "root-level help" does not inject `$ name <command>` into the `Usage` section
* the "root-level help" does not display `For more info, run any command with the `--help` flag` text
You may customize the `Usage` of your command by modifying the `name` argument directly.<br>
Please read [Single Command Mode](#single-command-mode) for an example and more information.
> **Important:** Whenever `name` includes a custom usage, then `isSingle` is automatically assumed and enforced!
### prog.command(usage, desc, opts)

@@ -157,0 +235,0 @@

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc