Skip to content

Commit da591f5

Browse files
committed
upd
1 parent dab43ca commit da591f5

File tree

2 files changed

+59
-28
lines changed

2 files changed

+59
-28
lines changed

src/classes.ts

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,10 @@ export class ArgsParser implements ArgsParserInterface {
423423

424424
// Process options
425425
for (const [key, value] of Object.entries(parsedValuesMap)) {
426+
if (argConfigsMap[key] === undefined) {
427+
continue;
428+
}
429+
426430
const argConfig = argConfigsMap[key]!;
427431
result.add(argConfig.name, this.processArgValue(value, argConfig, result, true));
428432
argConfigsSet.delete(argConfig);
@@ -604,6 +608,11 @@ export class ArgsParser implements ArgsParserInterface {
604608
* @returns The number of arguments to read.
605609
*/
606610
private getArgsCountToRead(argConfig: ArgConfigExtended, remainingArgConfigs: ArgConfigExtended[], values: string[]): number {
611+
// If the argument is required and not multiple, read one value.
612+
if (argConfig.required && !argConfig.multiple) {
613+
return Math.min(1, values.length);
614+
}
615+
607616
// The total number of arguments that must be read by the remaining arguments.
608617
const minRemainingValuesCount = remainingArgConfigs.reduce((acc, x) => acc + x.minValuesCount, 0);
609618

@@ -645,9 +654,8 @@ export class ArgsParser implements ArgsParserInterface {
645654
* @category Router
646655
*/
647656
export class Router implements RouterInterface {
648-
private readonly parser: ArgsParserInterface;
649657
private readonly routes: Record<string, RouterAction>;
650-
private rawArgs: string[] = [];
658+
private readonly parser: ArgsParserInterface;
651659

652660
/**
653661
* Creates a new Router instance.
@@ -656,23 +664,16 @@ export class Router implements RouterInterface {
656664
* @param routes - The routes for the router.
657665
*/
658666
constructor(config: ArgParserConfig, routes: Record<string, RouterAction>) {
659-
config.ignoreUnrecognized = true;
660667
this.routes = routes;
661-
this.parser = new ArgsParser(config);
668+
this.parser = new ArgsParser({
669+
...config,
670+
ignoreUnrecognized: true,
671+
});
662672
this.parser.addArgument({
663673
name: 'action',
664674
type: 'string',
665675
description: 'Action to run',
666676
choices: Object.keys(routes),
667-
action: (value) => {
668-
const key = value as keyof typeof routes;
669-
const actionArgsParser = new ArgsParser({
670-
name: `${config.name} ${key}`,
671-
});
672-
this.actionToRun = () => routes[key]?.(actionArgsParser, this.passedArgv.slice(1));
673-
this.actionToRunAsync = async () => await routes[key]?.(actionArgsParser, this.passedArgv.slice(1));
674-
throw new RouterStopException();
675-
},
676677
});
677678
this.parser.addHelpAction();
678679
this.parser.addVersionAction();
@@ -689,18 +690,10 @@ export class Router implements RouterInterface {
689690
const actionName = parsed.get<keyof typeof this.routes>('action');
690691

691692
const actionArgsParser = new ArgsParser({
692-
name: `${config.name} ${key}`,
693+
name: `${this.parser.config.name} ${actionName}`,
693694
});
694695

695696
this.routes[actionName](actionArgsParser, passedArgv.slice(1));
696-
697-
698-
try {
699-
this.passedArgv = argv ?? process.argv.slice(2);
700-
this.parser.parse(this.passedArgv);
701-
} catch (e) {
702-
this.actionToRun!();
703-
}
704697
}
705698

706699
/**
@@ -709,11 +702,14 @@ export class Router implements RouterInterface {
709702
* @param argv - The argument string.
710703
*/
711704
async runAsync(argv?: string[]): Promise<void> {
712-
try {
713-
this.passedArgv = argv ?? process.argv.slice(2);
714-
this.parser.parse(this.passedArgv);
715-
} catch (e) {
716-
await this.actionToRunAsync!();
717-
}
705+
const passedArgv = argv ?? process.argv.slice(2);
706+
const parsed = this.parser.parse(passedArgv);
707+
const actionName = parsed.get<keyof typeof this.routes>('action');
708+
709+
const actionArgsParser = new ArgsParser({
710+
name: `${this.parser.config.name} ${actionName}`,
711+
});
712+
713+
await this.routes[actionName](actionArgsParser, passedArgv.slice(1));
718714
}
719715
}

tests/examples/example.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,3 +389,38 @@ it('Tenth Test', async () => {
389389

390390
console.log(parsedArgs.options);
391391
});
392+
393+
it('Eleventh Test', async () => {
394+
const parser = new ArgsParser({
395+
name: 'Test',
396+
ignoreUnrecognized: true,
397+
}, [
398+
{
399+
name: 'positional-first',
400+
description: "My first positional argument",
401+
type: 'string',
402+
choices: ['test', 'dev', 'prod'],
403+
},
404+
{
405+
name: '--optional-first',
406+
alias: '-f',
407+
description: "My first optional argument",
408+
type: 'string',
409+
nargs: '?',
410+
choices: ['test', 'dev', 'prod'],
411+
validator: (x: unknown) => String(x).length > 2,
412+
required: true,
413+
}
414+
]);
415+
416+
const argv = ['dev', 'other', 'another', '--optional-first', 'test', '--optional-other', '123', '--optional-another'];
417+
const parsedArgs = parser.parse(argv);
418+
419+
expect(parsedArgs.positional).toEqual({
420+
'positional-first': 'dev',
421+
});
422+
423+
expect(parsedArgs.options).toEqual({
424+
'optional-first': 'test',
425+
});
426+
});

0 commit comments

Comments
 (0)