bob-core 1.3.1 → 1.3.3

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.
@@ -1,9 +1,9 @@
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}})
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(i=>`, -${i}`).join("")??""}`,r=" ".repeat(30-s.length);e(o` {green ${s}} ${r} ${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,...r){this.io=e,this.signature=t,this.helperDefinitions=n,this.defaultCommandOptions=s;const[i,...u]=t.split(/\{(.*?)\}/g).map(c=>c.trim()).filter(Boolean),{_:a,...m}=A(r);this.command=i,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 r=e.shift();this.arguments[t]=this.getParamValue(r,s)}}}handleOptions(e){for(const[t,n]of Object.entries(e)){const s=this.optionAliases[t],r=this.optionSignatures[t]??this.optionSignatures[s];if(!r)throw new k(t,Object.values(this.optionSignatures));this.options[t]=this.getParamValue(n,r);for(const i of r.alias??[])e[i]&&(this.options[r.name]=e[i])}}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(r=>r.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 r=o`{yellow.bold ${n.name}} is required`;n.help&&(r+=o`: {gray (${n.help})}`),r+=`
2
+ `,s=await this.io.askForInput(r,n.defaultValue,{validate:i=>i?.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 r=Math.max(...n.map(a=>a.optionWithAlias.length))??0,i=Math.max(...t.map(a=>a.name.length))??0,u=i>r?i:r;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 i of t)typeof i=="string"?s.push({title:i,value:i}):s.push(i);return(await f({type:"select",name:"value",message:e,choices:s,...n}))?.value??null}newLoader(e="",t=["⠙","⠘","⠰","⠴","⠤","⠦","⠆","⠃","⠋","⠉"],n=100){let s=e,r=null,i=0;const u=setInterval(function(){r&&(process.stdout.write(new TextEncoder().encode("\r"+" ".repeat(r.length+5)+"\r")),r=null),process.stdout.write(new TextEncoder().encode("\r"+t[i++]+" "+s)),i=i%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=>{r=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 r of n)if(this.parser.option(r.option)){const i=await r.handler.call(this);if(i&&i!==0)return i}await this.parser.validate();const s=this.preHandle?await this.preHandle():null;return s&&s!==0?s: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 H 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 I{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,r=typeof t=="string"?t:s.command;if(!s){const i=await this.suggestCommand(r);return i?await this.runCommand(e,i,...n):1}return await s.run(e,...n)}async suggestCommand(e){const t=this.getAvailableCommands(),{bestMatch:n,bestMatchIndex:s,ratings:r}=j.findBestMatch(e,t),i=r.filter(u=>u.rating>.3).map(u=>u.target);if(n.rating>0&&i.length<=1||n.rating>.7&&i.length>1){const u=t[s];return await this.askRunSimilarCommand(e,u)?u:null}if(i.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?}`,i);if(u)return u}throw new H(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 D 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-BtTsLWPa.cjs")))?.default?.version??"0.0.0";console.log(o`${t} {green ${n}} (core: {yellow ${s}})
4
4
 
5
5
  {yellow Usage}:
6
6
  command [options] [arguments]
7
7
 
8
8
  {yellow Available commands}:
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;
9
+ `);const r=Math.max(...e.map(a=>a.command.length))??0,i={};for(const a of e){const m=a.command.split(":")[0];i[m]||(i[m]=[]),i[m].push(a)}const u=Object.entries(i).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(r-d.command.length);c&&(g=g.slice(2)),console.log(o`${c?" ":""}{green ${d.command}} ${g} ${d.description}`)}}}}class P 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 B 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 I}get HelpCommandClass(){return D}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=B;exports.BadCommandParameter=P;exports.BobError=p;exports.Cli=T;exports.Command=R;exports.CommandIO=v;exports.HelpOption=O;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="bob-core",s="1.3.3",t="BOB Core",i="module",n=["/dist"],r={".":{import:"./dist/esm/bob-core.js",require:"./dist/cjs/bob-core.cjs"}},o={"*":{"*":["./dist/types/*.d.ts"]}},c={start:"node -r @swc-node/register debug/main.ts",build:"rimraf ./dist && vite build",prepare:"npm run build",test:"vitest run"},p="Léo Hubert",d="ISC",m={"@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"},l={name:e,version:s,description:t,type:i,files:n,exports:r,typesVersions:o,scripts:c,author:p,license:d,devDependencies:m,dependencies:a};exports.author=p;exports.default=l;exports.dependencies=a;exports.description=t;exports.devDependencies=m;exports.exports=r;exports.files=n;exports.license=d;exports.name=e;exports.scripts=c;exports.type=i;exports.typesVersions=o;exports.version=s;
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -58,8 +58,8 @@ class A extends c {
58
58
  if (this.optionsSignature.length > 0) {
59
59
  t(o`\n{yellow Available options}:`);
60
60
  for (const e of this.optionsSignature) {
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}`);
61
+ const n = e.type ? o`{white (${e.type})}` : "", s = `--${e.name}${e.alias?.map((i) => `, -${i}`).join("") ?? ""}`, r = " ".repeat(30 - s.length);
62
+ t(o` {green ${s}} ${r} ${e.help ?? "\b"} ${n}`);
63
63
  }
64
64
  t("");
65
65
  }
@@ -67,10 +67,10 @@ class A extends c {
67
67
  }
68
68
  }
69
69
  class x {
70
- constructor(t, e, n, s, ...i) {
70
+ constructor(t, e, n, s, ...r) {
71
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);
72
+ const [i, ...m] = e.split(/\{(.*?)\}/g).map((p) => p.trim()).filter(Boolean), { _: a, ...l } = b(r);
73
+ this.command = i, this.parseSignature(m), this.parseDefaultOptions(), this.handleArguments(a), this.handleOptions(l);
74
74
  }
75
75
  command;
76
76
  arguments = {};
@@ -123,19 +123,19 @@ class x {
123
123
  if (s.variadic)
124
124
  this.arguments[e] = t;
125
125
  else {
126
- const i = t.shift();
127
- this.arguments[e] = this.getParamValue(i, s);
126
+ const r = t.shift();
127
+ this.arguments[e] = this.getParamValue(r, s);
128
128
  }
129
129
  }
130
130
  }
131
131
  handleOptions(t) {
132
132
  for (const [e, n] of Object.entries(t)) {
133
- const s = this.optionAliases[e], i = this.optionSignatures[e] ?? this.optionSignatures[s];
134
- if (!i)
133
+ const s = this.optionAliases[e], r = this.optionSignatures[e] ?? this.optionSignatures[s];
134
+ if (!r)
135
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]);
136
+ this.options[e] = this.getParamValue(n, r);
137
+ for (const i of r.alias ?? [])
138
+ t[i] && (this.options[r.name] = t[i]);
139
139
  }
140
140
  }
141
141
  parseSignature(t) {
@@ -187,7 +187,7 @@ class x {
187
187
  e.name.startsWith("--") && (e.optional = !0, e.defaultValue = !1, e.type = "boolean");
188
188
  if (e.name.includes("|")) {
189
189
  const [n, ...s] = e.name.split("|");
190
- e.name = n.trim(), e.alias = s.map((i) => i.trim());
190
+ e.name = n.trim(), e.alias = s.map((r) => r.trim());
191
191
  }
192
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;
193
193
  }
@@ -198,10 +198,10 @@ class x {
198
198
  let s = null;
199
199
  switch (n.type) {
200
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`
201
+ let r = o`{yellow.bold ${n.name}} is required`;
202
+ n.help && (r += o`: {gray (${n.help})}`), r += `
203
+ `, s = await this.io.askForInput(r, n.defaultValue, {
204
+ validate: (i) => i?.trim()?.length ? !0 : `${n.name} cannot be empty`
205
205
  });
206
206
  break;
207
207
  }
@@ -229,7 +229,7 @@ class V {
229
229
  optionWithAlias: `--${a.name}${a.alias?.map((l) => `, -${l}`).join("") ?? ""}`
230
230
  })), s = e.filter((a) => !a.optional);
231
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;
232
+ const r = Math.max(...n.map((a) => a.optionWithAlias.length)) ?? 0, i = Math.max(...e.map((a) => a.name.length)) ?? 0, m = i > r ? i : r;
233
233
  if (e.length > 0) {
234
234
  t(o`\n{yellow Arguments}:`);
235
235
  for (const a of e) {
@@ -299,8 +299,8 @@ class S {
299
299
  if (e.length === 0)
300
300
  throw new Error("No options provided");
301
301
  const s = [];
302
- for (const r of e)
303
- typeof r == "string" ? s.push({ title: r, value: r }) : s.push(r);
302
+ for (const i of e)
303
+ typeof i == "string" ? s.push({ title: i, value: i }) : s.push(i);
304
304
  return (await f({
305
305
  type: "select",
306
306
  name: "value",
@@ -310,9 +310,9 @@ class S {
310
310
  }))?.value ?? null;
311
311
  }
312
312
  newLoader(t = "", e = ["⠙", "⠘", "⠰", "⠴", "⠤", "⠦", "⠆", "⠃", "⠋", "⠉"], n = 100) {
313
- let s = t, i = null, r = 0;
313
+ let s = t, r = null, i = 0;
314
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;
315
+ r && (process.stdout.write(new TextEncoder().encode("\r" + " ".repeat(r.length + 5) + "\r")), r = null), process.stdout.write(new TextEncoder().encode("\r" + e[i++] + " " + s)), i = i % e.length;
316
316
  }, n), a = () => {
317
317
  clearInterval(m), process.stdout.write(new TextEncoder().encode("\r" + " ".repeat(s.length + 5) + "\r"));
318
318
  };
@@ -320,7 +320,7 @@ class S {
320
320
  [Symbol.dispose]: a,
321
321
  [Symbol.asyncDispose]: a,
322
322
  updateText: (l) => {
323
- i = s, s = l;
323
+ r = s, s = l;
324
324
  },
325
325
  stop: a
326
326
  };
@@ -348,13 +348,15 @@ class E {
348
348
  this.ctx = t;
349
349
  const n = this.defaultOptions();
350
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);
351
+ for (const r of n)
352
+ if (this.parser.option(r.option)) {
353
+ const i = await r.handler.call(this);
354
354
  if (i && i !== 0)
355
355
  return i;
356
356
  }
357
- return await this.parser.validate(), await this.handle() ?? 0;
357
+ await this.parser.validate();
358
+ const s = this.preHandle ? await this.preHandle() : null;
359
+ return s && s !== 0 ? s : await this.handle() ?? 0;
358
360
  }
359
361
  setOption(t, e) {
360
362
  this.parser.setOption(t, e);
@@ -463,24 +465,24 @@ class F {
463
465
  }
464
466
  }
465
467
  async runCommand(t, e, ...n) {
466
- const s = typeof e == "string" ? this.commands[e] : e, i = typeof e == "string" ? e : s.command;
468
+ const s = typeof e == "string" ? this.commands[e] : e, r = typeof e == "string" ? e : s.command;
467
469
  if (!s) {
468
- const r = await this.suggestCommand(i);
469
- return r ? await this.runCommand(t, r, ...n) : 1;
470
+ const i = await this.suggestCommand(r);
471
+ return i ? await this.runCommand(t, i, ...n) : 1;
470
472
  }
471
473
  return await s.run(t, ...n);
472
474
  }
473
475
  async suggestCommand(t) {
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);
475
- if (n.rating > 0 && r.length <= 1 || n.rating > 0.7 && r.length > 1) {
476
+ const e = this.getAvailableCommands(), { bestMatch: n, bestMatchIndex: s, ratings: r } = O.findBestMatch(t, e), i = r.filter((m) => m.rating > 0.3).map((m) => m.target);
477
+ if (n.rating > 0 && i.length <= 1 || n.rating > 0.7 && i.length > 1) {
476
478
  const m = e[s];
477
479
  return await this.askRunSimilarCommand(t, m) ? m : null;
478
480
  }
479
- if (r.length) {
481
+ if (i.length) {
480
482
  console.log(o`{bgRed ERROR } Command {yellow ${t}} not found.\n`);
481
483
  const m = await this.io.askForSelect(
482
484
  o`{green Did you mean to run one of these commands instead?}`,
483
- r
485
+ i
484
486
  );
485
487
  if (m)
486
488
  return m;
@@ -511,7 +513,7 @@ class k extends E {
511
513
  signature = "help";
512
514
  description = "Show help";
513
515
  async handle() {
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";
516
+ const t = this.opts.commandRegistry.getCommands(), e = this.opts.cliName ?? "Bob CLI", n = this.opts.cliVersion ?? "0.0.0", s = (await import("./package-DIsWn6xB.js"))?.default?.version ?? "0.0.0";
515
517
  console.log(o`${e} {green ${n}} (core: {yellow ${s}})
516
518
 
517
519
  {yellow Usage}:
@@ -519,18 +521,18 @@ class k extends E {
519
521
 
520
522
  {yellow Available commands}:
521
523
  `);
522
- const i = Math.max(...t.map((a) => a.command.length)) ?? 0, r = {};
524
+ const r = Math.max(...t.map((a) => a.command.length)) ?? 0, i = {};
523
525
  for (const a of t) {
524
526
  const l = a.command.split(":")[0];
525
- r[l] || (r[l] = []), r[l].push(a);
527
+ i[l] || (i[l] = []), i[l].push(a);
526
528
  }
527
- const m = Object.entries(r).sort(([a], [l]) => a.toLowerCase().localeCompare(l.toLowerCase())).sort(([, a], [, l]) => a.length - l.length);
529
+ const m = Object.entries(i).sort(([a], [l]) => a.toLowerCase().localeCompare(l.toLowerCase())).sort(([, a], [, l]) => a.length - l.length);
528
530
  for (const [a, l] of m) {
529
531
  const p = l.length > 1;
530
532
  p && console.log(o`{yellow ${a}}:`);
531
533
  const h = l.sort((d, g) => d.command.toLowerCase().localeCompare(g.command.toLowerCase()));
532
534
  for (const d of h) {
533
- let g = C(i - d.command.length);
535
+ let g = C(r - d.command.length);
534
536
  p && (g = g.slice(2)), console.log(o`${p ? " " : ""}{green ${d.command}} ${g} ${d.description}`);
535
537
  }
536
538
  }
@@ -556,7 +558,7 @@ class M extends c {
556
558
  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}`);
557
559
  }
558
560
  }
559
- class I {
561
+ class H {
560
562
  handle(t) {
561
563
  if (t instanceof c)
562
564
  return t.pretty(), -1;
@@ -575,7 +577,7 @@ class N {
575
577
  return k;
576
578
  }
577
579
  get ExceptionHandlerClass() {
578
- return I;
580
+ return H;
579
581
  }
580
582
  constructor(t = {}) {
581
583
  this.ctx = t.ctx, this.commandRegistry = new this.CommandRegistryClass(), this.exceptionHandler = new this.ExceptionHandlerClass(), this.helpCommand = new this.HelpCommandClass({
@@ -0,0 +1,29 @@
1
+ const s = "bob-core", t = "1.3.3", e = "BOB Core", i = "module", r = ["/dist"], n = { ".": { import: "./dist/esm/bob-core.js", require: "./dist/cjs/bob-core.cjs" } }, o = { "*": { "*": ["./dist/types/*.d.ts"] } }, c = { start: "node -r @swc-node/register debug/main.ts", build: "rimraf ./dist && vite build", prepare: "npm run build", test: "vitest run" }, p = "Léo Hubert", d = "ISC", m = { "@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" }, u = {
2
+ name: s,
3
+ version: t,
4
+ description: e,
5
+ type: i,
6
+ files: r,
7
+ exports: n,
8
+ typesVersions: o,
9
+ scripts: c,
10
+ author: p,
11
+ license: d,
12
+ devDependencies: m,
13
+ dependencies: a
14
+ };
15
+ export {
16
+ p as author,
17
+ u as default,
18
+ a as dependencies,
19
+ e as description,
20
+ m as devDependencies,
21
+ n as exports,
22
+ r as files,
23
+ d as license,
24
+ s as name,
25
+ c as scripts,
26
+ i as type,
27
+ o as typesVersions,
28
+ t as version
29
+ };
@@ -16,6 +16,7 @@ export declare abstract class Command<C = any> {
16
16
  protected parser: CommandParser;
17
17
  protected io: CommandIO;
18
18
  protected abstract handle(): Promise<void | number>;
19
+ protected preHandle?(): Promise<void | number>;
19
20
  protected get CommandParserClass(): typeof CommandParser;
20
21
  protected get CommandIOClass(): typeof CommandIO;
21
22
  protected defaultOptions(): CommandOption<Command<C>>[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bob-core",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "BOB Core",
5
5
  "type": "module",
6
6
  "files": [
@@ -8,9 +8,15 @@
8
8
  ],
9
9
  "exports": {
10
10
  ".": {
11
- "types": "./dist/types/src/index.d.ts",
12
- "import": "./dist/bob-core.js",
13
- "require": "./dist/bob-core.cjs"
11
+ "import": "./dist/esm/bob-core.js",
12
+ "require": "./dist/cjs/bob-core.cjs"
13
+ }
14
+ },
15
+ "typesVersions": {
16
+ "*": {
17
+ "*": [
18
+ "./dist/types/*.d.ts"
19
+ ]
14
20
  }
15
21
  },
16
22
  "scripts": {
@@ -1,27 +0,0 @@
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
- name: t,
3
- version: s,
4
- description: e,
5
- type: i,
6
- files: r,
7
- exports: n,
8
- scripts: o,
9
- author: c,
10
- license: p,
11
- devDependencies: d,
12
- dependencies: m
13
- };
14
- export {
15
- c as author,
16
- a as default,
17
- m as dependencies,
18
- e as description,
19
- d as devDependencies,
20
- n as exports,
21
- r as files,
22
- p as license,
23
- t as name,
24
- o as scripts,
25
- i as type,
26
- s as version
27
- };
@@ -1 +0,0 @@
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;