apcore-cli 0.3.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +7 -4
- package/dist/bin/apcore-cli.js +233 -11
- package/dist/bin/apcore-cli.js.map +1 -1
- package/dist/index.d.ts +41 -3
- package/dist/index.js +1135 -886
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to apcore-cli (TypeScript SDK) will be documented in this fi
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.0] - 2026-03-29
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Verbose help mode** — Built-in apcore options (`--input`, `--yes`, `--large-input`, `--format`, `--sandbox`) are now hidden from `--help` output by default. Pass `--help --verbose` to display the full option list including built-in options.
|
|
12
|
+
- **Universal man page generation** — `buildProgramManPage()` generates a complete roff man page covering all registered commands. `configureManHelp()` adds `--help --man` support to any Commander program, enabling downstream projects to get man pages for free.
|
|
13
|
+
- **Documentation URL support** — `setDocsUrl()` sets a base URL for online docs. Per-command help shows `Docs: {url}/commands/{name}`, man page SEE ALSO includes `Full documentation at {url}`. No default — disabled when not set.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- `buildModuleCommand()` accepts optional `verboseHelp` parameter to control built-in option visibility in help.
|
|
17
|
+
- `--sandbox` is now always hidden from help (not yet implemented). Only four built-in options (`--input`, `--yes`, `--large-input`, `--format`) toggle with `--verbose`.
|
|
18
|
+
- Improved built-in option descriptions for clarity (e.g., `--input` now reads "Read JSON input from a file path, or use '-' to read from stdin pipe").
|
|
19
|
+
|
|
8
20
|
## [0.3.2] - 2026-03-28
|
|
9
21
|
|
|
10
22
|
### Fixed
|
package/README.md
CHANGED
|
@@ -148,6 +148,8 @@ apcore-cli [OPTIONS] COMMAND [ARGS]
|
|
|
148
148
|
| `--log-level` | `WARNING` | Logging: `DEBUG`, `INFO`, `WARNING`, `ERROR` |
|
|
149
149
|
| `--version` | | Show version and exit |
|
|
150
150
|
| `--help` | | Show help and exit |
|
|
151
|
+
| `--verbose` | | Show all options in help (including built-in apcore options) |
|
|
152
|
+
| `--man` | | Output man page in roff format (use with `--help`) |
|
|
151
153
|
|
|
152
154
|
### Built-in Commands
|
|
153
155
|
|
|
@@ -161,7 +163,7 @@ apcore-cli [OPTIONS] COMMAND [ARGS]
|
|
|
161
163
|
|
|
162
164
|
### Module Execution Options
|
|
163
165
|
|
|
164
|
-
When executing a module (e.g. `apcore-cli math.add`), these built-in options are
|
|
166
|
+
When executing a module (e.g. `apcore-cli math.add`), these built-in options are available (hidden by default; use `--verbose` to show in `--help`):
|
|
165
167
|
|
|
166
168
|
| Option | Description |
|
|
167
169
|
|--------|-------------|
|
|
@@ -169,7 +171,7 @@ When executing a module (e.g. `apcore-cli math.add`), these built-in options are
|
|
|
169
171
|
| `--yes` / `-y` | Bypass approval prompts |
|
|
170
172
|
| `--large-input` | Allow STDIN input larger than 10MB |
|
|
171
173
|
| `--format` | Output format: `json` or `table` |
|
|
172
|
-
| `--sandbox` | Run module in subprocess sandbox |
|
|
174
|
+
| `--sandbox` | Run module in subprocess sandbox (not yet implemented — always hidden) |
|
|
173
175
|
|
|
174
176
|
Schema-generated flags (e.g. `--a`, `--b`) are added automatically from the module's `input_schema`.
|
|
175
177
|
|
|
@@ -234,7 +236,8 @@ cli:
|
|
|
234
236
|
- **Schema validation** -- inputs validated against JSON Schema before execution, with `$ref`/`allOf`/`anyOf`/`oneOf` resolution
|
|
235
237
|
- **Security** -- API key auth (keyring + AES-256-GCM), append-only audit logging, subprocess sandboxing
|
|
236
238
|
- **Shell completions** -- `apcore-cli completion bash|zsh|fish` generates completion scripts with dynamic module ID completion
|
|
237
|
-
- **Man pages** -- `apcore-cli man <command>`
|
|
239
|
+
- **Man pages** -- `apcore-cli man <command>` for single commands, or `--help --man` for a complete program man page. `configureManHelp()` provides one-line integration for downstream projects
|
|
240
|
+
- **Documentation URL** -- `setDocsUrl()` adds doc links to help footers and man pages
|
|
238
241
|
- **Audit logging** -- all executions logged to `~/.apcore-cli/audit.jsonl` with SHA-256 input hashing
|
|
239
242
|
|
|
240
243
|
## How It Works
|
|
@@ -274,7 +277,7 @@ apcore Registry + Executor (your modules, unchanged)
|
|
|
274
277
|
|
|
275
278
|
**Classes:** `LazyModuleGroup`, `ConfigResolver`, `AuthProvider`, `ConfigEncryptor`, `AuditLogger`, `Sandbox`
|
|
276
279
|
|
|
277
|
-
**Functions:** `createCli`, `main`, `buildModuleCommand`, `validateModuleId`, `collectInput`, `schemaToCliOptions`, `reconvertEnumValues`, `resolveRefs`, `checkApproval`, `resolveFormat`, `formatModuleList`, `formatModuleDetail`, `formatExecResult`, `registerDiscoveryCommands`, `registerShellCommands`, `setAuditLogger`, `getAuditLogger`, `exitCodeForError`, `mapType`, `extractHelp`, `truncate`
|
|
280
|
+
**Functions:** `createCli`, `main`, `buildModuleCommand`, `validateModuleId`, `collectInput`, `schemaToCliOptions`, `reconvertEnumValues`, `resolveRefs`, `checkApproval`, `resolveFormat`, `formatModuleList`, `formatModuleDetail`, `formatExecResult`, `registerDiscoveryCommands`, `registerShellCommands`, `setAuditLogger`, `getAuditLogger`, `setVerboseHelp`, `setDocsUrl`, `buildProgramManPage`, `configureManHelp`, `exitCodeForError`, `mapType`, `extractHelp`, `truncate`
|
|
278
281
|
|
|
279
282
|
**Errors:** `ApprovalTimeoutError`, `ApprovalDeniedError`, `AuthenticationError`, `ConfigDecryptionError`, `ModuleExecutionError`, `ModuleNotFoundError`, `SchemaValidationError`
|
|
280
283
|
|
package/dist/bin/apcore-cli.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
+
}) : x)(function(x) {
|
|
6
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
3
9
|
var __esm = (fn, res) => function __init() {
|
|
4
10
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
11
|
};
|
|
@@ -46,11 +52,19 @@ function exitCodeForError(error) {
|
|
|
46
52
|
SCHEMA_CIRCULAR_REF: EXIT_CODES.SCHEMA_CIRCULAR_REF,
|
|
47
53
|
APPROVAL_DENIED: EXIT_CODES.APPROVAL_DENIED,
|
|
48
54
|
APPROVAL_TIMEOUT: EXIT_CODES.APPROVAL_TIMEOUT,
|
|
55
|
+
APPROVAL_PENDING: EXIT_CODES.APPROVAL_DENIED,
|
|
49
56
|
CONFIG_NOT_FOUND: EXIT_CODES.CONFIG_NOT_FOUND,
|
|
50
57
|
CONFIG_INVALID: EXIT_CODES.CONFIG_INVALID,
|
|
51
58
|
MODULE_EXECUTE_ERROR: EXIT_CODES.MODULE_EXECUTE_ERROR,
|
|
52
59
|
MODULE_TIMEOUT: EXIT_CODES.MODULE_TIMEOUT,
|
|
53
|
-
ACL_DENIED: EXIT_CODES.ACL_DENIED
|
|
60
|
+
ACL_DENIED: EXIT_CODES.ACL_DENIED,
|
|
61
|
+
// Config Bus errors (apcore >= 0.15.0)
|
|
62
|
+
CONFIG_NAMESPACE_RESERVED: EXIT_CODES.CONFIG_NAMESPACE_RESERVED,
|
|
63
|
+
CONFIG_NAMESPACE_DUPLICATE: EXIT_CODES.CONFIG_NAMESPACE_DUPLICATE,
|
|
64
|
+
CONFIG_ENV_PREFIX_CONFLICT: EXIT_CODES.CONFIG_ENV_PREFIX_CONFLICT,
|
|
65
|
+
CONFIG_MOUNT_ERROR: EXIT_CODES.CONFIG_MOUNT_ERROR,
|
|
66
|
+
CONFIG_BIND_ERROR: EXIT_CODES.CONFIG_BIND_ERROR,
|
|
67
|
+
ERROR_FORMATTER_DUPLICATE: EXIT_CODES.ERROR_FORMATTER_DUPLICATE
|
|
54
68
|
};
|
|
55
69
|
if (code && code in codeMap) {
|
|
56
70
|
return codeMap[code];
|
|
@@ -120,6 +134,13 @@ var init_errors = __esm({
|
|
|
120
134
|
CONFIG_INVALID: 47,
|
|
121
135
|
SCHEMA_CIRCULAR_REF: 48,
|
|
122
136
|
ACL_DENIED: 77,
|
|
137
|
+
// Config Bus errors (apcore >= 0.15.0)
|
|
138
|
+
CONFIG_NAMESPACE_RESERVED: 78,
|
|
139
|
+
CONFIG_NAMESPACE_DUPLICATE: 78,
|
|
140
|
+
CONFIG_ENV_PREFIX_CONFLICT: 78,
|
|
141
|
+
CONFIG_MOUNT_ERROR: 66,
|
|
142
|
+
CONFIG_BIND_ERROR: 65,
|
|
143
|
+
ERROR_FORMATTER_DUPLICATE: 70,
|
|
123
144
|
KEYBOARD_INTERRUPT: 130
|
|
124
145
|
};
|
|
125
146
|
}
|
|
@@ -131,10 +152,10 @@ init_esm_shims();
|
|
|
131
152
|
// src/main.ts
|
|
132
153
|
init_esm_shims();
|
|
133
154
|
init_errors();
|
|
134
|
-
import { readFileSync } from "fs";
|
|
135
|
-
import { fileURLToPath as
|
|
136
|
-
import * as
|
|
137
|
-
import { Command, CommanderError } from "commander";
|
|
155
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
156
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
157
|
+
import * as path4 from "path";
|
|
158
|
+
import { Command as Command2, CommanderError, Option as Option2 } from "commander";
|
|
138
159
|
|
|
139
160
|
// src/ref-resolver.ts
|
|
140
161
|
init_esm_shims();
|
|
@@ -309,22 +330,222 @@ function createBindingModule(moduleId, prefix, funcName, description, outputDir)
|
|
|
309
330
|
// src/display-helpers.ts
|
|
310
331
|
init_esm_shims();
|
|
311
332
|
|
|
312
|
-
// src/
|
|
333
|
+
// src/config.ts
|
|
334
|
+
init_esm_shims();
|
|
335
|
+
import * as fs2 from "fs";
|
|
336
|
+
import yaml from "js-yaml";
|
|
337
|
+
var NAMESPACE_TO_LEGACY = {
|
|
338
|
+
"apcore-cli.stdin_buffer_limit": "cli.stdin_buffer_limit",
|
|
339
|
+
"apcore-cli.auto_approve": "cli.auto_approve",
|
|
340
|
+
"apcore-cli.help_text_max_length": "cli.help_text_max_length",
|
|
341
|
+
"apcore-cli.logging_level": "logging.level"
|
|
342
|
+
};
|
|
343
|
+
var LEGACY_TO_NAMESPACE = Object.fromEntries(
|
|
344
|
+
Object.entries(NAMESPACE_TO_LEGACY).map(([k, v]) => [v, k])
|
|
345
|
+
);
|
|
346
|
+
function registerConfigNamespace() {
|
|
347
|
+
try {
|
|
348
|
+
const { Config } = __require("apcore-js");
|
|
349
|
+
if (typeof Config?.registerNamespace === "function") {
|
|
350
|
+
Config.registerNamespace({
|
|
351
|
+
name: "apcore-cli",
|
|
352
|
+
envPrefix: "APCORE_CLI",
|
|
353
|
+
defaults: {
|
|
354
|
+
stdin_buffer_limit: 10485760,
|
|
355
|
+
auto_approve: false,
|
|
356
|
+
help_text_max_length: 1e3,
|
|
357
|
+
logging_level: "WARNING"
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
} catch {
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// src/shell.ts
|
|
366
|
+
init_esm_shims();
|
|
367
|
+
init_errors();
|
|
368
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
369
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
370
|
+
import * as path3 from "path";
|
|
371
|
+
import { spawnSync } from "child_process";
|
|
372
|
+
import { Command, Help, Option } from "commander";
|
|
313
373
|
var __dirname2 = path3.dirname(fileURLToPath2(import.meta.url));
|
|
374
|
+
var SHELL_VERSION = "0.0.0";
|
|
375
|
+
try {
|
|
376
|
+
const pkg = JSON.parse(readFileSync2(path3.resolve(__dirname2, "../package.json"), "utf-8"));
|
|
377
|
+
SHELL_VERSION = pkg.version;
|
|
378
|
+
} catch {
|
|
379
|
+
}
|
|
380
|
+
function roffEscape(s) {
|
|
381
|
+
return s.replace(/\\/g, "\\\\").replace(/-/g, "\\-").replace(/'/g, "\\(aq");
|
|
382
|
+
}
|
|
383
|
+
function buildProgramManPage(program, progName, version, description, docsUrl) {
|
|
384
|
+
const help = new Help();
|
|
385
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
386
|
+
const s = [];
|
|
387
|
+
const resolvedDesc = description ?? program.description() ?? `${progName} CLI`;
|
|
388
|
+
s.push(`.TH "${progName.toUpperCase()}" "1" "${today}" "${progName} ${version}" "${progName} Manual"`);
|
|
389
|
+
s.push(".SH NAME");
|
|
390
|
+
s.push(`${progName} \\- ${roffEscape(resolvedDesc)}`);
|
|
391
|
+
s.push(".SH SYNOPSIS");
|
|
392
|
+
s.push(`\\fB${progName}\\fR [\\fIglobal\\-options\\fR] \\fIcommand\\fR [\\fIcommand\\-options\\fR]`);
|
|
393
|
+
if (resolvedDesc) {
|
|
394
|
+
s.push(".SH DESCRIPTION");
|
|
395
|
+
s.push(roffEscape(resolvedDesc));
|
|
396
|
+
}
|
|
397
|
+
const globalOpts = help.visibleOptions(program).filter((o) => !["help", "version", "all", "man"].includes(o.long?.replace("--", "") ?? ""));
|
|
398
|
+
if (globalOpts.length > 0) {
|
|
399
|
+
s.push(".SH GLOBAL OPTIONS");
|
|
400
|
+
for (const opt of globalOpts) {
|
|
401
|
+
const flag = [opt.short, opt.long].filter(Boolean).join(", ");
|
|
402
|
+
s.push(".TP");
|
|
403
|
+
s.push(`\\fB${roffEscape(flag)}\\fR`);
|
|
404
|
+
if (opt.description) s.push(roffEscape(opt.description));
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
const allCommands = help.visibleCommands(program);
|
|
408
|
+
if (allCommands.length > 0) {
|
|
409
|
+
s.push(".SH COMMANDS");
|
|
410
|
+
for (const cmd of allCommands) {
|
|
411
|
+
if (cmd.name() === "help") continue;
|
|
412
|
+
const desc = help.subcommandDescription(cmd);
|
|
413
|
+
s.push(".TP");
|
|
414
|
+
s.push(`\\fB${progName} ${roffEscape(cmd.name())}\\fR`);
|
|
415
|
+
if (desc) s.push(roffEscape(desc));
|
|
416
|
+
const cmdHelp = new Help();
|
|
417
|
+
const opts = cmdHelp.visibleOptions(cmd).filter((o) => !["help", "version"].includes(o.long?.replace("--", "") ?? ""));
|
|
418
|
+
for (const opt of opts) {
|
|
419
|
+
const flag = [opt.short, opt.long].filter(Boolean).join(", ");
|
|
420
|
+
s.push(".RS");
|
|
421
|
+
s.push(".TP");
|
|
422
|
+
s.push(`\\fB${roffEscape(flag)}\\fR`);
|
|
423
|
+
if (opt.description) s.push(roffEscape(opt.description));
|
|
424
|
+
s.push(".RE");
|
|
425
|
+
}
|
|
426
|
+
const subCmds = cmdHelp.visibleCommands(cmd).filter((c) => c.name() !== "help");
|
|
427
|
+
for (const sub of subCmds) {
|
|
428
|
+
const subDesc = help.subcommandDescription(sub);
|
|
429
|
+
s.push(".TP");
|
|
430
|
+
s.push(`\\fB${progName} ${roffEscape(cmd.name())} ${roffEscape(sub.name())}\\fR`);
|
|
431
|
+
if (subDesc) s.push(roffEscape(subDesc));
|
|
432
|
+
const subOpts = cmdHelp.visibleOptions(sub).filter((o) => !["help", "version"].includes(o.long?.replace("--", "") ?? ""));
|
|
433
|
+
for (const opt of subOpts) {
|
|
434
|
+
const flag = [opt.short, opt.long].filter(Boolean).join(", ");
|
|
435
|
+
s.push(".RS");
|
|
436
|
+
s.push(".TP");
|
|
437
|
+
s.push(`\\fB${roffEscape(flag)}\\fR`);
|
|
438
|
+
if (opt.description) s.push(roffEscape(opt.description));
|
|
439
|
+
s.push(".RE");
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
s.push(".SH ENVIRONMENT");
|
|
445
|
+
s.push(".TP");
|
|
446
|
+
s.push("\\fBAPCORE_EXTENSIONS_ROOT\\fR");
|
|
447
|
+
s.push("Path to the apcore extensions directory.");
|
|
448
|
+
s.push(".TP");
|
|
449
|
+
s.push("\\fBAPCORE_CLI_AUTO_APPROVE\\fR");
|
|
450
|
+
s.push("Set to \\fB1\\fR to bypass approval prompts.");
|
|
451
|
+
s.push(".TP");
|
|
452
|
+
s.push("\\fBAPCORE_CLI_LOGGING_LEVEL\\fR");
|
|
453
|
+
s.push("CLI\\-specific logging verbosity (DEBUG|INFO|WARNING|ERROR).");
|
|
454
|
+
s.push(".SH EXIT CODES");
|
|
455
|
+
const exitCodes = [
|
|
456
|
+
["0", "Success."],
|
|
457
|
+
["1", "Module execution error."],
|
|
458
|
+
["2", "Invalid CLI input or missing argument."],
|
|
459
|
+
["44", "Module not found, disabled, or failed to load."],
|
|
460
|
+
["45", "Input failed JSON Schema validation."],
|
|
461
|
+
["46", "Approval denied or timed out."],
|
|
462
|
+
["47", "Configuration error."],
|
|
463
|
+
["77", "ACL denied."],
|
|
464
|
+
["130", "Cancelled by user (SIGINT)."]
|
|
465
|
+
];
|
|
466
|
+
for (const [code, meaning] of exitCodes) {
|
|
467
|
+
s.push(`.TP
|
|
468
|
+
\\fB${code}\\fR
|
|
469
|
+
${meaning}`);
|
|
470
|
+
}
|
|
471
|
+
s.push(".SH SEE ALSO");
|
|
472
|
+
s.push(`\\fB${progName} \\-\\-help \\-\\-verbose\\fR for full option list.`);
|
|
473
|
+
if (docsUrl) {
|
|
474
|
+
s.push(`.PP
|
|
475
|
+
Full documentation at \\fI${roffEscape(docsUrl)}\\fR`);
|
|
476
|
+
}
|
|
477
|
+
return s.join("\n");
|
|
478
|
+
}
|
|
479
|
+
function configureManHelp(program, progName, version, description, docsUrl) {
|
|
480
|
+
const manOpt = new Option("--man", "Output man page in roff format (use with --help)").hideHelp();
|
|
481
|
+
program.addOption(manOpt);
|
|
482
|
+
program.addHelpText("beforeAll", () => {
|
|
483
|
+
if (program.opts().man) {
|
|
484
|
+
const roff = buildProgramManPage(program, progName, version, description, docsUrl) + "\n";
|
|
485
|
+
if (process.stdout.isTTY) {
|
|
486
|
+
const pagers = [
|
|
487
|
+
{ cmd: "mandoc", args: ["-a"] },
|
|
488
|
+
{ cmd: "groff", args: ["-man", "-Tutf8"] }
|
|
489
|
+
];
|
|
490
|
+
let rendered = false;
|
|
491
|
+
for (const { cmd, args } of pagers) {
|
|
492
|
+
const result = spawnSync(cmd, args, {
|
|
493
|
+
input: roff,
|
|
494
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
495
|
+
encoding: "utf-8"
|
|
496
|
+
});
|
|
497
|
+
if (result.status === 0 && result.stdout) {
|
|
498
|
+
const pager = process.env.PAGER || "less";
|
|
499
|
+
const pagerResult = spawnSync(pager, ["-R"], {
|
|
500
|
+
input: result.stdout,
|
|
501
|
+
stdio: ["pipe", "inherit", "inherit"]
|
|
502
|
+
});
|
|
503
|
+
if (pagerResult.status !== null) {
|
|
504
|
+
rendered = true;
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
if (!rendered) {
|
|
510
|
+
process.stdout.write(roff);
|
|
511
|
+
}
|
|
512
|
+
} else {
|
|
513
|
+
process.stdout.write(roff);
|
|
514
|
+
}
|
|
515
|
+
process.exit(0);
|
|
516
|
+
}
|
|
517
|
+
return "";
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// src/main.ts
|
|
522
|
+
var __dirname3 = path4.dirname(fileURLToPath3(import.meta.url));
|
|
523
|
+
var verboseHelp = false;
|
|
524
|
+
function hasVerboseFlag() {
|
|
525
|
+
return process.argv.includes("--verbose");
|
|
526
|
+
}
|
|
314
527
|
var VERSION = "0.0.0";
|
|
315
528
|
try {
|
|
316
|
-
const pkg = JSON.parse(
|
|
529
|
+
const pkg = JSON.parse(readFileSync3(path4.resolve(__dirname3, "../package.json"), "utf-8"));
|
|
317
530
|
VERSION = pkg.version;
|
|
318
531
|
} catch {
|
|
319
532
|
}
|
|
320
|
-
function createCli(extensionsDir, progName) {
|
|
321
|
-
|
|
533
|
+
function createCli(extensionsDir, progName, verbose = false) {
|
|
534
|
+
verboseHelp = verbose;
|
|
535
|
+
registerConfigNamespace();
|
|
536
|
+
const resolvedProgName = progName ?? path4.basename(process.argv[1] ?? "apcore-cli") ?? "apcore-cli";
|
|
322
537
|
const cliLogLevel = process.env.APCORE_CLI_LOGGING_LEVEL ?? process.env.APCORE_LOGGING_LEVEL ?? "WARNING";
|
|
323
538
|
setLogLevel(cliLogLevel);
|
|
324
|
-
const program = new
|
|
539
|
+
const program = new Command2(resolvedProgName).exitOverride().version(VERSION, "--version", `Show ${resolvedProgName} version`).description("apcore CLI \u2014 execute apcore modules from the command line").option("--extensions-dir <path>", "Path to extensions directory").option("--commands-dir <path>", "Path to convention-based commands directory").option("--binding <path>", "Path to binding.yaml for display overlay").option("--log-level <level>", "Logging level (DEBUG|INFO|WARNING|ERROR)", "WARNING").option("--verbose", "Show all options in help output (including built-in apcore options)");
|
|
325
540
|
const resolvedExtDir = extensionsDir ?? process.env.APCORE_EXTENSIONS_ROOT ?? "./extensions";
|
|
326
541
|
void resolvedExtDir;
|
|
542
|
+
program.addHelpText("after", [
|
|
543
|
+
"",
|
|
544
|
+
"Use --help --verbose to show all options (including built-in apcore options).",
|
|
545
|
+
"Use --help --man to display a formatted man page."
|
|
546
|
+
].join("\n"));
|
|
327
547
|
registerInitCommand(program);
|
|
548
|
+
configureManHelp(program, resolvedProgName, VERSION);
|
|
328
549
|
program.hook("preAction", async (thisCommand) => {
|
|
329
550
|
const opts = thisCommand.opts();
|
|
330
551
|
const commandsDir = opts.commandsDir;
|
|
@@ -355,7 +576,8 @@ async function applyToolkitIntegration(commandsDir, bindingPath) {
|
|
|
355
576
|
}
|
|
356
577
|
}
|
|
357
578
|
function main(progName) {
|
|
358
|
-
|
|
579
|
+
verboseHelp = hasVerboseFlag();
|
|
580
|
+
const program = createCli(void 0, progName, verboseHelp);
|
|
359
581
|
try {
|
|
360
582
|
program.parse(process.argv);
|
|
361
583
|
} catch (error) {
|