bob-core 1.2.4 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bob-core.cjs +4 -3
- package/dist/bob-core.js +256 -159
- package/dist/{package-B3ICsvyj.js → package-7cIQdc3-.js} +1 -1
- package/dist/{package-sv16L6xn.cjs → package-D1l4pNru.cjs} +1 -1
- package/dist/types/src/Command.d.ts +11 -1
- package/dist/types/src/CommandIO.d.ts +35 -0
- package/dist/types/src/CommandParser.d.ts +5 -3
- package/dist/types/src/CommandRegistry.d.ts +3 -0
- package/dist/types/src/errors/CommandNotFoundError.d.ts +1 -2
- package/dist/types/src/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/bob-core.cjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
2
|
-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const A=require("minimist"),o=require("chalk"),f=require("prompts"),x=require("node:fs"),$=require("path"),V=require("string-similarity");function b(l){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(l){for(const t in l)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(l,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>l[t]})}}return e.default=l,Object.freeze(e)}const E=b(x),j=b(V);class p extends Error{}class S extends p{constructor(e){super(`Argument "${e.name}" is required.`),this.paramSignature=e}pretty(){const e=console.log;e(o`{white.bgRed ERROR } Argument {bold.yellow ${this.paramSignature.name}} is required.`)}}class y extends p{constructor(e,t){super(`Missing ${e} in the command signature`),this.option=e,this.optionsSignature=t}pretty(){const e=console.log;if(this.optionsSignature.length){e(o`{yellow Available options}:`);for(const t of this.optionsSignature){const n=t.type?o`{white (${t.type})}`:"",s=" ".repeat(20-t.name.length);e(o` {green ${t.name}} ${s} ${t.help??"\b"} ${n}`)}e("")}e(o`{white.bgRed ERROR } Option {bold.yellow ${this.option}} is missing in the signature.`)}}class w extends p{constructor(e,t){super(`Missing ${e} in the command signature`),this.argument=e,this.argumentSignatures=t}pretty(){const e=console.log;if(this.argumentSignatures.length){e(o`\n{yellow Available arguments}:`);for(const t of this.argumentSignatures){const n=t.type?o`{white (${t.type})}`:"",s=" ".repeat(20-t.name.length);e(o` {green ${t.name}} ${s} ${t.help??"\b"} ${n}`)}e("")}e(o`{white.bgRed ERROR } Argument {bold.yellow ${this.argument}} is missing in the signature.`)}}class k extends p{constructor(e,t){super(`Invalid option ${e} in not recognized`),this.option=e,this.optionsSignature=t}pretty(){const e=console.log;if(this.optionsSignature.length>0){e(o`\n{yellow Available options}:`);for(const t of this.optionsSignature){const n=t.type?o`{white (${t.type})}`:"",s=`--${t.name}${t.alias?.map(r=>`, -${r}`).join("")??""}`,i=" ".repeat(30-s.length);e(o` {green ${s}} ${i} ${t.help??"\b"} ${n}`)}e("")}e(o`{white.bgRed ERROR } Option {bold.yellow ${this.option}} is not recognized.`)}}class F{constructor(e,t,n,s,...i){this.io=e,this.signature=t,this.helperDefinitions=n,this.defaultCommandOptions=s;const[r,...u]=t.split(/\{(.*?)\}/g).map(c=>c.trim()).filter(Boolean),{_:a,...m}=A(i);this.command=r,this.parseSignature(u),this.parseDefaultOptions(),this.handleArguments(a),this.handleOptions(m)}command;arguments={};options={};argumentsSignature={};optionSignatures={};optionAliases={};option(e){if(!this.optionSignatures[e])throw new y(e,Object.values(this.optionSignatures));return this.options[e]}setOption(e,t){if(!this.optionSignatures[e])throw new y(e,Object.values(this.optionSignatures));this.options[e]=t}optionHelp(e){if(!this.optionSignatures[e])throw new y(e,Object.values(this.optionSignatures));return this.optionSignatures[e].help}argument(e){if(!this.argumentsSignature[e])throw new w(e,Object.values(this.argumentsSignature));return this.arguments[e]}setArgument(e,t){if(!this.argumentsSignature[e])throw new w(e,Object.values(this.argumentsSignature));this.arguments[e]=t}argumentHelp(e){if(!this.argumentsSignature[e])throw new w(e,Object.values(this.argumentsSignature));return this.argumentsSignature[e].help}getArgumentSignatures(){return this.argumentsSignature}getOptionSignatures(){return this.optionSignatures}getParamValue(e,t){return t.type==="boolean"?e==="true"||e==="1"?!0:e==="false"||e==="0"?!1:!!e:t.type==="array"?e?Array.isArray(e)?e:[e]:[]:e??t.defaultValue}handleArguments(e){for(const[t,n]of Object.entries(this.arguments)){const s=this.argumentsSignature[t];if(s.variadic)this.arguments[t]=e;else{const i=e.shift();this.arguments[t]=this.getParamValue(i,s)}}}handleOptions(e){for(const[t,n]of Object.entries(e)){const s=this.optionAliases[t],i=this.optionSignatures[t]??this.optionSignatures[s];if(!i)throw new k(t,Object.values(this.optionSignatures));this.options[t]=this.getParamValue(n,i);for(const r of i.alias??[])e[r]&&(this.options[i.name]=e[r])}}parseSignature(e){for(const t of e){const n=this.parseParamSignature(t);if(n.isOption){this.options[n.name]=n.defaultValue??null,this.optionSignatures[n.name]=n;for(const s of n.alias??[])this.optionAliases[s]=n.name}else this.arguments[n.name]=n.defaultValue??null,this.argumentsSignature[n.name]=n}}parseDefaultOptions(){if(this.defaultCommandOptions.length){for(const e of this.defaultCommandOptions)if(this.optionSignatures[e.option]={name:e.option,type:e.defaultValue==null?"string":typeof e.defaultValue=="boolean"?"boolean":Array.isArray(e.defaultValue)?"array":"string",optional:!0,alias:e.alias,variadic:!1,help:e.description,defaultValue:e.defaultValue??null,isOption:!0},this.options[e.option]=e.defaultValue,e.alias)for(const t of e.alias)this.optionAliases[t]=e.option}}parseParamSignature(e){const t={name:e,optional:!1,type:"string",help:void 0,defaultValue:null,variadic:!1,isOption:!1};if(t.name.includes(":")){const[n,s]=t.name.split(":");t.name=n.trim(),t.help=s.trim()}if(t.name.includes("=")){const[n,s]=t.name.split("=");t.name=n.trim(),t.defaultValue=s.trim(),t.optional=!0,t.defaultValue.length?t.defaultValue==="true"?(t.defaultValue=!0,t.type="boolean"):t.defaultValue==="false"&&(t.defaultValue=!1,t.type="boolean"):t.defaultValue=null}else t.name.startsWith("--")&&(t.optional=!0,t.defaultValue=!1,t.type="boolean");if(t.name.includes("|")){const[n,...s]=t.name.split("|");t.name=n.trim(),t.alias=s.map(i=>i.trim())}return t.name.startsWith("--")&&(t.isOption=!0,t.name=t.name.slice(2)),t.defaultValue==="*"&&(t.defaultValue=[],t.type="array"),t.name.endsWith("?")&&(t.optional=!0,t.name=t.name.slice(0,-1)),t.name.endsWith("*")&&(t.type="array",t.variadic=!0,t.defaultValue=[],t.name=t.name.slice(0,-1)),t.help=t.help??this.helperDefinitions[t.name]??this.helperDefinitions[`--${t.name}`],t}async validate(){for(const[e,t]of Object.entries(this.arguments)){const n=this.argumentsSignature[e];if(!t&&!n.optional){let s=null;switch(n.type){case"string":let i=o`{yellow.bold ${n.name}} is required`;n.help&&(i+=o`: {gray (${n.help})}`),i+=`
|
|
2
|
+
`,s=await this.io.askForInput(i,n.defaultValue,{validate:r=>r?.trim()?.length?!0:`${n.name} cannot be empty`});break}if(s)this.setArgument(e,s);else throw new S(n)}if(!t?.length&&n.variadic&&!n.optional)throw new S(n)}}}function C(l){return new Array(l+5).join(" ")}class O{option="help";alias=["h"];defaultValue=!1;description=o`Display help for the given command. When no command is given display help for the {green list} command`;async handler(){const e=console.log,t=Object.values(this.parser.getArgumentSignatures()),n=Object.values(this.parser.getOptionSignatures()).map(a=>({...a,optionWithAlias:`--${a.name}${a.alias?.map(m=>`, -${m}`).join("")??""}`})),s=t.filter(a=>!a.optional);e(o`{yellow Description}:`),e(o` ${this.description}\n`),e(o`{yellow Usage}:`),e(o` ${this.command} ${s.length>0?s.map(a=>`<${a.name}>`).join(" "):"\b"} [options]`);const i=Math.max(...n.map(a=>a.optionWithAlias.length))??0,r=Math.max(...t.map(a=>a.name.length))??0,u=r>i?r:i;if(t.length>0){e(o`\n{yellow Arguments}:`);for(const a of t){const m=C(u-a.name.length);let c=o` {green ${a.name}} ${m} ${a.help??"\b"}`;if(a.defaultValue!==void 0&&a.optional){const h=a.type==="array"?JSON.stringify(a.defaultValue):a.defaultValue;c+=o` {yellow [default: ${h}]}`}a.variadic&&(c+=o` {white (variadic)}`),e(c)}}if(n.length>0){e(o`\n{yellow Options}:`);for(const a of n){const m=C(u-a.optionWithAlias.length);let c=o`{green ${a.optionWithAlias}} ${m} ${a.help??"\b"}`;if(a.type&&(c+=o` {white (${a.type})}`),a.defaultValue!==void 0&&a.optional){const h=a.type==="array"?JSON.stringify(a.defaultValue):a.defaultValue;c+=o` {yellow [default: ${h}]}`}e(c)}}if(this.commandsExamples.length>0){e(o`\n{yellow Examples}:`);let a=process.argv[0].split("/").pop();a==="node"&&(a+=" "+process.argv[1].split("/").pop());for(const[m,c]of this.commandsExamples.entries())m>0&&e(""),e(` ${c.description}
|
|
3
|
+
`),e(o` {green ${a} ${c.command}}`)}return-1}}class v{async askForConfirmation(e="Do you want to continue?",t){return(await f({type:"confirm",name:"value",message:e,initial:t??!1})).value}async askForInput(e,t,n){return(await f({type:"text",name:"value",message:e,initial:t,...n}))?.value??null}async askForToggle(e,t,n){return(await f({type:"toggle",name:"value",message:e,initial:t,...n}))?.value??null}async askForSelect(e,t,n){if(t.length===0)throw new Error("No options provided");const s=[];for(const r of t)typeof r=="string"?s.push({title:r,value:r}):s.push(r);return(await f({type:"select",name:"value",message:e,choices:s,...n}))?.value??null}newLoader(e="",t=["⠙","⠘","⠰","⠴","⠤","⠦","⠆","⠃","⠋","⠉"],n=100){let s=e,i=null,r=0;const u=setInterval(function(){i&&(process.stdout.write(new TextEncoder().encode("\r"+" ".repeat(i.length+5)+"\r")),i=null),process.stdout.write(new TextEncoder().encode("\r"+t[r++]+" "+s)),r=r%t.length},n),a=()=>{clearInterval(u),process.stdout.write(new TextEncoder().encode("\r"+" ".repeat(s.length+5)+"\r"))};return{[Symbol.dispose]:a,[Symbol.asyncDispose]:a,updateText:m=>{i=s,s=m},stop:a}}}class R{ctx;helperDefinitions={};commandsExamples=[];parser;io;get CommandParserClass(){return F}get CommandIOClass(){return v}defaultOptions(){return[new O]}get command(){return this.parser?this.parser.command:this.signature.split(" ")[0]}async run(e,...t){this.ctx=e;const n=this.defaultOptions();this.io=new this.CommandIOClass,this.parser=new this.CommandParserClass(this.io,this.signature,this.helperDefinitions,n,...t);for(const s of n)if(this.parser.option(s.option)){const i=await s.handler.call(this);if(i&&i!==0)return i}return await this.parser.validate(),await this.handle()??0}setOption(e,t){this.parser.setOption(e,t)}setArgument(e,t){this.parser.setArgument(e,t)}option(e,t=null){return this.parser.option(e)??t}optionBoolean(e,t=!1){return this.parser.option(e)??t}optionArray(e,t=[]){const n=this.parser.option(e);if(!Array.isArray(n))throw new Error(`Option ${e} is not an array`);return n.length?n:t}optionNumber(e,t=null){const n=this.parser.option(e);return n?typeof n=="number"?n:parseInt(n):t}argument(e,t=null){return this.parser.argument(e)??t}argumentArray(e,t=[]){const n=this.parser.argument(e);if(!Array.isArray(n))throw new Error(`Argument ${e} is not an array`);return n?.length?n:t}argumentBoolean(e,t=!1){return this.parser.argument(e)??t}argumentNumber(e,t=null){const n=this.parser.argument(e);return n?typeof n=="number"?n:parseInt(n):t}async askForConfirmation(...e){return this.io.askForConfirmation(...e)}async askForInput(...e){return this.io.askForInput(...e)}async askForSelect(...e){return this.io.askForSelect(...e)}newLoader(...e){return this.io.newLoader(...e)}}class I extends p{constructor(e){super(`Command "${e}" not found.`),this.command=e}pretty(){const e=console.log;e(o`{bgRed ERROR } Command {yellow ${this.command}} not found.`)}}class D{commands={};io;get commandSuffix(){return"Command"}get CommandIOClass(){return v}constructor(){this.io=new this.CommandIOClass}getAvailableCommands(){return Object.keys(this.commands)}getCommands(){return Object.values(this.commands)}commandResolver=async e=>{const t=(await import(e)).default;let n;return t?.default?n=new t.default:n=new t,n};setCommandResolver(e){this.commandResolver=e}registerCommand(e,t=!1){const n=e.signature.split(" ")[0];if(!n)throw new Error("Command signature is invalid, it must have a command name.");if(!t&&this.commands[n])throw new Error(`Command ${n} already registered.`);this.commands[n]=e}async loadCommandsPath(e){for await(const t of this.listCommandsFiles(e))try{const n=await this.commandResolver(t);this.registerCommand(n)}catch(n){throw new Error(`Command ${t} failed to load. ${n}`)}}async runCommand(e,t,...n){const s=typeof t=="string"?this.commands[t]:t,i=typeof t=="string"?t:s.command;if(!s){const r=await this.suggestCommand(i);return r?await this.runCommand(e,r,...n):1}return await s.run(e,...n)}async suggestCommand(e){const t=this.getAvailableCommands(),{bestMatch:n,bestMatchIndex:s,ratings:i}=j.findBestMatch(e,t),r=i.filter(u=>u.rating>.3).map(u=>u.target);if(n.rating>0&&r.length<=1||n.rating>.7&&r.length>1){const u=t[s];return await this.askRunSimilarCommand(e,u)?u:null}if(r.length){console.log(o`{bgRed ERROR } Command {yellow ${e}} not found.\n`);const u=await this.io.askForSelect(o`{green Did you mean to run one of these commands instead?}`,r);if(u)return u}throw new I(e)}async askRunSimilarCommand(e,t){return console.log(o`{bgRed ERROR } Command {yellow ${e}} not found.\n`),this.io.askForConfirmation(o`{green Do you want to run {yellow ${t}} instead?} `)}async*listCommandsFiles(e){const t=E.readdirSync(e,{withFileTypes:!0});for(const n of t){const s=$.resolve(e,n.name);if(n.isDirectory())yield*this.listCommandsFiles($.resolve(e,n.name));else{if(!s.endsWith(`${this.commandSuffix}.ts`)&&!s.endsWith(`${this.commandSuffix}.js`))continue;yield s}}}}class P extends R{constructor(e){super(),this.opts=e}signature="help";description="Show help";async handle(){const e=this.opts.commandRegistry.getCommands(),t=this.opts.cliName??"Bob CLI",n=this.opts.cliVersion??"0.0.0",s=(await Promise.resolve().then(()=>require("./package-D1l4pNru.cjs")))?.default?.version??"0.0.0";console.log(o`${t} {green ${n}} (core: {yellow ${s}})
|
|
3
4
|
|
|
4
5
|
{yellow Usage}:
|
|
5
6
|
command [options] [arguments]
|
|
6
7
|
|
|
7
8
|
{yellow Available commands}:
|
|
8
|
-
`);const
|
|
9
|
+
`);const i=Math.max(...e.map(a=>a.command.length))??0,r={};for(const a of e){const m=a.command.split(":")[0];r[m]||(r[m]=[]),r[m].push(a)}const u=Object.entries(r).sort(([a],[m])=>a.toLowerCase().localeCompare(m.toLowerCase())).sort(([,a],[,m])=>a.length-m.length);for(const[a,m]of u){const c=m.length>1;c&&console.log(o`{yellow ${a}}:`);const h=m.sort((d,g)=>d.command.toLowerCase().localeCompare(g.command.toLowerCase()));for(const d of h){let g=C(i-d.command.length);c&&(g=g.slice(2)),console.log(o`${c?" ":""}{green ${d.command}} ${g} ${d.description}`)}}}}class B extends p{constructor(e){let t=`Argument "${e.param}" value is invalid.`;e.reason?t+=` Reason: ${e.reason}`:t+=` Value: "${e.value}"`,super(t),this.param=e}pretty(){const e=console.log;e(o` {white.bgRed ERROR } Argument {bold.yellow ${this.param.param}} value is invalid. `),(this.param.value||this.param.reason)&&e(""),this.param.value&&e(o` {blue Value}: ${this.param.value}`),this.param.reason&&e(o` {yellow Reason}: ${this.param.reason}`)}}class H extends p{constructor(e){let t=`Option "${e.option}" value is invalid.`;e.reason?t+=` Reason: ${e.reason}`:t+=` Value: "${e.value}"`,super(t),this.param=e}pretty(){const e=console.log;e(o` {white.bgRed ERROR } Option {bold.yellow ${this.param.option}} value is invalid. `),(this.param.value||this.param.reason)&&e(""),this.param.value&&e(o` {blue Value}: ${this.param.value}`),this.param.reason&&e(o` {yellow Reason}: ${this.param.reason}`)}}class M{handle(e){if(e instanceof p)return e.pretty(),-1;throw e}}class T{commandRegistry;exceptionHandler;ctx;helpCommand;get CommandRegistryClass(){return D}get HelpCommandClass(){return P}get ExceptionHandlerClass(){return M}constructor(e={}){this.ctx=e.ctx,this.commandRegistry=new this.CommandRegistryClass,this.exceptionHandler=new this.ExceptionHandlerClass,this.helpCommand=new this.HelpCommandClass({cliName:e.name,cliVersion:e.version,commandRegistry:this.commandRegistry})}setCommandResolver(e){this.commandRegistry.setCommandResolver(e)}async withCommands(...e){for(const t of e)typeof t=="string"?await this.commandRegistry.loadCommandsPath(t):typeof t=="function"?this.registerCommand(new t):this.registerCommand(t)}async runCommand(e,...t){return e?await this.commandRegistry.runCommand(this.ctx,e,...t).catch(this.exceptionHandler.handle):await this.runHelpCommand()}async runHelpCommand(){return await this.runCommand(this.helpCommand)}registerCommand(e){this.commandRegistry.registerCommand(e)}}exports.BadCommandOption=H;exports.BadCommandParameter=B;exports.BobError=p;exports.Cli=T;exports.Command=R;exports.CommandIO=v;exports.HelpOption=O;
|
package/dist/bob-core.js
CHANGED
|
@@ -1,75 +1,76 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
1
|
+
import b from "minimist";
|
|
2
|
+
import o from "chalk";
|
|
3
|
+
import f from "prompts";
|
|
4
|
+
import * as R from "node:fs";
|
|
5
|
+
import $ from "path";
|
|
6
|
+
import * as O from "string-similarity";
|
|
7
|
+
class c extends Error {
|
|
7
8
|
}
|
|
8
|
-
class
|
|
9
|
+
class v extends c {
|
|
9
10
|
constructor(t) {
|
|
10
11
|
super(`Argument "${t.name}" is required.`), this.paramSignature = t;
|
|
11
12
|
}
|
|
12
13
|
pretty() {
|
|
13
14
|
const t = console.log;
|
|
14
|
-
|
|
15
|
+
t(o`{white.bgRed ERROR } Argument {bold.yellow ${this.paramSignature.name}} is required.`);
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
|
-
class
|
|
18
|
+
class y extends c {
|
|
18
19
|
constructor(t, e) {
|
|
19
20
|
super(`Missing ${t} in the command signature`), this.option = t, this.optionsSignature = e;
|
|
20
21
|
}
|
|
21
22
|
pretty() {
|
|
22
23
|
const t = console.log;
|
|
23
24
|
if (this.optionsSignature.length) {
|
|
24
|
-
t(
|
|
25
|
+
t(o`{yellow Available options}:`);
|
|
25
26
|
for (const e of this.optionsSignature) {
|
|
26
|
-
const n = e.type ?
|
|
27
|
-
t(
|
|
27
|
+
const n = e.type ? o`{white (${e.type})}` : "", s = " ".repeat(20 - e.name.length);
|
|
28
|
+
t(o` {green ${e.name}} ${s} ${e.help ?? "\b"} ${n}`);
|
|
28
29
|
}
|
|
29
30
|
t("");
|
|
30
31
|
}
|
|
31
|
-
t(
|
|
32
|
+
t(o`{white.bgRed ERROR } Option {bold.yellow ${this.option}} is missing in the signature.`);
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
|
-
class
|
|
35
|
+
class w extends c {
|
|
35
36
|
constructor(t, e) {
|
|
36
37
|
super(`Missing ${t} in the command signature`), this.argument = t, this.argumentSignatures = e;
|
|
37
38
|
}
|
|
38
39
|
pretty() {
|
|
39
40
|
const t = console.log;
|
|
40
41
|
if (this.argumentSignatures.length) {
|
|
41
|
-
t(
|
|
42
|
+
t(o`\n{yellow Available arguments}:`);
|
|
42
43
|
for (const e of this.argumentSignatures) {
|
|
43
|
-
const n = e.type ?
|
|
44
|
-
t(
|
|
44
|
+
const n = e.type ? o`{white (${e.type})}` : "", s = " ".repeat(20 - e.name.length);
|
|
45
|
+
t(o` {green ${e.name}} ${s} ${e.help ?? "\b"} ${n}`);
|
|
45
46
|
}
|
|
46
47
|
t("");
|
|
47
48
|
}
|
|
48
|
-
t(
|
|
49
|
+
t(o`{white.bgRed ERROR } Argument {bold.yellow ${this.argument}} is missing in the signature.`);
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
|
-
class
|
|
52
|
+
class A extends c {
|
|
52
53
|
constructor(t, e) {
|
|
53
54
|
super(`Invalid option ${t} in not recognized`), this.option = t, this.optionsSignature = e;
|
|
54
55
|
}
|
|
55
56
|
pretty() {
|
|
56
57
|
const t = console.log;
|
|
57
58
|
if (this.optionsSignature.length > 0) {
|
|
58
|
-
t(
|
|
59
|
+
t(o`\n{yellow Available options}:`);
|
|
59
60
|
for (const e of this.optionsSignature) {
|
|
60
|
-
const n = e.type ?
|
|
61
|
-
t(
|
|
61
|
+
const n = e.type ? o`{white (${e.type})}` : "", s = `--${e.name}${e.alias?.map((r) => `, -${r}`).join("") ?? ""}`, i = " ".repeat(30 - s.length);
|
|
62
|
+
t(o` {green ${s}} ${i} ${e.help ?? "\b"} ${n}`);
|
|
62
63
|
}
|
|
63
64
|
t("");
|
|
64
65
|
}
|
|
65
|
-
t(
|
|
66
|
+
t(o`{white.bgRed ERROR } Option {bold.yellow ${this.option}} is not recognized.`);
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
|
-
class
|
|
69
|
-
constructor(t, e, n, ...i) {
|
|
70
|
-
this.
|
|
71
|
-
const [
|
|
72
|
-
this.command =
|
|
69
|
+
class x {
|
|
70
|
+
constructor(t, e, n, s, ...i) {
|
|
71
|
+
this.io = t, this.signature = e, this.helperDefinitions = n, this.defaultCommandOptions = s;
|
|
72
|
+
const [r, ...m] = e.split(/\{(.*?)\}/g).map((p) => p.trim()).filter(Boolean), { _: a, ...l } = b(i);
|
|
73
|
+
this.command = r, this.parseSignature(m), this.parseDefaultOptions(), this.handleArguments(a), this.handleOptions(l);
|
|
73
74
|
}
|
|
74
75
|
command;
|
|
75
76
|
arguments = {};
|
|
@@ -79,32 +80,32 @@ class O {
|
|
|
79
80
|
optionAliases = {};
|
|
80
81
|
option(t) {
|
|
81
82
|
if (!this.optionSignatures[t])
|
|
82
|
-
throw new
|
|
83
|
+
throw new y(t, Object.values(this.optionSignatures));
|
|
83
84
|
return this.options[t];
|
|
84
85
|
}
|
|
85
86
|
setOption(t, e) {
|
|
86
87
|
if (!this.optionSignatures[t])
|
|
87
|
-
throw new
|
|
88
|
+
throw new y(t, Object.values(this.optionSignatures));
|
|
88
89
|
this.options[t] = e;
|
|
89
90
|
}
|
|
90
91
|
optionHelp(t) {
|
|
91
92
|
if (!this.optionSignatures[t])
|
|
92
|
-
throw new
|
|
93
|
+
throw new y(t, Object.values(this.optionSignatures));
|
|
93
94
|
return this.optionSignatures[t].help;
|
|
94
95
|
}
|
|
95
96
|
argument(t) {
|
|
96
97
|
if (!this.argumentsSignature[t])
|
|
97
|
-
throw new
|
|
98
|
+
throw new w(t, Object.values(this.argumentsSignature));
|
|
98
99
|
return this.arguments[t];
|
|
99
100
|
}
|
|
100
101
|
setArgument(t, e) {
|
|
101
102
|
if (!this.argumentsSignature[t])
|
|
102
|
-
throw new
|
|
103
|
+
throw new w(t, Object.values(this.argumentsSignature));
|
|
103
104
|
this.arguments[t] = e;
|
|
104
105
|
}
|
|
105
106
|
argumentHelp(t) {
|
|
106
107
|
if (!this.argumentsSignature[t])
|
|
107
|
-
throw new
|
|
108
|
+
throw new w(t, Object.values(this.argumentsSignature));
|
|
108
109
|
return this.argumentsSignature[t].help;
|
|
109
110
|
}
|
|
110
111
|
getArgumentSignatures() {
|
|
@@ -118,23 +119,23 @@ class O {
|
|
|
118
119
|
}
|
|
119
120
|
handleArguments(t) {
|
|
120
121
|
for (const [e, n] of Object.entries(this.arguments)) {
|
|
121
|
-
const
|
|
122
|
-
if (
|
|
122
|
+
const s = this.argumentsSignature[e];
|
|
123
|
+
if (s.variadic)
|
|
123
124
|
this.arguments[e] = t;
|
|
124
125
|
else {
|
|
125
|
-
const
|
|
126
|
-
this.arguments[e] = this.getParamValue(
|
|
126
|
+
const i = t.shift();
|
|
127
|
+
this.arguments[e] = this.getParamValue(i, s);
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
130
|
}
|
|
130
131
|
handleOptions(t) {
|
|
131
132
|
for (const [e, n] of Object.entries(t)) {
|
|
132
|
-
const
|
|
133
|
-
if (!
|
|
134
|
-
throw new
|
|
135
|
-
this.options[e] = this.getParamValue(n,
|
|
136
|
-
for (const r of
|
|
137
|
-
t[r] && (this.options[
|
|
133
|
+
const s = this.optionAliases[e], i = this.optionSignatures[e] ?? this.optionSignatures[s];
|
|
134
|
+
if (!i)
|
|
135
|
+
throw new A(e, Object.values(this.optionSignatures));
|
|
136
|
+
this.options[e] = this.getParamValue(n, i);
|
|
137
|
+
for (const r of i.alias ?? [])
|
|
138
|
+
t[r] && (this.options[i.name] = t[r]);
|
|
138
139
|
}
|
|
139
140
|
}
|
|
140
141
|
parseSignature(t) {
|
|
@@ -142,8 +143,8 @@ class O {
|
|
|
142
143
|
const n = this.parseParamSignature(e);
|
|
143
144
|
if (n.isOption) {
|
|
144
145
|
this.options[n.name] = n.defaultValue ?? null, this.optionSignatures[n.name] = n;
|
|
145
|
-
for (const
|
|
146
|
-
this.optionAliases[
|
|
146
|
+
for (const s of n.alias ?? [])
|
|
147
|
+
this.optionAliases[s] = n.name;
|
|
147
148
|
} else
|
|
148
149
|
this.arguments[n.name] = n.defaultValue ?? null, this.argumentsSignature[n.name] = n;
|
|
149
150
|
}
|
|
@@ -153,7 +154,7 @@ class O {
|
|
|
153
154
|
for (const t of this.defaultCommandOptions)
|
|
154
155
|
if (this.optionSignatures[t.option] = {
|
|
155
156
|
name: t.option,
|
|
156
|
-
type: t.defaultValue == null ? "string" : typeof t.defaultValue,
|
|
157
|
+
type: t.defaultValue == null ? "string" : typeof t.defaultValue == "boolean" ? "boolean" : Array.isArray(t.defaultValue) ? "array" : "string",
|
|
157
158
|
optional: !0,
|
|
158
159
|
alias: t.alias,
|
|
159
160
|
variadic: !1,
|
|
@@ -176,90 +177,169 @@ class O {
|
|
|
176
177
|
isOption: !1
|
|
177
178
|
};
|
|
178
179
|
if (e.name.includes(":")) {
|
|
179
|
-
const [n,
|
|
180
|
-
e.name = n.trim(), e.help =
|
|
180
|
+
const [n, s] = e.name.split(":");
|
|
181
|
+
e.name = n.trim(), e.help = s.trim();
|
|
181
182
|
}
|
|
182
183
|
if (e.name.includes("=")) {
|
|
183
|
-
const [n,
|
|
184
|
-
e.name = n.trim(), e.defaultValue =
|
|
184
|
+
const [n, s] = e.name.split("=");
|
|
185
|
+
e.name = n.trim(), e.defaultValue = s.trim(), e.optional = !0, e.defaultValue.length ? e.defaultValue === "true" ? (e.defaultValue = !0, e.type = "boolean") : e.defaultValue === "false" && (e.defaultValue = !1, e.type = "boolean") : e.defaultValue = null;
|
|
185
186
|
} else
|
|
186
187
|
e.name.startsWith("--") && (e.optional = !0, e.defaultValue = !1, e.type = "boolean");
|
|
187
188
|
if (e.name.includes("|")) {
|
|
188
|
-
const [n, ...
|
|
189
|
-
e.name = n.trim(), e.alias =
|
|
189
|
+
const [n, ...s] = e.name.split("|");
|
|
190
|
+
e.name = n.trim(), e.alias = s.map((i) => i.trim());
|
|
190
191
|
}
|
|
191
192
|
return e.name.startsWith("--") && (e.isOption = !0, e.name = e.name.slice(2)), e.defaultValue === "*" && (e.defaultValue = [], e.type = "array"), e.name.endsWith("?") && (e.optional = !0, e.name = e.name.slice(0, -1)), e.name.endsWith("*") && (e.type = "array", e.variadic = !0, e.defaultValue = [], e.name = e.name.slice(0, -1)), e.help = e.help ?? this.helperDefinitions[e.name] ?? this.helperDefinitions[`--${e.name}`], e;
|
|
192
193
|
}
|
|
193
|
-
validate() {
|
|
194
|
+
async validate() {
|
|
194
195
|
for (const [t, e] of Object.entries(this.arguments)) {
|
|
195
196
|
const n = this.argumentsSignature[t];
|
|
196
|
-
if (!e && !n.optional)
|
|
197
|
-
|
|
197
|
+
if (!e && !n.optional) {
|
|
198
|
+
let s = null;
|
|
199
|
+
switch (n.type) {
|
|
200
|
+
case "string":
|
|
201
|
+
let i = o`{yellow.bold ${n.name}} is required`;
|
|
202
|
+
n.help && (i += o`: {gray (${n.help})}`), i += `
|
|
203
|
+
`, s = await this.io.askForInput(i, n.defaultValue, {
|
|
204
|
+
validate: (r) => r?.trim()?.length ? !0 : `${n.name} cannot be empty`
|
|
205
|
+
});
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
if (s)
|
|
209
|
+
this.setArgument(t, s);
|
|
210
|
+
else
|
|
211
|
+
throw new v(n);
|
|
212
|
+
}
|
|
198
213
|
if (!e?.length && n.variadic && !n.optional)
|
|
199
|
-
throw new
|
|
214
|
+
throw new v(n);
|
|
200
215
|
}
|
|
201
216
|
}
|
|
202
217
|
}
|
|
203
|
-
function
|
|
204
|
-
return new Array(
|
|
218
|
+
function C(u) {
|
|
219
|
+
return new Array(u + 5).join(" ");
|
|
205
220
|
}
|
|
206
|
-
class
|
|
221
|
+
class V {
|
|
207
222
|
option = "help";
|
|
208
223
|
alias = ["h"];
|
|
209
224
|
defaultValue = !1;
|
|
210
|
-
description =
|
|
225
|
+
description = o`Display help for the given command. When no command is given display help for the {green list} command`;
|
|
211
226
|
async handler() {
|
|
212
|
-
const t = console.log, e = Object.values(this.parser.getArgumentSignatures()), n = Object.values(this.parser.getOptionSignatures()).map((
|
|
213
|
-
...
|
|
214
|
-
optionWithAlias: `--${
|
|
215
|
-
})),
|
|
216
|
-
t(
|
|
217
|
-
const
|
|
227
|
+
const t = console.log, e = Object.values(this.parser.getArgumentSignatures()), n = Object.values(this.parser.getOptionSignatures()).map((a) => ({
|
|
228
|
+
...a,
|
|
229
|
+
optionWithAlias: `--${a.name}${a.alias?.map((l) => `, -${l}`).join("") ?? ""}`
|
|
230
|
+
})), s = e.filter((a) => !a.optional);
|
|
231
|
+
t(o`{yellow Description}:`), t(o` ${this.description}\n`), t(o`{yellow Usage}:`), t(o` ${this.command} ${s.length > 0 ? s.map((a) => `<${a.name}>`).join(" ") : "\b"} [options]`);
|
|
232
|
+
const i = Math.max(...n.map((a) => a.optionWithAlias.length)) ?? 0, r = Math.max(...e.map((a) => a.name.length)) ?? 0, m = r > i ? r : i;
|
|
218
233
|
if (e.length > 0) {
|
|
219
|
-
t(
|
|
220
|
-
for (const
|
|
221
|
-
const l =
|
|
222
|
-
let
|
|
223
|
-
if (
|
|
224
|
-
const
|
|
225
|
-
|
|
234
|
+
t(o`\n{yellow Arguments}:`);
|
|
235
|
+
for (const a of e) {
|
|
236
|
+
const l = C(m - a.name.length);
|
|
237
|
+
let p = o` {green ${a.name}} ${l} ${a.help ?? "\b"}`;
|
|
238
|
+
if (a.defaultValue !== void 0 && a.optional) {
|
|
239
|
+
const h = a.type === "array" ? JSON.stringify(a.defaultValue) : a.defaultValue;
|
|
240
|
+
p += o` {yellow [default: ${h}]}`;
|
|
226
241
|
}
|
|
227
|
-
|
|
242
|
+
a.variadic && (p += o` {white (variadic)}`), t(p);
|
|
228
243
|
}
|
|
229
244
|
}
|
|
230
245
|
if (n.length > 0) {
|
|
231
|
-
t(
|
|
232
|
-
for (const
|
|
233
|
-
const l =
|
|
234
|
-
let
|
|
235
|
-
if (
|
|
236
|
-
const
|
|
237
|
-
|
|
246
|
+
t(o`\n{yellow Options}:`);
|
|
247
|
+
for (const a of n) {
|
|
248
|
+
const l = C(m - a.optionWithAlias.length);
|
|
249
|
+
let p = o`{green ${a.optionWithAlias}} ${l} ${a.help ?? "\b"}`;
|
|
250
|
+
if (a.type && (p += o` {white (${a.type})}`), a.defaultValue !== void 0 && a.optional) {
|
|
251
|
+
const h = a.type === "array" ? JSON.stringify(a.defaultValue) : a.defaultValue;
|
|
252
|
+
p += o` {yellow [default: ${h}]}`;
|
|
238
253
|
}
|
|
239
|
-
t(
|
|
254
|
+
t(p);
|
|
240
255
|
}
|
|
241
256
|
}
|
|
242
257
|
if (this.commandsExamples.length > 0) {
|
|
243
|
-
t(
|
|
244
|
-
let
|
|
245
|
-
|
|
246
|
-
for (const [l,
|
|
247
|
-
l > 0 && t(""), t(` ${
|
|
248
|
-
`), t(
|
|
258
|
+
t(o`\n{yellow Examples}:`);
|
|
259
|
+
let a = process.argv[0].split("/").pop();
|
|
260
|
+
a === "node" && (a += " " + process.argv[1].split("/").pop());
|
|
261
|
+
for (const [l, p] of this.commandsExamples.entries())
|
|
262
|
+
l > 0 && t(""), t(` ${p.description}
|
|
263
|
+
`), t(o` {green ${a} ${p.command}}`);
|
|
249
264
|
}
|
|
250
265
|
return -1;
|
|
251
266
|
}
|
|
252
267
|
}
|
|
253
|
-
class
|
|
268
|
+
class S {
|
|
269
|
+
/**
|
|
270
|
+
* Prompt utils
|
|
271
|
+
*/
|
|
272
|
+
async askForConfirmation(t = "Do you want to continue?", e) {
|
|
273
|
+
return (await f({
|
|
274
|
+
type: "confirm",
|
|
275
|
+
name: "value",
|
|
276
|
+
message: t,
|
|
277
|
+
initial: e ?? !1
|
|
278
|
+
})).value;
|
|
279
|
+
}
|
|
280
|
+
async askForInput(t, e, n) {
|
|
281
|
+
return (await f({
|
|
282
|
+
type: "text",
|
|
283
|
+
name: "value",
|
|
284
|
+
message: t,
|
|
285
|
+
initial: e,
|
|
286
|
+
...n
|
|
287
|
+
}))?.value ?? null;
|
|
288
|
+
}
|
|
289
|
+
async askForToggle(t, e, n) {
|
|
290
|
+
return (await f({
|
|
291
|
+
type: "toggle",
|
|
292
|
+
name: "value",
|
|
293
|
+
message: t,
|
|
294
|
+
initial: e,
|
|
295
|
+
...n
|
|
296
|
+
}))?.value ?? null;
|
|
297
|
+
}
|
|
298
|
+
async askForSelect(t, e, n) {
|
|
299
|
+
if (e.length === 0)
|
|
300
|
+
throw new Error("No options provided");
|
|
301
|
+
const s = [];
|
|
302
|
+
for (const r of e)
|
|
303
|
+
typeof r == "string" ? s.push({ title: r, value: r }) : s.push(r);
|
|
304
|
+
return (await f({
|
|
305
|
+
type: "select",
|
|
306
|
+
name: "value",
|
|
307
|
+
message: t,
|
|
308
|
+
choices: s,
|
|
309
|
+
...n
|
|
310
|
+
}))?.value ?? null;
|
|
311
|
+
}
|
|
312
|
+
newLoader(t = "", e = ["⠙", "⠘", "⠰", "⠴", "⠤", "⠦", "⠆", "⠃", "⠋", "⠉"], n = 100) {
|
|
313
|
+
let s = t, i = null, r = 0;
|
|
314
|
+
const m = setInterval(function() {
|
|
315
|
+
i && (process.stdout.write(new TextEncoder().encode("\r" + " ".repeat(i.length + 5) + "\r")), i = null), process.stdout.write(new TextEncoder().encode("\r" + e[r++] + " " + s)), r = r % e.length;
|
|
316
|
+
}, n), a = () => {
|
|
317
|
+
clearInterval(m), process.stdout.write(new TextEncoder().encode("\r" + " ".repeat(s.length + 5) + "\r"));
|
|
318
|
+
};
|
|
319
|
+
return {
|
|
320
|
+
[Symbol.dispose]: a,
|
|
321
|
+
[Symbol.asyncDispose]: a,
|
|
322
|
+
updateText: (l) => {
|
|
323
|
+
i = s, s = l;
|
|
324
|
+
},
|
|
325
|
+
stop: a
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
class E {
|
|
254
330
|
ctx;
|
|
255
331
|
helperDefinitions = {};
|
|
256
332
|
commandsExamples = [];
|
|
257
333
|
parser;
|
|
334
|
+
io;
|
|
258
335
|
get CommandParserClass() {
|
|
259
|
-
return
|
|
336
|
+
return x;
|
|
337
|
+
}
|
|
338
|
+
get CommandIOClass() {
|
|
339
|
+
return S;
|
|
260
340
|
}
|
|
261
341
|
defaultOptions() {
|
|
262
|
-
return [new
|
|
342
|
+
return [new V()];
|
|
263
343
|
}
|
|
264
344
|
get command() {
|
|
265
345
|
return this.parser ? this.parser.command : this.signature.split(" ")[0];
|
|
@@ -267,14 +347,14 @@ class V {
|
|
|
267
347
|
async run(t, ...e) {
|
|
268
348
|
this.ctx = t;
|
|
269
349
|
const n = this.defaultOptions();
|
|
270
|
-
this.parser = new this.CommandParserClass(this.signature, this.helperDefinitions, n, ...e);
|
|
271
|
-
for (const
|
|
272
|
-
if (this.parser.option(
|
|
273
|
-
const
|
|
274
|
-
if (
|
|
275
|
-
return
|
|
350
|
+
this.io = new this.CommandIOClass(), this.parser = new this.CommandParserClass(this.io, this.signature, this.helperDefinitions, n, ...e);
|
|
351
|
+
for (const s of n)
|
|
352
|
+
if (this.parser.option(s.option)) {
|
|
353
|
+
const i = await s.handler.call(this);
|
|
354
|
+
if (i && i !== 0)
|
|
355
|
+
return i;
|
|
276
356
|
}
|
|
277
|
-
return this.parser.validate(), await this.handle() ?? 0;
|
|
357
|
+
return await this.parser.validate(), await this.handle() ?? 0;
|
|
278
358
|
}
|
|
279
359
|
setOption(t, e) {
|
|
280
360
|
this.parser.setOption(t, e);
|
|
@@ -314,27 +394,42 @@ class V {
|
|
|
314
394
|
const n = this.parser.argument(t);
|
|
315
395
|
return n ? typeof n == "number" ? n : parseInt(n) : e;
|
|
316
396
|
}
|
|
397
|
+
/**
|
|
398
|
+
* Prompt utils
|
|
399
|
+
*/
|
|
400
|
+
async askForConfirmation(...t) {
|
|
401
|
+
return this.io.askForConfirmation(...t);
|
|
402
|
+
}
|
|
403
|
+
async askForInput(...t) {
|
|
404
|
+
return this.io.askForInput(...t);
|
|
405
|
+
}
|
|
406
|
+
async askForSelect(...t) {
|
|
407
|
+
return this.io.askForSelect(...t);
|
|
408
|
+
}
|
|
409
|
+
newLoader(...t) {
|
|
410
|
+
return this.io.newLoader(...t);
|
|
411
|
+
}
|
|
317
412
|
}
|
|
318
|
-
class
|
|
319
|
-
constructor(t
|
|
320
|
-
super(`Command "${t}" not found.`), this.command = t
|
|
413
|
+
class j extends c {
|
|
414
|
+
constructor(t) {
|
|
415
|
+
super(`Command "${t}" not found.`), this.command = t;
|
|
321
416
|
}
|
|
322
417
|
pretty() {
|
|
323
418
|
const t = console.log;
|
|
324
|
-
|
|
325
|
-
t(a` {white.bgRed ERROR } Command "${this.command}" not found, Did you mean one of these?`);
|
|
326
|
-
for (const e of this.similarCommands)
|
|
327
|
-
t(a` {gray ⇂ ${e}}`);
|
|
328
|
-
} else
|
|
329
|
-
t(a` {white.bgRed ERROR } Command "${this.command}" not found.`);
|
|
419
|
+
t(o`{bgRed ERROR } Command {yellow ${this.command}} not found.`);
|
|
330
420
|
}
|
|
331
421
|
}
|
|
332
|
-
class
|
|
422
|
+
class F {
|
|
333
423
|
commands = {};
|
|
424
|
+
io;
|
|
334
425
|
get commandSuffix() {
|
|
335
426
|
return "Command";
|
|
336
427
|
}
|
|
428
|
+
get CommandIOClass() {
|
|
429
|
+
return S;
|
|
430
|
+
}
|
|
337
431
|
constructor() {
|
|
432
|
+
this.io = new this.CommandIOClass();
|
|
338
433
|
}
|
|
339
434
|
getAvailableCommands() {
|
|
340
435
|
return Object.keys(this.commands);
|
|
@@ -368,101 +463,102 @@ class E {
|
|
|
368
463
|
}
|
|
369
464
|
}
|
|
370
465
|
async runCommand(t, e, ...n) {
|
|
371
|
-
const
|
|
372
|
-
if (!
|
|
373
|
-
const r = await this.suggestCommand(
|
|
466
|
+
const s = typeof e == "string" ? this.commands[e] : e, i = typeof e == "string" ? e : s.command;
|
|
467
|
+
if (!s) {
|
|
468
|
+
const r = await this.suggestCommand(i);
|
|
374
469
|
return r ? await this.runCommand(t, r, ...n) : 1;
|
|
375
470
|
}
|
|
376
|
-
return await
|
|
471
|
+
return await s.run(t, ...n);
|
|
377
472
|
}
|
|
378
473
|
async suggestCommand(t) {
|
|
379
|
-
const e = this.getAvailableCommands(), { bestMatch: n, bestMatchIndex:
|
|
474
|
+
const e = this.getAvailableCommands(), { bestMatch: n, bestMatchIndex: s, ratings: i } = O.findBestMatch(t, e), r = i.filter((m) => m.rating > 0.3).map((m) => m.target);
|
|
380
475
|
if (n.rating > 0 && r.length <= 1 || n.rating > 0.7 && r.length > 1) {
|
|
381
|
-
const
|
|
382
|
-
return await this.askRunSimilarCommand(t,
|
|
476
|
+
const m = e[s];
|
|
477
|
+
return await this.askRunSimilarCommand(t, m) ? m : null;
|
|
478
|
+
}
|
|
479
|
+
if (r.length) {
|
|
480
|
+
console.log(o`{bgRed ERROR } Command {yellow ${t}} not found.\n`);
|
|
481
|
+
const m = await this.io.askForSelect(
|
|
482
|
+
o`{green Did you mean to run one of these commands instead?}`,
|
|
483
|
+
r
|
|
484
|
+
);
|
|
485
|
+
if (m)
|
|
486
|
+
return m;
|
|
383
487
|
}
|
|
384
|
-
throw new
|
|
488
|
+
throw new j(t);
|
|
385
489
|
}
|
|
386
490
|
async askRunSimilarCommand(t, e) {
|
|
387
|
-
|
|
388
|
-
input: process.stdin,
|
|
389
|
-
output: process.stdout
|
|
390
|
-
});
|
|
391
|
-
return console.log(a` {bgRed ERROR } Command {yellow ${t}} not found.\n`), new Promise((i) => {
|
|
392
|
-
n.question(a`{green Do you want to run {yellow ${e}} instead?} {white (yes/no)} [{yellow no}]\n > `, (o) => {
|
|
393
|
-
i(o === "yes" || o === "y"), n.close();
|
|
394
|
-
});
|
|
395
|
-
});
|
|
491
|
+
return console.log(o`{bgRed ERROR } Command {yellow ${t}} not found.\n`), this.io.askForConfirmation(o`{green Do you want to run {yellow ${e}} instead?} `);
|
|
396
492
|
}
|
|
397
493
|
async *listCommandsFiles(t) {
|
|
398
|
-
const e =
|
|
494
|
+
const e = R.readdirSync(t, { withFileTypes: !0 });
|
|
399
495
|
for (const n of e) {
|
|
400
|
-
const
|
|
496
|
+
const s = $.resolve(t, n.name);
|
|
401
497
|
if (n.isDirectory())
|
|
402
|
-
yield* this.listCommandsFiles(
|
|
498
|
+
yield* this.listCommandsFiles($.resolve(t, n.name));
|
|
403
499
|
else {
|
|
404
|
-
if (!
|
|
500
|
+
if (!s.endsWith(`${this.commandSuffix}.ts`) && !s.endsWith(`${this.commandSuffix}.js`))
|
|
405
501
|
continue;
|
|
406
|
-
yield
|
|
502
|
+
yield s;
|
|
407
503
|
}
|
|
408
504
|
}
|
|
409
505
|
}
|
|
410
506
|
}
|
|
411
|
-
class
|
|
507
|
+
class k extends E {
|
|
412
508
|
constructor(t) {
|
|
413
509
|
super(), this.opts = t;
|
|
414
510
|
}
|
|
415
511
|
signature = "help";
|
|
416
512
|
description = "Show help";
|
|
417
513
|
async handle() {
|
|
418
|
-
const t = this.opts.commandRegistry.getCommands(), e = this.opts.cliName ?? "Bob CLI", n = this.opts.cliVersion ?? "0.0.0",
|
|
419
|
-
console.log(
|
|
514
|
+
const t = this.opts.commandRegistry.getCommands(), e = this.opts.cliName ?? "Bob CLI", n = this.opts.cliVersion ?? "0.0.0", s = (await import("./package-7cIQdc3-.js"))?.default?.version ?? "0.0.0";
|
|
515
|
+
console.log(o`${e} {green ${n}} (core: {yellow ${s}})
|
|
420
516
|
|
|
421
517
|
{yellow Usage}:
|
|
422
518
|
command [options] [arguments]
|
|
423
519
|
|
|
424
520
|
{yellow Available commands}:
|
|
425
521
|
`);
|
|
426
|
-
const
|
|
427
|
-
for (const
|
|
428
|
-
const l =
|
|
429
|
-
r[l] || (r[l] = []), r[l].push(
|
|
522
|
+
const i = Math.max(...t.map((a) => a.command.length)) ?? 0, r = {};
|
|
523
|
+
for (const a of t) {
|
|
524
|
+
const l = a.command.split(":")[0];
|
|
525
|
+
r[l] || (r[l] = []), r[l].push(a);
|
|
430
526
|
}
|
|
431
|
-
const
|
|
432
|
-
for (const [
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
const
|
|
436
|
-
for (const d of
|
|
437
|
-
let g =
|
|
438
|
-
|
|
527
|
+
const m = Object.entries(r).sort(([a], [l]) => a.toLowerCase().localeCompare(l.toLowerCase())).sort(([, a], [, l]) => a.length - l.length);
|
|
528
|
+
for (const [a, l] of m) {
|
|
529
|
+
const p = l.length > 1;
|
|
530
|
+
p && console.log(o`{yellow ${a}}:`);
|
|
531
|
+
const h = l.sort((d, g) => d.command.toLowerCase().localeCompare(g.command.toLowerCase()));
|
|
532
|
+
for (const d of h) {
|
|
533
|
+
let g = C(i - d.command.length);
|
|
534
|
+
p && (g = g.slice(2)), console.log(o`${p ? " " : ""}{green ${d.command}} ${g} ${d.description}`);
|
|
439
535
|
}
|
|
440
536
|
}
|
|
441
537
|
}
|
|
442
538
|
}
|
|
443
|
-
class
|
|
539
|
+
class W extends c {
|
|
444
540
|
constructor(t) {
|
|
445
541
|
let e = `Argument "${t.param}" value is invalid.`;
|
|
446
542
|
t.reason ? e += ` Reason: ${t.reason}` : e += ` Value: "${t.value}"`, super(e), this.param = t;
|
|
447
543
|
}
|
|
448
544
|
pretty() {
|
|
449
545
|
const t = console.log;
|
|
450
|
-
t(
|
|
546
|
+
t(o` {white.bgRed ERROR } Argument {bold.yellow ${this.param.param}} value is invalid. `), (this.param.value || this.param.reason) && t(""), this.param.value && t(o` {blue Value}: ${this.param.value}`), this.param.reason && t(o` {yellow Reason}: ${this.param.reason}`);
|
|
451
547
|
}
|
|
452
548
|
}
|
|
453
|
-
class M extends
|
|
549
|
+
class M extends c {
|
|
454
550
|
constructor(t) {
|
|
455
551
|
let e = `Option "${t.option}" value is invalid.`;
|
|
456
552
|
t.reason ? e += ` Reason: ${t.reason}` : e += ` Value: "${t.value}"`, super(e), this.param = t;
|
|
457
553
|
}
|
|
458
554
|
pretty() {
|
|
459
555
|
const t = console.log;
|
|
460
|
-
t(
|
|
556
|
+
t(o` {white.bgRed ERROR } Option {bold.yellow ${this.param.option}} value is invalid. `), (this.param.value || this.param.reason) && t(""), this.param.value && t(o` {blue Value}: ${this.param.value}`), this.param.reason && t(o` {yellow Reason}: ${this.param.reason}`);
|
|
461
557
|
}
|
|
462
558
|
}
|
|
463
|
-
class
|
|
559
|
+
class I {
|
|
464
560
|
handle(t) {
|
|
465
|
-
if (t instanceof
|
|
561
|
+
if (t instanceof c)
|
|
466
562
|
return t.pretty(), -1;
|
|
467
563
|
throw t;
|
|
468
564
|
}
|
|
@@ -473,13 +569,13 @@ class N {
|
|
|
473
569
|
ctx;
|
|
474
570
|
helpCommand;
|
|
475
571
|
get CommandRegistryClass() {
|
|
476
|
-
return
|
|
572
|
+
return F;
|
|
477
573
|
}
|
|
478
574
|
get HelpCommandClass() {
|
|
479
|
-
return
|
|
575
|
+
return k;
|
|
480
576
|
}
|
|
481
577
|
get ExceptionHandlerClass() {
|
|
482
|
-
return
|
|
578
|
+
return I;
|
|
483
579
|
}
|
|
484
580
|
constructor(t = {}) {
|
|
485
581
|
this.ctx = t.ctx, this.commandRegistry = new this.CommandRegistryClass(), this.exceptionHandler = new this.ExceptionHandlerClass(), this.helpCommand = new this.HelpCommandClass({
|
|
@@ -507,9 +603,10 @@ class N {
|
|
|
507
603
|
}
|
|
508
604
|
export {
|
|
509
605
|
M as BadCommandOption,
|
|
510
|
-
|
|
511
|
-
|
|
606
|
+
W as BadCommandParameter,
|
|
607
|
+
c as BobError,
|
|
512
608
|
N as Cli,
|
|
513
|
-
|
|
514
|
-
|
|
609
|
+
E as Command,
|
|
610
|
+
S as CommandIO,
|
|
611
|
+
V as HelpOption
|
|
515
612
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const t = "bob-core", s = "1.
|
|
1
|
+
const t = "bob-core", s = "1.3.1", e = "BOB Core", i = "module", r = ["/dist"], n = { ".": { types: "./dist/types/src/index.d.ts", import: "./dist/bob-core.js", require: "./dist/bob-core.cjs" } }, o = { start: "node -r @swc-node/register debug/main.ts", build: "rimraf ./dist && vite build", prepare: "npm run build", test: "vitest run" }, c = "Léo Hubert", p = "ISC", d = { "@swc-node/register": "^1.11.1", "@types/minimist": "^1.2.5", "@types/node": "^20.14.5", "@types/prompts": "^2.4.9", "@types/string-similarity": "^4.0.2", rimraf: "^6.0.1", typescript: "^5.7.3", vite: "^7.1.6", "vite-plugin-dts": "^4.5.4", vitest: "^3.2.4" }, m = { chalk: "^4.1.2", minimist: "^1.2.8", prompts: "^2.4.2", "string-similarity": "^4.0.4" }, a = {
|
|
2
2
|
name: t,
|
|
3
3
|
version: s,
|
|
4
4
|
description: e,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="bob-core",t="1.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="bob-core",t="1.3.1",s="BOB Core",i="module",r=["/dist"],n={".":{types:"./dist/types/src/index.d.ts",import:"./dist/bob-core.js",require:"./dist/bob-core.cjs"}},o={start:"node -r @swc-node/register debug/main.ts",build:"rimraf ./dist && vite build",prepare:"npm run build",test:"vitest run"},c="Léo Hubert",p="ISC",d={"@swc-node/register":"^1.11.1","@types/minimist":"^1.2.5","@types/node":"^20.14.5","@types/prompts":"^2.4.9","@types/string-similarity":"^4.0.2",rimraf:"^6.0.1",typescript:"^5.7.3",vite:"^7.1.6","vite-plugin-dts":"^4.5.4",vitest:"^3.2.4"},a={chalk:"^4.1.2",minimist:"^1.2.8",prompts:"^2.4.2","string-similarity":"^4.0.4"},m={name:e,version:t,description:s,type:i,files:r,exports:n,scripts:o,author:c,license:p,devDependencies:d,dependencies:a};exports.author=c;exports.default=m;exports.dependencies=a;exports.description=s;exports.devDependencies=d;exports.exports=n;exports.files=r;exports.license=p;exports.name=e;exports.scripts=o;exports.type=i;exports.version=t;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CommandParser } from './CommandParser.js';
|
|
2
2
|
import { CommandOption } from './contracts/index.js';
|
|
3
|
+
import { CommandIO } from './CommandIO.js';
|
|
3
4
|
export type CommandExample = {
|
|
4
5
|
description: string;
|
|
5
6
|
command: string;
|
|
@@ -13,8 +14,10 @@ export declare abstract class Command<C = any> {
|
|
|
13
14
|
};
|
|
14
15
|
protected commandsExamples: CommandExample[];
|
|
15
16
|
protected parser: CommandParser;
|
|
17
|
+
protected io: CommandIO;
|
|
16
18
|
protected abstract handle(): Promise<void | number>;
|
|
17
|
-
|
|
19
|
+
protected get CommandParserClass(): typeof CommandParser;
|
|
20
|
+
protected get CommandIOClass(): typeof CommandIO;
|
|
18
21
|
protected defaultOptions(): CommandOption<Command<C>>[];
|
|
19
22
|
get command(): string;
|
|
20
23
|
run(ctx: C, ...args: any[]): Promise<number>;
|
|
@@ -31,4 +34,11 @@ export declare abstract class Command<C = any> {
|
|
|
31
34
|
protected argumentArray<T = string>(key: string, defaultValue?: Array<any>): Array<T>;
|
|
32
35
|
protected argumentBoolean(key: string, defaultValue?: boolean): boolean;
|
|
33
36
|
protected argumentNumber(key: string, defaultValue?: number | null): number | null;
|
|
37
|
+
/**
|
|
38
|
+
* Prompt utils
|
|
39
|
+
*/
|
|
40
|
+
askForConfirmation(...opts: Parameters<typeof this.io.askForConfirmation>): ReturnType<typeof this.io.askForConfirmation>;
|
|
41
|
+
askForInput(...opts: Parameters<typeof this.io.askForInput>): ReturnType<typeof this.io.askForInput>;
|
|
42
|
+
askForSelect(...opts: Parameters<typeof this.io.askForSelect>): ReturnType<typeof this.io.askForSelect>;
|
|
43
|
+
newLoader(...opts: Parameters<typeof this.io.newLoader>): ReturnType<typeof this.io.newLoader>;
|
|
34
44
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type SelectOption = {
|
|
2
|
+
title: string;
|
|
3
|
+
value?: any;
|
|
4
|
+
disabled?: boolean | undefined;
|
|
5
|
+
selected?: boolean | undefined;
|
|
6
|
+
description?: string | undefined;
|
|
7
|
+
};
|
|
8
|
+
export declare class CommandIO {
|
|
9
|
+
/**
|
|
10
|
+
* Prompt utils
|
|
11
|
+
*/
|
|
12
|
+
askForConfirmation(message?: string, defaultValue?: boolean): Promise<boolean>;
|
|
13
|
+
askForInput(message: string, defaultValue?: string | number, opts?: {
|
|
14
|
+
type?: 'text' | 'password' | 'number';
|
|
15
|
+
validate?: (value: string) => boolean | string;
|
|
16
|
+
min?: number;
|
|
17
|
+
max?: number;
|
|
18
|
+
}): Promise<string | null>;
|
|
19
|
+
askForToggle(message: string, defaultValue?: boolean, opts?: {
|
|
20
|
+
active?: string;
|
|
21
|
+
inactive?: string;
|
|
22
|
+
}): Promise<boolean>;
|
|
23
|
+
askForSelect(message: string, options: Array<string | SelectOption>, opts?: {
|
|
24
|
+
type?: 'select' | 'multiselect' | 'autocomplete' | 'autocompleteMultiselect';
|
|
25
|
+
initial?: number;
|
|
26
|
+
validate?: (value: string) => boolean;
|
|
27
|
+
suggest?: (input: string, choices: SelectOption[]) => Promise<SelectOption[]>;
|
|
28
|
+
}): Promise<string | null>;
|
|
29
|
+
newLoader(text?: string, chars?: string[], delay?: number): {
|
|
30
|
+
[Symbol.dispose]: () => void;
|
|
31
|
+
[Symbol.asyncDispose]: () => void;
|
|
32
|
+
updateText: (newText: string) => void;
|
|
33
|
+
stop: () => void;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { CommandOption } from './contracts/index.js';
|
|
2
|
+
import { CommandIO } from './CommandIO.js';
|
|
2
3
|
export type ArgSignature = {
|
|
3
4
|
name: string;
|
|
4
|
-
type: string;
|
|
5
|
+
type: 'string' | 'boolean' | 'array';
|
|
5
6
|
optional?: boolean;
|
|
6
7
|
variadic?: boolean;
|
|
7
8
|
alias?: string[];
|
|
@@ -10,6 +11,7 @@ export type ArgSignature = {
|
|
|
10
11
|
isOption?: boolean;
|
|
11
12
|
};
|
|
12
13
|
export declare class CommandParser {
|
|
14
|
+
protected readonly io: CommandIO;
|
|
13
15
|
protected readonly signature: string;
|
|
14
16
|
protected readonly helperDefinitions: {
|
|
15
17
|
[key: string]: string;
|
|
@@ -21,7 +23,7 @@ export declare class CommandParser {
|
|
|
21
23
|
private argumentsSignature;
|
|
22
24
|
private optionSignatures;
|
|
23
25
|
private optionAliases;
|
|
24
|
-
constructor(signature: string, helperDefinitions: {
|
|
26
|
+
constructor(io: CommandIO, signature: string, helperDefinitions: {
|
|
25
27
|
[key: string]: string;
|
|
26
28
|
}, defaultCommandOptions: CommandOption<any>[], ...args: any[]);
|
|
27
29
|
option(name: string): any;
|
|
@@ -42,5 +44,5 @@ export declare class CommandParser {
|
|
|
42
44
|
private parseSignature;
|
|
43
45
|
private parseDefaultOptions;
|
|
44
46
|
private parseParamSignature;
|
|
45
|
-
validate(): void
|
|
47
|
+
validate(): Promise<void>;
|
|
46
48
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Command } from './Command.js';
|
|
2
|
+
import { CommandIO } from './CommandIO.js';
|
|
2
3
|
export type CommandResolver = (path: string) => Promise<Command>;
|
|
3
4
|
export declare class CommandRegistry {
|
|
4
5
|
private readonly commands;
|
|
6
|
+
protected readonly io: CommandIO;
|
|
5
7
|
get commandSuffix(): string;
|
|
8
|
+
protected get CommandIOClass(): typeof CommandIO;
|
|
6
9
|
constructor();
|
|
7
10
|
getAvailableCommands(): string[];
|
|
8
11
|
getCommands(): Command[];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { BobError } from './BobError.js';
|
|
2
2
|
export declare class CommandNotFoundError extends BobError {
|
|
3
3
|
readonly command: string;
|
|
4
|
-
|
|
5
|
-
constructor(command: string, similarCommands: string[]);
|
|
4
|
+
constructor(command: string);
|
|
6
5
|
pretty(): void;
|
|
7
6
|
}
|