bob-core 1.3.4 → 1.3.6

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.
Files changed (52) hide show
  1. package/dist/cjs/bob-core.js +1 -1
  2. package/dist/cjs/package-CH7KBlFr.cjs +1 -0
  3. package/dist/esm/bob-core.js +1 -1
  4. package/dist/esm/package-War71qwn.js +29 -0
  5. package/dist/esm/src/Cli.d.ts +26 -0
  6. package/dist/esm/src/Command.d.ts +45 -0
  7. package/dist/esm/src/CommandIO.d.ts +35 -0
  8. package/dist/esm/src/CommandParser.d.ts +48 -0
  9. package/dist/esm/src/CommandRegistry.d.ts +20 -0
  10. package/dist/esm/src/ExceptionHandler.d.ts +4 -0
  11. package/dist/esm/src/commands/HelpCommand.d.ts +14 -0
  12. package/dist/esm/src/contracts/CommandOption.d.ts +7 -0
  13. package/dist/esm/src/contracts/index.d.ts +1 -0
  14. package/dist/esm/src/errors/BadCommandOption.d.ts +11 -0
  15. package/dist/esm/src/errors/BadCommandParameter.d.ts +11 -0
  16. package/dist/esm/src/errors/BobError.d.ts +3 -0
  17. package/dist/esm/src/errors/CommandNotFoundError.d.ts +6 -0
  18. package/dist/esm/src/errors/InvalidOption.d.ts +8 -0
  19. package/dist/esm/src/errors/MissingRequiredArgumentValue.d.ts +7 -0
  20. package/dist/esm/src/errors/MissingSignatureArgument.d.ts +8 -0
  21. package/dist/esm/src/errors/MissingSignatureOption.d.ts +8 -0
  22. package/dist/esm/src/errors/index.d.ts +3 -0
  23. package/dist/esm/src/index.d.ts +6 -0
  24. package/dist/esm/src/lib/string.d.ts +1 -0
  25. package/dist/esm/src/options/HelpOption.d.ts +9 -0
  26. package/dist/esm/src/options/index.d.ts +1 -0
  27. package/package.json +2 -2
  28. package/dist/cjs/package-DhC03y1s.cjs +0 -1
  29. package/dist/esm/package-Bo2EHkpi.js +0 -29
  30. package/dist/types/package.json +0 -3
  31. /package/dist/{types → cjs}/src/Cli.d.ts +0 -0
  32. /package/dist/{types → cjs}/src/Command.d.ts +0 -0
  33. /package/dist/{types → cjs}/src/CommandIO.d.ts +0 -0
  34. /package/dist/{types → cjs}/src/CommandParser.d.ts +0 -0
  35. /package/dist/{types → cjs}/src/CommandRegistry.d.ts +0 -0
  36. /package/dist/{types → cjs}/src/ExceptionHandler.d.ts +0 -0
  37. /package/dist/{types → cjs}/src/commands/HelpCommand.d.ts +0 -0
  38. /package/dist/{types → cjs}/src/contracts/CommandOption.d.ts +0 -0
  39. /package/dist/{types → cjs}/src/contracts/index.d.ts +0 -0
  40. /package/dist/{types → cjs}/src/errors/BadCommandOption.d.ts +0 -0
  41. /package/dist/{types → cjs}/src/errors/BadCommandParameter.d.ts +0 -0
  42. /package/dist/{types → cjs}/src/errors/BobError.d.ts +0 -0
  43. /package/dist/{types → cjs}/src/errors/CommandNotFoundError.d.ts +0 -0
  44. /package/dist/{types → cjs}/src/errors/InvalidOption.d.ts +0 -0
  45. /package/dist/{types → cjs}/src/errors/MissingRequiredArgumentValue.d.ts +0 -0
  46. /package/dist/{types → cjs}/src/errors/MissingSignatureArgument.d.ts +0 -0
  47. /package/dist/{types → cjs}/src/errors/MissingSignatureOption.d.ts +0 -0
  48. /package/dist/{types → cjs}/src/errors/index.d.ts +0 -0
  49. /package/dist/{types → cjs}/src/index.d.ts +0 -0
  50. /package/dist/{types → cjs}/src/lib/string.d.ts +0 -0
  51. /package/dist/{types → cjs}/src/options/HelpOption.d.ts +0 -0
  52. /package/dist/{types → cjs}/src/options/index.d.ts +0 -0
@@ -1,6 +1,6 @@
1
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
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-DhC03y1s.cjs")))?.default?.version??"0.0.0";console.log(o`${t} {green ${n}} (core: {yellow ${s}})
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-CH7KBlFr.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]
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="bob-core",s="1.3.6",t="BOB Core",i="module",n=["/dist"],r={".":{import:"./dist/esm/bob-core.js",require:"./dist/cjs/bob-core.cjs"}},o={"*":{"*":["./dist/cjs/*.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;
@@ -513,7 +513,7 @@ class k extends E {
513
513
  signature = "help";
514
514
  description = "Show help";
515
515
  async handle() {
516
- const t = this.opts.commandRegistry.getCommands(), e = this.opts.cliName ?? "Bob CLI", n = this.opts.cliVersion ?? "0.0.0", s = (await import("./package-Bo2EHkpi.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-War71qwn.js"))?.default?.version ?? "0.0.0";
517
517
  console.log(o`${e} {green ${n}} (core: {yellow ${s}})
518
518
 
519
519
  {yellow Usage}:
@@ -0,0 +1,29 @@
1
+ const s = "bob-core", t = "1.3.6", e = "BOB Core", i = "module", r = ["/dist"], n = { ".": { import: "./dist/esm/bob-core.js", require: "./dist/cjs/bob-core.cjs" } }, o = { "*": { "*": ["./dist/cjs/*.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
+ };
@@ -0,0 +1,26 @@
1
+ import { CommandRegistry } from './CommandRegistry.js';
2
+ import { Command } from './Command.js';
3
+ import { default as HelpCommand } from './commands/HelpCommand.js';
4
+ import { ExceptionHandler } from './ExceptionHandler.js';
5
+ export type CliOptions<C> = {
6
+ ctx?: C;
7
+ name?: string;
8
+ version?: string;
9
+ };
10
+ export declare class Cli<C> {
11
+ readonly commandRegistry: CommandRegistry;
12
+ private readonly exceptionHandler;
13
+ private readonly ctx?;
14
+ private readonly helpCommand;
15
+ get CommandRegistryClass(): typeof CommandRegistry;
16
+ get HelpCommandClass(): typeof HelpCommand;
17
+ get ExceptionHandlerClass(): typeof ExceptionHandler;
18
+ constructor(opts?: CliOptions<C>);
19
+ setCommandResolver(resolver: (path: string) => Promise<Command<C>>): void;
20
+ withCommands(...commands: Array<Command<C> | {
21
+ new (): Command<C>;
22
+ } | string>): Promise<void>;
23
+ runCommand(command: string | Command, ...args: any[]): Promise<number>;
24
+ runHelpCommand(): Promise<number>;
25
+ protected registerCommand(command: Command<C>): void;
26
+ }
@@ -0,0 +1,45 @@
1
+ import { CommandParser } from './CommandParser.js';
2
+ import { CommandOption } from './contracts/index.js';
3
+ import { CommandIO } from './CommandIO.js';
4
+ export type CommandExample = {
5
+ description: string;
6
+ command: string;
7
+ };
8
+ export declare abstract class Command<C = any> {
9
+ abstract signature: string;
10
+ abstract description: string;
11
+ protected ctx: C;
12
+ protected helperDefinitions: {
13
+ [key: string]: string;
14
+ };
15
+ protected commandsExamples: CommandExample[];
16
+ protected parser: CommandParser;
17
+ protected io: CommandIO;
18
+ protected abstract handle(): Promise<void | number>;
19
+ protected preHandle?(): Promise<void | number>;
20
+ protected get CommandParserClass(): typeof CommandParser;
21
+ protected get CommandIOClass(): typeof CommandIO;
22
+ protected defaultOptions(): CommandOption<Command<C>>[];
23
+ get command(): string;
24
+ run(ctx: C, ...args: any[]): Promise<number>;
25
+ protected setOption(name: string, value: any): void;
26
+ protected setArgument(name: string, value: any): void;
27
+ protected option<T = string>(key: string): T | null;
28
+ protected option<T = string>(key: string, defaultValue: T): NoInfer<T>;
29
+ protected optionBoolean(key: string, defaultValue?: boolean): boolean;
30
+ protected optionArray<T = string>(key: string, defaultValue?: Array<T>): Array<NoInfer<T>>;
31
+ protected optionNumber(key: string): number | null;
32
+ protected optionNumber(key: string, defaultValue: number): number;
33
+ protected argument<T = string>(key: string): T | null;
34
+ protected argument<T = string>(key: string, defaultValue: T): NoInfer<T>;
35
+ protected argumentArray<T = string>(key: string, defaultValue?: Array<any>): Array<T>;
36
+ protected argumentBoolean(key: string, defaultValue?: boolean): boolean;
37
+ protected argumentNumber(key: string, defaultValue?: number | null): number | null;
38
+ /**
39
+ * Prompt utils
40
+ */
41
+ askForConfirmation(...opts: Parameters<typeof this.io.askForConfirmation>): ReturnType<typeof this.io.askForConfirmation>;
42
+ askForInput(...opts: Parameters<typeof this.io.askForInput>): ReturnType<typeof this.io.askForInput>;
43
+ askForSelect(...opts: Parameters<typeof this.io.askForSelect>): ReturnType<typeof this.io.askForSelect>;
44
+ newLoader(...opts: Parameters<typeof this.io.newLoader>): ReturnType<typeof this.io.newLoader>;
45
+ }
@@ -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
+ }
@@ -0,0 +1,48 @@
1
+ import { CommandOption } from './contracts/index.js';
2
+ import { CommandIO } from './CommandIO.js';
3
+ export type ArgSignature = {
4
+ name: string;
5
+ type: 'string' | 'boolean' | 'array';
6
+ optional?: boolean;
7
+ variadic?: boolean;
8
+ alias?: string[];
9
+ help?: string;
10
+ defaultValue: string | boolean | Array<string> | null;
11
+ isOption?: boolean;
12
+ };
13
+ export declare class CommandParser {
14
+ protected readonly io: CommandIO;
15
+ protected readonly signature: string;
16
+ protected readonly helperDefinitions: {
17
+ [key: string]: string;
18
+ };
19
+ protected readonly defaultCommandOptions: CommandOption<any>[];
20
+ command: string;
21
+ private arguments;
22
+ private options;
23
+ private argumentsSignature;
24
+ private optionSignatures;
25
+ private optionAliases;
26
+ constructor(io: CommandIO, signature: string, helperDefinitions: {
27
+ [key: string]: string;
28
+ }, defaultCommandOptions: CommandOption<any>[], ...args: any[]);
29
+ option(name: string): any;
30
+ setOption(name: string, value: any): void;
31
+ optionHelp(name: string): string | undefined;
32
+ argument(name: string): any;
33
+ setArgument(name: string, value: any): void;
34
+ argumentHelp(name: string): string | undefined;
35
+ getArgumentSignatures(): {
36
+ [argument: string]: ArgSignature;
37
+ };
38
+ getOptionSignatures(): {
39
+ [option: string]: ArgSignature;
40
+ };
41
+ private getParamValue;
42
+ private handleArguments;
43
+ private handleOptions;
44
+ private parseSignature;
45
+ private parseDefaultOptions;
46
+ private parseParamSignature;
47
+ validate(): Promise<void>;
48
+ }
@@ -0,0 +1,20 @@
1
+ import { Command } from './Command.js';
2
+ import { CommandIO } from './CommandIO.js';
3
+ export type CommandResolver = (path: string) => Promise<Command>;
4
+ export declare class CommandRegistry {
5
+ private readonly commands;
6
+ protected readonly io: CommandIO;
7
+ get commandSuffix(): string;
8
+ protected get CommandIOClass(): typeof CommandIO;
9
+ constructor();
10
+ getAvailableCommands(): string[];
11
+ getCommands(): Command[];
12
+ private commandResolver;
13
+ setCommandResolver(resolver: (path: string) => Promise<Command>): void;
14
+ registerCommand(command: Command, force?: boolean): void;
15
+ loadCommandsPath(commandsPath: string): Promise<void>;
16
+ runCommand(ctx: any, command: string | Command, ...args: any[]): Promise<number>;
17
+ private suggestCommand;
18
+ private askRunSimilarCommand;
19
+ private listCommandsFiles;
20
+ }
@@ -0,0 +1,4 @@
1
+ import { BobError } from './errors/index.js';
2
+ export declare class ExceptionHandler {
3
+ handle(err: Error | BobError): number;
4
+ }
@@ -0,0 +1,14 @@
1
+ import { Command } from '../Command.js';
2
+ import { CommandRegistry } from '../CommandRegistry.js';
3
+ export type HelpCommandOptions = {
4
+ commandRegistry: CommandRegistry;
5
+ cliName?: string;
6
+ cliVersion?: string;
7
+ };
8
+ export default class HelpCommand extends Command {
9
+ private opts;
10
+ signature: string;
11
+ description: string;
12
+ constructor(opts: HelpCommandOptions);
13
+ protected handle(): Promise<void>;
14
+ }
@@ -0,0 +1,7 @@
1
+ export interface CommandOption<C> {
2
+ option: string;
3
+ alias?: string[];
4
+ defaultValue: string | boolean | Array<string> | null;
5
+ description?: string;
6
+ handler(this: C): Promise<number | void>;
7
+ }
@@ -0,0 +1 @@
1
+ export * from './CommandOption.js';
@@ -0,0 +1,11 @@
1
+ import { BobError } from './BobError.js';
2
+ export type OptionProps = {
3
+ option: string;
4
+ value?: string;
5
+ reason?: string;
6
+ };
7
+ export declare class BadCommandOption extends BobError {
8
+ readonly param: OptionProps;
9
+ constructor(param: OptionProps);
10
+ pretty(): void;
11
+ }
@@ -0,0 +1,11 @@
1
+ import { BobError } from './BobError.js';
2
+ export type ParameterProps = {
3
+ param: string;
4
+ value?: string;
5
+ reason?: string;
6
+ };
7
+ export declare class BadCommandParameter extends BobError {
8
+ readonly param: ParameterProps;
9
+ constructor(param: ParameterProps);
10
+ pretty(): void;
11
+ }
@@ -0,0 +1,3 @@
1
+ export declare abstract class BobError extends Error {
2
+ abstract pretty(): void;
3
+ }
@@ -0,0 +1,6 @@
1
+ import { BobError } from './BobError.js';
2
+ export declare class CommandNotFoundError extends BobError {
3
+ readonly command: string;
4
+ constructor(command: string);
5
+ pretty(): void;
6
+ }
@@ -0,0 +1,8 @@
1
+ import { BobError } from './BobError.js';
2
+ import { ArgSignature } from '../CommandParser.js';
3
+ export declare class InvalidOption extends BobError {
4
+ private option;
5
+ private optionsSignature;
6
+ constructor(option: string, optionsSignature: ArgSignature[]);
7
+ pretty(): void;
8
+ }
@@ -0,0 +1,7 @@
1
+ import { BobError } from './BobError.js';
2
+ import { ArgSignature } from '../CommandParser.js';
3
+ export declare class MissingRequiredArgumentValue extends BobError {
4
+ readonly paramSignature: ArgSignature;
5
+ constructor(paramSignature: ArgSignature);
6
+ pretty(): void;
7
+ }
@@ -0,0 +1,8 @@
1
+ import { BobError } from './BobError.js';
2
+ import { ArgSignature } from '../CommandParser.js';
3
+ export declare class MissingSignatureArgument extends BobError {
4
+ private argument;
5
+ private argumentSignatures;
6
+ constructor(argument: string, argumentSignatures: ArgSignature[]);
7
+ pretty(): void;
8
+ }
@@ -0,0 +1,8 @@
1
+ import { BobError } from './BobError.js';
2
+ import { ArgSignature } from '../CommandParser.js';
3
+ export declare class MissingSignatureOption extends BobError {
4
+ private option;
5
+ private optionsSignature;
6
+ constructor(option: string, optionsSignature: ArgSignature[]);
7
+ pretty(): void;
8
+ }
@@ -0,0 +1,3 @@
1
+ export * from './BobError.js';
2
+ export * from './BadCommandParameter.js';
3
+ export * from './BadCommandOption.js';
@@ -0,0 +1,6 @@
1
+ export * from './Command.js';
2
+ export * from './CommandIO.js';
3
+ export * from './Cli.js';
4
+ export * from './errors/index.js';
5
+ export * from './contracts/index.js';
6
+ export * from './options/index.js';
@@ -0,0 +1 @@
1
+ export declare function generateSpace(nb: number): string;
@@ -0,0 +1,9 @@
1
+ import { Command } from '../Command.js';
2
+ import { CommandOption } from '../contracts/index.js';
3
+ export declare class HelpOption implements CommandOption<Command> {
4
+ option: string;
5
+ alias: string[];
6
+ defaultValue: boolean;
7
+ description: string;
8
+ handler(this: Command): Promise<number | void>;
9
+ }
@@ -0,0 +1 @@
1
+ export * from './HelpOption.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bob-core",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "description": "BOB Core",
5
5
  "type": "module",
6
6
  "files": [
@@ -15,7 +15,7 @@
15
15
  "typesVersions": {
16
16
  "*": {
17
17
  "*": [
18
- "./dist/types/*.d.ts"
18
+ "./dist/cjs/*.d.ts"
19
19
  ]
20
20
  }
21
21
  },
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="bob-core",s="1.3.4",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;
@@ -1,29 +0,0 @@
1
- const s = "bob-core", t = "1.3.4", 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
- };
@@ -1,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes