Skip to content

Commit b5accd6

Browse files
author
Benjamin E. Coe
authored
fix(builder): nested builder is now awaited (#1925)
1 parent 8ac32ee commit b5accd6

4 files changed

Lines changed: 76 additions & 12 deletions

File tree

lib/command.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,9 @@ export class CommandInstance {
307307
parentCommands: string[],
308308
commandIndex: number,
309309
helpOnly: boolean
310-
): {aliases: Dictionary<string[]>; innerArgv: Arguments} {
310+
):
311+
| {aliases: Dictionary<string[]>; innerArgv: Arguments}
312+
| Promise<{aliases: Dictionary<string[]>; innerArgv: Arguments}> {
311313
// A null command indicates we are running the default command,
312314
// if this is the case, we should show the root usage instructions
313315
// rather than the usage instructions for the nested default command:
@@ -334,10 +336,19 @@ export class CommandInstance {
334336
commandIndex,
335337
helpOnly
336338
);
337-
return {
338-
aliases: (innerYargs.parsed as DetailedArguments).aliases,
339-
innerArgv: innerArgv as Arguments,
340-
};
339+
if (isPromise(innerArgv)) {
340+
return innerArgv.then(argv => {
341+
return {
342+
aliases: (innerYargs.parsed as DetailedArguments).aliases,
343+
innerArgv: argv,
344+
};
345+
});
346+
} else {
347+
return {
348+
aliases: (innerYargs.parsed as DetailedArguments).aliases,
349+
innerArgv: innerArgv,
350+
};
351+
}
341352
}
342353
private shouldUpdateUsage(yargs: YargsInstance) {
343354
return (

lib/yargs-factory.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,11 +1032,7 @@ export class YargsInstance {
10321032
);
10331033
this[kFreeze](); // Push current state of parser onto stack.
10341034
if (typeof args === 'undefined') {
1035-
const argv = this[kRunYargsParserAndExecuteCommands](this.#processArgs);
1036-
const tmpParsed = this.parsed;
1037-
this[kUnfreeze](); // Pop the stack.
1038-
this.parsed = tmpParsed;
1039-
return argv;
1035+
args = this.#processArgs;
10401036
}
10411037

10421038
// a context object can optionally be provided, this allows
@@ -1063,6 +1059,7 @@ export class YargsInstance {
10631059
args,
10641060
!!shortCircuit
10651061
);
1062+
const tmpParsed = this.parsed;
10661063
this.#completion!.setParsed(this.parsed as DetailedArguments);
10671064
if (isPromise(parsed)) {
10681065
return parsed
@@ -1082,10 +1079,12 @@ export class YargsInstance {
10821079
})
10831080
.finally(() => {
10841081
this[kUnfreeze](); // Pop the stack.
1082+
this.parsed = tmpParsed;
10851083
});
10861084
} else {
10871085
if (this.#parseFn) this.#parseFn(this.#exitError, parsed, this.#output);
10881086
this[kUnfreeze](); // Pop the stack.
1087+
this.parsed = tmpParsed;
10891088
}
10901089
return parsed;
10911090
}
@@ -1983,7 +1982,6 @@ export class YargsInstance {
19831982
const handlerKeys = this.#command.getCommands();
19841983
const requestCompletions = this.#completion!.completionKey in argv;
19851984
const skipRecommendation = helpOptSet || requestCompletions || helpOnly;
1986-
19871985
if (argv._.length) {
19881986
if (handlerKeys.length) {
19891987
let firstUnknownCommand;

test/command.cjs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,6 +2065,62 @@ describe('Command', () => {
20652065
argv.help.should.equal(true);
20662066
});
20672067
});
2068+
// Refs: https://github.com/yargs/yargs/issues/1917
2069+
it('allows command to be defined in async builder', async () => {
2070+
let invoked = false;
2071+
await yargs('alpha beta')
2072+
.strict()
2073+
.command({
2074+
command: 'alpha',
2075+
describe: 'A',
2076+
builder: async yargs => {
2077+
await wait();
2078+
yargs
2079+
.command({
2080+
command: 'beta',
2081+
describe: 'B',
2082+
handler: () => {
2083+
invoked = true;
2084+
},
2085+
})
2086+
.demandCommand(1);
2087+
},
2088+
})
2089+
.demandCommand(1)
2090+
.parse();
2091+
assert.strictEqual(invoked, true);
2092+
});
2093+
it('allows deeply nested command to be defined in async builder', async () => {
2094+
let invoked = false;
2095+
await yargs('alpha beta gamma')
2096+
.strict()
2097+
.command('alpha', 'A', async yargs => {
2098+
await wait();
2099+
yargs
2100+
.command({
2101+
command: 'beta',
2102+
describe: 'B',
2103+
builder: async yargs => {
2104+
await wait();
2105+
return yargs.command(
2106+
'gamma',
2107+
'C',
2108+
async () => {
2109+
await wait();
2110+
},
2111+
async () => {
2112+
await wait();
2113+
invoked = true;
2114+
}
2115+
);
2116+
},
2117+
})
2118+
.demandCommand(1);
2119+
})
2120+
.demandCommand(1)
2121+
.parse();
2122+
assert.strictEqual(invoked, true);
2123+
});
20682124
});
20692125

20702126
describe('builder', () => {

test/usage.cjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,6 @@ describe('usage tests', () => {
596596
// ignore the error, we only test the output here
597597
}
598598
});
599-
console.info(r);
600599
r.errors
601600
.join('\n')
602601
.split(/\n+/)

0 commit comments

Comments
 (0)