burgee 0.7.0 → 0.8.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/dist/cli.d.ts +25 -3
- package/dist/cli.js +25 -7
- package/dist/commander/argument.js +0 -3
- package/dist/commander/command.d.ts +7 -3
- package/dist/commander/command.js +50 -186
- package/dist/commander/error.js +0 -2
- package/dist/commander/help.js +0 -17
- package/dist/commander/option.js +0 -14
- package/dist/commander.d.ts +1 -1
- package/dist/compat.d.ts +30 -0
- package/dist/compat.js +4 -0
- package/dist/definition.d.ts +11 -2
- package/dist/definition.js +9 -11
- package/dist/execute.js +5 -1
- package/dist/mcp.d.ts +33 -13
- package/dist/mcp.js +4 -3
- package/dist/migrate.d.ts +142 -0
- package/dist/migrate.js +284 -0
- package/dist/shutdown.d.ts +1 -1
- package/dist/yargs/burgee.js +0 -14
- package/dist/yargs/cliui.js +0 -53
- package/dist/yargs/command.js +0 -7
- package/dist/yargs/completion.js +0 -5
- package/dist/yargs/factory.js +0 -55
- package/dist/yargs/middleware.js +0 -5
- package/dist/yargs/shim.js +0 -20
- package/dist/yargs/usage.js +0 -8
- package/dist/yargs/utils.js +0 -11
- package/dist/yargs/validation.js +0 -6
- package/dist/yargs/y18n.js +0 -6
- package/package.json +5 -5
|
@@ -2,21 +2,6 @@ import { EventEmitter } from 'node:events';
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { stripVTControlCharacters } from 'node:util';
|
|
5
|
-
/**
|
|
6
|
-
* commander's `Command`, ported method for method from commander 15 and graded by
|
|
7
|
-
* commander's own suite through `compat-oracle`. The parse pipeline, the option
|
|
8
|
-
* grammar, every error string and exit code are commander's — that is what makes a
|
|
9
|
-
* user's existing program run unchanged (J2).
|
|
10
|
-
*
|
|
11
|
-
* burgee's additions sit beside it and never alter the default behaviour:
|
|
12
|
-
* - `manifest` projects the command tree, so plugins (`use`) and the generated
|
|
13
|
-
* surfaces read commander-syntax programs exactly like native ones (J7, J8);
|
|
14
|
-
* - `--json`, when the program has not declared that option itself, wraps the
|
|
15
|
-
* action's return value in the envelope (N-family);
|
|
16
|
-
* - `parse(argv, { stdout, stderr, exit })` injects the streams and the exit, and
|
|
17
|
-
* then reports through the E1 taxonomy — the harness's seam (T1).
|
|
18
|
-
*/
|
|
19
|
-
// eslint-disable-next-line import-next/no-namespace -- `spawn` is read off the namespace at the call site and never captured into a local. commander's own suite mocks `childProcess.spawn` in roughly 23 `executableSubcommand` cases, and a binding captured at import never re-syncs; bellpull's `cross-spawn.ts` reads `spawn` off its default import for this exact consumer, so a named import here would undo that and take the row from 1360 / 1360 to ungradeable.
|
|
20
5
|
import * as crossSpawn from 'bellpull/cross-spawn';
|
|
21
6
|
import { ExitCode } from '../exit-code.js';
|
|
22
7
|
import { Manifest } from '../manifest.js';
|
|
@@ -28,7 +13,6 @@ import { Argument, humanReadableArgName } from './argument.js';
|
|
|
28
13
|
import { CommanderError } from './error.js';
|
|
29
14
|
import { Help } from './help.js';
|
|
30
15
|
import { DualOptions, Option } from './option.js';
|
|
31
|
-
/** Names that would reach Object.prototype if used as an option key. */
|
|
32
16
|
const POLLUTING = new Set(['__proto__', 'constructor', 'prototype']);
|
|
33
17
|
const ENV_SOURCES = ['default', 'config', 'env'];
|
|
34
18
|
const IMPLIED_SOURCES = ['default', 'implied'];
|
|
@@ -36,12 +20,10 @@ const HOOK_EVENTS = ['preSubcommand', 'preAction', 'postAction'];
|
|
|
36
20
|
const HELP_POSITIONS = ['beforeAll', 'before', 'after', 'afterAll'];
|
|
37
21
|
const SOURCE_EXT = ['.js', '.ts', '.tsx', '.mjs', '.cjs'];
|
|
38
22
|
const FORWARDED_SIGNALS = ['SIGUSR1', 'SIGUSR2', 'SIGTERM', 'SIGINT', 'SIGHUP'];
|
|
39
|
-
/** Wraps in single quotes. Used where a message says "from" right before a quoted method name, which a static import scanner would otherwise read as a specifier. */
|
|
40
23
|
const quoted = (s) => `'${s}'`;
|
|
41
24
|
function isThenable(value) {
|
|
42
25
|
return typeof value?.then === 'function';
|
|
43
26
|
}
|
|
44
|
-
/** commander's exit codes, read through burgee's taxonomy when the exit is injected (E1). */
|
|
45
27
|
function e1(err) {
|
|
46
28
|
switch (err.code) {
|
|
47
29
|
case 'commander.helpDisplayed':
|
|
@@ -56,7 +38,6 @@ function e1(err) {
|
|
|
56
38
|
return err.exitCode === 1 ? ExitCode.USAGE : err.exitCode;
|
|
57
39
|
}
|
|
58
40
|
}
|
|
59
|
-
/** What a run prints for an action's return value when the streams are injected. */
|
|
60
41
|
function render(value) {
|
|
61
42
|
if (value === undefined || value === null)
|
|
62
43
|
return '';
|
|
@@ -74,12 +55,9 @@ export class Command extends EventEmitter {
|
|
|
74
55
|
options = [];
|
|
75
56
|
parent = null;
|
|
76
57
|
registeredArguments = [];
|
|
77
|
-
/** @deprecated old name for registeredArguments */
|
|
78
58
|
_args;
|
|
79
|
-
/** cli args with options removed */
|
|
80
59
|
args = [];
|
|
81
60
|
rawArgs = [];
|
|
82
|
-
/** like .args but after custom processing and collecting variadic */
|
|
83
61
|
processedArgs = [];
|
|
84
62
|
runningCommand = undefined;
|
|
85
63
|
_allowUnknownOption = false;
|
|
@@ -108,7 +86,6 @@ export class Command extends EventEmitter {
|
|
|
108
86
|
_savedState = null;
|
|
109
87
|
_outputConfiguration;
|
|
110
88
|
_hidden = false;
|
|
111
|
-
/** Lazy created on demand; null once disabled. */
|
|
112
89
|
_helpOption = undefined;
|
|
113
90
|
_addImplicitHelpCommand = undefined;
|
|
114
91
|
_helpCommand = undefined;
|
|
@@ -119,14 +96,10 @@ export class Command extends EventEmitter {
|
|
|
119
96
|
_version = undefined;
|
|
120
97
|
_versionOptionName = undefined;
|
|
121
98
|
_usage = undefined;
|
|
122
|
-
/** burgee: the root's projection, created on first use. */
|
|
123
99
|
_manifest = undefined;
|
|
124
|
-
/** burgee: what this command does to the world (N6); declaring it exposes the command as an MCP tool. */
|
|
125
100
|
_effects = undefined;
|
|
126
|
-
/** burgee: `true`, or the replacement's name (M5). Shown in help, schema and a one-line warning on use. */
|
|
127
101
|
_deprecated = undefined;
|
|
128
102
|
_deprecationWarned = false;
|
|
129
|
-
/** burgee: set for the duration of a parse that injected the streams or the exit. */
|
|
130
103
|
_burgee = undefined;
|
|
131
104
|
constructor(name) {
|
|
132
105
|
super();
|
|
@@ -143,7 +116,6 @@ export class Command extends EventEmitter {
|
|
|
143
116
|
stripColor: (str) => stripVTControlCharacters(str),
|
|
144
117
|
};
|
|
145
118
|
}
|
|
146
|
-
/** Copy settings useful to share between the root and its subcommands. */
|
|
147
119
|
copyInheritedSettings(sourceCommand) {
|
|
148
120
|
this._outputConfiguration = sourceCommand._outputConfiguration;
|
|
149
121
|
this._helpOption = sourceCommand._helpOption;
|
|
@@ -191,7 +163,6 @@ export class Command extends EventEmitter {
|
|
|
191
163
|
return this;
|
|
192
164
|
return cmd;
|
|
193
165
|
}
|
|
194
|
-
/** Factory for an unattached command; override to customise subcommands. */
|
|
195
166
|
createCommand(name) {
|
|
196
167
|
return new Command(name);
|
|
197
168
|
}
|
|
@@ -263,7 +234,6 @@ export class Command extends EventEmitter {
|
|
|
263
234
|
this.registeredArguments.push(argument);
|
|
264
235
|
return this;
|
|
265
236
|
}
|
|
266
|
-
/** Customise or disable the default help command (added by default when there are subcommands). */
|
|
267
237
|
helpCommand(enableOrNameAndArgs, description) {
|
|
268
238
|
if (typeof enableOrNameAndArgs === 'boolean') {
|
|
269
239
|
this._addImplicitHelpCommand = enableOrNameAndArgs;
|
|
@@ -320,25 +290,21 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
320
290
|
this._lifeCycleHooks[event] = [listener];
|
|
321
291
|
return this;
|
|
322
292
|
}
|
|
323
|
-
/** Replace the call to process.exit; defaults to throwing the CommanderError. */
|
|
324
293
|
exitOverride(fn) {
|
|
325
294
|
this._exitCallback =
|
|
326
295
|
fn ??
|
|
327
296
|
((err) => {
|
|
328
297
|
if (err.code !== 'commander.executeSubCommandAsync')
|
|
329
298
|
throw err;
|
|
330
|
-
// Async callback from spawn events, not useful to throw.
|
|
331
299
|
});
|
|
332
300
|
return this;
|
|
333
301
|
}
|
|
334
302
|
_exit(exitCode, code, message) {
|
|
335
303
|
if (this._exitCallback) {
|
|
336
304
|
this._exitCallback(new CommanderError(exitCode, code, message));
|
|
337
|
-
// Expecting this line is not reached.
|
|
338
305
|
}
|
|
339
306
|
return host.exit(exitCode);
|
|
340
307
|
}
|
|
341
|
-
// commander's contract: the positional args, then the options, then the command itself.
|
|
342
308
|
action(fn) {
|
|
343
309
|
const listener = (args) => {
|
|
344
310
|
const expectedArgsCount = this.registeredArguments.length;
|
|
@@ -353,7 +319,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
353
319
|
createOption(flags, description) {
|
|
354
320
|
return new Option(flags, description);
|
|
355
321
|
}
|
|
356
|
-
/** Wrap parseArg to turn `commander.invalidArgument` into an error with context. */
|
|
357
322
|
_callParseArg(target, value, previous, invalidArgumentMessage) {
|
|
358
323
|
try {
|
|
359
324
|
return target.parseArg?.(value, previous);
|
|
@@ -401,7 +366,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
401
366
|
if (option.defaultValue !== undefined) {
|
|
402
367
|
this.setOptionValueWithSource(name, option.defaultValue, 'default');
|
|
403
368
|
}
|
|
404
|
-
// val is null for an optional option used without its argument, undefined for boolean and negated.
|
|
405
369
|
const handleOptionValue = (val, invalidValueMessage, valueSource) => {
|
|
406
370
|
let value = val;
|
|
407
371
|
if (value == null && option.presetArg !== undefined)
|
|
@@ -419,7 +383,7 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
419
383
|
else if (option.isBoolean() || option.optional)
|
|
420
384
|
value = true;
|
|
421
385
|
else
|
|
422
|
-
value = '';
|
|
386
|
+
value = '';
|
|
423
387
|
}
|
|
424
388
|
this.setOptionValueWithSource(name, value, valueSource);
|
|
425
389
|
};
|
|
@@ -443,7 +407,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
443
407
|
option.default(defaultValue).argParser(fn);
|
|
444
408
|
}
|
|
445
409
|
else if (fn instanceof RegExp) {
|
|
446
|
-
// deprecated
|
|
447
410
|
const regex = fn;
|
|
448
411
|
option.default(defaultValue).argParser((val, def) => {
|
|
449
412
|
const m = regex.exec(val);
|
|
@@ -461,7 +424,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
461
424
|
requiredOption(flags, description, parseArg, defaultValue) {
|
|
462
425
|
return this._optionEx({ mandatory: true }, flags, description, parseArg, defaultValue);
|
|
463
426
|
}
|
|
464
|
-
/** `-f80` as `--flag=80` (default) versus `-fb` as `-f -b`. */
|
|
465
427
|
combineFlagAndOptionalValue(combine = true) {
|
|
466
428
|
this._combineFlagAndOptionalValue = !!combine;
|
|
467
429
|
return this;
|
|
@@ -474,12 +436,10 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
474
436
|
this._allowExcessArguments = !!allowExcess;
|
|
475
437
|
return this;
|
|
476
438
|
}
|
|
477
|
-
/** Global options before subcommands only, so subcommands may reuse option names. */
|
|
478
439
|
enablePositionalOptions(positional = true) {
|
|
479
440
|
this._enablePositionalOptions = !!positional;
|
|
480
441
|
return this;
|
|
481
442
|
}
|
|
482
|
-
/** Options after the first command-argument are passed through, not parsed. */
|
|
483
443
|
passThroughOptions(passThrough = true) {
|
|
484
444
|
this._passThroughOptions = !!passThrough;
|
|
485
445
|
this._checkForBrokenPassThrough();
|
|
@@ -506,7 +466,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
506
466
|
setOptionValue(key, value) {
|
|
507
467
|
return this.setOptionValueWithSource(key, value, undefined);
|
|
508
468
|
}
|
|
509
|
-
/** `source` is default | config | env | cli | implied. */
|
|
510
469
|
setOptionValueWithSource(key, value, source) {
|
|
511
470
|
if (this._storeOptionsAsProperties)
|
|
512
471
|
this[key] = value;
|
|
@@ -518,7 +477,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
518
477
|
getOptionValueSource(key) {
|
|
519
478
|
return this._optionValueSources[key];
|
|
520
479
|
}
|
|
521
|
-
/** Globals overwrite locals, like optsWithGlobals. */
|
|
522
480
|
getOptionValueSourceWithGlobals(key) {
|
|
523
481
|
let source;
|
|
524
482
|
for (const cmd of this._getCommandAndAncestors()) {
|
|
@@ -527,7 +485,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
527
485
|
}
|
|
528
486
|
return source;
|
|
529
487
|
}
|
|
530
|
-
/** User args from argv per `from`; sets `_scriptPath` and the default program name. */
|
|
531
488
|
_prepareUserArgs(argv, parseOptions) {
|
|
532
489
|
if (argv !== undefined && !Array.isArray(argv))
|
|
533
490
|
throw new Error('first parameter to parse must be array or undefined');
|
|
@@ -537,7 +494,7 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
537
494
|
parseOptions.from = 'electron';
|
|
538
495
|
const execArgv = host.execArgv ?? [];
|
|
539
496
|
if (execArgv.includes('-e') || execArgv.includes('--eval') || execArgv.includes('-p') || execArgv.includes('--print')) {
|
|
540
|
-
parseOptions.from = 'eval';
|
|
497
|
+
parseOptions.from = 'eval';
|
|
541
498
|
}
|
|
542
499
|
}
|
|
543
500
|
if (argv === undefined)
|
|
@@ -573,17 +530,10 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
573
530
|
this._name = this._name || 'program';
|
|
574
531
|
return userArgs;
|
|
575
532
|
}
|
|
576
|
-
/**
|
|
577
|
-
* Parse argv, set options and run commands. Use `parseAsync` when an action is async.
|
|
578
|
-
* With no arguments, parses process.argv and auto-detects Electron and `node --eval`.
|
|
579
|
-
*/
|
|
580
533
|
parse(argv, parseOptions) {
|
|
581
534
|
const from = this._prepareBurgee(parseOptions);
|
|
582
535
|
this._prepareForParse();
|
|
583
536
|
const userArgs = this._prepareUserArgs(argv, from);
|
|
584
|
-
// The surface check is synchronous unless a surface is actually served (completions,
|
|
585
|
-
// --mcp), so a synchronous action has run by the time parse() returns — commander's
|
|
586
|
-
// contract, which its suite asserts on after every parse(). commander-sync.test.ts.
|
|
587
537
|
this._runBurgee(() => {
|
|
588
538
|
const served = this._burgeeSurface(userArgs);
|
|
589
539
|
if (isThenable(served))
|
|
@@ -596,8 +546,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
596
546
|
const from = this._prepareBurgee(parseOptions);
|
|
597
547
|
this._prepareForParse();
|
|
598
548
|
const userArgs = this._prepareUserArgs(argv, from);
|
|
599
|
-
// Same synchronous start as parse(): a preAction hook has run before the promise is
|
|
600
|
-
// handed back, which commander's hook tests assert on.
|
|
601
549
|
await this._runBurgee(() => {
|
|
602
550
|
const served = this._burgeeSurface(userArgs);
|
|
603
551
|
if (isThenable(served))
|
|
@@ -608,7 +556,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
608
556
|
}
|
|
609
557
|
_prepareForParse() {
|
|
610
558
|
if (this._savedState === null) {
|
|
611
|
-
// Lone negated option (--no-foo without --foo) defaults to true, now that all options are known.
|
|
612
559
|
for (const option of this.options) {
|
|
613
560
|
if (option.negate && option.defaultValue === undefined && this.getOptionValue(option.attributeName()) === undefined) {
|
|
614
561
|
const positiveLongFlag = (option.long ?? '').replace(/^--no-/, '--');
|
|
@@ -622,7 +569,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
622
569
|
this.restoreStateBeforeParse();
|
|
623
570
|
}
|
|
624
571
|
}
|
|
625
|
-
/** Called lazily on first parse; available for subclasses to save custom state. */
|
|
626
572
|
saveStateBeforeParse() {
|
|
627
573
|
this._savedState = {
|
|
628
574
|
_name: this._name,
|
|
@@ -668,7 +614,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
668
614
|
const foundExt = SOURCE_EXT.find((ext) => fs.existsSync(`${localBin}${ext}`));
|
|
669
615
|
return foundExt ? `${localBin}${foundExt}` : undefined;
|
|
670
616
|
};
|
|
671
|
-
// Not checking for help first: can't robustly test for help flags in an external command.
|
|
672
617
|
this._checkForMissingMandatoryOptions();
|
|
673
618
|
this._checkForConflictingOptions();
|
|
674
619
|
let executableFile = subcommand._executableFile || `${this._name}-${subcommand._name}`;
|
|
@@ -685,7 +630,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
685
630
|
}
|
|
686
631
|
if (executableDir) {
|
|
687
632
|
let localFile = findFile(executableDir, executableFile);
|
|
688
|
-
// Legacy search using the script name as prefix instead of the command name.
|
|
689
633
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
690
634
|
const legacyName = path.basename(this._scriptPath, path.extname(this._scriptPath));
|
|
691
635
|
if (legacyName !== this._name)
|
|
@@ -694,10 +638,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
694
638
|
executableFile = localFile || executableFile;
|
|
695
639
|
}
|
|
696
640
|
const launchWithNode = SOURCE_EXT.includes(path.extname(executableFile));
|
|
697
|
-
// Through `bellpull`, not `node:child_process`: it resolves the executable properly on
|
|
698
|
-
// Windows, where upstream sends every spawn through `node` to dodge `PATHEXT`. The
|
|
699
|
-
// reasoning, the measurement and the mock constraint are in `weight.test.ts`'s
|
|
700
|
-
// `./commander` entry — they are prose, and prose in this file ships.
|
|
701
641
|
let proc;
|
|
702
642
|
if (host.platform !== 'win32') {
|
|
703
643
|
if (launchWithNode) {
|
|
@@ -717,12 +657,10 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
717
657
|
proc = crossSpawn.spawn(host.execPath, args, { stdio: 'inherit' });
|
|
718
658
|
}
|
|
719
659
|
else {
|
|
720
|
-
// The case upstream cannot reach: a `.cmd`, a `.bat`, or a shebang that is not node.
|
|
721
660
|
proc = crossSpawn.spawn(executableFile, args, { stdio: 'inherit' });
|
|
722
661
|
}
|
|
723
662
|
}
|
|
724
663
|
if (!proc.killed) {
|
|
725
|
-
// Testing mainly to avoid leak warnings during unit tests with mocked spawn.
|
|
726
664
|
for (const signal of FORWARDED_SIGNALS) {
|
|
727
665
|
host.on(signal, () => {
|
|
728
666
|
if (proc.killed === false && proc.exitCode === null)
|
|
@@ -732,7 +670,7 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
732
670
|
}
|
|
733
671
|
const exitCallback = this._exitCallback;
|
|
734
672
|
proc.on('close', (code) => {
|
|
735
|
-
code = code ?? 1;
|
|
673
|
+
code = code ?? 1;
|
|
736
674
|
if (!exitCallback)
|
|
737
675
|
host.exit(code);
|
|
738
676
|
else
|
|
@@ -772,14 +710,12 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
772
710
|
});
|
|
773
711
|
return promiseChain;
|
|
774
712
|
}
|
|
775
|
-
/** `help foo`: invoke help directly if possible, or dispatch if necessary. */
|
|
776
713
|
_dispatchHelpCommand(subcommandName) {
|
|
777
714
|
if (!subcommandName)
|
|
778
715
|
this.help();
|
|
779
716
|
const subCommand = this._findCommand(subcommandName);
|
|
780
717
|
if (subCommand && !subCommand._executableHandler)
|
|
781
718
|
subCommand.help();
|
|
782
|
-
// Fallback to parsing the help flag to invoke the help.
|
|
783
719
|
return this._dispatchSubcommand(subcommandName ?? '', [], [
|
|
784
720
|
this._getHelpOption()?.long ?? this._getHelpOption()?.short ?? '--help',
|
|
785
721
|
]);
|
|
@@ -795,7 +731,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
795
731
|
if (this.args.length > this.registeredArguments.length)
|
|
796
732
|
this._excessArguments(this.args);
|
|
797
733
|
}
|
|
798
|
-
/** Process this.args against registeredArguments into this.processedArgs. */
|
|
799
734
|
_processArguments() {
|
|
800
735
|
const myParseArg = (argument, value, previous) => {
|
|
801
736
|
let parsedValue = value;
|
|
@@ -828,7 +763,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
828
763
|
});
|
|
829
764
|
this.processedArgs = processedArgs;
|
|
830
765
|
}
|
|
831
|
-
/** Chain once we have a promise; call synchronously until then. */
|
|
832
766
|
_chainOrCall(promise, fn) {
|
|
833
767
|
if (isThenable(promise))
|
|
834
768
|
return promise.then(() => fn());
|
|
@@ -855,15 +789,12 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
855
789
|
}
|
|
856
790
|
return result;
|
|
857
791
|
}
|
|
858
|
-
/** Process arguments in the context of this command; returns the action result in case it is a promise. */
|
|
859
792
|
_parseCommand(operands, unknown) {
|
|
860
793
|
const parsed = this.parseOptions(unknown);
|
|
861
|
-
this._parseOptionsEnv();
|
|
794
|
+
this._parseOptionsEnv();
|
|
862
795
|
this._parseOptionsImplied();
|
|
863
796
|
operands = operands.concat(parsed.operands);
|
|
864
797
|
unknown = parsed.unknown;
|
|
865
|
-
if (this._actionHandler && !this._findCommand(operands[0]) && !this._defaultCommandName)
|
|
866
|
-
this._takeJson(unknown);
|
|
867
798
|
this.args = operands.concat(unknown);
|
|
868
799
|
if (operands && this._findCommand(operands[0])) {
|
|
869
800
|
return this._dispatchSubcommand(operands[0] ?? '', operands.slice(1), unknown);
|
|
@@ -873,17 +804,15 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
873
804
|
return this._dispatchHelpCommand(operands[1]);
|
|
874
805
|
}
|
|
875
806
|
if (this._defaultCommandName) {
|
|
876
|
-
this._outputHelpIfRequested(unknown);
|
|
807
|
+
this._outputHelpIfRequested(unknown);
|
|
877
808
|
return this._dispatchSubcommand(this._defaultCommandName, operands, unknown);
|
|
878
809
|
}
|
|
879
810
|
if (this.commands.length && this.args.length === 0 && !this._actionHandler && !this._defaultCommandName) {
|
|
880
|
-
// probably missing subcommand and no handler, user needs help (and exit)
|
|
881
811
|
this.help({ error: true });
|
|
882
812
|
}
|
|
883
813
|
this._outputHelpIfRequested(parsed.unknown);
|
|
884
814
|
this._checkForMissingMandatoryOptions();
|
|
885
815
|
this._checkForConflictingOptions();
|
|
886
|
-
// Not always called, to avoid masking a "better" error like unknown command.
|
|
887
816
|
const checkForUnknownOptions = () => {
|
|
888
817
|
if (parsed.unknown.length > 0)
|
|
889
818
|
this.unknownOption(parsed.unknown[0] ?? '');
|
|
@@ -897,7 +826,7 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
897
826
|
promiseChain = this._chainOrCall(promiseChain, () => this._runAction());
|
|
898
827
|
if (this.parent) {
|
|
899
828
|
promiseChain = this._chainOrCall(promiseChain, () => {
|
|
900
|
-
this.parent?.emit(commandEvent, operands, unknown);
|
|
829
|
+
this.parent?.emit(commandEvent, operands, unknown);
|
|
901
830
|
});
|
|
902
831
|
}
|
|
903
832
|
promiseChain = this._chainOrCallHooks(promiseChain, 'postAction');
|
|
@@ -906,15 +835,13 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
906
835
|
if (this.parent?.listenerCount(commandEvent)) {
|
|
907
836
|
checkForUnknownOptions();
|
|
908
837
|
this._processArguments();
|
|
909
|
-
this.parent.emit(commandEvent, operands, unknown);
|
|
838
|
+
this.parent.emit(commandEvent, operands, unknown);
|
|
910
839
|
}
|
|
911
840
|
else if (operands.length) {
|
|
912
841
|
if (this._findCommand('*')) {
|
|
913
|
-
// legacy default command
|
|
914
842
|
return this._dispatchSubcommand('*', operands, unknown);
|
|
915
843
|
}
|
|
916
844
|
if (this.listenerCount('command:*')) {
|
|
917
|
-
// skip option check, emit event for possible misspelling suggestion
|
|
918
845
|
this.emit('command:*', operands, unknown);
|
|
919
846
|
}
|
|
920
847
|
else if (this.commands.length) {
|
|
@@ -927,13 +854,11 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
927
854
|
}
|
|
928
855
|
else if (this.commands.length) {
|
|
929
856
|
checkForUnknownOptions();
|
|
930
|
-
// This command has subcommands and nothing hooked up at this level, so display help (and exit).
|
|
931
857
|
this.help({ error: true });
|
|
932
858
|
}
|
|
933
859
|
else {
|
|
934
860
|
checkForUnknownOptions();
|
|
935
861
|
this._processArguments();
|
|
936
|
-
// fall through for caller to handle after calling .parse()
|
|
937
862
|
}
|
|
938
863
|
return undefined;
|
|
939
864
|
}
|
|
@@ -945,7 +870,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
945
870
|
_findOption(arg) {
|
|
946
871
|
return this.options.find((option) => option.is(arg));
|
|
947
872
|
}
|
|
948
|
-
/** Walks up the hierarchy so a subcommand can check after displaying help. */
|
|
949
873
|
_checkForMissingMandatoryOptions() {
|
|
950
874
|
for (const cmd of this._getCommandAndAncestors()) {
|
|
951
875
|
for (const anOption of cmd.options) {
|
|
@@ -973,15 +897,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
973
897
|
for (const cmd of this._getCommandAndAncestors())
|
|
974
898
|
cmd._checkForConflictingLocalOptions();
|
|
975
899
|
}
|
|
976
|
-
/**
|
|
977
|
-
* Parse options from `args`, removing known options, and return argv split into
|
|
978
|
-
* operands and unknown arguments. Side effect: stores option values on the command.
|
|
979
|
-
*
|
|
980
|
-
* --known kkk op => [op], []
|
|
981
|
-
* op --known kkk => [op], []
|
|
982
|
-
* sub --unknown uuu op => [sub], [--unknown uuu op]
|
|
983
|
-
* sub -- --unknown uuu op => [sub --unknown uuu op], []
|
|
984
|
-
*/
|
|
985
900
|
parseOptions(args) {
|
|
986
901
|
const operands = [];
|
|
987
902
|
const unknown = [];
|
|
@@ -990,11 +905,10 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
990
905
|
const negativeNumberArg = (arg) => {
|
|
991
906
|
if (!/^-(\d+|\d*\.\d+)(e[+-]?\d+)?$/.test(arg))
|
|
992
907
|
return false;
|
|
993
|
-
// a negative number is ok unless a digit is used as an option in the command hierarchy
|
|
994
908
|
return !this._getCommandAndAncestors().some((cmd) => cmd.options.some((opt) => /^-\d$/.test(opt.short ?? '')));
|
|
995
909
|
};
|
|
996
910
|
let activeVariadicOption = null;
|
|
997
|
-
let activeGroup = null;
|
|
911
|
+
let activeGroup = null;
|
|
998
912
|
let i = 0;
|
|
999
913
|
while (i < args.length || activeGroup) {
|
|
1000
914
|
const arg = activeGroup ?? args[i++] ?? '';
|
|
@@ -1021,7 +935,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1021
935
|
}
|
|
1022
936
|
else if (option.optional) {
|
|
1023
937
|
let value = null;
|
|
1024
|
-
// historical behaviour: the optional value is the following arg unless it is an option
|
|
1025
938
|
const next = args[i];
|
|
1026
939
|
if (i < args.length && next !== undefined && (!maybeOption(next) || negativeNumberArg(next))) {
|
|
1027
940
|
value = next;
|
|
@@ -1035,8 +948,13 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1035
948
|
activeVariadicOption = option.variadic ? option : null;
|
|
1036
949
|
continue;
|
|
1037
950
|
}
|
|
951
|
+
if (arg === '--json' && !this._root()._declares('--json')) {
|
|
952
|
+
const root = this._root();
|
|
953
|
+
root._burgee ??= { exit: undefined, json: false };
|
|
954
|
+
root._burgee.json = true;
|
|
955
|
+
continue;
|
|
956
|
+
}
|
|
1038
957
|
}
|
|
1039
|
-
// Combined short options: eat the first one if known.
|
|
1040
958
|
if (arg.length > 2 && arg[0] === '-' && arg[1] !== '-') {
|
|
1041
959
|
const option = this._findOption(`-${arg[1]}`);
|
|
1042
960
|
if (option) {
|
|
@@ -1050,7 +968,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1050
968
|
continue;
|
|
1051
969
|
}
|
|
1052
970
|
}
|
|
1053
|
-
// Known long flag with value, like --foo=bar
|
|
1054
971
|
if (/^--[^=]+=/.test(arg)) {
|
|
1055
972
|
const index = arg.indexOf('=');
|
|
1056
973
|
const option = this._findOption(arg.slice(0, index));
|
|
@@ -1059,13 +976,9 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1059
976
|
continue;
|
|
1060
977
|
}
|
|
1061
978
|
}
|
|
1062
|
-
// Not recognised by this command: command-argument, subcommand option, unknown option, or help.
|
|
1063
|
-
// An unknown option makes everything after it unknown too, for a subcommand to reprocess.
|
|
1064
|
-
// A negative number in a leaf command is not an unknown option.
|
|
1065
979
|
if (dest === operands && maybeOption(arg) && !(this.commands.length === 0 && negativeNumberArg(arg))) {
|
|
1066
980
|
dest = unknown;
|
|
1067
981
|
}
|
|
1068
|
-
// Positional options: stop processing our options at a subcommand.
|
|
1069
982
|
if ((this._enablePositionalOptions || this._passThroughOptions) && operands.length === 0 && unknown.length === 0) {
|
|
1070
983
|
if (this._findCommand(arg)) {
|
|
1071
984
|
operands.push(arg);
|
|
@@ -1081,7 +994,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1081
994
|
break;
|
|
1082
995
|
}
|
|
1083
996
|
}
|
|
1084
|
-
// Pass-through options: stop processing options at the first command-argument.
|
|
1085
997
|
if (this._passThroughOptions) {
|
|
1086
998
|
dest.push(arg, ...args.slice(i));
|
|
1087
999
|
break;
|
|
@@ -1090,7 +1002,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1090
1002
|
}
|
|
1091
1003
|
return { operands, unknown };
|
|
1092
1004
|
}
|
|
1093
|
-
/** Local option values as key-value pairs. */
|
|
1094
1005
|
opts() {
|
|
1095
1006
|
if (this._storeOptionsAsProperties) {
|
|
1096
1007
|
const result = {};
|
|
@@ -1102,31 +1013,40 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1102
1013
|
}
|
|
1103
1014
|
return this._optionValues;
|
|
1104
1015
|
}
|
|
1105
|
-
/** Merged local and global option values; globals overwrite locals. */
|
|
1106
1016
|
optsWithGlobals() {
|
|
1107
1017
|
return this._getCommandAndAncestors().reduce((combined, cmd) => Object.assign(combined, cmd.opts()), {});
|
|
1108
1018
|
}
|
|
1109
|
-
/** Display an error message and exit (or call exitOverride). */
|
|
1110
1019
|
error(message, errorOptions) {
|
|
1111
|
-
this._outputConfiguration.outputError(`${message}\n`, this._outputConfiguration.writeErr);
|
|
1112
|
-
if (typeof this._showHelpAfterError === 'string') {
|
|
1113
|
-
this._outputConfiguration.writeErr(`${this._showHelpAfterError}\n`);
|
|
1114
|
-
}
|
|
1115
|
-
else if (this._showHelpAfterError) {
|
|
1116
|
-
this._outputConfiguration.writeErr('\n');
|
|
1117
|
-
this.outputHelp({ error: true });
|
|
1118
|
-
}
|
|
1119
1020
|
const config = errorOptions ?? {};
|
|
1120
1021
|
const exitCode = config.exitCode || 1;
|
|
1121
1022
|
const code = config.code || 'commander.error';
|
|
1023
|
+
if (this._root()._burgee?.json === true)
|
|
1024
|
+
this._reportJson(code, message);
|
|
1025
|
+
else {
|
|
1026
|
+
this._outputConfiguration.outputError(`${message}\n`, this._outputConfiguration.writeErr);
|
|
1027
|
+
if (typeof this._showHelpAfterError === 'string') {
|
|
1028
|
+
this._outputConfiguration.writeErr(`${this._showHelpAfterError}\n`);
|
|
1029
|
+
}
|
|
1030
|
+
else if (this._showHelpAfterError) {
|
|
1031
|
+
this._outputConfiguration.writeErr('\n');
|
|
1032
|
+
this.outputHelp({ error: true });
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1122
1035
|
this._exit(exitCode, code, message);
|
|
1123
1036
|
}
|
|
1124
|
-
|
|
1037
|
+
_reportJson(code, message) {
|
|
1038
|
+
const burgee = this._root()._burgee;
|
|
1039
|
+
if (burgee === undefined || !burgee.json || burgee.reported)
|
|
1040
|
+
return;
|
|
1041
|
+
burgee.reported = true;
|
|
1042
|
+
const [first = '', ...rest] = message.replace(/^error: /, '').split('\n');
|
|
1043
|
+
const guess = /\(Did you mean (\S+)\?\)/.exec(rest.join(''));
|
|
1044
|
+
this._outputConfiguration.writeOut(`${JSON.stringify({ ok: false, error: { code, message: first, ...(guess === null ? {} : { fix: guess[1] }) } })}\n`);
|
|
1045
|
+
}
|
|
1125
1046
|
_parseOptionsEnv() {
|
|
1126
1047
|
for (const option of this.options) {
|
|
1127
1048
|
if (option.envVar && option.envVar in host.env) {
|
|
1128
1049
|
const optionKey = option.attributeName();
|
|
1129
|
-
// Do not overwrite cli values or values from an unknown (client-code) source.
|
|
1130
1050
|
if (this.getOptionValue(optionKey) === undefined || ENV_SOURCES.includes(this.getOptionValueSource(optionKey) ?? '')) {
|
|
1131
1051
|
if (option.required || option.optional)
|
|
1132
1052
|
this.emit(`optionEnv:${option.name()}`, host.env[option.envVar]);
|
|
@@ -1136,7 +1056,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1136
1056
|
}
|
|
1137
1057
|
}
|
|
1138
1058
|
}
|
|
1139
|
-
/** Apply implied option values where the option is undefined or at its default. */
|
|
1140
1059
|
_parseOptionsImplied() {
|
|
1141
1060
|
const dualHelper = new DualOptions(this.options);
|
|
1142
1061
|
const hasCustomOptionValue = (optionKey) => this.getOptionValue(optionKey) !== undefined && !IMPLIED_SOURCES.includes(this.getOptionValueSource(optionKey) ?? '');
|
|
@@ -1160,7 +1079,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1160
1079
|
this.error(`error: required option '${option.flags}' not specified`, { code: 'commander.missingMandatoryOptionValue' });
|
|
1161
1080
|
}
|
|
1162
1081
|
_conflictingOption(option, conflictingOption) {
|
|
1163
|
-
// The caller does not know whether a negated option is the source of the value; take an educated guess.
|
|
1164
1082
|
const findBestOptionFromValue = (candidate) => {
|
|
1165
1083
|
const optionKey = candidate.attributeName();
|
|
1166
1084
|
const optionValue = this.getOptionValue(optionKey);
|
|
@@ -1188,7 +1106,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1188
1106
|
return;
|
|
1189
1107
|
let suggestion = '';
|
|
1190
1108
|
if (flag.startsWith('--') && this._showSuggestionAfterError) {
|
|
1191
|
-
// Looping to pick up the global options too.
|
|
1192
1109
|
let candidateFlags = [];
|
|
1193
1110
|
let command = this;
|
|
1194
1111
|
do {
|
|
@@ -1265,7 +1182,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1265
1182
|
let command = this;
|
|
1266
1183
|
const last = this.commands[this.commands.length - 1];
|
|
1267
1184
|
if (this.commands.length !== 0 && last?._executableHandler) {
|
|
1268
|
-
// assume adding an alias for the last added executable subcommand, rather than this
|
|
1269
1185
|
command = last;
|
|
1270
1186
|
}
|
|
1271
1187
|
if (alias === command._name)
|
|
@@ -1329,7 +1245,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1329
1245
|
if (this._defaultCommandGroup && !cmd.helpGroup())
|
|
1330
1246
|
cmd.helpGroup(this._defaultCommandGroup);
|
|
1331
1247
|
}
|
|
1332
|
-
/** Name the command from a script filename, such as process.argv[1] or import.meta.filename. */
|
|
1333
1248
|
nameFromFilename(filename) {
|
|
1334
1249
|
this._name = path.basename(filename, path.extname(filename));
|
|
1335
1250
|
return this;
|
|
@@ -1376,7 +1291,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1376
1291
|
};
|
|
1377
1292
|
return { error, write, hasColors, helpWidth };
|
|
1378
1293
|
}
|
|
1379
|
-
/** Output built-in help plus any text added with `addHelpText`. */
|
|
1380
1294
|
outputHelp(contextOptions) {
|
|
1381
1295
|
let deprecatedCallback;
|
|
1382
1296
|
if (typeof contextOptions === 'function') {
|
|
@@ -1398,17 +1312,16 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1398
1312
|
outputContext.write(String(helpInformation));
|
|
1399
1313
|
const helpLong = this._getHelpOption()?.long;
|
|
1400
1314
|
if (helpLong)
|
|
1401
|
-
this.emit(helpLong);
|
|
1315
|
+
this.emit(helpLong);
|
|
1402
1316
|
this.emit('afterHelp', eventContext);
|
|
1403
1317
|
for (const command of this._getCommandAndAncestors())
|
|
1404
1318
|
command.emit('afterAllHelp', eventContext);
|
|
1405
1319
|
}
|
|
1406
|
-
/** Customise the built-in help option, or pass false to disable it. */
|
|
1407
1320
|
helpOption(flags, description) {
|
|
1408
1321
|
if (typeof flags === 'boolean') {
|
|
1409
1322
|
if (flags) {
|
|
1410
1323
|
if (this._helpOption === null)
|
|
1411
|
-
this._helpOption = undefined;
|
|
1324
|
+
this._helpOption = undefined;
|
|
1412
1325
|
if (this._defaultOptionGroup) {
|
|
1413
1326
|
const helpOption = this._getHelpOption();
|
|
1414
1327
|
if (helpOption)
|
|
@@ -1416,7 +1329,7 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1416
1329
|
}
|
|
1417
1330
|
}
|
|
1418
1331
|
else {
|
|
1419
|
-
this._helpOption = null;
|
|
1332
|
+
this._helpOption = null;
|
|
1420
1333
|
}
|
|
1421
1334
|
return this;
|
|
1422
1335
|
}
|
|
@@ -1425,7 +1338,6 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1425
1338
|
this._initOptionGroup(this._helpOption);
|
|
1426
1339
|
return this;
|
|
1427
1340
|
}
|
|
1428
|
-
/** Lazily created; null once disabled with `helpOption(false)`. */
|
|
1429
1341
|
_getHelpOption() {
|
|
1430
1342
|
if (this._helpOption === undefined)
|
|
1431
1343
|
this.helpOption(undefined, undefined);
|
|
@@ -1436,16 +1348,13 @@ Expecting one of '${HOOK_EVENTS.join("', '")}'`);
|
|
|
1436
1348
|
this._initOptionGroup(option);
|
|
1437
1349
|
return this;
|
|
1438
1350
|
}
|
|
1439
|
-
/** Output help and exit. */
|
|
1440
1351
|
help(contextOptions) {
|
|
1441
1352
|
this.outputHelp(contextOptions);
|
|
1442
1353
|
let exitCode = Number(host.exitCode ?? 0);
|
|
1443
1354
|
if (exitCode === 0 && contextOptions && typeof contextOptions !== 'function' && contextOptions.error)
|
|
1444
1355
|
exitCode = 1;
|
|
1445
|
-
// message: not all displayed text is available, so only a placeholder is passed.
|
|
1446
1356
|
this._exit(exitCode, 'commander.help', '(outputHelp)');
|
|
1447
1357
|
}
|
|
1448
|
-
/** Extra help text: 'before'/'after' for this command, 'beforeAll'/'afterAll' for its subcommands too. */
|
|
1449
1358
|
addHelpText(position, text) {
|
|
1450
1359
|
if (!HELP_POSITIONS.includes(position)) {
|
|
1451
1360
|
throw new Error(`Unexpected value for position to addHelpText.
|
|
@@ -1465,17 +1374,12 @@ Expecting one of '${HELP_POSITIONS.join("', '")}'`);
|
|
|
1465
1374
|
this._exit(0, 'commander.helpDisplayed', '(outputHelp)');
|
|
1466
1375
|
}
|
|
1467
1376
|
}
|
|
1468
|
-
// ───── burgee: the manifest projection, plugins, `--json` and the injected seam ─────
|
|
1469
1377
|
_root() {
|
|
1470
1378
|
let command = this;
|
|
1471
1379
|
while (command.parent)
|
|
1472
1380
|
command = command.parent;
|
|
1473
1381
|
return command;
|
|
1474
1382
|
}
|
|
1475
|
-
/**
|
|
1476
|
-
* The manifest every surface reads. Projected from the command tree on each access,
|
|
1477
|
-
* so it is never stale; plugin-contributed nodes are kept across projections.
|
|
1478
|
-
*/
|
|
1479
1383
|
get manifest() {
|
|
1480
1384
|
const root = this._root();
|
|
1481
1385
|
root._manifest ??= new Manifest();
|
|
@@ -1507,7 +1411,6 @@ Expecting one of '${HELP_POSITIONS.join("', '")}'`);
|
|
|
1507
1411
|
};
|
|
1508
1412
|
visit(this, [rootName]);
|
|
1509
1413
|
}
|
|
1510
|
-
/** Options as the manifest describes them, on a null-prototype record. */
|
|
1511
1414
|
_optionSpecs() {
|
|
1512
1415
|
const specs = Object.create(null);
|
|
1513
1416
|
for (const option of this.options) {
|
|
@@ -1526,32 +1429,19 @@ Expecting one of '${HELP_POSITIONS.join("', '")}'`);
|
|
|
1526
1429
|
}
|
|
1527
1430
|
return specs;
|
|
1528
1431
|
}
|
|
1529
|
-
/** burgee: declare what the command does to the world (N6). This is what exposes it as an MCP tool (N2). */
|
|
1530
1432
|
effects(value) {
|
|
1531
1433
|
this._effects = value;
|
|
1532
1434
|
return this;
|
|
1533
1435
|
}
|
|
1534
|
-
/**
|
|
1535
|
-
* burgee: mark the command deprecated (M5). Help and `--schema` show it; running it prints
|
|
1536
|
-
* `warning: 'old' is deprecated, use 'new'` on stderr once and goes on, exit unchanged.
|
|
1537
|
-
*/
|
|
1538
1436
|
deprecate(use) {
|
|
1539
1437
|
this._deprecated = use ?? true;
|
|
1540
1438
|
return this;
|
|
1541
1439
|
}
|
|
1542
|
-
/**
|
|
1543
|
-
* burgee: `--schema` and `--mcp` on a commander-syntax program, from its manifest (J2).
|
|
1544
|
-
* Only when the program declares neither option itself; `--mcp` runs commands through
|
|
1545
|
-
* this very program with the streams captured, so tool results are the `--json` envelope.
|
|
1546
|
-
*/
|
|
1547
1440
|
_burgeeSurface(userArgs) {
|
|
1548
1441
|
const root = this._root();
|
|
1549
|
-
// Any command in the tree that declares the flag keeps it: the surface is additive only.
|
|
1550
|
-
const declared = (flag, at = root) => at._findOption(flag) !== undefined || at.commands.some((sub) => declared(flag, sub));
|
|
1551
1442
|
const terminator = userArgs.indexOf('--');
|
|
1552
1443
|
const head = terminator === -1 ? userArgs : userArgs.slice(0, terminator);
|
|
1553
1444
|
if (head[0] === 'completion' && root._findCommand('completion') === undefined) {
|
|
1554
|
-
// Loaded on this command only (K6), exactly as the engine does.
|
|
1555
1445
|
return import('../completions.js').then(({ renderCompletion, renderFigSpec, SHELLS }) => {
|
|
1556
1446
|
const shell = head[1] ?? '';
|
|
1557
1447
|
if (shell === 'fig') {
|
|
@@ -1563,21 +1453,19 @@ Expecting one of '${HELP_POSITIONS.join("', '")}'`);
|
|
|
1563
1453
|
root._outputConfiguration.writeOut(renderCompletion(this.manifest, known));
|
|
1564
1454
|
return true;
|
|
1565
1455
|
}
|
|
1566
|
-
return this._burgeeSurfaceRest(head
|
|
1456
|
+
return this._burgeeSurfaceRest(head);
|
|
1567
1457
|
});
|
|
1568
1458
|
}
|
|
1569
|
-
return this._burgeeSurfaceRest(head
|
|
1459
|
+
return this._burgeeSurfaceRest(head);
|
|
1570
1460
|
}
|
|
1571
|
-
|
|
1572
|
-
_burgeeSurfaceRest(head, declared) {
|
|
1461
|
+
_burgeeSurfaceRest(head) {
|
|
1573
1462
|
const root = this._root();
|
|
1574
|
-
if (head.includes('--schema') && !
|
|
1575
|
-
// R1, and the same escape hatch the engine has: `--schema` is burgee's surface, not
|
|
1576
|
-
// commander's, so it answers to E-floor byte discipline rather than to the host.
|
|
1463
|
+
if (head.includes('--schema') && !root._declares('--schema')) {
|
|
1577
1464
|
root._outputConfiguration.writeOut(`${machineJson(schemaOf(this.manifest), head)}\n`);
|
|
1578
1465
|
return true;
|
|
1579
1466
|
}
|
|
1580
|
-
if (head[0] === '--mcp' && !
|
|
1467
|
+
if (head[0] === '--mcp' && !root._declares('--mcp')) {
|
|
1468
|
+
const writeOut = root._outputConfiguration.writeOut;
|
|
1581
1469
|
const invoke = async (args) => {
|
|
1582
1470
|
const out = [];
|
|
1583
1471
|
const err = [];
|
|
@@ -1585,16 +1473,14 @@ Expecting one of '${HELP_POSITIONS.join("', '")}'`);
|
|
|
1585
1473
|
await root.parseAsync(args, { from: 'user', stdout: { write: (s) => out.push(s) }, stderr: { write: (s) => err.push(s) }, exit: (c) => void (code = c) });
|
|
1586
1474
|
return { stdout: out.join(''), stderr: err.join(''), code };
|
|
1587
1475
|
};
|
|
1588
|
-
return serveMcp(this.manifest, { input: host.stdin, output: { write:
|
|
1476
|
+
return serveMcp(this.manifest, { input: host.stdin, output: { write: writeOut }, invoke }).then(() => true);
|
|
1589
1477
|
}
|
|
1590
1478
|
return false;
|
|
1591
1479
|
}
|
|
1592
|
-
/** Additive, and the point of the whole exercise: plugins commander has never had (#2505, unlanded). */
|
|
1593
1480
|
use(plugin) {
|
|
1594
1481
|
this.manifest.use(plugin);
|
|
1595
1482
|
return this;
|
|
1596
1483
|
}
|
|
1597
|
-
/** Inject the streams and the exit for one parse; returns commander's own parse options. */
|
|
1598
1484
|
_prepareBurgee(parseOptions) {
|
|
1599
1485
|
if (parseOptions === undefined)
|
|
1600
1486
|
return undefined;
|
|
@@ -1621,7 +1507,6 @@ Expecting one of '${HELP_POSITIONS.join("', '")}'`);
|
|
|
1621
1507
|
visit(root);
|
|
1622
1508
|
return from;
|
|
1623
1509
|
}
|
|
1624
|
-
/** In burgee mode the whole run settles to one E1 exit; otherwise commander's behaviour, untouched. */
|
|
1625
1510
|
_runBurgee(run) {
|
|
1626
1511
|
const root = this._root();
|
|
1627
1512
|
const burgee = root._burgee;
|
|
@@ -1633,15 +1518,14 @@ Expecting one of '${HELP_POSITIONS.join("', '")}'`);
|
|
|
1633
1518
|
};
|
|
1634
1519
|
const fail = (err) => {
|
|
1635
1520
|
if (err instanceof CommanderError) {
|
|
1636
|
-
if (
|
|
1637
|
-
root.
|
|
1638
|
-
}
|
|
1521
|
+
if (err.code !== 'commander.helpDisplayed' && err.code !== 'commander.version')
|
|
1522
|
+
root._reportJson(err.code, err.message);
|
|
1639
1523
|
finish(e1(err));
|
|
1640
1524
|
return;
|
|
1641
1525
|
}
|
|
1642
1526
|
const message = err instanceof Error ? err.message : String(err);
|
|
1643
1527
|
if (burgee.json)
|
|
1644
|
-
root.
|
|
1528
|
+
root._reportJson('runtime', message);
|
|
1645
1529
|
else
|
|
1646
1530
|
root._outputConfiguration.writeErr(`error: ${message}\n`);
|
|
1647
1531
|
finish(ExitCode.RUNTIME);
|
|
@@ -1658,20 +1542,9 @@ Expecting one of '${HELP_POSITIONS.join("', '")}'`);
|
|
|
1658
1542
|
return undefined;
|
|
1659
1543
|
}
|
|
1660
1544
|
}
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
const terminator = unknown.indexOf('--');
|
|
1664
|
-
const index = unknown.indexOf('--json');
|
|
1665
|
-
if (index === -1 || (terminator !== -1 && index > terminator))
|
|
1666
|
-
return;
|
|
1667
|
-
if (this._getCommandAndAncestors().some((cmd) => cmd._findOption('--json')))
|
|
1668
|
-
return;
|
|
1669
|
-
unknown.splice(index, 1);
|
|
1670
|
-
const root = this._root();
|
|
1671
|
-
root._burgee ??= { exit: undefined, json: false };
|
|
1672
|
-
root._burgee.json = true;
|
|
1545
|
+
_declares(flag) {
|
|
1546
|
+
return this._findOption(flag) !== undefined || this.commands.some((sub) => sub._declares(flag));
|
|
1673
1547
|
}
|
|
1674
|
-
/** The action, wrapped in the plugin hooks and followed by the envelope or the rendering. */
|
|
1675
1548
|
_runAction() {
|
|
1676
1549
|
const handler = this._actionHandler;
|
|
1677
1550
|
if (handler === null)
|
|
@@ -1694,7 +1567,6 @@ Expecting one of '${HELP_POSITIONS.join("', '")}'`);
|
|
|
1694
1567
|
settle(value);
|
|
1695
1568
|
});
|
|
1696
1569
|
}
|
|
1697
|
-
/** burgee (M5): once per process, on stderr; only for a command that asked, so commander's own output is untouched. */
|
|
1698
1570
|
_warnDeprecated() {
|
|
1699
1571
|
if (this._deprecated === undefined || this._deprecated === false || this._deprecationWarned)
|
|
1700
1572
|
return;
|
|
@@ -1702,7 +1574,6 @@ Expecting one of '${HELP_POSITIONS.join("', '")}'`);
|
|
|
1702
1574
|
const use = typeof this._deprecated === 'string' ? `, use '${this._deprecated}'` : '';
|
|
1703
1575
|
this._outputConfiguration.writeErr(`warning: '${this.name()}' is deprecated${use}\n`);
|
|
1704
1576
|
}
|
|
1705
|
-
/** burgee: where every option value came from, from commander's own value sources (V3). */
|
|
1706
1577
|
_provenance() {
|
|
1707
1578
|
const out = {};
|
|
1708
1579
|
const names = { cli: 'flag', env: 'env', config: 'config', default: 'default', implied: 'implied' };
|
|
@@ -1725,9 +1596,7 @@ Expecting one of '${HELP_POSITIONS.join("', '")}'`);
|
|
|
1725
1596
|
this._outputConfiguration.writeOut(text);
|
|
1726
1597
|
}
|
|
1727
1598
|
}
|
|
1728
|
-
/** Bump inspector ports so a spawned subcommand does not collide with the parent. */
|
|
1729
1599
|
function incrementNodeInspectorPort(args) {
|
|
1730
|
-
// --inspect[=[host:]port], --inspect-brk[=[host:]port], --inspect-port=[host:]port
|
|
1731
1600
|
return args.map((arg) => {
|
|
1732
1601
|
if (!arg.startsWith('--inspect'))
|
|
1733
1602
|
return arg;
|
|
@@ -1755,10 +1624,6 @@ function incrementNodeInspectorPort(args) {
|
|
|
1755
1624
|
return arg;
|
|
1756
1625
|
});
|
|
1757
1626
|
}
|
|
1758
|
-
/**
|
|
1759
|
-
* The common colour conventions: NO_COLOR and FORCE_COLOR=0/false disable, FORCE_COLOR
|
|
1760
|
-
* and CLICOLOR_FORCE enable, otherwise undecided (the stream's TTY-ness decides).
|
|
1761
|
-
*/
|
|
1762
1627
|
export function useColor() {
|
|
1763
1628
|
if (host.env['NO_COLOR'] || host.env['FORCE_COLOR'] === '0' || host.env['FORCE_COLOR'] === 'false')
|
|
1764
1629
|
return false;
|
|
@@ -1766,4 +1631,3 @@ export function useColor() {
|
|
|
1766
1631
|
return true;
|
|
1767
1632
|
return undefined;
|
|
1768
1633
|
}
|
|
1769
|
-
//# sourceMappingURL=command.js.map
|