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 CHANGED
@@ -1,8 +1,9 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const O=require("minimist"),a=require("chalk"),R=require("node:fs"),C=require("path"),A=require("string-similarity");function S(r){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>r[t]})}}return e.default=r,Object.freeze(e)}const V=S(R),x=S(A);class c extends Error{}class $ extends c{constructor(e){super(`Argument "${e.name}" is required.`),this.paramSignature=e}pretty(){const e=console.log;this.paramSignature.help&&e(a`{yellow Help}: ${this.paramSignature.help}\n`),e(a` {white.bgRed ERROR } Argument {bold.yellow ${this.paramSignature.name}} is required.`)}}class f extends c{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(a`{yellow Available options}:`);for(const t of this.optionsSignature){const n=t.type?a`{white (${t.type})}`:"",i=" ".repeat(20-t.name.length);e(a` {green ${t.name}} ${i} ${t.help??"\b"} ${n}`)}e("")}e(a` {white.bgRed ERROR } Option {bold.yellow ${this.option}} is missing in the signature.`)}}class y extends c{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(a`\n{yellow Available arguments}:`);for(const t of this.argumentSignatures){const n=t.type?a`{white (${t.type})}`:"",i=" ".repeat(20-t.name.length);e(a` {green ${t.name}} ${i} ${t.help??"\b"} ${n}`)}e("")}e(a` {white.bgRed ERROR } Argument {bold.yellow ${this.argument}} is missing in the signature.`)}}class E extends c{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(a`\n{yellow Available options}:`);for(const t of this.optionsSignature){const n=t.type?a`{white (${t.type})}`:"",i=`--${t.name}${t.alias?.map(l=>`, -${l}`).join("")??""}`,o=" ".repeat(30-i.length);e(a` {green ${i}} ${o} ${t.help??"\b"} ${n}`)}e("")}e(a` {white.bgRed ERROR } Option {bold.yellow ${this.option}} is not recognized.`)}}class j{constructor(e,t,n,...i){this.signature=e,this.helperDefinitions=t,this.defaultCommandOptions=n;const[o,...l]=e.split(/\{(.*?)\}/g).map(m=>m.trim()).filter(Boolean),{_:p,...s}=O(i);this.command=o,this.parseSignature(l),this.parseDefaultOptions(),this.handleArguments(p),this.handleOptions(s)}command;arguments={};options={};argumentsSignature={};optionSignatures={};optionAliases={};option(e){if(!this.optionSignatures[e])throw new f(e,Object.values(this.optionSignatures));return this.options[e]}setOption(e,t){if(!this.optionSignatures[e])throw new f(e,Object.values(this.optionSignatures));this.options[e]=t}optionHelp(e){if(!this.optionSignatures[e])throw new f(e,Object.values(this.optionSignatures));return this.optionSignatures[e].help}argument(e){if(!this.argumentsSignature[e])throw new y(e,Object.values(this.argumentsSignature));return this.arguments[e]}setArgument(e,t){if(!this.argumentsSignature[e])throw new y(e,Object.values(this.argumentsSignature));this.arguments[e]=t}argumentHelp(e){if(!this.argumentsSignature[e])throw new y(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 i=this.argumentsSignature[t];if(i.variadic)this.arguments[t]=e;else{const o=e.shift();this.arguments[t]=this.getParamValue(o,i)}}}handleOptions(e){for(const[t,n]of Object.entries(e)){const i=this.optionAliases[t],o=this.optionSignatures[t]??this.optionSignatures[i];if(!o)throw new E(t,Object.values(this.optionSignatures));this.options[t]=this.getParamValue(n,o);for(const l of o.alias??[])e[l]&&(this.options[o.name]=e[l])}}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 i of n.alias??[])this.optionAliases[i]=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,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,i]=t.name.split(":");t.name=n.trim(),t.help=i.trim()}if(t.name.includes("=")){const[n,i]=t.name.split("=");t.name=n.trim(),t.defaultValue=i.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,...i]=t.name.split("|");t.name=n.trim(),t.alias=i.map(o=>o.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}validate(){for(const[e,t]of Object.entries(this.arguments)){const n=this.argumentsSignature[e];if(!t&&!n.optional)throw new $(n);if(!t?.length&&n.variadic&&!n.optional)throw new $(n)}}}function w(r){return new Array(r+5).join(" ")}class b{option="help";alias=["h"];defaultValue=!1;description=a`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(s=>({...s,optionWithAlias:`--${s.name}${s.alias?.map(m=>`, -${m}`).join("")??""}`})),i=t.filter(s=>!s.optional);e(a`{yellow Description}:`),e(a` ${this.description}\n`),e(a`{yellow Usage}:`),e(a` ${this.command} ${i.length>0?i.map(s=>`<${s.name}>`).join(" "):"\b"} [options]`);const o=Math.max(...n.map(s=>s.optionWithAlias.length))??0,l=Math.max(...t.map(s=>s.name.length))??0,p=l>o?l:o;if(t.length>0){e(a`\n{yellow Arguments}:`);for(const s of t){const m=w(p-s.name.length);let u=a` {green ${s.name}} ${m} ${s.help??"\b"}`;if(s.defaultValue!==void 0&&s.optional){const h=s.type==="array"?JSON.stringify(s.defaultValue):s.defaultValue;u+=a` {yellow [default: ${h}]}`}s.variadic&&(u+=a` {white (variadic)}`),e(u)}}if(n.length>0){e(a`\n{yellow Options}:`);for(const s of n){const m=w(p-s.optionWithAlias.length);let u=a`{green ${s.optionWithAlias}} ${m} ${s.help??"\b"}`;if(s.type&&(u+=a` {white (${s.type})}`),s.defaultValue!==void 0&&s.optional){const h=s.type==="array"?JSON.stringify(s.defaultValue):s.defaultValue;u+=a` {yellow [default: ${h}]}`}e(u)}}if(this.commandsExamples.length>0){e(a`\n{yellow Examples}:`);let s=process.argv[0].split("/").pop();s==="node"&&(s+=" "+process.argv[1].split("/").pop());for(const[m,u]of this.commandsExamples.entries())m>0&&e(""),e(` ${u.description}
2
- `),e(a` {green ${s} ${u.command}}`)}return-1}}class v{ctx;helperDefinitions={};commandsExamples=[];parser;get CommandParserClass(){return j}defaultOptions(){return[new b]}get command(){return this.parser?this.parser.command:this.signature.split(" ")[0]}async run(e,...t){this.ctx=e;const n=this.defaultOptions();this.parser=new this.CommandParserClass(this.signature,this.helperDefinitions,n,...t);for(const i of n)if(this.parser.option(i.option)){const o=await i.handler.call(this);if(o&&o!==0)return o}return 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}}class P extends c{constructor(e,t){super(`Command "${e}" not found.`),this.command=e,this.similarCommands=t}pretty(){const e=console.log;if(this.similarCommands.length){e(a` {white.bgRed ERROR } Command "${this.command}" not found, Did you mean one of these?`);for(const t of this.similarCommands)e(a` {gray ⇂ ${t}}`)}else e(a` {white.bgRed ERROR } Command "${this.command}" not found.`)}}class H{commands={};get commandSuffix(){return"Command"}constructor(){}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 i=typeof t=="string"?this.commands[t]:t,o=typeof t=="string"?t:i.command;if(!i){const l=await this.suggestCommand(o);return l?await this.runCommand(e,l,...n):1}return await i.run(e,...n)}async suggestCommand(e){const t=this.getAvailableCommands(),{bestMatch:n,bestMatchIndex:i,ratings:o}=x.findBestMatch(e,t),l=o.filter(p=>p.rating>.3).map(p=>p.target);if(n.rating>0&&l.length<=1||n.rating>.7&&l.length>1){const p=t[i];return await this.askRunSimilarCommand(e,p)?p:null}throw new P(e,l)}async askRunSimilarCommand(e,t){const n=require("readline").createInterface({input:process.stdin,output:process.stdout});return console.log(a` {bgRed ERROR } Command {yellow ${e}} not found.\n`),new Promise(i=>{n.question(a`{green Do you want to run {yellow ${t}} instead?} {white (yes/no)} [{yellow no}]\n > `,o=>{i(o==="yes"||o==="y"),n.close()})})}async*listCommandsFiles(e){const t=V.readdirSync(e,{withFileTypes:!0});for(const n of t){const i=C.resolve(e,n.name);if(n.isDirectory())yield*this.listCommandsFiles(C.resolve(e,n.name));else{if(!i.endsWith(`${this.commandSuffix}.ts`)&&!i.endsWith(`${this.commandSuffix}.js`))continue;yield i}}}}class B extends v{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",i=(await Promise.resolve().then(()=>require("./package-sv16L6xn.cjs")))?.default?.version??"0.0.0";console.log(a`${t} {green ${n}} (core: {yellow ${i}})
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 o=Math.max(...e.map(s=>s.command.length))??0,l={};for(const s of e){const m=s.command.split(":")[0];l[m]||(l[m]=[]),l[m].push(s)}const p=Object.entries(l).sort(([s],[m])=>s.toLowerCase().localeCompare(m.toLowerCase())).sort(([,s],[,m])=>s.length-m.length);for(const[s,m]of p){const u=m.length>1;u&&console.log(a`{yellow ${s}}:`);const h=m.sort((d,g)=>d.command.toLowerCase().localeCompare(g.command.toLowerCase()));for(const d of h){let g=w(o-d.command.length);u&&(g=g.slice(2)),console.log(a`${u?" ":""}{green ${d.command}} ${g} ${d.description}`)}}}}class D extends c{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(a` {white.bgRed ERROR } Argument {bold.yellow ${this.param.param}} value is invalid. `),(this.param.value||this.param.reason)&&e(""),this.param.value&&e(a` {blue Value}: ${this.param.value}`),this.param.reason&&e(a` {yellow Reason}: ${this.param.reason}`)}}class M extends c{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(a` {white.bgRed ERROR } Option {bold.yellow ${this.param.option}} value is invalid. `),(this.param.value||this.param.reason)&&e(""),this.param.value&&e(a` {blue Value}: ${this.param.value}`),this.param.reason&&e(a` {yellow Reason}: ${this.param.reason}`)}}class q{handle(e){if(e instanceof c)return e.pretty(),-1;throw e}}class W{commandRegistry;exceptionHandler;ctx;helpCommand;get CommandRegistryClass(){return H}get HelpCommandClass(){return B}get ExceptionHandlerClass(){return q}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=M;exports.BadCommandParameter=D;exports.BobError=c;exports.Cli=W;exports.Command=v;exports.HelpOption=b;
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 S from "minimist";
2
- import a from "chalk";
3
- import * as v from "node:fs";
4
- import C from "path";
5
- import * as R from "string-similarity";
6
- class h extends Error {
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 $ extends h {
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
- this.paramSignature.help && t(a`{yellow Help}: ${this.paramSignature.help}\n`), t(a` {white.bgRed ERROR } Argument {bold.yellow ${this.paramSignature.name}} is required.`);
15
+ t(o`{white.bgRed ERROR } Argument {bold.yellow ${this.paramSignature.name}} is required.`);
15
16
  }
16
17
  }
17
- class f extends h {
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(a`{yellow Available options}:`);
25
+ t(o`{yellow Available options}:`);
25
26
  for (const e of this.optionsSignature) {
26
- const n = e.type ? a`{white (${e.type})}` : "", i = " ".repeat(20 - e.name.length);
27
- t(a` {green ${e.name}} ${i} ${e.help ?? "\b"} ${n}`);
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(a` {white.bgRed ERROR } Option {bold.yellow ${this.option}} is missing in the signature.`);
32
+ t(o`{white.bgRed ERROR } Option {bold.yellow ${this.option}} is missing in the signature.`);
32
33
  }
33
34
  }
34
- class y extends h {
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(a`\n{yellow Available arguments}:`);
42
+ t(o`\n{yellow Available arguments}:`);
42
43
  for (const e of this.argumentSignatures) {
43
- const n = e.type ? a`{white (${e.type})}` : "", i = " ".repeat(20 - e.name.length);
44
- t(a` {green ${e.name}} ${i} ${e.help ?? "\b"} ${n}`);
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(a` {white.bgRed ERROR } Argument {bold.yellow ${this.argument}} is missing in the signature.`);
49
+ t(o`{white.bgRed ERROR } Argument {bold.yellow ${this.argument}} is missing in the signature.`);
49
50
  }
50
51
  }
51
- class b extends h {
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(a`\n{yellow Available options}:`);
59
+ t(o`\n{yellow Available options}:`);
59
60
  for (const e of this.optionsSignature) {
60
- const n = e.type ? a`{white (${e.type})}` : "", i = `--${e.name}${e.alias?.map((r) => `, -${r}`).join("") ?? ""}`, o = " ".repeat(30 - i.length);
61
- t(a` {green ${i}} ${o} ${e.help ?? "\b"} ${n}`);
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(a` {white.bgRed ERROR } Option {bold.yellow ${this.option}} is not recognized.`);
66
+ t(o`{white.bgRed ERROR } Option {bold.yellow ${this.option}} is not recognized.`);
66
67
  }
67
68
  }
68
- class O {
69
- constructor(t, e, n, ...i) {
70
- this.signature = t, this.helperDefinitions = e, this.defaultCommandOptions = n;
71
- const [o, ...r] = t.split(/\{(.*?)\}/g).map((l) => l.trim()).filter(Boolean), { _: p, ...s } = S(i);
72
- this.command = o, this.parseSignature(r), this.parseDefaultOptions(), this.handleArguments(p), this.handleOptions(s);
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 f(t, Object.values(this.optionSignatures));
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 f(t, Object.values(this.optionSignatures));
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 f(t, Object.values(this.optionSignatures));
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 y(t, Object.values(this.argumentsSignature));
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 y(t, Object.values(this.argumentsSignature));
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 y(t, Object.values(this.argumentsSignature));
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 i = this.argumentsSignature[e];
122
- if (i.variadic)
122
+ const s = this.argumentsSignature[e];
123
+ if (s.variadic)
123
124
  this.arguments[e] = t;
124
125
  else {
125
- const o = t.shift();
126
- this.arguments[e] = this.getParamValue(o, i);
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 i = this.optionAliases[e], o = this.optionSignatures[e] ?? this.optionSignatures[i];
133
- if (!o)
134
- throw new b(e, Object.values(this.optionSignatures));
135
- this.options[e] = this.getParamValue(n, o);
136
- for (const r of o.alias ?? [])
137
- t[r] && (this.options[o.name] = t[r]);
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 i of n.alias ?? [])
146
- this.optionAliases[i] = n.name;
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, i] = e.name.split(":");
180
- e.name = n.trim(), e.help = i.trim();
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, i] = e.name.split("=");
184
- e.name = n.trim(), e.defaultValue = i.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;
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, ...i] = e.name.split("|");
189
- e.name = n.trim(), e.alias = i.map((o) => o.trim());
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
- throw new $(n);
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 $(n);
214
+ throw new v(n);
200
215
  }
201
216
  }
202
217
  }
203
- function w(m) {
204
- return new Array(m + 5).join(" ");
218
+ function C(u) {
219
+ return new Array(u + 5).join(" ");
205
220
  }
206
- class A {
221
+ class V {
207
222
  option = "help";
208
223
  alias = ["h"];
209
224
  defaultValue = !1;
210
- description = a`Display help for the given command. When no command is given display help for the {green list} command`;
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((s) => ({
213
- ...s,
214
- optionWithAlias: `--${s.name}${s.alias?.map((l) => `, -${l}`).join("") ?? ""}`
215
- })), i = e.filter((s) => !s.optional);
216
- t(a`{yellow Description}:`), t(a` ${this.description}\n`), t(a`{yellow Usage}:`), t(a` ${this.command} ${i.length > 0 ? i.map((s) => `<${s.name}>`).join(" ") : "\b"} [options]`);
217
- const o = Math.max(...n.map((s) => s.optionWithAlias.length)) ?? 0, r = Math.max(...e.map((s) => s.name.length)) ?? 0, p = r > o ? r : o;
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(a`\n{yellow Arguments}:`);
220
- for (const s of e) {
221
- const l = w(p - s.name.length);
222
- let u = a` {green ${s.name}} ${l} ${s.help ?? "\b"}`;
223
- if (s.defaultValue !== void 0 && s.optional) {
224
- const c = s.type === "array" ? JSON.stringify(s.defaultValue) : s.defaultValue;
225
- u += a` {yellow [default: ${c}]}`;
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
- s.variadic && (u += a` {white (variadic)}`), t(u);
242
+ a.variadic && (p += o` {white (variadic)}`), t(p);
228
243
  }
229
244
  }
230
245
  if (n.length > 0) {
231
- t(a`\n{yellow Options}:`);
232
- for (const s of n) {
233
- const l = w(p - s.optionWithAlias.length);
234
- let u = a`{green ${s.optionWithAlias}} ${l} ${s.help ?? "\b"}`;
235
- if (s.type && (u += a` {white (${s.type})}`), s.defaultValue !== void 0 && s.optional) {
236
- const c = s.type === "array" ? JSON.stringify(s.defaultValue) : s.defaultValue;
237
- u += a` {yellow [default: ${c}]}`;
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(u);
254
+ t(p);
240
255
  }
241
256
  }
242
257
  if (this.commandsExamples.length > 0) {
243
- t(a`\n{yellow Examples}:`);
244
- let s = process.argv[0].split("/").pop();
245
- s === "node" && (s += " " + process.argv[1].split("/").pop());
246
- for (const [l, u] of this.commandsExamples.entries())
247
- l > 0 && t(""), t(` ${u.description}
248
- `), t(a` {green ${s} ${u.command}}`);
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 V {
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 O;
336
+ return x;
337
+ }
338
+ get CommandIOClass() {
339
+ return S;
260
340
  }
261
341
  defaultOptions() {
262
- return [new A()];
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 i of n)
272
- if (this.parser.option(i.option)) {
273
- const o = await i.handler.call(this);
274
- if (o && o !== 0)
275
- return o;
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 x extends h {
319
- constructor(t, e) {
320
- super(`Command "${t}" not found.`), this.command = t, this.similarCommands = e;
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
- if (this.similarCommands.length) {
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 E {
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 i = typeof e == "string" ? this.commands[e] : e, o = typeof e == "string" ? e : i.command;
372
- if (!i) {
373
- const r = await this.suggestCommand(o);
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 i.run(t, ...n);
471
+ return await s.run(t, ...n);
377
472
  }
378
473
  async suggestCommand(t) {
379
- const e = this.getAvailableCommands(), { bestMatch: n, bestMatchIndex: i, ratings: o } = R.findBestMatch(t, e), r = o.filter((p) => p.rating > 0.3).map((p) => p.target);
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 p = e[i];
382
- return await this.askRunSimilarCommand(t, p) ? p : null;
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 x(t, r);
488
+ throw new j(t);
385
489
  }
386
490
  async askRunSimilarCommand(t, e) {
387
- const n = require("readline").createInterface({
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 = v.readdirSync(t, { withFileTypes: !0 });
494
+ const e = R.readdirSync(t, { withFileTypes: !0 });
399
495
  for (const n of e) {
400
- const i = C.resolve(t, n.name);
496
+ const s = $.resolve(t, n.name);
401
497
  if (n.isDirectory())
402
- yield* this.listCommandsFiles(C.resolve(t, n.name));
498
+ yield* this.listCommandsFiles($.resolve(t, n.name));
403
499
  else {
404
- if (!i.endsWith(`${this.commandSuffix}.ts`) && !i.endsWith(`${this.commandSuffix}.js`))
500
+ if (!s.endsWith(`${this.commandSuffix}.ts`) && !s.endsWith(`${this.commandSuffix}.js`))
405
501
  continue;
406
- yield i;
502
+ yield s;
407
503
  }
408
504
  }
409
505
  }
410
506
  }
411
- class j extends V {
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", i = (await import("./package-B3ICsvyj.js"))?.default?.version ?? "0.0.0";
419
- console.log(a`${e} {green ${n}} (core: {yellow ${i}})
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 o = Math.max(...t.map((s) => s.command.length)) ?? 0, r = {};
427
- for (const s of t) {
428
- const l = s.command.split(":")[0];
429
- r[l] || (r[l] = []), r[l].push(s);
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 p = Object.entries(r).sort(([s], [l]) => s.toLowerCase().localeCompare(l.toLowerCase())).sort(([, s], [, l]) => s.length - l.length);
432
- for (const [s, l] of p) {
433
- const u = l.length > 1;
434
- u && console.log(a`{yellow ${s}}:`);
435
- const c = l.sort((d, g) => d.command.toLowerCase().localeCompare(g.command.toLowerCase()));
436
- for (const d of c) {
437
- let g = w(o - d.command.length);
438
- u && (g = g.slice(2)), console.log(a`${u ? " " : ""}{green ${d.command}} ${g} ${d.description}`);
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 B extends h {
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(a` {white.bgRed ERROR } Argument {bold.yellow ${this.param.param}} value is invalid. `), (this.param.value || this.param.reason) && t(""), this.param.value && t(a` {blue Value}: ${this.param.value}`), this.param.reason && t(a` {yellow Reason}: ${this.param.reason}`);
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 h {
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(a` {white.bgRed ERROR } Option {bold.yellow ${this.param.option}} value is invalid. `), (this.param.value || this.param.reason) && t(""), this.param.value && t(a` {blue Value}: ${this.param.value}`), this.param.reason && t(a` {yellow Reason}: ${this.param.reason}`);
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 H {
559
+ class I {
464
560
  handle(t) {
465
- if (t instanceof h)
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 E;
572
+ return F;
477
573
  }
478
574
  get HelpCommandClass() {
479
- return j;
575
+ return k;
480
576
  }
481
577
  get ExceptionHandlerClass() {
482
- return H;
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
- B as BadCommandParameter,
511
- h as BobError,
606
+ W as BadCommandParameter,
607
+ c as BobError,
512
608
  N as Cli,
513
- V as Command,
514
- A as HelpOption
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.2.4", 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 = {
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.2.4",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
+ "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
- private get CommandParserClass();
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
- readonly similarCommands: string[];
5
- constructor(command: string, similarCommands: string[]);
4
+ constructor(command: string);
6
5
  pretty(): void;
7
6
  }
@@ -1,4 +1,5 @@
1
1
  export * from './Command.js';
2
+ export * from './CommandIO.js';
2
3
  export * from './Cli.js';
3
4
  export * from './errors/index.js';
4
5
  export * from './contracts/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bob-core",
3
- "version": "1.2.4",
3
+ "version": "1.3.1",
4
4
  "description": "BOB Core",
5
5
  "type": "module",
6
6
  "files": [