@alcyone-labs/arg-parser 1.0.0 → 1.1.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/README.md +844 -45
- package/dist/examples/fuzzy-demo.d.ts +8 -0
- package/dist/examples/fuzzy-demo.d.ts.map +1 -0
- package/dist/examples/fuzzy-test-example.d.ts +8 -0
- package/dist/examples/fuzzy-test-example.d.ts.map +1 -0
- package/dist/examples/fzf-search-cli.d.ts +8 -0
- package/dist/examples/fzf-search-cli.d.ts.map +1 -0
- package/dist/examples/getting-started.d.ts +27 -0
- package/dist/examples/getting-started.d.ts.map +1 -0
- package/dist/examples/mcp-preset-transports.d.ts +19 -0
- package/dist/examples/mcp-preset-transports.d.ts.map +1 -0
- package/dist/examples/simple-cli.d.ts +26 -0
- package/dist/examples/simple-cli.d.ts.map +1 -0
- package/dist/examples/v1.1.0-showcase.d.ts +16 -0
- package/dist/examples/v1.1.0-showcase.d.ts.map +1 -0
- package/dist/examples/with-env-example.d.ts +3 -0
- package/dist/examples/with-env-example.d.ts.map +1 -0
- package/dist/index-6G9StDO_.js +6445 -0
- package/dist/index-6G9StDO_.js.map +1 -0
- package/dist/index-CqU7Fj3C.cjs +6444 -0
- package/dist/index-CqU7Fj3C.cjs.map +1 -0
- package/dist/index-Dx_q1msW.js +4682 -0
- package/dist/index-Dx_q1msW.js.map +1 -0
- package/dist/index.cjs +1704 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.min.mjs +1628 -484
- package/dist/index.min.mjs.map +1 -1
- package/dist/index.mjs +1660 -59
- package/dist/index.mjs.map +1 -1
- package/dist/src/ArgParser.d.ts +156 -0
- package/dist/src/ArgParser.d.ts.map +1 -0
- package/dist/{ArgParser.d.ts → src/ArgParserBase.d.ts} +20 -13
- package/dist/src/ArgParserBase.d.ts.map +1 -0
- package/dist/{FlagManager.d.ts → src/FlagManager.d.ts} +1 -1
- package/dist/src/FlagManager.d.ts.map +1 -0
- package/dist/src/fuzzy-test-cli.d.ts +5 -0
- package/dist/src/fuzzy-test-cli.d.ts.map +1 -0
- package/dist/src/fuzzy-tester.d.ts +101 -0
- package/dist/src/fuzzy-tester.d.ts.map +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/mcp-integration.d.ts +31 -0
- package/dist/src/mcp-integration.d.ts.map +1 -0
- package/dist/src/types.d.ts +154 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/sse-B5Jf_YpG.cjs +121 -0
- package/dist/sse-B5Jf_YpG.cjs.map +1 -0
- package/dist/sse-BDL3h2Ll.js +121 -0
- package/dist/sse-BDL3h2Ll.js.map +1 -0
- package/dist/sse-DSjLfGFo.js +107 -0
- package/dist/sse-DSjLfGFo.js.map +1 -0
- package/dist/stdio-Cf19UQO7.js +70 -0
- package/dist/stdio-Cf19UQO7.js.map +1 -0
- package/dist/stdio-DESvSONI.cjs +94 -0
- package/dist/stdio-DESvSONI.cjs.map +1 -0
- package/dist/stdio-DLOResWr.js +94 -0
- package/dist/stdio-DLOResWr.js.map +1 -0
- package/dist/streamableHttp-DXIdDSbF.js +342 -0
- package/dist/streamableHttp-DXIdDSbF.js.map +1 -0
- package/dist/streamableHttp-DsXlAnqJ.cjs +456 -0
- package/dist/streamableHttp-DsXlAnqJ.cjs.map +1 -0
- package/dist/streamableHttp-Vd4Qsgko.js +456 -0
- package/dist/streamableHttp-Vd4Qsgko.js.map +1 -0
- package/dist/types-DSxPEImy.cjs +943 -0
- package/dist/types-DSxPEImy.cjs.map +1 -0
- package/dist/types-DdsPVLQ5.js +846 -0
- package/dist/types-DdsPVLQ5.js.map +1 -0
- package/dist/types-DpK81FWv.js +944 -0
- package/dist/types-DpK81FWv.js.map +1 -0
- package/package.json +18 -7
- package/dist/ArgParser.d.ts.map +0 -1
- package/dist/FlagManager.d.ts.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/types.d.ts +0 -91
- package/dist/types.d.ts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,18 +1,65 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
2
8
|
var __typeError = (msg) => {
|
|
3
9
|
throw TypeError(msg);
|
|
4
10
|
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
5
27
|
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
6
28
|
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
7
29
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
8
30
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
9
31
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
10
|
-
var __flags, _throwForDuplicateFlags, _appName, _appCommandName, _subCommandName, _parameters, _handler, _throwForDuplicateFlags2, _description, _handleErrors, _parentParser, _lastParseResult, _inheritParentFlags, _subCommands, _flagManager,
|
|
32
|
+
var __flags, _throwForDuplicateFlags, _appName, _appCommandName, _subCommandName, _parameters, _handler, _throwForDuplicateFlags2, _description, _handleErrors, _parentParser, _lastParseResult, _inheritParentFlags, _subCommands, _flagManager, _fuzzyMode, _ArgParserBase_instances, _identifyCommandChainAndParsers_fn, _handleGlobalChecks_fn, _validateMandatoryFlags_fn, _applyDefaultValues_fn, _prepareAndExecuteHandler_fn, parseFlags_fn, _enableFuzzyMode_fn, displayErrorAndExit_fn, _printRecursiveToConsole_fn, _buildRecursiveString_fn, _buildRecursiveJson_fn, _generateDefaultEnvFileName_fn, _handleSaveToEnvFlag_fn, _saveToEnvFile_fn, _loadEnvFile_fn, _parseEnvFile_fn, _parseYamlFile_fn, _parseJsonFile_fn, _parseTomlFile_fn, _convertConfigToFlagValues_fn, _convertValueToFlagType_fn, _mergeEnvConfigWithArgs_fn, _generateEnvFormat_fn, _generateYamlFormat_fn, _generateJsonFormat_fn, _generateTomlFormat_fn, _getTypeString_fn, _ArgParser_instances, _startSingleTransport_fn;
|
|
11
33
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
34
|
+
const fs = require("node:fs");
|
|
35
|
+
const path = require("node:path");
|
|
12
36
|
const chalk = require("chalk");
|
|
13
37
|
const magicRegexp = require("magic-regexp");
|
|
38
|
+
const yaml = require("js-yaml");
|
|
39
|
+
const toml = require("@iarna/toml");
|
|
40
|
+
const dotenv = require("dotenv");
|
|
14
41
|
const zod = require("zod");
|
|
15
|
-
|
|
42
|
+
function _interopNamespaceDefault(e) {
|
|
43
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
44
|
+
if (e) {
|
|
45
|
+
for (const k in e) {
|
|
46
|
+
if (k !== "default") {
|
|
47
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
48
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: () => e[k]
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
n.default = e;
|
|
56
|
+
return Object.freeze(n);
|
|
57
|
+
}
|
|
58
|
+
const fs__namespace = /* @__PURE__ */ _interopNamespaceDefault(fs);
|
|
59
|
+
const path__namespace = /* @__PURE__ */ _interopNamespaceDefault(path);
|
|
60
|
+
const yaml__namespace = /* @__PURE__ */ _interopNamespaceDefault(yaml);
|
|
61
|
+
const toml__namespace = /* @__PURE__ */ _interopNamespaceDefault(toml);
|
|
62
|
+
const dotenv__namespace = /* @__PURE__ */ _interopNamespaceDefault(dotenv);
|
|
16
63
|
const zodFlagSchema = zod.z.object({
|
|
17
64
|
name: zod.z.string().min(1, "Flag name cannot be empty").describe(
|
|
18
65
|
"The output property name, used as a return key `{name: value}`. Must be unique."
|
|
@@ -37,14 +84,17 @@ const zodFlagSchema = zod.z.object({
|
|
|
37
84
|
message: "Must be Boolean constructor"
|
|
38
85
|
}),
|
|
39
86
|
zod.z.any().refine((val) => val === Array, {
|
|
87
|
+
// Native Array constructor
|
|
40
88
|
message: "Must be Array constructor"
|
|
41
89
|
}),
|
|
42
90
|
zod.z.any().refine((val) => val === Object, {
|
|
91
|
+
// Native Object constructor
|
|
43
92
|
message: "Must be Object constructor"
|
|
44
93
|
}),
|
|
45
94
|
zod.z.function().args(zod.z.string()).returns(zod.z.any()),
|
|
46
|
-
// Custom parser function
|
|
95
|
+
// Custom parser function (value: string) => any
|
|
47
96
|
zod.z.string().refine(
|
|
97
|
+
// String literal types
|
|
48
98
|
(value) => ["boolean", "string", "number", "array", "object"].includes(
|
|
49
99
|
value.toLowerCase()
|
|
50
100
|
),
|
|
@@ -53,7 +103,7 @@ const zodFlagSchema = zod.z.object({
|
|
|
53
103
|
}
|
|
54
104
|
)
|
|
55
105
|
]).default("string").describe(
|
|
56
|
-
"Expected data type or a custom parser function. Defaults to 'string'."
|
|
106
|
+
"Expected data type (constructor or string literal) or a custom parser function. Defaults to 'string'."
|
|
57
107
|
),
|
|
58
108
|
mandatory: zod.z.union([zod.z.boolean(), zod.z.function().args(zod.z.any()).returns(zod.z.boolean())]).optional().describe(
|
|
59
109
|
"Makes the flag mandatory, can be a boolean or a function conditional on other args."
|
|
@@ -179,9 +229,9 @@ class ArgParserError extends Error {
|
|
|
179
229
|
this.commandChain = cmdChain;
|
|
180
230
|
}
|
|
181
231
|
}
|
|
182
|
-
const
|
|
232
|
+
const _ArgParserBase = class _ArgParserBase {
|
|
183
233
|
constructor(options = {}, initialFlags) {
|
|
184
|
-
__privateAdd(this,
|
|
234
|
+
__privateAdd(this, _ArgParserBase_instances);
|
|
185
235
|
__privateAdd(this, _appName, "Argument Parser");
|
|
186
236
|
__privateAdd(this, _appCommandName);
|
|
187
237
|
__privateAdd(this, _subCommandName, "");
|
|
@@ -200,6 +250,7 @@ const _ArgParser = class _ArgParser {
|
|
|
200
250
|
__privateAdd(this, _inheritParentFlags, false);
|
|
201
251
|
__privateAdd(this, _subCommands, /* @__PURE__ */ new Map());
|
|
202
252
|
__privateAdd(this, _flagManager);
|
|
253
|
+
__privateAdd(this, _fuzzyMode, false);
|
|
203
254
|
__privateSet(this, _appName, options.appName || "app");
|
|
204
255
|
if (options.blankSpaceWidth && !isNaN(Number(options.blankSpaceWidth)) && Number(options.blankSpaceWidth) > 20)
|
|
205
256
|
__privateGet(this, _parameters).blankSpaceWidth = Number(options.blankSpaceWidth);
|
|
@@ -249,9 +300,27 @@ const _ArgParser = class _ArgParser {
|
|
|
249
300
|
get flagNames() {
|
|
250
301
|
return __privateGet(this, _flagManager).flagNames;
|
|
251
302
|
}
|
|
303
|
+
getAppName() {
|
|
304
|
+
return __privateGet(this, _appName);
|
|
305
|
+
}
|
|
306
|
+
getAppCommandName() {
|
|
307
|
+
return __privateGet(this, _appCommandName);
|
|
308
|
+
}
|
|
309
|
+
getSubCommandName() {
|
|
310
|
+
return __privateGet(this, _subCommandName);
|
|
311
|
+
}
|
|
312
|
+
getDescription() {
|
|
313
|
+
return __privateGet(this, _description);
|
|
314
|
+
}
|
|
315
|
+
getHandler() {
|
|
316
|
+
return __privateGet(this, _handler);
|
|
317
|
+
}
|
|
318
|
+
getSubCommands() {
|
|
319
|
+
return __privateGet(this, _subCommands);
|
|
320
|
+
}
|
|
252
321
|
_addToOutput(flag, arg, output, _parseOptions) {
|
|
253
322
|
let value = arg;
|
|
254
|
-
if (flag
|
|
323
|
+
if (flag["type"] === Boolean) {
|
|
255
324
|
if (typeof arg === "boolean") {
|
|
256
325
|
value = arg;
|
|
257
326
|
} else if (typeof arg === "string") {
|
|
@@ -302,9 +371,9 @@ const _ArgParser = class _ArgParser {
|
|
|
302
371
|
throw new Error(`Sub-command '${subCommandConfig.name}' already exists`);
|
|
303
372
|
}
|
|
304
373
|
const subParser = subCommandConfig.parser;
|
|
305
|
-
if (!(subParser instanceof
|
|
374
|
+
if (!(subParser instanceof _ArgParserBase)) {
|
|
306
375
|
throw new Error(
|
|
307
|
-
`Parser for subcommand '${subCommandConfig.name}' is not an instance of
|
|
376
|
+
`Parser for subcommand '${subCommandConfig.name}' is not an instance of ArgParserBase. Please provide 'new ArgParserBase(...)' for the 'parser' property of an ISubCommand.`
|
|
308
377
|
);
|
|
309
378
|
}
|
|
310
379
|
__privateSet(subParser, _parentParser, this);
|
|
@@ -341,22 +410,22 @@ const _ArgParser = class _ArgParser {
|
|
|
341
410
|
printAll(filePath) {
|
|
342
411
|
if (filePath) {
|
|
343
412
|
try {
|
|
344
|
-
const dir =
|
|
345
|
-
if (!
|
|
346
|
-
|
|
413
|
+
const dir = path__namespace.dirname(filePath);
|
|
414
|
+
if (!fs__namespace.existsSync(dir)) {
|
|
415
|
+
fs__namespace.mkdirSync(dir, { recursive: true });
|
|
347
416
|
}
|
|
348
417
|
if (filePath.toLowerCase().endsWith(".json")) {
|
|
349
|
-
const outputObject = __privateMethod(this,
|
|
418
|
+
const outputObject = __privateMethod(this, _ArgParserBase_instances, _buildRecursiveJson_fn).call(this, this);
|
|
350
419
|
const jsonString = JSON.stringify(outputObject, null, 2);
|
|
351
|
-
|
|
420
|
+
fs__namespace.writeFileSync(filePath, jsonString);
|
|
352
421
|
console.log(`ArgParser configuration JSON dumped to: ${filePath}`);
|
|
353
422
|
} else {
|
|
354
|
-
const outputString = __privateMethod(this,
|
|
423
|
+
const outputString = __privateMethod(this, _ArgParserBase_instances, _buildRecursiveString_fn).call(this, this, 0);
|
|
355
424
|
const plainText = outputString.replace(
|
|
356
425
|
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
|
|
357
426
|
""
|
|
358
427
|
);
|
|
359
|
-
|
|
428
|
+
fs__namespace.writeFileSync(filePath, plainText);
|
|
360
429
|
console.log(`ArgParser configuration text dumped to: ${filePath}`);
|
|
361
430
|
}
|
|
362
431
|
} catch (error) {
|
|
@@ -367,12 +436,21 @@ const _ArgParser = class _ArgParser {
|
|
|
367
436
|
}
|
|
368
437
|
} else {
|
|
369
438
|
console.log("\n--- ArgParser Configuration Dump ---");
|
|
370
|
-
__privateMethod(this,
|
|
439
|
+
__privateMethod(this, _ArgParserBase_instances, _printRecursiveToConsole_fn).call(this, this, 0);
|
|
371
440
|
console.log("--- End Configuration Dump ---\\n");
|
|
372
441
|
}
|
|
373
442
|
}
|
|
374
443
|
parse(processArgs, options) {
|
|
375
|
-
|
|
444
|
+
var _a;
|
|
445
|
+
const originalProcessArgs = [...processArgs];
|
|
446
|
+
const shouldPreventExecution = typeof process !== "undefined" && (process.env["ARGPARSER_FUZZY_MODE"] === "true" || process.argv && process.argv.includes("--s-enable-fuzzy") && !processArgs.includes("--s-enable-fuzzy")) && !(options == null ? void 0 : options.skipHelpHandling);
|
|
447
|
+
if (shouldPreventExecution) {
|
|
448
|
+
return {
|
|
449
|
+
_fuzzyModePreventedExecution: true,
|
|
450
|
+
_originalInputArgs: originalProcessArgs
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
if (__privateMethod(this, _ArgParserBase_instances, _handleGlobalChecks_fn).call(this, processArgs, options)) {
|
|
376
454
|
return {};
|
|
377
455
|
}
|
|
378
456
|
try {
|
|
@@ -380,25 +458,34 @@ const _ArgParser = class _ArgParser {
|
|
|
380
458
|
finalParser: identifiedFinalParser,
|
|
381
459
|
commandChain: identifiedCommandChain,
|
|
382
460
|
parserChain: identifiedParserChain
|
|
383
|
-
} = __privateMethod(this,
|
|
461
|
+
} = __privateMethod(this, _ArgParserBase_instances, _identifyCommandChainAndParsers_fn).call(this, processArgs, this, [], [this]);
|
|
462
|
+
if (__privateMethod(_a = identifiedFinalParser, _ArgParserBase_instances, _handleSaveToEnvFlag_fn).call(_a, processArgs, identifiedParserChain)) {
|
|
463
|
+
return {};
|
|
464
|
+
}
|
|
384
465
|
const { finalArgs, handlerToExecute } = this._parseRecursive(
|
|
385
466
|
processArgs,
|
|
386
467
|
this,
|
|
387
468
|
{},
|
|
388
469
|
[],
|
|
389
|
-
options
|
|
470
|
+
options,
|
|
471
|
+
void 0
|
|
390
472
|
);
|
|
391
473
|
if (identifiedCommandChain.length > 0) {
|
|
392
474
|
finalArgs.$commandChain = identifiedCommandChain;
|
|
393
475
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
476
|
+
if (__privateGet(this, _fuzzyMode)) {
|
|
477
|
+
finalArgs._originalInputArgs = originalProcessArgs;
|
|
478
|
+
}
|
|
479
|
+
if (!__privateGet(this, _fuzzyMode)) {
|
|
480
|
+
__privateMethod(this, _ArgParserBase_instances, _validateMandatoryFlags_fn).call(this, finalArgs, identifiedParserChain, identifiedCommandChain);
|
|
481
|
+
}
|
|
482
|
+
__privateMethod(this, _ArgParserBase_instances, _applyDefaultValues_fn).call(this, finalArgs, identifiedFinalParser);
|
|
483
|
+
__privateMethod(this, _ArgParserBase_instances, _prepareAndExecuteHandler_fn).call(this, handlerToExecute, finalArgs, (options == null ? void 0 : options.skipHandlers) ?? false);
|
|
397
484
|
return finalArgs;
|
|
398
485
|
} catch (error) {
|
|
399
486
|
if (error instanceof ArgParserError) {
|
|
400
487
|
if (__privateGet(this, _handleErrors)) {
|
|
401
|
-
__privateMethod(this,
|
|
488
|
+
__privateMethod(this, _ArgParserBase_instances, displayErrorAndExit_fn).call(this, error);
|
|
402
489
|
return {};
|
|
403
490
|
} else {
|
|
404
491
|
throw error;
|
|
@@ -412,7 +499,7 @@ const _ArgParser = class _ArgParser {
|
|
|
412
499
|
* Recursive helper for parsing arguments and handling sub-commands.
|
|
413
500
|
* This method assumes the global help check has already been performed in `parse`.
|
|
414
501
|
*/
|
|
415
|
-
_parseRecursive(argsToParse, currentParser, accumulatedParentArgs, commandChainSoFar, options) {
|
|
502
|
+
_parseRecursive(argsToParse, currentParser, accumulatedParentArgs, commandChainSoFar, options, parentParser) {
|
|
416
503
|
var _a, _b;
|
|
417
504
|
let subCommandIndex = -1;
|
|
418
505
|
let subCommandName = null;
|
|
@@ -425,8 +512,8 @@ const _ArgParser = class _ArgParser {
|
|
|
425
512
|
}
|
|
426
513
|
}
|
|
427
514
|
const argsForCurrentLevel = subCommandIndex === -1 ? argsToParse : argsToParse.slice(0, subCommandIndex);
|
|
428
|
-
const { parsedArgs: currentLevelArgs, firstUnconsumedIndex } = __privateMethod(_a = currentParser,
|
|
429
|
-
__privateMethod(_b = currentParser,
|
|
515
|
+
const { parsedArgs: currentLevelArgs, firstUnconsumedIndex } = __privateMethod(_a = currentParser, _ArgParserBase_instances, parseFlags_fn).call(_a, argsForCurrentLevel, options);
|
|
516
|
+
__privateMethod(_b = currentParser, _ArgParserBase_instances, _applyDefaultValues_fn).call(_b, currentLevelArgs, currentParser);
|
|
430
517
|
const combinedArgsFromThisAndParents = {
|
|
431
518
|
...accumulatedParentArgs,
|
|
432
519
|
...currentLevelArgs
|
|
@@ -451,7 +538,8 @@ const _ArgParser = class _ArgParser {
|
|
|
451
538
|
args: currentLevelArgs,
|
|
452
539
|
parentArgs: accumulatedParentArgs,
|
|
453
540
|
commandChain: commandChainSoFar,
|
|
454
|
-
parser: currentParser
|
|
541
|
+
parser: currentParser,
|
|
542
|
+
parentParser
|
|
455
543
|
}
|
|
456
544
|
};
|
|
457
545
|
}
|
|
@@ -465,7 +553,7 @@ const _ArgParser = class _ArgParser {
|
|
|
465
553
|
);
|
|
466
554
|
}
|
|
467
555
|
const subCommandConfig = __privateGet(currentParser, _subCommands).get(subCommandName);
|
|
468
|
-
if (!subCommandConfig || !(subCommandConfig.parser instanceof
|
|
556
|
+
if (!subCommandConfig || !(subCommandConfig.parser instanceof _ArgParserBase)) {
|
|
469
557
|
throw new ArgParserError(
|
|
470
558
|
`Internal error: Subcommand '${subCommandName}' is misconfigured or its parser is not a valid ArgParser instance.`,
|
|
471
559
|
commandChainSoFar
|
|
@@ -483,7 +571,8 @@ const _ArgParser = class _ArgParser {
|
|
|
483
571
|
nextParser,
|
|
484
572
|
combinedArgsForNextLevel,
|
|
485
573
|
nextCommandChain,
|
|
486
|
-
options
|
|
574
|
+
options,
|
|
575
|
+
currentParser
|
|
487
576
|
);
|
|
488
577
|
}
|
|
489
578
|
helpText() {
|
|
@@ -515,7 +604,7 @@ const _ArgParser = class _ArgParser {
|
|
|
515
604
|
`;
|
|
516
605
|
help += Array.from(__privateGet(this, _subCommands).entries()).sort(([nameA], [nameB]) => nameA.localeCompare(nameB)).map(([name, subCommandConfig]) => {
|
|
517
606
|
const actualSubParserInstance = subCommandConfig.parser;
|
|
518
|
-
if (!(actualSubParserInstance instanceof
|
|
607
|
+
if (!(actualSubParserInstance instanceof _ArgParserBase)) {
|
|
519
608
|
return `${indent()}${green(name.padEnd(20))} [Error: Subcommand '${name}' has an invalid parser configuration]`;
|
|
520
609
|
}
|
|
521
610
|
let subHelp = `${indent()}${green(name.padEnd(20))} ${white(__privateGet(actualSubParserInstance, _description) || "")}`;
|
|
@@ -558,7 +647,7 @@ ${cyan("Flags:")}
|
|
|
558
647
|
const localFlags = __privateGet(this, _flagManager).flags;
|
|
559
648
|
if (localFlags.length > 0) {
|
|
560
649
|
help += localFlags.sort((flagA, flagB) => flagA["name"].localeCompare(flagB["name"])).map((flag) => {
|
|
561
|
-
const optionsText = flag["options"].
|
|
650
|
+
const optionsText = flag["options"].slice().sort((a, b) => a.length - b.length).map((opt) => green(opt)).join(", ");
|
|
562
651
|
const isMandatory = typeof flag.mandatory === "function" ? "dynamic" : flag.mandatory;
|
|
563
652
|
const mandatoryIndicator = isMandatory === true ? ` ${red(__privateGet(this, _parameters).mandatoryCharacter)}` : isMandatory === "dynamic" ? ` ${dim("(conditionally mandatory)")}` : "";
|
|
564
653
|
const descriptionLines = Array.isArray(flag["description"]) ? flag["description"] : [flag["description"]];
|
|
@@ -638,7 +727,8 @@ _lastParseResult = new WeakMap();
|
|
|
638
727
|
_inheritParentFlags = new WeakMap();
|
|
639
728
|
_subCommands = new WeakMap();
|
|
640
729
|
_flagManager = new WeakMap();
|
|
641
|
-
|
|
730
|
+
_fuzzyMode = new WeakMap();
|
|
731
|
+
_ArgParserBase_instances = new WeakSet();
|
|
642
732
|
_identifyCommandChainAndParsers_fn = function(argsToParse, currentParser, commandChainSoFar, parserChainSoFar) {
|
|
643
733
|
let subCommandIndex = -1;
|
|
644
734
|
let subCommandName = null;
|
|
@@ -659,7 +749,7 @@ _identifyCommandChainAndParsers_fn = function(argsToParse, currentParser, comman
|
|
|
659
749
|
};
|
|
660
750
|
}
|
|
661
751
|
const subCommandConfig = __privateGet(currentParser, _subCommands).get(subCommandName);
|
|
662
|
-
if (!subCommandConfig || !(subCommandConfig.parser instanceof
|
|
752
|
+
if (!subCommandConfig || !(subCommandConfig.parser instanceof _ArgParserBase)) {
|
|
663
753
|
throw new Error(
|
|
664
754
|
`Internal error: Subcommand '${subCommandName}' configuration is invalid or parser is missing.`
|
|
665
755
|
);
|
|
@@ -668,33 +758,72 @@ _identifyCommandChainAndParsers_fn = function(argsToParse, currentParser, comman
|
|
|
668
758
|
const nextArgs = argsToParse.slice(subCommandIndex + 1);
|
|
669
759
|
const nextCommandChain = [...commandChainSoFar, subCommandName];
|
|
670
760
|
const nextParserChain = [...parserChainSoFar, nextParser];
|
|
671
|
-
return __privateMethod(this,
|
|
761
|
+
return __privateMethod(this, _ArgParserBase_instances, _identifyCommandChainAndParsers_fn).call(this, nextArgs, nextParser, nextCommandChain, nextParserChain);
|
|
672
762
|
};
|
|
673
763
|
_handleGlobalChecks_fn = function(processArgs, options) {
|
|
674
|
-
var _a, _b, _c, _d;
|
|
675
|
-
|
|
764
|
+
var _a, _b, _c, _d, _e, _f;
|
|
765
|
+
const isRootCliParser = !__privateGet(this, _parentParser) && !!__privateGet(this, _appCommandName);
|
|
766
|
+
if (processArgs.length === 0 && isRootCliParser && !__privateGet(this, _handler)) {
|
|
676
767
|
console.log(this.helpText());
|
|
677
768
|
if (typeof process === "object" && typeof process.exit === "function") {
|
|
678
769
|
process.exit(0);
|
|
679
770
|
}
|
|
680
771
|
return true;
|
|
681
772
|
}
|
|
682
|
-
if (processArgs.includes("--
|
|
773
|
+
if (processArgs.includes("--s-debug-print")) {
|
|
683
774
|
this.printAll("ArgParser.full.json");
|
|
684
775
|
if (typeof process === "object" && typeof process.exit === "function") {
|
|
685
776
|
process.exit(0);
|
|
686
777
|
}
|
|
687
778
|
return true;
|
|
688
779
|
}
|
|
689
|
-
|
|
690
|
-
|
|
780
|
+
if (processArgs.includes("--s-enable-fuzzy")) {
|
|
781
|
+
__privateMethod(this, _ArgParserBase_instances, _enableFuzzyMode_fn).call(this);
|
|
782
|
+
const fuzzyIndex = processArgs.indexOf("--s-enable-fuzzy");
|
|
783
|
+
processArgs.splice(fuzzyIndex, 1);
|
|
784
|
+
}
|
|
785
|
+
const withEnvIndex = processArgs.findIndex((arg) => arg === "--s-with-env");
|
|
786
|
+
if (withEnvIndex !== -1) {
|
|
787
|
+
if (withEnvIndex + 1 >= processArgs.length) {
|
|
788
|
+
console.error(chalk.red("Error: --s-with-env requires a file path argument"));
|
|
789
|
+
if (typeof process === "object" && typeof process.exit === "function") {
|
|
790
|
+
process.exit(1);
|
|
791
|
+
}
|
|
792
|
+
return true;
|
|
793
|
+
}
|
|
794
|
+
const filePath = processArgs[withEnvIndex + 1];
|
|
795
|
+
if (!filePath || filePath.startsWith("-")) {
|
|
796
|
+
console.error(chalk.red("Error: --s-with-env requires a file path argument"));
|
|
797
|
+
if (typeof process === "object" && typeof process.exit === "function") {
|
|
798
|
+
process.exit(1);
|
|
799
|
+
}
|
|
800
|
+
return true;
|
|
801
|
+
}
|
|
802
|
+
try {
|
|
803
|
+
const { finalParser: identifiedFinalParser2, parserChain: identifiedParserChain } = __privateMethod(this, _ArgParserBase_instances, _identifyCommandChainAndParsers_fn).call(this, processArgs, this, [], [this]);
|
|
804
|
+
const envConfigArgs = __privateMethod(_a = identifiedFinalParser2, _ArgParserBase_instances, _loadEnvFile_fn).call(_a, filePath, identifiedParserChain);
|
|
805
|
+
if (envConfigArgs) {
|
|
806
|
+
const mergedArgs = __privateMethod(_b = identifiedFinalParser2, _ArgParserBase_instances, _mergeEnvConfigWithArgs_fn).call(_b, envConfigArgs, processArgs);
|
|
807
|
+
processArgs.length = 0;
|
|
808
|
+
processArgs.push(...mergedArgs);
|
|
809
|
+
}
|
|
810
|
+
} catch (error) {
|
|
811
|
+
console.error(chalk.red(`Error loading environment file: ${error instanceof Error ? error.message : String(error)}`));
|
|
812
|
+
if (typeof process === "object" && typeof process.exit === "function") {
|
|
813
|
+
process.exit(1);
|
|
814
|
+
}
|
|
815
|
+
return true;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
const { finalParser: identifiedFinalParser } = __privateMethod(this, _ArgParserBase_instances, _identifyCommandChainAndParsers_fn).call(this, processArgs, this, [], [this]);
|
|
819
|
+
if (processArgs.includes("--s-debug")) {
|
|
691
820
|
console.log(
|
|
692
|
-
chalk.yellow.bold("\n--- ArgParser --
|
|
821
|
+
chalk.yellow.bold("\n--- ArgParser --s-debug Runtime Context ---")
|
|
693
822
|
);
|
|
694
823
|
const {
|
|
695
824
|
commandChain: identifiedCommandChain,
|
|
696
825
|
parserChain: _identifiedParserChain
|
|
697
|
-
} = __privateMethod(this,
|
|
826
|
+
} = __privateMethod(this, _ArgParserBase_instances, _identifyCommandChainAndParsers_fn).call(this, processArgs, this, [], [this]);
|
|
698
827
|
console.log(
|
|
699
828
|
`Identified Command Chain: ${chalk.cyan(identifiedCommandChain.join(" -> ") || "(root)")}`
|
|
700
829
|
);
|
|
@@ -711,7 +840,7 @@ _handleGlobalChecks_fn = function(processArgs, options) {
|
|
|
711
840
|
const rootArgsSlice = rootSubCommandIndex === -1 ? remainingArgs : remainingArgs.slice(0, rootSubCommandIndex);
|
|
712
841
|
parsingSteps.push({ level: "(root)", argsSlice: rootArgsSlice });
|
|
713
842
|
try {
|
|
714
|
-
const { parsedArgs: rootParsedArgs } = __privateMethod(
|
|
843
|
+
const { parsedArgs: rootParsedArgs } = __privateMethod(_c = currentParser, _ArgParserBase_instances, parseFlags_fn).call(_c, rootArgsSlice, { skipHelpHandling: true });
|
|
715
844
|
parsingSteps[0].parsed = rootParsedArgs;
|
|
716
845
|
accumulatedArgs = { ...accumulatedArgs, ...rootParsedArgs };
|
|
717
846
|
} catch (e) {
|
|
@@ -728,7 +857,7 @@ _handleGlobalChecks_fn = function(processArgs, options) {
|
|
|
728
857
|
});
|
|
729
858
|
break;
|
|
730
859
|
}
|
|
731
|
-
currentParser = (
|
|
860
|
+
currentParser = (_d = __privateGet(currentParser, _subCommands).get(subCommandName)) == null ? void 0 : _d.parser;
|
|
732
861
|
remainingArgs = remainingArgs.slice(1);
|
|
733
862
|
const nextSubCommandIndex = remainingArgs.findIndex(
|
|
734
863
|
(arg) => __privateGet(currentParser, _subCommands).has(arg)
|
|
@@ -740,7 +869,7 @@ _handleGlobalChecks_fn = function(processArgs, options) {
|
|
|
740
869
|
};
|
|
741
870
|
parsingSteps.push(stepInfo);
|
|
742
871
|
try {
|
|
743
|
-
const { parsedArgs: currentLevelParsedArgs } = __privateMethod(
|
|
872
|
+
const { parsedArgs: currentLevelParsedArgs } = __privateMethod(_e = currentParser, _ArgParserBase_instances, parseFlags_fn).call(_e, currentLevelArgsSlice, {
|
|
744
873
|
skipHelpHandling: true
|
|
745
874
|
});
|
|
746
875
|
stepInfo.parsed = currentLevelParsedArgs;
|
|
@@ -781,21 +910,21 @@ _handleGlobalChecks_fn = function(processArgs, options) {
|
|
|
781
910
|
)
|
|
782
911
|
);
|
|
783
912
|
identifiedFinalParser.printAll();
|
|
784
|
-
console.log(chalk.yellow.bold("--- End ArgParser --
|
|
913
|
+
console.log(chalk.yellow.bold("--- End ArgParser --s-debug ---"));
|
|
785
914
|
if (typeof process === "object" && typeof process.exit === "function") {
|
|
786
915
|
process.exit(0);
|
|
787
916
|
}
|
|
788
917
|
return true;
|
|
789
918
|
}
|
|
790
919
|
let parserNameForLog = "undefined_parser";
|
|
791
|
-
if (identifiedFinalParser instanceof
|
|
920
|
+
if (identifiedFinalParser instanceof _ArgParserBase) {
|
|
792
921
|
parserNameForLog = identifiedFinalParser["#subCommandName"] || identifiedFinalParser["#appName"];
|
|
793
922
|
} else if (identifiedFinalParser) {
|
|
794
923
|
parserNameForLog = identifiedFinalParser.name || identifiedFinalParser.appName || "unknown_type";
|
|
795
924
|
}
|
|
796
|
-
if (!(identifiedFinalParser instanceof
|
|
925
|
+
if (!(identifiedFinalParser instanceof _ArgParserBase)) {
|
|
797
926
|
console.error(
|
|
798
|
-
`[ArgParser #_handleGlobalChecks Critical Error] identifiedFinalParser is not an instance of ArgParser. Cannot process help. Name: ${parserNameForLog}, Constructor: ${identifiedFinalParser ? (
|
|
927
|
+
`[ArgParser #_handleGlobalChecks Critical Error] identifiedFinalParser is not an instance of ArgParser. Cannot process help. Name: ${parserNameForLog}, Constructor: ${identifiedFinalParser ? (_f = identifiedFinalParser.constructor) == null ? void 0 : _f.name : "undefined"}`
|
|
799
928
|
);
|
|
800
929
|
return false;
|
|
801
930
|
}
|
|
@@ -818,11 +947,27 @@ _handleGlobalChecks_fn = function(processArgs, options) {
|
|
|
818
947
|
_validateMandatoryFlags_fn = function(finalArgs, parserChain, commandChain) {
|
|
819
948
|
const finalMandatoryFlagsMissing = [];
|
|
820
949
|
const checkedFlagNames = /* @__PURE__ */ new Set();
|
|
821
|
-
|
|
950
|
+
let parsersToValidate = [...parserChain];
|
|
951
|
+
if (parserChain.length > 1) {
|
|
952
|
+
const immediateChild = parserChain[1];
|
|
953
|
+
if (!__privateGet(immediateChild, _inheritParentFlags)) {
|
|
954
|
+
parsersToValidate = parsersToValidate.slice(1);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
for (let i = 0; i < parsersToValidate.length; i++) {
|
|
958
|
+
const parser = parsersToValidate[i];
|
|
822
959
|
const currentCommandChain = parser.getCommandChain();
|
|
823
960
|
for (const flag of __privateGet(parser, _flagManager).flags) {
|
|
824
961
|
if (flag["name"] === "help" || checkedFlagNames.has(flag["name"]))
|
|
825
962
|
continue;
|
|
963
|
+
let flagIsInheritedByChild = false;
|
|
964
|
+
if (i < parsersToValidate.length - 1) {
|
|
965
|
+
const immediateChild = parsersToValidate[i + 1];
|
|
966
|
+
if (__privateGet(immediateChild, _inheritParentFlags) && __privateGet(immediateChild, _flagManager).hasFlag(flag["name"])) {
|
|
967
|
+
flagIsInheritedByChild = true;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
if (flagIsInheritedByChild) continue;
|
|
826
971
|
const isMandatory = typeof flag["mandatory"] === "function" ? flag["mandatory"](finalArgs) : flag["mandatory"];
|
|
827
972
|
if (!isMandatory) continue;
|
|
828
973
|
const value = finalArgs[flag["name"]];
|
|
@@ -871,6 +1016,16 @@ _prepareAndExecuteHandler_fn = function(handlerToExecute, finalArgs, skipHandler
|
|
|
871
1016
|
if (skipHandlers || !handlerToExecute) {
|
|
872
1017
|
return;
|
|
873
1018
|
}
|
|
1019
|
+
if (__privateGet(this, _fuzzyMode)) {
|
|
1020
|
+
const commandChain = handlerToExecute.context.commandChain || [];
|
|
1021
|
+
const args = handlerToExecute.context.args || {};
|
|
1022
|
+
const inputArgs = finalArgs._originalInputArgs || "unknown";
|
|
1023
|
+
const inputArgsStr = Array.isArray(inputArgs) ? inputArgs.join(" ") : inputArgs;
|
|
1024
|
+
console.log(`[--s-enable-fuzzy] handler() skipped for command chain: ${commandChain.join(" ") || "(root)"}`);
|
|
1025
|
+
console.log(` Input args: [${inputArgsStr}]`);
|
|
1026
|
+
console.log(` Parsed args: ${JSON.stringify(args)}`);
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
874
1029
|
const finalParserWhoseHandlerWillRun = handlerToExecute.context.parser;
|
|
875
1030
|
const finalParserFlags = __privateGet(finalParserWhoseHandlerWillRun, _flagManager).flags;
|
|
876
1031
|
const handlerArgs = handlerToExecute.context.args;
|
|
@@ -883,7 +1038,23 @@ _prepareAndExecuteHandler_fn = function(handlerToExecute, finalArgs, skipHandler
|
|
|
883
1038
|
}
|
|
884
1039
|
}
|
|
885
1040
|
handlerToExecute.context.args = handlerArgs;
|
|
886
|
-
|
|
1041
|
+
try {
|
|
1042
|
+
const handlerResult = handlerToExecute.handler(handlerToExecute.context);
|
|
1043
|
+
if (handlerResult && typeof handlerResult.then === "function") {
|
|
1044
|
+
finalArgs._asyncHandlerPromise = handlerResult;
|
|
1045
|
+
finalArgs._asyncHandlerInfo = handlerToExecute;
|
|
1046
|
+
handlerResult.catch(() => {
|
|
1047
|
+
});
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
finalArgs.handlerResponse = handlerResult;
|
|
1051
|
+
} catch (error) {
|
|
1052
|
+
if (__privateGet(this, _handleErrors)) {
|
|
1053
|
+
__privateMethod(this, _ArgParserBase_instances, displayErrorAndExit_fn).call(this, new ArgParserError(`Handler error: ${error}`, []));
|
|
1054
|
+
} else {
|
|
1055
|
+
throw error;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
887
1058
|
};
|
|
888
1059
|
parseFlags_fn = function(args, options) {
|
|
889
1060
|
var _a, _b;
|
|
@@ -951,6 +1122,19 @@ parseFlags_fn = function(args, options) {
|
|
|
951
1122
|
}
|
|
952
1123
|
return { parsedArgs: output, firstUnconsumedIndex };
|
|
953
1124
|
};
|
|
1125
|
+
/**
|
|
1126
|
+
* Enables fuzzy testing mode by disabling error handling and making flags optional
|
|
1127
|
+
*/
|
|
1128
|
+
_enableFuzzyMode_fn = function() {
|
|
1129
|
+
var _a;
|
|
1130
|
+
__privateSet(this, _fuzzyMode, true);
|
|
1131
|
+
__privateSet(this, _handleErrors, false);
|
|
1132
|
+
for (const [, subCommand] of __privateGet(this, _subCommands)) {
|
|
1133
|
+
if (subCommand.parser instanceof _ArgParserBase) {
|
|
1134
|
+
__privateMethod(_a = subCommand.parser, _ArgParserBase_instances, _enableFuzzyMode_fn).call(_a);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
};
|
|
954
1138
|
displayErrorAndExit_fn = function(error) {
|
|
955
1139
|
let commandNameToSuggest = "your-script";
|
|
956
1140
|
if (__privateGet(this, _appCommandName)) {
|
|
@@ -959,19 +1143,15 @@ displayErrorAndExit_fn = function(error) {
|
|
|
959
1143
|
commandNameToSuggest = __privateGet(this, _appName);
|
|
960
1144
|
} else if (typeof process !== "undefined" && process.argv && process.argv[1]) {
|
|
961
1145
|
try {
|
|
962
|
-
commandNameToSuggest =
|
|
1146
|
+
commandNameToSuggest = path__namespace.basename(process.argv[1]);
|
|
963
1147
|
} catch {
|
|
964
1148
|
}
|
|
965
1149
|
}
|
|
966
|
-
const commandPath = [
|
|
967
|
-
commandNameToSuggest,
|
|
968
|
-
...error.commandChain || []
|
|
969
|
-
].join(" ");
|
|
970
1150
|
console.error(`
|
|
971
1151
|
${chalk.red.bold("Error:")} ${error.message}`);
|
|
972
1152
|
console.error(
|
|
973
1153
|
`
|
|
974
|
-
${chalk.dim(`Try '${
|
|
1154
|
+
${chalk.dim(`Try '${commandNameToSuggest} --help' for usage details.`)}`
|
|
975
1155
|
);
|
|
976
1156
|
if (typeof process === "object" && typeof process.exit === "function") {
|
|
977
1157
|
process.exit(1);
|
|
@@ -1038,7 +1218,7 @@ _printRecursiveToConsole_fn = function(parser, level, visited = /* @__PURE__ */
|
|
|
1038
1218
|
if (subCommandParsers.length > 0) {
|
|
1039
1219
|
console.log(`${subIndent}Sub-Commands (${subCommandParsers.length}):`);
|
|
1040
1220
|
subCommandParsers.forEach((subCommand) => {
|
|
1041
|
-
__privateMethod(this,
|
|
1221
|
+
__privateMethod(this, _ArgParserBase_instances, _printRecursiveToConsole_fn).call(this, subCommand.parser, level + 1, visited);
|
|
1042
1222
|
});
|
|
1043
1223
|
} else {
|
|
1044
1224
|
console.log(`${subIndent}Sub-Commands: ${chalk.dim("none")}`);
|
|
@@ -1119,7 +1299,7 @@ _buildRecursiveString_fn = function(parser, level, visited = /* @__PURE__ */ new
|
|
|
1119
1299
|
if (subCommandParsers.length > 0) {
|
|
1120
1300
|
addLine(`${subIndent}Sub-Commands (${subCommandParsers.length}):`);
|
|
1121
1301
|
subCommandParsers.forEach((subCommand) => {
|
|
1122
|
-
output += __privateMethod(this,
|
|
1302
|
+
output += __privateMethod(this, _ArgParserBase_instances, _buildRecursiveString_fn).call(this, subCommand.parser, level + 1, visited);
|
|
1123
1303
|
});
|
|
1124
1304
|
} else {
|
|
1125
1305
|
addLine(`${subIndent}Sub-Commands: none`);
|
|
@@ -1181,12 +1361,1476 @@ _buildRecursiveJson_fn = function(parser, visited = /* @__PURE__ */ new Set()) {
|
|
|
1181
1361
|
const subCommands = Array.from(__privateGet(parser, _subCommands).values());
|
|
1182
1362
|
if (subCommands.length > 0) {
|
|
1183
1363
|
subCommands.forEach((sub) => {
|
|
1184
|
-
config.subCommands[sub.name] = __privateMethod(this,
|
|
1364
|
+
config.subCommands[sub.name] = __privateMethod(this, _ArgParserBase_instances, _buildRecursiveJson_fn).call(this, sub.parser, visited);
|
|
1185
1365
|
});
|
|
1186
1366
|
}
|
|
1187
1367
|
return config;
|
|
1188
1368
|
};
|
|
1369
|
+
/**
|
|
1370
|
+
* Generates a default environment file name based on the app name
|
|
1371
|
+
*/
|
|
1372
|
+
_generateDefaultEnvFileName_fn = function() {
|
|
1373
|
+
let baseName = "config";
|
|
1374
|
+
if (__privateGet(this, _appCommandName)) {
|
|
1375
|
+
baseName = __privateGet(this, _appCommandName);
|
|
1376
|
+
} else if (__privateGet(this, _appName) && __privateGet(this, _appName) !== "Argument Parser") {
|
|
1377
|
+
baseName = __privateGet(this, _appName);
|
|
1378
|
+
}
|
|
1379
|
+
baseName = baseName.split(/[\s-_]+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
|
|
1380
|
+
return `${baseName}.env`;
|
|
1381
|
+
};
|
|
1382
|
+
/**
|
|
1383
|
+
* Handles the --s-save-to-env system flag at the final parser level
|
|
1384
|
+
*/
|
|
1385
|
+
_handleSaveToEnvFlag_fn = function(processArgs, parserChain) {
|
|
1386
|
+
const saveToEnvIndex = processArgs.findIndex((arg) => arg === "--s-save-to-env");
|
|
1387
|
+
if (saveToEnvIndex !== -1) {
|
|
1388
|
+
let filePath;
|
|
1389
|
+
if (saveToEnvIndex + 1 < processArgs.length) {
|
|
1390
|
+
const nextArg = processArgs[saveToEnvIndex + 1];
|
|
1391
|
+
if (nextArg && !nextArg.startsWith("-")) {
|
|
1392
|
+
filePath = nextArg;
|
|
1393
|
+
} else {
|
|
1394
|
+
filePath = __privateMethod(this, _ArgParserBase_instances, _generateDefaultEnvFileName_fn).call(this);
|
|
1395
|
+
}
|
|
1396
|
+
} else {
|
|
1397
|
+
filePath = __privateMethod(this, _ArgParserBase_instances, _generateDefaultEnvFileName_fn).call(this);
|
|
1398
|
+
}
|
|
1399
|
+
try {
|
|
1400
|
+
__privateMethod(this, _ArgParserBase_instances, _saveToEnvFile_fn).call(this, filePath, processArgs, parserChain);
|
|
1401
|
+
console.log(chalk.green(`Environment configuration saved to: ${filePath}`));
|
|
1402
|
+
if (typeof process === "object" && typeof process.exit === "function") {
|
|
1403
|
+
process.exit(0);
|
|
1404
|
+
}
|
|
1405
|
+
return true;
|
|
1406
|
+
} catch (error) {
|
|
1407
|
+
console.error(chalk.red(`Error saving environment file: ${error instanceof Error ? error.message : String(error)}`));
|
|
1408
|
+
if (typeof process === "object" && typeof process.exit === "function") {
|
|
1409
|
+
process.exit(1);
|
|
1410
|
+
}
|
|
1411
|
+
return true;
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
return false;
|
|
1415
|
+
};
|
|
1416
|
+
/**
|
|
1417
|
+
* Saves the current parser's flags and their values to an environment file
|
|
1418
|
+
* in the specified format based on file extension.
|
|
1419
|
+
*/
|
|
1420
|
+
_saveToEnvFile_fn = function(filePath, processArgs, parserChain) {
|
|
1421
|
+
const ext = path__namespace.extname(filePath).toLowerCase();
|
|
1422
|
+
let format;
|
|
1423
|
+
if (ext === ".yaml" || ext === ".yml") {
|
|
1424
|
+
format = "yaml";
|
|
1425
|
+
} else if (ext === ".json" || ext === ".jsonc") {
|
|
1426
|
+
format = "json";
|
|
1427
|
+
} else if (ext === ".toml" || ext === ".tml") {
|
|
1428
|
+
format = "toml";
|
|
1429
|
+
} else {
|
|
1430
|
+
format = "env";
|
|
1431
|
+
}
|
|
1432
|
+
const allFlags = [];
|
|
1433
|
+
const seenFlagNames = /* @__PURE__ */ new Set();
|
|
1434
|
+
for (let i = parserChain.length - 1; i >= 0; i--) {
|
|
1435
|
+
const parser = parserChain[i];
|
|
1436
|
+
for (const flag of __privateGet(parser, _flagManager).flags) {
|
|
1437
|
+
if (!seenFlagNames.has(flag["name"])) {
|
|
1438
|
+
allFlags.push(flag);
|
|
1439
|
+
seenFlagNames.add(flag["name"]);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
const flags = allFlags;
|
|
1444
|
+
const { parsedArgs } = __privateMethod(this, _ArgParserBase_instances, parseFlags_fn).call(this, processArgs.filter(
|
|
1445
|
+
(arg) => arg !== "--s-save-to-env" && arg !== filePath
|
|
1446
|
+
));
|
|
1447
|
+
let content;
|
|
1448
|
+
switch (format) {
|
|
1449
|
+
case "env":
|
|
1450
|
+
content = __privateMethod(this, _ArgParserBase_instances, _generateEnvFormat_fn).call(this, flags, parsedArgs);
|
|
1451
|
+
break;
|
|
1452
|
+
case "yaml":
|
|
1453
|
+
content = __privateMethod(this, _ArgParserBase_instances, _generateYamlFormat_fn).call(this, flags, parsedArgs);
|
|
1454
|
+
break;
|
|
1455
|
+
case "json":
|
|
1456
|
+
content = __privateMethod(this, _ArgParserBase_instances, _generateJsonFormat_fn).call(this, flags, parsedArgs);
|
|
1457
|
+
break;
|
|
1458
|
+
case "toml":
|
|
1459
|
+
content = __privateMethod(this, _ArgParserBase_instances, _generateTomlFormat_fn).call(this, flags, parsedArgs);
|
|
1460
|
+
break;
|
|
1461
|
+
}
|
|
1462
|
+
const dir = path__namespace.dirname(filePath);
|
|
1463
|
+
if (!fs__namespace.existsSync(dir)) {
|
|
1464
|
+
fs__namespace.mkdirSync(dir, { recursive: true });
|
|
1465
|
+
}
|
|
1466
|
+
fs__namespace.writeFileSync(filePath, content, "utf8");
|
|
1467
|
+
};
|
|
1468
|
+
/**
|
|
1469
|
+
* Loads configuration from an environment file in various formats
|
|
1470
|
+
*/
|
|
1471
|
+
_loadEnvFile_fn = function(filePath, parserChain) {
|
|
1472
|
+
if (!fs__namespace.existsSync(filePath)) {
|
|
1473
|
+
throw new Error(`Configuration file not found: ${filePath}`);
|
|
1474
|
+
}
|
|
1475
|
+
const ext = path__namespace.extname(filePath).toLowerCase();
|
|
1476
|
+
let format;
|
|
1477
|
+
if (ext === ".yaml" || ext === ".yml") {
|
|
1478
|
+
format = "yaml";
|
|
1479
|
+
} else if (ext === ".json" || ext === ".jsonc") {
|
|
1480
|
+
format = "json";
|
|
1481
|
+
} else if (ext === ".toml" || ext === ".tml") {
|
|
1482
|
+
format = "toml";
|
|
1483
|
+
} else {
|
|
1484
|
+
format = "env";
|
|
1485
|
+
}
|
|
1486
|
+
const fileContent = fs__namespace.readFileSync(filePath, "utf8");
|
|
1487
|
+
let rawConfig;
|
|
1488
|
+
switch (format) {
|
|
1489
|
+
case "env":
|
|
1490
|
+
rawConfig = __privateMethod(this, _ArgParserBase_instances, _parseEnvFile_fn).call(this, fileContent);
|
|
1491
|
+
break;
|
|
1492
|
+
case "yaml":
|
|
1493
|
+
rawConfig = __privateMethod(this, _ArgParserBase_instances, _parseYamlFile_fn).call(this, fileContent);
|
|
1494
|
+
break;
|
|
1495
|
+
case "json":
|
|
1496
|
+
rawConfig = __privateMethod(this, _ArgParserBase_instances, _parseJsonFile_fn).call(this, fileContent);
|
|
1497
|
+
break;
|
|
1498
|
+
case "toml":
|
|
1499
|
+
rawConfig = __privateMethod(this, _ArgParserBase_instances, _parseTomlFile_fn).call(this, fileContent);
|
|
1500
|
+
break;
|
|
1501
|
+
}
|
|
1502
|
+
return __privateMethod(this, _ArgParserBase_instances, _convertConfigToFlagValues_fn).call(this, rawConfig, parserChain);
|
|
1503
|
+
};
|
|
1504
|
+
/**
|
|
1505
|
+
* Parses .env file content using dotenv
|
|
1506
|
+
*/
|
|
1507
|
+
_parseEnvFile_fn = function(content) {
|
|
1508
|
+
const parsed = dotenv__namespace.parse(content);
|
|
1509
|
+
const result = {};
|
|
1510
|
+
for (const [envKey, envValue] of Object.entries(parsed)) {
|
|
1511
|
+
const flagName = envKey.toLowerCase().replace(/_/g, "-");
|
|
1512
|
+
if (envValue === "true") {
|
|
1513
|
+
result[flagName] = true;
|
|
1514
|
+
} else if (envValue === "false") {
|
|
1515
|
+
result[flagName] = false;
|
|
1516
|
+
} else if (/^-?\d+$/.test(envValue)) {
|
|
1517
|
+
result[flagName] = parseInt(envValue, 10);
|
|
1518
|
+
} else if (/^-?\d*\.\d+$/.test(envValue)) {
|
|
1519
|
+
result[flagName] = parseFloat(envValue);
|
|
1520
|
+
} else if (envValue.includes(",")) {
|
|
1521
|
+
result[flagName] = envValue.split(",").map((v) => v.trim());
|
|
1522
|
+
} else {
|
|
1523
|
+
result[flagName] = envValue;
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
return result;
|
|
1527
|
+
};
|
|
1528
|
+
/**
|
|
1529
|
+
* Parses YAML file content
|
|
1530
|
+
*/
|
|
1531
|
+
_parseYamlFile_fn = function(content) {
|
|
1532
|
+
const parsed = yaml__namespace.load(content);
|
|
1533
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
1534
|
+
throw new Error("YAML file must contain an object at the root level");
|
|
1535
|
+
}
|
|
1536
|
+
const { _meta, ...config } = parsed;
|
|
1537
|
+
return config;
|
|
1538
|
+
};
|
|
1539
|
+
/**
|
|
1540
|
+
* Parses JSON file content
|
|
1541
|
+
*/
|
|
1542
|
+
_parseJsonFile_fn = function(content) {
|
|
1543
|
+
const parsed = JSON.parse(content);
|
|
1544
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
1545
|
+
throw new Error("JSON file must contain an object at the root level");
|
|
1546
|
+
}
|
|
1547
|
+
const { _meta, ...config } = parsed;
|
|
1548
|
+
return config;
|
|
1549
|
+
};
|
|
1550
|
+
/**
|
|
1551
|
+
* Parses TOML file content
|
|
1552
|
+
*/
|
|
1553
|
+
_parseTomlFile_fn = function(content) {
|
|
1554
|
+
const parsed = toml__namespace.parse(content);
|
|
1555
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
1556
|
+
throw new Error("TOML file must contain an object at the root level");
|
|
1557
|
+
}
|
|
1558
|
+
return parsed;
|
|
1559
|
+
};
|
|
1560
|
+
/**
|
|
1561
|
+
* Converts raw configuration values to match flag types and validates them
|
|
1562
|
+
*/
|
|
1563
|
+
_convertConfigToFlagValues_fn = function(rawConfig, parserChain) {
|
|
1564
|
+
const result = {};
|
|
1565
|
+
const allFlags = [];
|
|
1566
|
+
const seenFlagNames = /* @__PURE__ */ new Set();
|
|
1567
|
+
for (let i = parserChain.length - 1; i >= 0; i--) {
|
|
1568
|
+
const parser = parserChain[i];
|
|
1569
|
+
for (const flag of __privateGet(parser, _flagManager).flags) {
|
|
1570
|
+
if (!seenFlagNames.has(flag["name"])) {
|
|
1571
|
+
allFlags.push(flag);
|
|
1572
|
+
seenFlagNames.add(flag["name"]);
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
for (const [configKey, configValue] of Object.entries(rawConfig)) {
|
|
1577
|
+
const flag = allFlags.find((f) => f["name"] === configKey);
|
|
1578
|
+
if (!flag) {
|
|
1579
|
+
console.warn(chalk.yellow(`Warning: Configuration key '${configKey}' does not match any known flag. Ignoring.`));
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1582
|
+
try {
|
|
1583
|
+
const convertedValue = __privateMethod(this, _ArgParserBase_instances, _convertValueToFlagType_fn).call(this, configValue, flag);
|
|
1584
|
+
result[configKey] = convertedValue;
|
|
1585
|
+
} catch (error) {
|
|
1586
|
+
console.error(chalk.red(`Error converting configuration value for '${configKey}': ${error instanceof Error ? error.message : String(error)}`));
|
|
1587
|
+
if (typeof process === "object" && typeof process.exit === "function") {
|
|
1588
|
+
process.exit(1);
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
return result;
|
|
1593
|
+
};
|
|
1594
|
+
/**
|
|
1595
|
+
* Converts a configuration value to match the expected flag type
|
|
1596
|
+
*/
|
|
1597
|
+
_convertValueToFlagType_fn = function(value, flag) {
|
|
1598
|
+
const flagType = flag["type"];
|
|
1599
|
+
if (value === null || value === void 0) {
|
|
1600
|
+
return value;
|
|
1601
|
+
}
|
|
1602
|
+
if (flagType === Array || flag["allowMultiple"]) {
|
|
1603
|
+
if (Array.isArray(value)) return value;
|
|
1604
|
+
if (typeof value === "string") {
|
|
1605
|
+
return value.split(",").map((v) => v.trim());
|
|
1606
|
+
}
|
|
1607
|
+
return [value];
|
|
1608
|
+
}
|
|
1609
|
+
if (flagType === Boolean) {
|
|
1610
|
+
if (typeof value === "boolean") return value;
|
|
1611
|
+
if (typeof value === "string") {
|
|
1612
|
+
const lowerValue = value.toLowerCase();
|
|
1613
|
+
if (lowerValue === "true" || lowerValue === "1" || lowerValue === "yes") return true;
|
|
1614
|
+
if (lowerValue === "false" || lowerValue === "0" || lowerValue === "no") return false;
|
|
1615
|
+
}
|
|
1616
|
+
throw new Error(`Cannot convert '${value}' to boolean for flag '${flag["name"]}'`);
|
|
1617
|
+
}
|
|
1618
|
+
if (flagType === String) {
|
|
1619
|
+
return String(value);
|
|
1620
|
+
}
|
|
1621
|
+
if (flagType === Number) {
|
|
1622
|
+
const numValue = Number(value);
|
|
1623
|
+
if (isNaN(numValue)) {
|
|
1624
|
+
throw new Error(`Cannot convert '${value}' to number for flag '${flag["name"]}'`);
|
|
1625
|
+
}
|
|
1626
|
+
return numValue;
|
|
1627
|
+
}
|
|
1628
|
+
if (flag["enum"] && flag["enum"].length > 0) {
|
|
1629
|
+
if (!flag["enum"].includes(value)) {
|
|
1630
|
+
throw new Error(`Value '${value}' is not allowed for flag '${flag["name"]}'. Allowed values: ${flag["enum"].join(", ")}`);
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
return value;
|
|
1634
|
+
};
|
|
1635
|
+
/**
|
|
1636
|
+
* Merges environment configuration with command line arguments
|
|
1637
|
+
* CLI arguments take precedence over file configuration
|
|
1638
|
+
*/
|
|
1639
|
+
_mergeEnvConfigWithArgs_fn = function(envConfig, processArgs) {
|
|
1640
|
+
const result = [...processArgs];
|
|
1641
|
+
const withEnvIndex = result.findIndex((arg) => arg === "--s-with-env");
|
|
1642
|
+
if (withEnvIndex !== -1) {
|
|
1643
|
+
result.splice(withEnvIndex, 2);
|
|
1644
|
+
}
|
|
1645
|
+
const existingFlags = /* @__PURE__ */ new Set();
|
|
1646
|
+
for (let i = 0; i < result.length; i++) {
|
|
1647
|
+
const arg = result[i];
|
|
1648
|
+
if (arg.startsWith("-")) {
|
|
1649
|
+
existingFlags.add(arg);
|
|
1650
|
+
if (arg.includes("=")) {
|
|
1651
|
+
const flagPart = arg.split("=")[0];
|
|
1652
|
+
existingFlags.add(flagPart);
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
for (const [flagName, flagValue] of Object.entries(envConfig)) {
|
|
1657
|
+
const longFlag = `--${flagName}`;
|
|
1658
|
+
if (existingFlags.has(longFlag)) {
|
|
1659
|
+
continue;
|
|
1660
|
+
}
|
|
1661
|
+
if (typeof flagValue === "boolean") {
|
|
1662
|
+
if (flagValue) {
|
|
1663
|
+
result.push(longFlag);
|
|
1664
|
+
}
|
|
1665
|
+
} else if (Array.isArray(flagValue)) {
|
|
1666
|
+
for (const item of flagValue) {
|
|
1667
|
+
result.push(longFlag, String(item));
|
|
1668
|
+
}
|
|
1669
|
+
} else {
|
|
1670
|
+
result.push(longFlag, String(flagValue));
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
return result;
|
|
1674
|
+
};
|
|
1675
|
+
/**
|
|
1676
|
+
* Generates environment file content in Bash .env format
|
|
1677
|
+
*/
|
|
1678
|
+
_generateEnvFormat_fn = function(flags, parsedArgs) {
|
|
1679
|
+
const lines = [];
|
|
1680
|
+
lines.push("# Environment configuration generated by ArgParser");
|
|
1681
|
+
lines.push("# Format: Bash .env style");
|
|
1682
|
+
lines.push("");
|
|
1683
|
+
for (const flag of flags) {
|
|
1684
|
+
if (flag["name"] === "help") continue;
|
|
1685
|
+
const flagValue = parsedArgs[flag["name"]];
|
|
1686
|
+
const isSet = flagValue !== void 0 && flagValue !== null;
|
|
1687
|
+
const isMandatory = typeof flag["mandatory"] === "function" ? false : flag["mandatory"] ?? false;
|
|
1688
|
+
lines.push(`# ${flag["name"]}: ${Array.isArray(flag["description"]) ? flag["description"].join(" | ") : flag["description"]}`);
|
|
1689
|
+
lines.push(`# Options: ${flag["options"].join(", ")}`);
|
|
1690
|
+
lines.push(`# Type: ${__privateMethod(this, _ArgParserBase_instances, _getTypeString_fn).call(this, flag["type"])}`);
|
|
1691
|
+
if (flag["defaultValue"] !== void 0) {
|
|
1692
|
+
lines.push(`# Default: ${JSON.stringify(flag["defaultValue"])}`);
|
|
1693
|
+
}
|
|
1694
|
+
if (flag["enum"] && flag["enum"].length > 0) {
|
|
1695
|
+
lines.push(`# Allowed values: ${flag["enum"].join(", ")}`);
|
|
1696
|
+
}
|
|
1697
|
+
const envVarName = flag["name"].toUpperCase().replace(/[^A-Z0-9_]/g, "_");
|
|
1698
|
+
let envValue = "";
|
|
1699
|
+
if (isSet) {
|
|
1700
|
+
if (Array.isArray(flagValue)) {
|
|
1701
|
+
envValue = flagValue.join(",");
|
|
1702
|
+
} else if (typeof flagValue === "boolean") {
|
|
1703
|
+
envValue = flagValue ? "true" : "false";
|
|
1704
|
+
} else {
|
|
1705
|
+
envValue = String(flagValue);
|
|
1706
|
+
}
|
|
1707
|
+
lines.push(`${envVarName}="${envValue}"`);
|
|
1708
|
+
} else {
|
|
1709
|
+
const defaultVal = flag["defaultValue"] !== void 0 ? String(flag["defaultValue"]) : "";
|
|
1710
|
+
const prefix = isMandatory ? "" : "# ";
|
|
1711
|
+
lines.push(`${prefix}${envVarName}="${defaultVal}"`);
|
|
1712
|
+
}
|
|
1713
|
+
lines.push("");
|
|
1714
|
+
}
|
|
1715
|
+
return lines.join("\n");
|
|
1716
|
+
};
|
|
1717
|
+
/**
|
|
1718
|
+
* Generates environment file content in YAML format
|
|
1719
|
+
*/
|
|
1720
|
+
_generateYamlFormat_fn = function(flags, parsedArgs) {
|
|
1721
|
+
const config = {};
|
|
1722
|
+
const comments = [];
|
|
1723
|
+
comments.push("# Environment configuration generated by ArgParser");
|
|
1724
|
+
comments.push("# Format: YAML");
|
|
1725
|
+
comments.push("");
|
|
1726
|
+
for (const flag of flags) {
|
|
1727
|
+
if (flag["name"] === "help") continue;
|
|
1728
|
+
const flagValue = parsedArgs[flag["name"]];
|
|
1729
|
+
const isSet = flagValue !== void 0 && flagValue !== null;
|
|
1730
|
+
const isMandatory = typeof flag["mandatory"] === "function" ? false : flag["mandatory"] ?? false;
|
|
1731
|
+
comments.push(`# ${flag["name"]}: ${Array.isArray(flag["description"]) ? flag["description"].join(" | ") : flag["description"]}`);
|
|
1732
|
+
comments.push(`# Options: ${flag["options"].join(", ")}`);
|
|
1733
|
+
comments.push(`# Type: ${__privateMethod(this, _ArgParserBase_instances, _getTypeString_fn).call(this, flag["type"])}`);
|
|
1734
|
+
if (flag["defaultValue"] !== void 0) {
|
|
1735
|
+
comments.push(`# Default: ${JSON.stringify(flag["defaultValue"])}`);
|
|
1736
|
+
}
|
|
1737
|
+
if (flag["enum"] && flag["enum"].length > 0) {
|
|
1738
|
+
comments.push(`# Allowed values: ${flag["enum"].join(", ")}`);
|
|
1739
|
+
}
|
|
1740
|
+
if (isSet) {
|
|
1741
|
+
config[flag["name"]] = flagValue;
|
|
1742
|
+
} else if (isMandatory) {
|
|
1743
|
+
config[flag["name"]] = flag["defaultValue"] !== void 0 ? flag["defaultValue"] : null;
|
|
1744
|
+
}
|
|
1745
|
+
comments.push("");
|
|
1746
|
+
}
|
|
1747
|
+
const yamlContent = yaml__namespace.dump(config, {
|
|
1748
|
+
indent: 2,
|
|
1749
|
+
lineWidth: -1,
|
|
1750
|
+
noRefs: true,
|
|
1751
|
+
sortKeys: true
|
|
1752
|
+
});
|
|
1753
|
+
return comments.join("\n") + "\n" + yamlContent;
|
|
1754
|
+
};
|
|
1755
|
+
/**
|
|
1756
|
+
* Generates environment file content in JSON format
|
|
1757
|
+
*/
|
|
1758
|
+
_generateJsonFormat_fn = function(flags, parsedArgs) {
|
|
1759
|
+
const config = {};
|
|
1760
|
+
const metadata = {
|
|
1761
|
+
_meta: {
|
|
1762
|
+
generated_by: "ArgParser",
|
|
1763
|
+
format: "JSON",
|
|
1764
|
+
flags_info: {}
|
|
1765
|
+
}
|
|
1766
|
+
};
|
|
1767
|
+
for (const flag of flags) {
|
|
1768
|
+
if (flag["name"] === "help") continue;
|
|
1769
|
+
const flagValue = parsedArgs[flag["name"]];
|
|
1770
|
+
const isSet = flagValue !== void 0 && flagValue !== null;
|
|
1771
|
+
const isMandatory = typeof flag["mandatory"] === "function" ? false : flag["mandatory"] ?? false;
|
|
1772
|
+
metadata._meta.flags_info[flag["name"]] = {
|
|
1773
|
+
description: Array.isArray(flag["description"]) ? flag["description"].join(" | ") : flag["description"],
|
|
1774
|
+
options: flag["options"],
|
|
1775
|
+
type: __privateMethod(this, _ArgParserBase_instances, _getTypeString_fn).call(this, flag["type"]),
|
|
1776
|
+
mandatory: isMandatory,
|
|
1777
|
+
defaultValue: flag["defaultValue"],
|
|
1778
|
+
enum: flag["enum"] && flag["enum"].length > 0 ? flag["enum"] : void 0
|
|
1779
|
+
};
|
|
1780
|
+
if (isSet) {
|
|
1781
|
+
config[flag["name"]] = flagValue;
|
|
1782
|
+
} else if (isMandatory) {
|
|
1783
|
+
config[flag["name"]] = flag["defaultValue"] !== void 0 ? flag["defaultValue"] : null;
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
const result = { ...metadata, ...config };
|
|
1787
|
+
return JSON.stringify(result, null, 2);
|
|
1788
|
+
};
|
|
1789
|
+
/**
|
|
1790
|
+
* Generates environment file content in TOML format
|
|
1791
|
+
*/
|
|
1792
|
+
_generateTomlFormat_fn = function(flags, parsedArgs) {
|
|
1793
|
+
const config = {};
|
|
1794
|
+
const lines = [];
|
|
1795
|
+
lines.push("# Environment configuration generated by ArgParser");
|
|
1796
|
+
lines.push("# Format: TOML");
|
|
1797
|
+
lines.push("");
|
|
1798
|
+
for (const flag of flags) {
|
|
1799
|
+
if (flag["name"] === "help") continue;
|
|
1800
|
+
const flagValue = parsedArgs[flag["name"]];
|
|
1801
|
+
const isSet = flagValue !== void 0 && flagValue !== null;
|
|
1802
|
+
const isMandatory = typeof flag["mandatory"] === "function" ? false : flag["mandatory"] ?? false;
|
|
1803
|
+
lines.push(`# ${flag["name"]}: ${Array.isArray(flag["description"]) ? flag["description"].join(" | ") : flag["description"]}`);
|
|
1804
|
+
lines.push(`# Options: ${flag["options"].join(", ")}`);
|
|
1805
|
+
lines.push(`# Type: ${__privateMethod(this, _ArgParserBase_instances, _getTypeString_fn).call(this, flag["type"])}`);
|
|
1806
|
+
if (flag["defaultValue"] !== void 0) {
|
|
1807
|
+
lines.push(`# Default: ${JSON.stringify(flag["defaultValue"])}`);
|
|
1808
|
+
}
|
|
1809
|
+
if (flag["enum"] && flag["enum"].length > 0) {
|
|
1810
|
+
lines.push(`# Allowed values: ${flag["enum"].join(", ")}`);
|
|
1811
|
+
}
|
|
1812
|
+
if (isSet) {
|
|
1813
|
+
config[flag["name"]] = flagValue;
|
|
1814
|
+
} else if (isMandatory) {
|
|
1815
|
+
config[flag["name"]] = flag["defaultValue"] !== void 0 ? flag["defaultValue"] : null;
|
|
1816
|
+
}
|
|
1817
|
+
lines.push("");
|
|
1818
|
+
}
|
|
1819
|
+
const tomlContent = toml__namespace.stringify(config);
|
|
1820
|
+
return lines.join("\n") + "\n" + tomlContent;
|
|
1821
|
+
};
|
|
1822
|
+
/**
|
|
1823
|
+
* Helper method to get a string representation of a flag's type
|
|
1824
|
+
*/
|
|
1825
|
+
_getTypeString_fn = function(type) {
|
|
1826
|
+
var _a;
|
|
1827
|
+
if (typeof type === "function") {
|
|
1828
|
+
return type.name || "custom function";
|
|
1829
|
+
} else if (typeof type === "string") {
|
|
1830
|
+
return type;
|
|
1831
|
+
} else if (typeof type === "object" && type) {
|
|
1832
|
+
try {
|
|
1833
|
+
return ((_a = type.constructor) == null ? void 0 : _a.name) || "object";
|
|
1834
|
+
} catch {
|
|
1835
|
+
return "object";
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
return "unknown";
|
|
1839
|
+
};
|
|
1840
|
+
let ArgParserBase = _ArgParserBase;
|
|
1841
|
+
function mapArgParserFlagToZodSchema(flag) {
|
|
1842
|
+
let zodSchema;
|
|
1843
|
+
const flagTypeOpt = flag["type"];
|
|
1844
|
+
let typeName;
|
|
1845
|
+
if (typeof flagTypeOpt === "function") {
|
|
1846
|
+
typeName = flagTypeOpt.name.toLowerCase().replace("constructor", "");
|
|
1847
|
+
} else {
|
|
1848
|
+
typeName = String(flagTypeOpt).toLowerCase();
|
|
1849
|
+
}
|
|
1850
|
+
const flagEnum = flag["enum"];
|
|
1851
|
+
const allowMultiple = flag["allowMultiple"];
|
|
1852
|
+
if (allowMultiple) {
|
|
1853
|
+
let itemSchema;
|
|
1854
|
+
if (flagEnum && Array.isArray(flagEnum) && flagEnum.length > 0) {
|
|
1855
|
+
if (flagEnum.every((e) => typeof e === "string")) {
|
|
1856
|
+
itemSchema = zod.z.enum(flagEnum);
|
|
1857
|
+
} else if (flagEnum.every((e) => typeof e === "number")) {
|
|
1858
|
+
const literalSchemas = flagEnum.map((val) => zod.z.literal(val));
|
|
1859
|
+
if (literalSchemas.length === 1) {
|
|
1860
|
+
itemSchema = literalSchemas[0];
|
|
1861
|
+
} else {
|
|
1862
|
+
itemSchema = zod.z.union(
|
|
1863
|
+
literalSchemas
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
} else {
|
|
1867
|
+
itemSchema = zod.z.string();
|
|
1868
|
+
}
|
|
1869
|
+
} else {
|
|
1870
|
+
switch (typeName) {
|
|
1871
|
+
case "number":
|
|
1872
|
+
itemSchema = zod.z.number();
|
|
1873
|
+
break;
|
|
1874
|
+
case "boolean":
|
|
1875
|
+
itemSchema = zod.z.boolean();
|
|
1876
|
+
break;
|
|
1877
|
+
default:
|
|
1878
|
+
itemSchema = zod.z.string();
|
|
1879
|
+
break;
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
zodSchema = zod.z.array(itemSchema);
|
|
1883
|
+
} else {
|
|
1884
|
+
switch (typeName) {
|
|
1885
|
+
case "string":
|
|
1886
|
+
zodSchema = flagEnum && Array.isArray(flagEnum) && flagEnum.length > 0 && flagEnum.every((e) => typeof e === "string") ? zod.z.enum(flagEnum) : zod.z.string();
|
|
1887
|
+
break;
|
|
1888
|
+
case "number":
|
|
1889
|
+
if (flagEnum && Array.isArray(flagEnum) && flagEnum.length > 0 && flagEnum.every((e) => typeof e === "number")) {
|
|
1890
|
+
const literalSchemas = flagEnum.map((val) => zod.z.literal(val));
|
|
1891
|
+
if (literalSchemas.length === 1) {
|
|
1892
|
+
zodSchema = literalSchemas[0];
|
|
1893
|
+
} else if (literalSchemas.length >= 2) {
|
|
1894
|
+
zodSchema = zod.z.union(
|
|
1895
|
+
literalSchemas
|
|
1896
|
+
);
|
|
1897
|
+
} else {
|
|
1898
|
+
zodSchema = zod.z.number();
|
|
1899
|
+
}
|
|
1900
|
+
} else {
|
|
1901
|
+
zodSchema = zod.z.number();
|
|
1902
|
+
}
|
|
1903
|
+
break;
|
|
1904
|
+
case "boolean":
|
|
1905
|
+
zodSchema = zod.z.boolean();
|
|
1906
|
+
break;
|
|
1907
|
+
case "array":
|
|
1908
|
+
const itemSchema = flagEnum && Array.isArray(flagEnum) && flagEnum.length > 0 && flagEnum.every((e) => typeof e === "string") ? zod.z.enum(flagEnum) : zod.z.string();
|
|
1909
|
+
zodSchema = zod.z.array(itemSchema);
|
|
1910
|
+
break;
|
|
1911
|
+
case "object":
|
|
1912
|
+
zodSchema = zod.z.record(zod.z.string(), zod.z.any());
|
|
1913
|
+
break;
|
|
1914
|
+
default:
|
|
1915
|
+
console.warn(
|
|
1916
|
+
`[MCP Integration] Flag '${flag["name"]}' has an unknown type '${typeName}'. Defaulting to z.string().`
|
|
1917
|
+
);
|
|
1918
|
+
zodSchema = zod.z.string();
|
|
1919
|
+
break;
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
const description = flag["description"];
|
|
1923
|
+
if (description) {
|
|
1924
|
+
zodSchema = zodSchema.describe(
|
|
1925
|
+
Array.isArray(description) ? description.join("\n") : description
|
|
1926
|
+
);
|
|
1927
|
+
}
|
|
1928
|
+
const defaultValue = flag["defaultValue"];
|
|
1929
|
+
if (defaultValue !== void 0) {
|
|
1930
|
+
zodSchema = zodSchema.default(defaultValue);
|
|
1931
|
+
} else if (!flag["mandatory"]) {
|
|
1932
|
+
zodSchema = zodSchema.optional();
|
|
1933
|
+
}
|
|
1934
|
+
return zodSchema;
|
|
1935
|
+
}
|
|
1936
|
+
function generateMcpToolsFromArgParser(rootParser, options) {
|
|
1937
|
+
const tools = [];
|
|
1938
|
+
const visitedParsers = /* @__PURE__ */ new Set();
|
|
1939
|
+
function buildToolsRecursively(currentParser, commandPathParts) {
|
|
1940
|
+
if (visitedParsers.has(currentParser)) return;
|
|
1941
|
+
visitedParsers.add(currentParser);
|
|
1942
|
+
const typedRootParser = rootParser;
|
|
1943
|
+
const typedCurrentParser = currentParser;
|
|
1944
|
+
const appName = typedRootParser.getAppName ? typedRootParser.getAppName() : typedRootParser["#appName"];
|
|
1945
|
+
const currentParserDescription = typedCurrentParser.getDescription ? typedCurrentParser.getDescription() : typedCurrentParser["#description"];
|
|
1946
|
+
const currentParserHandler = typedCurrentParser.getHandler ? typedCurrentParser.getHandler() : typedCurrentParser["#handler"];
|
|
1947
|
+
const currentParserFlags = typedCurrentParser.flags;
|
|
1948
|
+
const subCommandsMap = typedCurrentParser.getSubCommands ? typedCurrentParser.getSubCommands() : typedCurrentParser["#subCommands"];
|
|
1949
|
+
const currentParserSubCommands = subCommandsMap ? Array.from(subCommandsMap.values()) : [];
|
|
1950
|
+
let currentParserCommandName = typedCurrentParser.getAppCommandName ? typedCurrentParser.getAppCommandName() : typedCurrentParser["#appCommandName"];
|
|
1951
|
+
if (!currentParserCommandName && currentParser !== rootParser) {
|
|
1952
|
+
currentParserCommandName = typedCurrentParser.getSubCommandName ? typedCurrentParser.getSubCommandName() : typedCurrentParser["#subCommandName"];
|
|
1953
|
+
}
|
|
1954
|
+
if (currentParser !== rootParser && commandPathParts.length > 0) {
|
|
1955
|
+
currentParserCommandName = commandPathParts[commandPathParts.length - 1];
|
|
1956
|
+
}
|
|
1957
|
+
const currentParserCommandNameOrAppName = currentParserCommandName || appName;
|
|
1958
|
+
const effectiveCommandName = currentParserCommandName || (commandPathParts.length > 0 ? commandPathParts[commandPathParts.length - 1] : appName);
|
|
1959
|
+
let toolName;
|
|
1960
|
+
if (options == null ? void 0 : options.generateToolName) {
|
|
1961
|
+
toolName = options.generateToolName(commandPathParts, appName);
|
|
1962
|
+
} else {
|
|
1963
|
+
if (currentParser === rootParser) {
|
|
1964
|
+
toolName = currentParserCommandNameOrAppName || appName || "root_cmd";
|
|
1965
|
+
} else {
|
|
1966
|
+
toolName = effectiveCommandName || "cmd";
|
|
1967
|
+
}
|
|
1968
|
+
toolName = toolName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1969
|
+
}
|
|
1970
|
+
if (!toolName)
|
|
1971
|
+
toolName = currentParser === rootParser && appName ? appName : "cmd";
|
|
1972
|
+
if (options == null ? void 0 : options.toolNamePrefix) {
|
|
1973
|
+
toolName = options.toolNamePrefix + toolName;
|
|
1974
|
+
}
|
|
1975
|
+
if (options == null ? void 0 : options.toolNameSuffix) {
|
|
1976
|
+
toolName = toolName + options.toolNameSuffix;
|
|
1977
|
+
}
|
|
1978
|
+
if (currentParserHandler) {
|
|
1979
|
+
const flags = currentParserFlags;
|
|
1980
|
+
const zodProperties = {};
|
|
1981
|
+
const hasHelpFlag = flags.some((flag) => flag["name"] === "help");
|
|
1982
|
+
for (const flag of flags) {
|
|
1983
|
+
let flagSchema = mapArgParserFlagToZodSchema(flag);
|
|
1984
|
+
if (hasHelpFlag && flag["name"] !== "help" && flag["mandatory"]) {
|
|
1985
|
+
flagSchema = flagSchema.optional();
|
|
1986
|
+
}
|
|
1987
|
+
zodProperties[flag["name"]] = flagSchema;
|
|
1988
|
+
}
|
|
1989
|
+
const inputSchema = zod.z.object(zodProperties);
|
|
1990
|
+
let outputSchema;
|
|
1991
|
+
if ((options == null ? void 0 : options.outputSchemaMap) && options.outputSchemaMap[toolName]) {
|
|
1992
|
+
const customSchema = options.outputSchemaMap[toolName];
|
|
1993
|
+
outputSchema = typeof customSchema === "object" && !customSchema._def ? zod.z.object(customSchema) : customSchema;
|
|
1994
|
+
} else if (options == null ? void 0 : options.defaultOutputSchema) {
|
|
1995
|
+
outputSchema = options.defaultOutputSchema;
|
|
1996
|
+
}
|
|
1997
|
+
const tool = {
|
|
1998
|
+
name: toolName,
|
|
1999
|
+
description: currentParserDescription || `Executes the ${toolName} command.`,
|
|
2000
|
+
inputSchema,
|
|
2001
|
+
outputSchema,
|
|
2002
|
+
async execute(mcpInputArgs) {
|
|
2003
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2004
|
+
if (mcpInputArgs["help"] === true) {
|
|
2005
|
+
let helpParser = rootParser;
|
|
2006
|
+
const pathParts = [...commandPathParts];
|
|
2007
|
+
for (const part of pathParts) {
|
|
2008
|
+
const subCmd = helpParser.getSubCommand ? helpParser.getSubCommand(part) : void 0;
|
|
2009
|
+
if (subCmd && subCmd.parser) {
|
|
2010
|
+
helpParser = subCmd.parser;
|
|
2011
|
+
} else {
|
|
2012
|
+
break;
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
const helpText = helpParser.helpText ? helpParser.helpText() : "Help not available";
|
|
2016
|
+
if ((_a = options == null ? void 0 : options.outputSchemaMap) == null ? void 0 : _a[toolName]) {
|
|
2017
|
+
return {
|
|
2018
|
+
success: true,
|
|
2019
|
+
help: helpText,
|
|
2020
|
+
files: [],
|
|
2021
|
+
commandExecuted: null,
|
|
2022
|
+
stderrOutput: null
|
|
2023
|
+
};
|
|
2024
|
+
}
|
|
2025
|
+
return { success: true, message: helpText };
|
|
2026
|
+
}
|
|
2027
|
+
const argv = [...commandPathParts];
|
|
2028
|
+
const parserFlags = currentParserFlags;
|
|
2029
|
+
for (const flagDef of parserFlags) {
|
|
2030
|
+
const flagName = flagDef["name"];
|
|
2031
|
+
if (mcpInputArgs.hasOwnProperty(flagName)) {
|
|
2032
|
+
const value = mcpInputArgs[flagName];
|
|
2033
|
+
const flagType = flagDef["type"];
|
|
2034
|
+
const flagOptions = flagDef["options"];
|
|
2035
|
+
const isFlagOnly = flagDef["flagOnly"];
|
|
2036
|
+
const allowMultiple = flagDef["allowMultiple"];
|
|
2037
|
+
let flagTypeName = typeof flagType === "function" ? flagType.name.toLowerCase().replace("constructor", "") : String(flagType).toLowerCase();
|
|
2038
|
+
argv.push(flagOptions[0]);
|
|
2039
|
+
if (flagTypeName === "boolean") {
|
|
2040
|
+
if (value === true && isFlagOnly === false)
|
|
2041
|
+
argv.push(String(value));
|
|
2042
|
+
else if (value === false && isFlagOnly === false)
|
|
2043
|
+
argv.push(String(value));
|
|
2044
|
+
} else if (flagTypeName === "array") {
|
|
2045
|
+
if (Array.isArray(value)) {
|
|
2046
|
+
if (allowMultiple) {
|
|
2047
|
+
const originalArgvLength = argv.length;
|
|
2048
|
+
value.forEach((item) => {
|
|
2049
|
+
argv.push(flagOptions[0]);
|
|
2050
|
+
argv.push(String(item));
|
|
2051
|
+
});
|
|
2052
|
+
if (value.length > 0 && argv[originalArgvLength - 1] === flagOptions[0]) {
|
|
2053
|
+
argv.splice(originalArgvLength - 1, 1);
|
|
2054
|
+
}
|
|
2055
|
+
} else {
|
|
2056
|
+
argv.push(value.join(","));
|
|
2057
|
+
}
|
|
2058
|
+
} else if (value != null) argv.push(String(value));
|
|
2059
|
+
} else if (value !== null && value !== void 0)
|
|
2060
|
+
argv.push(String(value));
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
try {
|
|
2064
|
+
const parseResult = await rootParser.parse(
|
|
2065
|
+
argv
|
|
2066
|
+
);
|
|
2067
|
+
if (parseResult["$error"]) {
|
|
2068
|
+
const errorDetails = parseResult["$error"];
|
|
2069
|
+
const errPayload = {
|
|
2070
|
+
message: `Cmd error: ${errorDetails.type} - ${errorDetails.message}`,
|
|
2071
|
+
details: errorDetails.details
|
|
2072
|
+
};
|
|
2073
|
+
if ((_b = options == null ? void 0 : options.outputSchemaMap) == null ? void 0 : _b[toolName]) {
|
|
2074
|
+
return {
|
|
2075
|
+
error: errPayload.message,
|
|
2076
|
+
files: [],
|
|
2077
|
+
commandExecuted: null,
|
|
2078
|
+
stderrOutput: ((_c = errPayload.details) == null ? void 0 : _c.stderr) || null
|
|
2079
|
+
};
|
|
2080
|
+
}
|
|
2081
|
+
return {
|
|
2082
|
+
success: false,
|
|
2083
|
+
message: errPayload.message,
|
|
2084
|
+
data: errPayload.details
|
|
2085
|
+
};
|
|
2086
|
+
}
|
|
2087
|
+
let handlerResponse = parseResult["handlerResponse"];
|
|
2088
|
+
if (handlerResponse === void 0 && parseResult["$commandChain"]) {
|
|
2089
|
+
let finalParser = rootParser;
|
|
2090
|
+
let currentArgs = { ...parseResult };
|
|
2091
|
+
let resolvedParentArgs = void 0;
|
|
2092
|
+
const chain = parseResult["$commandChain"];
|
|
2093
|
+
for (let i = 0; i < chain.length; i++) {
|
|
2094
|
+
const cmdName = chain[i];
|
|
2095
|
+
const subCmdInfo = (finalParser == null ? void 0 : finalParser.getSubCommand) ? finalParser.getSubCommand(cmdName) : void 0;
|
|
2096
|
+
if (subCmdInfo && subCmdInfo.parser) {
|
|
2097
|
+
resolvedParentArgs = { ...currentArgs };
|
|
2098
|
+
currentArgs = currentArgs[cmdName] || {};
|
|
2099
|
+
finalParser = subCmdInfo.parser;
|
|
2100
|
+
} else if (i === 0 && finalParser && cmdName === (finalParser.getAppCommandName ? finalParser.getAppCommandName() : finalParser["#appCommandName"] || (finalParser.getAppName ? finalParser.getAppName() : finalParser["#appName"]))) {
|
|
2101
|
+
currentArgs = { ...parseResult };
|
|
2102
|
+
break;
|
|
2103
|
+
} else {
|
|
2104
|
+
finalParser = void 0;
|
|
2105
|
+
break;
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
const finalParserTyped = finalParser;
|
|
2109
|
+
const finalHandler = finalParserTyped.getHandler ? finalParserTyped.getHandler() : finalParserTyped["#handler"];
|
|
2110
|
+
if (finalParser && finalHandler) {
|
|
2111
|
+
const handlerToCall = finalHandler;
|
|
2112
|
+
const handlerContext = {
|
|
2113
|
+
args: currentArgs,
|
|
2114
|
+
commandChain: chain,
|
|
2115
|
+
parser: finalParser,
|
|
2116
|
+
parentArgs: resolvedParentArgs
|
|
2117
|
+
};
|
|
2118
|
+
try {
|
|
2119
|
+
handlerResponse = await handlerToCall(handlerContext);
|
|
2120
|
+
} catch (handlerError) {
|
|
2121
|
+
const errorMsg = `Handler error: ${handlerError.message || String(handlerError)}`;
|
|
2122
|
+
if ((_d = options == null ? void 0 : options.outputSchemaMap) == null ? void 0 : _d[toolName]) {
|
|
2123
|
+
return {
|
|
2124
|
+
error: errorMsg,
|
|
2125
|
+
files: [],
|
|
2126
|
+
commandExecuted: null,
|
|
2127
|
+
stderrOutput: null
|
|
2128
|
+
};
|
|
2129
|
+
}
|
|
2130
|
+
return { success: false, message: errorMsg };
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
if ((_e = options == null ? void 0 : options.outputSchemaMap) == null ? void 0 : _e[toolName]) {
|
|
2135
|
+
return handlerResponse;
|
|
2136
|
+
}
|
|
2137
|
+
return { success: true, data: handlerResponse };
|
|
2138
|
+
} catch (e) {
|
|
2139
|
+
let errorMsg;
|
|
2140
|
+
let errorDetails = e;
|
|
2141
|
+
if (e instanceof Error && e.message) {
|
|
2142
|
+
errorMsg = `Cmd error: handler_error - ${e.message}`;
|
|
2143
|
+
errorDetails = { details: e };
|
|
2144
|
+
} else {
|
|
2145
|
+
errorMsg = `MCP tool exec failed: ${e.message || String(e)}`;
|
|
2146
|
+
}
|
|
2147
|
+
if ((_f = options == null ? void 0 : options.outputSchemaMap) == null ? void 0 : _f[toolName]) {
|
|
2148
|
+
return {
|
|
2149
|
+
error: errorMsg,
|
|
2150
|
+
files: [],
|
|
2151
|
+
commandExecuted: null,
|
|
2152
|
+
stderrOutput: (errorDetails == null ? void 0 : errorDetails.stderr) || null
|
|
2153
|
+
};
|
|
2154
|
+
}
|
|
2155
|
+
return {
|
|
2156
|
+
success: false,
|
|
2157
|
+
message: errorMsg,
|
|
2158
|
+
data: errorDetails
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
};
|
|
2163
|
+
tools.push(tool);
|
|
2164
|
+
}
|
|
2165
|
+
const subCommands = currentParserSubCommands;
|
|
2166
|
+
if (subCommands && (options == null ? void 0 : options.includeSubCommands) !== false) {
|
|
2167
|
+
for (const subCmdObj of subCommands) {
|
|
2168
|
+
if (subCmdObj.isMcp === true) {
|
|
2169
|
+
continue;
|
|
2170
|
+
}
|
|
2171
|
+
const nextPathParts = [...commandPathParts, subCmdObj.name];
|
|
2172
|
+
buildToolsRecursively(
|
|
2173
|
+
subCmdObj.parser,
|
|
2174
|
+
nextPathParts.filter((p) => p)
|
|
2175
|
+
);
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
buildToolsRecursively(rootParser, []);
|
|
2180
|
+
return tools;
|
|
2181
|
+
}
|
|
2182
|
+
const _ArgParser = class _ArgParser extends ArgParserBase {
|
|
2183
|
+
constructor() {
|
|
2184
|
+
super(...arguments);
|
|
2185
|
+
__privateAdd(this, _ArgParser_instances);
|
|
2186
|
+
}
|
|
2187
|
+
/**
|
|
2188
|
+
* Generate MCP tools from this ArgParser instance
|
|
2189
|
+
* @param options Optional configuration for MCP tool generation
|
|
2190
|
+
* @returns Array of MCP tool structures ready for server registration
|
|
2191
|
+
*/
|
|
2192
|
+
toMcpTools(options) {
|
|
2193
|
+
return generateMcpToolsFromArgParser(this, options);
|
|
2194
|
+
}
|
|
2195
|
+
/**
|
|
2196
|
+
* Create an MCP server with tools generated from this ArgParser
|
|
2197
|
+
* @param serverInfo Server configuration
|
|
2198
|
+
* @param toolOptions Optional MCP tool generation options
|
|
2199
|
+
* @returns Configured MCP server instance
|
|
2200
|
+
*/
|
|
2201
|
+
createMcpServer(serverInfo, toolOptions) {
|
|
2202
|
+
const { McpServer } = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
2203
|
+
const server = new McpServer({
|
|
2204
|
+
id: serverInfo.name,
|
|
2205
|
+
version: serverInfo.version,
|
|
2206
|
+
name: serverInfo.name,
|
|
2207
|
+
description: serverInfo.description
|
|
2208
|
+
});
|
|
2209
|
+
const tools = this.toMcpTools(toolOptions);
|
|
2210
|
+
const uniqueTools = tools.reduce((acc, tool) => {
|
|
2211
|
+
if (!acc.find((t) => t.name === tool.name)) {
|
|
2212
|
+
acc.push(tool);
|
|
2213
|
+
}
|
|
2214
|
+
return acc;
|
|
2215
|
+
}, []);
|
|
2216
|
+
uniqueTools.forEach((tool) => {
|
|
2217
|
+
const toolConfig = {
|
|
2218
|
+
description: tool.description || "No description provided.",
|
|
2219
|
+
inputSchema: tool.inputSchema.shape || tool.inputSchema
|
|
2220
|
+
};
|
|
2221
|
+
if (tool.outputSchema) {
|
|
2222
|
+
toolConfig.outputSchema = tool.outputSchema.shape || tool.outputSchema;
|
|
2223
|
+
}
|
|
2224
|
+
server.registerTool(tool.name, toolConfig, tool.execute);
|
|
2225
|
+
});
|
|
2226
|
+
return server;
|
|
2227
|
+
}
|
|
2228
|
+
/**
|
|
2229
|
+
* Start an MCP server using stdio transport
|
|
2230
|
+
* @param serverInfo Server configuration
|
|
2231
|
+
* @param toolOptions Optional MCP tool generation options
|
|
2232
|
+
* @returns Promise that resolves when server is connected
|
|
2233
|
+
*/
|
|
2234
|
+
async startMcpServer(serverInfo, toolOptions) {
|
|
2235
|
+
return this.startMcpServerWithTransport(serverInfo, "stdio", {}, toolOptions);
|
|
2236
|
+
}
|
|
2237
|
+
/**
|
|
2238
|
+
* Start an MCP server with multiple transport types simultaneously
|
|
2239
|
+
* @param serverInfo Server configuration
|
|
2240
|
+
* @param transports Array of transport configurations
|
|
2241
|
+
* @param toolOptions Optional MCP tool generation options
|
|
2242
|
+
* @returns Promise that resolves when all servers are started
|
|
2243
|
+
*/
|
|
2244
|
+
async startMcpServerWithMultipleTransports(serverInfo, transports, toolOptions) {
|
|
2245
|
+
const server = this.createMcpServer(serverInfo, toolOptions);
|
|
2246
|
+
const startPromises = [];
|
|
2247
|
+
for (const transportConfig of transports) {
|
|
2248
|
+
const promise = __privateMethod(this, _ArgParser_instances, _startSingleTransport_fn).call(this, server, serverInfo, transportConfig);
|
|
2249
|
+
startPromises.push(promise);
|
|
2250
|
+
}
|
|
2251
|
+
await Promise.all(startPromises);
|
|
2252
|
+
console.error(`[${serverInfo.name}] All MCP transports started successfully`);
|
|
2253
|
+
}
|
|
2254
|
+
/**
|
|
2255
|
+
* Start an MCP server with a specific transport type
|
|
2256
|
+
* @param serverInfo Server configuration
|
|
2257
|
+
* @param transportType Type of transport to use
|
|
2258
|
+
* @param transportOptions Transport-specific options
|
|
2259
|
+
* @param toolOptions Optional MCP tool generation options
|
|
2260
|
+
* @returns Promise that resolves when server is connected
|
|
2261
|
+
*/
|
|
2262
|
+
async startMcpServerWithTransport(serverInfo, transportType, transportOptions = {}, toolOptions) {
|
|
2263
|
+
const server = this.createMcpServer(serverInfo, toolOptions);
|
|
2264
|
+
await __privateMethod(this, _ArgParser_instances, _startSingleTransport_fn).call(this, server, serverInfo, {
|
|
2265
|
+
type: transportType,
|
|
2266
|
+
...transportOptions
|
|
2267
|
+
});
|
|
2268
|
+
}
|
|
2269
|
+
/**
|
|
2270
|
+
* Override parse() to handle async handlers properly
|
|
2271
|
+
* This allows ArgParser to work with async handlers while keeping
|
|
2272
|
+
* backwards compatibility for synchronous usage
|
|
2273
|
+
*/
|
|
2274
|
+
parse(processArgs, options) {
|
|
2275
|
+
const result = super.parse(processArgs, options);
|
|
2276
|
+
const anyResult = result;
|
|
2277
|
+
if (anyResult._fuzzyModePreventedExecution) {
|
|
2278
|
+
return result;
|
|
2279
|
+
}
|
|
2280
|
+
if (anyResult._asyncHandlerPromise) {
|
|
2281
|
+
return this.parseAsync(processArgs, options);
|
|
2282
|
+
}
|
|
2283
|
+
return result;
|
|
2284
|
+
}
|
|
2285
|
+
/**
|
|
2286
|
+
* Async version of parse for when async handlers are detected
|
|
2287
|
+
*/
|
|
2288
|
+
async parseAsync(processArgs, options) {
|
|
2289
|
+
const result = super.parse(processArgs, options);
|
|
2290
|
+
const anyResult = result;
|
|
2291
|
+
if (anyResult._fuzzyModePreventedExecution) {
|
|
2292
|
+
return result;
|
|
2293
|
+
}
|
|
2294
|
+
if (anyResult._asyncHandlerPromise) {
|
|
2295
|
+
try {
|
|
2296
|
+
const handlerResult = await anyResult._asyncHandlerPromise;
|
|
2297
|
+
anyResult.handlerResponse = handlerResult;
|
|
2298
|
+
} catch (error) {
|
|
2299
|
+
if (this["#handleErrors"]) {
|
|
2300
|
+
anyResult.$error = {
|
|
2301
|
+
type: "handler_error",
|
|
2302
|
+
message: error instanceof Error ? error.message : String(error),
|
|
2303
|
+
details: error
|
|
2304
|
+
};
|
|
2305
|
+
} else {
|
|
2306
|
+
throw error;
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
delete anyResult._asyncHandlerPromise;
|
|
2310
|
+
delete anyResult._asyncHandlerInfo;
|
|
2311
|
+
}
|
|
2312
|
+
return result;
|
|
2313
|
+
}
|
|
2314
|
+
addMcpSubCommand(subCommandName = "mcp-server", serverInfo, optionsOrToolOptions) {
|
|
2315
|
+
let options;
|
|
2316
|
+
if (optionsOrToolOptions && typeof optionsOrToolOptions === "object" && ("includeSubCommands" in optionsOrToolOptions || "toolNamePrefix" in optionsOrToolOptions || "toolNameSuffix" in optionsOrToolOptions)) {
|
|
2317
|
+
options = { toolOptions: optionsOrToolOptions };
|
|
2318
|
+
} else {
|
|
2319
|
+
options = optionsOrToolOptions || {};
|
|
2320
|
+
}
|
|
2321
|
+
const { defaultTransports, defaultTransport, toolOptions } = options;
|
|
2322
|
+
const mcpHandler = async (ctx) => {
|
|
2323
|
+
if (!ctx.parentParser) {
|
|
2324
|
+
console.error(
|
|
2325
|
+
"[MCP Server] Critical: MCP server handler called without a parent parser context."
|
|
2326
|
+
);
|
|
2327
|
+
process.exit(1);
|
|
2328
|
+
}
|
|
2329
|
+
console.error(`[${serverInfo.name}] Starting MCP Server...`);
|
|
2330
|
+
const mcpParser = ctx.parentParser;
|
|
2331
|
+
const transports = ctx.args["transports"];
|
|
2332
|
+
if (transports) {
|
|
2333
|
+
try {
|
|
2334
|
+
const transportConfigs = JSON.parse(transports);
|
|
2335
|
+
await mcpParser.startMcpServerWithMultipleTransports(serverInfo, transportConfigs, toolOptions);
|
|
2336
|
+
} catch (error) {
|
|
2337
|
+
console.error("❌ Error parsing transports configuration:", error.message);
|
|
2338
|
+
console.error(`Expected JSON format: '[{"type":"stdio"},{"type":"sse","port":3001}]'`);
|
|
2339
|
+
process.exit(1);
|
|
2340
|
+
}
|
|
2341
|
+
} else if (defaultTransports && defaultTransports.length > 0) {
|
|
2342
|
+
await mcpParser.startMcpServerWithMultipleTransports(serverInfo, defaultTransports, toolOptions);
|
|
2343
|
+
} else if (defaultTransport) {
|
|
2344
|
+
await mcpParser.startMcpServerWithTransport(
|
|
2345
|
+
serverInfo,
|
|
2346
|
+
defaultTransport.type,
|
|
2347
|
+
{
|
|
2348
|
+
port: defaultTransport.port,
|
|
2349
|
+
host: defaultTransport.host,
|
|
2350
|
+
path: defaultTransport.path,
|
|
2351
|
+
sessionIdGenerator: defaultTransport.sessionIdGenerator
|
|
2352
|
+
},
|
|
2353
|
+
toolOptions
|
|
2354
|
+
);
|
|
2355
|
+
} else {
|
|
2356
|
+
const transportType = ctx.args["transport"] || "stdio";
|
|
2357
|
+
const transportOptions = {
|
|
2358
|
+
port: ctx.args["port"],
|
|
2359
|
+
host: ctx.args["host"],
|
|
2360
|
+
path: ctx.args["path"]
|
|
2361
|
+
};
|
|
2362
|
+
await mcpParser.startMcpServerWithTransport(serverInfo, transportType, transportOptions, toolOptions);
|
|
2363
|
+
}
|
|
2364
|
+
return new Promise(() => {
|
|
2365
|
+
});
|
|
2366
|
+
};
|
|
2367
|
+
const mcpSubParser = new ArgParserBase({}, [
|
|
2368
|
+
{
|
|
2369
|
+
name: "transport",
|
|
2370
|
+
description: "Transport type for MCP server (single transport mode)",
|
|
2371
|
+
options: ["--transport", "-t"],
|
|
2372
|
+
type: "string",
|
|
2373
|
+
enum: ["stdio", "sse", "streamable-http"],
|
|
2374
|
+
defaultValue: "stdio"
|
|
2375
|
+
},
|
|
2376
|
+
{
|
|
2377
|
+
name: "transports",
|
|
2378
|
+
description: "Multiple transports configuration as JSON array (overrides single transport)",
|
|
2379
|
+
options: ["--transports"],
|
|
2380
|
+
type: "string"
|
|
2381
|
+
},
|
|
2382
|
+
{
|
|
2383
|
+
name: "port",
|
|
2384
|
+
description: "Port number for HTTP-based transports (single transport mode)",
|
|
2385
|
+
options: ["--port", "-p"],
|
|
2386
|
+
type: "number",
|
|
2387
|
+
defaultValue: 3e3
|
|
2388
|
+
},
|
|
2389
|
+
{
|
|
2390
|
+
name: "host",
|
|
2391
|
+
description: "Host address for HTTP-based transports (single transport mode)",
|
|
2392
|
+
options: ["--host"],
|
|
2393
|
+
type: "string",
|
|
2394
|
+
defaultValue: "localhost"
|
|
2395
|
+
},
|
|
2396
|
+
{
|
|
2397
|
+
name: "path",
|
|
2398
|
+
description: "Path for HTTP-based transports (single transport mode)",
|
|
2399
|
+
options: ["--path"],
|
|
2400
|
+
type: "string",
|
|
2401
|
+
defaultValue: "/mcp"
|
|
2402
|
+
}
|
|
2403
|
+
]);
|
|
2404
|
+
this.addSubCommand({
|
|
2405
|
+
name: subCommandName,
|
|
2406
|
+
description: `Start ${serverInfo.name} as an MCP server`,
|
|
2407
|
+
handler: mcpHandler,
|
|
2408
|
+
parser: mcpSubParser,
|
|
2409
|
+
isMcp: true
|
|
2410
|
+
});
|
|
2411
|
+
return this;
|
|
2412
|
+
}
|
|
2413
|
+
/**
|
|
2414
|
+
* Factory method to create an ArgParser instance with MCP capabilities
|
|
2415
|
+
* This provides a clean API for users who want MCP functionality from the start
|
|
2416
|
+
*/
|
|
2417
|
+
static withMcp(options, initialFlags) {
|
|
2418
|
+
return new _ArgParser(options, initialFlags);
|
|
2419
|
+
}
|
|
2420
|
+
/**
|
|
2421
|
+
* Convert an existing ArgParserBase instance to ArgParser with MCP
|
|
2422
|
+
* This allows upgrading existing parsers to support MCP
|
|
2423
|
+
*/
|
|
2424
|
+
static fromArgParser(parser) {
|
|
2425
|
+
const originalParser = parser;
|
|
2426
|
+
const mcpParser = new _ArgParser({
|
|
2427
|
+
appName: originalParser.getAppName(),
|
|
2428
|
+
appCommandName: originalParser.getAppCommandName(),
|
|
2429
|
+
description: originalParser.getDescription(),
|
|
2430
|
+
handler: originalParser.getHandler(),
|
|
2431
|
+
handleErrors: originalParser["#handleErrors"],
|
|
2432
|
+
throwForDuplicateFlags: originalParser["#throwForDuplicateFlags"]
|
|
2433
|
+
});
|
|
2434
|
+
const originalFlags = originalParser.flags.filter(
|
|
2435
|
+
(flag) => flag.name !== "help"
|
|
2436
|
+
);
|
|
2437
|
+
if (originalFlags.length > 0) {
|
|
2438
|
+
mcpParser.addFlags(originalFlags);
|
|
2439
|
+
}
|
|
2440
|
+
const newParser = mcpParser;
|
|
2441
|
+
newParser["#subCommandName"] = originalParser["#subCommandName"];
|
|
2442
|
+
newParser["#parameters"] = originalParser["#parameters"];
|
|
2443
|
+
newParser["#parentParser"] = originalParser["#parentParser"];
|
|
2444
|
+
newParser["#lastParseResult"] = originalParser["#lastParseResult"];
|
|
2445
|
+
newParser["#inheritParentFlags"] = originalParser["#inheritParentFlags"];
|
|
2446
|
+
newParser["#subCommands"] = originalParser["#subCommands"];
|
|
2447
|
+
return mcpParser;
|
|
2448
|
+
}
|
|
2449
|
+
};
|
|
2450
|
+
_ArgParser_instances = new WeakSet();
|
|
2451
|
+
_startSingleTransport_fn = async function(server, serverInfo, transportConfig) {
|
|
2452
|
+
switch (transportConfig.type) {
|
|
2453
|
+
case "stdio": {
|
|
2454
|
+
const { StdioServerTransport } = await Promise.resolve().then(() => require("./stdio-DESvSONI.cjs"));
|
|
2455
|
+
const transport = new StdioServerTransport();
|
|
2456
|
+
await server.connect(transport);
|
|
2457
|
+
console.error(`[${serverInfo.name}] MCP Server started with stdio transport`);
|
|
2458
|
+
break;
|
|
2459
|
+
}
|
|
2460
|
+
case "sse": {
|
|
2461
|
+
const { SSEServerTransport } = await Promise.resolve().then(() => require("./sse-B5Jf_YpG.cjs"));
|
|
2462
|
+
const express = (await import("express")).default;
|
|
2463
|
+
const app = express();
|
|
2464
|
+
app.use(express.json());
|
|
2465
|
+
const port = transportConfig.port || 3e3;
|
|
2466
|
+
const path2 = transportConfig.path || "/sse";
|
|
2467
|
+
app.get(path2, (_req, res) => {
|
|
2468
|
+
const transport = new SSEServerTransport(path2, res);
|
|
2469
|
+
server.connect(transport);
|
|
2470
|
+
});
|
|
2471
|
+
await new Promise((resolve) => {
|
|
2472
|
+
app.listen(port, transportConfig.host || "localhost", () => {
|
|
2473
|
+
console.error(`[${serverInfo.name}] MCP Server listening on http://${transportConfig.host || "localhost"}:${port}${path2} (SSE)`);
|
|
2474
|
+
resolve();
|
|
2475
|
+
});
|
|
2476
|
+
});
|
|
2477
|
+
break;
|
|
2478
|
+
}
|
|
2479
|
+
case "streamable-http": {
|
|
2480
|
+
const { StreamableHTTPServerTransport } = await Promise.resolve().then(() => require("./streamableHttp-DsXlAnqJ.cjs"));
|
|
2481
|
+
const express = (await import("express")).default;
|
|
2482
|
+
const app = express();
|
|
2483
|
+
app.use(express.json());
|
|
2484
|
+
const port = transportConfig.port || 3e3;
|
|
2485
|
+
const path2 = transportConfig.path || "/mcp";
|
|
2486
|
+
const transports = {};
|
|
2487
|
+
app.all(path2, async (req, res) => {
|
|
2488
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
2489
|
+
let transport;
|
|
2490
|
+
if (sessionId && transports[sessionId]) {
|
|
2491
|
+
transport = transports[sessionId];
|
|
2492
|
+
} else {
|
|
2493
|
+
transport = new StreamableHTTPServerTransport({
|
|
2494
|
+
sessionIdGenerator: transportConfig.sessionIdGenerator || (() => Math.random().toString(36).substring(7)),
|
|
2495
|
+
onsessioninitialized: (sessionId2) => {
|
|
2496
|
+
transports[sessionId2] = transport;
|
|
2497
|
+
}
|
|
2498
|
+
});
|
|
2499
|
+
transport.onclose = () => {
|
|
2500
|
+
if (transport.sessionId) {
|
|
2501
|
+
delete transports[transport.sessionId];
|
|
2502
|
+
}
|
|
2503
|
+
};
|
|
2504
|
+
await server.connect(transport);
|
|
2505
|
+
}
|
|
2506
|
+
await transport.handleRequest(req, res, req.body);
|
|
2507
|
+
});
|
|
2508
|
+
await new Promise((resolve) => {
|
|
2509
|
+
app.listen(port, transportConfig.host || "localhost", () => {
|
|
2510
|
+
console.error(`[${serverInfo.name}] MCP Server listening on http://${transportConfig.host || "localhost"}:${port}${path2} (HTTP)`);
|
|
2511
|
+
resolve();
|
|
2512
|
+
});
|
|
2513
|
+
});
|
|
2514
|
+
break;
|
|
2515
|
+
}
|
|
2516
|
+
default:
|
|
2517
|
+
throw new Error(`Unsupported transport type: ${transportConfig.type}`);
|
|
2518
|
+
}
|
|
2519
|
+
};
|
|
1189
2520
|
let ArgParser = _ArgParser;
|
|
2521
|
+
class ArgParserFuzzyTester {
|
|
2522
|
+
constructor(parser, options = {}) {
|
|
2523
|
+
this.parser = parser;
|
|
2524
|
+
this.options = {
|
|
2525
|
+
maxDepth: options.maxDepth ?? 5,
|
|
2526
|
+
randomTestCases: options.randomTestCases ?? 10,
|
|
2527
|
+
includePerformance: options.includePerformance ?? true,
|
|
2528
|
+
testErrorCases: options.testErrorCases ?? true,
|
|
2529
|
+
verbose: options.verbose ?? false
|
|
2530
|
+
};
|
|
2531
|
+
}
|
|
2532
|
+
/**
|
|
2533
|
+
* Run comprehensive fuzzy testing on the ArgParser instance
|
|
2534
|
+
*/
|
|
2535
|
+
async runFuzzyTest() {
|
|
2536
|
+
const commandPaths = this.discoverCommandPaths();
|
|
2537
|
+
const results = [];
|
|
2538
|
+
if (this.options.verbose) {
|
|
2539
|
+
console.log(`Discovered ${commandPaths.length} command paths:`);
|
|
2540
|
+
commandPaths.forEach((path2) => console.log(` ${path2.join(" ") || "(root)"}`));
|
|
2541
|
+
}
|
|
2542
|
+
for (const commandPath of commandPaths) {
|
|
2543
|
+
const pathResults = await this.testCommandPath(commandPath);
|
|
2544
|
+
results.push(...pathResults);
|
|
2545
|
+
}
|
|
2546
|
+
return this.generateReport(commandPaths, results);
|
|
2547
|
+
}
|
|
2548
|
+
/**
|
|
2549
|
+
* Discover all possible command paths in the parser
|
|
2550
|
+
*/
|
|
2551
|
+
discoverCommandPaths() {
|
|
2552
|
+
const paths = [];
|
|
2553
|
+
paths.push([]);
|
|
2554
|
+
this.discoverSubCommandPaths(this.parser, [], paths, 0);
|
|
2555
|
+
return paths;
|
|
2556
|
+
}
|
|
2557
|
+
/**
|
|
2558
|
+
* Recursively discover subcommand paths
|
|
2559
|
+
*/
|
|
2560
|
+
discoverSubCommandPaths(parser, currentPath, allPaths, depth) {
|
|
2561
|
+
if (depth >= this.options.maxDepth) return;
|
|
2562
|
+
const subCommands = this.getSubCommands(parser);
|
|
2563
|
+
for (const [subCommandName, subCommand] of subCommands) {
|
|
2564
|
+
const newPath = [...currentPath, subCommandName];
|
|
2565
|
+
allPaths.push(newPath);
|
|
2566
|
+
this.discoverSubCommandPaths(subCommand.parser, newPath, allPaths, depth + 1);
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
/**
|
|
2570
|
+
* Get subcommands from a parser instance
|
|
2571
|
+
*/
|
|
2572
|
+
getSubCommands(parser) {
|
|
2573
|
+
return parser.getSubCommands();
|
|
2574
|
+
}
|
|
2575
|
+
/**
|
|
2576
|
+
* Get flags from a parser instance
|
|
2577
|
+
*/
|
|
2578
|
+
getFlags(parser) {
|
|
2579
|
+
return parser.flags;
|
|
2580
|
+
}
|
|
2581
|
+
/**
|
|
2582
|
+
* Test a specific command path with various flag combinations
|
|
2583
|
+
*/
|
|
2584
|
+
async testCommandPath(commandPath) {
|
|
2585
|
+
const results = [];
|
|
2586
|
+
const targetParser = this.getParserForPath(commandPath);
|
|
2587
|
+
const flags = this.getFlags(targetParser);
|
|
2588
|
+
if (this.options.verbose) {
|
|
2589
|
+
console.log(`Testing command path: ${commandPath.join(" ") || "(root)"}`);
|
|
2590
|
+
}
|
|
2591
|
+
const validCombinations = this.generateValidFlagCombinations(flags);
|
|
2592
|
+
for (const flagArgs of validCombinations) {
|
|
2593
|
+
const fullArgs = [...commandPath, ...flagArgs];
|
|
2594
|
+
const result = await this.executeTest(fullArgs, commandPath);
|
|
2595
|
+
results.push(result);
|
|
2596
|
+
}
|
|
2597
|
+
for (let i = 0; i < this.options.randomTestCases; i++) {
|
|
2598
|
+
const randomArgs = this.generateRandomFlagCombination(flags);
|
|
2599
|
+
const fullArgs = [...commandPath, ...randomArgs];
|
|
2600
|
+
const result = await this.executeTest(fullArgs, commandPath);
|
|
2601
|
+
results.push(result);
|
|
2602
|
+
}
|
|
2603
|
+
if (this.options.testErrorCases) {
|
|
2604
|
+
const errorCases = this.generateErrorCases(flags);
|
|
2605
|
+
for (const errorArgs of errorCases) {
|
|
2606
|
+
const fullArgs = [...commandPath, ...errorArgs];
|
|
2607
|
+
const result = await this.executeTest(fullArgs, commandPath, true);
|
|
2608
|
+
results.push(result);
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
return results;
|
|
2612
|
+
}
|
|
2613
|
+
/**
|
|
2614
|
+
* Get the parser instance for a specific command path
|
|
2615
|
+
*/
|
|
2616
|
+
getParserForPath(commandPath) {
|
|
2617
|
+
let currentParser = this.parser;
|
|
2618
|
+
for (const command of commandPath) {
|
|
2619
|
+
const subCommands = this.getSubCommands(currentParser);
|
|
2620
|
+
const subCommand = subCommands.get(command);
|
|
2621
|
+
if (!subCommand) {
|
|
2622
|
+
throw new Error(`Command path not found: ${commandPath.join(" ")}`);
|
|
2623
|
+
}
|
|
2624
|
+
currentParser = subCommand.parser;
|
|
2625
|
+
}
|
|
2626
|
+
return currentParser;
|
|
2627
|
+
}
|
|
2628
|
+
/**
|
|
2629
|
+
* Generate valid flag combinations for testing
|
|
2630
|
+
*/
|
|
2631
|
+
generateValidFlagCombinations(flags) {
|
|
2632
|
+
const combinations = [];
|
|
2633
|
+
const mandatoryFlags = flags.filter(
|
|
2634
|
+
(f) => f["name"] !== "help" && (typeof f["mandatory"] === "boolean" ? f["mandatory"] : false)
|
|
2635
|
+
);
|
|
2636
|
+
const optionalFlags = flags.filter(
|
|
2637
|
+
(f) => f["name"] !== "help" && (typeof f["mandatory"] === "boolean" ? !f["mandatory"] : true)
|
|
2638
|
+
);
|
|
2639
|
+
const mandatoryArgs = [];
|
|
2640
|
+
for (const flag of mandatoryFlags) {
|
|
2641
|
+
const flagArgs = this.generateFlagArgs(flag, "valid");
|
|
2642
|
+
mandatoryArgs.push(...flagArgs);
|
|
2643
|
+
}
|
|
2644
|
+
if (mandatoryArgs.length > 0) {
|
|
2645
|
+
combinations.push([...mandatoryArgs]);
|
|
2646
|
+
} else {
|
|
2647
|
+
combinations.push([]);
|
|
2648
|
+
}
|
|
2649
|
+
for (const flag of optionalFlags) {
|
|
2650
|
+
const flagArgs = this.generateFlagArgs(flag, "valid");
|
|
2651
|
+
if (flagArgs.length > 0) {
|
|
2652
|
+
combinations.push([...mandatoryArgs, ...flagArgs]);
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
if (optionalFlags.length > 1) {
|
|
2656
|
+
for (let i = 0; i < optionalFlags.length - 1; i++) {
|
|
2657
|
+
for (let j = i + 1; j < optionalFlags.length; j++) {
|
|
2658
|
+
const flag1Args = this.generateFlagArgs(optionalFlags[i], "valid");
|
|
2659
|
+
const flag2Args = this.generateFlagArgs(optionalFlags[j], "valid");
|
|
2660
|
+
if (flag1Args.length > 0 && flag2Args.length > 0) {
|
|
2661
|
+
combinations.push([...mandatoryArgs, ...flag1Args, ...flag2Args]);
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
return combinations;
|
|
2667
|
+
}
|
|
2668
|
+
/**
|
|
2669
|
+
* Generate random flag combination
|
|
2670
|
+
*/
|
|
2671
|
+
generateRandomFlagCombination(flags) {
|
|
2672
|
+
const args = [];
|
|
2673
|
+
const availableFlags = flags.filter((f) => f["name"] !== "help");
|
|
2674
|
+
for (const flag of availableFlags) {
|
|
2675
|
+
if (Math.random() < 0.3) {
|
|
2676
|
+
const flagArgs = this.generateFlagArgs(flag, "random");
|
|
2677
|
+
args.push(...flagArgs);
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
return args;
|
|
2681
|
+
}
|
|
2682
|
+
/**
|
|
2683
|
+
* Generate error test cases
|
|
2684
|
+
*/
|
|
2685
|
+
generateErrorCases(flags) {
|
|
2686
|
+
const errorCases = [];
|
|
2687
|
+
errorCases.push(["--invalid-flag"]);
|
|
2688
|
+
errorCases.push(["--nonexistent", "value"]);
|
|
2689
|
+
for (const flag of flags) {
|
|
2690
|
+
if (flag["name"] === "help") continue;
|
|
2691
|
+
const invalidArgs = this.generateFlagArgs(flag, "invalid");
|
|
2692
|
+
if (invalidArgs.length > 0) {
|
|
2693
|
+
errorCases.push(invalidArgs);
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
return errorCases;
|
|
2697
|
+
}
|
|
2698
|
+
/**
|
|
2699
|
+
* Generate arguments for a specific flag
|
|
2700
|
+
*/
|
|
2701
|
+
generateFlagArgs(flag, mode) {
|
|
2702
|
+
const option = flag["options"][0];
|
|
2703
|
+
if (!option) return [];
|
|
2704
|
+
if (flag["flagOnly"]) {
|
|
2705
|
+
return [option];
|
|
2706
|
+
}
|
|
2707
|
+
const values = this.generateFlagValues(flag, mode);
|
|
2708
|
+
const args = [];
|
|
2709
|
+
for (const value of values) {
|
|
2710
|
+
if (flag["allowLigature"] && Math.random() < 0.5) {
|
|
2711
|
+
args.push(`${option}=${value}`);
|
|
2712
|
+
} else {
|
|
2713
|
+
args.push(option, value);
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
return args;
|
|
2717
|
+
}
|
|
2718
|
+
/**
|
|
2719
|
+
* Generate values for a flag based on its type and constraints
|
|
2720
|
+
*/
|
|
2721
|
+
generateFlagValues(flag, mode) {
|
|
2722
|
+
const count = flag["allowMultiple"] && mode !== "invalid" ? Math.floor(Math.random() * 3) + 1 : 1;
|
|
2723
|
+
const values = [];
|
|
2724
|
+
for (let i = 0; i < count; i++) {
|
|
2725
|
+
values.push(this.generateSingleFlagValue(flag, mode));
|
|
2726
|
+
}
|
|
2727
|
+
return values;
|
|
2728
|
+
}
|
|
2729
|
+
/**
|
|
2730
|
+
* Generate a single value for a flag
|
|
2731
|
+
*/
|
|
2732
|
+
generateSingleFlagValue(flag, mode) {
|
|
2733
|
+
if (mode === "invalid") {
|
|
2734
|
+
if (flag["type"] === Number) return "not-a-number";
|
|
2735
|
+
if (flag["enum"] && flag["enum"].length > 0) return "invalid-enum-value";
|
|
2736
|
+
if (flag["type"] === Boolean) return "not-boolean";
|
|
2737
|
+
return "invalid-value";
|
|
2738
|
+
}
|
|
2739
|
+
if (flag["enum"] && flag["enum"].length > 0) {
|
|
2740
|
+
const randomIndex = Math.floor(Math.random() * flag["enum"].length);
|
|
2741
|
+
return String(flag["enum"][randomIndex]);
|
|
2742
|
+
}
|
|
2743
|
+
if (flag["type"] === Number) {
|
|
2744
|
+
return String(Math.floor(Math.random() * 1e3));
|
|
2745
|
+
}
|
|
2746
|
+
if (flag["type"] === Boolean) {
|
|
2747
|
+
return Math.random() < 0.5 ? "true" : "false";
|
|
2748
|
+
}
|
|
2749
|
+
const testStrings = [
|
|
2750
|
+
"test-value",
|
|
2751
|
+
"hello-world",
|
|
2752
|
+
"file.txt",
|
|
2753
|
+
"/path/to/file",
|
|
2754
|
+
"user@example.com",
|
|
2755
|
+
"123",
|
|
2756
|
+
"special-chars-!@#"
|
|
2757
|
+
];
|
|
2758
|
+
return testStrings[Math.floor(Math.random() * testStrings.length)];
|
|
2759
|
+
}
|
|
2760
|
+
/**
|
|
2761
|
+
* Execute a single test case
|
|
2762
|
+
*/
|
|
2763
|
+
async executeTest(args, commandPath, expectError = false) {
|
|
2764
|
+
const startTime = this.options.includePerformance ? Date.now() : 0;
|
|
2765
|
+
try {
|
|
2766
|
+
const originalArgs = [...args];
|
|
2767
|
+
const testResult = this.parser.parse(args, {
|
|
2768
|
+
skipHelpHandling: true
|
|
2769
|
+
});
|
|
2770
|
+
if (testResult && typeof testResult === "object") {
|
|
2771
|
+
testResult._originalInputArgs = originalArgs;
|
|
2772
|
+
}
|
|
2773
|
+
const executionTime = this.options.includePerformance ? Date.now() - startTime : void 0;
|
|
2774
|
+
return {
|
|
2775
|
+
commandPath,
|
|
2776
|
+
args,
|
|
2777
|
+
success: !expectError,
|
|
2778
|
+
parsedResult: testResult,
|
|
2779
|
+
executionTime
|
|
2780
|
+
};
|
|
2781
|
+
} catch (error) {
|
|
2782
|
+
const executionTime = this.options.includePerformance ? Date.now() - startTime : void 0;
|
|
2783
|
+
return {
|
|
2784
|
+
commandPath,
|
|
2785
|
+
args,
|
|
2786
|
+
success: expectError,
|
|
2787
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2788
|
+
executionTime
|
|
2789
|
+
};
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
/**
|
|
2793
|
+
* Generate comprehensive test report
|
|
2794
|
+
*/
|
|
2795
|
+
generateReport(commandPaths, results) {
|
|
2796
|
+
const totalTests = results.length;
|
|
2797
|
+
const successfulTests = results.filter((r) => r.success).length;
|
|
2798
|
+
const failedTests = totalTests - successfulTests;
|
|
2799
|
+
const coverageByPath = {};
|
|
2800
|
+
for (const path2 of commandPaths) {
|
|
2801
|
+
const pathKey = path2.join(" ") || "(root)";
|
|
2802
|
+
const pathResults = results.filter(
|
|
2803
|
+
(r) => JSON.stringify(r.commandPath) === JSON.stringify(path2)
|
|
2804
|
+
);
|
|
2805
|
+
coverageByPath[pathKey] = {
|
|
2806
|
+
total: pathResults.length,
|
|
2807
|
+
passed: pathResults.filter((r) => r.success).length
|
|
2808
|
+
};
|
|
2809
|
+
}
|
|
2810
|
+
const errorTypes = {};
|
|
2811
|
+
for (const result of results) {
|
|
2812
|
+
if (result.error) {
|
|
2813
|
+
const errorType = result.error.split(":")[0] || "Unknown";
|
|
2814
|
+
errorTypes[errorType] = (errorTypes[errorType] || 0) + 1;
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
return {
|
|
2818
|
+
totalTests,
|
|
2819
|
+
successfulTests,
|
|
2820
|
+
failedTests,
|
|
2821
|
+
commandPaths,
|
|
2822
|
+
results,
|
|
2823
|
+
summary: {
|
|
2824
|
+
coverageByPath,
|
|
2825
|
+
errorTypes
|
|
2826
|
+
}
|
|
2827
|
+
};
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
1190
2830
|
exports.ArgParser = ArgParser;
|
|
2831
|
+
exports.ArgParserBase = ArgParserBase;
|
|
1191
2832
|
exports.ArgParserError = ArgParserError;
|
|
2833
|
+
exports.ArgParserFuzzyTester = ArgParserFuzzyTester;
|
|
2834
|
+
exports.generateMcpToolsFromArgParser = generateMcpToolsFromArgParser;
|
|
2835
|
+
exports.zodFlagSchema = zodFlagSchema;
|
|
1192
2836
|
//# sourceMappingURL=index.cjs.map
|