bob-core 2.0.0-beta.9 → 2.0.0
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/README.md +57 -33
- package/dist/cjs/package-Blqq-jZJ.cjs +1 -0
- package/dist/cjs/src/Cli.d.ts +10 -11
- package/dist/cjs/src/Command.d.ts +11 -18
- package/dist/cjs/src/CommandIO.d.ts +5 -2
- package/dist/cjs/src/CommandParser.d.ts +13 -5
- package/dist/cjs/src/CommandRegistry.d.ts +13 -6
- package/dist/cjs/src/CommandSignatureParser.d.ts +5 -4
- package/dist/cjs/src/CommandWithSignature.d.ts +3 -3
- package/dist/cjs/src/ExceptionHandler.d.ts +1 -1
- package/dist/cjs/src/Logger.d.ts +1 -1
- package/dist/cjs/src/StringSimilarity.d.ts +26 -0
- package/dist/cjs/src/commands/HelpCommand.d.ts +1 -1
- package/dist/cjs/src/contracts/CommandOption.d.ts +3 -3
- package/dist/cjs/src/errors/BadCommandOption.d.ts +2 -1
- package/dist/cjs/src/errors/BadCommandParameter.d.ts +2 -1
- package/dist/cjs/src/errors/CommandNotFoundError.d.ts +2 -1
- package/dist/cjs/src/errors/InvalidOption.d.ts +2 -1
- package/dist/cjs/src/errors/MissingRequiredArgumentValue.d.ts +2 -1
- package/dist/cjs/src/errors/MissingRequiredOptionValue.d.ts +2 -1
- package/dist/cjs/src/index.d.ts +1 -0
- package/dist/cjs/src/index.js +17 -0
- package/dist/cjs/src/lib/types.d.ts +4 -2
- package/dist/cjs/src/options/HelpOption.d.ts +1 -1
- package/dist/esm/package-DbMvpGfM.js +33 -0
- package/dist/esm/src/Cli.d.ts +10 -11
- package/dist/esm/src/Command.d.ts +11 -18
- package/dist/esm/src/CommandIO.d.ts +5 -2
- package/dist/esm/src/CommandParser.d.ts +13 -5
- package/dist/esm/src/CommandRegistry.d.ts +13 -6
- package/dist/esm/src/CommandSignatureParser.d.ts +5 -4
- package/dist/esm/src/CommandWithSignature.d.ts +3 -3
- package/dist/esm/src/ExceptionHandler.d.ts +1 -1
- package/dist/esm/src/Logger.d.ts +1 -1
- package/dist/esm/src/StringSimilarity.d.ts +26 -0
- package/dist/esm/src/commands/HelpCommand.d.ts +1 -1
- package/dist/esm/src/contracts/CommandOption.d.ts +3 -3
- package/dist/esm/src/errors/BadCommandOption.d.ts +2 -1
- package/dist/esm/src/errors/BadCommandParameter.d.ts +2 -1
- package/dist/esm/src/errors/CommandNotFoundError.d.ts +2 -1
- package/dist/esm/src/errors/InvalidOption.d.ts +2 -1
- package/dist/esm/src/errors/MissingRequiredArgumentValue.d.ts +2 -1
- package/dist/esm/src/errors/MissingRequiredOptionValue.d.ts +2 -1
- package/dist/esm/src/index.d.ts +1 -0
- package/dist/esm/src/index.js +1029 -0
- package/dist/esm/src/lib/types.d.ts +4 -2
- package/dist/esm/src/options/HelpOption.d.ts +1 -1
- package/package.json +28 -21
- package/dist/cjs/index.d.ts +0 -2
- package/dist/cjs/index.js +0 -21
- package/dist/cjs/package-BpbpSdBI.cjs +0 -1
- package/dist/cjs/src/testFixtures.d.ts +0 -11
- package/dist/esm/index.d.ts +0 -2
- package/dist/esm/index.js +0 -1247
- package/dist/esm/package-CjHUTRfV.js +0 -31
- package/dist/esm/src/testFixtures.d.ts +0 -11
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
export type OptionPrimitive = '
|
|
1
|
+
export type OptionPrimitive = 'string' | 'number' | 'boolean' | ['string'] | ['number'];
|
|
2
2
|
export type OptionDefinition = {
|
|
3
3
|
type: OptionPrimitive;
|
|
4
4
|
description?: string;
|
|
5
5
|
alias?: string | Array<string>;
|
|
6
6
|
required?: boolean;
|
|
7
|
+
secret?: boolean;
|
|
7
8
|
default?: any;
|
|
8
9
|
variadic?: boolean;
|
|
9
10
|
};
|
|
10
11
|
export type Option = OptionPrimitive | OptionDefinition;
|
|
11
|
-
export type OptionType<O extends Option> = O extends '
|
|
12
|
+
export type OptionType<O extends Option> = O extends 'string' ? string : O extends 'number' ? number : O extends 'boolean' ? boolean : O extends Array<'string'> ? Array<string> : O extends Array<'number'> ? Array<number> : O extends {
|
|
12
13
|
type: infer T extends Option;
|
|
13
14
|
} ? OptionType<T> : never;
|
|
14
15
|
export type IsRequired<O extends Option> = O extends {
|
|
@@ -27,3 +28,4 @@ export type ArgumentsSchema = {
|
|
|
27
28
|
export type ArgumentsObject<Arguments extends ArgumentsSchema> = {
|
|
28
29
|
[Key in keyof Arguments]: OptionReturnType<Arguments[Key]>;
|
|
29
30
|
};
|
|
31
|
+
export type ContextDefinition = any;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CommandOption } from '../contracts/index.js';
|
|
2
1
|
import { Command } from '../Command.js';
|
|
2
|
+
import { CommandOption } from '../contracts/index.js';
|
|
3
3
|
import { OptionPrimitive } from '../lib/types.js';
|
|
4
4
|
export declare class HelpOption implements CommandOption<Command> {
|
|
5
5
|
type: OptionPrimitive;
|
package/package.json
CHANGED
|
@@ -1,53 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bob-core",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "BOB Core",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
],
|
|
6
|
+
"main": "./dist/cjs/src/index.js",
|
|
7
|
+
"module": "./dist/esm/src/index.js",
|
|
8
|
+
"types": "./dist/esm/src/index.d.ts",
|
|
9
|
+
"files": ["dist"],
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
|
-
"import":
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
]
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/esm/src/index.d.ts",
|
|
14
|
+
"default": "./dist/esm/src/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/cjs/src/index.d.ts",
|
|
18
|
+
"default": "./dist/cjs/src/index.js"
|
|
19
|
+
}
|
|
21
20
|
}
|
|
22
21
|
},
|
|
23
22
|
"scripts": {
|
|
24
23
|
"start": "node -r @swc-node/register debug/main.ts",
|
|
25
24
|
"build": "rimraf ./dist && vite build",
|
|
26
25
|
"typecheck": "tsc --noEmit",
|
|
27
|
-
"
|
|
28
|
-
"test": "vitest run"
|
|
26
|
+
"prepack": "npm run build",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"lint": "eslint .",
|
|
29
|
+
"lint:fix": "eslint . --fix"
|
|
29
30
|
},
|
|
30
31
|
"author": "Léo Hubert",
|
|
31
32
|
"license": "ISC",
|
|
32
33
|
"devDependencies": {
|
|
34
|
+
"@eslint/js": "^9.37.0",
|
|
33
35
|
"@faker-js/faker": "^10.0.0",
|
|
34
36
|
"@swc-node/register": "^1.11.1",
|
|
37
|
+
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
|
35
38
|
"@types/minimist": "^1.2.5",
|
|
36
39
|
"@types/node": "^20.14.5",
|
|
37
40
|
"@types/prompts": "^2.4.9",
|
|
38
41
|
"@types/string-similarity": "^4.0.2",
|
|
39
42
|
"@vitest/coverage-v8": "^3.2.4",
|
|
43
|
+
"eslint": "^9.37.0",
|
|
44
|
+
"eslint-config-prettier": "^10.1.8",
|
|
45
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
46
|
+
"prettier": "^3.6.2",
|
|
40
47
|
"rimraf": "^6.0.1",
|
|
41
48
|
"tsx": "^4.20.6",
|
|
42
|
-
"typescript": "^5.
|
|
43
|
-
"
|
|
49
|
+
"typescript": "^5.9.3",
|
|
50
|
+
"typescript-eslint": "^8.46.0",
|
|
51
|
+
"vite": "^7.2.7",
|
|
44
52
|
"vite-plugin-dts": "^4.5.4",
|
|
45
53
|
"vitest": "^3.2.4"
|
|
46
54
|
},
|
|
47
55
|
"dependencies": {
|
|
48
|
-
"chalk": "^
|
|
56
|
+
"chalk": "^4.1.2",
|
|
49
57
|
"minimist": "^1.2.8",
|
|
50
|
-
"prompts": "^2.4.2"
|
|
51
|
-
"string-similarity": "^4.0.4"
|
|
58
|
+
"prompts": "^2.4.2"
|
|
52
59
|
}
|
|
53
60
|
}
|
package/dist/cjs/index.d.ts
DELETED
package/dist/cjs/index.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const se=require("minimist"),v=require("prompts"),ie=require("node:fs"),D=require("path"),oe=require("string-similarity");function Q(r){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>r[t]})}}return e.default=r,Object.freeze(e)}const ae=Q(ie),le=Q(oe);class w extends Error{}const k=10,V=(r=0)=>e=>`\x1B[${e+r}m`,H=(r=0)=>e=>`\x1B[${38+r};5;${e}m`,W=(r=0)=>(e,t,n)=>`\x1B[${38+r};2;${e};${t};${n}m`,c={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};Object.keys(c.modifier);const ue=Object.keys(c.color),me=Object.keys(c.bgColor);[...ue,...me];function de(){const r=new Map;for(const[e,t]of Object.entries(c)){for(const[n,s]of Object.entries(t))c[n]={open:`\x1B[${s[0]}m`,close:`\x1B[${s[1]}m`},t[n]=c[n],r.set(s[0],s[1]);Object.defineProperty(c,e,{value:t,enumerable:!1})}return Object.defineProperty(c,"codes",{value:r,enumerable:!1}),c.color.close="\x1B[39m",c.bgColor.close="\x1B[49m",c.color.ansi=V(),c.color.ansi256=H(),c.color.ansi16m=W(),c.bgColor.ansi=V(k),c.bgColor.ansi256=H(k),c.bgColor.ansi16m=W(k),Object.defineProperties(c,{rgbToAnsi256:{value(e,t,n){return e===t&&t===n?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(t/255*5)+Math.round(n/255*5)},enumerable:!1},hexToRgb:{value(e){const t=/[a-f\d]{6}|[a-f\d]{3}/i.exec(e.toString(16));if(!t)return[0,0,0];let[n]=t;n.length===3&&(n=[...n].map(i=>i+i).join(""));const s=Number.parseInt(n,16);return[s>>16&255,s>>8&255,s&255]},enumerable:!1},hexToAnsi256:{value:e=>c.rgbToAnsi256(...c.hexToRgb(e)),enumerable:!1},ansi256ToAnsi:{value(e){if(e<8)return 30+e;if(e<16)return 90+(e-8);let t,n,s;if(e>=232)t=((e-232)*10+8)/255,n=t,s=t;else{e-=16;const u=e%36;t=Math.floor(e/36)/5,n=Math.floor(u/6)/5,s=u%6/5}const i=Math.max(t,n,s)*2;if(i===0)return 30;let o=30+(Math.round(s)<<2|Math.round(n)<<1|Math.round(t));return i===2&&(o+=60),o},enumerable:!1},rgbToAnsi:{value:(e,t,n)=>c.ansi256ToAnsi(c.rgbToAnsi256(e,t,n)),enumerable:!1},hexToAnsi:{value:e=>c.ansi256ToAnsi(c.hexToAnsi256(e)),enumerable:!1}}),c}const f=de(),_=(()=>{if(!("navigator"in globalThis))return 0;if(globalThis.navigator.userAgentData){const r=navigator.userAgentData.brands.find(({brand:e})=>e==="Chromium");if(r&&r.version>93)return 3}return/\b(Chrome|Chromium)\//.test(globalThis.navigator.userAgent)?1:0})(),G=_!==0&&{level:_},ce={stdout:G,stderr:G};function he(r,e,t){let n=r.indexOf(e);if(n===-1)return r;const s=e.length;let i=0,o="";do o+=r.slice(i,n)+e+t,i=n+s,n=r.indexOf(e,i);while(n!==-1);return o+=r.slice(i),o}function pe(r,e,t,n){let s=0,i="";do{const o=r[n-1]==="\r";i+=r.slice(s,o?n-1:n)+e+(o?`\r
|
|
2
|
-
`:`
|
|
3
|
-
`)+t,s=n+1,n=r.indexOf(`
|
|
4
|
-
`,s)}while(n!==-1);return i+=r.slice(s),i}const{stdout:U,stderr:Y}=ce,B=Symbol("GENERATOR"),C=Symbol("STYLER"),$=Symbol("IS_EMPTY"),z=["ansi","ansi","ansi256","ansi16m"],O=Object.create(null),ge=(r,e={})=>{if(e.level&&!(Number.isInteger(e.level)&&e.level>=0&&e.level<=3))throw new Error("The `level` option should be an integer from 0 to 3");const t=U?U.level:0;r.level=e.level===void 0?t:e.level},fe=r=>{const e=(...t)=>t.join(" ");return ge(e,r),Object.setPrototypeOf(e,x.prototype),e};function x(r){return fe(r)}Object.setPrototypeOf(x.prototype,Function.prototype);for(const[r,e]of Object.entries(f))O[r]={get(){const t=E(this,T(e.open,e.close,this[C]),this[$]);return Object.defineProperty(this,r,{value:t}),t}};O.visible={get(){const r=E(this,this[C],!0);return Object.defineProperty(this,"visible",{value:r}),r}};const P=(r,e,t,...n)=>r==="rgb"?e==="ansi16m"?f[t].ansi16m(...n):e==="ansi256"?f[t].ansi256(f.rgbToAnsi256(...n)):f[t].ansi(f.rgbToAnsi(...n)):r==="hex"?P("rgb",e,t,...f.hexToRgb(...n)):f[t][r](...n),ye=["rgb","hex","ansi256"];for(const r of ye){O[r]={get(){const{level:t}=this;return function(...n){const s=T(P(r,z[t],"color",...n),f.color.close,this[C]);return E(this,s,this[$])}}};const e="bg"+r[0].toUpperCase()+r.slice(1);O[e]={get(){const{level:t}=this;return function(...n){const s=T(P(r,z[t],"bgColor",...n),f.bgColor.close,this[C]);return E(this,s,this[$])}}}}const we=Object.defineProperties(()=>{},{...O,level:{enumerable:!0,get(){return this[B].level},set(r){this[B].level=r}}}),T=(r,e,t)=>{let n,s;return t===void 0?(n=r,s=e):(n=t.openAll+r,s=e+t.closeAll),{open:r,close:e,openAll:n,closeAll:s,parent:t}},E=(r,e,t)=>{const n=(...s)=>be(n,s.length===1?""+s[0]:s.join(" "));return Object.setPrototypeOf(n,we),n[B]=r,n[C]=e,n[$]=t,n},be=(r,e)=>{if(r.level<=0||!e)return r[$]?"":e;let t=r[C];if(t===void 0)return e;const{openAll:n,closeAll:s}=t;if(e.includes("\x1B"))for(;t!==void 0;)e=he(e,t.close,t.open),t=t.parent;const i=e.indexOf(`
|
|
5
|
-
`);return i!==-1&&(e=pe(e,s,n,i)),n+e+s};Object.defineProperties(x.prototype,O);const a=x();x({level:Y?Y.level:0});class ve extends w{constructor(e){let t=`Argument "${e.param}" value is invalid.`;e.reason?t+=` Reason: ${e.reason}`:t+=` Value: "${e.value}"`,super(t),this.param=e}pretty(e){e.log(` ${a.white.bgRed(" ERROR ")} Argument ${a.bold.yellow(this.param.param)} value is invalid. `),(this.param.value||this.param.reason)&&e.log(""),this.param.value&&e.log(` ${a.blue("Value")}: ${this.param.value}`),this.param.reason&&e.log(` ${a.yellow("Reason")}: ${this.param.reason}`)}}class F extends w{constructor(e){let t=`Option "${e.option}" value is invalid.`;e.reason?t+=` Reason: ${e.reason}`:t+=` Value: "${e.value}"`,super(t),this.param=e}pretty(e){e.log(` ${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.param.option)} value is invalid. `),(this.param.value||this.param.reason)&&e.log(""),this.param.value&&e.log(` ${a.blue("Value")}: ${this.param.value}`),this.param.reason&&e.log(` ${a.yellow("Reason")}: ${this.param.reason}`)}}function J(r){if(r==="string"||r==="secret"||r==="number")return null;if(r==="boolean")return!1;if(Array.isArray(r)&&r.length===1){if(r[0]==="string")return[];if(r[0]==="number")return[]}throw new Error("Invalid option type: "+r)}function K(r){return!Array.isArray(r)&&typeof r=="object"&&r.type?r.default!==void 0?r.default:J(r.type):J(r)}function y(r){return typeof r=="string"||Array.isArray(r)?{type:r,default:K(r),description:"",alias:[],required:!1,variadic:!1}:{type:r.type,default:r.default??K(r.type),description:r.description??"",alias:r.alias?Array.isArray(r.alias)?r.alias:[r.alias]:[],required:r.required??!1,variadic:r.variadic??!1}}class S extends w{constructor(e,t={}){super(`Invalid option ${e} in not recognized`),this.option=e,this.optionsSchema=t}pretty(e){const t=Object.entries(this.optionsSchema);if(t.length>0){e.log(`
|
|
6
|
-
${a.yellow("Available options")}:`);for(const[n,s]of t){const i=y(s),o=typeof i.alias=="string"?[i.alias]:i.alias,u=Array.isArray(i.type)?`[${i.type[0]}]`:i.type,m=`--${n}${o.length>0?o.map(l=>`, -${l}`).join(""):""}`,h=" ".repeat(30-m.length);e.log(` ${a.green(m)} ${h} ${i.description||"\b"} ${a.white(`(${u})`)}`)}e.log("")}e.log(`${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.option)} is not recognized.`)}}class X extends w{constructor(e){super(`Command "${e}" not found.`),this.command=e}pretty(e){e.log(`${a.bgRed(" ERROR ")} Command ${a.yellow(this.command)} not found.`)}}class j extends w{constructor(e){super(`Argument "${e}" is required.`),this.argument=e}pretty(e){e.log(`${a.white.bgRed(" ERROR ")} Argument ${a.bold.yellow(this.argument)} is required.`)}}class Z extends w{constructor(e){super(`Argument "${e}" is required.`),this.option=e}pretty(e){e.log(`${a.white.bgRed(" ERROR ")} Option ${a.bold.yellow(this.option)} is required.`)}}function A(r,e,t,n){if(r==null)return n??null;if(e==="string")return String(r);if(e==="number"){const s=Number(r);if(isNaN(s))throw new F({option:t,reason:`Expected a number, got "${r}"`});return s}if(e==="boolean")return typeof r=="boolean"?r:r==="true"||r==="1"?!0:r==="false"||r==="0"?!1:!!r;if(Array.isArray(e)){const s=e[0],i=Array.isArray(r)?r:[r];if(s==="string")return i.map(o=>String(o));if(s==="number")return i.map(o=>{const u=Number(o);if(isNaN(u))throw new F({option:t,reason:`Expected array of numbers, got "${o}" in array`});return u})}return r}class I{options;parsedOptions=null;arguments;parsedArguments=null;io;shouldPromptForMissingOptions=!0;constructor(e){this.options=e.options,this.arguments=e.arguments,this.io=e.io}init(e){const{_:t,...n}=se(e);return this.validateUnknownOptions(n),this.parsedOptions=this.handleOptions(n),this.parsedArguments=this.handleArguments(t),{options:this.parsedOptions,arguments:this.parsedArguments}}async validate(){for(const e in this.options)if(y(this.options[e]).required&&(this.parsedOptions?.[e]===void 0||this.parsedOptions?.[e]===null))throw new Z(e);for(const e in this.arguments){const t=y(this.arguments[e]),n=this.parsedArguments?.[e];if(t.required&&n==null){if(this.shouldPromptForMissingOptions){const s=await this.promptForArgument(e,t);if(s&&this.parsedArguments){this.parsedArguments[e]=A(s,t.type,e);continue}}throw new j(e)}if(t.required&&t.variadic&&Array.isArray(n)&&n.length===0){if(this.shouldPromptForMissingOptions){const s=await this.promptForArgument(e,t);if(s&&this.parsedArguments){this.parsedArguments[e]=A(s,t.type,e);continue}}throw new j(e)}}}option(e){if(!this.parsedOptions)throw new Error("Options have not been parsed yet. Call init() first.");return this.parsedOptions[e]}setOption(e,t){if(!this.parsedOptions)throw new Error("Options have not been parsed yet. Call init() first.");if(!(e in this.options))throw new S(e,this.options);this.parsedOptions[e]=t}argument(e){if(!this.parsedArguments)throw new Error("Arguments have not been parsed yet. Call init() first.");return this.parsedArguments[e]}setArgument(e,t){if(!this.parsedArguments)throw new Error("Arguments have not been parsed yet. Call init() first.");if(!(e in this.arguments))throw new S(e,this.arguments);this.parsedArguments[e]=t}validateUnknownOptions(e){const t=new Set;for(const n in this.options){t.add(n);const s=y(this.options[n]);for(const i of s.alias)t.add(i)}for(const n in e)if(!t.has(n))throw new S(n,this.options)}handleOptions(e){const t={};for(const n in this.options){const s=y(this.options[n]);t[n]=this.resolveOptionValue(n,s,e)}return t}handleArguments(e){const t={},n=[...e];for(const s in this.arguments){const i=y(this.arguments[s]);if(i.variadic){t[s]=this.handleVariadicArgument(s,i,n);continue}t[s]=this.resolveArgumentValue(s,i,n.shift())}return t}handleVariadicArgument(e,t,n){return n.length?A(n,t.type,e,t.default):t.default}resolveArgumentValue(e,t,n){return n===void 0?t.default:A(n,t.type,e,t.default)}resolveOptionValue(e,t,n){let s;const i=[e,...t.alias];for(const o of i)if(o in n){s=n[o];break}if(s===void 0){if(t.required)throw new F({option:e,reason:"Required option is missing"});return t.default}return A(s,t.type,e,t.default)}optionDefinitions(){const e={};for(const t in this.options)e[t]=y(this.options[t]);return e}argumentDefinitions(){const e={};for(const t in this.arguments)e[t]=y(this.arguments[t]);return e}availableOptions(){return Object.keys(this.options)}availableArguments(){return Object.keys(this.arguments)}disablePrompting(){return this.shouldPromptForMissingOptions=!1,this}async promptForArgument(e,t){if(!Array.isArray(t.type)&&!["string","number","secret"].includes(t.type))return null;let n=`${a.yellow.bold(e)} is required`;return t.description&&(n+=`: ${a.gray(`(${t.description})`)}`),n+=`
|
|
7
|
-
`,Array.isArray(t.type)?(n+=`Please provide one or more values, separated by commas:
|
|
8
|
-
`,await this.io.askForList(n,void 0,{validate:s=>s.length?!0:"Please enter at least one value"})):await this.io.askForInput(n,void 0,{type:t.type==="number"?"number":t.type==="secret"?"password":"text",validate:s=>{if(t.type==="number"){const i=Number(s);if(isNaN(i))return"Please enter a valid number"}else if(t.type==="string"&&(typeof s!="string"||!s.length))return"Please enter a valid text";return!0}})}}function N(r){return new Array(r+5).join(" ")}class ee{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 e=this.parser.argumentDefinitions(),t=this.parser.optionDefinitions(),n=Object.entries(e),s=Object.entries(t),i=s.map(([l,d])=>{const p=Array.isArray(d.alias)?d.alias:d.alias?[d.alias]:[];return{name:l,...d,optionWithAlias:`--${l}${p.map(g=>`, -${g}`).join("")}`}}),o=n.filter(([,l])=>l.required);this.io.log(a.yellow("Description:")),this.io.log(` ${this.description}
|
|
9
|
-
`),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(...i.map(l=>l.optionWithAlias.length),0),m=Math.max(...n.map(([l])=>l.length),0),h=m>u?m:u;if(n.length>0){this.io.log(`
|
|
10
|
-
${a.yellow("Arguments")}:`);for(const[l,d]of n){const p=N(h-l.length);let g=` ${a.green(l)} ${p} ${d.description??"\b"}`;if(d.default!==void 0&&!d.required){const re=(Array.isArray(d.type)?`[${d.type[0]}]`:d.type)==="array"||Array.isArray(d.type)?JSON.stringify(d.default):d.default;g+=` ${a.yellow(`[default: ${re}]`)}`}d.variadic&&(g+=` ${a.white("(variadic)")}`),this.io.log(g)}}if(s.length>0){this.io.log(`
|
|
11
|
-
${a.yellow("Options")}:`);for(const l of i){const d=N(h-l.optionWithAlias.length);let p=`${a.green(l.optionWithAlias)} ${d} ${l.description??"\b"}`;if(l.type){const g=Array.isArray(l.type)?`[${l.type[0]}]`:l.type;p+=` ${a.white(`(${g})`)}`}if(l.default!==void 0&&!l.required){const L=(Array.isArray(l.type)?`[${l.type[0]}]`:l.type)==="array"||Array.isArray(l.type)?JSON.stringify(l.default):l.default;p+=` ${a.yellow(`[default: ${L}]`)}`}this.io.log(p)}}if(this.commandsExamples.length>0){this.io.log(`
|
|
12
|
-
${a.yellow("Examples")}:`);let l=process.argv[0].split("/").pop();l==="node"&&(l+=" "+process.argv[1].split("/").pop());for(const[d,p]of this.commandsExamples.entries())d>0&&this.io.log(""),this.io.log(` ${p.description}
|
|
13
|
-
`),this.io.log(` ${a.green(`${l} ${p.command}`)}`)}return-1}}class M{logger;constructor(e){this.logger=e}log(...e){this.logger.log(...e)}info(...e){this.logger.info(...e)}warn(...e){this.logger.warn(...e)}error(...e){this.logger.error(...e)}debug(...e){this.logger.debug(...e)}async askForConfirmation(e="Do you want to continue?",t){return(await v({type:"confirm",name:"value",message:e,initial:t??!1})).value}async askForInput(e,t,n){return(await v({type:"text",name:"value",message:e,initial:t,...n}))?.value??null}async askForDate(e,t,n){return(await v({type:"date",name:"value",message:e,initial:t,...n}))?.value??null}async askForList(e,t,n){return(await v({type:"list",name:"value",message:e,initial:t,...n}))?.value??null}async askForToggle(e,t,n){return(await v({type:"toggle",name:"value",message:e,initial:t,...n}))?.value??null}async askForSelect(e,t,n){if(t.length===0)throw new Error("No options provided");const s=[];for(const o of t)typeof o=="string"?s.push({title:o,value:o}):s.push(o);return(await v({type:"select",name:"value",message:e,choices:s,...n}))?.value??null}newLoader(e="",t=["⠙","⠘","⠰","⠴","⠤","⠦","⠆","⠃","⠋","⠉"],n=100){let s=e,i=null,o=0;const u=setInterval(function(){i&&(process.stdout.write(new TextEncoder().encode("\r"+" ".repeat(i.length+5)+"\r")),i=null),process.stdout.write(new TextEncoder().encode("\r"+t[o++]+" "+s)),o=o%t.length},n),m=()=>{clearInterval(u),process.stdout.write(new TextEncoder().encode("\r"+" ".repeat(s.length+5)+"\r"))};return{[Symbol.dispose]:m,[Symbol.asyncDispose]:m,updateText:h=>{i=s,s=h},stop:m}}}class R{_command;description="";group;commandsExamples=[];get command(){return this._command}ctx;io;logger;parser;disablePromptingFlag=!1;_preHandler;_handler;tmp;defaultOptions(){return[new ee]}newCommandParser(e){return new I({io:e.io,options:e.options,arguments:e.arguments})}newCommandIO(e){return new M(e.logger)}constructor(e,t){this._command=e,this.description=t?.description??"",this.group=t?.group,this.tmp={options:t?.options??{},arguments:t?.arguments??{}};const n=this.defaultOptions();if(n.length>0)for(const s of n)this.tmp.options[s.option]=s}disablePrompting(){return this.disablePromptingFlag=!0,this}preHandler(e){return this._preHandler=e,this}handler(e){return this._handler=e,this}options(e){return this.tmp={options:{...this.tmp?.options??{},...e},arguments:this.tmp?.arguments??{}},this}arguments(e){return this.tmp={options:this.tmp?.options??{},arguments:{...this.tmp?.arguments??{},...e}},this}async run(e){if(!this._handler&&!this.handle)throw new Error(`No handler defined for command ${this.command||"(unknown)"}`);let t;if(this.ctx=e.ctx,this.logger=e.logger,this.io=this.newCommandIO({logger:e.logger}),e&&"args"in e){const i=this.tmp?.options??{};for(const o of this.defaultOptions())o.option in i||(i[o.option]=o);this.parser=this.newCommandParser({io:this.io,options:i,arguments:this.tmp?.arguments??{}}),t=this.parser.init(e.args);for(const o of this.defaultOptions())if(t.options[o.option]===!0){const u=await o.handler.call(this);if(u&&u!==0)return u}this.disablePromptingFlag&&this.parser.disablePrompting(),await this.parser.validate()}else t={options:e.options,arguments:e.arguments};const n=this.preHandle?await this.preHandle():null;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(e.ctx,t)??0}}class b extends I{command;constructor(e){const t=b.parseSignature(e.signature,e.helperDefinitions,e.defaultOptions);super({io:e.io,options:t.options,arguments:t.arguments}),this.command=t.command}static parseSignature(e,t,n){const[s,...i]=e.split(/\{(.*?)\}/g).map(m=>m.trim()).filter(Boolean),o={},u={};for(const m of i){const{name:h,isOption:l,definition:d}=b.parseParamSignature(m,t);l?o[h]=d:u[h]=d}for(const m of n)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:s,options:o,arguments:u}}static parseParamSignature(e,t){let n=e,s=!1;const i={required:!0,type:"string",description:void 0,default:null,variadic:!1};if(n.includes(":")){const[o,u]=n.split(":");n=o.trim(),i.description=u.trim()}if(n.includes("=")){const[o,u]=n.split("=");n=o.trim(),i.default=u.trim(),i.required=!1,i.default.length?i.default==="true"?(i.default=!0,i.type="boolean"):i.default==="false"&&(i.default=!1,i.type="boolean"):i.default=null}else n.startsWith("--")&&(i.required=!1,i.default=!1,i.type="boolean");if(n.includes("|")){const[o,...u]=n.split("|");n=o.trim(),i.alias=u.map(m=>m.trim())}return n.startsWith("--")&&(s=!0,n=n.slice(2)),i.default==="*"&&(i.default=[],i.type=["string"]),n.endsWith("?")&&(i.required=!1,n=n.slice(0,-1)),n.endsWith("*")&&(i.type=["string"],i.variadic=!0,i.default=[],n=n.slice(0,-1)),i.description=i.description??t[n]??t[`--${n}`],{name:n,isOption:s,definition:i}}}class Ce extends R{helperDefinitions={};get command(){return this.parser?this.parser.command:this.signature.split(" ")[0]}newCommandParser(e){return new b({io:e.io,signature:this.signature,helperDefinitions:this.helperDefinitions,defaultOptions:this.defaultOptions()})}constructor(){super("")}option(e,t=null){return this.parser instanceof b?this.parser.option(e)??t:t}argument(e,t=null){return this.parser instanceof b?this.parser.argument(e)??t:t}async askForConfirmation(...e){return this.io.askForConfirmation(...e)}async askForInput(...e){return this.io.askForInput(...e)}async askForSelect(...e){return this.io.askForSelect(...e)}newLoader(...e){return this.io.newLoader(...e)}}class q{level;constructor(e={}){this.level=e.level??"info"}shouldLog(e){const t=["debug","info","warn","error"],n=t.indexOf(this.level);return t.indexOf(e)>=n}setLevel(e){this.level=e}getLevel(){return this.level}log(...e){console.log(...e)}info(...e){this.shouldLog("info")&&console.log(...e)}warn(...e){this.shouldLog("warn")&&console.warn(...e)}error(...e){this.shouldLog("error")&&console.error(...e)}debug(...e){this.shouldLog("debug")&&console.log(...e)}}class te{commands={};io;logger;get CommandIOClass(){return M}constructor(e){this.logger=e??new q,this.io=new this.CommandIOClass(this.logger)}getAvailableCommands(){return Object.keys(this.commands)}getCommands(){return Object.values(this.commands)}importFile=async e=>(await import(e)).default;commandResolver=async e=>{let t=await this.importFile(e);if(!t)throw new Error(`The command at path ${e} does not have a default export.`);return t?.default&&(t=t.default),typeof t=="function"?new t:t instanceof R?t:null};withCommandResolver(e){return this.commandResolver=e,this}withFileImporter(e){return this.importFile=e,this}registerCommand(e,t=!1){const n=e.command;if(!n)throw new Error("Command signature is invalid, it must have a command name.");if(!t&&this.commands[n])throw new Error(`Command ${n} already registered.`);this.commands[n]=e}async loadCommandsPath(e){for await(const t of this.listCommandsFiles(e))try{const n=await this.commandResolver(t);n instanceof R&&this.registerCommand(n)}catch(n){throw new Error(`Command ${t} failed to load. ${n}`,{cause:n})}}async runCommand(e,t,...n){const s=typeof t=="string"?this.commands[t]:t,i=typeof t=="string"?t:s.command;if(!s){const o=await this.suggestCommand(i);return o?await this.runCommand(e,o,...n):1}return await s.run({ctx:e,logger:this.logger,args:n})??0}async suggestCommand(e){const t=this.getAvailableCommands(),{bestMatch:n,bestMatchIndex:s,ratings:i}=le.findBestMatch(e,t),o=i.filter(u=>u.rating>.3).map(u=>u.target);if(n.rating>0&&o.length<=1||n.rating>.7&&o.length>1){const u=t[s];return await this.askRunSimilarCommand(e,u)?u:null}if(o.length){this.io.error(`${a.bgRed(" ERROR ")} Command ${a.yellow(e)} not found.
|
|
14
|
-
`);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 X(e)}async askRunSimilarCommand(e,t){return this.io.error(`${a.bgRed(" ERROR ")} Command ${a.yellow(e)} not found.
|
|
15
|
-
`),this.io.askForConfirmation(`${a.green(`Do you want to run ${a.yellow(t)} instead?`)} `)}async*listCommandsFiles(e){const t=ae.readdirSync(e,{withFileTypes:!0});for(const n of t){const s=D.resolve(e,n.name);if(n.isDirectory())yield*this.listCommandsFiles(D.resolve(e,n.name));else{if(!s.endsWith(".ts")&&!s.endsWith(".js")&&!s.endsWith(".mjs")&&!s.endsWith(".cjs"))continue;yield s}}}}class Oe extends R{constructor(e){super("help",{description:a.bold("Show help information about the CLI and its commands")}),this.opts=e}async handle(){const e=this.opts.commandRegistry.getCommands(),t=this.opts.cliName??"Bob CLI",n=this.opts.cliVersion??"0.0.0",s=(await Promise.resolve().then(()=>require("./package-BpbpSdBI.cjs")))?.default?.version??"0.0.0";this.io.log(`${t} ${a.green(n)} (core: ${a.yellow(s)})
|
|
16
|
-
|
|
17
|
-
${a.yellow("Usage")}:
|
|
18
|
-
command [options] [arguments]
|
|
19
|
-
|
|
20
|
-
${a.yellow("Available commands")}:
|
|
21
|
-
`);const i=Math.max(...e.map(m=>m.command.length))??0,o={};for(const m of e){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((p,g)=>p.command.toLowerCase().localeCompare(g.command.toLowerCase()));for(const p of d){let g=N(i-p.command.length);l&&(g=g.slice(2)),this.io.log(`${l?" ":""}${a.green(p.command)} ${g} ${p.description}`)}}}}class ne{logger;constructor(e){this.logger=e}handle(e){if(e instanceof w)return e.pretty(this.logger),-1;throw e}}class Ae{ctx;logger;commandRegistry;exceptionHandler;helpCommand;newCommandRegistry(e){return new te(e.logger)}newHelpCommand(e){return new Oe(e)}newExceptionHandler(e){return new ne(e.logger)}constructor(e={}){this.ctx=e.ctx,this.logger=e.logger??new q,this.commandRegistry=this.newCommandRegistry({logger:this.logger}),this.exceptionHandler=this.newExceptionHandler({logger:this.logger}),this.helpCommand=this.newHelpCommand({cliName:e.name,cliVersion:e.version,commandRegistry:this.commandRegistry})}withCommandResolver(e){return this.commandRegistry.withCommandResolver(e),this}withFileImporter(e){return this.commandRegistry.withFileImporter(e),this}async withCommands(...e){for(const t of e)typeof t=="string"?await this.commandRegistry.loadCommandsPath(t):typeof t=="function"?this.registerCommand(new t):this.registerCommand(t)}async runCommand(e,...t){return e?await this.commandRegistry.runCommand(this.ctx,e,...t).catch(this.exceptionHandler.handle.bind(this.exceptionHandler)):await this.runHelpCommand()}async runHelpCommand(){return await this.runCommand(this.helpCommand)}registerCommand(e){this.commandRegistry.registerCommand(e)}}exports.BadCommandOption=F;exports.BadCommandParameter=ve;exports.BobError=w;exports.Cli=Ae;exports.Command=R;exports.CommandIO=M;exports.CommandNotFoundError=X;exports.CommandParser=I;exports.CommandRegistry=te;exports.CommandSignatureParser=b;exports.CommandWithSignature=Ce;exports.ExceptionHandler=ne;exports.HelpOption=ee;exports.InvalidOption=S;exports.Logger=q;exports.MissingRequiredArgumentValue=j;exports.MissingRequiredOptionValue=Z;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="bob-core",s="2.0.0-beta.9",t="BOB Core",i="module",n=!1,r=["dist/**"],o={".":{import:"./dist/esm/index.js",require:"./dist/cjs/index.js"}},c={"*":{"*":["./dist/cjs/*.d.ts"]}},d={start:"node -r @swc-node/register debug/main.ts",build:"rimraf ./dist && vite build",typecheck:"tsc --noEmit",prepare:"npm run build",test:"vitest run"},p="Léo Hubert",a="ISC",m={"@faker-js/faker":"^10.0.0","@swc-node/register":"^1.11.1","@types/minimist":"^1.2.5","@types/node":"^20.14.5","@types/prompts":"^2.4.9","@types/string-similarity":"^4.0.2","@vitest/coverage-v8":"^3.2.4",rimraf:"^6.0.1",tsx:"^4.20.6",typescript:"^5.7.3",vite:"^7.1.6","vite-plugin-dts":"^4.5.4",vitest:"^3.2.4"},l={chalk:"^5.6.2",minimist:"^1.2.8",prompts:"^2.4.2","string-similarity":"^4.0.4"},u={name:e,version:s,description:t,type:i,sideEffects:n,files:r,exports:o,typesVersions:c,scripts:d,author:p,license:a,devDependencies:m,dependencies:l};exports.author=p;exports.default=u;exports.dependencies=l;exports.description=t;exports.devDependencies=m;exports.exports=o;exports.files=r;exports.license=a;exports.name=e;exports.scripts=d;exports.sideEffects=n;exports.type=i;exports.typesVersions=c;exports.version=s;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Mocked } from 'vitest';
|
|
2
|
-
import { Logger } from './Logger.js';
|
|
3
|
-
export type TestLogger = Mocked<Logger>;
|
|
4
|
-
export declare function newTestLogger(): TestLogger;
|
|
5
|
-
/**
|
|
6
|
-
* Creates test fixtures with a mocked logger
|
|
7
|
-
* @returns Object containing mocked logger instance
|
|
8
|
-
*/
|
|
9
|
-
export declare function newFixtures(): {
|
|
10
|
-
logger: TestLogger;
|
|
11
|
-
};
|
package/dist/esm/index.d.ts
DELETED