bob-core 2.0.1 → 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.
- package/dist/cjs/{package-DO_9Y5-u.cjs → package-B3VP5AzR.cjs} +1 -1
- package/dist/cjs/src/Command.d.ts +1 -0
- package/dist/cjs/src/ExceptionHandler.d.ts +1 -2
- package/dist/cjs/src/errors/BobError.d.ts +1 -0
- package/dist/cjs/src/index.js +8 -8
- package/dist/cjs/src/lib/helpers.d.ts +4 -0
- package/dist/esm/{package-Drh2xcXq.js → package-DuYxJEEx.js} +1 -1
- package/dist/esm/src/Command.d.ts +1 -0
- package/dist/esm/src/ExceptionHandler.d.ts +1 -2
- package/dist/esm/src/errors/BobError.d.ts +1 -0
- package/dist/esm/src/index.js +82 -74
- package/dist/esm/src/lib/helpers.d.ts +4 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="bob-core",t="2.0.
|
|
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;
|
package/dist/cjs/src/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("prompts"),a=require("chalk"),M=require("minimist"),
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
11
|
-
`),this.io.askForConfirmation(`${a.green(`Do you want to run ${a.yellow(e)} instead?`)} `)}async*listCommandsFiles(t){const e=
|
|
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
|
|
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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const t = "bob-core", s = "2.0.
|
|
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;
|
package/dist/esm/src/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import f from "prompts";
|
|
2
2
|
import a from "chalk";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import I from "minimist";
|
|
4
|
+
import V from "node:fs";
|
|
5
5
|
import R from "node:path";
|
|
6
|
-
class
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 } =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
481
|
+
function C(r) {
|
|
481
482
|
return new Array(r + 5).join(" ");
|
|
482
483
|
}
|
|
483
|
-
class
|
|
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 =
|
|
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
|
|
509
|
-
c += ` ${a.yellow(`[default: ${
|
|
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 =
|
|
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
|
|
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
|
|
561
|
+
return [new D()];
|
|
560
562
|
}
|
|
561
563
|
newCommandParser(t) {
|
|
562
|
-
return new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
841
|
+
return new k(t);
|
|
834
842
|
}
|
|
835
843
|
constructor(t) {
|
|
836
|
-
this.logger = t?.logger ?? new
|
|
844
|
+
this.logger = t?.logger ?? new L(), this.io = this.newCommandIO({
|
|
837
845
|
logger: this.logger
|
|
838
|
-
}), this.stringSimilarity = t?.stringSimilarity ?? new
|
|
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
|
|
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
|
|
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
|
|
@@ -898,14 +906,14 @@ class j {
|
|
|
898
906
|
if (u)
|
|
899
907
|
return u;
|
|
900
908
|
}
|
|
901
|
-
throw new
|
|
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 =
|
|
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
|
|
929
|
+
class _ {
|
|
922
930
|
logger;
|
|
923
931
|
constructor(t) {
|
|
924
932
|
this.logger = t;
|
|
925
933
|
}
|
|
926
934
|
handle(t) {
|
|
927
|
-
if (t
|
|
935
|
+
if (W(t))
|
|
928
936
|
return t.pretty(this.logger), -1;
|
|
929
937
|
throw t;
|
|
930
938
|
}
|
|
931
939
|
}
|
|
932
|
-
class
|
|
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-
|
|
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 =
|
|
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
|
|
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
|
|
979
|
+
return new M(t);
|
|
972
980
|
}
|
|
973
981
|
newHelpCommand(t) {
|
|
974
|
-
return new
|
|
982
|
+
return new j(t);
|
|
975
983
|
}
|
|
976
984
|
newExceptionHandler(t) {
|
|
977
|
-
return new
|
|
985
|
+
return new _(t.logger);
|
|
978
986
|
}
|
|
979
987
|
constructor(t = {}) {
|
|
980
|
-
this.ctx = t.ctx, this.logger = t.logger ?? new
|
|
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
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
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
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
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
|
-
|
|
1028
|
-
|
|
1035
|
+
P as MissingRequiredOptionValue,
|
|
1036
|
+
B as StringSimilarity
|
|
1029
1037
|
};
|