@visulima/cerebro 3.0.0-alpha.7 → 3.0.0-alpha.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/commands/completion-command.js +203 -5
  3. package/dist/commands/help-command.js +3 -1
  4. package/dist/commands/readme-command.js +330 -32
  5. package/dist/commands/version-command.js +18 -1
  6. package/dist/index.js +7 -1
  7. package/dist/logger/create-pail-logger.js +34 -1
  8. package/dist/packem_chunks/has-new-version.js +259 -1
  9. package/dist/packem_shared/Cerebro-C2mnCyQf.js +3313 -0
  10. package/dist/packem_shared/VERBOSITY_QUIET-Dp46zlLW.js +10 -0
  11. package/dist/packem_shared/VisulimaError-DA7QsCxH.js +34 -0
  12. package/dist/packem_shared/cerebro-error-GmJ3jN7Q.js +16 -0
  13. package/dist/packem_shared/help-command-BY7rQUvM.js +249 -0
  14. package/dist/packem_shared/index-C2-8b3A4.js +259 -0
  15. package/dist/packem_shared/runtime-process-B6ZplyWn.js +187 -0
  16. package/dist/plugins/error-handler-plugin.js +636 -1
  17. package/dist/plugins/runtime-version-check-plugin.js +77 -1
  18. package/dist/plugins/update-notifier/update-notifier-plugin.js +517 -1
  19. package/package.json +8 -7
  20. package/dist/packem_shared/Cerebro-aPZjbfzf.js +0 -4
  21. package/dist/packem_shared/VERBOSITY_QUIET-XPultrIA.js +0 -1
  22. package/dist/packem_shared/VisulimaError-wAUvPRfg.js +0 -76
  23. package/dist/packem_shared/cerebro-error-BnJTixb2.js +0 -1
  24. package/dist/packem_shared/help-command-CIRIXN03.js +0 -1
  25. package/dist/packem_shared/index-DQ3pvLQH.js +0 -6
  26. package/dist/packem_shared/isVisulimaError-jVZgumOU-C4fgdbWg.js +0 -1
  27. package/dist/packem_shared/renderError-ZMlMvw1N-eVUSdl6c.js +0 -24
  28. package/dist/packem_shared/runtime-process-G-n-wOub.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,50 @@
1
+ ## @visulima/cerebro [3.0.0-alpha.9](https://github.com/visulima/visulima/compare/@visulima/cerebro@3.0.0-alpha.8...@visulima/cerebro@3.0.0-alpha.9) (2026-03-26)
2
+
3
+ ### Features
4
+
5
+ * **web:** auto-generate packages page from workspace metadata ([623e520](https://github.com/visulima/visulima/commit/623e5207693a7fe720f5f2f179593a3654c880e3))
6
+
7
+
8
+ ### Dependencies
9
+
10
+ * **@visulima/colorize:** upgraded to 2.0.0-alpha.7
11
+ * **@visulima/tabular:** upgraded to 4.0.0-alpha.8
12
+ * **@visulima/boxen:** upgraded to 3.0.0-alpha.8
13
+ * **@visulima/command-line-args:** upgraded to 2.0.0-alpha.6
14
+ * **@visulima/error:** upgraded to 6.0.0-alpha.7
15
+ * **@visulima/find-cache-dir:** upgraded to 3.0.0-alpha.6
16
+ * **@visulima/pail:** upgraded to 4.0.0-alpha.9
17
+ * **@visulima/path:** upgraded to 3.0.0-alpha.7
18
+ * **@visulima/string:** upgraded to 3.0.0-alpha.8
19
+
20
+ ## @visulima/cerebro [3.0.0-alpha.8](https://github.com/visulima/visulima/compare/@visulima/cerebro@3.0.0-alpha.7...@visulima/cerebro@3.0.0-alpha.8) (2026-03-26)
21
+
22
+ ### Bug Fixes
23
+
24
+ * **cerebro:** use workspace:* for internal [@visulima](https://github.com/visulima) deps ([6647854](https://github.com/visulima/visulima/commit/6647854b69a518466318af623938c0435f3a2579))
25
+ * **web:** improve build setup with incremental stats caching and prod install ([fe33e75](https://github.com/visulima/visulima/commit/fe33e75827586779b4b3a0c6d57b39f889ee6207))
26
+
27
+ ### Miscellaneous Chores
28
+
29
+ * **cerebro:** migrate deps to pnpm catalogs ([75cfac0](https://github.com/visulima/visulima/commit/75cfac01080464cc07279164520177472aff3b13))
30
+
31
+ ### Code Refactoring
32
+
33
+ * **docs:** migrate Nextra components to fumadocs-ui, remove Nextra stripping ([484878f](https://github.com/visulima/visulima/commit/484878f01879363ef5e9a0282904dc4627d6060c))
34
+
35
+
36
+ ### Dependencies
37
+
38
+ * **@visulima/colorize:** upgraded to 2.0.0-alpha.6
39
+ * **@visulima/tabular:** upgraded to 4.0.0-alpha.7
40
+ * **@visulima/boxen:** upgraded to 3.0.0-alpha.7
41
+ * **@visulima/command-line-args:** upgraded to 2.0.0-alpha.5
42
+ * **@visulima/error:** upgraded to 6.0.0-alpha.6
43
+ * **@visulima/find-cache-dir:** upgraded to 3.0.0-alpha.5
44
+ * **@visulima/pail:** upgraded to 4.0.0-alpha.8
45
+ * **@visulima/path:** upgraded to 3.0.0-alpha.6
46
+ * **@visulima/string:** upgraded to 3.0.0-alpha.7
47
+
1
48
  ## @visulima/cerebro [3.0.0-alpha.7](https://github.com/visulima/visulima/compare/@visulima/cerebro@3.0.0-alpha.6...@visulima/cerebro@3.0.0-alpha.7) (2026-03-16)
2
49
 
3
50
  ### Miscellaneous Chores
@@ -1,5 +1,203 @@
1
- var g=Object.defineProperty;var a=(e,t)=>g(e,"name",{value:t,configurable:!0});import S from"@bomb.sh/tab";import{c as $}from"../packem_shared/cerebro-error-BnJTixb2.js";var w=Object.defineProperty,y=a((e,t)=>w(e,"name",{value:t,configurable:!0}),"n");class p extends ${static{a(this,"l")}static{y(this,"CompletionError")}troubleshooting;constructor(t,o,n=[]){super(t,o,{troubleshooting:n}),this.name="CompletionError",this.troubleshooting=n,n.length>0&&(this.hint=n.join(`
2
- `))}}var C=Object.defineProperty,s=a((e,t)=>C(e,"name",{value:t,configurable:!0}),"s");const h=["bash","zsh","fish","powershell"],d=["node","bun","deno"],v=s(e=>"Deno"in e,"hasDeno"),L=s(e=>"Bun"in e,"hasBun"),u=s(()=>v(globalThis)?"deno":L(globalThis)?"bun":"node","detectRuntime"),m=s(e=>{const t=e?.starshipShell??e?.shell;if(t){const r=t.toLowerCase();if(r.includes("zsh"))return"zsh";if(r.includes("bash"))return"bash";if(r.includes("fish"))return"fish"}const o=e?.psModulePath,n=e?.prompt;if(o||n?.includes("PS"))return"powershell";if(e?.comSpec?.toLowerCase().includes("cmd.exe"))return"bash"},"detectShell"),f=S,I=s((e,t)=>{for(const o of t)o.hidden||(o.name&&e.option(o.name,o.description||""),o.alias&&e.option(o.alias,o.description||""))},"registerCommandOptions"),P=s((e,t)=>{for(const[o,n]of t){if(n.name!==o||n.hidden)continue;const r=e.command(n.name,n.description||"");n.options&&I(r,n.options)}},"registerCommands"),E=s(e=>{if(!h.includes(e))throw new p(`Invalid shell type: ${e}`,"INVALID_SHELL",[`Valid shells are: ${h.join(", ")}`,"Shell will be auto-detected if not specified"])},"validateShell"),j=s(e=>{if(e&&!d.includes(e))throw new p(`Invalid runtime: ${e}`,"INVALID_RUNTIME",[`Valid runtimes are: ${d.join(", ")}`,"Runtime will be auto-detected if not specified"])},"validateRuntime"),z=s((e,t)=>{e.error("Could not detect current shell");const o=[`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(o)},"printUsageInstructions"),x={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:s(async({env:e,logger:t,options:o,runtime:n})=>{const r=n.getCliName(),c=o?.shell||m(e);if(!c){z(t,r);return}try{E(c),j(o?.runtime),P(f,n.getCommands());const i=`${o?.runtime||u()} ${r}`;f.setup(r,i,c)}catch(i){if(i instanceof p){const l=[`Failed to generate completion script: ${i.message}`,`Error code: ${i.code}`];throw i.troubleshooting.length>0&&l.push("","Troubleshooting:",...i.troubleshooting.map(b=>` • ${b}`)),t.error(l.join(`
4
- `)),i}else{const l=["Failed to generate completion script",`Error: ${i instanceof Error?i.message:String(i)}`,"","Troubleshooting:"," • Ensure @bomb.sh/tab is installed: pnpm add @bomb.sh/tab",` • Verify shell is supported: ${h.join(", ")}`,` • Verify runtime is supported: ${d.join(", ")}`," • Check that your CLI name is correct"];t.error(l.join(`
5
- `))}}},"execute"),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}"},{defaultOption:!0,defaultValue:u(),description:"JavaScript runtime (node, bun, deno). Defaults to current runtime if detected.",name:"runtime",type:String,typeLabel:"{underline runtime}"}]};export{x as default};
1
+ import tab from '@bomb.sh/tab';
2
+ import { C as CerebroError } from '../packem_shared/cerebro-error-GmJ3jN7Q.js';
3
+
4
+ class CompletionError extends CerebroError {
5
+ troubleshooting;
6
+ constructor(message, code, troubleshooting = []) {
7
+ super(message, code, { troubleshooting });
8
+ this.name = "CompletionError";
9
+ this.troubleshooting = troubleshooting;
10
+ if (troubleshooting.length > 0) {
11
+ this.hint = troubleshooting.join("\n");
12
+ }
13
+ }
14
+ }
15
+
16
+ const validShells = ["bash", "zsh", "fish", "powershell"];
17
+ const validRuntimes = ["node", "bun", "deno"];
18
+ const hasDeno = (global) => "Deno" in global;
19
+ const hasBun = (global) => "Bun" in global;
20
+ const detectRuntime = () => {
21
+ if (hasDeno(globalThis)) {
22
+ return "deno";
23
+ }
24
+ if (hasBun(globalThis)) {
25
+ return "bun";
26
+ }
27
+ return "node";
28
+ };
29
+ const detectShell = (toolboxEnv) => {
30
+ const starshipShell = toolboxEnv?.starshipShell;
31
+ const shell = starshipShell ?? toolboxEnv?.shell;
32
+ if (shell) {
33
+ const shellPath = shell.toLowerCase();
34
+ if (shellPath.includes("zsh")) {
35
+ return "zsh";
36
+ }
37
+ if (shellPath.includes("bash")) {
38
+ return "bash";
39
+ }
40
+ if (shellPath.includes("fish")) {
41
+ return "fish";
42
+ }
43
+ }
44
+ const psModulePath = toolboxEnv?.psModulePath;
45
+ const prompt = toolboxEnv?.prompt;
46
+ if (psModulePath || prompt?.includes("PS")) {
47
+ return "powershell";
48
+ }
49
+ const comSpec = toolboxEnv?.comSpec;
50
+ if (comSpec?.toLowerCase().includes("cmd.exe")) {
51
+ return "bash";
52
+ }
53
+ return void 0;
54
+ };
55
+ const tabInstance = tab;
56
+ const registerCommandOptions = (cmd, options) => {
57
+ for (const option of options) {
58
+ if (option.hidden) {
59
+ continue;
60
+ }
61
+ if (option.name) {
62
+ cmd.option(option.name, option.description || "");
63
+ }
64
+ if (option.alias) {
65
+ cmd.option(option.alias, option.description || "");
66
+ }
67
+ }
68
+ };
69
+ const registerCommands = (tabInstance2, commands) => {
70
+ for (const [commandName, command] of commands) {
71
+ if (command.name !== commandName || command.hidden) {
72
+ continue;
73
+ }
74
+ const cmd = tabInstance2.command(command.name, command.description || "");
75
+ if (command.options) {
76
+ registerCommandOptions(cmd, command.options);
77
+ }
78
+ }
79
+ };
80
+ const validateShell = (shell) => {
81
+ if (!validShells.includes(shell)) {
82
+ throw new CompletionError(`Invalid shell type: ${shell}`, "INVALID_SHELL", [
83
+ `Valid shells are: ${validShells.join(", ")}`,
84
+ "Shell will be auto-detected if not specified"
85
+ ]);
86
+ }
87
+ };
88
+ const validateRuntime = (runtime) => {
89
+ if (runtime && !validRuntimes.includes(runtime)) {
90
+ throw new CompletionError(`Invalid runtime: ${runtime}`, "INVALID_RUNTIME", [
91
+ `Valid runtimes are: ${validRuntimes.join(", ")}`,
92
+ "Runtime will be auto-detected if not specified"
93
+ ]);
94
+ }
95
+ };
96
+ const printUsageInstructions = (logger, cliName) => {
97
+ logger.error("Could not detect current shell");
98
+ const usageInfo = [
99
+ `Usage: ${cliName} completion --shell=<bash|zsh|fish|powershell> [--runtime=<node|bun|deno>]`,
100
+ "",
101
+ "Examples:",
102
+ ` # Install completions for zsh:`,
103
+ ` ${cliName} completion --shell=zsh > ~/.${cliName}-completion.zsh`,
104
+ ` echo 'source ~/.${cliName}-completion.zsh' >> ~/.zshrc`,
105
+ "",
106
+ ` # Install completions for bash with custom runtime:`,
107
+ ` ${cliName} completion --shell=bash --runtime=bun > ~/.${cliName}-completion.bash`,
108
+ ` echo 'source ~/.${cliName}-completion.bash' >> ~/.bashrc`,
109
+ "",
110
+ ` # Install completions for fish:`,
111
+ ` ${cliName} completion --shell=fish > ~/.config/fish/completions/${cliName}.fish`
112
+ ].join("\n");
113
+ logger.info(usageInfo);
114
+ };
115
+ const completionCommand = {
116
+ description: "Generate shell completion scripts",
117
+ env: [
118
+ {
119
+ description: "Shell path (Unix-like systems). Used for shell detection.",
120
+ name: "SHELL",
121
+ type: String
122
+ },
123
+ {
124
+ description: "Starship shell configuration. Takes precedence over SHELL for detection.",
125
+ name: "STARSHIP_SHELL",
126
+ type: String
127
+ },
128
+ {
129
+ description: "PowerShell module path (Windows). Used for PowerShell detection.",
130
+ name: "PSModulePath",
131
+ type: String
132
+ },
133
+ {
134
+ description: "Command prompt variable (Windows). Used for PowerShell detection.",
135
+ name: "PROMPT",
136
+ type: String
137
+ },
138
+ {
139
+ description: "Command processor (Windows). Used for Windows Command Prompt detection.",
140
+ name: "ComSpec",
141
+ type: String
142
+ }
143
+ ],
144
+ execute: async ({ env: toolboxEnv, logger, options, runtime }) => {
145
+ const cliName = runtime.getCliName();
146
+ const shell = options?.shell || detectShell(toolboxEnv);
147
+ if (!shell) {
148
+ printUsageInstructions(logger, cliName);
149
+ return;
150
+ }
151
+ try {
152
+ validateShell(shell);
153
+ validateRuntime(options?.runtime);
154
+ registerCommands(tabInstance, runtime.getCommands());
155
+ const jsRuntime = options?.runtime || detectRuntime();
156
+ const scriptPath = `${jsRuntime} ${cliName}`;
157
+ tabInstance.setup(cliName, scriptPath, shell);
158
+ } catch (error) {
159
+ if (error instanceof CompletionError) {
160
+ const errorMessages = [`Failed to generate completion script: ${error.message}`, `Error code: ${error.code}`];
161
+ if (error.troubleshooting.length > 0) {
162
+ errorMessages.push("", "Troubleshooting:", ...error.troubleshooting.map((tip) => ` • ${tip}`));
163
+ }
164
+ logger.error(errorMessages.join("\n"));
165
+ throw error;
166
+ } else {
167
+ const errorMessage = error instanceof Error ? error.message : String(error);
168
+ const errorMessages = [
169
+ "Failed to generate completion script",
170
+ `Error: ${errorMessage}`,
171
+ "",
172
+ "Troubleshooting:",
173
+ " • Ensure @bomb.sh/tab is installed: pnpm add @bomb.sh/tab",
174
+ ` • Verify shell is supported: ${validShells.join(", ")}`,
175
+ ` • Verify runtime is supported: ${validRuntimes.join(", ")}`,
176
+ " • Check that your CLI name is correct"
177
+ ];
178
+ logger.error(errorMessages.join("\n"));
179
+ }
180
+ }
181
+ },
182
+ name: "completion",
183
+ options: [
184
+ {
185
+ defaultOption: true,
186
+ defaultValue: detectShell(),
187
+ description: "Shell type (bash, zsh, fish, powershell). Defaults to current shell if detected.",
188
+ name: "shell",
189
+ type: String,
190
+ typeLabel: "{underline shell}"
191
+ },
192
+ {
193
+ defaultOption: true,
194
+ defaultValue: detectRuntime(),
195
+ description: "JavaScript runtime (node, bun, deno). Defaults to current runtime if detected.",
196
+ name: "runtime",
197
+ type: String,
198
+ typeLabel: "{underline runtime}"
199
+ }
200
+ ]
201
+ };
202
+
203
+ export { completionCommand as default };
@@ -1 +1,3 @@
1
- import"@visulima/colorize";import{D as p}from"../packem_shared/help-command-CIRIXN03.js";import"../packem_shared/index-DQ3pvLQH.js";export{p as default};
1
+ import '@visulima/colorize';
2
+ export { H as default } from '../packem_shared/help-command-BY7rQUvM.js';
3
+ import '../packem_shared/index-C2-8b3A4.js';
@@ -1,36 +1,265 @@
1
- var O=Object.defineProperty;var f=(e,n)=>O(e,"name",{value:n,configurable:!0});import{createRequire as L}from"node:module";import G from"github-slugger";import{p as U}from"../packem_shared/index-DQ3pvLQH.js";import{g as F,a as M,b as W,c as z}from"../packem_shared/runtime-process-G-n-wOub.js";const N=L(import.meta.url),g=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,w=f(e=>{if(typeof g<"u"&&g.versions&&g.versions.node){const[n,t]=g.versions.node.split(".").map(Number);if(n>22||n===22&&t>=3||n===20&&t>=16)return g.getBuiltinModule(e)}return N(e)},"__cjs_getBuiltinModule"),{existsSync:E}=w("node:fs"),{readFile:T,mkdir:k,writeFile:B}=w("node:fs/promises"),{resolve:v,join:V,dirname:q}=w("node:path");var H=Object.defineProperty,d=f((e,n)=>H(e,"name",{value:n,configurable:!0}),"d");const I=new G,b=I.slug,J=d(e=>e.filter(Boolean),"compact"),K=d((e,n)=>{const t=new Set,a=[];for(const r of e){const i=n(r);t.has(i)||(t.add(i),a.push(r))}return a},"uniqBy"),D=d((e,n)=>{const t=(e.commandPath?[...e.commandPath,e.name]:[e.name]).join(" ");if(e.argument){const a=e.argument.name?.toUpperCase()??"ARG",r=e.argument.required?a:`[${a}]`;return`${n} ${t} ${r}`}return`${n} ${t}`},"formatCommandUsage"),Q=d((e,n)=>{if(!Array.isArray(e.env)||e.env.length===0)return;const t=e.env.filter(a=>!a.hidden);t.length>0&&n.push({content:t.map(a=>[a.name,a.description??""]),header:" Environment Variables "})},"addEnvironmentVariables"),X=d((e,n)=>{const t=[],a=(e.commandPath?[...e.commandPath,e.name]:[e.name]).join(" "),r=!!e.argument,i=!!e.options;if(t.push({content:`${n} ${a}${r?" [positional arguments]":""}${i?" [options]":""}`,header:" Usage "}),e.description&&t.push({content:e.description,header:" Description "}),e.argument&&t.push({header:"Command Positional Arguments",isArgument:!0,optionList:[e.argument]}),Array.isArray(e.options)&&e.options.length>0&&t.push({header:" Command Options ",optionList:e.options.filter(o=>typeof o=="object"&&o!==null&&(!("hidden"in o)||!o.hidden))}),Q(e,t),e.alias!==void 0&&e.alias.length>0){const o=Array.isArray(e.alias)?e.alias:[e.alias];t.splice(1,0,{content:o,header:"Alias(es)"})}return Array.isArray(e.examples)&&e.examples.length>0&&t.push({content:e.examples,header:"Examples"}),U(t)},"formatCommandHelp"),Y=d((e,n)=>{const t=e.description?.trim().split(`
2
- `)[0]??"",a=D(e,n),r=X(e,n);return J([`## \`${a}\``,t,`\`\`\`
3
- ${r.trim()}
4
- \`\`\``]).join(`
5
-
6
- `)},"renderCommand"),Z=d((e,n,t,a)=>{const r=`(${["--version","-V"].join("|")})`,i=W(),o=z();return`\`\`\`sh-session
7
- $ npm install -g ${n}
8
- $ ${e} COMMAND
1
+ import { createRequire as __cjs_createRequire } from "node:module";
2
+
3
+ const __cjs_require = __cjs_createRequire(import.meta.url);
4
+
5
+ const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process;
6
+
7
+ const __cjs_getBuiltinModule = (module) => {
8
+ // Check if we're in Node.js and version supports getBuiltinModule
9
+ if (typeof __cjs_getProcess !== "undefined" && __cjs_getProcess.versions && __cjs_getProcess.versions.node) {
10
+ const [major, minor] = __cjs_getProcess.versions.node.split(".").map(Number);
11
+ // Node.js 20.16.0+ and 22.3.0+
12
+ if (major > 22 || (major === 22 && minor >= 3) || (major === 20 && minor >= 16)) {
13
+ return __cjs_getProcess.getBuiltinModule(module);
14
+ }
15
+ }
16
+ // Fallback to createRequire
17
+ return __cjs_require(module);
18
+ };
19
+
20
+ const {
21
+ existsSync
22
+ } = __cjs_getBuiltinModule("node:fs");
23
+ const {
24
+ readFile,
25
+ mkdir,
26
+ writeFile
27
+ } = __cjs_getBuiltinModule("node:fs/promises");
28
+ const {
29
+ resolve,
30
+ join,
31
+ dirname
32
+ } = __cjs_getBuiltinModule("node:path");
33
+ import GithubSlugger from 'github-slugger';
34
+ import { c as commandLineUsage } from '../packem_shared/index-C2-8b3A4.js';
35
+ import { g as getCwd, a as getVersions, b as getPlatform, c as getArch } from '../packem_shared/runtime-process-B6ZplyWn.js';
36
+
37
+ const slugger = new GithubSlugger();
38
+ const slugify = slugger.slug;
39
+ const compact = (array) => array.filter(Boolean);
40
+ const uniqBy = (array, keyFunction) => {
41
+ const seen = /* @__PURE__ */ new Set();
42
+ const result = [];
43
+ for (const item of array) {
44
+ const key = keyFunction(item);
45
+ if (!seen.has(key)) {
46
+ seen.add(key);
47
+ result.push(item);
48
+ }
49
+ }
50
+ return result;
51
+ };
52
+ const formatCommandUsage = (command, cliName) => {
53
+ const fullPath = command.commandPath ? [...command.commandPath, command.name] : [command.name];
54
+ const commandId = fullPath.join(" ");
55
+ if (command.argument) {
56
+ const argumentName = command.argument.name?.toUpperCase() ?? "ARG";
57
+ const argumentString = command.argument.required ? argumentName : `[${argumentName}]`;
58
+ return `${cliName} ${commandId} ${argumentString}`;
59
+ }
60
+ return `${cliName} ${commandId}`;
61
+ };
62
+ const addEnvironmentVariables = (command, usageGroups) => {
63
+ if (!Array.isArray(command.env) || command.env.length === 0) {
64
+ return;
65
+ }
66
+ const visibleEnvVariables = command.env.filter((envVariable) => !envVariable.hidden);
67
+ if (visibleEnvVariables.length > 0) {
68
+ usageGroups.push({
69
+ content: visibleEnvVariables.map((envVariable) => [envVariable.name, envVariable.description ?? ""]),
70
+ header: " Environment Variables "
71
+ });
72
+ }
73
+ };
74
+ const formatCommandHelp = (command, cliName) => {
75
+ const usageGroups = [];
76
+ const fullCommandPath = command.commandPath ? [...command.commandPath, command.name] : [command.name];
77
+ const commandDisplay = fullCommandPath.join(" ");
78
+ const hasArgument = Boolean(command.argument);
79
+ const hasOptions = Boolean(command.options);
80
+ usageGroups.push({
81
+ content: `${cliName} ${commandDisplay}${hasArgument ? " [positional arguments]" : ""}${hasOptions ? " [options]" : ""}`,
82
+ header: " Usage "
83
+ });
84
+ if (command.description) {
85
+ usageGroups.push({ content: command.description, header: " Description " });
86
+ }
87
+ if (command.argument) {
88
+ usageGroups.push({ header: "Command Positional Arguments", isArgument: true, optionList: [command.argument] });
89
+ }
90
+ if (Array.isArray(command.options) && command.options.length > 0) {
91
+ usageGroups.push({
92
+ header: " Command Options ",
93
+ optionList: command.options.filter(
94
+ (option) => typeof option === "object" && option !== null && (!("hidden" in option) || !option.hidden)
95
+ )
96
+ });
97
+ }
98
+ addEnvironmentVariables(command, usageGroups);
99
+ if (command.alias !== void 0 && command.alias.length > 0) {
100
+ const alias = Array.isArray(command.alias) ? command.alias : [command.alias];
101
+ usageGroups.splice(1, 0, {
102
+ content: alias,
103
+ header: "Alias(es)"
104
+ });
105
+ }
106
+ if (Array.isArray(command.examples) && command.examples.length > 0) {
107
+ usageGroups.push({
108
+ content: command.examples,
109
+ header: "Examples"
110
+ });
111
+ }
112
+ return commandLineUsage(usageGroups);
113
+ };
114
+ const renderCommand = (command, cliName) => {
115
+ const title = command.description?.trim().split("\n")[0] ?? "";
116
+ const usage = formatCommandUsage(command, cliName);
117
+ const helpText = formatCommandHelp(command, cliName);
118
+ return compact([`## \`${usage}\``, title, `\`\`\`
119
+ ${helpText.trim()}
120
+ \`\`\``]).join("\n\n");
121
+ };
122
+ const generateUsage = (cliName, packageName, version, nodeVersion) => {
123
+ const versionFlags = ["--version", "-V"];
124
+ const versionFlagsString = `(${versionFlags.join("|")})`;
125
+ const platform = getPlatform();
126
+ const arch = getArch();
127
+ return `\`\`\`sh-session
128
+ $ npm install -g ${packageName}
129
+ $ ${cliName} COMMAND
9
130
  running command...
10
- $ ${e} ${r}
11
- ${n}/${t??"unknown"} ${i}-${o} node-v${a}
12
- $ ${e} --help [COMMAND]
131
+ $ ${cliName} ${versionFlagsString}
132
+ ${packageName}/${version ?? "unknown"} ${platform}-${arch} node-v${nodeVersion}
133
+ $ ${cliName} --help [COMMAND]
13
134
  USAGE
14
- $ ${e} COMMAND
135
+ $ ${cliName} COMMAND
15
136
  ...
16
137
  \`\`\`
17
- `},"generateUsage"),R=d(async(e,n,t)=>{const a=await Promise.all(e.map(async i=>{const o=D(i,n);return`* [\`${o}\`](#${await b(o)})`})),r=e.map(i=>Y(i,n)).map(i=>`${i.trim()}
18
- `);return[...a,"",...r].join(`
19
- `).trim()},"generateCommands"),j=d(async(e,n)=>{const t=q(e);E(t)||await k(t,{recursive:!0}),await B(e,n,"utf8")},"writeFileWithDirectory"),ee=d(async(e,n,t,a)=>{const r=new Map;for(const o of e){const s=o.group??"__Other",l=r.get(s)??[];l.push(o),r.set(s,l)}const i=[...r.entries()].map(([o,s])=>o==="__Other"?["Other",s]:[o,s]);return await Promise.all(i.map(async([o,s])=>{const l=o.replaceAll(":","/"),$=V(".",n,`${l}.md`),p=`\`${t} ${o}\``,c=`${[p,"=".repeat(p.length),"",`Commands in the ${o} group.`,"",await R(s,t,a)].join(`
20
- `).trim()}
21
- `;a.dryRun||await j(v(M(),$),c)})),`${[`# Command Topics
22
- `,...i.map(([o])=>{const s=o.replaceAll(":","/");return`* [\`${t} ${o}\`](${n}/${s}.md)`})].join(`
23
- `).trim()}
24
- `},"generateMultiCommands"),A=d(e=>e.replaceAll(`\r
25
- `,`
26
- `).replaceAll("\r",`
27
- `),"normalizeLineEndings"),te=d(async e=>{const n=A(e);return(await Promise.all(n.split(`
28
- `).filter(t=>t.startsWith("# ")).map(t=>t.trim().slice(2)).map(async t=>`* [${t}](#${await b(t)})`))).join(`
29
- `)},"generateTableOfContents"),P=d(e=>e.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`),"escapeRegex"),y=d((e,n,t)=>{const a=A(e),r=`<!-- ${n} -->`,i=`<!-- ${n}stop -->`;if(a.includes(r)&&a.includes(i)){const o=P(r),s=P(i),l=new RegExp(String.raw`${o}(.|\n)*${s}`,"m");return a.replace(l,`${r}
30
- ${t}
31
- ${i}`)}return a.replace(r,`${r}
32
- ${t}
33
- ${i}`)},"replaceTag"),se={description:"Generate README documentation for CLI commands",execute:d(async({logger:e,options:n,runtime:t})=>{const a=t.getCliName(),r=t.getPackageName()??a,i=t.getPackageVersion(),o=F().node??"unknown",s={aliases:n?.aliases,dryRun:n?.dryRun,multi:n?.multi,nestedTopicsDepth:n?.nestedTopicsDepth,outputDir:n?.outputDir??"docs",readmePath:n?.readmePath??"README.md",repositoryPrefix:n?.repositoryPrefix,version:n?.version??i??void 0},l=t.getCommands(),$=[...l.values()].filter(m=>!m.hidden).filter(m=>s.aliases?!0:m.name===l.get(m.name)?.name).toSorted((m,h)=>{const _=m.commandPath?[...m.commandPath,m.name].join(" "):m.name,S=h.commandPath?[...h.commandPath,h.name].join(" "):h.name;return _.localeCompare(S)}),p=K($,m=>m.commandPath?[...m.commandPath,m.name].join(" "):m.name);e.debug(`Processing ${p.length} commands for README generation`);let c;const u=v(M(),s.readmePath??"README.md");if(E(u)){const m=await T(u,"utf8");c=A(m)}else e.warn(`README file not found at ${u}, creating template`),c=`# ${r}
138
+ `;
139
+ };
140
+ const generateCommands = async (commands, cliName, _options) => {
141
+ const commandList = await Promise.all(
142
+ commands.map(async (command) => {
143
+ const usage = formatCommandUsage(command, cliName);
144
+ return `* [\`${usage}\`](#${await slugify(usage)})`;
145
+ })
146
+ );
147
+ const commandDocumentation = commands.map((command) => renderCommand(command, cliName)).map((s) => `${s.trim()}
148
+ `);
149
+ return [...commandList, "", ...commandDocumentation].join("\n").trim();
150
+ };
151
+ const writeFileWithDirectory = async (filePath, content) => {
152
+ const directory = dirname(filePath);
153
+ if (!existsSync(directory)) {
154
+ await mkdir(directory, { recursive: true });
155
+ }
156
+ await writeFile(filePath, content, "utf8");
157
+ };
158
+ const generateMultiCommands = async (commands, outputDirectory, cliName, options) => {
159
+ const groupedCommands = /* @__PURE__ */ new Map();
160
+ for (const command of commands) {
161
+ const group = command.group ?? "__Other";
162
+ const groupCommands = groupedCommands.get(group) ?? [];
163
+ groupCommands.push(command);
164
+ groupedCommands.set(group, groupCommands);
165
+ }
166
+ const groups = [...groupedCommands.entries()].map(([group, groupCommands]) => {
167
+ if (group === "__Other") {
168
+ return ["Other", groupCommands];
169
+ }
170
+ return [group, groupCommands];
171
+ });
172
+ await Promise.all(
173
+ groups.map(async ([group, groupCommands]) => {
174
+ const groupPath = group.replaceAll(":", "/");
175
+ const filePath = join(".", outputDirectory, `${groupPath}.md`);
176
+ const bin = `\`${cliName} ${group}\``;
177
+ const document = `${[
178
+ bin,
179
+ "=".repeat(bin.length),
180
+ "",
181
+ `Commands in the ${group} group.`,
182
+ "",
183
+ await generateCommands(groupCommands, cliName)
184
+ ].join("\n").trim()}
185
+ `;
186
+ if (!options.dryRun) {
187
+ await writeFileWithDirectory(resolve(getCwd(), filePath), document);
188
+ }
189
+ })
190
+ );
191
+ const topicLinks = groups.map(([group]) => {
192
+ const groupPath = group.replaceAll(":", "/");
193
+ return `* [\`${cliName} ${group}\`](${outputDirectory}/${groupPath}.md)`;
194
+ });
195
+ return `${["# Command Topics\n", ...topicLinks].join("\n").trim()}
196
+ `;
197
+ };
198
+ const normalizeLineEndings = (text) => text.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
199
+ const generateTableOfContents = async (readme) => {
200
+ const normalizedReadme = normalizeLineEndings(readme);
201
+ const toc = await Promise.all(
202
+ normalizedReadme.split("\n").filter((line) => line.startsWith("# ")).map((line) => line.trim().slice(2)).map(async (line) => `* [${line}](#${await slugify(line)})`)
203
+ );
204
+ return toc.join("\n");
205
+ };
206
+ const escapeRegex = (string_) => string_.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
207
+ const replaceTag = (readme, tag, body) => {
208
+ const normalizedReadme = normalizeLineEndings(readme);
209
+ const tagStart = `<!-- ${tag} -->`;
210
+ const tagStop = `<!-- ${tag}stop -->`;
211
+ if (normalizedReadme.includes(tagStart) && normalizedReadme.includes(tagStop)) {
212
+ const escapedStart = escapeRegex(tagStart);
213
+ const escapedStop = escapeRegex(tagStop);
214
+ const tagPattern = new RegExp(String.raw`${escapedStart}(.|\n)*${escapedStop}`, "m");
215
+ return normalizedReadme.replace(tagPattern, `${tagStart}
216
+ ${body}
217
+ ${tagStop}`);
218
+ }
219
+ return normalizedReadme.replace(tagStart, `${tagStart}
220
+ ${body}
221
+ ${tagStop}`);
222
+ };
223
+ const readmeCommand = {
224
+ description: "Generate README documentation for CLI commands",
225
+ execute: async ({ logger, options, runtime }) => {
226
+ const cliName = runtime.getCliName();
227
+ const packageName = runtime.getPackageName() ?? cliName;
228
+ const packageVersion = runtime.getPackageVersion();
229
+ const versions = getVersions();
230
+ const nodeVersion = versions.node ?? "unknown";
231
+ const readmeOptions = {
232
+ aliases: options?.aliases,
233
+ dryRun: options?.dryRun,
234
+ multi: options?.multi,
235
+ outputDir: options?.outputDir ?? "docs",
236
+ readmePath: options?.readmePath ?? "README.md",
237
+ version: options?.version ?? packageVersion ?? void 0
238
+ };
239
+ const commandsMap = runtime.getCommands();
240
+ const commands = [...commandsMap.values()].filter((c) => !c.hidden).filter((c) => {
241
+ if (readmeOptions.aliases) {
242
+ return true;
243
+ }
244
+ return c.name === commandsMap.get(c.name)?.name;
245
+ }).toSorted((a, b) => {
246
+ const aPath = a.commandPath ? [...a.commandPath, a.name].join(" ") : a.name;
247
+ const bPath = b.commandPath ? [...b.commandPath, b.name].join(" ") : b.name;
248
+ return aPath.localeCompare(bPath);
249
+ });
250
+ const uniqueCommands = uniqBy(commands, (c) => {
251
+ const path = c.commandPath ? [...c.commandPath, c.name].join(" ") : c.name;
252
+ return path;
253
+ });
254
+ logger.debug(`Processing ${uniqueCommands.length} commands for README generation`);
255
+ let readme;
256
+ const readmePath = resolve(getCwd(), readmeOptions.readmePath ?? "README.md");
257
+ if (existsSync(readmePath)) {
258
+ const rawReadme = await readFile(readmePath, "utf8");
259
+ readme = normalizeLineEndings(rawReadme);
260
+ } else {
261
+ logger.warn(`README file not found at ${readmePath}, creating template`);
262
+ readme = `# ${packageName}
34
263
 
35
264
  <!-- usage -->
36
265
  <!-- usagestop -->
@@ -40,6 +269,75 @@ ${i}`)},"replaceTag"),se={description:"Generate README documentation for CLI com
40
269
 
41
270
  <!-- toc -->
42
271
  <!-- tocstop -->
43
- `;const C=s.outputDir??"docs",x=s.version??i??"unknown";c=y(c,"usage",Z(a,r,x,o)),c=y(c,"commands",s.multi?await ee(p,C,a,s):await R(p,a,s)),c=y(c,"toc",await te(c)),c=`${c.trimEnd()}
44
- `,s.dryRun?(e.info("Dry run mode - README not written"),e.info(`Generated README content:
45
- ${c}`)):(await j(u,c),e.info(`README generated successfully at ${u}`))},"execute"),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{se as default};
272
+ `;
273
+ }
274
+ const outputDirectory = readmeOptions.outputDir ?? "docs";
275
+ const version = readmeOptions.version ?? packageVersion ?? "unknown";
276
+ readme = replaceTag(readme, "usage", generateUsage(cliName, packageName, version, nodeVersion));
277
+ readme = replaceTag(
278
+ readme,
279
+ "commands",
280
+ readmeOptions.multi ? await generateMultiCommands(uniqueCommands, outputDirectory, cliName, readmeOptions) : await generateCommands(uniqueCommands, cliName)
281
+ );
282
+ readme = replaceTag(readme, "toc", await generateTableOfContents(readme));
283
+ readme = `${readme.trimEnd()}
284
+ `;
285
+ if (readmeOptions.dryRun) {
286
+ logger.info("Dry run mode - README not written");
287
+ logger.info(`Generated README content:
288
+ ${readme}`);
289
+ } else {
290
+ await writeFileWithDirectory(readmePath, readme);
291
+ logger.info(`README generated successfully at ${readmePath}`);
292
+ }
293
+ },
294
+ name: "readme",
295
+ options: [
296
+ {
297
+ description: "Include aliases in command list",
298
+ name: "aliases",
299
+ type: Boolean
300
+ },
301
+ {
302
+ description: "Show what would be generated without writing files",
303
+ name: "dry-run",
304
+ type: Boolean
305
+ },
306
+ {
307
+ description: "Generate multi-file documentation by command groups",
308
+ name: "multi",
309
+ type: Boolean
310
+ },
311
+ {
312
+ description: "Maximum depth for nested topics when using multi-file mode",
313
+ name: "nested-topics-depth",
314
+ type: Number
315
+ },
316
+ {
317
+ description: "Output directory for multi-file documentation",
318
+ name: "output-dir",
319
+ type: String,
320
+ typeLabel: "{underline directory}"
321
+ },
322
+ {
323
+ description: "Path to README file to generate",
324
+ name: "readme-path",
325
+ type: String,
326
+ typeLabel: "{underline path}"
327
+ },
328
+ {
329
+ description: "Repository prefix for code links",
330
+ name: "repository-prefix",
331
+ type: String,
332
+ typeLabel: "{underline prefix}"
333
+ },
334
+ {
335
+ description: "Version to use in generated documentation",
336
+ name: "version",
337
+ type: String,
338
+ typeLabel: "{underline version}"
339
+ }
340
+ ]
341
+ };
342
+
343
+ export { readmeCommand as default };