Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add async custom processing support. Add chainArgParserCalls() for configuration. Additionally await thenable implicit and default option values and thenable default argument values #1915

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2c6bcf4
Add thenable function
aweebit Jul 25, 2023
9f292ad
Chain parseArg calls when parseAsync() is called
aweebit Jul 25, 2023
d1ac0cd
Improve JSDoc readability for chainArgParserCalls
aweebit Jul 25, 2023
2e7ccd1
Await thenable option and argument values when parseAsync() is called
aweebit Jul 25, 2023
2d0c78f
Leave argument variations test untouched
aweebit Jul 25, 2023
905dac0
Remove redundant checkForUnknownOptions() call
aweebit Jul 25, 2023
dacdde0
Rework _parseArg()
aweebit Jul 26, 2023
b64f298
Simplify overwritten option value handling
aweebit Jul 26, 2023
254865c
Handle thenable errors not only when chaining but only when awaiting
aweebit Jul 26, 2023
e66eda5
Precompute _shouldAwait to avoid repeating costly computation
aweebit Jul 26, 2023
fb48134
Position _parseArg() better
aweebit Jul 26, 2023
c34a839
Inherit _asyncParsing. Do not unset it and _shouldAwait
aweebit Jul 26, 2023
4d65c6c
Simplify _shouldAwait computation
aweebit Jul 26, 2023
679bcb5
Inherit await behavior the commander way
aweebit Jul 27, 2023
ade5f95
Handle overwritten not chained options correctly
aweebit Jul 27, 2023
d5799cb
Aggressively prevent unhandled rejections due to overwritten options
aweebit Jul 27, 2023
f5a0557
Fix linting errors
aweebit Jul 27, 2023
ea25170
Forbid parse() usage with async calls
aweebit Jul 27, 2023
b9643bc
Remove await configuration and unnecessary chain mode
aweebit Jul 27, 2023
385fe48
Warn about incorrect parse() instead of throwing
aweebit Jul 28, 2023
d9dcc57
Separation of concerns: add callback to _parseArg()
aweebit Jul 28, 2023
3e0e305
Position awaiting methods better
aweebit Jul 28, 2023
608d91c
Update life cycle description
aweebit Jul 28, 2023
249a0c6
Update life cycle description: clarify and better match source code
aweebit Jul 28, 2023
bf7e096
Adhere to established dot usage pattern
aweebit Jul 28, 2023
6858bdf
Place async argParser warning better
aweebit Jul 29, 2023
1cf9fed
Add thenable default option value warning
aweebit Jul 29, 2023
aa6f7c9
Unify & place thenable option value warnings better
aweebit Jul 29, 2023
9d6cee0
Fix linting error
aweebit Jul 30, 2023
2d21112
Add missing thenable argument value warnings
aweebit Jul 30, 2023
cb8c30b
Remove NODE_ENV check
aweebit Aug 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 22 additions & 15 deletions docs/parsing-and-hooks.md
@@ -1,23 +1,30 @@
# Parsing life cycle and hooks

The processing starts with an array of args. Each command processes and removes the options it understands, and passes the remaining args to the next subcommand.
The final command calls the action handler.
The processing starts with an array of args. Each command processes and removes the options it understands, and passes the remaining args to the next subcommand. The final command calls the action handler.

Starting with top-level command (program):

- parse options: parse recognised options (for this command) and remove from args
- parse env: look for environment variables (for this command)
- process implied: set any implied option values (for this command)
- if the first arg is a subcommand
- call `preSubcommand` hooks
- pass remaining arguments to subcommand, and process same way
* process options for this command (includes calling or chaining provided argParsers[^1])
* recognised options from args
* options based on environment variables
* set implied option values (for this command)
* remove recognised options from args
* await thenable option values if parsing with `parseAsync()`
* if the first arg is a subcommand
* call or chain `preSubcommand` hooks[^1]
* pass remaining arguments to subcommand, and process same way

Once reach final (leaf) command:

- check for missing mandatory options
- check for conflicting options
- check for unknown options
- process remaining args as command-arguments
- call `preAction` hooks
- call action handler
- call `postAction` hooks
* check for missing mandatory options
* check for conflicting options
* check for unknown options
* process remaining args as command-arguments (includes calling or chaining provided argParsers[^1])
* await thenable argument values if parsing with `parseAsync()`
* if an action handler is provided
* call or chain `preAction` hooks[^1]
* call or chain action handler[^1]
* call or chain `postAction` hooks[^1]
</details>

[^1]: output a warning suggesting use of `parseAsync()` when parsing with `parse()` and a thenable is returned, unless `process.env.NODE_ENV === 'production'`
12 changes: 12 additions & 0 deletions lib/argument.js
Expand Up @@ -16,6 +16,7 @@ class Argument {
this.description = description || '';
this.variadic = false;
this.parseArg = undefined;
this.chained = true;
this.defaultValue = undefined;
this.defaultValueDescription = undefined;
this.argChoices = undefined;
Expand Down Expand Up @@ -89,6 +90,17 @@ class Argument {
return this;
}

/**
* When set to `true` (the default), next call to the function provided via `.argParser()` will be chained to its return value if it is thenable.
*
* @param {boolean} [chained=true]
* @return {Argument}
*/
chainArgParserCalls(chained = true) {
this.chained = !!chained;
return this;
}

/**
* Only allow argument value to be one of choices.
*
Expand Down