Comparing version 1.7.4 to 1.8.0
204
lib/index.js
@@ -1,203 +0,1 @@ | ||
const mri = require('mri'); | ||
const $ = require('./utils'); | ||
const ALL = '__all__'; | ||
const DEF = '__default__'; | ||
class Sade { | ||
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].concat(isOne ? rest : '<command>').join(' ')); | ||
this.single = isOne; | ||
this.curr = ''; // reset | ||
} | ||
command(str, desc, opts={}) { | ||
if (this.single) { | ||
throw new Error('Disable "single" mode to add commands'); | ||
} | ||
// All non-([|<) are commands | ||
let cmd=[], usage=[], rgx=/(\[|<)/; | ||
str.split(/\s+/).forEach(x => { | ||
(rgx.test(x.charAt(0)) ? usage : cmd).push(x); | ||
}); | ||
// Back to string~! | ||
cmd = cmd.join(' '); | ||
if (cmd in this.tree) { | ||
throw new Error(`Command already exists: ${cmd}`); | ||
} | ||
// re-include `cmd` for commands | ||
cmd.includes('__') || usage.unshift(cmd); | ||
usage = usage.join(' '); // to string | ||
this.curr = cmd; | ||
if (opts.default) this.default=cmd; | ||
this.tree[cmd] = { usage, alibi:[], options:[], alias:{}, default:{}, examples:[] }; | ||
if (opts.alias) this.alias(opts.alias); | ||
if (desc) this.describe(desc); | ||
return this; | ||
} | ||
describe(str) { | ||
this.tree[this.curr || DEF].describe = Array.isArray(str) ? str : $.sentences(str); | ||
return this; | ||
} | ||
alias(...names) { | ||
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'); | ||
let arr = this.tree[this.curr].alibi = this.tree[this.curr].alibi.concat(...names); | ||
arr.forEach(key => this.tree[key] = this.curr); | ||
return this; | ||
} | ||
option(str, desc, val) { | ||
let cmd = this.tree[ this.curr || ALL ]; | ||
let [flag, alias] = $.parse(str); | ||
if (alias && alias.length > 1) [flag, alias]=[alias, flag]; | ||
str = `--${flag}`; | ||
if (alias && alias.length > 0) { | ||
str = `-${alias}, ${str}`; | ||
let old = cmd.alias[alias]; | ||
cmd.alias[alias] = (old || []).concat(flag); | ||
} | ||
let arr = [str, desc || '']; | ||
if (val !== void 0) { | ||
arr.push(val); | ||
cmd.default[flag] = val; | ||
} else if (!alias) { | ||
cmd.default[flag] = void 0; | ||
} | ||
cmd.options.push(arr); | ||
return this; | ||
} | ||
action(handler) { | ||
this.tree[ this.curr || DEF ].handler = handler; | ||
return this; | ||
} | ||
example(str) { | ||
this.tree[ this.curr || DEF ].examples.push(str); | ||
return this; | ||
} | ||
version(str) { | ||
this.ver = str; | ||
return this; | ||
} | ||
parse(arr, opts={}) { | ||
arr = arr.slice(); // copy | ||
let offset=2, tmp, idx, isVoid, cmd; | ||
let alias = { h:'help', v:'version' }; | ||
let argv = mri(arr.slice(offset), { alias }); | ||
let isSingle = this.single; | ||
let bin = this.bin; | ||
let name = ''; | ||
if (isSingle) { | ||
cmd = this.tree[DEF]; | ||
} else { | ||
// Loop thru possible command(s) | ||
let i=1, xyz, len=argv._.length + 1; | ||
for (; i < len; i++) { | ||
tmp = argv._.slice(0, i).join(' '); | ||
xyz = this.tree[tmp]; | ||
if (typeof xyz === 'string') { | ||
idx = (name=xyz).split(' '); | ||
arr.splice(arr.indexOf(argv._[0]), i, ...idx); | ||
i += (idx.length - i); | ||
} else if (xyz) { | ||
name = tmp; | ||
} else if (name) { | ||
break; | ||
} | ||
} | ||
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... | ||
} | ||
} | ||
// 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 (!isSingle && cmd === void 0) { | ||
return $.error(bin, 'No command specified.'); | ||
} | ||
let all = this.tree[ALL]; | ||
// merge all objects :: params > command > all | ||
opts.alias = Object.assign(all.alias, cmd.alias, opts.alias); | ||
opts.default = Object.assign(all.default, cmd.default, opts.default); | ||
tmp = name.split(' '); | ||
idx = arr.indexOf(tmp[0], 2); | ||
if (!!~idx) arr.splice(idx, tmp.length); | ||
let vals = mri(arr.slice(offset), opts); | ||
if (!vals || typeof vals === 'string') { | ||
return $.error(bin, vals || 'Parsed unknown option flag(s)!'); | ||
} | ||
let segs = cmd.usage.split(/\s+/); | ||
let reqs = segs.filter(x => x.charAt(0)==='<'); | ||
let args = vals._.splice(0, reqs.length); | ||
if (args.length < reqs.length) { | ||
if (name) bin += ` ${name}`; // for help text | ||
return $.error(bin, 'Insufficient arguments!'); | ||
} | ||
segs.filter(x => x.charAt(0)==='[').forEach(_ => { | ||
args.push(vals._.shift()); // adds `undefined` per [slot] if no more | ||
}); | ||
args.push(vals); // flags & co are last | ||
let handler = cmd.handler; | ||
return opts.lazy ? { args, name, handler } : handler.apply(null, args); | ||
} | ||
help(str) { | ||
console.log( | ||
$.help(this.bin, this.tree, str || DEF, this.single) | ||
); | ||
} | ||
_version() { | ||
console.log(`${this.bin}, ${this.ver}`); | ||
} | ||
} | ||
module.exports = (str, isOne) => new Sade(str, isOne); | ||
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); |
{ | ||
"name": "sade", | ||
"version": "1.7.4", | ||
"version": "1.8.0", | ||
"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" | ||
@@ -17,3 +20,4 @@ ], | ||
"scripts": { | ||
"test": "tape test/*.js | tap-spec" | ||
"build": "rollup -c", | ||
"test": "tape -r esm test/*.js | tap-spec" | ||
}, | ||
@@ -24,3 +28,3 @@ "dependencies": { | ||
"engines": { | ||
"node": ">= 6" | ||
"node": ">=6" | ||
}, | ||
@@ -37,5 +41,8 @@ "keywords": [ | ||
"devDependencies": { | ||
"tap-spec": "^4.1.1", | ||
"tape": "^4.8.0" | ||
"esm": "3.2.25", | ||
"rollup": "1.32.1", | ||
"tap-spec": "4.1.2", | ||
"tape": "4.14.0", | ||
"terser": "4.8.0" | ||
} | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
31658
6
5
62
1
1