diff --git a/README.md b/README.md index 3d956fa..f74bf98 100755 --- a/README.md +++ b/README.md @@ -5,7 +5,56 @@ [![Coverage Status][coverage-image]][coverage-url] [![styled with prettier][prettier-image]][prettier-url] -A lightweight configuration module powered by yaml. +A lightweight/opinionated/versatile configuration module powered by yaml. + +- [Motivation](#motivation) +- [Installation](#installation) +- [Usage](#usage) + - [Environment variables override](#environment-variables-override) + - [NODE_ENV override](#node-env-override) + - [More overrides](#more-overrides) :smiling_imp: + - [Inheritance model](#inheritance-model) + +## Motivation + +Why the hell another Node.js config package? + +That's a question we asked ourselves before starting this module, +we wanted simple config management with the following features: + +- Simple to use +- Small footprint +- Homogeneous config file format +- No global/specific/pre-configured module to load (eg. require the lib, configure it and then require this file instead directly using the package) +- Human readable +- Concise +- Comments +- Types +- Overrides +- Env variables support + +Several modules already exist, but none of them matched our requirements, +some were far too limited and others, in our opinion, really bloated. + +We chose yaml because it automatically covered several requirements, +it's concise compared to json, you can add comments, it supports types +and it's really easy to read it. Yaml also offers other neat features +such as [anchors](http://www.yaml.org/spec/1.2/spec.html#id2765878). + +**We only support yaml config files**, having a project with `json`, `xml`, +`toml`, `ini`, `properties`,… just does not scale when working on big projects, +everyone adding its favorite flavor. + +Then we used environment variables to load overrides or define some specific keys, +it makes really easy to tweak your config depending on the environment +you're running on without touching a single line of code or even a config file. +Really handy when using Docker heavily. + +We used this code across several projects (a small file comprised of ~100 loc at this time), +and improved it when required. + +And here we are! It's now open source, and we hope it will help others +building awesome things like it did for us. ## Installation @@ -23,16 +72,249 @@ npm install @ekino/config ## Usage -This module assumes all your configuration is defined in a single directory: +As this module heavily relies on **environment variables**, you could read +[this](https://en.wikipedia.org/wiki/Environment_variable) first if you're not comfortable with them. + +This module assumes all your configuration is defined in a single directory, +located at the root of your current working directory (`process.cwd()`): ``` ├─ conf/ ├─ base.yaml # the base configuration ├─ env_mapping.yaml # defines mapping between env vars and config keys - └─ dev.yaml # loaded if NODE_ENV is `dev` + └─ dev.yaml # Optional file loaded if NODE_ENV is `dev` +``` + +`base.yaml` is required, it defines the common basic configuration of your application. + +Then to get a config key value in your code: + +```yaml +# /conf/base.yaml +host: base.config.io +external_api: + key: xxxxx +``` + +```javascript +// test.js +const config = require('@ekino/config') +console.log(config.get('host')) +console.log(config.get('external_api.key')) +``` + +If we run this script, we'll have: + +```sh +node test.js +> base.config.io +> xxxxx +``` + +### Environment variables override + +Sometimes you want to override a single value on certain environments, to do so this module provides +a special file called `env_mapping.yaml`, it allows to define per key override according to +environment variable value. + +Assuming we've got the following config files: + +```yaml +# /conf/base.yaml +host: base.config.io +external_api: + key: xxxxx +``` + +```yaml +# /conf/env_mapping.yaml +HOST: host +API_KEY: external_api.key +``` + +And the following code: + +```javascript +// test.js +const config = require('@ekino/config') +console.log(config.get('host')) +console.log(config.get('external_api.key')) +``` + +If we run this script, we'll have: + +```sh +node test.js +> base.config.io +> xxxxx + +HOST=staging.config.io API_KEY=12345 node test.js +> staging.config.io +> 12345 +``` + +The second run outputs a different values because we mapped the `HOST` and `API_KEY` environment variables +to the `host` and `external_api.key` config keys using `env_mapping.yaml`. + +Environment variables can be handy, however when reading them from node, we'll always get a string, +this can be annoying when dealing with boolean values for example. +That's why you can optionally force the type of the gathered environment variables value: + +```yaml +# /conf/env_mapping.yaml +PORT: + key: port + type: number +USE_SSL: + key: use_ssl + type: boolean +``` + +For now we only support `number` and `boolean` types, if you think others could be useful, +do not hesitate to contribute! + +### NODE_ENV override + +If you've got a bunch of variations depending on the environment your're running your application on, +it can be cumbersome to define tens of mappings inside the `env_mapping.yaml` file. + +This module gives you the ability to load overrides depending on the special `NODE_ENV` +environment variable value, let's say we'got those config files: + +```yaml +# /conf/dev.yaml +host: dev.config.io +``` + +```yaml +# /conf/prod.yaml +host: prod.config.io +``` + +And the following code: + +```javascript +// test.js +const config = require('@ekino/config') +console.log(config.get('host')) +``` + +If we run this script, we'll have: + +```sh +NODE_ENV=dev node test.js +> dev.config.io + +NODE_ENV=prod node test.js +> prod.config.io +``` + +### More overrides + +As we've seen previously with [Environment variables override](#environment-variables-override) +and [NODE_ENV override](#node-env-override), you can easily tweak your config without changing +a single line of code, but if those features aren't sufficient to cover your requirements, +you have another available level of override using `CONF_OVERRIDES`. + +> Please make sure you really need it before using it +> as it makes more unclear what the final config will be. + +Let's say we've got those config files: + +```yaml +# /conf/base.yaml +service: awesome +host: base.config.io +port: 8080 +``` + +```yaml +# /conf/prod.yaml +host: prod.config.io +port: 8081 ``` -> Be warned that this module uses synchronous file reads in order to be easily required. +```yaml +# /conf/aws.yaml +host: prod.aws.config.io +``` + +```yaml +# /conf/google.yaml +host: prod.google.config.io +``` + +```yaml +# /conf/extra.yaml +port: 8082 +``` + +And the following code: + +```javascript +// test.js +const config = require('@ekino/config') +console.log(config.get('service')) +console.log(config.get('host')) +console.log(config.get('port')) +``` + +If we run this script, we'll have: + +```sh +node test.js +> awesome # from base.yaml +> base.config.io # from base.yaml +> 8080 # from base.yaml + +NODE_ENV=prod node test.js +> awesome # from base.yaml +> prod.config.io # from prod.yaml +> 8081 # from prod.yaml + +NODE_ENV=prod CONF_OVERRIDES=aws node test.js +> awesome # from base.yaml +> prod.aws.config.io # from aws.yaml +> 8081 # from prod.yaml + +NODE_ENV=prod CONF_OVERRIDES=google node test.js +> awesome # from base.yaml +> prod.google.config.io # from google.yaml +> 8081 # from prod.yaml + +NODE_ENV=prod CONF_OVERRIDES=google,extra node test.js +> awesome # from base.yaml +> prod.google.config.io # from google.yaml +> 8082 # from extra.yaml +``` + +The overrides from files defined in `CONF_OVERRIDES` are loaded in the same order they are defined, +so for `CONF_OVERRIDES=google,extra`, it will load `/conf/google.yaml`, then `/conf/extra.yaml`. + +For the sake of mental health, if a file is defined twice, it will be ignored, +if you take this example: + +```sh +NODE_ENV=prod CONF_OVERRIDES=aws,prod node test.js +``` + +the second `prod` value defined inside `CONF_OVERRIDES` will be ignored as it has been already loaded +because of `NODE_ENV=prod`. + +:warning: The `env_mapping.yaml` will always take precedence over files overrides. + +### Inheritance model + +``` +base.yaml <— [.yaml] <— [.yaml] <— [env_mapping.yaml] +``` + +*All files surrounded by `[]` are optional.* + +1. Load config from `base.yaml` +2. If `NODE_ENV` is defined & `.yaml` exists, load it +3. If `CONF_OVERRIDES` is defined, load each corresponding file if it exists +4. If `env_mapping.yaml` exists and some environment variables match, override with those values [npm-image]: https://img.shields.io/npm/v/@ekino/config.svg?style=flat-square [npm-url]: https://www.npmjs.com/package/@ekino/config diff --git a/conf/base.yaml b/conf/base.yaml index 6a2c318..6d6043a 100644 --- a/conf/base.yaml +++ b/conf/base.yaml @@ -1,4 +1,12 @@ -port: 8080 +# +# This is the base config file, loaded for all tests +# +port: 8080 version: 0.0.0 -name: test-app0 -uuid: 01A0 +name: test-app0 +uuid: 01A0 +api: + credentials: + id: base-api-id + key: base-api-key + retries: 3 \ No newline at end of file diff --git a/conf/env_mapping.yaml b/conf/env_mapping.yaml index b0b4fdb..4917d4a 100644 --- a/conf/env_mapping.yaml +++ b/conf/env_mapping.yaml @@ -1,16 +1,27 @@ +# +# Defines environment mapping, loaded for all tests +# PORT: - key: port + key: port type: number + NAME: key: name + VERSION: version + ID: - key: id + key: id type: number + USE_SSL: - key: useSsl + key: useSsl type: boolean + USE_MOCKS: - key: useMocks + key: useMocks type: boolean - \ No newline at end of file + +API_RETRIES: + key: api.retries + type: number \ No newline at end of file diff --git a/conf/override_a.yaml b/conf/override_a.yaml new file mode 100644 index 0000000..dd97fb7 --- /dev/null +++ b/conf/override_a.yaml @@ -0,0 +1,6 @@ +port: 8082 +version: 0.0.2 +api: + credentials: + key: override-a-api-key + diff --git a/conf/override_b.yaml b/conf/override_b.yaml new file mode 100644 index 0000000..1c2429b --- /dev/null +++ b/conf/override_b.yaml @@ -0,0 +1,4 @@ +version: 0.0.3 +api: + credentials: + key: override-b-api-key diff --git a/conf/prod.yaml b/conf/prod.yaml index fd5c013..81211f7 100644 --- a/conf/prod.yaml +++ b/conf/prod.yaml @@ -1,3 +1,6 @@ -port: 8081 +port: 8081 version: 0.0.1 -env: prod +env: prod +api: + credentials: + key: prod-api-key diff --git a/index.js b/index.js index 949227a..8276d0b 100644 --- a/index.js +++ b/index.js @@ -5,15 +5,7 @@ const yaml = require('js-yaml') const fs = require('fs') const path = require('path') -const internals = {} - -internals.cfg = {} - -internals.confPath = process.env.NODE_CONFIG_DIR ? `${process.env.NODE_CONFIG_DIR}` : path.join(process.cwd(), 'conf') - -internals.basePath = path.join(internals.confPath, 'base.yaml') -internals.envMappingPath = path.join(internals.confPath, 'env_mapping.yaml') -internals.overridesPath = process.env.NODE_ENV ? path.join(internals.confPath, `${process.env.NODE_ENV}.yaml`) : null +const internals = { cfg: {} } /** * Get a value from the configuration. Supports dot notation (eg: "key.subkey.subsubkey")... @@ -49,27 +41,56 @@ exports.dump = () => internals.cfg /** ***** Internals **********/ /** - * Read a yaml file and convert it to json. - * WARNING : This use a sync function to read file + * Read a yaml file and convert it to javascript object. + * + * WARNING: This use a sync function to read file + * * @param {string} path * @return {Object} */ internals.read = path => { const content = fs.readFileSync(path, { encoding: 'utf8' }) let result = yaml.safeLoad(content) + return result } +/** + * Try to load a yaml file, if the file does not exist, return null. + * + * @see internals.read + * + * @param {string} path + * @return {Object|null} + */ +internals.readEventually = path => { + try { + const content = internals.read(path) + return content + } catch (e) { + if (!e || e.code !== 'ENOENT') throw e + return null + } +} + +/** + * Cast a value using given type. + * + * @param {string} type + * @param {string} value + * @returns {string|number|boolean} Casted value + */ internals.cast = (type, value) => { switch (type) { case 'number': { const result = Number(value) - if (_.isNaN(result)) throw new Error(`Config error : expected a number got ${value}`) + if (_.isNaN(result)) throw new Error(`Config error: expected a number got ${value}`) return result } case 'boolean': - if (!_.includes(['true', 'false', '0', '1'], value)) throw new Error(`Config error : expected a boolean got ${value}`) + if (!_.includes(['true', 'false', '0', '1'], value)) + throw new Error(`Config error: expected a boolean got ${value}`) return value === 'true' || value === '1' default: @@ -78,62 +99,85 @@ internals.cast = (type, value) => { } /** - * Read env variables override file and set config from env vars + * Read env variables override file and set config from env vars. + * + * @param {Object} mappings * @return {Object} */ -internals.readEnvOverrides = () => { - const result = {} +internals.getEnvOverrides = mappings => { + const overriden = {} - try { - const content = internals.read(internals.envMappingPath) - _.forOwn(content, (mapping, key) => { - if (_.isUndefined(process.env[key])) return true - - let value = process.env[key] - let mappedKey = mapping - - if (mapping.key) { - mappedKey = mapping.key - value = internals.cast(mapping.type, value) - } - _.set(result, mappedKey, value) - }) - } catch (e) { - if (!e || e.code !== 'ENOENT') throw e - } + _.forOwn(mappings, (mapping, key) => { + if (_.isUndefined(process.env[key])) return true - return result + let value = process.env[key] + let mappedKey = mapping + + if (mapping.key) { + mappedKey = mapping.key + value = internals.cast(mapping.type, value) + } + _.set(overriden, mappedKey, value) + }) + + return overriden } /** - * Return the source value if it is an array - * This function is used to customize the default output of _.mergeWith + * Return the source value if it is an array. + * This function is used to customize the default output of `_.mergeWith()`. * * @param {*} objValue: the target field content * @param {*} srcValue: the new value - * @returns {*}: return what we want as a value, or undefined to let the default behaviour kick in + * @returns {*} return what we want as a value, or undefined to let the default behaviour kick in */ -internals.customizer = (objValue, srcValue) => { - return _.isArray(srcValue) ? srcValue : undefined -} +internals.customizer = (objValue, srcValue) => (_.isArray(srcValue) ? srcValue : undefined) + +internals.merge = _.partialRight(_.mergeWith, internals.customizer) /** - * Read base file, override it with env file and finally override it with env vars + * Loads config: + * + * 1. load base.yaml + * 2. if NODE_ENV is defined and a config file matching its value exists, load it + * 3. if CONF_OVERRIDES is defined, try to load corresponding files + * 4. load env_mapping.yaml if it exists and search for overrides */ internals.load = () => { - const base = internals.read(internals.basePath) - let env = {} - if (internals.overridesPath) { - try { - env = internals.read(internals.overridesPath) - } catch (e) { - if (!e || e.code !== 'ENOENT') throw e - } + const confPath = process.env.NODE_CONFIG_DIR + ? `${process.env.NODE_CONFIG_DIR}` + : path.join(process.cwd(), 'conf') + + // load base config (required) + const baseConfig = internals.read(path.join(confPath, 'base.yaml')) + internals.cfg = Object.assign({}, baseConfig) + + // apply file overrides (optional) + let overrideFiles = [] + if (process.env.NODE_ENV) overrideFiles.push(process.env.NODE_ENV) + if (process.env.CONF_OVERRIDES) { + overrideFiles = overrideFiles.concat( + process.env.CONF_OVERRIDES.split(',').filter( + // remove garbage and prevent dupes + override => + !_.isEmpty(override) && override !== 'base' && !overrideFiles.includes(override) + ) + ) } - const envOverrides = internals.readEnvOverrides() + overrideFiles.forEach(overrideFile => { + const overridePath = path.join(confPath, `${overrideFile}.yaml`) + const override = internals.readEventually(overridePath) - internals.cfg = _.mergeWith({}, base, env, envOverrides, internals.customizer) + if (override !== null) internals.merge(internals.cfg, override) + }) + + // apply environment overrides (optional) + const envOverridesConfig = internals.readEventually(path.join(confPath, 'env_mapping.yaml')) + if (envOverridesConfig !== null) { + const envOverrides = internals.getEnvOverrides(envOverridesConfig) + internals.merge(internals.cfg, envOverrides) + } } internals.load() diff --git a/package.json b/package.json index 5e20e98..9a46b4f 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,8 @@ "prettier": "1.x.x" }, "scripts": { - "fmt": "prettier --print-width 140 --tab-width=4 --single-quote --bracket-spacing --no-semi --color --write index.js test/*.js test/**/*.js", - "check-fmt": "prettier --print-width 140 --tab-width=4 --single-quote --bracket-spacing --no-semi --list-different index.js test/*.js test/**/*.js", + "fmt": "prettier --print-width 100 --tab-width=4 --single-quote --bracket-spacing --no-semi --color --write index.js test/*.js test/**/*.js", + "check-fmt": "prettier --print-width 100 --tab-width=4 --single-quote --bracket-spacing --no-semi --list-different index.js test/*.js test/**/*.js", "test": "ava", "test-cover": "nyc ava", "coverage": "nyc report --reporter=text-lcov | coveralls", diff --git a/test/test.js b/test/test.js index 4c304a1..0c8851e 100644 --- a/test/test.js +++ b/test/test.js @@ -6,7 +6,7 @@ test.cb('I can override conf directory path with env variable NODE_CONFIG_DIR', const testPath = `${__dirname}/helpers/child.load_conf.js` const env = { NODE_CONFIG_DIR: 'test/conf/basic' } - const child = childProcess.fork(testPath, { env: env }) + const child = childProcess.fork(testPath, { env }) child.on('message', content => { t.deepEqual(content, { name: 'test-app2', port: 8082, uuid: '01A2', version: '0.0.2' }) @@ -14,47 +14,200 @@ test.cb('I can override conf directory path with env variable NODE_CONFIG_DIR', }) }) -test.cb('I can override config values with NODE_ENV config file in the following order : base, env file', t => { +test.cb( + 'I can override config values with NODE_ENV config file in the following order: base, env file', + t => { + const testPath = `${__dirname}/helpers/child.load_conf.js` + + const env = { NODE_ENV: 'prod' } + const child = childProcess.fork(testPath, { env }) + + child.on('message', content => { + t.deepEqual(content, { + name: 'test-app0', + port: 8081, + uuid: '01A0', + version: '0.0.1', + env: 'prod', + api: { + credentials: { + id: 'base-api-id', + key: 'prod-api-key' + }, + retries: 3 + } + }) + t.end() + }) + } +) + +test.cb( + 'I can override config values with env values in the following order: base, env values', + t => { + const testPath = `${__dirname}/helpers/child.load_conf.js` + + const env = { NODE_ENV: 'dev', PORT: '8083', API_RETRIES: '6' } + const child = childProcess.fork(testPath, { env }) + + child.on('message', content => { + t.deepEqual(content, { + name: 'test-app0', + port: 8083, + uuid: '01A0', + version: '0.0.0', + api: { + credentials: { + id: 'base-api-id', + key: 'base-api-key' + }, + retries: 6 + } + }) + t.end() + }) + } +) + +test.cb( + 'I can override config values with NODE_ENV config file and env values in the following order: base, env file, env values', + t => { + const testPath = `${__dirname}/helpers/child.load_conf.js` + + const env = { NODE_ENV: 'prod', PORT: '8083' } + const child = childProcess.fork(testPath, { env }) + + child.on('message', content => { + t.deepEqual(content, { + name: 'test-app0', + port: 8083, + uuid: '01A0', + version: '0.0.1', + env: 'prod', + api: { + credentials: { + id: 'base-api-id', + key: 'prod-api-key' + }, + retries: 3 + } + }) + t.end() + }) + } +) + +test.cb('I can override config values with config file defined through CONF_OVERRIDES', t => { const testPath = `${__dirname}/helpers/child.load_conf.js` - const env = { NODE_ENV: 'prod' } - const child = childProcess.fork(testPath, { env: env }) + const env = { CONF_OVERRIDES: 'override_a' } + const child = childProcess.fork(testPath, { env }) child.on('message', content => { - t.deepEqual(content, { name: 'test-app0', port: 8081, uuid: '01A0', version: '0.0.1', env: 'prod' }) + t.deepEqual(content, { + name: 'test-app0', + port: 8082, + uuid: '01A0', + version: '0.0.2', + api: { + credentials: { + id: 'base-api-id', + key: 'override-a-api-key' + }, + retries: 3 + } + }) t.end() }) }) -test.cb('I can override config values with env values in the following order : base, env values', t => { - const testPath = `${__dirname}/helpers/child.load_conf.js` - - const env = { NODE_ENV: 'dev', PORT: 8083 } - const child = childProcess.fork(testPath, { env: env }) - - child.on('message', content => { - t.deepEqual(content, { name: 'test-app0', port: 8083, uuid: '01A0', version: '0.0.0' }) - t.end() - }) -}) - -test.cb('I can override config values with NODE_ENV config file and env values in the following order : base, env file, env values', t => { - const testPath = `${__dirname}/helpers/child.load_conf.js` - - const env = { NODE_ENV: 'prod', PORT: 8083 } - const child = childProcess.fork(testPath, { env: env }) - - child.on('message', content => { - t.deepEqual(content, { name: 'test-app0', port: 8083, uuid: '01A0', version: '0.0.1', env: 'prod' }) - t.end() - }) -}) +test.cb( + 'I can override config values with multiple config files defined through CONF_OVERRIDES', + t => { + const testPath = `${__dirname}/helpers/child.load_conf.js` + + const env = { CONF_OVERRIDES: 'override_a,override_b' } + const child = childProcess.fork(testPath, { env }) + + child.on('message', content => { + t.deepEqual(content, { + name: 'test-app0', + port: 8082, + uuid: '01A0', + version: '0.0.3', + api: { + credentials: { + id: 'base-api-id', + key: 'override-b-api-key' + }, + retries: 3 + } + }) + t.end() + }) + } +) + +test.cb( + 'Environment variables mapped through env_mapping should take precedence over CONF_OVERRIDES', + t => { + const testPath = `${__dirname}/helpers/child.load_conf.js` + + const env = { CONF_OVERRIDES: 'override_a,override_b', VERSION: '0.0.4', API_RETRIES: '6' } + const child = childProcess.fork(testPath, { env }) + + child.on('message', content => { + t.deepEqual(content, { + name: 'test-app0', + port: 8082, + uuid: '01A0', + version: '0.0.4', + api: { + credentials: { + id: 'base-api-id', + key: 'override-b-api-key' + }, + retries: 6 + } + }) + t.end() + }) + } +) + +test.cb( + 'A config file occurring several times through NODE_ENV or CONF_OVERRIDES should be ignored', + t => { + const testPath = `${__dirname}/helpers/child.load_conf.js` + + const env = { NODE_ENV: 'prod', CONF_OVERRIDES: 'override_a,override_b,prod' } + const child = childProcess.fork(testPath, { env }) + + child.on('message', content => { + t.deepEqual(content, { + name: 'test-app0', + port: 8082, + uuid: '01A0', + version: '0.0.3', + env: 'prod', + api: { + credentials: { + id: 'base-api-id', + key: 'override-b-api-key' + }, + retries: 3 + } + }) + t.end() + }) + } +) test.cb('I can cast env values overrides', t => { const testPath = `${__dirname}/helpers/child.load_conf.js` const env = { PORT: 8080, NAME: 'app', ID: '12', USE_SSL: 'false', USE_MOCKS: 1 } - const child = childProcess.fork(testPath, { env: env }) + const child = childProcess.fork(testPath, { env }) child.on('message', content => { t.deepEqual(typeof content.port, 'number') @@ -70,7 +223,7 @@ test.cb('I can cast truthy boolean env values overrides', t => { const testPath = `${__dirname}/helpers/child.load_conf.js` const env = { USE_SSL: 'true', USE_MOCKS: 1 } - const child = childProcess.fork(testPath, { env: env }) + const child = childProcess.fork(testPath, { env }) child.on('message', content => { t.is(content.useSsl, true) @@ -83,7 +236,7 @@ test.cb('I can cast falsy boolean env values overrides', t => { const testPath = `${__dirname}/helpers/child.load_conf.js` const env = { USE_SSL: 'false', USE_MOCKS: 0 } - const child = childProcess.fork(testPath, { env: env }) + const child = childProcess.fork(testPath, { env }) child.on('message', content => { t.is(content.useSsl, false) @@ -96,11 +249,11 @@ test.cb('It throws an error when number cast on env value fails', t => { const testPath = `${__dirname}/helpers/child.catch_conf_errors.js` const env = { PORT: 'NotANumber' } - const child = childProcess.fork(testPath, { env: env }) + const child = childProcess.fork(testPath, { env }) child.on('message', content => { t.deepEqual(content.name, 'Error') - t.deepEqual(content.message, 'Config error : expected a number got NotANumber') + t.deepEqual(content.message, 'Config error: expected a number got NotANumber') t.end() }) }) @@ -109,11 +262,11 @@ test.cb('It throws an error when boolean string cast on env value fails', t => { const testPath = `${__dirname}/helpers/child.catch_conf_errors.js` const env = { USE_SSL: 'NotABoolean' } - const child = childProcess.fork(testPath, { env: env }) + const child = childProcess.fork(testPath, { env }) child.on('message', content => { t.deepEqual(content.name, 'Error') - t.deepEqual(content.message, 'Config error : expected a boolean got NotABoolean') + t.deepEqual(content.message, 'Config error: expected a boolean got NotABoolean') t.end() }) }) @@ -122,11 +275,11 @@ test.cb('It throws an error when boolean number cast on env value fails', t => { const testPath = `${__dirname}/helpers/child.catch_conf_errors.js` const env = { USE_MOCKS: 42 } - const child = childProcess.fork(testPath, { env: env }) + const child = childProcess.fork(testPath, { env }) child.on('message', content => { t.deepEqual(content.name, 'Error') - t.deepEqual(content.message, 'Config error : expected a boolean got 42') + t.deepEqual(content.message, 'Config error: expected a boolean got 42') t.end() }) }) @@ -135,7 +288,7 @@ test.cb('It throws an error when env_mapping file is not yaml valid', t => { const testPath = `${__dirname}/helpers/child.catch_conf_errors.js` const env = { NODE_CONFIG_DIR: 'test/conf/malformatted_env_mapping_file', PORT: '8081' } - const child = childProcess.fork(testPath, { env: env }) + const child = childProcess.fork(testPath, { env }) child.on('message', content => { t.deepEqual(content.name, 'YAMLException') @@ -147,7 +300,7 @@ test.cb('It throws an error when base file is not yaml valid', t => { const testPath = `${__dirname}/helpers/child.catch_conf_errors.js` const env = { NODE_CONFIG_DIR: 'test/conf/malformatted_base_file' } - const child = childProcess.fork(testPath, { env: env }) + const child = childProcess.fork(testPath, { env }) child.on('message', content => { t.deepEqual(content.name, 'YAMLException') @@ -159,7 +312,7 @@ test.cb('It throws an error when env file is not yaml valid', t => { const testPath = `${__dirname}/helpers/child.catch_conf_errors.js` const env = { NODE_CONFIG_DIR: 'test/conf/malformatted_env_file', NODE_ENV: 'dev' } - const child = childProcess.fork(testPath, { env: env }) + const child = childProcess.fork(testPath, { env }) child.on('message', content => { t.deepEqual(content.name, 'YAMLException') @@ -171,7 +324,7 @@ test.cb('It throws an error when no base file', t => { const testPath = `${__dirname}/helpers/child.catch_conf_errors.js` const env = { NODE_CONFIG_DIR: 'test/conf/no_base_file', NODE_ENV: 'dev' } - const child = childProcess.fork(testPath, { env: env }) + const child = childProcess.fork(testPath, { env }) child.on('message', content => { t.deepEqual(content.name, 'Error')