Skip to content

Commit

Permalink
feat: add support for configuration file (#522)
Browse files Browse the repository at this point in the history
* Add support for `--config` command-line argument

* Add unit-tests for `--config` command-line argument

* Update documentation with configuration file details

* Add an alias for `--verbose-watch` to fix regression

Fix a regression that was caused by removing `default` from `yargs-parser`
  • Loading branch information
nooreldeensalah authored Jul 5, 2022
1 parent 742615d commit 550261b
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 19 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,11 @@ This works with a `.js` extension if you are using Node.js >= 14 and the nearest
If your `package.json` does not have `"type": "module"`, use `.mjs` for the extension (`plugin.mjs` in the above example).

#### Options
You can pass the following options via CLI arguments. Every option has a corresponding environment variable:
You can pass the following options via CLI arguments. You can also use `--config` or `-c` flag to pass a configuration file that exports all the properties listed below in camelCase convention. In case of collision (i.e., An argument existing in both the configuration file and as a command-line argument, the command-line argument is given the priority). Every option has a corresponding environment variable:

| Description | Short command | Full command | Environment variable |
| --------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ------------------ | ------------------------ |
| Path to configuration file that can be used to manage the options listed below | `-c` | `--config` | `FASTIFY_CONFIG or CONFIG` |
| Port to listen on (default to 3000) | `-p` | `--port` | `FASTIFY_PORT or PORT` |
| Address to listen on | `-a` | `--address` | `FASTIFY_ADDRESS` |
| Socket to listen on | `-s` | `--socket` | `FASTIFY_SOCKET` |
Expand All @@ -143,7 +144,7 @@ You can pass the following options via CLI arguments. Every option has a corresp
| Prints pretty logs | `-P` | `--pretty-logs` | `FASTIFY_PRETTY_LOGS` |
| Watch process.cwd() directory for changes, recursively; when that happens, the process will auto reload | `-w` | `--watch` | `FASTIFY_WATCH` |
| Ignore changes to the specified files or directories when watch is enabled. (e.g. `--ignore-watch='node_modules .git logs/error.log'` ) | | `--ignore-watch` | `FASTIFY_IGNORE_WATCH` |
| Prints events triggered by watch listener (useful to debug unexpected reload when using `--watch` ) | | `--verbose-watch` | `FASTIFY_VERBOSE_WATCH` |
| Prints events triggered by watch listener (useful to debug unexpected reload when using `--watch` ) | `-V` | `--verbose-watch` | `FASTIFY_VERBOSE_WATCH` |
| Use custom options | `-o` | `--options` | `FASTIFY_OPTIONS` |
| Set the prefix | `-x` | `--prefix` | `FASTIFY_PREFIX` |
| Set the plugin timeout | `-T` | `--plugin-timeout` | `FASTIFY_PLUGIN_TIMEOUT` |
Expand Down
43 changes: 26 additions & 17 deletions args.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,38 @@

const argv = require('yargs-parser')
const dotenv = require('dotenv')
const { requireModule } = require('./util')

const DEFAULT_IGNORE = 'node_modules build dist .git bower_components logs .swp .nyc_output'

const DEFAULT_ARGUMENTS = {
logLevel: 'fatal',
prettyLogs: false,
watch: false,
verboseWatch: false,
debug: false,
debugPort: 9320,
options: false,
pluginTimeout: 10 * 1000, // everything should load in 10 seconds
lang: 'js',
standardlint: false
}

module.exports = function parseArgs (args) {
dotenv.config()
const parsedArgs = argv(args, {
const commandLineArguments = argv(args, {
configuration: {
'populate--': true
},
number: ['port', 'inspect-port', 'body-limit', 'plugin-timeout'],
string: ['log-level', 'address', 'socket', 'prefix', 'ignore-watch', 'logging-module', 'debug-host', 'lang', 'require'],
string: ['log-level', 'address', 'socket', 'prefix', 'ignore-watch', 'logging-module', 'debug-host', 'lang', 'require', 'config'],
boolean: ['pretty-logs', 'options', 'watch', 'verbose-watch', 'debug', 'standardlint'],
envPrefix: 'FASTIFY_',
alias: {
port: ['p'],
socket: ['s'],
help: ['h'],
config: ['c'],
options: ['o'],
address: ['a'],
watch: ['w'],
Expand All @@ -29,31 +44,25 @@ module.exports = function parseArgs (args) {
'log-level': ['l'],
'pretty-logs': ['P'],
'plugin-timeout': ['T'],
'logging-module': ['L']
},
default: {
'log-level': 'fatal',
'pretty-logs': false,
watch: false,
verboseWatch: false,
debug: false,
debugPort: 9320,
options: false,
'plugin-timeout': 10 * 1000, // everything should load in 10 seconds
lang: 'js',
standardlint: false
'logging-module': ['L'],
'verbose-watch': ['V']
}
})

const additionalArgs = parsedArgs['--'] || []
const configFileOptions = commandLineArguments.config ? requireModule(commandLineArguments.config) : undefined

const additionalArgs = commandLineArguments['--'] || []
const { _, ...pluginOptions } = argv(additionalArgs)
const ignoreWatchArg = parsedArgs.ignoreWatch || ''
const ignoreWatchArg = commandLineArguments.ignoreWatch || configFileOptions?.ignoreWatch || ''

let ignoreWatch = `${DEFAULT_IGNORE} ${ignoreWatchArg}`.trim()
if (ignoreWatchArg.includes('.ts$')) {
ignoreWatch = ignoreWatch.replace('dist', '')
}

// Merge objects from lower to higher priority
const parsedArgs = { ...DEFAULT_ARGUMENTS, ...configFileOptions, ...commandLineArguments }

return {
_: parsedArgs._,
'--': additionalArgs,
Expand Down
71 changes: 71 additions & 0 deletions test/args.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,74 @@ test('should parse custom plugin options', t => {
lang: 'js'
})
})

test('should parse config file correctly and prefer config values over default ones', t => {
t.plan(1)

const argv = [
'--config', './test/data/custom-config.js',
'app.js'
]
const parsedArgs = parseArgs(argv)

t.strictSame(parsedArgs, {
_: ['app.js'],
'--': [],
port: 5000,
bodyLimit: undefined,
pluginTimeout: 9000,
pluginOptions: {},
prettyLogs: true,
options: false,
watch: true,
debug: false,
debugPort: 4000,
debugHost: '1.1.1.1',
ignoreWatch: 'node_modules build dist .git bower_components logs .swp .nyc_output',
verboseWatch: false,
logLevel: 'fatal',
address: 'fastify.io:9999',
socket: undefined,
require: undefined,
prefix: 'FASTIFY_',
loggingModule: undefined,
lang: 'js'
})
})

test('should prefer command line args over config file options', t => {
t.plan(1)

const argv = [
'--config', './test/data/custom-config.js',
'--port', '4000',
'--debugPort', '9320',
'--plugin-timeout', '10000',
'app.js'
]
const parsedArgs = parseArgs(argv)

t.strictSame(parsedArgs, {
_: ['app.js'],
'--': [],
port: 4000,
bodyLimit: undefined,
pluginTimeout: 10000,
pluginOptions: {},
prettyLogs: true,
options: false,
watch: true,
debug: false,
debugPort: 9320,
debugHost: '1.1.1.1',
ignoreWatch: 'node_modules build dist .git bower_components logs .swp .nyc_output',
verboseWatch: false,
logLevel: 'fatal',
address: 'fastify.io:9999',
socket: undefined,
require: undefined,
prefix: 'FASTIFY_',
loggingModule: undefined,
lang: 'js'
})
})
9 changes: 9 additions & 0 deletions test/data/custom-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
port: 5000,
address: 'fastify.io:9999',
prefix: 'FASTIFY_',
watch: true,
prettyLogs: true,
debugPort: 4000,
pluginTimeout: 9 * 1000
}

0 comments on commit 550261b

Please sign in to comment.