@visulima/cerebro 3.0.6 → 3.1.1
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/CHANGELOG.md +14 -0
- package/LICENSE.md +5 -811
- package/README.md +41 -0
- package/dist/commands/completion-command.d.ts +1 -1
- package/dist/commands/completion-command.js +5 -5
- package/dist/commands/help-command.d.ts +1 -1
- package/dist/commands/help-command.js +1 -1
- package/dist/commands/readme-command.d.ts +1 -1
- package/dist/commands/readme-command.js +20 -20
- package/dist/commands/version-command.d.ts +1 -1
- package/dist/commands/version-command.js +1 -1
- package/dist/index.d.ts +284 -7
- package/dist/index.js +1 -1
- package/dist/logger/create-pail-logger.d.ts +36 -1
- package/dist/logger/create-pail-logger.js +1 -1
- package/dist/packem_chunks/has-new-version.js +1 -1
- package/dist/packem_shared/Cerebro-B02RU3RC.js +4 -0
- package/dist/packem_shared/InvalidArgumentChoiceError-BpovuqrZ.js +1 -0
- package/dist/packem_shared/MissingArgumentError-D78kza2a.js +1 -0
- package/dist/packem_shared/SurplusArgumentError-BLwT9lo0.js +1 -0
- package/dist/packem_shared/VERBOSITY_DEBUG-D7HfSD5l.js +1 -0
- package/dist/packem_shared/VisulimaError-BDqtOVL5-Db_MJ_p7.js +1 -0
- package/dist/packem_shared/VisulimaError-CuhG0hlQ.js +76 -0
- package/dist/packem_shared/cerebro-error-Dv3FuXO8.js +1 -0
- package/dist/packem_shared/{command.d-B_G9vIYJ.d.ts → command.d-Dz7hkMI0.d.ts} +160 -4
- package/dist/packem_shared/constants-BKuEbBw1-BRv49X2l.js +1 -0
- package/dist/packem_shared/defineCommand-C_isHeEs.js +1 -0
- package/dist/packem_shared/format-positional-usage-DWL9qN10.js +6 -0
- package/dist/packem_shared/format-user-facing-error-Cb7ySnUi.js +2 -0
- package/dist/packem_shared/lazyNamed-BKSCmVsV.js +1 -0
- package/dist/packem_shared/renderError-CIIYTTfx-BdX-afLI.js +27 -0
- package/dist/packem_shared/runtime-process-BN-eTlwy.js +1 -0
- package/dist/plugins/error-handler-plugin.d.ts +1 -1
- package/dist/plugins/error-handler-plugin.js +1 -1
- package/dist/plugins/runtime-version-check-plugin.d.ts +1 -1
- package/dist/plugins/runtime-version-check-plugin.js +1 -1
- package/dist/plugins/update-notifier/update-notifier-plugin.d.ts +1 -1
- package/dist/plugins/update-notifier/update-notifier-plugin.js +1 -1
- package/dist/util/general/heap-tuning.js +1 -1
- package/package.json +4 -4
- package/dist/packem_shared/Cerebro-58LHN3_T.js +0 -4
- package/dist/packem_shared/VERBOSITY_DEBUG-XPultrIA.js +0 -1
- package/dist/packem_shared/VisulimaError-DTMgXonA-CzaryRgZ.js +0 -1
- package/dist/packem_shared/VisulimaError-k1qGkvab.js +0 -76
- package/dist/packem_shared/cerebro-error-DWpjBY_M.js +0 -1
- package/dist/packem_shared/index-Dpm7gUHe.js +0 -29
- package/dist/packem_shared/lazyNamed-DMUm8mZe.js +0 -1
- package/dist/packem_shared/renderError-BISXNU8L-B47ZikMV.js +0 -27
- package/dist/packem_shared/runtime-process-BEw54Ar-.js +0 -1
- package/dist/packem_shared/split-by-case-BZ6XOTIf.js +0 -1
package/README.md
CHANGED
|
@@ -158,6 +158,46 @@ You should see help output and command execution based on the options provided:
|
|
|
158
158
|
|
|
159
159
|

|
|
160
160
|
|
|
161
|
+
### Typed commands with `defineCommand`
|
|
162
|
+
|
|
163
|
+
`options` and `env` can also be given as records keyed by name. Wrap the command in
|
|
164
|
+
`defineCommand` and the toolbox types are inferred from those definitions — no separate
|
|
165
|
+
options interface to keep in sync, and a renamed option becomes a compile error rather
|
|
166
|
+
than a silent `undefined`. `arguments` stays an array, because slot order is
|
|
167
|
+
load-bearing, and its names stay typed without an `as const`:
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
import { Cerebro, defineCommand } from "@visulima/cerebro";
|
|
171
|
+
|
|
172
|
+
const build = defineCommand({
|
|
173
|
+
name: "build",
|
|
174
|
+
description: "Build the project",
|
|
175
|
+
arguments: [{ name: "target", type: String, required: true, description: "Build target" }],
|
|
176
|
+
options: {
|
|
177
|
+
"output-dir": { alias: "o", type: String, defaultValue: "dist" },
|
|
178
|
+
production: { alias: "p", type: Boolean },
|
|
179
|
+
tags: { type: String, multiple: true },
|
|
180
|
+
},
|
|
181
|
+
env: {
|
|
182
|
+
NODE_ENV: { type: String },
|
|
183
|
+
},
|
|
184
|
+
execute: ({ args, env, logger, options }) => {
|
|
185
|
+
args.target; // string — required
|
|
186
|
+
options.outputDir; // string — has a defaultValue
|
|
187
|
+
options.production; // boolean | undefined
|
|
188
|
+
options.tags; // string[] | undefined
|
|
189
|
+
env.nodeEnv; // string | undefined
|
|
190
|
+
|
|
191
|
+
logger.info(`Building ${args.target} into ${options.outputDir}`);
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
new Cerebro("my-cli").addCommand(build);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The array form of `options`/`env` and the single `argument` field keep working unchanged —
|
|
199
|
+
`defineCommand`, the record forms, and `arguments` are all purely additive.
|
|
200
|
+
|
|
161
201
|
## Lazy commands
|
|
162
202
|
|
|
163
203
|
For CLIs with many subcommands or heavy per-command dependencies, you can defer importing each handler until the command is actually invoked. Declare the metadata inline and point `loader` at a dynamic `import()`:
|
|
@@ -194,6 +234,7 @@ When your command's `execute` function is called, it receives a toolbox object w
|
|
|
194
234
|
- **`console`**: Alias for `logger`. Use it when porting goke-style code or when a `console`-named parameter reads more naturally.
|
|
195
235
|
- **`options`**: Parsed command-line options (camelCase keys)
|
|
196
236
|
- **`argument`**: Array of positional arguments
|
|
237
|
+
- **`args`**: Named positional arguments (camelCase keys) from the command's `arguments: [ ... ]` definitions; empty when none are declared
|
|
197
238
|
- **`env`**: Environment variables (camelCase keys) processed from the command's `env: [...]` definitions
|
|
198
239
|
- **`fs`**: Injected filesystem adapter (subset of `node:fs/promises`). Swap via `CliOptions.fs` for tests or sandboxed runtimes.
|
|
199
240
|
- **`process`**: Runtime snapshot — `cwd`, `env`, `argv`, `stdin`, `exit`, `platform`, `arch`. Prefer this over the global `process` so commands stay portable across Node, Deno, Bun, and mocked test runtimes.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`))}}const
|
|
3
|
-
`);e.info(
|
|
4
|
-
`)),
|
|
5
|
-
`))}}},name:"completion",options:[{defaultOption:!0,defaultValue:
|
|
1
|
+
import{C as u}from"../packem_shared/cerebro-error-Dv3FuXO8.js";class d extends u{troubleshooting;constructor(t,n,o=[]){super(t,n,{troubleshooting:o}),this.name="CompletionError",this.troubleshooting=o,o.length>0&&(this.hint=o.join(`
|
|
2
|
+
`))}}const c=["bash","zsh","fish","powershell"],h=["node","bun","deno"],f=e=>"Deno"in e,S=e=>"Bun"in e,p=()=>f(globalThis)?"deno":S(globalThis)?"bun":"node",m=e=>{const n=e?.starshipShell??e?.shell;if(n){const s=n.toLowerCase();if(s.includes("zsh"))return"zsh";if(s.includes("bash"))return"bash";if(s.includes("fish"))return"fish"}const o=e?.psModulePath,i=e?.prompt;if(o||i?.includes("PS"))return"powershell";if(e?.comSpec?.toLowerCase().includes("cmd.exe"))return"bash"},b=async()=>(await import("@bomb.sh/tab")).default,g=(e,t)=>{for(const n of t)n.hidden||(n.name&&e.option(n.name,n.description??""),n.alias&&e.option(n.alias,n.description??""))},w=(e,t)=>{for(const[n,o]of t){if(o.name!==n||o.hidden)continue;const i=e.command(o.name,o.description??"");o.options&&g(i,o.options)}},$=e=>{if(!c.includes(e))throw new d(`Invalid shell type: ${e}`,"INVALID_SHELL",[`Valid shells are: ${c.join(", ")}`,"Shell will be auto-detected if not specified"])},y=e=>{if(e&&!h.includes(e))throw new d(`Invalid runtime: ${e}`,"INVALID_RUNTIME",[`Valid runtimes are: ${h.join(", ")}`,"Runtime will be auto-detected if not specified"])},C=(e,t)=>{e.error("Could not detect current shell");const n=[`Usage: ${t} completion --shell=<bash|zsh|fish|powershell> [--runtime=<node|bun|deno>]`,"","Examples:"," # Install completions for zsh:",` ${t} completion --shell=zsh > ~/.${t}-completion.zsh`,` echo 'source ~/.${t}-completion.zsh' >> ~/.zshrc`,""," # Install completions for bash with custom runtime:",` ${t} completion --shell=bash --runtime=bun > ~/.${t}-completion.bash`,` echo 'source ~/.${t}-completion.bash' >> ~/.bashrc`,""," # Install completions for fish:",` ${t} completion --shell=fish > ~/.config/fish/completions/${t}.fish`].join(`
|
|
3
|
+
`);e.info(n)},L={description:"Generate shell completion scripts",env:[{description:"Shell path (Unix-like systems). Used for shell detection.",name:"SHELL",type:String},{description:"Starship shell configuration. Takes precedence over SHELL for detection.",name:"STARSHIP_SHELL",type:String},{description:"PowerShell module path (Windows). Used for PowerShell detection.",name:"PSModulePath",type:String},{description:"Command prompt variable (Windows). Used for PowerShell detection.",name:"PROMPT",type:String},{description:"Command processor (Windows). Used for Windows Command Prompt detection.",name:"ComSpec",type:String}],execute:async({env:e,logger:t,options:n,runtime:o})=>{const i=o.getCliName(),l=n.shell??m(e);if(!l){C(t,i);return}try{$(l),y(n.runtime);const s=await b();w(s,o.getCommands());const r=`${n.runtime??p()} ${i}`;s.setup(i,r,l)}catch(s){if(s instanceof d){const a=[`Failed to generate completion script: ${s.message}`,`Error code: ${s.code}`];throw s.troubleshooting.length>0&&a.push("","Troubleshooting:",...s.troubleshooting.map(r=>` • ${r}`)),t.error(a.join(`
|
|
4
|
+
`)),s}else{const r=["Failed to generate completion script",`Error: ${s instanceof Error?s.message:String(s)}`,"","Troubleshooting:"," • Ensure @bomb.sh/tab is installed: pnpm add @bomb.sh/tab",` • Verify shell is supported: ${c.join(", ")}`,` • Verify runtime is supported: ${h.join(", ")}`," • Check that your CLI name is correct"];t.error(r.join(`
|
|
5
|
+
`))}}},name:"completion",options:[{defaultOption:!0,defaultValue:m(),description:"Shell type (bash, zsh, fish, powershell). Defaults to current shell if detected.",name:"shell",type:String,typeLabel:"{underline shell}"},{defaultValue:p(),description:"JavaScript runtime (node, bun, deno). Defaults to current runtime if detected.",name:"runtime",type:String,typeLabel:"{underline runtime}"}]};export{L as default};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { O as OptionDefinition, A as ArgumentDefinition, C as Command, T as Toolbox } from "../packem_shared/command.d-
|
|
1
|
+
import { O as OptionDefinition, A as ArgumentDefinition, C as Command, T as Toolbox } from "../packem_shared/command.d-Dz7hkMI0.js";
|
|
2
2
|
import '@visulima/tabular';
|
|
3
3
|
declare class HelpCommand<TLogger extends Console = Console> implements Command<OptionDefinition<string>, TLogger> {
|
|
4
4
|
argument: ArgumentDefinition<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{inverse as
|
|
1
|
+
import{inverse as d,cyan as f,green as h,yellow as y}from"@visulima/colorize";import{t as v,c as b,f as E}from"../packem_shared/format-positional-usage-DWL9qN10.js";const N=[{defaultValue:"32",description:"Controls the verbosity level of output. Valid values: '16' (quiet), '32' (normal), '64' (verbose), '128' (debug)",name:"CEREBRO_OUTPUT_LEVEL",type:String},{description:"Sets the minimum required Node.js version. Overrides the default minimum version check",name:"CEREBRO_MIN_NODE_VERSION",type:Number},{defaultValue:!1,description:"When set, disables the update notifier check",name:"NO_UPDATE_NOTIFIER",type:Boolean},{description:"Standard Node.js environment variable. When set to 'test', disables update notifier",name:"NODE_ENV",type:String},{defaultValue:!1,description:"When set, enables debug output (same as --debug flag)",name:"DEBUG",type:Boolean},{description:"Sets the terminal width for table rendering. Useful for testing and consistent output",name:"CEREBRO_TERMINAL_WIDTH",type:Number}],$="__Other",C=r=>r.charAt(0).toUpperCase()+r.slice(1),w=(r,s,l,o)=>{r.debug("no command given, printing general help...");let m=[...new Set(l.values())].filter(t=>!t.hidden);o&&(m=m.filter(t=>t.group===o));const e=m.reduce((t,i)=>{const p=i.group??$;return t[p]??=[],t[p].push(i),t},{}),a=t=>t.map(i=>{let p="";typeof i.alias=="string"?p=i.alias:Array.isArray(i.alias)&&(p=i.alias.join(", ")),p!==""&&(p=` [${p}]`);let u=i.name;return i.commandPath&&i.commandPath.length>0&&(u=`${i.commandPath.join(" ")} ${i.name}`),[`${h(u)}${p}`,i.description??""]});(r.raw??r.log)(b([{content:`${f(s.getCliName())} ${h("<command>")} [positional arguments] ${y("[options]")}`,header:d.cyan(" Usage ")},...Object.keys(e).map(t=>{const i=o?` ${C(o)}`:"";return{content:a(e[t]),header:t===$||o?d.green(` Available${i} Commands `):` ${d.green(` ${C(t)} `)}`}}),l.has("help")?{header:d.yellow(" Command Options "),optionList:l.get("help").options?.filter(t=>!t.hidden)}:void 0,{header:d.yellow(" Global Options "),optionList:s.getGlobalOptions()},{content:N.filter(t=>!t.hidden).map(t=>[t.name,t.description??""]),header:d.magenta(" Environment Variables ")},{content:`Run "${f(s.getCliName())} ${h("help <command>")}" or "${f(s.getCliName())} ${h("<command>")} ${y("--help")}" for help with a specific command.`,raw:!0}].filter(Boolean)))},P=(r,s)=>{const l=[];for(const o of r.values()){if(o.hidden)continue;const m=o.commandPath??[];if(m.length!==s.length)continue;let e=!0;for(const[a,t]of s.entries())if(m[a]!==t){e=!1;break}e&&l.push(o)}return l},O=(r,s,l,o)=>{const m=l.join(" "),e=[{content:`${f(s.getCliName())} ${h(m)} ${h("<subcommand>")} [positional arguments] ${y("[options]")}`,header:d.cyan(" Usage ")},{content:o.map(a=>{const t=[...a.commandPath??[],a.name].join(" ");return[h(t),a.description??""]}),header:d.green(" Subcommands ")},{header:d.yellow(" Global Options "),optionList:s.getGlobalOptions()},{content:`Run "${f(s.getCliName())} ${h(`${m} <subcommand>`)} ${y("--help")}" for help with a specific subcommand.`,raw:!0}];(r.raw??r.log)(b(e))},A=(r,s,l,o,m)=>{let e=m??l.get(o);if(!e)for(const n of l.values()){const c=n.commandPath?[...n.commandPath,n.name]:[n.name];if(c.at(-1)===o||c.join(" ")===o){e=n;break}}if(!e){const n=o.split(" ").filter(Boolean),c=n.length>0?P(l,n):[];if(c.length>0){O(r,s,n,c);return}r.error(`Command "${o}" not found`);return}const a=[],i=(e.commandPath?[...e.commandPath,e.name]:[e.name]).join(" ");a.push({content:`${f(s.getCliName())} ${h(i)}${E(e)}${e.options?" [options]":""}`,header:d.cyan(" Usage ")}),e.description&&a.push({content:e.description,header:d.green(" Description ")});const p=(e.argument?[e.argument]:e.arguments??[]).filter(n=>!n.hidden);if(p.length>0&&a.push({header:"Command Positional Arguments",isArgument:!0,optionList:p}),Array.isArray(e.options)&&e.options.length>0&&a.push({header:d.yellow(" Command Options "),optionList:e.options.filter(n=>!n.hidden)}),a.push({header:d.yellow(" Global Options "),optionList:s.getGlobalOptions()}),Array.isArray(e.env)&&e.env.length>0){const n=e.env.filter(c=>!c.hidden);n.length>0&&a.push({content:n.map(c=>[c.name,c.description??""]),header:d.magenta(" Environment Variables ")})}if(e.alias!==void 0&&e.alias.length>0){let n=e.alias;typeof e.alias=="string"&&(n=[e.alias]),a.splice(1,0,{content:n,header:"Alias(es)"})}Array.isArray(e.examples)&&e.examples.length>0&&a.push({content:e.examples,header:"Examples"});const u=[...e.commandPath??[],e.name],g=P(l,u);g.length>0&&a.push({content:g.map(n=>{const c=[...n.commandPath??[],n.name].join(" ");return[h(c),n.description??""]}),header:d.green(" Subcommands ")}),(r.raw??r.log)(b(a))};class S{argument={description:"Command to show help for (subcommand path supported, e.g. `cli help docker build`)",name:"command",type:String};name="help";options=[{description:"Display only the specified group",name:"group",type:String}];commands;constructor(s){this.commands=s}execute(s){const{argument:l,command:o,commandName:m,logger:e,options:a,runtime:t}=s,{footer:i,header:p}=t.getCommandSection();p&&(e.raw??e.log)(v(p));const u=m==="help"&&Array.isArray(l)&&l.length>0?l.join(" "):void 0;if(m==="help"&&u===void 0)w(e,t,this.commands,typeof a?.group=="string"?a.group:void 0);else{const g=u!==void 0||o===void 0||o.name==="help"?void 0:o;A(e,t,this.commands,u??m,g)}i&&(e.raw??e.log)(v(i))}}export{S as default};
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import{createRequire as
|
|
2
|
-
`)[0]??"",
|
|
3
|
-
${
|
|
1
|
+
import{createRequire as L}from"node:module";import{f as R,c as F}from"../packem_shared/format-positional-usage-DWL9qN10.js";import{g as q,a as G,b as U}from"../packem_shared/runtime-process-BN-eTlwy.js";let k;const O=e=>(k??=L(import.meta.url))(e),$=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,T=e=>{if(typeof $<"u"&&$.versions&&$.versions.node){const[n,t]=$.versions.node.split(".").map(Number);if(n>22||n===22&&t>=3||n===20&&t>=16)return $.getBuiltinModule(e)}return O(e)},{resolve:v,join:V,dirname:B}=T("node:path"),C=async(e,n)=>{try{return await e.access(n),!0}catch{return!1}},z=async()=>{const{default:e}=await import("github-slugger"),n=new e;return t=>n.slug(t)},I=e=>e.filter(Boolean),W=(e,n)=>{const t=new Set,o=[];for(const s of e){const r=n(s);t.has(r)||(t.add(r),o.push(s))}return o},D=(e,n)=>{const o=(e.commandPath?[...e.commandPath,e.name]:[e.name]).join(" ");return`${n} ${o}${R(e,"readme")}`},H=(e,n)=>{if(!Array.isArray(e.env)||e.env.length===0)return;const t=e.env.filter(o=>!o.hidden);t.length>0&&n.push({content:t.map(o=>[o.name,o.description??""]),header:" Environment Variables "})},N=(e,n)=>{const t=[],s=(e.commandPath?[...e.commandPath,e.name]:[e.name]).join(" "),r=!!e.options;t.push({content:`${n} ${s}${R(e)}${r?" [options]":""}`,header:" Usage "}),e.description&&t.push({content:e.description,header:" Description "});const c=(e.argument?[e.argument]:e.arguments??[]).filter(a=>!a.hidden);if(c.length>0&&t.push({header:"Command Positional Arguments",isArgument:!0,optionList:c}),Array.isArray(e.options)&&e.options.length>0&&t.push({header:" Command Options ",optionList:e.options.filter(a=>!a.hidden)}),H(e,t),e.alias!==void 0&&e.alias.length>0){const a=Array.isArray(e.alias)?e.alias:[e.alias];t.splice(1,0,{content:a,header:"Alias(es)"})}return Array.isArray(e.examples)&&e.examples.length>0&&t.push({content:e.examples,header:"Examples"}),F(t)},J=(e,n)=>{const t=e.description?.trim().split(`
|
|
2
|
+
`)[0]??"",o=D(e,n),s=N(e,n);return I([`## \`${o}\``,t,`\`\`\`
|
|
3
|
+
${s.trim()}
|
|
4
4
|
\`\`\``]).join(`
|
|
5
5
|
|
|
6
|
-
`)},
|
|
6
|
+
`)},K=(e,n,t,o)=>{const r=`(${["--version","-V"].join("|")})`,c=G(),a=U();return`\`\`\`sh-session
|
|
7
7
|
$ npm install -g ${n}
|
|
8
8
|
$ ${e} COMMAND
|
|
9
9
|
running command...
|
|
10
|
-
$ ${e} ${
|
|
11
|
-
${n}/${t??"unknown"} ${
|
|
10
|
+
$ ${e} ${r}
|
|
11
|
+
${n}/${t??"unknown"} ${c}-${a} node-v${o}
|
|
12
12
|
$ ${e} --help [COMMAND]
|
|
13
13
|
USAGE
|
|
14
14
|
$ ${e} COMMAND
|
|
15
15
|
...
|
|
16
16
|
\`\`\`
|
|
17
|
-
`},M=(e,n,t,
|
|
18
|
-
`);return[...
|
|
19
|
-
`).trim()},
|
|
17
|
+
`},M=(e,n,t,o)=>{const s=e.map(c=>{const a=D(c,n);return`* [\`${a}\`](#${o(a)})`}),r=e.map(c=>J(c,n)).map(c=>`${c.trim()}
|
|
18
|
+
`);return[...s,"",...r].join(`
|
|
19
|
+
`).trim()},_=async(e,n,t)=>{const o=B(n);await C(e,o)||await e.mkdir(o,{recursive:!0}),await e.writeFile(n,t,"utf8")},Q=async(e,n,t,o,s,r,c)=>{const a=new Map;for(const l of t){const i=l.group??"__Other",p=a.get(i)??[];p.push(l),a.set(i,p)}const h=Array.from(a.entries(),([l,i])=>l==="__Other"?["Other",i]:[l,i]);return await Promise.all(h.map(async([l,i])=>{const p=l.replaceAll(":","/"),y=V(".",o,`${p}.md`),m=`\`${s} ${l}\``,u=`${[m,"=".repeat(m.length),"",`Commands in the ${l} group.`,"",M(i,s,r,c)].join(`
|
|
20
20
|
`).trim()}
|
|
21
|
-
`;
|
|
22
|
-
`,...
|
|
21
|
+
`;r.dryRun||await _(e,v(n,y),u)})),`${[`# Command Topics
|
|
22
|
+
`,...h.map(([l])=>{const i=l.replaceAll(":","/");return`* [\`${s} ${l}\`](${o}/${i}.md)`})].join(`
|
|
23
23
|
`).trim()}
|
|
24
|
-
`},
|
|
24
|
+
`},P=e=>e.replaceAll(`\r
|
|
25
25
|
`,`
|
|
26
26
|
`).replaceAll("\r",`
|
|
27
|
-
`),
|
|
28
|
-
`).filter(
|
|
29
|
-
`),E=e=>e.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`),w=(e,n,t)=>{const
|
|
27
|
+
`),X=(e,n)=>P(e).split(`
|
|
28
|
+
`).filter(s=>s.startsWith("# ")).map(s=>s.trim().slice(2)).map(s=>`* [${s}](#${n(s)})`).join(`
|
|
29
|
+
`),E=e=>e.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`),w=(e,n,t)=>{const o=P(e),s=`<!-- ${n} -->`,r=`<!-- ${n}stop -->`;if(o.includes(s)&&o.includes(r)){const c=E(s),a=E(r),h=new RegExp(String.raw`${c}(.|\n)*${a}`,"m");return o.replace(h,`${s}
|
|
30
30
|
${t}
|
|
31
|
-
${
|
|
31
|
+
${r}`)}return o.replace(s,`${s}
|
|
32
32
|
${t}
|
|
33
|
-
${
|
|
33
|
+
${r}`)},te={description:"Generate README documentation for CLI commands",execute:async({fs:e,logger:n,options:t,process:o,runtime:s})=>{const r=s.getCliName(),c=s.getPackageName()??r,a=s.getPackageVersion(),A=q().node??"unknown",l=await z(),i={aliases:t.aliases,dryRun:t.dryRun,multi:t.multi,nestedTopicsDepth:t.nestedTopicsDepth,outputDir:t.outputDir??"docs",readmePath:t.readmePath??"README.md",repositoryPrefix:t.repositoryPrefix,version:t.version??a??void 0},p=s.getCommands(),y=[...p.values()].filter(d=>!d.hidden).filter(d=>i.aliases?!0:d.name===p.get(d.name)?.name).toSorted((d,f)=>{const S=d.commandPath?[...d.commandPath,d.name].join(" "):d.name,b=f.commandPath?[...f.commandPath,f.name].join(" "):f.name;return S.localeCompare(b)}),m=W(y,d=>d.commandPath?[...d.commandPath,d.name].join(" "):d.name);n.debug(`Processing ${String(m.length)} commands for README generation`);let u;const g=v(o.cwd,i.readmePath??"README.md");if(await C(e,g)){const d=await e.readFile(g,"utf8");u=P(d)}else n.warn(`README file not found at ${g}, creating template`),u=`# ${c}
|
|
34
34
|
|
|
35
35
|
<!-- usage -->
|
|
36
36
|
<!-- usagestop -->
|
|
@@ -40,6 +40,6 @@ ${o}`)},Z={description:"Generate README documentation for CLI commands",execute:
|
|
|
40
40
|
|
|
41
41
|
<!-- toc -->
|
|
42
42
|
<!-- tocstop -->
|
|
43
|
-
`;const j=
|
|
44
|
-
`,
|
|
45
|
-
${
|
|
43
|
+
`;const j=i.outputDir??"docs",x=i.version??a??"unknown";u=w(u,"usage",K(r,c,x,A)),u=w(u,"commands",i.multi?await Q(e,o.cwd,m,j,r,i,l):M(m,r,i,l)),u=w(u,"toc",X(u,l)),u=`${u.trimEnd()}
|
|
44
|
+
`,i.dryRun?(n.info("Dry run mode - README not written"),n.info(`Generated README content:
|
|
45
|
+
${u}`)):(await _(e,g,u),n.info(`README generated successfully at ${g}`))},name:"readme",options:[{description:"Include aliases in command list",name:"aliases",type:Boolean},{description:"Show what would be generated without writing files",name:"dry-run",type:Boolean},{description:"Generate multi-file documentation by command groups",name:"multi",type:Boolean},{description:"Maximum depth for nested topics when using multi-file mode",name:"nested-topics-depth",type:Number},{description:"Output directory for multi-file documentation",name:"output-dir",type:String,typeLabel:"{underline directory}"},{description:"Path to README file to generate",name:"readme-path",type:String,typeLabel:"{underline path}"},{description:"Repository prefix for code links",name:"repository-prefix",type:String,typeLabel:"{underline prefix}"},{description:"Version to use in generated documentation",name:"version",type:String,typeLabel:"{underline version}"}]};export{te as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const s={alias:["v","V"],description:"Output the version number",execute:({logger:e,runtime:o})=>{const n=o.getPackageVersion();n===void 0?(e.warn("Unknown version"),e.debug("The version number was not provided by the cli constructor.")):e.info(n)},name:"version",options:[],usage:[]};export{s as default};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as CerebroFs, b as CommandSection, O as OptionDefinition,
|
|
2
|
-
export type {
|
|
3
|
-
|
|
1
|
+
import { a as CerebroFs, b as CommandSection, O as OptionDefinition, T as Toolbox, c as CommandInput, P as Plugin, d as PluginManager, C as Command, e as CliRunOptions, R as RunCommandOptions, f as CommandExecute, g as Cli$1, h as OptionDefinitionRecord, E as EnvDefinitionRecord, A as ArgumentDefinition, L as LazyCommandModule } from "./packem_shared/command.d-Dz7hkMI0.js";
|
|
2
|
+
export type { i as AnyCommandInput, j as CerebroProcess, k as EnvDefinition, l as OutputType, m as PluginContext, V as VERBOSITY_LEVEL } from "./packem_shared/command.d-Dz7hkMI0.js";
|
|
3
|
+
import { V as VisulimaError } from "./packem_shared/index.d-CnnVYgSZ.js";
|
|
4
4
|
import '@visulima/tabular';
|
|
5
5
|
type CliOptions<T extends Console = Console> = {
|
|
6
6
|
argv?: ReadonlyArray<string>;
|
|
@@ -106,7 +106,8 @@ declare class Cli<T extends Console = Console> implements Cli$1<T> {
|
|
|
106
106
|
* Commands define the available operations that users can execute.
|
|
107
107
|
* Each command can have options, arguments, aliases, and custom execution logic.
|
|
108
108
|
* @template OD - The option definition type for the command
|
|
109
|
-
* @
|
|
109
|
+
* @template TContext - The toolbox shape the command's handler receives
|
|
110
|
+
* @param commandInput The command configuration object
|
|
110
111
|
* @returns The CLI instance for method chaining
|
|
111
112
|
* @throws {CerebroError} If the command name already exists or validation fails
|
|
112
113
|
* @example
|
|
@@ -128,7 +129,7 @@ declare class Cli<T extends Console = Console> implements Cli$1<T> {
|
|
|
128
129
|
* });
|
|
129
130
|
* ```
|
|
130
131
|
*/
|
|
131
|
-
addCommand<OD extends OptionDefinition<unknown> = OptionDefinition<unknown>>(
|
|
132
|
+
addCommand<OD extends OptionDefinition<unknown> = OptionDefinition<unknown>, TContext extends Toolbox<T> = Toolbox<T>>(commandInput: CommandInput<OD, T, TContext>): this;
|
|
132
133
|
/**
|
|
133
134
|
* Adds a global option available to all commands.
|
|
134
135
|
*
|
|
@@ -388,6 +389,15 @@ declare const VERBOSITY_DEBUG = 128;
|
|
|
388
389
|
type OptionNameToCamelCase<T extends string> = T extends `${infer Start}-${infer Rest}` ? `${Lowercase<Start>}${Capitalize<OptionNameToCamelCase<Rest>>}` : T extends `${infer Start}_${infer Rest}` ? `${Lowercase<Start>}${Capitalize<OptionNameToCamelCase<Rest>>}` : Lowercase<T>;
|
|
389
390
|
/**
|
|
390
391
|
* Helper type to create a type-safe options object from option definitions.
|
|
392
|
+
*
|
|
393
|
+
* Prefer `defineCommand`, which infers this shape from the definitions
|
|
394
|
+
* themselves instead of restating their names. Reach for `CreateOptions` when
|
|
395
|
+
* you are annotating a `Toolbox` by hand — typically because the command uses
|
|
396
|
+
* the array form of `options`, which carries no inferable key information.
|
|
397
|
+
*
|
|
398
|
+
* Note that this type lowercases a name with no separator in it (`outputDir`
|
|
399
|
+
* becomes `outputdir`), which matches how environment variables are folded but
|
|
400
|
+
* not* how the option parser folds option names.
|
|
391
401
|
* @example
|
|
392
402
|
* ```typescript
|
|
393
403
|
* type MyOptions = CreateOptions<{
|
|
@@ -401,6 +411,9 @@ type OptionNameToCamelCase<T extends string> = T extends `${infer Start}-${infer
|
|
|
401
411
|
type CreateOptions<T extends Record<string, unknown>> = { [K in keyof T as OptionNameToCamelCase<K & string>]: T[K]; };
|
|
402
412
|
/**
|
|
403
413
|
* Helper type to create a type-safe environment variables object from env definitions.
|
|
414
|
+
*
|
|
415
|
+
* Prefer `defineCommand`, which infers this shape from the definitions
|
|
416
|
+
* themselves. This type matches the env folding rules exactly.
|
|
404
417
|
* Environment variable names are converted from UPPER_SNAKE_CASE to camelCase.
|
|
405
418
|
* @example
|
|
406
419
|
* ```typescript
|
|
@@ -412,6 +425,239 @@ type CreateOptions<T extends Record<string, unknown>> = { [K in keyof T as Optio
|
|
|
412
425
|
* ```
|
|
413
426
|
*/
|
|
414
427
|
type CreateEnv<T extends Record<string, unknown>> = { [K in keyof T as OptionNameToCamelCase<K & string>]: T[K]; };
|
|
428
|
+
/**
|
|
429
|
+
* Folds a name the way the parser folds it.
|
|
430
|
+
*
|
|
431
|
+
* A direct transcription of `command-line-args`' `/-([a-z])/g`: a hyphen folds
|
|
432
|
+
* into the following character *only* when that character is an ASCII lowercase
|
|
433
|
+
* letter. `a-1` and `x-` are left alone, `A-b` becomes `AB`, and a name with no
|
|
434
|
+
* hyphen is returned untouched — including `outputDir`, `UPPER` and `HTTPProxy`.
|
|
435
|
+
*
|
|
436
|
+
* Positional names go through the same fold at runtime (`foldName` in
|
|
437
|
+
* `resolve-arguments.ts`), so one type serves both surfaces. Environment
|
|
438
|
+
* variables do not — they lowercase first, which is what
|
|
439
|
+
* {@link OptionNameToCamelCase} models.
|
|
440
|
+
*/
|
|
441
|
+
type FoldName<T extends string> = T extends `${infer Head}-${infer Tail}` ? Tail extends `${infer First}${infer Rest}` ? Lowercase<First> extends First ? Uppercase<First> extends Lowercase<First> ? `${Head}-${FoldName<Tail>}` : `${Head}${Uppercase<First>}${FoldName<Rest>}` : `${Head}-${FoldName<Tail>}` : `${Head}-` : T;
|
|
442
|
+
/**
|
|
443
|
+
* The value a `type` constructor produces. Falls back to `string` when no `type`
|
|
444
|
+
* is declared, matching the parser, which leaves untyped values as raw strings.
|
|
445
|
+
*
|
|
446
|
+
* Not modelled: `TypeConstructor<T>` is declared as returning `T | undefined`, so
|
|
447
|
+
* a transform that genuinely returns `undefined` is still typed as `T` here.
|
|
448
|
+
*/
|
|
449
|
+
type TypeConstructorResult<D> = D extends {
|
|
450
|
+
type: (...arguments_: never[]) => infer R;
|
|
451
|
+
} ? Exclude<R, undefined> : string;
|
|
452
|
+
/** `multiple` / `lazyMultiple` collect every occurrence into an array. */
|
|
453
|
+
type Collected<D> = D extends {
|
|
454
|
+
lazyMultiple: true;
|
|
455
|
+
} | {
|
|
456
|
+
multiple: true;
|
|
457
|
+
} ? TypeConstructorResult<D>[] : TypeConstructorResult<D>;
|
|
458
|
+
/** Whether a `defaultValue` was declared, which fills the gap when the flag is absent. */
|
|
459
|
+
type HasDefault<D> = "defaultValue" extends keyof D ? true : false;
|
|
460
|
+
/**
|
|
461
|
+
* Whether a **boolean** option is declared. `listMissingArguments` short-circuits
|
|
462
|
+
* missing required booleans instead of raising, and the substituted `false` never
|
|
463
|
+
* reaches `parsedArgs._all` — so a required boolean can still be absent from the
|
|
464
|
+
* toolbox at runtime and must keep its `| undefined`.
|
|
465
|
+
*/
|
|
466
|
+
type IsBooleanOption<D> = D extends {
|
|
467
|
+
type: BooleanConstructor;
|
|
468
|
+
} ? true : false;
|
|
469
|
+
/**
|
|
470
|
+
* Whether an **option** is guaranteed a value.
|
|
471
|
+
*
|
|
472
|
+
* `required` is enforced before `execute` runs, and a `defaultValue` fills the
|
|
473
|
+
* gap when the flag is absent — except for booleans, which
|
|
474
|
+
* `listMissingArguments` lets through (see {@link IsBooleanOption}).
|
|
475
|
+
*/
|
|
476
|
+
type IsOptionAlwaysPresent<D> = D extends {
|
|
477
|
+
required: true;
|
|
478
|
+
} ? (IsBooleanOption<D> extends true ? HasDefault<D> : true) : HasDefault<D>;
|
|
479
|
+
/**
|
|
480
|
+
* Whether a **positional** is guaranteed a value.
|
|
481
|
+
*
|
|
482
|
+
* No boolean exception here: `resolveArguments` reports every unfilled
|
|
483
|
+
* `required` slot whatever its `type`, and `applyNamedArguments` raises before
|
|
484
|
+
* `execute` runs. A required boolean positional really is always present.
|
|
485
|
+
*/
|
|
486
|
+
type IsArgumentAlwaysPresent<D> = D extends {
|
|
487
|
+
required: true;
|
|
488
|
+
} ? true : HasDefault<D>;
|
|
489
|
+
/**
|
|
490
|
+
* Keys declared as `no-x` produce an `x` option instead. `addNegatableOptions`
|
|
491
|
+
* generates the counterpart definition and `mapNegatableOptions` rewrites the
|
|
492
|
+
* parsed value onto the non-negated key, deleting `noX` — so `no-x` never
|
|
493
|
+
* surfaces on the toolbox under its own name.
|
|
494
|
+
*/
|
|
495
|
+
type PositiveOptionKeys<R> = { [K in keyof R]: K extends `no-${string}` ? never : K; }[keyof R];
|
|
496
|
+
/**
|
|
497
|
+
* The positive names cerebro *generates* from a `no-x` declaration.
|
|
498
|
+
*
|
|
499
|
+
* Only when `x` is not declared itself. `negatable()` declares both halves, and
|
|
500
|
+
* a positive half without a `defaultValue` stays `undefined` when neither flag
|
|
501
|
+
* is passed — `mapNegatableOptions` rewrites nothing because the negated key
|
|
502
|
+
* never reaches the parsed options. Claiming `boolean` there would erase a
|
|
503
|
+
* deliberate tri-state.
|
|
504
|
+
*/
|
|
505
|
+
type NegatedOptionKeys<R> = { [K in keyof R]: K extends `no-${infer Rest}` ? (Rest extends keyof R ? never : Rest) : never; }[keyof R];
|
|
506
|
+
/** Collapses an intersection into a single object literal so tooltips stay readable. */
|
|
507
|
+
type Simplify<T> = { [K in keyof T]: T[K]; } & {};
|
|
508
|
+
/**
|
|
509
|
+
* Infers the shape of `toolbox.options` from a record of option definitions.
|
|
510
|
+
*
|
|
511
|
+
* Option names are folded the way the parser folds them, `required: true` or a
|
|
512
|
+
* `defaultValue` drops the `| undefined`, and `multiple` produces an array.
|
|
513
|
+
*
|
|
514
|
+
* Not modelled: values injected by `implies`, which is an untyped
|
|
515
|
+
* `Record<string, unknown>` and can name any option.
|
|
516
|
+
* @example
|
|
517
|
+
* ```typescript
|
|
518
|
+
* type Options = InferOptions<{
|
|
519
|
+
* "output-dir": { required: true; type: StringConstructor };
|
|
520
|
+
* verbose: { type: BooleanConstructor };
|
|
521
|
+
* }>;
|
|
522
|
+
* // { outputDir: string; verbose: boolean | undefined }
|
|
523
|
+
* ```
|
|
524
|
+
*/
|
|
525
|
+
type InferOptions<R extends OptionDefinitionRecord> = Simplify<{ [K in NegatedOptionKeys<R> & string as FoldName<K>]: boolean; } & { [K in PositiveOptionKeys<R> & string as FoldName<K>]: IsOptionAlwaysPresent<R[K]> extends true ? Collected<R[K]> : Collected<R[K]> | undefined; }>;
|
|
526
|
+
/**
|
|
527
|
+
* Infers the shape of `toolbox.env` from a record of environment definitions.
|
|
528
|
+
*
|
|
529
|
+
* `processEnvVariables` lowercases the whole name before folding snake segments,
|
|
530
|
+
* so `API_KEY` becomes `apiKey` and an already-camelCase `apiKey` becomes
|
|
531
|
+
* `apikey` — which is what {@link OptionNameToCamelCase} models. Only a
|
|
532
|
+
* `defaultValue` removes the `| undefined`; environment variables have no
|
|
533
|
+
* `required` concept.
|
|
534
|
+
* @example
|
|
535
|
+
* ```typescript
|
|
536
|
+
* type Env = InferEnv<{ API_KEY: { type: StringConstructor } }>;
|
|
537
|
+
* // { apiKey: string | undefined }
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
540
|
+
type InferEnv<R extends EnvDefinitionRecord> = Simplify<{ [K in keyof R & string as OptionNameToCamelCase<K>]: HasDefault<R[K]> extends true ? TypeConstructorResult<R[K]> : TypeConstructorResult<R[K]> | undefined; }>;
|
|
541
|
+
/** Picks the positional definition carrying a given name out of the tuple. */
|
|
542
|
+
type ArgumentNamed<T extends ReadonlyArray<ArgumentDefinition>, N extends string> = Extract<T[number], {
|
|
543
|
+
name: N;
|
|
544
|
+
}>;
|
|
545
|
+
/**
|
|
546
|
+
* Infers the shape of `toolbox.args` from a tuple of positional definitions.
|
|
547
|
+
*
|
|
548
|
+
* Positional names are camelCased, `multiple: true` on the final entry produces
|
|
549
|
+
* an array, and `required: true` or a `defaultValue` drops the `| undefined`.
|
|
550
|
+
*
|
|
551
|
+
* Slot order matters, so `arguments` is an array rather than a record. The tuple
|
|
552
|
+
* is captured by a `const` type parameter on `defineCommand`, so no `as const` is
|
|
553
|
+
* needed at the call site.
|
|
554
|
+
* @example
|
|
555
|
+
* ```typescript
|
|
556
|
+
* type Args = InferArguments<
|
|
557
|
+
* [{ name: "source"; required: true; type: StringConstructor }, { multiple: true; name: "targets"; type: StringConstructor }]
|
|
558
|
+
* >;
|
|
559
|
+
* // { source: string; targets: string[] | undefined }
|
|
560
|
+
* ```
|
|
561
|
+
*/
|
|
562
|
+
type InferArguments<T extends ReadonlyArray<ArgumentDefinition>> = Simplify<{ [K in T[number]["name"] as FoldName<K>]: IsArgumentAlwaysPresent<ArgumentNamed<T, K>> extends true ? Collected<ArgumentNamed<T, K>> : Collected<ArgumentNamed<T, K>> | undefined; }>;
|
|
563
|
+
/**
|
|
564
|
+
* The toolbox a command declared through {@link defineCommand} receives, with
|
|
565
|
+
* `options`, `env` and `args` inferred from the command's own definitions.
|
|
566
|
+
*/
|
|
567
|
+
type InferredToolbox<TOptions extends OptionDefinitionRecord, TEnv extends EnvDefinitionRecord, TArguments extends ReadonlyArray<ArgumentDefinition>, TLogger extends Console = Console> = Toolbox<TLogger, InferOptions<TOptions>, InferEnv<TEnv>, InferArguments<TArguments>>;
|
|
568
|
+
/**
|
|
569
|
+
* A command whose `execute` / `loader` handler is typed from its own `options`,
|
|
570
|
+
* `env` and `arguments` declarations.
|
|
571
|
+
*/
|
|
572
|
+
type DefinedCommand<TOptions extends OptionDefinitionRecord, TEnv extends EnvDefinitionRecord, TArguments extends ReadonlyArray<ArgumentDefinition>, TLogger extends Console = Console> = Omit<CommandInput<OptionDefinition<unknown>, TLogger>, "arguments" | "env" | "execute" | "loader" | "options"> & {
|
|
573
|
+
arguments?: TArguments;
|
|
574
|
+
env?: TEnv;
|
|
575
|
+
execute?: CommandExecute<NoInfer<InferredToolbox<TOptions, TEnv, TArguments, TLogger>>>;
|
|
576
|
+
loader?: () => Promise<LazyCommandModule<NoInfer<InferredToolbox<TOptions, TEnv, TArguments, TLogger>>>>;
|
|
577
|
+
options?: TOptions;
|
|
578
|
+
};
|
|
579
|
+
/**
|
|
580
|
+
* Declares a command with a single source of truth for its options and
|
|
581
|
+
* environment variables.
|
|
582
|
+
*
|
|
583
|
+
* `options` and `env` are records keyed by name, and the `execute` handler's
|
|
584
|
+
* `toolbox.options` / `toolbox.env` are inferred from them — no second type
|
|
585
|
+
* declaration, no `Toolbox<...>` annotation, and a renamed option becomes a
|
|
586
|
+
* compile error at every use site instead of a silent `undefined`.
|
|
587
|
+
*
|
|
588
|
+
* Identity at runtime: it exists only to capture the literal types of the
|
|
589
|
+
* definitions, so it costs nothing beyond the call itself.
|
|
590
|
+
* @param command The command definition.
|
|
591
|
+
* @returns The same object, with its definition types preserved.
|
|
592
|
+
* @example
|
|
593
|
+
* ```typescript
|
|
594
|
+
* import { defineCommand } from "@visulima/cerebro";
|
|
595
|
+
*
|
|
596
|
+
* const build = defineCommand({
|
|
597
|
+
* name: "build",
|
|
598
|
+
* options: {
|
|
599
|
+
* "output-dir": { required: true, type: String },
|
|
600
|
+
* verbose: { defaultValue: false, type: Boolean },
|
|
601
|
+
* },
|
|
602
|
+
* env: {
|
|
603
|
+
* API_KEY: { type: String },
|
|
604
|
+
* },
|
|
605
|
+
* arguments: [{ name: "entry", required: true, type: String }],
|
|
606
|
+
* execute: ({ args, env, options }) => {
|
|
607
|
+
* args.entry; // string
|
|
608
|
+
* options.outputDir; // string
|
|
609
|
+
* options.verbose; // boolean
|
|
610
|
+
* env.apiKey; // string | undefined
|
|
611
|
+
* },
|
|
612
|
+
* });
|
|
613
|
+
*
|
|
614
|
+
* cli.addCommand(build);
|
|
615
|
+
* ```
|
|
616
|
+
*/
|
|
617
|
+
declare const defineCommand: <TOptions extends OptionDefinitionRecord = {}, TEnv extends EnvDefinitionRecord = {}, const TArguments extends ReadonlyArray<ArgumentDefinition> = [], TLogger extends Console = Console>(command: DefinedCommand<TOptions, TEnv, TArguments, TLogger>) => DefinedCommand<TOptions, TEnv, TArguments, TLogger>;
|
|
618
|
+
/**
|
|
619
|
+
* Base error class for Cerebro CLI operations.
|
|
620
|
+
*/
|
|
621
|
+
declare class CerebroError extends VisulimaError {
|
|
622
|
+
readonly code: string;
|
|
623
|
+
readonly context?: Record<string, unknown>;
|
|
624
|
+
constructor(message: string, code: string, context?: Record<string, unknown>);
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Error thrown when a positional argument's value is not one of its declared
|
|
628
|
+
* `choices`.
|
|
629
|
+
*
|
|
630
|
+
* Distinct from `InvalidChoiceError`, which phrases its hint as `--<option>
|
|
631
|
+
* <value>`. A positional has no flag, so that hint would name something the
|
|
632
|
+
* command does not declare.
|
|
633
|
+
*/
|
|
634
|
+
declare class InvalidArgumentChoiceError extends CerebroError {
|
|
635
|
+
readonly argument: string;
|
|
636
|
+
readonly choices: ReadonlyArray<string>;
|
|
637
|
+
readonly value: string;
|
|
638
|
+
constructor(argument: string, value: string, choices: ReadonlyArray<string>);
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Error thrown when a command is invoked without one of its required positional
|
|
642
|
+
* arguments. Distinct from `CommandValidationError`, which reports missing
|
|
643
|
+
* options* — telling a user to "provide the required option" for a positional
|
|
644
|
+
* sends them looking for a `--flag` that does not exist.
|
|
645
|
+
*/
|
|
646
|
+
declare class MissingArgumentError extends CerebroError {
|
|
647
|
+
readonly commandName: string;
|
|
648
|
+
readonly missingArguments: string[];
|
|
649
|
+
constructor(commandName: string, missingArguments: string[]);
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Error thrown when more positional arguments were supplied than the command
|
|
653
|
+
* declares. A command using named `arguments` knows its exact arity, so a
|
|
654
|
+
* surplus token is a mistake worth reporting rather than discarding in silence.
|
|
655
|
+
*/
|
|
656
|
+
declare class SurplusArgumentError extends CerebroError {
|
|
657
|
+
readonly commandName: string;
|
|
658
|
+
readonly surplusArguments: ReadonlyArray<string>;
|
|
659
|
+
constructor(commandName: string, surplusArguments: ReadonlyArray<string>, expected: number);
|
|
660
|
+
}
|
|
415
661
|
/**
|
|
416
662
|
* Builds a `loader` for commands whose handler lives as a named export in a
|
|
417
663
|
* shared handler module (the typical pattern when one file holds multiple
|
|
@@ -429,7 +675,7 @@ type CreateEnv<T extends Record<string, unknown>> = { [K in keyof T as OptionNam
|
|
|
429
675
|
* });
|
|
430
676
|
* ```
|
|
431
677
|
*/
|
|
432
|
-
declare const lazyNamed: <M extends Record<string, unknown
|
|
678
|
+
declare const lazyNamed: <M extends Record<string, unknown>>(load: () => Promise<M>, key: keyof M) => () => Promise<LazyCommandModule<Toolbox>>;
|
|
433
679
|
declare global {
|
|
434
680
|
namespace Cerebro {
|
|
435
681
|
/**
|
|
@@ -487,4 +733,35 @@ declare global {
|
|
|
487
733
|
* ```
|
|
488
734
|
*/
|
|
489
735
|
declare const createCerebro: <T extends Console = Console>(name: string, options?: CliOptions<T>) => InstanceType<typeof Cli<T>>;
|
|
490
|
-
export { Cli as Cerebro, type CerebroFs, type Cli$1 as Cli,
|
|
736
|
+
export { type ArgumentDefinition, Cli as Cerebro, type CerebroFs, type Cli$1 as Cli,
|
|
737
|
+
/**
|
|
738
|
+
* Main entry point for the Cerebro CLI framework.
|
|
739
|
+
*
|
|
740
|
+
* This module provides a lightweight, extensible CLI framework for building command-line applications.
|
|
741
|
+
* It supports plugins, subcommands, argument parsing, help generation, and more.
|
|
742
|
+
* @example
|
|
743
|
+
* ```typescript
|
|
744
|
+
* import { createCerebro } from '@visulima/cerebro';
|
|
745
|
+
*
|
|
746
|
+
* const cli = createCerebro('my-app', {
|
|
747
|
+
* packageName: 'my-app',
|
|
748
|
+
* packageVersion: '1.0.0'
|
|
749
|
+
* });
|
|
750
|
+
*
|
|
751
|
+
* cli.addCommand({
|
|
752
|
+
* name: 'greet',
|
|
753
|
+
* description: 'Greet someone',
|
|
754
|
+
* argument: {
|
|
755
|
+
* name: 'name',
|
|
756
|
+
* description: 'Name to greet',
|
|
757
|
+
* type: String
|
|
758
|
+
* },
|
|
759
|
+
* execute: ({ argument }) => {
|
|
760
|
+
* console.log(`Hello, ${argument[0]}!`);
|
|
761
|
+
* }
|
|
762
|
+
* });
|
|
763
|
+
*
|
|
764
|
+
* cli.run();
|
|
765
|
+
* ```
|
|
766
|
+
*/
|
|
767
|
+
type CliOptions, type CliRunOptions, type Command, type CommandExecute, type CommandInput, type CreateEnv, type CreateOptions, type DefinedCommand, type EnvDefinitionRecord, type InferArguments, type InferEnv, type InferOptions, type InferredToolbox, InvalidArgumentChoiceError, type LazyCommandModule, MissingArgumentError, type OptionDefinition, type OptionDefinitionRecord, type OptionNameToCamelCase, type Plugin, type RunCommandOptions, SurplusArgumentError, type Toolbox, VERBOSITY_DEBUG, VERBOSITY_NORMAL, VERBOSITY_QUIET, VERBOSITY_VERBOSE, VisulimaError, createCerebro, defineCommand, lazyNamed };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Cli as
|
|
1
|
+
import{Cli as o}from"./packem_shared/Cerebro-B02RU3RC.js";import{VERBOSITY_DEBUG as E,VERBOSITY_NORMAL as s,VERBOSITY_QUIET as p,VERBOSITY_VERBOSE as u}from"./packem_shared/VERBOSITY_DEBUG-D7HfSD5l.js";import{default as l}from"./packem_shared/defineCommand-C_isHeEs.js";import{default as d}from"./packem_shared/InvalidArgumentChoiceError-BpovuqrZ.js";import{default as B}from"./packem_shared/MissingArgumentError-D78kza2a.js";import{default as O}from"./packem_shared/SurplusArgumentError-BLwT9lo0.js";import{lazyNamed as S}from"./packem_shared/lazyNamed-BKSCmVsV.js";import{c as C}from"./packem_shared/VisulimaError-BDqtOVL5-Db_MJ_p7.js";const a=(r,e)=>new o(r,e);export{o as Cerebro,d as InvalidArgumentChoiceError,B as MissingArgumentError,O as SurplusArgumentError,E as VERBOSITY_DEBUG,s as VERBOSITY_NORMAL,p as VERBOSITY_QUIET,u as VERBOSITY_VERBOSE,C as VisulimaError,a as createCerebro,l as defineCommand,S as lazyNamed};
|