@visulima/cerebro 3.0.0-alpha.9 → 3.0.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 +593 -0
- package/LICENSE.md +1295 -3950
- package/README.md +182 -2
- package/dist/commands/completion-command.d.ts +6 -5
- package/dist/commands/completion-command.js +5 -203
- package/dist/commands/help-command.d.ts +10 -9
- package/dist/commands/help-command.js +1 -3
- package/dist/commands/readme-command.d.ts +6 -5
- package/dist/commands/readme-command.js +32 -330
- package/dist/commands/version-command.d.ts +4 -3
- package/dist/commands/version-command.js +1 -18
- package/dist/index.d.ts +516 -95
- package/dist/index.js +1 -7
- package/dist/logger/create-pail-logger.d.ts +770 -8
- package/dist/logger/create-pail-logger.js +1 -34
- package/dist/packem_chunks/has-new-version.js +1 -259
- package/dist/packem_shared/Cerebro-Czc4t-75.js +4 -0
- package/dist/packem_shared/VERBOSITY_DEBUG-XPultrIA.js +1 -0
- package/dist/packem_shared/VisulimaError-C90oeIMu.js +76 -0
- package/dist/packem_shared/VisulimaError-DTMgXonA-CzaryRgZ.js +1 -0
- package/dist/packem_shared/cerebro-error-BjBcYVRO.js +1 -0
- package/dist/packem_shared/command.d-DbhtfXF4.d.ts +639 -0
- package/dist/packem_shared/index-DvVGK4kr.js +29 -0
- package/dist/packem_shared/index.d-BL4NtVR3.d.ts +127 -0
- package/dist/packem_shared/lazyNamed-DMUm8mZe.js +1 -0
- package/dist/packem_shared/renderError-B3ePOoBG-BmZlyMcr.js +25 -0
- package/dist/packem_shared/runtime-process-Dmz0vCJy.js +1 -0
- package/dist/packem_shared/split-by-case-Dbpgd7rf.js +1 -0
- package/dist/plugins/error-handler-plugin.d.ts +21 -19
- package/dist/plugins/error-handler-plugin.js +1 -636
- package/dist/plugins/runtime-version-check-plugin.d.ts +22 -20
- package/dist/plugins/runtime-version-check-plugin.js +1 -77
- package/dist/plugins/update-notifier/update-notifier-plugin.d.ts +28 -8
- package/dist/plugins/update-notifier/update-notifier-plugin.js +1 -517
- package/dist/util/general/compile-cache.d.ts +41 -0
- package/dist/util/general/compile-cache.js +1 -0
- package/dist/util/general/heap-tuning.d.ts +18 -0
- package/dist/util/general/heap-tuning.js +1 -0
- package/package.json +53 -48
- package/dist/cli.d.ts +0 -203
- package/dist/constants.d.ts +0 -29
- package/dist/default-env.d.ts +0 -7
- package/dist/default-options.d.ts +0 -3
- package/dist/empty-toolbox.d.ts +0 -15
- package/dist/errors/cerebro-error.d.ts +0 -10
- package/dist/errors/command-not-found-error.d.ts +0 -9
- package/dist/errors/command-validation-error.d.ts +0 -10
- package/dist/errors/completion-error.d.ts +0 -9
- package/dist/errors/conflicting-options-error.d.ts +0 -10
- package/dist/errors/plugin-error.d.ts +0 -9
- package/dist/errors/update-notifier-error.d.ts +0 -7
- package/dist/packem_shared/Cerebro-C2mnCyQf.js +0 -3313
- package/dist/packem_shared/VERBOSITY_QUIET-Dp46zlLW.js +0 -10
- package/dist/packem_shared/VisulimaError-DA7QsCxH.js +0 -34
- package/dist/packem_shared/cerebro-error-GmJ3jN7Q.js +0 -16
- package/dist/packem_shared/help-command-BY7rQUvM.js +0 -249
- package/dist/packem_shared/index-C2-8b3A4.js +0 -259
- package/dist/packem_shared/runtime-process-B6ZplyWn.js +0 -187
- package/dist/plugin-manager.d.ts +0 -53
- package/dist/plugins/update-notifier/cache.d.ts +0 -11
- package/dist/plugins/update-notifier/get-distribution-version.d.ts +0 -2
- package/dist/plugins/update-notifier/has-new-version.d.ts +0 -14
- package/dist/types/cli.d.ts +0 -102
- package/dist/types/command-line-usage.d.ts +0 -37
- package/dist/types/command.d.ts +0 -136
- package/dist/types/option-types.d.ts +0 -83
- package/dist/types/options.d.ts +0 -4
- package/dist/types/plugin.d.ts +0 -53
- package/dist/types/toolbox.d.ts +0 -96
- package/dist/util/arg-processing/get-boolean-values.d.ts +0 -7
- package/dist/util/arg-processing/get-parameter-option.d.ts +0 -7
- package/dist/util/arg-processing/map-option-type-label.d.ts +0 -3
- package/dist/util/arg-processing/option-is-boolean.d.ts +0 -9
- package/dist/util/arg-processing/remove-boolean-values.d.ts +0 -9
- package/dist/util/command-line-commands.d.ts +0 -10
- package/dist/util/command-line-usage/get-terminal-width.d.ts +0 -7
- package/dist/util/command-line-usage/index.d.ts +0 -3
- package/dist/util/command-line-usage/section/base-section.d.ts +0 -8
- package/dist/util/command-line-usage/section/content-section.d.ts +0 -65
- package/dist/util/command-line-usage/section/option-list-section.d.ts +0 -44
- package/dist/util/command-processing/command-processor.d.ts +0 -37
- package/dist/util/command-processing/command-validation.d.ts +0 -17
- package/dist/util/command-processing/nested-command-parser.d.ts +0 -25
- package/dist/util/command-processing/option-processor.d.ts +0 -44
- package/dist/util/data-processing/list-missing-arguments.d.ts +0 -15
- package/dist/util/data-processing/merge-arguments.d.ts +0 -7
- package/dist/util/general/find-alternatives.d.ts +0 -8
- package/dist/util/general/hide-bin.d.ts +0 -2
- package/dist/util/general/parse-raw-command.d.ts +0 -7
- package/dist/util/general/register-exception-handler.d.ts +0 -9
- package/dist/util/general/runtime-process.d.ts +0 -65
- package/dist/util/general/semver-gt.d.ts +0 -2
- package/dist/util/general/validate-input.d.ts +0 -24
- package/dist/util/process-env-variables.d.ts +0 -9
- package/dist/util/security.d.ts +0 -58
- package/dist/util/text-processing/template-format.d.ts +0 -5
package/README.md
CHANGED
|
@@ -158,16 +158,45 @@ You should see help output and command execution based on the options provided:
|
|
|
158
158
|
|
|
159
159
|

|
|
160
160
|
|
|
161
|
+
## Lazy commands
|
|
162
|
+
|
|
163
|
+
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()`:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
// commands/build.ts
|
|
167
|
+
export default ({ logger, options }) => {
|
|
168
|
+
logger.info(`Building to ${options.output ?? "dist"}`);
|
|
169
|
+
};
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
// index.ts
|
|
174
|
+
cli.addCommand({
|
|
175
|
+
name: "build",
|
|
176
|
+
description: "Build the project",
|
|
177
|
+
options: [{ name: "output", alias: "o", type: String, description: "Output directory" }],
|
|
178
|
+
argument: { name: "target", type: String },
|
|
179
|
+
loader: () => import("./commands/build"),
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`loader` is a zero-argument function that returns a promise resolving to a module — typically `() => import("./path")`. The handler module's **default export** is the toolbox-receiving function. Help, completion, and option validation work entirely from the metadata you declared on `addCommand` and never trigger the loader. The first invocation of the command imports the module; subsequent calls reuse the cached handler.
|
|
184
|
+
|
|
185
|
+
A command may declare either `execute` or `loader`, but not both. If a loader rejects or returns a module without a default-exported function, a `CommandLoaderError` is thrown.
|
|
186
|
+
|
|
161
187
|
## Toolbox API
|
|
162
188
|
|
|
163
189
|
When your command's `execute` function is called, it receives a toolbox object with various utilities and context. Here's what you can access:
|
|
164
190
|
|
|
165
191
|
### Core Properties
|
|
166
192
|
|
|
167
|
-
- **`logger`**: Logger instance for output (debug, info, warn, error)
|
|
193
|
+
- **`logger`**: Logger instance for output (debug, info, warn, error). Verbosity-gated via `--quiet`/`--verbose`/`--debug`.
|
|
194
|
+
- **`console`**: Alias for `logger`. Use it when porting goke-style code or when a `console`-named parameter reads more naturally.
|
|
168
195
|
- **`options`**: Parsed command-line options (camelCase keys)
|
|
169
196
|
- **`argument`**: Array of positional arguments
|
|
170
|
-
- **`env`**: Environment variables (camelCase keys)
|
|
197
|
+
- **`env`**: Environment variables (camelCase keys) processed from the command's `env: [...]` definitions
|
|
198
|
+
- **`fs`**: Injected filesystem adapter (subset of `node:fs/promises`). Swap via `CliOptions.fs` for tests or sandboxed runtimes.
|
|
199
|
+
- **`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.
|
|
171
200
|
- **`runtime`**: Reference to the CLI instance
|
|
172
201
|
- **`argv`**: Original command-line arguments array
|
|
173
202
|
|
|
@@ -215,6 +244,157 @@ cli.addCommand({
|
|
|
215
244
|
});
|
|
216
245
|
```
|
|
217
246
|
|
|
247
|
+
## Runtime Injection
|
|
248
|
+
|
|
249
|
+
Commands receive an injected `{ fs, console, process }` context on the toolbox. Prefer reading from these over reaching for `node:fs/promises`, the global `console`, or the global `process` — commands written against the injected context stay testable, portable across Node/Deno/Bun, and ready to run inside sandboxed environments like MCP servers.
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
import { Cerebro } from "@visulima/cerebro";
|
|
253
|
+
|
|
254
|
+
const cli = new Cerebro("acme");
|
|
255
|
+
|
|
256
|
+
cli.addCommand({
|
|
257
|
+
name: "login",
|
|
258
|
+
description: "Save an auth token",
|
|
259
|
+
options: [{ name: "token", type: String, description: "API token" }],
|
|
260
|
+
execute: async ({ fs, console, process, options }) => {
|
|
261
|
+
await fs.mkdir(".acme", { recursive: true });
|
|
262
|
+
await fs.writeFile(".acme/auth.json", JSON.stringify({ token: options.token }), "utf8");
|
|
263
|
+
console.log("saved credentials in", process.cwd);
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
await cli.run();
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Overriding the runtime
|
|
271
|
+
|
|
272
|
+
Pass any of the new `CliOptions` to swap the runtime context. Each override defaults to a sensible host value:
|
|
273
|
+
|
|
274
|
+
| Option | Default | Used for |
|
|
275
|
+
| --------------- | ---------------------------- | ---------------------------------------------------------------------------------- |
|
|
276
|
+
| `fs` | `node:fs/promises` adapter | Filesystem operations from `toolbox.fs` |
|
|
277
|
+
| `exit` | Runtime-agnostic exit helper | `toolbox.process.exit` |
|
|
278
|
+
| `env` | Host `process.env` | `toolbox.process.env` (does **not** affect `toolbox.env`) |
|
|
279
|
+
| `stdin` | `""` (empty string) | `toolbox.process.stdin` |
|
|
280
|
+
| `cwd` | Runtime cwd | `toolbox.process.cwd` |
|
|
281
|
+
| `logger` | Verbosity-aware console shim | `toolbox.logger` and `toolbox.console` |
|
|
282
|
+
| `maxArguments` | A very generous cap | Upper bound on argv tokens; set `Number.POSITIVE_INFINITY` to disable entirely |
|
|
283
|
+
| `strictOptions` | `false` | Reject unknown `--options` (before `--`) with a did-you-mean instead of swallowing |
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
const exitSpy = vi.fn();
|
|
287
|
+
const fakeFs = new InMemoryFs();
|
|
288
|
+
|
|
289
|
+
const cli = new Cerebro("acme", {
|
|
290
|
+
cwd: "/virtual/project",
|
|
291
|
+
fs: fakeFs,
|
|
292
|
+
exit: exitSpy,
|
|
293
|
+
env: { NODE_ENV: "test" },
|
|
294
|
+
stdin: "y\n",
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Testing with mocked runtime
|
|
299
|
+
|
|
300
|
+
The runtime overrides remove the need for `vi.spyOn(process, "exit")` or `vi.spyOn(console, "log")` in command tests. Pass mocks at CLI construction; assert on them directly.
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
import { describe, expect, test, vi } from "vitest";
|
|
304
|
+
import { Cerebro } from "@visulima/cerebro";
|
|
305
|
+
|
|
306
|
+
describe("deploy command", () => {
|
|
307
|
+
test("exits with code 2 when env is missing", async () => {
|
|
308
|
+
const exit = vi.fn();
|
|
309
|
+
const calls: string[] = [];
|
|
310
|
+
const logger = {
|
|
311
|
+
log: (...args: unknown[]) => calls.push(String(args[0])),
|
|
312
|
+
info: () => {},
|
|
313
|
+
warn: () => {},
|
|
314
|
+
error: () => {},
|
|
315
|
+
debug: () => {},
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
const cli = new Cerebro("acme", { argv: ["deploy"], exit, logger });
|
|
319
|
+
cli.addCommand({
|
|
320
|
+
name: "deploy",
|
|
321
|
+
execute: ({ console, process, options }) => {
|
|
322
|
+
if (!options.env) {
|
|
323
|
+
console.log("missing --env");
|
|
324
|
+
process.exit(2);
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
await cli.run({ shouldExitProcess: false });
|
|
330
|
+
|
|
331
|
+
expect(exit).toHaveBeenCalledWith(2);
|
|
332
|
+
expect(calls).toStrictEqual(["missing --env"]);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### `cli.clone(options?)`
|
|
338
|
+
|
|
339
|
+
Creates an independent CLI sharing the same command definitions. The clone has its own commands map, global options, default-command setting, and plugin manager — so adding commands or changing options on the clone never mutates the original. Primarily useful in tests to run the same CLI with different `argv`/`exit`/`fs` overrides without rebuilding the command tree.
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
const cli = new Cerebro("acme");
|
|
343
|
+
cli.addCommand({ name: "build", execute: ({ console }) => console.log("building") });
|
|
344
|
+
|
|
345
|
+
// In tests: clone with mocked exit + captured argv
|
|
346
|
+
const isolatedExit = vi.fn();
|
|
347
|
+
const isolated = cli.clone({ argv: ["build"], exit: isolatedExit });
|
|
348
|
+
await isolated.run({ shouldExitProcess: false });
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### `cli.getAction(commandName)`
|
|
352
|
+
|
|
353
|
+
Returns the resolved `execute` function for a registered command. For lazy commands defined with `loader`, the module is loaded once and cached. Supports space-separated nested command paths.
|
|
354
|
+
|
|
355
|
+
```ts
|
|
356
|
+
const cli = new Cerebro("acme");
|
|
357
|
+
|
|
358
|
+
cli.addCommand({
|
|
359
|
+
name: "deploy",
|
|
360
|
+
execute: ({ console, options }) => console.log("deploying to", options.env),
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
// Call the action directly with a synthesized toolbox — no argv parsing.
|
|
364
|
+
const action = await cli.getAction("deploy");
|
|
365
|
+
await action({ console: fakeConsole, options: { env: "staging" } } as never);
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Use this when you want to unit-test a command action in isolation without going through `run()`'s full lifecycle (plugin init, exception handlers, exit). For end-to-end tests that exercise argv parsing and lifecycle hooks, prefer `cli.clone(...).run(...)` instead.
|
|
369
|
+
|
|
370
|
+
## Validating option values with `choices`
|
|
371
|
+
|
|
372
|
+
Restrict an option to a fixed set of values, validated at parse time (like commander's `.choices()` / yargs `choices`). For `multiple` options every provided value must be a member of the set. An invalid value throws an `InvalidChoiceError` with a hint listing the allowed values.
|
|
373
|
+
|
|
374
|
+
```ts
|
|
375
|
+
cli.addCommand({
|
|
376
|
+
name: "fmt",
|
|
377
|
+
options: [{ name: "format", type: String, choices: ["json", "yaml", "table"] }],
|
|
378
|
+
execute: ({ options }) => {
|
|
379
|
+
// options.format is guaranteed to be one of json | yaml | table
|
|
380
|
+
},
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// `mycli fmt --format xml` → Invalid value "xml" for option "format". Allowed values: json, yaml, table
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Strict unknown-option handling
|
|
387
|
+
|
|
388
|
+
By default, unknown long options on commands that accept a positional `argument` are routed to `toolbox.rawUnknown` (the passthrough buffer) rather than rejected. Set `strictOptions: true` to fail fast on a typo'd flag — tokens after a `--` separator are always preserved as passthrough.
|
|
389
|
+
|
|
390
|
+
```ts
|
|
391
|
+
const cli = new Cerebro("mycli", { argv: ["build", "app", "--produciton"], strictOptions: true });
|
|
392
|
+
// → throws UnknownOptionError: Found unknown option: --produciton (Did you mean: --production?)
|
|
393
|
+
|
|
394
|
+
// Tokens after `--` are still passthrough, even in strict mode:
|
|
395
|
+
// `mycli build app -- --produciton` → toolbox.rawUnknown === ["--produciton"]
|
|
396
|
+
```
|
|
397
|
+
|
|
218
398
|
## Built-in Commands
|
|
219
399
|
|
|
220
400
|
Cerebro comes with several built-in commands that are automatically available:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { C as Command } from "../packem_shared/command.d-DbhtfXF4.js";
|
|
2
|
+
import '@visulima/tabular';
|
|
2
3
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
declare const completionCommand:
|
|
6
|
-
export default
|
|
4
|
+
* Generates shell completion scripts for the CLI application.
|
|
5
|
+
*/
|
|
6
|
+
declare const completionCommand: Command;
|
|
7
|
+
export { completionCommand as default };
|
|
@@ -1,203 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
+
import{t as u}from"../packem_shared/cerebro-error-BjBcYVRO.js";class h extends u{troubleshooting;constructor(o,t,i=[]){super(o,t,{troubleshooting:i}),this.name="CompletionError",this.troubleshooting=i,i.length>0&&(this.hint=i.join(`
|
|
2
|
+
`))}}const a=["bash","zsh","fish","powershell"],c=["node","bun","deno"],f=e=>"Deno"in e,b=e=>"Bun"in e,d=()=>f(globalThis)?"deno":b(globalThis)?"bun":"node",p=e=>{const o=e?.starshipShell??e?.shell;if(o){const s=o.toLowerCase();if(s.includes("zsh"))return"zsh";if(s.includes("bash"))return"bash";if(s.includes("fish"))return"fish"}const t=e?.psModulePath,i=e?.prompt;if(t||i?.includes("PS"))return"powershell";if(e?.comSpec?.toLowerCase().includes("cmd.exe"))return"bash"},g=async()=>(await import("@bomb.sh/tab")).default,S=(e,o)=>{for(const t of o)t.hidden||(t.name&&e.option(t.name,t.description??""),t.alias&&e.option(t.alias,t.description??""))},w=(e,o)=>{for(const[t,i]of o){if(i.name!==t||i.hidden)continue;const s=e.command(i.name,i.description??"");i.options&&S(s,i.options)}},$=e=>{if(!a.includes(e))throw new h(`Invalid shell type: ${e}`,"INVALID_SHELL",[`Valid shells are: ${a.join(", ")}`,"Shell will be auto-detected if not specified"])},y=e=>{if(e&&!c.includes(e))throw new h(`Invalid runtime: ${e}`,"INVALID_RUNTIME",[`Valid runtimes are: ${c.join(", ")}`,"Runtime will be auto-detected if not specified"])},L=(e,o)=>{e.error("Could not detect current shell");const t=[`Usage: ${o} completion --shell=<bash|zsh|fish|powershell> [--runtime=<node|bun|deno>]`,"","Examples:"," # Install completions for zsh:",` ${o} completion --shell=zsh > ~/.${o}-completion.zsh`,` echo 'source ~/.${o}-completion.zsh' >> ~/.zshrc`,""," # Install completions for bash with custom runtime:",` ${o} completion --shell=bash --runtime=bun > ~/.${o}-completion.bash`,` echo 'source ~/.${o}-completion.bash' >> ~/.bashrc`,""," # Install completions for fish:",` ${o} completion --shell=fish > ~/.config/fish/completions/${o}.fish`].join(`
|
|
3
|
+
`);e.info(t)},I={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:o,options:t,runtime:i})=>{const s=i.getCliName(),l=t.shell??p(e);if(!l){L(o,s);return}try{$(l),y(t.runtime);const n=await g();w(n,i.getCommands());const r=`${t.runtime??d()} ${s}`;n.setup(s,r,l)}catch(n){if(n instanceof h){const r=[`Failed to generate completion script: ${n.message}`,`Error code: ${n.code}`];throw n.troubleshooting.length>0&&r.push("","Troubleshooting:",...n.troubleshooting.map(m=>` • ${m}`)),o.error(r.join(`
|
|
4
|
+
`)),n}else{const r=["Failed to generate completion script",`Error: ${n instanceof Error?n.message:String(n)}`,"","Troubleshooting:"," • Ensure @bomb.sh/tab is installed: pnpm add @bomb.sh/tab",` • Verify shell is supported: ${a.join(", ")}`,` • Verify runtime is supported: ${c.join(", ")}`," • Check that your CLI name is correct"];o.error(r.join(`
|
|
5
|
+
`))}}},name:"completion",options:[{defaultOption:!0,defaultValue:p(),description:"Shell type (bash, zsh, fish, powershell). Defaults to current shell if detected.",name:"shell",type:String,typeLabel:"{underline shell}"},{defaultValue:d(),description:"JavaScript runtime (node, bun, deno). Defaults to current runtime if detected.",name:"runtime",type:String,typeLabel:"{underline runtime}"}]};export{I as default};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
declare class HelpCommand<TLogger extends Console = Console> implements
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { O as OptionDefinition, A as ArgumentDefinition, C as Command, T as Toolbox } from "../packem_shared/command.d-DbhtfXF4.js";
|
|
2
|
+
import '@visulima/tabular';
|
|
3
|
+
declare class HelpCommand<TLogger extends Console = Console> implements Command<OptionDefinition<string>, TLogger> {
|
|
4
|
+
argument: ArgumentDefinition<string>;
|
|
5
|
+
name: string;
|
|
6
|
+
options: OptionDefinition<string>[];
|
|
7
|
+
private readonly commands;
|
|
8
|
+
constructor(commands: Map<string, Command<OptionDefinition<unknown>, TLogger>>);
|
|
9
|
+
execute(toolbox: Toolbox<TLogger>): void;
|
|
9
10
|
}
|
|
10
|
-
export default
|
|
11
|
+
export { HelpCommand as default };
|
|
@@ -1,3 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
export { H as default } from '../packem_shared/help-command-BY7rQUvM.js';
|
|
3
|
-
import '../packem_shared/index-C2-8b3A4.js';
|
|
1
|
+
import{inverse as p,cyan as u,green as h,yellow as g}from"@visulima/colorize";import{o as y,r as f}from"../packem_shared/index-DvVGK4kr.js";const O=[{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}],b="__Other",v=s=>s.charAt(0).toUpperCase()+s.slice(1),w=(s,r,l,o)=>{s.debug("no command given, printing general help...");let m=[...new Set(l.values())].filter(n=>!n.hidden);o&&(m=m.filter(n=>n.group===o));const e=m.reduce((n,i)=>{const d=i.group??b;return n[d]??=[],n[d].push(i),n},{}),a=n=>n.map(i=>{let d="";typeof i.alias=="string"?d=i.alias:Array.isArray(i.alias)&&(d=i.alias.join(", ")),d!==""&&(d=` [${d}]`);let t=i.name;return i.commandPath&&i.commandPath.length>0&&(t=`${i.commandPath.join(" ")} ${i.name}`),[`${h(t)}${d}`,i.description??""]});(s.raw??s.log)(f([{content:`${u(r.getCliName())} ${h("<command>")} [positional arguments] ${g("[options]")}`,header:p.cyan(" Usage ")},...Object.keys(e).map(n=>{const i=o?` ${v(o)}`:"";return{content:a(e[n]),header:n===b||o?p.green(` Available${i} Commands `):` ${p.green(` ${v(n)} `)}`}}),l.has("help")?{header:p.yellow(" Command Options "),optionList:l.get("help").options?.filter(n=>!n.hidden)}:void 0,{header:p.yellow(" Global Options "),optionList:r.getGlobalOptions()},{content:O.filter(n=>!n.hidden).map(n=>[n.name,n.description??""]),header:p.magenta(" Environment Variables ")},{content:`Run "${u(r.getCliName())} ${h("help <command>")}" or "${u(r.getCliName())} ${h("<command>")} ${g("--help")}" for help with a specific command.`,raw:!0}].filter(Boolean)))},$=(s,r)=>{const l=[];for(const o of s.values()){if(o.hidden)continue;const m=o.commandPath??[];if(m.length!==r.length)continue;let e=!0;for(const[a,n]of r.entries())if(m[a]!==n){e=!1;break}e&&l.push(o)}return l},E=(s,r,l,o)=>{const m=l.join(" "),e=[{content:`${u(r.getCliName())} ${h(m)} ${h("<subcommand>")} [positional arguments] ${g("[options]")}`,header:p.cyan(" Usage ")},{content:o.map(a=>{const n=[...a.commandPath??[],a.name].join(" ");return[h(n),a.description??""]}),header:p.green(" Subcommands ")},{header:p.yellow(" Global Options "),optionList:r.getGlobalOptions()},{content:`Run "${u(r.getCliName())} ${h(`${m} <subcommand>`)} ${g("--help")}" for help with a specific subcommand.`,raw:!0}];(s.raw??s.log)(f(e))},N=(s,r,l,o,m)=>{let e=m??l.get(o);if(!e)for(const t of l.values()){const c=t.commandPath?[...t.commandPath,t.name]:[t.name];if(c.at(-1)===o||c.join(" ")===o){e=t;break}}if(!e){const t=o.split(" ").filter(Boolean),c=t.length>0?$(l,t):[];if(c.length>0){E(s,r,t,c);return}s.error(`Command "${o}" not found`);return}const a=[],n=(e.commandPath?[...e.commandPath,e.name]:[e.name]).join(" ");if(a.push({content:`${u(r.getCliName())} ${h(n)}${e.argument?" [positional arguments]":""}${e.options?" [options]":""}`,header:p.cyan(" Usage ")}),e.description&&a.push({content:e.description,header:p.green(" Description ")}),e.argument&&a.push({header:"Command Positional Arguments",isArgument:!0,optionList:[e.argument]}),Array.isArray(e.options)&&e.options.length>0&&a.push({header:p.yellow(" Command Options "),optionList:e.options.filter(t=>!t.hidden)}),a.push({header:p.yellow(" Global Options "),optionList:r.getGlobalOptions()}),Array.isArray(e.env)&&e.env.length>0){const t=e.env.filter(c=>!c.hidden);t.length>0&&a.push({content:t.map(c=>[c.name,c.description??""]),header:p.magenta(" Environment Variables ")})}if(e.alias!==void 0&&e.alias.length>0){let t=e.alias;typeof e.alias=="string"&&(t=[e.alias]),a.splice(1,0,{content:t,header:"Alias(es)"})}Array.isArray(e.examples)&&e.examples.length>0&&a.push({content:e.examples,header:"Examples"});const i=[...e.commandPath??[],e.name],d=$(l,i);d.length>0&&a.push({content:d.map(t=>{const c=[...t.commandPath??[],t.name].join(" ");return[h(c),t.description??""]}),header:p.green(" Subcommands ")}),(s.raw??s.log)(f(a))};class P{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(r){this.commands=r}execute(r){const{argument:l,command:o,commandName:m,logger:e,options:a,runtime:n}=r,{footer:i,header:d}=n.getCommandSection();d&&(e.raw??e.log)(y(d));const t=m==="help"&&Array.isArray(l)&&l.length>0?l.join(" "):void 0;if(m==="help"&&t===void 0)w(e,n,this.commands,typeof a?.group=="string"?a.group:void 0);else{const c=t!==void 0||o===void 0||o.name==="help"?void 0:o;N(e,n,this.commands,t??m,c)}i&&(e.raw??e.log)(y(i))}}export{P as default};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { C as Command } from "../packem_shared/command.d-DbhtfXF4.js";
|
|
2
|
+
import '@visulima/tabular';
|
|
2
3
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
declare const readmeCommand:
|
|
6
|
-
export default
|
|
4
|
+
* Generates README documentation for cerebro CLI commands.
|
|
5
|
+
*/
|
|
6
|
+
declare const readmeCommand: Command;
|
|
7
|
+
export { readmeCommand as default };
|