apcore-cli 0.4.0 → 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.
@@ -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 fileURLToPath2 } from "url";
136
- import * as path3 from "path";
137
- import { Command, CommanderError, Option } 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,27 +330,222 @@ function createBindingModule(moduleId, prefix, funcName, description, outputDir)
309
330
  // src/display-helpers.ts
310
331
  init_esm_shims();
311
332
 
312
- // src/main.ts
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));
314
523
  var verboseHelp = false;
315
524
  function hasVerboseFlag() {
316
525
  return process.argv.includes("--verbose");
317
526
  }
318
527
  var VERSION = "0.0.0";
319
528
  try {
320
- const pkg = JSON.parse(readFileSync(path3.resolve(__dirname2, "../package.json"), "utf-8"));
529
+ const pkg = JSON.parse(readFileSync3(path4.resolve(__dirname3, "../package.json"), "utf-8"));
321
530
  VERSION = pkg.version;
322
531
  } catch {
323
532
  }
324
533
  function createCli(extensionsDir, progName, verbose = false) {
325
534
  verboseHelp = verbose;
326
- const resolvedProgName = progName ?? path3.basename(process.argv[1] ?? "apcore-cli") ?? "apcore-cli";
535
+ registerConfigNamespace();
536
+ const resolvedProgName = progName ?? path4.basename(process.argv[1] ?? "apcore-cli") ?? "apcore-cli";
327
537
  const cliLogLevel = process.env.APCORE_CLI_LOGGING_LEVEL ?? process.env.APCORE_LOGGING_LEVEL ?? "WARNING";
328
538
  setLogLevel(cliLogLevel);
329
- const program = new Command(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)");
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)");
330
540
  const resolvedExtDir = extensionsDir ?? process.env.APCORE_EXTENSIONS_ROOT ?? "./extensions";
331
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"));
332
547
  registerInitCommand(program);
548
+ configureManHelp(program, resolvedProgName, VERSION);
333
549
  program.hook("preAction", async (thisCommand) => {
334
550
  const opts = thisCommand.opts();
335
551
  const commandsDir = opts.commandsDir;