mahemoff/node-config-demo
How to read options from command line, config files, and mix both. With Node and Yargs.
node-config-demo
How to read options from command line, config files, and mix both. With Node and Yargs.
YARGS is a powerful tool if you're building anything complex with Node. One of the best things is it not only looks at command-line arguments, but config files, and it's even possible to mix them together.
I created this project because I wanted to explore how all of this works. How is a conflicts handled in a situation where the same argument is specified in multiple placs? How does all this work when there are nested hashes (i.e. a hierarchy of options, not just a simple, flat, list). And how to deal with config files flexibly, not just the standard idea of a JSON file at a location specified by the user.
The yargs invocations can be found in lib/ folder. This doc is generated by the bash script demo.sh, which runs the scripts with various arguments to demonstrate each usage pattern.
BASE CASE
NO ARGUMENTS
No app-specific variables are set.
demo.js
{
"_": [],
"$0": "lib/demo.js"
}
--
COMMAND LINE ARGUMENTS
COMMAND-LINE ARGUMENTS
Variables set directly from command line. Note that a dashed-option gives you both camelCase and snake_case references as a convenience.
demo.js --time=60 --splash-screen=false
{
"_": [],
"time": 60,
"splash-screen": "false",
"splashScreen": "false",
"$0": "lib/demo.js"
}
--
NESTED COMMAND LINE ARGUMENTS
Specify hierarchies using dot notation.
demo.js --time=60 --splash-screen=false --enemy.speed=50 --enemy.visible=true --player.speed=20 --player.human=true
{
"_": [],
"time": 60,
"splash-screen": "false",
"splashScreen": "false",
"enemy": {
"speed": 50,
"visible": "true"
},
"player": {
"speed": 20,
"human": "true"
},
"$0": "lib/demo.js"
}
--
CONFIG FILE
SIMPLE CONFIG FILE
Instead of using command-line, its possible to include options in a file with yargs config() method.
demo.js --config=config/game.json
{
"_": [],
"config": "config/game.json",
"time": 30,
"splash-screen": true,
"splashScreen": true,
"enemy": {
"speed": 100,
"visible": false
},
"player": {
"speed": 30,
"human": false
},
"$0": "lib/demo.js"
}
--
TOML CONFIG FILE
It doesnt have to be a JSON file. Any format can be used as long as theres a way to parse itng into a hash, so well use a different config() here to support TOML instead.
toml_demo.js --config=config/game.toml
{
"_": [],
"config": "config/game.toml",
"time": 45,
"splash-screen": true,
"splashScreen": true,
"enemy": {
"speed": 100,
"visible": false
},
"player": {
"speed": 40,
"visible": true
},
"$0": "lib/toml_demo.js"
}
--
FLEXIBLE CONFIG FILES
In this case, config() has been modified to support looking for config in standard locations. You can try making a JSON file (with any content) at ~/.game.json and re-running the demo.
flexible_config_demo.js
{
"_": [],
"foo": "bar",
"config": "/dev/null",
"$0": "lib/flexible_config_demo.js"
}
--
MIXING COMMAND LINE ARGUMENTS WITH CONFIG FILE
SAME OPTION ON BOTH COMMAND LINE AND CONFIG FILE
As the results show, both config and command line are used. The config file provides defaults, which the command line can override.
demo.js --time=60 --config=config/simple_game.json
{
"_": [],
"time": 60,
"config": "config/simple_game.json",
"splash-screen": true,
"splashScreen": true,
"enemy": {
"speed": 100,
"visible": false
},
"player": {
"speed": 30,
"human": false
},
"$0": "lib/demo.js"
}
--
NESTED OPTIONS ON BOTH COMMAND LINE AND CONFIG FILE
Again, options present in both will be determined by the command line as it has priority. As before, options only in one or the other will still be respected, this time with nesting.
demo.js --time=60 --enemy.speed=25 --physics.gravity=5 --config=config/game.json
{
"_": [],
"time": 60,
"enemy": {
"speed": 25,
"visible": false
},
"physics": {
"gravity": 5
},
"config": "config/game.json",
"splash-screen": true,
"splashScreen": true,
"player": {
"speed": 30,
"human": false
},
"$0": "lib/demo.js"
}
--