bob-core 2.0.0 → 2.0.2

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 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="bob-core",t="2.0.0",s="BOB Core",i="module",n="./dist/cjs/src/index.js",r="./dist/esm/src/index.js",c="./dist/esm/src/index.d.ts",o=["dist"],d={".":{import:{types:"./dist/esm/src/index.d.ts",default:"./dist/esm/src/index.js"},require:{types:"./dist/cjs/src/index.d.ts",default:"./dist/cjs/src/index.js"}}},p={start:"node -r @swc-node/register debug/main.ts",build:"rimraf ./dist && vite build",typecheck:"tsc --noEmit",prepack:"npm run build",test:"vitest run",lint:"eslint .","lint:fix":"eslint . --fix"},l="Léo Hubert",m="ISC",a={"@eslint/js":"^9.37.0","@faker-js/faker":"^10.0.0","@swc-node/register":"^1.11.1","@trivago/prettier-plugin-sort-imports":"^5.2.2","@types/minimist":"^1.2.5","@types/node":"^20.14.5","@types/prompts":"^2.4.9","@types/string-similarity":"^4.0.2","@vitest/coverage-v8":"^3.2.4",eslint:"^9.37.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4",prettier:"^3.6.2",rimraf:"^6.0.1",tsx:"^4.20.6",typescript:"^5.9.3","typescript-eslint":"^8.46.0",vite:"^7.2.7","vite-plugin-dts":"^4.5.4",vitest:"^3.2.4"},u={chalk:"^4.1.2",minimist:"^1.2.8",prompts:"^2.4.2"},y={name:e,version:t,description:s,type:i,main:n,module:r,types:c,files:o,exports:d,scripts:p,author:l,license:m,devDependencies:a,dependencies:u};exports.author=l;exports.default=y;exports.dependencies=u;exports.description=s;exports.devDependencies=a;exports.exports=d;exports.files=o;exports.license=m;exports.main=n;exports.module=r;exports.name=e;exports.scripts=p;exports.type=i;exports.types=c;exports.version=t;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="bob-core",t="2.0.2",s="BOB Core",i="module",n="./dist/cjs/src/index.js",r="./dist/esm/src/index.js",c="./dist/esm/src/index.d.ts",o=["dist"],d={".":{import:{types:"./dist/esm/src/index.d.ts",default:"./dist/esm/src/index.js"},require:{types:"./dist/cjs/src/index.d.ts",default:"./dist/cjs/src/index.js"}}},p={start:"node -r @swc-node/register debug/main.ts",build:"rimraf ./dist && vite build",typecheck:"tsc --noEmit",prepack:"npm run build",test:"vitest run",lint:"eslint .","lint:fix":"eslint . --fix"},l="Léo Hubert",m="ISC",a={"@eslint/js":"^9.37.0","@faker-js/faker":"^10.0.0","@swc-node/register":"^1.11.1","@trivago/prettier-plugin-sort-imports":"^5.2.2","@types/minimist":"^1.2.5","@types/node":"^20.14.5","@types/prompts":"^2.4.9","@types/string-similarity":"^4.0.2","@vitest/coverage-v8":"^3.2.4",eslint:"^9.37.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4",prettier:"^3.6.2",rimraf:"^6.0.1",tsx:"^4.20.6",typescript:"^5.9.3","typescript-eslint":"^8.46.0",vite:"^7.2.7","vite-plugin-dts":"^4.5.4",vitest:"^3.2.4"},u={chalk:"^4.1.2",minimist:"^1.2.8",prompts:"^2.4.2"},y={name:e,version:t,description:s,type:i,main:n,module:r,types:c,files:o,exports:d,scripts:p,author:l,license:m,devDependencies:a,dependencies:u};exports.author=l;exports.default=y;exports.dependencies=u;exports.description=s;exports.devDependencies=a;exports.exports=d;exports.files=o;exports.license=m;exports.main=n;exports.module=r;exports.name=e;exports.scripts=p;exports.type=i;exports.types=c;exports.version=t;
@@ -22,6 +22,7 @@ export type CommandExample = {
22
22
  command: string;
23
23
  };
24
24
  export declare class Command<C extends ContextDefinition = ContextDefinition, Options extends OptionsSchema = OptionsSchema, Arguments extends ArgumentsSchema = ArgumentsSchema> {
25
+ $type: "BobCommand";
25
26
  readonly _command: string;
26
27
  readonly description: string;
27
28
  readonly group?: string;
@@ -1,7 +1,6 @@
1
1
  import { Logger } from './Logger.js';
2
- import { BobError } from './errors/index.js';
3
2
  export declare class ExceptionHandler {
4
3
  private readonly logger;
5
4
  constructor(logger: Logger);
6
- handle(err: Error | BobError): number;
5
+ handle(err: Error): number;
7
6
  }
@@ -1,4 +1,5 @@
1
1
  import { Logger } from '../Logger.js';
2
2
  export declare abstract class BobError extends Error {
3
+ $type: "BobError";
3
4
  abstract pretty(logger: Logger): void;
4
5
  }
@@ -1,17 +1,17 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("prompts"),a=require("chalk"),M=require("minimist"),j=require("node:fs"),F=require("node:path");class R{logger;constructor(t){this.logger=t.logger}log(...t){this.logger.log(...t)}info(...t){this.logger.info(...t)}warn(...t){this.logger.warn(...t)}error(...t){this.logger.error(...t)}debug(...t){this.logger.debug(...t)}async askForConfirmation(t="Do you want to continue?",e){return(await y({type:"confirm",name:"value",message:t,initial:e??!1})).value}async askForInput(t,e,i){return(await y({type:"text",name:"value",message:t,initial:e,...i}))?.value??null}async askForDate(t,e,i){return(await y({type:"date",name:"value",message:t,initial:e,...i}))?.value??null}async askForList(t,e,i){return(await y({type:"list",name:"value",message:t,initial:e,...i}))?.value??null}async askForToggle(t,e,i){return(await y({type:"toggle",name:"value",message:t,initial:e,...i}))?.value??null}async askForSelect(t,e,i){if(e.length===0)throw new Error("No options provided");const n=[];for(const o of e)typeof o=="string"?n.push({title:o,value:o}):n.push(o);return(await y({type:"select",name:"value",message:t,choices:n,...i}))?.value??null}newLoader(t="",e=["⠙","⠘","⠰","⠴","⠤","⠦","⠆","⠃","⠋","⠉"],i=100){let n=t,r=null,o=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"+e[o++]+" "+n)),o=o%e.length},i),m=()=>{clearInterval(u),process.stdout.write(new TextEncoder().encode("\r"+" ".repeat(n.length+5)+"\r"))};return{[Symbol.dispose]:m,[Symbol.asyncDispose]:m,updateText:h=>{r=n,n=h},stop:m}}}class f extends Error{}function q(s){if(s==="string"||s==="number")return null;if(s==="boolean")return!1;if(Array.isArray(s)&&s.length===1){if(s[0]==="string")return[];if(s[0]==="number")return[]}throw new Error("Invalid option type: "+s)}function k(s){return typeof s=="string"||Array.isArray(s)?q(s):s.default!==void 0?s.default:q(s.type)}function g(s){return typeof s=="string"||Array.isArray(s)?{alias:[],default:k(s),description:"",required:!1,secret:!1,type:s,variadic:!1}:{alias:s.alias?Array.isArray(s.alias)?s.alias:[s.alias]:[],default:s.default??k(s.type),description:s.description??"",required:s.required??!1,secret:s.secret??!1,type:s.type,variadic:s.variadic??!1}}class b extends f{constructor(t,e={}){super(`Invalid option ${t} in not recognized`),this.option=t,this.optionsSchema=e}pretty(t){const e=Object.entries(this.optionsSchema);if(e.length>0){t.log(`
2
- ${a.yellow("Available options")}:`);for(const[i,n]of e){const r=g(n),o=r.alias?typeof r.alias=="string"?[r.alias]:r.alias:[],u=Array.isArray(r.type)?`[${r.type[0]}]`:r.type,m=`--${i}${o.length>0?o.map(l=>`, -${l}`).join(""):""}`,h=" ".repeat(30-m.length);t.log(` ${a.green(m)} ${h} ${r.description||"\b"} ${a.white(`(${u})`)}`)}t.log("")}t.log(`${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.option)} is not recognized.`)}}class A extends f{constructor(t){super(`Argument "${t}" is required.`),this.argument=t}pretty(t){t.log(`${a.white.bgRed(" ERROR ")} Argument ${a.bold.yellow(this.argument)} is required.`)}}class N extends f{constructor(t){super(`Argument "${t}" is required.`),this.option=t}pretty(t){t.log(`${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.option)} is required.`)}}class W extends f{constructor(t){let e=`Argument "${t.param}" value is invalid.`;t.reason?e+=` Reason: ${t.reason}`:e+=` Value: "${t.value}"`,super(e),this.param=t}pretty(t){t.log(` ${a.white.bgRed(" ERROR ")} Argument ${a.bold.yellow(this.param.param)} value is invalid. `),(this.param.value||this.param.reason)&&t.log(""),this.param.value&&t.log(` ${a.blue("Value")}: ${this.param.value}`),this.param.reason&&t.log(` ${a.yellow("Reason")}: ${this.param.reason}`)}}class C extends f{constructor(t){let e=`Option "${t.option}" value is invalid.`;t.reason?e+=` Reason: ${t.reason}`:e+=` Value: "${t.value}"`,super(e),this.param=t}pretty(t){t.log(` ${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.param.option)} value is invalid. `),(this.param.value||this.param.reason)&&t.log(""),this.param.value&&t.log(` ${a.blue("Value")}: ${this.param.value}`),this.param.reason&&t.log(` ${a.yellow("Reason")}: ${this.param.reason}`)}}class P extends f{constructor(t){super(`Command "${t}" not found.`),this.command=t}pretty(t){t.log(`${a.bgRed(" ERROR ")} Command ${a.yellow(this.command)} not found.`)}}function w(s,t,e,i){if(s==null)return i??null;if(t==="string")return String(s);if(t==="number"){const n=Number(s);if(isNaN(n))throw new C({option:e,reason:`Expected a number, got "${s}"`});return n}if(t==="boolean")return typeof s=="boolean"?s:s==="true"||s==="1"?!0:s==="false"||s==="0"?!1:!!s;if(Array.isArray(t)){const n=t[0],r=Array.isArray(s)?s:[s];if(n==="string")return r.map(o=>String(o));if(n==="number")return r.map(o=>{const u=Number(o);if(isNaN(u))throw new C({option:e,reason:`Expected array of numbers, got "${o}" in array`});return u})}return s}class x{options;parsedOptions=null;arguments;parsedArguments=null;io;shouldPromptForMissingOptions=!0;constructor(t){this.options=t.options,this.arguments=t.arguments,this.io=t.io}init(t){const{_:e,...i}=M(t);return this.validateUnknownOptions(i),this.parsedOptions=this.handleOptions(i),this.parsedArguments=this.handleArguments(e),{options:this.parsedOptions,arguments:this.parsedArguments}}async validate(){for(const t in this.options)if(g(this.options[t]).required&&(this.parsedOptions?.[t]===void 0||this.parsedOptions?.[t]===null))throw new N(t);for(const t in this.arguments){const e=g(this.arguments[t]),i=this.parsedArguments?.[t];if(e.required&&i==null){if(this.shouldPromptForMissingOptions){const n=await this.promptForArgument(t,e);if(n&&this.parsedArguments){this.parsedArguments[t]=w(n,e.type,t);continue}}throw new A(t)}if(e.required&&e.variadic&&Array.isArray(i)&&i.length===0){if(this.shouldPromptForMissingOptions){const n=await this.promptForArgument(t,e);if(n&&this.parsedArguments){this.parsedArguments[t]=w(n,e.type,t);continue}}throw new A(t)}}}option(t,e){if(!this.parsedOptions)throw new Error("Options have not been parsed yet. Call init() first.");return this.isEmptyValue(this.parsedOptions[t])&&e!==void 0?e:this.parsedOptions[t]}setOption(t,e){if(!this.parsedOptions)throw new Error("Options have not been parsed yet. Call init() first.");if(!(t in this.options))throw new b(t,this.options);this.parsedOptions[t]=e}argument(t,e){if(!this.parsedArguments)throw new Error("Arguments have not been parsed yet. Call init() first.");return this.isEmptyValue(this.parsedArguments[t])&&e!==void 0?e:this.parsedArguments[t]}setArgument(t,e){if(!this.parsedArguments)throw new Error("Arguments have not been parsed yet. Call init() first.");if(!(t in this.arguments))throw new b(t,this.arguments);this.parsedArguments[t]=e}isEmptyValue(t){return t==null||Array.isArray(t)&&t.length===0}validateUnknownOptions(t){const e=new Set;for(const i in this.options){e.add(i);const n=g(this.options[i]);for(const r of n.alias)e.add(r)}for(const i in t)if(!e.has(i))throw new b(i,this.options)}handleOptions(t){const e={};for(const i in this.options){const n=g(this.options[i]);e[i]=this.resolveOptionValue(i,n,t)}return e}handleArguments(t){const e={},i=[...t];for(const n in this.arguments){const r=g(this.arguments[n]);if(r.variadic){e[n]=this.handleVariadicArgument(n,r,i);continue}e[n]=this.resolveArgumentValue(n,r,i.shift())}return e}handleVariadicArgument(t,e,i){return i.length?w(i,e.type,t,e.default):e.default}resolveArgumentValue(t,e,i){return i===void 0?e.default:w(i,e.type,t,e.default)}resolveOptionValue(t,e,i){let n;const r=[t,...e.alias];for(const o of r)if(o in i){n=i[o];break}if(n===void 0){if(e.required)throw new C({option:t,reason:"Required option is missing"});return e.default}return w(n,e.type,t,e.default)}optionDefinitions(){const t={};for(const e in this.options)t[e]=g(this.options[e]);return t}argumentDefinitions(){const t={};for(const e in this.arguments)t[e]=g(this.arguments[e]);return t}availableOptions(){return Object.keys(this.options)}availableArguments(){return Object.keys(this.arguments)}disablePrompting(){return this.shouldPromptForMissingOptions=!1,this}async promptForArgument(t,e){if(!Array.isArray(e.type)&&!["string","number","secret"].includes(e.type))return null;let i=`${a.yellow.bold(t)} is required`;return e.description&&(i+=`: ${a.gray(`(${e.description})`)}`),i+=` ${a.green(`(${e.type}${e.variadic==!0?"[]":""})`)}
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("prompts"),a=require("chalk"),M=require("minimist"),W=require("node:fs"),F=require("node:path");class R{logger;constructor(t){this.logger=t.logger}log(...t){this.logger.log(...t)}info(...t){this.logger.info(...t)}warn(...t){this.logger.warn(...t)}error(...t){this.logger.error(...t)}debug(...t){this.logger.debug(...t)}async askForConfirmation(t="Do you want to continue?",e){return(await y({type:"confirm",name:"value",message:t,initial:e??!1})).value}async askForInput(t,e,i){return(await y({type:"text",name:"value",message:t,initial:e,...i}))?.value??null}async askForDate(t,e,i){return(await y({type:"date",name:"value",message:t,initial:e,...i}))?.value??null}async askForList(t,e,i){return(await y({type:"list",name:"value",message:t,initial:e,...i}))?.value??null}async askForToggle(t,e,i){return(await y({type:"toggle",name:"value",message:t,initial:e,...i}))?.value??null}async askForSelect(t,e,i){if(e.length===0)throw new Error("No options provided");const n=[];for(const o of e)typeof o=="string"?n.push({title:o,value:o}):n.push(o);return(await y({type:"select",name:"value",message:t,choices:n,...i}))?.value??null}newLoader(t="",e=["⠙","⠘","⠰","⠴","⠤","⠦","⠆","⠃","⠋","⠉"],i=100){let n=t,r=null,o=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"+e[o++]+" "+n)),o=o%e.length},i),m=()=>{clearInterval(u),process.stdout.write(new TextEncoder().encode("\r"+" ".repeat(n.length+5)+"\r"))};return{[Symbol.dispose]:m,[Symbol.asyncDispose]:m,updateText:h=>{r=n,n=h},stop:m}}}class f extends Error{$type="BobError"}function q(s){if(s==="string"||s==="number")return null;if(s==="boolean")return!1;if(Array.isArray(s)&&s.length===1){if(s[0]==="string")return[];if(s[0]==="number")return[]}throw new Error("Invalid option type: "+s)}function k(s){return typeof s=="string"||Array.isArray(s)?q(s):s.default!==void 0?s.default:q(s.type)}function g(s){return typeof s=="string"||Array.isArray(s)?{alias:[],default:k(s),description:"",required:!1,secret:!1,type:s,variadic:!1}:{alias:s.alias?Array.isArray(s.alias)?s.alias:[s.alias]:[],default:s.default??k(s.type),description:s.description??"",required:s.required??!1,secret:s.secret??!1,type:s.type,variadic:s.variadic??!1}}class $ extends f{constructor(t,e={}){super(`Invalid option ${t} in not recognized`),this.option=t,this.optionsSchema=e}pretty(t){const e=Object.entries(this.optionsSchema);if(e.length>0){t.log(`
2
+ ${a.yellow("Available options")}:`);for(const[i,n]of e){const r=g(n),o=r.alias?typeof r.alias=="string"?[r.alias]:r.alias:[],u=Array.isArray(r.type)?`[${r.type[0]}]`:r.type,m=`--${i}${o.length>0?o.map(l=>`, -${l}`).join(""):""}`,h=" ".repeat(30-m.length);t.log(` ${a.green(m)} ${h} ${r.description||"\b"} ${a.white(`(${u})`)}`)}t.log("")}t.log(`${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.option)} is not recognized.`)}}class A extends f{constructor(t){super(`Argument "${t}" is required.`),this.argument=t}pretty(t){t.log(`${a.white.bgRed(" ERROR ")} Argument ${a.bold.yellow(this.argument)} is required.`)}}class P extends f{constructor(t){super(`Argument "${t}" is required.`),this.option=t}pretty(t){t.log(`${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.option)} is required.`)}}class j extends f{constructor(t){let e=`Argument "${t.param}" value is invalid.`;t.reason?e+=` Reason: ${t.reason}`:e+=` Value: "${t.value}"`,super(e),this.param=t}pretty(t){t.log(` ${a.white.bgRed(" ERROR ")} Argument ${a.bold.yellow(this.param.param)} value is invalid. `),(this.param.value||this.param.reason)&&t.log(""),this.param.value&&t.log(` ${a.blue("Value")}: ${this.param.value}`),this.param.reason&&t.log(` ${a.yellow("Reason")}: ${this.param.reason}`)}}class b extends f{constructor(t){let e=`Option "${t.option}" value is invalid.`;t.reason?e+=` Reason: ${t.reason}`:e+=` Value: "${t.value}"`,super(e),this.param=t}pretty(t){t.log(` ${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.param.option)} value is invalid. `),(this.param.value||this.param.reason)&&t.log(""),this.param.value&&t.log(` ${a.blue("Value")}: ${this.param.value}`),this.param.reason&&t.log(` ${a.yellow("Reason")}: ${this.param.reason}`)}}class L extends f{constructor(t){super(`Command "${t}" not found.`),this.command=t}pretty(t){t.log(`${a.bgRed(" ERROR ")} Command ${a.yellow(this.command)} not found.`)}}function w(s,t,e,i){if(s==null)return i??null;if(t==="string")return String(s);if(t==="number"){const n=Number(s);if(isNaN(n))throw new b({option:e,reason:`Expected a number, got "${s}"`});return n}if(t==="boolean")return typeof s=="boolean"?s:s==="true"||s==="1"?!0:s==="false"||s==="0"?!1:!!s;if(Array.isArray(t)){const n=t[0],r=Array.isArray(s)?s:[s];if(n==="string")return r.map(o=>String(o));if(n==="number")return r.map(o=>{const u=Number(o);if(isNaN(u))throw new b({option:e,reason:`Expected array of numbers, got "${o}" in array`});return u})}return s}class x{options;parsedOptions=null;arguments;parsedArguments=null;io;shouldPromptForMissingOptions=!0;constructor(t){this.options=t.options,this.arguments=t.arguments,this.io=t.io}init(t){const{_:e,...i}=M(t);return this.validateUnknownOptions(i),this.parsedOptions=this.handleOptions(i),this.parsedArguments=this.handleArguments(e),{options:this.parsedOptions,arguments:this.parsedArguments}}async validate(){for(const t in this.options)if(g(this.options[t]).required&&(this.parsedOptions?.[t]===void 0||this.parsedOptions?.[t]===null))throw new P(t);for(const t in this.arguments){const e=g(this.arguments[t]),i=this.parsedArguments?.[t];if(e.required&&i==null){if(this.shouldPromptForMissingOptions){const n=await this.promptForArgument(t,e);if(n&&this.parsedArguments){this.parsedArguments[t]=w(n,e.type,t);continue}}throw new A(t)}if(e.required&&e.variadic&&Array.isArray(i)&&i.length===0){if(this.shouldPromptForMissingOptions){const n=await this.promptForArgument(t,e);if(n&&this.parsedArguments){this.parsedArguments[t]=w(n,e.type,t);continue}}throw new A(t)}}}option(t,e){if(!this.parsedOptions)throw new Error("Options have not been parsed yet. Call init() first.");return this.isEmptyValue(this.parsedOptions[t])&&e!==void 0?e:this.parsedOptions[t]}setOption(t,e){if(!this.parsedOptions)throw new Error("Options have not been parsed yet. Call init() first.");if(!(t in this.options))throw new $(t,this.options);this.parsedOptions[t]=e}argument(t,e){if(!this.parsedArguments)throw new Error("Arguments have not been parsed yet. Call init() first.");return this.isEmptyValue(this.parsedArguments[t])&&e!==void 0?e:this.parsedArguments[t]}setArgument(t,e){if(!this.parsedArguments)throw new Error("Arguments have not been parsed yet. Call init() first.");if(!(t in this.arguments))throw new $(t,this.arguments);this.parsedArguments[t]=e}isEmptyValue(t){return t==null||Array.isArray(t)&&t.length===0}validateUnknownOptions(t){const e=new Set;for(const i in this.options){e.add(i);const n=g(this.options[i]);for(const r of n.alias)e.add(r)}for(const i in t)if(!e.has(i))throw new $(i,this.options)}handleOptions(t){const e={};for(const i in this.options){const n=g(this.options[i]);e[i]=this.resolveOptionValue(i,n,t)}return e}handleArguments(t){const e={},i=[...t];for(const n in this.arguments){const r=g(this.arguments[n]);if(r.variadic){e[n]=this.handleVariadicArgument(n,r,i);continue}e[n]=this.resolveArgumentValue(n,r,i.shift())}return e}handleVariadicArgument(t,e,i){return i.length?w(i,e.type,t,e.default):e.default}resolveArgumentValue(t,e,i){return i===void 0?e.default:w(i,e.type,t,e.default)}resolveOptionValue(t,e,i){let n;const r=[t,...e.alias];for(const o of r)if(o in i){n=i[o];break}if(n===void 0){if(e.required)throw new b({option:t,reason:"Required option is missing"});return e.default}return w(n,e.type,t,e.default)}optionDefinitions(){const t={};for(const e in this.options)t[e]=g(this.options[e]);return t}argumentDefinitions(){const t={};for(const e in this.arguments)t[e]=g(this.arguments[e]);return t}availableOptions(){return Object.keys(this.options)}availableArguments(){return Object.keys(this.arguments)}disablePrompting(){return this.shouldPromptForMissingOptions=!1,this}async promptForArgument(t,e){if(!Array.isArray(e.type)&&!["string","number","secret"].includes(e.type))return null;let i=`${a.yellow.bold(t)} is required`;return e.description&&(i+=`: ${a.gray(`(${e.description})`)}`),i+=` ${a.green(`(${e.type}${e.variadic==!0?"[]":""})`)}
3
3
  `,Array.isArray(e.type)?(i+=`Please provide one or more values, separated by commas:
4
- `,await this.io.askForList(i,void 0,{separator:",",validate:n=>{if(!n.length)return"Please enter at least one value";if(e.type[0]==="number"){for(const r of n.split(","))if(isNaN(Number(r)))return"Please enter only valid numbers"}return!0}})):await this.io.askForInput(i,void 0,{type:e.type==="number"?"number":e.secret?"password":"text",validate:n=>{if(n==null||typeof n=="string"&&!n.length)return"This value is required";if(e.type==="number"){const r=Number(n);if(isNaN(r))return"Please enter a valid number"}else if(e.type==="string"&&(typeof n!="string"||!n.length))return"Please enter a valid text";return!0}})}}function O(s){return new Array(s+5).join(" ")}class L{type="boolean";option="help";alias=["h"];default=!1;description=`Display help for the given command. When no command is given display help for the ${a.green("list")} command`;async handler(){const t=this.parser.argumentDefinitions(),e=this.parser.optionDefinitions(),i=Object.entries(t),n=Object.entries(e),r=n.map(([l,d])=>{const c=Array.isArray(d.alias)?d.alias:d.alias?[d.alias]:[];return{name:l,...d,optionWithAlias:`--${l}${c.map(p=>`, -${p}`).join("")}`}}),o=i.filter(([,l])=>l.required);this.io.log(a.yellow("Description:")),this.io.log(` ${this.description}
4
+ `,await this.io.askForList(i,void 0,{separator:",",validate:n=>{if(!n.length)return"Please enter at least one value";if(e.type[0]==="number"){for(const r of n.split(","))if(isNaN(Number(r)))return"Please enter only valid numbers"}return!0}})):await this.io.askForInput(i,void 0,{type:e.type==="number"?"number":e.secret?"password":"text",validate:n=>{if(n==null||typeof n=="string"&&!n.length)return"This value is required";if(e.type==="number"){const r=Number(n);if(isNaN(r))return"Please enter a valid number"}else if(e.type==="string"&&(typeof n!="string"||!n.length))return"Please enter a valid text";return!0}})}}function O(s){return new Array(s+5).join(" ")}class I{type="boolean";option="help";alias=["h"];default=!1;description=`Display help for the given command. When no command is given display help for the ${a.green("list")} command`;async handler(){const t=this.parser.argumentDefinitions(),e=this.parser.optionDefinitions(),i=Object.entries(t),n=Object.entries(e),r=n.map(([l,d])=>{const c=Array.isArray(d.alias)?d.alias:d.alias?[d.alias]:[];return{name:l,...d,optionWithAlias:`--${l}${c.map(p=>`, -${p}`).join("")}`}}),o=i.filter(([,l])=>l.required);this.io.log(a.yellow("Description:")),this.io.log(` ${this.description}
5
5
  `),this.io.log(a.yellow("Usage:")),this.io.log(` ${this.command} ${o.length>0?o.map(([l])=>`<${l}>`).join(" "):"\b"} [options]`);const u=Math.max(...r.map(l=>l.optionWithAlias.length),0),m=Math.max(...i.map(([l])=>l.length),0),h=m>u?m:u;if(i.length>0){this.io.log(`
6
6
  ${a.yellow("Arguments")}:`);for(const[l,d]of i){const c=O(h-l.length);let p=` ${a.green(l)} ${c} ${d.description??"\b"}`;if(d.default!==void 0&&!d.required){const D=(Array.isArray(d.type)?`[${d.type[0]}]`:d.type)==="array"||Array.isArray(d.type)?JSON.stringify(d.default):d.default;p+=` ${a.yellow(`[default: ${D}]`)}`}d.variadic&&(p+=` ${a.white("(variadic)")}`),this.io.log(p)}}if(n.length>0){this.io.log(`
7
- ${a.yellow("Options")}:`);for(const l of r){const d=O(h-l.optionWithAlias.length);let c=`${a.green(l.optionWithAlias)} ${d} ${l.description??"\b"}`;if(l.type){const p=Array.isArray(l.type)?`[${l.type[0]}]`:l.type;c+=` ${a.white(`(${p})`)}`}if(l.default!==void 0&&!l.required){const E=(Array.isArray(l.type)?`[${l.type[0]}]`:l.type)==="array"||Array.isArray(l.type)?JSON.stringify(l.default):l.default;c+=` ${a.yellow(`[default: ${E}]`)}`}this.io.log(c)}}if(this.commandsExamples.length>0){this.io.log(`
7
+ ${a.yellow("Options")}:`);for(const l of r){const d=O(h-l.optionWithAlias.length);let c=`${a.green(l.optionWithAlias)} ${d} ${l.description??"\b"}`;if(l.type){const p=Array.isArray(l.type)?`[${l.type[0]}]`:l.type;c+=` ${a.white(`(${p})`)}`}if(l.default!==void 0&&!l.required){const S=(Array.isArray(l.type)?`[${l.type[0]}]`:l.type)==="array"||Array.isArray(l.type)?JSON.stringify(l.default):l.default;c+=` ${a.yellow(`[default: ${S}]`)}`}this.io.log(c)}}if(this.commandsExamples.length>0){this.io.log(`
8
8
  ${a.yellow("Examples")}:`);let l=process.argv[0].split("/").pop();l==="node"&&(l+=" "+process.argv[1].split("/").pop());for(const[d,c]of this.commandsExamples.entries())d>0&&this.io.log(""),this.io.log(` ${c.description}
9
- `),this.io.log(` ${a.green(`${l} ${c.command}`)}`)}return-1}}class v{_command;description;group;commandsExamples=[];get command(){return this._command}ctx;io;parser;disablePromptingFlag=!1;_preHandler;_handler;tmp;defaultOptions(){return[new L]}newCommandParser(t){return new x({io:t.io,options:t.options,arguments:t.arguments})}newCommandIO(t){return new R(t)}constructor(t,e){this._command=t,this.description=e?.description??"",this.group=e?.group,this.tmp={options:e?.options??{},arguments:e?.arguments??{}};const i=this.defaultOptions();if(i.length>0)for(const n of i)this.tmp.options[n.option]=n}disablePrompting(){return this.disablePromptingFlag=!0,this}preHandler(t){return this._preHandler=t,this}handler(t){return this._handler=t,this}options(t){return this.tmp={options:{...this.tmp?.options??{},...t},arguments:this.tmp?.arguments??{}},this}arguments(t){return this.tmp={options:this.tmp?.options??{},arguments:{...this.tmp?.arguments??{},...t}},this}async run(t){if(!this._handler&&!this.handle)throw new Error(`No handler defined for command ${this.command||"(unknown)"}`);let e;if(this.ctx=t.ctx,this.io=this.newCommandIO({logger:t.logger}),t&&"args"in t){const n=this.tmp?.options??{};for(const r of this.defaultOptions())r.option in n||(n[r.option]=r);this.parser=this.newCommandParser({io:this.io,options:n,arguments:this.tmp?.arguments??{}}),e=this.parser.init(t.args);for(const r of this.defaultOptions())if(e.options[r.option]===!0){const o=await r.handler.call(this);if(o&&o!==0)return o}this.disablePromptingFlag&&this.parser.disablePrompting(),await this.parser.validate()}else e={options:t.options,arguments:t.arguments};if(!this._preHandler&&this.preHandle&&(this._preHandler=this.preHandle.bind(this)),this._preHandler){const n=await this._preHandler(t.ctx,e);if(n&&n!==0)return n}if(!this._handler&&this.handle)this._handler=this.handle.bind(this);else if(!this._handler)throw new Error(`No handler defined for command ${this.command||"(unknown)"}`);return await this._handler(t.ctx,e)??0}}class $ extends x{command;constructor(t){const e=$.parseSignature(t.signature,t.helperDefinitions,t.defaultOptions);super({io:t.io,options:e.options,arguments:e.arguments}),this.command=e.command}static parseSignature(t,e,i){const[n,...r]=t.split(/\{(.*?)\}/g).map(m=>m.trim()).filter(Boolean),o={},u={};for(const m of r){const{name:h,isOption:l,definition:d}=$.parseParamSignature(m,e);l?o[h]=d:u[h]=d}for(const m of i)o[m.option]={type:m.type,required:m.required,alias:m.alias,variadic:m.variadic??!1,description:m.description,default:m.default??null};return{command:n,options:o,arguments:u}}static parseParamSignature(t,e){let i=t,n=!1;const r={required:!0,type:"string",description:void 0,default:null,variadic:!1};if(i.includes(":")){const[o,u]=i.split(":");i=o.trim(),r.description=u.trim()}if(i.includes("=")){const[o,u]=i.split("=");i=o.trim(),r.default=u.trim(),r.required=!1,typeof r.default=="string"&&!r.default.length?r.default=null:r.default==="true"?(r.default=!0,r.type="boolean"):r.default==="false"&&(r.default=!1,r.type="boolean")}else i.startsWith("--")&&(r.required=!1,r.default=!1,r.type="boolean");if(i.includes("|")){const[o,...u]=i.split("|");i=o.trim(),r.alias=u.map(m=>m.trim())}return i.startsWith("--")&&(n=!0,i=i.slice(2)),r.default==="*"&&(r.default=[],r.type=["string"]),i.endsWith("?")&&(r.required=!1,i=i.slice(0,-1)),i.endsWith("*")&&(r.type=["string"],r.variadic=!0,r.default=[],i=i.slice(0,-1)),r.description=r.description??e[i]??e[`--${i}`],{name:i,isOption:n,definition:r}}}class B extends v{helperDefinitions={};get command(){return this.parser?this.parser.command:this.signature.split(" ")[0]}newCommandParser(t){return new $({io:t.io,signature:this.signature,helperDefinitions:this.helperDefinitions,defaultOptions:this.defaultOptions()})}constructor(){super("")}option(t,e=null){return this.parser.option(t,e)}argument(t,e=null){return this.parser.argument(t,e)}async askForConfirmation(...t){return this.io.askForConfirmation(...t)}async askForInput(...t){return this.io.askForInput(...t)}async askForSelect(...t){return this.io.askForSelect(...t)}newLoader(...t){return this.io.newLoader(...t)}}class S{level;constructor(t={}){this.level=t.level??"info"}shouldLog(t){const e=["debug","info","warn","error"],i=e.indexOf(this.level);return e.indexOf(t)>=i}setLevel(t){this.level=t}getLevel(){return this.level}log(...t){console.log(...t)}info(...t){this.shouldLog("info")&&console.log(...t)}warn(...t){this.shouldLog("warn")&&console.warn(...t)}error(...t){this.shouldLog("error")&&console.error(...t)}debug(...t){this.shouldLog("debug")&&console.log(...t)}}class I{getBigrams(t){const e=[],i=t.toLowerCase();for(let n=0;n<i.length-1;n++)e.push(i.slice(n,n+2));return e}calculateSimilarity(t,e){if(t===e)return 1;if(t.length<2||e.length<2)return 0;const i=this.getBigrams(t),n=this.getBigrams(e),r=new Set(n);let o=0;for(const u of i)r.has(u)&&(o++,r.delete(u));return 2*o/(i.length+n.length)}findBestMatch(t,e){const i=e.map(o=>({target:o,rating:this.calculateSimilarity(t,o)}));let n=0,r=i[0]?.rating??0;for(let o=1;o<i.length;o++)i[o].rating>r&&(r=i[o].rating,n=o);return{ratings:i,bestMatch:i[n],bestMatchIndex:n}}}class V{commands={};io;logger;stringSimilarity;newCommandIO(t){return new R(t)}constructor(t){this.logger=t?.logger??new S,this.io=this.newCommandIO({logger:this.logger}),this.stringSimilarity=t?.stringSimilarity??new I}getAvailableCommands(){return Object.keys(this.commands)}getCommands(){return Object.values(this.commands)}importFile=async t=>(await import(t)).default;commandResolver=async t=>{let e=await this.importFile(t);return e?(e&&typeof e=="object"&&"default"in e&&(e=e.default),typeof e=="function"?new e:e instanceof v?e:null):null};withCommandResolver(t){return this.commandResolver=t,this}withFileImporter(t){return this.importFile=t,this}registerCommand(t,e=!1){const i=t.command;if(!i)throw new Error("Command signature is invalid, it must have a command name.");if(!e&&this.commands[i])throw new Error(`Command ${i} already registered.`);this.commands[i]=t}async loadCommandsPath(t){for await(const e of this.listCommandsFiles(t))try{const i=await this.commandResolver(e);i instanceof v&&this.registerCommand(i)}catch(i){throw new Error(`Command ${e} failed to load. ${i}`,{cause:i})}}async runCommand(t,e,...i){const n=typeof e=="string"?this.commands[e]:e,r=typeof e=="string"?e:n.command;if(!n){const o=await this.suggestCommand(r);return o?await this.runCommand(t,o,...i):1}return await n.run({ctx:t,logger:this.logger,args:i})??0}async suggestCommand(t){const e=this.getAvailableCommands(),{bestMatch:i,bestMatchIndex:n,ratings:r}=this.stringSimilarity.findBestMatch(t,e),o=r.filter(u=>u.rating>.3).map(u=>u.target);if(i.rating>0&&o.length<=1||i.rating>.7&&o.length>1){const u=e[n];return await this.askRunSimilarCommand(t,u)?u:null}if(o.length){this.io.error(`${a.bgRed(" ERROR ")} Command ${a.yellow(t)} not found.
10
- `);const u=await this.io.askForSelect(a.green("Did you mean to run one of these commands instead?"),o);if(u)return u}throw new P(t)}async askRunSimilarCommand(t,e){return this.io.error(`${a.bgRed(" ERROR ")} Command ${a.yellow(t)} not found.
11
- `),this.io.askForConfirmation(`${a.green(`Do you want to run ${a.yellow(e)} instead?`)} `)}async*listCommandsFiles(t){const e=j.readdirSync(t,{withFileTypes:!0});for(const i of e){const n=F.resolve(t,i.name);if(i.isDirectory())yield*this.listCommandsFiles(F.resolve(t,i.name));else{if(!n.endsWith(".ts")&&!n.endsWith(".js")&&!n.endsWith(".mjs")&&!n.endsWith(".cjs"))continue;yield n}}}}class H{logger;constructor(t){this.logger=t}handle(t){if(t instanceof f)return t.pretty(this.logger),-1;throw t}}class T extends v{constructor(t){super("help",{description:a.bold("Show help information about the CLI and its commands")}),this.opts=t}async handle(){const t=this.opts.commandRegistry.getCommands(),e=this.opts.cliName??"Bob CLI",i=this.opts.cliVersion??"0.0.0",n=(await Promise.resolve().then(()=>require("../package-Blqq-jZJ.cjs")))?.default?.version??"0.0.0";this.io.log(`${e} ${a.green(i)} (core: ${a.yellow(n)})
9
+ `),this.io.log(` ${a.green(`${l} ${c.command}`)}`)}return-1}}class C{$type="BobCommand";_command;description;group;commandsExamples=[];get command(){return this._command}ctx;io;parser;disablePromptingFlag=!1;_preHandler;_handler;tmp;defaultOptions(){return[new I]}newCommandParser(t){return new x({io:t.io,options:t.options,arguments:t.arguments})}newCommandIO(t){return new R(t)}constructor(t,e){this._command=t,this.description=e?.description??"",this.group=e?.group,this.tmp={options:e?.options??{},arguments:e?.arguments??{}};const i=this.defaultOptions();if(i.length>0)for(const n of i)this.tmp.options[n.option]=n}disablePrompting(){return this.disablePromptingFlag=!0,this}preHandler(t){return this._preHandler=t,this}handler(t){return this._handler=t,this}options(t){return this.tmp={options:{...this.tmp?.options??{},...t},arguments:this.tmp?.arguments??{}},this}arguments(t){return this.tmp={options:this.tmp?.options??{},arguments:{...this.tmp?.arguments??{},...t}},this}async run(t){if(!this._handler&&!this.handle)throw new Error(`No handler defined for command ${this.command||"(unknown)"}`);let e;if(this.ctx=t.ctx,this.io=this.newCommandIO({logger:t.logger}),t&&"args"in t){const n=this.tmp?.options??{};for(const r of this.defaultOptions())r.option in n||(n[r.option]=r);this.parser=this.newCommandParser({io:this.io,options:n,arguments:this.tmp?.arguments??{}}),e=this.parser.init(t.args);for(const r of this.defaultOptions())if(e.options[r.option]===!0){const o=await r.handler.call(this);if(o&&o!==0)return o}this.disablePromptingFlag&&this.parser.disablePrompting(),await this.parser.validate()}else e={options:t.options,arguments:t.arguments};if(!this._preHandler&&this.preHandle&&(this._preHandler=this.preHandle.bind(this)),this._preHandler){const n=await this._preHandler(t.ctx,e);if(n&&n!==0)return n}if(!this._handler&&this.handle)this._handler=this.handle.bind(this);else if(!this._handler)throw new Error(`No handler defined for command ${this.command||"(unknown)"}`);return await this._handler(t.ctx,e)??0}}class v extends x{command;constructor(t){const e=v.parseSignature(t.signature,t.helperDefinitions,t.defaultOptions);super({io:t.io,options:e.options,arguments:e.arguments}),this.command=e.command}static parseSignature(t,e,i){const[n,...r]=t.split(/\{(.*?)\}/g).map(m=>m.trim()).filter(Boolean),o={},u={};for(const m of r){const{name:h,isOption:l,definition:d}=v.parseParamSignature(m,e);l?o[h]=d:u[h]=d}for(const m of i)o[m.option]={type:m.type,required:m.required,alias:m.alias,variadic:m.variadic??!1,description:m.description,default:m.default??null};return{command:n,options:o,arguments:u}}static parseParamSignature(t,e){let i=t,n=!1;const r={required:!0,type:"string",description:void 0,default:null,variadic:!1};if(i.includes(":")){const[o,u]=i.split(":");i=o.trim(),r.description=u.trim()}if(i.includes("=")){const[o,u]=i.split("=");i=o.trim(),r.default=u.trim(),r.required=!1,typeof r.default=="string"&&!r.default.length?r.default=null:r.default==="true"?(r.default=!0,r.type="boolean"):r.default==="false"&&(r.default=!1,r.type="boolean")}else i.startsWith("--")&&(r.required=!1,r.default=!1,r.type="boolean");if(i.includes("|")){const[o,...u]=i.split("|");i=o.trim(),r.alias=u.map(m=>m.trim())}return i.startsWith("--")&&(n=!0,i=i.slice(2)),r.default==="*"&&(r.default=[],r.type=["string"]),i.endsWith("?")&&(r.required=!1,i=i.slice(0,-1)),i.endsWith("*")&&(r.type=["string"],r.variadic=!0,r.default=[],i=i.slice(0,-1)),r.description=r.description??e[i]??e[`--${i}`],{name:i,isOption:n,definition:r}}}class T extends C{helperDefinitions={};get command(){return this.parser?this.parser.command:this.signature.split(" ")[0]}newCommandParser(t){return new v({io:t.io,signature:this.signature,helperDefinitions:this.helperDefinitions,defaultOptions:this.defaultOptions()})}constructor(){super("")}option(t,e=null){return this.parser.option(t,e)}argument(t,e=null){return this.parser.argument(t,e)}async askForConfirmation(...t){return this.io.askForConfirmation(...t)}async askForInput(...t){return this.io.askForInput(...t)}async askForSelect(...t){return this.io.askForSelect(...t)}newLoader(...t){return this.io.newLoader(...t)}}class E{level;constructor(t={}){this.level=t.level??"info"}shouldLog(t){const e=["debug","info","warn","error"],i=e.indexOf(this.level);return e.indexOf(t)>=i}setLevel(t){this.level=t}getLevel(){return this.level}log(...t){console.log(...t)}info(...t){this.shouldLog("info")&&console.log(...t)}warn(...t){this.shouldLog("warn")&&console.warn(...t)}error(...t){this.shouldLog("error")&&console.error(...t)}debug(...t){this.shouldLog("debug")&&console.log(...t)}}class V{getBigrams(t){const e=[],i=t.toLowerCase();for(let n=0;n<i.length-1;n++)e.push(i.slice(n,n+2));return e}calculateSimilarity(t,e){if(t===e)return 1;if(t.length<2||e.length<2)return 0;const i=this.getBigrams(t),n=this.getBigrams(e),r=new Set(n);let o=0;for(const u of i)r.has(u)&&(o++,r.delete(u));return 2*o/(i.length+n.length)}findBestMatch(t,e){const i=e.map(o=>({target:o,rating:this.calculateSimilarity(t,o)}));let n=0,r=i[0]?.rating??0;for(let o=1;o<i.length;o++)i[o].rating>r&&(r=i[o].rating,n=o);return{ratings:i,bestMatch:i[n],bestMatchIndex:n}}}function _(s){return typeof s=="object"&&s!==null&&"$type"in s&&s.$type==="BobError"}function N(s){return typeof s=="object"&&s!==null&&(s instanceof C||"$type"in s&&s.$type==="BobCommand")}class H{commands={};io;logger;stringSimilarity;newCommandIO(t){return new R(t)}constructor(t){this.logger=t?.logger??new E,this.io=this.newCommandIO({logger:this.logger}),this.stringSimilarity=t?.stringSimilarity??new V}getAvailableCommands(){return Object.keys(this.commands)}getCommands(){return Object.values(this.commands)}importFile=async t=>(await import(t)).default;commandResolver=async t=>{let e=await this.importFile(t);return e?(e&&typeof e=="object"&&"default"in e&&(e=e.default),typeof e=="function"?new e:N(e)?e:null):null};withCommandResolver(t){return this.commandResolver=t,this}withFileImporter(t){return this.importFile=t,this}registerCommand(t,e=!1){const i=t.command;if(!i)throw new Error("Command signature is invalid, it must have a command name.");if(!e&&this.commands[i])throw new Error(`Command ${i} already registered.`);this.commands[i]=t}async loadCommandsPath(t){for await(const e of this.listCommandsFiles(t))try{const i=await this.commandResolver(e);N(i)&&this.registerCommand(i)}catch(i){throw new Error(`Command ${e} failed to load. ${i}`,{cause:i})}}async runCommand(t,e,...i){const n=typeof e=="string"?this.commands[e]:e,r=typeof e=="string"?e:n.command;if(!n){const o=await this.suggestCommand(r);return o?await this.runCommand(t,o,...i):1}return await n.run({ctx:t,logger:this.logger,args:i})??0}async suggestCommand(t){const e=this.getAvailableCommands(),{bestMatch:i,bestMatchIndex:n,ratings:r}=this.stringSimilarity.findBestMatch(t,e),o=r.filter(u=>u.rating>.3).map(u=>u.target);if(i&&(i.rating>0&&o.length<=1||i.rating>.7&&o.length>1)){const u=e[n];return await this.askRunSimilarCommand(t,u)?u:null}if(o.length){this.io.error(`${a.bgRed(" ERROR ")} Command ${a.yellow(t)} not found.
10
+ `);const u=await this.io.askForSelect(a.green("Did you mean to run one of these commands instead?"),o);if(u)return u}throw new L(t)}async askRunSimilarCommand(t,e){return this.io.error(`${a.bgRed(" ERROR ")} Command ${a.yellow(t)} not found.
11
+ `),this.io.askForConfirmation(`${a.green(`Do you want to run ${a.yellow(e)} instead?`)} `)}async*listCommandsFiles(t){const e=W.readdirSync(t,{withFileTypes:!0});for(const i of e){const n=F.resolve(t,i.name);if(i.isDirectory())yield*this.listCommandsFiles(F.resolve(t,i.name));else{if(!n.endsWith(".ts")&&!n.endsWith(".js")&&!n.endsWith(".mjs")&&!n.endsWith(".cjs"))continue;yield n}}}}class B{logger;constructor(t){this.logger=t}handle(t){if(_(t))return t.pretty(this.logger),-1;throw t}}class G extends C{constructor(t){super("help",{description:a.bold("Show help information about the CLI and its commands")}),this.opts=t}async handle(){const t=this.opts.commandRegistry.getCommands(),e=this.opts.cliName??"Bob CLI",i=this.opts.cliVersion??"0.0.0",n=(await Promise.resolve().then(()=>require("../package-B3VP5AzR.cjs")))?.default?.version??"0.0.0";this.io.log(`${e} ${a.green(i)} (core: ${a.yellow(n)})
12
12
 
13
13
  ${a.yellow("Usage")}:
14
14
  command [options] [arguments]
15
15
 
16
16
  ${a.yellow("Available commands")}:
17
- `);const r=Math.max(...t.map(m=>m.command.length))??0,o={};for(const m of t){const h=m.group??m.command.split(":")[0];o[h]||(o[h]=[]),o[h].push(m)}const u=Object.entries(o).sort(([m],[h])=>m.toLowerCase().localeCompare(h.toLowerCase())).sort(([,m],[,h])=>m.length-h.length);for(const[m,h]of u){const l=h.length>1;l&&this.io.log(a.yellow(`${m}:`));const d=h.sort((c,p)=>c.command.toLowerCase().localeCompare(p.command.toLowerCase()));for(const c of d){let p=O(r-c.command.length);l&&(p=p.slice(2)),this.io.log(`${l?" ":""}${a.green(c.command)} ${p} ${c.description}`)}}}}class _{ctx;logger;commandRegistry;exceptionHandler;helpCommand;newCommandRegistry(t){return new V(t)}newHelpCommand(t){return new T(t)}newExceptionHandler(t){return new H(t.logger)}constructor(t={}){this.ctx=t.ctx,this.logger=t.logger??new S,this.commandRegistry=this.newCommandRegistry({logger:this.logger}),this.exceptionHandler=this.newExceptionHandler({logger:this.logger}),this.helpCommand=this.newHelpCommand({cliName:t.name,cliVersion:t.version,commandRegistry:this.commandRegistry})}withCommandResolver(t){return this.commandRegistry.withCommandResolver(t),this}withFileImporter(t){return this.commandRegistry.withFileImporter(t),this}async withCommands(...t){for(const e of t)typeof e=="string"?await this.commandRegistry.loadCommandsPath(e):typeof e=="function"?this.registerCommand(new e):this.registerCommand(e)}async runCommand(t,...e){return t?await this.commandRegistry.runCommand(this.ctx??{},t,...e).catch(this.exceptionHandler.handle.bind(this.exceptionHandler)):await this.runHelpCommand()}async runHelpCommand(){return await this.runCommand(this.helpCommand)}registerCommand(t){this.commandRegistry.registerCommand(t)}}exports.BadCommandOption=C;exports.BadCommandParameter=W;exports.BobError=f;exports.Cli=_;exports.Command=v;exports.CommandIO=R;exports.CommandNotFoundError=P;exports.CommandParser=x;exports.CommandRegistry=V;exports.CommandSignatureParser=$;exports.CommandWithSignature=B;exports.ExceptionHandler=H;exports.HelpOption=L;exports.InvalidOption=b;exports.Logger=S;exports.MissingRequiredArgumentValue=A;exports.MissingRequiredOptionValue=N;exports.StringSimilarity=I;
17
+ `);const r=Math.max(...t.map(m=>m.command.length))??0,o={};for(const m of t){const h=m.group??m.command.split(":")[0];o[h]||(o[h]=[]),o[h].push(m)}const u=Object.entries(o).sort(([m],[h])=>m.toLowerCase().localeCompare(h.toLowerCase())).sort(([,m],[,h])=>m.length-h.length);for(const[m,h]of u){const l=h.length>1;l&&this.io.log(a.yellow(`${m}:`));const d=h.sort((c,p)=>c.command.toLowerCase().localeCompare(p.command.toLowerCase()));for(const c of d){let p=O(r-c.command.length);l&&(p=p.slice(2)),this.io.log(`${l?" ":""}${a.green(c.command)} ${p} ${c.description}`)}}}}class U{ctx;logger;commandRegistry;exceptionHandler;helpCommand;newCommandRegistry(t){return new H(t)}newHelpCommand(t){return new G(t)}newExceptionHandler(t){return new B(t.logger)}constructor(t={}){this.ctx=t.ctx,this.logger=t.logger??new E,this.commandRegistry=this.newCommandRegistry({logger:this.logger}),this.exceptionHandler=this.newExceptionHandler({logger:this.logger}),this.helpCommand=this.newHelpCommand({cliName:t.name,cliVersion:t.version,commandRegistry:this.commandRegistry})}withCommandResolver(t){return this.commandRegistry.withCommandResolver(t),this}withFileImporter(t){return this.commandRegistry.withFileImporter(t),this}async withCommands(...t){for(const e of t)typeof e=="string"?await this.commandRegistry.loadCommandsPath(e):typeof e=="function"?this.registerCommand(new e):this.registerCommand(e)}async runCommand(t,...e){return t?await this.commandRegistry.runCommand(this.ctx??{},t,...e).catch(this.exceptionHandler.handle.bind(this.exceptionHandler)):await this.runHelpCommand()}async runHelpCommand(){return await this.runCommand(this.helpCommand)}registerCommand(t){this.commandRegistry.registerCommand(t)}}exports.BadCommandOption=b;exports.BadCommandParameter=j;exports.BobError=f;exports.Cli=U;exports.Command=C;exports.CommandIO=R;exports.CommandNotFoundError=L;exports.CommandParser=x;exports.CommandRegistry=H;exports.CommandSignatureParser=v;exports.CommandWithSignature=T;exports.ExceptionHandler=B;exports.HelpOption=I;exports.InvalidOption=$;exports.Logger=E;exports.MissingRequiredArgumentValue=A;exports.MissingRequiredOptionValue=P;exports.StringSimilarity=V;
@@ -0,0 +1,4 @@
1
+ import { Command } from '../Command.js';
2
+ import { BobError } from '../errors/index.js';
3
+ export declare function isBobError(err: Error): err is BobError;
4
+ export declare function isBobCommand(obj: unknown): obj is Command;
@@ -1,4 +1,4 @@
1
- const t = "bob-core", s = "2.0.0", e = "BOB Core", i = "module", n = "./dist/cjs/src/index.js", r = "./dist/esm/src/index.js", c = "./dist/esm/src/index.d.ts", o = ["dist"], d = { ".": { import: { types: "./dist/esm/src/index.d.ts", default: "./dist/esm/src/index.js" }, require: { types: "./dist/cjs/src/index.d.ts", default: "./dist/cjs/src/index.js" } } }, p = { start: "node -r @swc-node/register debug/main.ts", build: "rimraf ./dist && vite build", typecheck: "tsc --noEmit", prepack: "npm run build", test: "vitest run", lint: "eslint .", "lint:fix": "eslint . --fix" }, l = "Léo Hubert", m = "ISC", a = { "@eslint/js": "^9.37.0", "@faker-js/faker": "^10.0.0", "@swc-node/register": "^1.11.1", "@trivago/prettier-plugin-sort-imports": "^5.2.2", "@types/minimist": "^1.2.5", "@types/node": "^20.14.5", "@types/prompts": "^2.4.9", "@types/string-similarity": "^4.0.2", "@vitest/coverage-v8": "^3.2.4", eslint: "^9.37.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.5.4", prettier: "^3.6.2", rimraf: "^6.0.1", tsx: "^4.20.6", typescript: "^5.9.3", "typescript-eslint": "^8.46.0", vite: "^7.2.7", "vite-plugin-dts": "^4.5.4", vitest: "^3.2.4" }, u = { chalk: "^4.1.2", minimist: "^1.2.8", prompts: "^2.4.2" }, x = {
1
+ const t = "bob-core", s = "2.0.2", e = "BOB Core", i = "module", n = "./dist/cjs/src/index.js", r = "./dist/esm/src/index.js", c = "./dist/esm/src/index.d.ts", o = ["dist"], d = { ".": { import: { types: "./dist/esm/src/index.d.ts", default: "./dist/esm/src/index.js" }, require: { types: "./dist/cjs/src/index.d.ts", default: "./dist/cjs/src/index.js" } } }, p = { start: "node -r @swc-node/register debug/main.ts", build: "rimraf ./dist && vite build", typecheck: "tsc --noEmit", prepack: "npm run build", test: "vitest run", lint: "eslint .", "lint:fix": "eslint . --fix" }, l = "Léo Hubert", m = "ISC", a = { "@eslint/js": "^9.37.0", "@faker-js/faker": "^10.0.0", "@swc-node/register": "^1.11.1", "@trivago/prettier-plugin-sort-imports": "^5.2.2", "@types/minimist": "^1.2.5", "@types/node": "^20.14.5", "@types/prompts": "^2.4.9", "@types/string-similarity": "^4.0.2", "@vitest/coverage-v8": "^3.2.4", eslint: "^9.37.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.5.4", prettier: "^3.6.2", rimraf: "^6.0.1", tsx: "^4.20.6", typescript: "^5.9.3", "typescript-eslint": "^8.46.0", vite: "^7.2.7", "vite-plugin-dts": "^4.5.4", vitest: "^3.2.4" }, u = { chalk: "^4.1.2", minimist: "^1.2.8", prompts: "^2.4.2" }, x = {
2
2
  name: t,
3
3
  version: s,
4
4
  description: e,
@@ -22,6 +22,7 @@ export type CommandExample = {
22
22
  command: string;
23
23
  };
24
24
  export declare class Command<C extends ContextDefinition = ContextDefinition, Options extends OptionsSchema = OptionsSchema, Arguments extends ArgumentsSchema = ArgumentsSchema> {
25
+ $type: "BobCommand";
25
26
  readonly _command: string;
26
27
  readonly description: string;
27
28
  readonly group?: string;
@@ -1,7 +1,6 @@
1
1
  import { Logger } from './Logger.js';
2
- import { BobError } from './errors/index.js';
3
2
  export declare class ExceptionHandler {
4
3
  private readonly logger;
5
4
  constructor(logger: Logger);
6
- handle(err: Error | BobError): number;
5
+ handle(err: Error): number;
7
6
  }
@@ -1,4 +1,5 @@
1
1
  import { Logger } from '../Logger.js';
2
2
  export declare abstract class BobError extends Error {
3
+ $type: "BobError";
3
4
  abstract pretty(logger: Logger): void;
4
5
  }
@@ -1,9 +1,9 @@
1
- import y from "prompts";
1
+ import f from "prompts";
2
2
  import a from "chalk";
3
- import q from "minimist";
4
- import I from "node:fs";
3
+ import I from "minimist";
4
+ import V from "node:fs";
5
5
  import R from "node:path";
6
- class S {
6
+ class k {
7
7
  logger;
8
8
  constructor(t) {
9
9
  this.logger = t.logger;
@@ -30,7 +30,7 @@ class S {
30
30
  * Prompt utils
31
31
  */
32
32
  async askForConfirmation(t = "Do you want to continue?", e) {
33
- return (await y({
33
+ return (await f({
34
34
  type: "confirm",
35
35
  name: "value",
36
36
  message: t,
@@ -38,7 +38,7 @@ class S {
38
38
  })).value;
39
39
  }
40
40
  async askForInput(t, e, i) {
41
- return (await y({
41
+ return (await f({
42
42
  type: "text",
43
43
  name: "value",
44
44
  message: t,
@@ -47,7 +47,7 @@ class S {
47
47
  }))?.value ?? null;
48
48
  }
49
49
  async askForDate(t, e, i) {
50
- return (await y({
50
+ return (await f({
51
51
  type: "date",
52
52
  name: "value",
53
53
  message: t,
@@ -56,7 +56,7 @@ class S {
56
56
  }))?.value ?? null;
57
57
  }
58
58
  async askForList(t, e, i) {
59
- return (await y({
59
+ return (await f({
60
60
  type: "list",
61
61
  name: "value",
62
62
  message: t,
@@ -65,7 +65,7 @@ class S {
65
65
  }))?.value ?? null;
66
66
  }
67
67
  async askForToggle(t, e, i) {
68
- return (await y({
68
+ return (await f({
69
69
  type: "toggle",
70
70
  name: "value",
71
71
  message: t,
@@ -79,7 +79,7 @@ class S {
79
79
  const n = [];
80
80
  for (const o of e)
81
81
  typeof o == "string" ? n.push({ title: o, value: o }) : n.push(o);
82
- return (await y({
82
+ return (await f({
83
83
  type: "select",
84
84
  name: "value",
85
85
  message: t,
@@ -104,7 +104,8 @@ class S {
104
104
  };
105
105
  }
106
106
  }
107
- class f extends Error {
107
+ class y extends Error {
108
+ $type = "BobError";
108
109
  }
109
110
  function x(r) {
110
111
  if (r === "string" || r === "number") return null;
@@ -137,7 +138,7 @@ function g(r) {
137
138
  variadic: r.variadic ?? !1
138
139
  };
139
140
  }
140
- class b extends f {
141
+ class v extends y {
141
142
  constructor(t, e = {}) {
142
143
  super(`Invalid option ${t} in not recognized`), this.option = t, this.optionsSchema = e;
143
144
  }
@@ -155,7 +156,7 @@ ${a.yellow("Available options")}:`);
155
156
  t.log(`${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.option)} is not recognized.`);
156
157
  }
157
158
  }
158
- class F extends f {
159
+ class F extends y {
159
160
  constructor(t) {
160
161
  super(`Argument "${t}" is required.`), this.argument = t;
161
162
  }
@@ -163,7 +164,7 @@ class F extends f {
163
164
  t.log(`${a.white.bgRed(" ERROR ")} Argument ${a.bold.yellow(this.argument)} is required.`);
164
165
  }
165
166
  }
166
- class V extends f {
167
+ class P extends y {
167
168
  constructor(t) {
168
169
  super(`Argument "${t}" is required.`), this.option = t;
169
170
  }
@@ -171,7 +172,7 @@ class V extends f {
171
172
  t.log(`${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.option)} is required.`);
172
173
  }
173
174
  }
174
- class z extends f {
175
+ class K extends y {
175
176
  constructor(t) {
176
177
  let e = `Argument "${t.param}" value is invalid.`;
177
178
  t.reason ? e += ` Reason: ${t.reason}` : e += ` Value: "${t.value}"`, super(e), this.param = t;
@@ -180,7 +181,7 @@ class z extends f {
180
181
  t.log(` ${a.white.bgRed(" ERROR ")} Argument ${a.bold.yellow(this.param.param)} value is invalid. `), (this.param.value || this.param.reason) && t.log(""), this.param.value && t.log(` ${a.blue("Value")}: ${this.param.value}`), this.param.reason && t.log(` ${a.yellow("Reason")}: ${this.param.reason}`);
181
182
  }
182
183
  }
183
- class C extends f {
184
+ class b extends y {
184
185
  constructor(t) {
185
186
  let e = `Option "${t.option}" value is invalid.`;
186
187
  t.reason ? e += ` Reason: ${t.reason}` : e += ` Value: "${t.value}"`, super(e), this.param = t;
@@ -189,7 +190,7 @@ class C extends f {
189
190
  t.log(` ${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.param.option)} value is invalid. `), (this.param.value || this.param.reason) && t.log(""), this.param.value && t.log(` ${a.blue("Value")}: ${this.param.value}`), this.param.reason && t.log(` ${a.yellow("Reason")}: ${this.param.reason}`);
190
191
  }
191
192
  }
192
- class P extends f {
193
+ class H extends y {
193
194
  constructor(t) {
194
195
  super(`Command "${t}" not found.`), this.command = t;
195
196
  }
@@ -205,7 +206,7 @@ function w(r, t, e, i) {
205
206
  if (t === "number") {
206
207
  const n = Number(r);
207
208
  if (isNaN(n))
208
- throw new C({
209
+ throw new b({
209
210
  option: e,
210
211
  reason: `Expected a number, got "${r}"`
211
212
  });
@@ -221,7 +222,7 @@ function w(r, t, e, i) {
221
222
  return s.map((o) => {
222
223
  const u = Number(o);
223
224
  if (isNaN(u))
224
- throw new C({
225
+ throw new b({
225
226
  option: e,
226
227
  reason: `Expected array of numbers, got "${o}" in array`
227
228
  });
@@ -230,7 +231,7 @@ function w(r, t, e, i) {
230
231
  }
231
232
  return r;
232
233
  }
233
- class k {
234
+ class N {
234
235
  options;
235
236
  parsedOptions = null;
236
237
  arguments;
@@ -249,7 +250,7 @@ class k {
249
250
  * @throws {BadCommandOption} If a value cannot be converted to the expected type
250
251
  */
251
252
  init(t) {
252
- const { _: e, ...i } = q(t);
253
+ const { _: e, ...i } = I(t);
253
254
  return this.validateUnknownOptions(i), this.parsedOptions = this.handleOptions(i), this.parsedArguments = this.handleArguments(e), {
254
255
  options: this.parsedOptions,
255
256
  arguments: this.parsedArguments
@@ -262,7 +263,7 @@ class k {
262
263
  async validate() {
263
264
  for (const t in this.options)
264
265
  if (g(this.options[t]).required && (this.parsedOptions?.[t] === void 0 || this.parsedOptions?.[t] === null))
265
- throw new V(t);
266
+ throw new P(t);
266
267
  for (const t in this.arguments) {
267
268
  const e = g(this.arguments[t]), i = this.parsedArguments?.[t];
268
269
  if (e.required && i == null) {
@@ -303,7 +304,7 @@ class k {
303
304
  if (!this.parsedOptions)
304
305
  throw new Error("Options have not been parsed yet. Call init() first.");
305
306
  if (!(t in this.options))
306
- throw new b(t, this.options);
307
+ throw new v(t, this.options);
307
308
  this.parsedOptions[t] = e;
308
309
  }
309
310
  /**
@@ -322,7 +323,7 @@ class k {
322
323
  if (!this.parsedArguments)
323
324
  throw new Error("Arguments have not been parsed yet. Call init() first.");
324
325
  if (!(t in this.arguments))
325
- throw new b(t, this.arguments);
326
+ throw new v(t, this.arguments);
326
327
  this.parsedArguments[t] = e;
327
328
  }
328
329
  // === PRIVATE HELPERS ===
@@ -348,7 +349,7 @@ class k {
348
349
  }
349
350
  for (const i in t)
350
351
  if (!e.has(i))
351
- throw new b(i, this.options);
352
+ throw new v(i, this.options);
352
353
  }
353
354
  /**
354
355
  * Processes named options from minimist output
@@ -403,7 +404,7 @@ class k {
403
404
  }
404
405
  if (n === void 0) {
405
406
  if (e.required)
406
- throw new C({
407
+ throw new b({
407
408
  option: t,
408
409
  reason: "Required option is missing"
409
410
  });
@@ -477,10 +478,10 @@ class k {
477
478
  });
478
479
  }
479
480
  }
480
- function A(r) {
481
+ function C(r) {
481
482
  return new Array(r + 5).join(" ");
482
483
  }
483
- class H {
484
+ class D {
484
485
  type = "boolean";
485
486
  option = "help";
486
487
  alias = ["h"];
@@ -502,11 +503,11 @@ class H {
502
503
  this.io.log(`
503
504
  ${a.yellow("Arguments")}:`);
504
505
  for (const [l, d] of i) {
505
- const p = A(h - l.length);
506
+ const p = C(h - l.length);
506
507
  let c = ` ${a.green(l)} ${p} ${d.description ?? "\b"}`;
507
508
  if (d.default !== void 0 && !d.required) {
508
- const L = (Array.isArray(d.type) ? `[${d.type[0]}]` : d.type) === "array" || Array.isArray(d.type) ? JSON.stringify(d.default) : d.default;
509
- c += ` ${a.yellow(`[default: ${L}]`)}`;
509
+ const q = (Array.isArray(d.type) ? `[${d.type[0]}]` : d.type) === "array" || Array.isArray(d.type) ? JSON.stringify(d.default) : d.default;
510
+ c += ` ${a.yellow(`[default: ${q}]`)}`;
510
511
  }
511
512
  d.variadic && (c += ` ${a.white("(variadic)")}`), this.io.log(c);
512
513
  }
@@ -515,7 +516,7 @@ ${a.yellow("Arguments")}:`);
515
516
  this.io.log(`
516
517
  ${a.yellow("Options")}:`);
517
518
  for (const l of s) {
518
- const d = A(h - l.optionWithAlias.length);
519
+ const d = C(h - l.optionWithAlias.length);
519
520
  let p = `${a.green(l.optionWithAlias)} ${d} ${l.description ?? "\b"}`;
520
521
  if (l.type) {
521
522
  const c = Array.isArray(l.type) ? `[${l.type[0]}]` : l.type;
@@ -540,7 +541,8 @@ ${a.yellow("Examples")}:`);
540
541
  return -1;
541
542
  }
542
543
  }
543
- class v {
544
+ class A {
545
+ $type = "BobCommand";
544
546
  _command;
545
547
  description;
546
548
  group;
@@ -556,17 +558,17 @@ class v {
556
558
  _handler;
557
559
  tmp;
558
560
  defaultOptions() {
559
- return [new H()];
561
+ return [new D()];
560
562
  }
561
563
  newCommandParser(t) {
562
- return new k({
564
+ return new N({
563
565
  io: t.io,
564
566
  options: t.options,
565
567
  arguments: t.arguments
566
568
  });
567
569
  }
568
570
  newCommandIO(t) {
569
- return new S(t);
571
+ return new k(t);
570
572
  }
571
573
  constructor(t, e) {
572
574
  this._command = t, this.description = e?.description ?? "", this.group = e?.group, this.tmp = {
@@ -644,7 +646,7 @@ class v {
644
646
  return await this._handler(t.ctx, e) ?? 0;
645
647
  }
646
648
  }
647
- class $ extends k {
649
+ class $ extends N {
648
650
  command;
649
651
  constructor(t) {
650
652
  const e = $.parseSignature(t.signature, t.helperDefinitions, t.defaultOptions);
@@ -717,7 +719,7 @@ class $ extends k {
717
719
  return i.startsWith("--") && (n = !0, i = i.slice(2)), s.default === "*" && (s.default = [], s.type = ["string"]), i.endsWith("?") && (s.required = !1, i = i.slice(0, -1)), i.endsWith("*") && (s.type = ["string"], s.variadic = !0, s.default = [], i = i.slice(0, -1)), s.description = s.description ?? e[i] ?? e[`--${i}`], { name: i, isOption: n, definition: s };
718
720
  }
719
721
  }
720
- class J extends v {
722
+ class Q extends A {
721
723
  helperDefinitions = {};
722
724
  get command() {
723
725
  return this.parser ? this.parser.command : this.signature.split(" ")[0];
@@ -753,7 +755,7 @@ class J extends v {
753
755
  return this.io.newLoader(...t);
754
756
  }
755
757
  }
756
- class N {
758
+ class L {
757
759
  level;
758
760
  constructor(t = {}) {
759
761
  this.level = t.level ?? "info";
@@ -784,7 +786,7 @@ class N {
784
786
  this.shouldLog("debug") && console.log(...t);
785
787
  }
786
788
  }
787
- class D {
789
+ class B {
788
790
  /**
789
791
  * Generate bigrams (character pairs) from a string
790
792
  */
@@ -824,18 +826,24 @@ class D {
824
826
  };
825
827
  }
826
828
  }
827
- class j {
829
+ function W(r) {
830
+ return typeof r == "object" && r !== null && "$type" in r && r.$type === "BobError";
831
+ }
832
+ function S(r) {
833
+ return typeof r == "object" && r !== null && (r instanceof A || "$type" in r && r.$type === "BobCommand");
834
+ }
835
+ class M {
828
836
  commands = {};
829
837
  io;
830
838
  logger;
831
839
  stringSimilarity;
832
840
  newCommandIO(t) {
833
- return new S(t);
841
+ return new k(t);
834
842
  }
835
843
  constructor(t) {
836
- this.logger = t?.logger ?? new N(), this.io = this.newCommandIO({
844
+ this.logger = t?.logger ?? new L(), this.io = this.newCommandIO({
837
845
  logger: this.logger
838
- }), this.stringSimilarity = t?.stringSimilarity ?? new D();
846
+ }), this.stringSimilarity = t?.stringSimilarity ?? new B();
839
847
  }
840
848
  getAvailableCommands() {
841
849
  return Object.keys(this.commands);
@@ -846,7 +854,7 @@ class j {
846
854
  importFile = async (t) => (await import(t)).default;
847
855
  commandResolver = async (t) => {
848
856
  let e = await this.importFile(t);
849
- return e ? (e && typeof e == "object" && "default" in e && (e = e.default), typeof e == "function" ? new e() : e instanceof v ? e : null) : null;
857
+ return e ? (e && typeof e == "object" && "default" in e && (e = e.default), typeof e == "function" ? new e() : S(e) ? e : null) : null;
850
858
  };
851
859
  withCommandResolver(t) {
852
860
  return this.commandResolver = t, this;
@@ -866,7 +874,7 @@ class j {
866
874
  for await (const e of this.listCommandsFiles(t))
867
875
  try {
868
876
  const i = await this.commandResolver(e);
869
- i instanceof v && this.registerCommand(i);
877
+ S(i) && this.registerCommand(i);
870
878
  } catch (i) {
871
879
  throw new Error(`Command ${e} failed to load. ${i}`, {
872
880
  cause: i
@@ -887,7 +895,7 @@ class j {
887
895
  }
888
896
  async suggestCommand(t) {
889
897
  const e = this.getAvailableCommands(), { bestMatch: i, bestMatchIndex: n, ratings: s } = this.stringSimilarity.findBestMatch(t, e), o = s.filter((u) => u.rating > 0.3).map((u) => u.target);
890
- if (i.rating > 0 && o.length <= 1 || i.rating > 0.7 && o.length > 1) {
898
+ if (i && (i.rating > 0 && o.length <= 1 || i.rating > 0.7 && o.length > 1)) {
891
899
  const u = e[n];
892
900
  return await this.askRunSimilarCommand(t, u) ? u : null;
893
901
  }
@@ -898,14 +906,14 @@ class j {
898
906
  if (u)
899
907
  return u;
900
908
  }
901
- throw new P(t);
909
+ throw new H(t);
902
910
  }
903
911
  async askRunSimilarCommand(t, e) {
904
912
  return this.io.error(`${a.bgRed(" ERROR ")} Command ${a.yellow(t)} not found.
905
913
  `), this.io.askForConfirmation(`${a.green(`Do you want to run ${a.yellow(e)} instead?`)} `);
906
914
  }
907
915
  async *listCommandsFiles(t) {
908
- const e = I.readdirSync(t, { withFileTypes: !0 });
916
+ const e = V.readdirSync(t, { withFileTypes: !0 });
909
917
  for (const i of e) {
910
918
  const n = R.resolve(t, i.name);
911
919
  if (i.isDirectory())
@@ -918,25 +926,25 @@ class j {
918
926
  }
919
927
  }
920
928
  }
921
- class W {
929
+ class _ {
922
930
  logger;
923
931
  constructor(t) {
924
932
  this.logger = t;
925
933
  }
926
934
  handle(t) {
927
- if (t instanceof f)
935
+ if (W(t))
928
936
  return t.pretty(this.logger), -1;
929
937
  throw t;
930
938
  }
931
939
  }
932
- class M extends v {
940
+ class j extends A {
933
941
  constructor(t) {
934
942
  super("help", {
935
943
  description: a.bold("Show help information about the CLI and its commands")
936
944
  }), this.opts = t;
937
945
  }
938
946
  async handle() {
939
- const t = this.opts.commandRegistry.getCommands(), e = this.opts.cliName ?? "Bob CLI", i = this.opts.cliVersion ?? "0.0.0", n = (await import("../package-DbMvpGfM.js"))?.default?.version ?? "0.0.0";
947
+ const t = this.opts.commandRegistry.getCommands(), e = this.opts.cliName ?? "Bob CLI", i = this.opts.cliVersion ?? "0.0.0", n = (await import("../package-DuYxJEEx.js"))?.default?.version ?? "0.0.0";
940
948
  this.io.log(`${e} ${a.green(i)} (core: ${a.yellow(n)})
941
949
 
942
950
  ${a.yellow("Usage")}:
@@ -955,29 +963,29 @@ ${a.yellow("Available commands")}:
955
963
  l && this.io.log(a.yellow(`${m}:`));
956
964
  const d = h.sort((p, c) => p.command.toLowerCase().localeCompare(c.command.toLowerCase()));
957
965
  for (const p of d) {
958
- let c = A(s - p.command.length);
966
+ let c = C(s - p.command.length);
959
967
  l && (c = c.slice(2)), this.io.log(`${l ? " " : ""}${a.green(p.command)} ${c} ${p.description}`);
960
968
  }
961
969
  }
962
970
  }
963
971
  }
964
- class K {
972
+ class X {
965
973
  ctx;
966
974
  logger;
967
975
  commandRegistry;
968
976
  exceptionHandler;
969
977
  helpCommand;
970
978
  newCommandRegistry(t) {
971
- return new j(t);
979
+ return new M(t);
972
980
  }
973
981
  newHelpCommand(t) {
974
- return new M(t);
982
+ return new j(t);
975
983
  }
976
984
  newExceptionHandler(t) {
977
- return new W(t.logger);
985
+ return new _(t.logger);
978
986
  }
979
987
  constructor(t = {}) {
980
- this.ctx = t.ctx, this.logger = t.logger ?? new N(), this.commandRegistry = this.newCommandRegistry({
988
+ this.ctx = t.ctx, this.logger = t.logger ?? new L(), this.commandRegistry = this.newCommandRegistry({
981
989
  logger: this.logger
982
990
  }), this.exceptionHandler = this.newExceptionHandler({
983
991
  logger: this.logger
@@ -1008,22 +1016,22 @@ class K {
1008
1016
  }
1009
1017
  }
1010
1018
  export {
1011
- C as BadCommandOption,
1012
- z as BadCommandParameter,
1013
- f as BobError,
1014
- K as Cli,
1015
- v as Command,
1016
- S as CommandIO,
1017
- P as CommandNotFoundError,
1018
- k as CommandParser,
1019
- j as CommandRegistry,
1019
+ b as BadCommandOption,
1020
+ K as BadCommandParameter,
1021
+ y as BobError,
1022
+ X as Cli,
1023
+ A as Command,
1024
+ k as CommandIO,
1025
+ H as CommandNotFoundError,
1026
+ N as CommandParser,
1027
+ M as CommandRegistry,
1020
1028
  $ as CommandSignatureParser,
1021
- J as CommandWithSignature,
1022
- W as ExceptionHandler,
1023
- H as HelpOption,
1024
- b as InvalidOption,
1025
- N as Logger,
1029
+ Q as CommandWithSignature,
1030
+ _ as ExceptionHandler,
1031
+ D as HelpOption,
1032
+ v as InvalidOption,
1033
+ L as Logger,
1026
1034
  F as MissingRequiredArgumentValue,
1027
- V as MissingRequiredOptionValue,
1028
- D as StringSimilarity
1035
+ P as MissingRequiredOptionValue,
1036
+ B as StringSimilarity
1029
1037
  };
@@ -0,0 +1,4 @@
1
+ import { Command } from '../Command.js';
2
+ import { BobError } from '../errors/index.js';
3
+ export declare function isBobError(err: Error): err is BobError;
4
+ export declare function isBobCommand(obj: unknown): obj is Command;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bob-core",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "BOB Core",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/src/index.js",