feat: docker compose maybe
This commit is contained in:
37
node_modules/sade/index.d.ts
generated
vendored
Normal file
37
node_modules/sade/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
import type * as mri from 'mri';
|
||||
|
||||
type Arrayable<T> = T | T[];
|
||||
|
||||
declare function sade(usage: string, isSingle?: boolean): sade.Sade;
|
||||
|
||||
declare namespace sade {
|
||||
export type Handler = (...args: any[]) => any;
|
||||
export type Value = number | string | boolean | null;
|
||||
|
||||
export interface LazyOutput {
|
||||
name: string;
|
||||
handler: Handler;
|
||||
args: string[];
|
||||
}
|
||||
|
||||
export interface Sade {
|
||||
command(usage: string, description?: string, options?: {
|
||||
alias?: Arrayable<string>;
|
||||
default?: boolean;
|
||||
}): Sade;
|
||||
|
||||
option(flag: string, description?: string, value?: Value): Sade;
|
||||
action(handler: Handler): Sade;
|
||||
describe(text: Arrayable<string>): Sade;
|
||||
alias(...names: string[]): Sade;
|
||||
example(usage: string): Sade;
|
||||
|
||||
parse(arr: string[], opts: { lazy: true } & mri.Options): LazyOutput;
|
||||
parse(arr: string[], opts?: { lazy?: boolean } & mri.Options): void;
|
||||
|
||||
version(value: string): Sade;
|
||||
help(cmd?: string): void;
|
||||
}
|
||||
}
|
||||
|
||||
export = sade;
|
1
node_modules/sade/lib/index.js
generated
vendored
Normal file
1
node_modules/sade/lib/index.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
const e=require("mri"),t="__all__",i="__default__",s="\n";function r(e){if(!e.length)return"";let t=function(e){let t=0,i=0,s=0,r=e.length;if(r)for(;r--;)i=e[r].length,i>t&&(s=r,t=i);return e[s].length}(e.map(e=>e[0]))+4;return e.map(e=>e[0]+" ".repeat(t-e[0].length)+e[1]+(null==e[2]?"":` (default ${e[2]})`))}function n(e){return e}function l(e,t,i){if(!t||!t.length)return"";let r=0,n="";for(n+="\n "+e;r<t.length;r++)n+="\n "+i(t[r]);return n+s}function a(e,t,i=1){let s=l("ERROR",[t],n);s+=`\n Run \`$ ${e} --help\` for more info.\n`,console.error(s),process.exit(i)}class o{constructor(e,s){let[r,...n]=e.split(/\s+/);s=s||n.length>0,this.bin=r,this.ver="0.0.0",this.default="",this.tree={},this.command(t),this.command([i].concat(s?n:"<command>").join(" ")),this.single=s,this.curr=""}command(e,t,i={}){if(this.single)throw new Error('Disable "single" mode to add commands');let s=[],r=[],n=/(\[|<)/;if(e.split(/\s+/).forEach(e=>{(n.test(e.charAt(0))?r:s).push(e)}),s=s.join(" "),s in this.tree)throw new Error("Command already exists: "+s);return s.includes("__")||r.unshift(s),r=r.join(" "),this.curr=s,i.default&&(this.default=s),this.tree[s]={usage:r,alibi:[],options:[],alias:{},default:{},examples:[]},i.alias&&this.alias(i.alias),t&&this.describe(t),this}describe(e){return this.tree[this.curr||i].describe=Array.isArray(e)?e:function(e){return(e||"").replace(/([.?!])\s*(?=[A-Z])/g,"$1|").split("|")}(e),this}alias(...e){if(this.single)throw new Error('Cannot call `alias()` in "single" mode');if(!this.curr)throw new Error("Cannot call `alias()` before defining a command");return(this.tree[this.curr].alibi=this.tree[this.curr].alibi.concat(...e)).forEach(e=>this.tree[e]=this.curr),this}option(e,i,s){let r=this.tree[this.curr||t],[n,l]=function(e){return(e||"").split(/^-{1,2}|,|\s+-{1,2}|\s+/).filter(Boolean)}(e);if(l&&l.length>1&&([n,l]=[l,n]),e="--"+n,l&&l.length>0){e=`-${l}, ${e}`;let t=r.alias[l];r.alias[l]=(t||[]).concat(n)}let a=[e,i||""];return void 0!==s?(a.push(s),r.default[n]=s):l||(r.default[n]=void 0),r.options.push(a),this}action(e){return this.tree[this.curr||i].handler=e,this}example(e){return this.tree[this.curr||i].examples.push(e),this}version(e){return this.ver=e,this}parse(s,r={}){s=s.slice();let n,l,o,h,u=2,c=e(s.slice(u),{alias:{h:"help",v:"version"}}),f=this.single,p=this.bin,d="";if(f)h=this.tree[i];else{let e,t=1,i=c._.length+1;for(;t<i;t++)if(n=c._.slice(0,t).join(" "),e=this.tree[n],"string"==typeof e)l=(d=e).split(" "),s.splice(s.indexOf(c._[0]),t,...l),t+=l.length-t;else if(e)d=n;else if(d)break;if(h=this.tree[d],o=void 0===h,o)if(this.default)d=this.default,h=this.tree[d],s.unshift(d),u++;else if(n)return a(p,"Invalid command: "+n)}if(c.help)return this.help(!f&&!o&&d);if(c.version)return this._version();if(!f&&void 0===h)return a(p,"No command specified.");let g=this.tree[t];r.alias=Object.assign(g.alias,h.alias,r.alias),r.default=Object.assign(g.default,h.default,r.default),n=d.split(" "),l=s.indexOf(n[0],2),~l&&s.splice(l,n.length);let m=e(s.slice(u),r);if(!m||"string"==typeof m)return a(p,m||"Parsed unknown option flag(s)!");let b=h.usage.split(/\s+/),_=b.filter(e=>"<"===e.charAt(0)),v=m._.splice(0,_.length);if(v.length<_.length)return d&&(p+=" "+d),a(p,"Insufficient arguments!");b.filter(e=>"["===e.charAt(0)).forEach(e=>{v.push(m._.shift())}),v.push(m);let $=h.handler;return r.lazy?{args:v,name:d,handler:$}:$.apply(null,v)}help(e){console.log(function(e,a,o,h){let u="",c=a[o],f="$ "+e,p=a[t],d=e=>`${f} ${e}`.replace(/\s+/g," "),g=[["-h, --help","Displays this message"]];if(o===i&&g.unshift(["-v, --version","Displays current version"]),c.options=(c.options||[]).concat(p.options,g),c.options.length>0&&(c.usage+=" [options]"),u+=l("Description",c.describe,n),u+=l("Usage",[c.usage],d),h||o!==i)h||o===i||(u+=l("Aliases",c.alibi,d));else{let e,t=/^__/,i="",o=[];for(e in a)"string"==typeof a[e]||t.test(e)||o.push([e,(a[e].describe||[""])[0]])<3&&(i+=`\n ${f} ${e} --help`);u+=l("Available Commands",r(o),n),u+="\n For more info, run any command with the `--help` flag"+i+s}return u+=l("Options",r(c.options),n),u+=l("Examples",c.examples.map(d),n),u}(this.bin,this.tree,e||i,this.single))}_version(){console.log(`${this.bin}, ${this.ver}`)}}module.exports=(e,t)=>new o(e,t);
|
1
node_modules/sade/lib/index.mjs
generated
vendored
Normal file
1
node_modules/sade/lib/index.mjs
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
import e from"mri";const t="__all__",i="__default__",s="\n";function r(e){if(!e.length)return"";let t=function(e){let t=0,i=0,s=0,r=e.length;if(r)for(;r--;)i=e[r].length,i>t&&(s=r,t=i);return e[s].length}(e.map(e=>e[0]))+4;return e.map(e=>e[0]+" ".repeat(t-e[0].length)+e[1]+(null==e[2]?"":` (default ${e[2]})`))}function n(e){return e}function l(e,t,i){if(!t||!t.length)return"";let r=0,n="";for(n+="\n "+e;r<t.length;r++)n+="\n "+i(t[r]);return n+s}function a(e,t,i=1){let s=l("ERROR",[t],n);s+=`\n Run \`$ ${e} --help\` for more info.\n`,console.error(s),process.exit(i)}class o{constructor(e,s){let[r,...n]=e.split(/\s+/);s=s||n.length>0,this.bin=r,this.ver="0.0.0",this.default="",this.tree={},this.command(t),this.command([i].concat(s?n:"<command>").join(" ")),this.single=s,this.curr=""}command(e,t,i={}){if(this.single)throw new Error('Disable "single" mode to add commands');let s=[],r=[],n=/(\[|<)/;if(e.split(/\s+/).forEach(e=>{(n.test(e.charAt(0))?r:s).push(e)}),s=s.join(" "),s in this.tree)throw new Error("Command already exists: "+s);return s.includes("__")||r.unshift(s),r=r.join(" "),this.curr=s,i.default&&(this.default=s),this.tree[s]={usage:r,alibi:[],options:[],alias:{},default:{},examples:[]},i.alias&&this.alias(i.alias),t&&this.describe(t),this}describe(e){return this.tree[this.curr||i].describe=Array.isArray(e)?e:function(e){return(e||"").replace(/([.?!])\s*(?=[A-Z])/g,"$1|").split("|")}(e),this}alias(...e){if(this.single)throw new Error('Cannot call `alias()` in "single" mode');if(!this.curr)throw new Error("Cannot call `alias()` before defining a command");return(this.tree[this.curr].alibi=this.tree[this.curr].alibi.concat(...e)).forEach(e=>this.tree[e]=this.curr),this}option(e,i,s){let r=this.tree[this.curr||t],[n,l]=function(e){return(e||"").split(/^-{1,2}|,|\s+-{1,2}|\s+/).filter(Boolean)}(e);if(l&&l.length>1&&([n,l]=[l,n]),e="--"+n,l&&l.length>0){e=`-${l}, ${e}`;let t=r.alias[l];r.alias[l]=(t||[]).concat(n)}let a=[e,i||""];return void 0!==s?(a.push(s),r.default[n]=s):l||(r.default[n]=void 0),r.options.push(a),this}action(e){return this.tree[this.curr||i].handler=e,this}example(e){return this.tree[this.curr||i].examples.push(e),this}version(e){return this.ver=e,this}parse(s,r={}){s=s.slice();let n,l,o,h,u=2,f=e(s.slice(u),{alias:{h:"help",v:"version"}}),c=this.single,p=this.bin,d="";if(c)h=this.tree[i];else{let e,t=1,i=f._.length+1;for(;t<i;t++)if(n=f._.slice(0,t).join(" "),e=this.tree[n],"string"==typeof e)l=(d=e).split(" "),s.splice(s.indexOf(f._[0]),t,...l),t+=l.length-t;else if(e)d=n;else if(d)break;if(h=this.tree[d],o=void 0===h,o)if(this.default)d=this.default,h=this.tree[d],s.unshift(d),u++;else if(n)return a(p,"Invalid command: "+n)}if(f.help)return this.help(!c&&!o&&d);if(f.version)return this._version();if(!c&&void 0===h)return a(p,"No command specified.");let g=this.tree[t];r.alias=Object.assign(g.alias,h.alias,r.alias),r.default=Object.assign(g.default,h.default,r.default),n=d.split(" "),l=s.indexOf(n[0],2),~l&&s.splice(l,n.length);let m=e(s.slice(u),r);if(!m||"string"==typeof m)return a(p,m||"Parsed unknown option flag(s)!");let b=h.usage.split(/\s+/),_=b.filter(e=>"<"===e.charAt(0)),v=m._.splice(0,_.length);if(v.length<_.length)return d&&(p+=" "+d),a(p,"Insufficient arguments!");b.filter(e=>"["===e.charAt(0)).forEach(e=>{v.push(m._.shift())}),v.push(m);let $=h.handler;return r.lazy?{args:v,name:d,handler:$}:$.apply(null,v)}help(e){console.log(function(e,a,o,h){let u="",f=a[o],c="$ "+e,p=a[t],d=e=>`${c} ${e}`.replace(/\s+/g," "),g=[["-h, --help","Displays this message"]];if(o===i&&g.unshift(["-v, --version","Displays current version"]),f.options=(f.options||[]).concat(p.options,g),f.options.length>0&&(f.usage+=" [options]"),u+=l("Description",f.describe,n),u+=l("Usage",[f.usage],d),h||o!==i)h||o===i||(u+=l("Aliases",f.alibi,d));else{let e,t=/^__/,i="",o=[];for(e in a)"string"==typeof a[e]||t.test(e)||o.push([e,(a[e].describe||[""])[0]])<3&&(i+=`\n ${c} ${e} --help`);u+=l("Available Commands",r(o),n),u+="\n For more info, run any command with the `--help` flag"+i+s}return u+=l("Options",r(f.options),n),u+=l("Examples",f.examples.map(d),n),u}(this.bin,this.tree,e||i,this.single))}_version(){console.log(`${this.bin}, ${this.ver}`)}}export default(e,t)=>new o(e,t);
|
21
node_modules/sade/license
generated
vendored
Normal file
21
node_modules/sade/license
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (https://lukeed.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
45
node_modules/sade/package.json
generated
vendored
Normal file
45
node_modules/sade/package.json
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "sade",
|
||||
"version": "1.8.1",
|
||||
"description": "Smooth (CLI) operator 🎶",
|
||||
"repository": "lukeed/sade",
|
||||
"module": "lib/index.mjs",
|
||||
"main": "lib/index.js",
|
||||
"types": "index.d.ts",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"*.d.ts",
|
||||
"lib"
|
||||
],
|
||||
"author": {
|
||||
"name": "Luke Edwards",
|
||||
"email": "luke.edwards05@gmail.com",
|
||||
"url": "https://lukeed.com"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"test": "tape -r esm test/*.js | tap-spec"
|
||||
},
|
||||
"dependencies": {
|
||||
"mri": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"keywords": [
|
||||
"cli",
|
||||
"cli-app",
|
||||
"commander",
|
||||
"arguments",
|
||||
"parser",
|
||||
"yargs",
|
||||
"argv"
|
||||
],
|
||||
"devDependencies": {
|
||||
"esm": "3.2.25",
|
||||
"rollup": "1.32.1",
|
||||
"tap-spec": "4.1.2",
|
||||
"tape": "4.14.0",
|
||||
"terser": "4.8.0"
|
||||
}
|
||||
}
|
672
node_modules/sade/readme.md
generated
vendored
Normal file
672
node_modules/sade/readme.md
generated
vendored
Normal file
@ -0,0 +1,672 @@
|
||||
# sade [](https://travis-ci.org/lukeed/sade)
|
||||
|
||||
> Smooth (CLI) Operator 🎶
|
||||
|
||||
Sade is a small but powerful tool for building command-line interface (CLI) applications for Node.js that are fast, responsive, and helpful!
|
||||
|
||||
It enables default commands, git-like subcommands, option flags with aliases, default option values with type-casting, required-vs-optional argument handling, command validation, and automated help text generation!
|
||||
|
||||
Your app's UX will be as smooth as butter... just like [Sade's voice](https://www.youtube.com/watch?v=4TYv2PhG89A). 😉
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save sade
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
***Input:***
|
||||
|
||||
```js
|
||||
#!/usr/bin/env node
|
||||
|
||||
const sade = require('sade');
|
||||
|
||||
const prog = sade('my-cli');
|
||||
|
||||
prog
|
||||
.version('1.0.5')
|
||||
.option('--global, -g', 'An example global flag')
|
||||
.option('-c, --config', 'Provide path to custom config', 'foo.config.js');
|
||||
|
||||
prog
|
||||
.command('build <src> <dest>')
|
||||
.describe('Build the source directory. Expects an `index.js` entry file.')
|
||||
.option('-o, --output', 'Change the name of the output file', 'bundle.js')
|
||||
.example('build src build --global --config my-conf.js')
|
||||
.example('build app public -o main.js')
|
||||
.action((src, dest, opts) => {
|
||||
console.log(`> building from ${src} to ${dest}`);
|
||||
console.log('> these are extra opts', opts);
|
||||
});
|
||||
|
||||
prog.parse(process.argv);
|
||||
```
|
||||
|
||||
***Output:***
|
||||
|
||||
```a
|
||||
$ my-cli --help
|
||||
|
||||
Usage
|
||||
$ my-cli <command> [options]
|
||||
|
||||
Available Commands
|
||||
build Build the source directory.
|
||||
|
||||
For more info, run any command with the `--help` flag
|
||||
$ my-cli build --help
|
||||
|
||||
Options
|
||||
-v, --version Displays current version
|
||||
-g, --global An example global flag
|
||||
-c, --config Provide path to custom config (default foo.config.js)
|
||||
-h, --help Displays this message
|
||||
|
||||
|
||||
$ my-cli build --help
|
||||
|
||||
Description
|
||||
Build the source directory.
|
||||
Expects an `index.js` entry file.
|
||||
|
||||
Usage
|
||||
$ my-cli build <src> [options]
|
||||
|
||||
Options
|
||||
-o, --output Change the name of the output file (default bundle.js)
|
||||
-g, --global An example global flag
|
||||
-c, --config Provide path to custom config (default foo.config.js)
|
||||
-h, --help Displays this message
|
||||
|
||||
Examples
|
||||
$ my-cli build src build --global --config my-conf.js
|
||||
$ my-cli build app public -o main.js
|
||||
```
|
||||
|
||||
## Tips
|
||||
|
||||
- **Define your global/program-wide version, options, description, and/or examples first.**<br>
|
||||
_Once you define a Command, you can't access the global-scope again._
|
||||
|
||||
- **Define all commands & options in the order that you want them to appear.**<br>
|
||||
_Sade will not mutate or sort your CLI for you. Global options print before local options._
|
||||
|
||||
- **Required arguments without values will error & exit**<br>
|
||||
_An `Insufficient arguments!` error will be displayed along with a help prompt._
|
||||
|
||||
- **Don't worry about manually displaying help~!**<br>
|
||||
_Your help text is displayed automatically... including command-specific help text!_
|
||||
|
||||
- **Automatic default/basic patterns**<br>
|
||||
_Usage text will always append `[options]` & `--help` and `--version` are done for you._
|
||||
|
||||
- **Only define what you want to display!**<br>
|
||||
_Help text sections (example, options, etc) will only display if you provide values._
|
||||
|
||||
|
||||
## Subcommands
|
||||
|
||||
Subcommands are defined & parsed like any other command! When defining their [`usage`](#usage-1), everything up until the first argument (`[foo]` or `<foo>`) is interpreted as the command string.
|
||||
|
||||
They should be defined in the order that you want them to appear in your general `--help` output.
|
||||
|
||||
Lastly, it is _not_ necessary to define the subcommand's "base" as an additional command. However, if you choose to do so, it's recommended that you define it first for better visibility.
|
||||
|
||||
```js
|
||||
const prog = sade('git');
|
||||
|
||||
// Not necessary for subcommands to work, but it's here anyway!
|
||||
prog
|
||||
.command('remote')
|
||||
.describe('Manage set of tracked repositories')
|
||||
.action(opts => {
|
||||
console.log('~> Print current remotes...');
|
||||
});
|
||||
|
||||
prog
|
||||
.command('remote add <name> <url>', 'Demo...')
|
||||
.action((name, url, opts) => {
|
||||
console.log(`~> Adding a new remote (${name}) to ${url}`);
|
||||
});
|
||||
|
||||
prog
|
||||
.command('remote rename <old> <new>', 'Demo...')
|
||||
.action((old, nxt, opts) => {
|
||||
console.log(`~> Renaming from ${old} to ${nxt}~!`);
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## Command Aliases
|
||||
|
||||
Command aliases are alternative names (aliases) for a command. They are often used as shortcuts or as typo relief!
|
||||
|
||||
The aliased names do not appear in the general help text.<br>
|
||||
Instead, they only appear within the Command-specific help text under an "Aliases" section.
|
||||
|
||||
***Limitations***
|
||||
|
||||
* You cannot assign aliases while in [Single Command Mode](#single-command-mode)
|
||||
* You cannot call [`prog.alias()`](#progaliasnames) before defining any Commands (via `prog.commmand()`)
|
||||
* You, the developer, must keep track of which aliases have already been used and/or exist as Command names
|
||||
|
||||
***Example***
|
||||
|
||||
Let's reconstruct the `npm install` command as a Sade program:
|
||||
|
||||
```js
|
||||
sade('npm')
|
||||
// ...
|
||||
.command('install [package]', 'Install a package', {
|
||||
alias: ['i', 'add', 'isntall']
|
||||
})
|
||||
.option('-P, --save-prod', 'Package will appear in your dependencies.')
|
||||
.option('-D, --save-dev', 'Package will appear in your devDependencies.')
|
||||
.option('-O, --save-optional', 'Package will appear in your optionalDependencies')
|
||||
.option('-E, --save-exact', 'Save exact versions instead of using a semver range operator')
|
||||
// ...
|
||||
```
|
||||
|
||||
When we run `npm --help` we'll see this general help text:
|
||||
|
||||
```
|
||||
Usage
|
||||
$ npm <command> [options]
|
||||
|
||||
Available Commands
|
||||
install Install a package
|
||||
|
||||
For more info, run any command with the `--help` flag
|
||||
$ npm install --help
|
||||
|
||||
Options
|
||||
-v, --version Displays current version
|
||||
-h, --help Displays this message
|
||||
```
|
||||
|
||||
When we run `npm install --help` — ***or*** the help flag with any of `install`'s aliases — we'll see this command-specific help text:
|
||||
|
||||
```
|
||||
Description
|
||||
Install a package
|
||||
|
||||
Usage
|
||||
$ npm install [package] [options]
|
||||
|
||||
Aliases
|
||||
$ npm i
|
||||
$ npm add
|
||||
$ npm isntall
|
||||
|
||||
Options
|
||||
-P, --save-prod Package will appear in your dependencies.
|
||||
-D, --save-dev Package will appear in your devDependencies.
|
||||
-O, --save-optional Package will appear in your optionalDependencies
|
||||
-E, --save-exact Save exact versions instead of using a semver range operator
|
||||
-h, --help Displays this message
|
||||
```
|
||||
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### sade(name, isSingle)
|
||||
Returns: `Program`
|
||||
|
||||
Returns your chainable Sade instance, aka your `Program`.
|
||||
|
||||
#### name
|
||||
Type: `String`<br>
|
||||
Required: `true`
|
||||
|
||||
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)
|
||||
|
||||
Create a new Command for your Program. This changes the current state of your Program.
|
||||
|
||||
All configuration methods (`prog.describe`, `prog.action`, etc) will apply to this Command until another Command has been created!
|
||||
|
||||
#### usage
|
||||
|
||||
Type: `String`
|
||||
|
||||
The usage pattern for your current Command. This will be included in the general or command-specific `--help` output.
|
||||
|
||||
_Required_ arguments are wrapped with `<` and `>` characters; for example, `<foo>` and `<bar>`.
|
||||
|
||||
_Optional_ arguments are wrapped with `[` and `]` characters; for example, `[foo]` and `[bar]`.
|
||||
|
||||
All arguments are ***positionally important***, which means they are passed to your current Command's [`handler`](#handler) function in the order that they were defined.
|
||||
|
||||
When optional arguments are defined but don't receive a value, their positionally-equivalent function parameter will be `undefined`.
|
||||
|
||||
> **Important:** You **must** define & expect required arguments _before_ optional arguments!
|
||||
|
||||
```js
|
||||
sade('foo')
|
||||
|
||||
.command('greet <adjective> <noun>')
|
||||
.action((adjective, noun, opts) => {
|
||||
console.log(`Hello, ${adjective} ${noun}!`);
|
||||
})
|
||||
|
||||
.command('drive <vehicle> [color] [speed]')
|
||||
.action((vehicle, color, speed, opts) => {
|
||||
let arr = ['Driving my'];
|
||||
arr.push(color ? `${color} ${vehicle}` : vehicle);
|
||||
speed && arr.push(`at ${speed}`);
|
||||
opts.yolo && arr.push('...YOLO!!');
|
||||
let str = arr.join(' ');
|
||||
console.log(str);
|
||||
});
|
||||
```
|
||||
|
||||
```sh
|
||||
$ foo greet beautiful person
|
||||
# //=> Hello, beautiful person!
|
||||
|
||||
$ foo drive car
|
||||
# //=> Driving my car
|
||||
|
||||
$ foo drive car red
|
||||
# //=> Driving my red card
|
||||
|
||||
$ foo drive car blue 100mph --yolo
|
||||
# //=> Driving my blue car at 100mph ...YOLO!!
|
||||
```
|
||||
|
||||
|
||||
#### desc
|
||||
|
||||
Type: `String`<br>
|
||||
Default: `''`
|
||||
|
||||
The Command's description. The value is passed directly to [`prog.describe`](#progdescribetext).
|
||||
|
||||
#### opts
|
||||
|
||||
Type: `Object`<br>
|
||||
Default: `{}`
|
||||
|
||||
##### opts.alias
|
||||
Type: `String|Array`
|
||||
|
||||
Optionally define one or more aliases for the current Command.<br>
|
||||
When declared, the `opts.alias` value is passed _directly_ to the [`prog.alias`](#progaliasnames) method.
|
||||
|
||||
```js
|
||||
// Program A is equivalent to Program B
|
||||
// ---
|
||||
|
||||
const A = sade('bin')
|
||||
.command('build', 'My build command', { alias: 'b' })
|
||||
.command('watch', 'My watch command', { alias: ['w', 'dev'] });
|
||||
|
||||
const B = sade('bin')
|
||||
.command('build', 'My build command').alias('b')
|
||||
.command('watch', 'My watch command').alias('w', 'dev');
|
||||
```
|
||||
|
||||
|
||||
##### opts.default
|
||||
|
||||
Type: `Boolean`
|
||||
|
||||
Manually set/force the current Command to be the Program's default command. This ensures that the current Command will run if no command was specified.
|
||||
|
||||
> **Important:** If you run your Program without a Command _and_ without specifying a default command, your Program will exit with a `No command specified` error.
|
||||
|
||||
```js
|
||||
const prog = sade('greet');
|
||||
|
||||
prog.command('hello');
|
||||
//=> only runs if :: `$ greet hello`
|
||||
|
||||
// $ greet
|
||||
//=> error: No command specified.
|
||||
|
||||
prog.command('howdy', '', { default:true });
|
||||
//=> runs as `$ greet` OR `$ greet howdy`
|
||||
|
||||
// $ greet
|
||||
//=> runs 'howdy' handler
|
||||
|
||||
// $ greet foobar
|
||||
//=> error: Invalid command
|
||||
```
|
||||
|
||||
|
||||
### prog.describe(text)
|
||||
|
||||
Add a description to the current Command.
|
||||
|
||||
#### text
|
||||
|
||||
Type: `String|Array`
|
||||
|
||||
The description text for the current Command. This will be included in the general or command-specific `--help` output.
|
||||
|
||||
Internally, your description will be separated into an `Array` of sentences.
|
||||
|
||||
For general `--help` output, ***only*** the first sentence will be displayed. However, **all sentences** will be printed for command-specific `--help` text.
|
||||
|
||||
> **Note:** Pass an `Array` if you don't want internal assumptions. However, the first item is _always_ displayed in general help, so it's recommended to keep it short.
|
||||
|
||||
|
||||
### prog.alias(...names)
|
||||
|
||||
Define one or more aliases for the current Command.
|
||||
|
||||
> **Important:** An error will be thrown if:<br>1) the program is in [Single Command Mode](#single-command-mode); or<br>2) `prog.alias` is called before any `prog.command`.
|
||||
|
||||
#### names
|
||||
|
||||
Type: `String`
|
||||
|
||||
The list of alternative names (aliases) for the current Command.<br>
|
||||
For example, you may want to define shortcuts and/or common typos for the Command's full name.
|
||||
|
||||
> **Important:** Sade _does not_ check if the incoming `names` are already in use by other Commands or their aliases.<br>During conflicts, the Command with the same `name` is given priority, otherwise the first Command (according to Program order) with `name` as an alias is chosen.
|
||||
|
||||
The `prog.alias()` is append-only, so calling it multiple times within a Command context will _keep_ all aliases, including those initially passed via [`opts.alias`](#optsdefault).
|
||||
|
||||
```js
|
||||
sade('bin')
|
||||
.command('hello <name>', 'Greet someone by their name', {
|
||||
alias: ['hey', 'yo']
|
||||
})
|
||||
.alias('hi', 'howdy')
|
||||
.alias('hola', 'oi');
|
||||
//=> hello aliases: hey, yo, hi, howdy, hola, oi
|
||||
```
|
||||
|
||||
|
||||
### prog.action(handler)
|
||||
|
||||
Attach a callback to the current Command.
|
||||
|
||||
#### handler
|
||||
|
||||
Type: `Function`
|
||||
|
||||
The function to run when the current Command is executed.
|
||||
|
||||
Its parameters are based (positionally) on your Command's [`usage`](#usage-1) definition.
|
||||
|
||||
All options, flags, and extra/unknown values are included as the last parameter.
|
||||
|
||||
> **Note:** Optional arguments are also passed as parameters & may be `undefined`!
|
||||
|
||||
```js
|
||||
sade('foo')
|
||||
.command('cp <src> <dest>')
|
||||
.option('-f, --force', 'Overwrite without confirmation')
|
||||
.option('-c, --clone-dir', 'Copy files to additional directory')
|
||||
.option('-v, --verbose', 'Enable verbose output')
|
||||
.action((src, dest, opts) => {
|
||||
console.log(`Copying files from ${src} --> ${dest}`);
|
||||
opts.c && console.log(`ALSO copying files from ${src} --> ${opts['clone-dir']}`);
|
||||
console.log('My options:', opts);
|
||||
})
|
||||
|
||||
// $ foo cp original my-copy -v
|
||||
//=> Copying files from original --> my-copy
|
||||
//=> My options: { _:[], v:true, verbose:true }
|
||||
|
||||
// $ foo cp original my-copy --clone-dir my-backup
|
||||
//=> Copying files from original --> my-copy
|
||||
//=> ALSO copying files from original --> my-backup
|
||||
//=> My options: { _:[], c:'my-backup', 'clone-dir':'my-backup' }
|
||||
```
|
||||
|
||||
|
||||
### prog.example(str)
|
||||
|
||||
Add an example for the current Command.
|
||||
|
||||
#### str
|
||||
|
||||
Type: `String`
|
||||
|
||||
The example string to add. This will be included in the general or command-specific `--help` output.
|
||||
|
||||
> **Note:** Your example's `str` will be prefixed with your Program's [`name`](#sadename).
|
||||
|
||||
|
||||
### prog.option(flags, desc, value)
|
||||
|
||||
Add an Option to the current Command.
|
||||
|
||||
#### flags
|
||||
|
||||
Type: `String`
|
||||
|
||||
The Option's flags, which may optionally include an alias.
|
||||
|
||||
You may use a comma (`,`) or a space (` `) to separate the flags.
|
||||
|
||||
> **Note:** The short & long flags can be declared in any order. However, the alias will always be displayed first.
|
||||
|
||||
> **Important:** If using hyphenated flag names, they will be accessible **as declared** within your [`action()`](#progactionhandler) handler!
|
||||
|
||||
```js
|
||||
prog.option('--global'); // no alias
|
||||
prog.option('-g, --global'); // alias first, comma
|
||||
prog.option('--global -g'); // alias last, space
|
||||
// etc...
|
||||
```
|
||||
|
||||
#### desc
|
||||
|
||||
Type: `String`
|
||||
|
||||
The description for the Option.
|
||||
|
||||
#### value
|
||||
|
||||
Type: `String`
|
||||
|
||||
The **default** value for the Option.
|
||||
|
||||
Flags and aliases, if parsed, are `true` by default. See [`mri`](https://github.com/lukeed/mri#minimist) for more info.
|
||||
|
||||
> **Note:** You probably only want to define a default `value` if you're expecting a `String` or `Number` value type.
|
||||
|
||||
If you _do_ pass a `String` or `Number` value type, your flag value will be casted to the same type. See [`mri#options.default`](https://github.com/lukeed/mri#optionsdefault) for info~!
|
||||
|
||||
|
||||
### prog.version(str)
|
||||
|
||||
The `--version` and `-v` flags will automatically output the Program version.
|
||||
|
||||
#### str
|
||||
|
||||
Type: `String`<br>
|
||||
Default: `0.0.0`
|
||||
|
||||
The new version number for your Program.
|
||||
|
||||
> **Note:** Your Program `version` is `0.0.0` until you change it.
|
||||
|
||||
### prog.parse(arr, opts)
|
||||
|
||||
Parse a set of CLI arguments.
|
||||
|
||||
#### arr
|
||||
|
||||
Type: `Array`
|
||||
|
||||
Your Program's `process.argv` input.
|
||||
|
||||
> **Important:** Do not `.slice(2)`! Doing so will break parsing~!
|
||||
|
||||
#### opts
|
||||
|
||||
Type: `Object`<br>
|
||||
Default: `{}`
|
||||
|
||||
Additional `process.argv` parsing config. See [`mri`'s options](https://github.com/lukeed/mri#mriargs-options) for details.
|
||||
|
||||
> **Important:** These values _override_ any internal values!
|
||||
|
||||
```js
|
||||
prog
|
||||
.command('hello')
|
||||
.option('-f, --force', 'My flag');
|
||||
//=> currently has alias pair: f <--> force
|
||||
|
||||
prog.parse(process.argv, {
|
||||
alias: {
|
||||
f: ['foo', 'fizz']
|
||||
},
|
||||
default: {
|
||||
abc: 123
|
||||
}
|
||||
});
|
||||
//=> ADDS alias pair: f <--> foo
|
||||
//=> REMOVES alias pair: f <--> force
|
||||
//=> ADDS alias pair: f <--> fizz
|
||||
//=> ADDS default: abc -> 123 (number)
|
||||
```
|
||||
|
||||
#### opts.unknown
|
||||
|
||||
Type: `Function`<br>
|
||||
Default: `undefined`
|
||||
|
||||
Callback to run when an unspecified option flag has been found. This is [passed directly to `mri`](https://github.com/lukeed/mri#optionsunknown).
|
||||
|
||||
Your handler will receive the unknown flag (string) as its only argument.<br>
|
||||
You may return a string, which will be used as a custom error message. Otherwise, a default message is displayed.
|
||||
|
||||
```js
|
||||
sade('sirv')
|
||||
.command('start [dir]')
|
||||
.parse(process.argv, {
|
||||
unknown: arg => `Custom error message: ${arg}`
|
||||
});
|
||||
|
||||
/*
|
||||
$ sirv start --foobar
|
||||
|
||||
ERROR
|
||||
Custom error message: --foobar
|
||||
|
||||
Run `$ sirv --help` for more info.
|
||||
*/
|
||||
```
|
||||
|
||||
#### opts.lazy
|
||||
|
||||
Type: `Boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
If true, Sade will not immediately execute the `action` handler. Instead, `parse()` will return an object of `{ name, args, handler }` shape, wherein the `name` is the command name, `args` is all arguments that _would be_ passed to the action handler, and `handler` is the function itself.
|
||||
|
||||
From this, you may choose when to run the `handler` function. You also have the option to further modify the `args` for any reason, if needed.
|
||||
|
||||
```js
|
||||
let { name, args, handler } = prog.parse(process.argv, { lazy:true });
|
||||
console.log('> Received command: ', name);
|
||||
|
||||
// later on...
|
||||
handler.apply(null, args);
|
||||
```
|
||||
|
||||
### prog.help(cmd)
|
||||
|
||||
Manually display the help text for a given command. If no command name is provided, the general/global help is printed.
|
||||
|
||||
Your general and command-specific help text is automatically attached to the `--help` and `-h` flags.
|
||||
|
||||
> **Note:** You don't have to call this directly! It's automatically run when you `bin --help`
|
||||
|
||||
#### cmd
|
||||
Type: `String`<br>
|
||||
Default: `null`
|
||||
|
||||
The name of the command for which to display help. Otherwise displays the general help.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Luke Edwards](https://lukeed.com)
|
Reference in New Issue
Block a user