2020-06-02 10:21:30 +00:00
# nconf-lite
2015-07-30 00:12:09 +00:00
2021-06-22 19:25:00 +00:00
Nconf-lite is a complete re-written design of original nconf with zero dependancy, tiny and fast while maintaining most if not all of the documented features of the old nconf.
2015-07-30 00:12:09 +00:00
2021-06-22 19:25:00 +00:00
It is a hierarchical node.js configuration with files, environment variables, and atomic object merging.
Compared to nconf running at 952KB with over 220 files *installed* , nconf-lite is clocking at measly 42KB with only 11 files of easily reviewable code and a ton more unit test, testing every micro functionality.
2011-04-02 08:59:18 +00:00
2011-11-24 05:26:32 +00:00
## Example
2015-01-20 18:41:46 +00:00
Using nconf is easy; it is designed to be a simple key-value store with support for both local and remote storage. Keys are namespaced and delimited by `:` . Let's dive right into sample usage:
2011-04-02 08:59:18 +00:00
2011-05-20 03:12:56 +00:00
``` js
2021-06-22 19:25:00 +00:00
import Nconf from 'nconf-lite'
const nconf = new Nconf()
2012-08-07 05:52:29 +00:00
2011-04-02 08:59:18 +00:00
//
2012-08-07 05:52:29 +00:00
// Setup nconf to use (in-order):
2011-11-24 05:26:32 +00:00
// 2. Environment variables
// 3. A file located at 'path/to/config.json'
//
2020-06-02 10:21:30 +00:00
nconf.env()
2015-09-20 07:34:44 +00:00
.file({ file: 'path/to/config.json' });
2012-08-07 05:52:29 +00:00
2011-11-24 05:26:32 +00:00
//
// Set a few variables on `nconf` .
2011-04-02 08:59:18 +00:00
//
nconf.set('database:host', '127.0.0.1');
nconf.set('database:port', 5984);
2012-08-07 05:52:29 +00:00
2011-04-02 08:59:18 +00:00
//
2011-09-19 01:34:45 +00:00
// Get the entire database object from nconf. This will output
// { host: '127.0.0.1', port: 5984 }
2011-04-02 08:59:18 +00:00
//
2011-11-24 05:26:32 +00:00
console.log('foo: ' + nconf.get('foo'));
console.log('NODE_ENV: ' + nconf.get('NODE_ENV'));
console.log('database: ' + nconf.get('database'));
2012-08-07 05:52:29 +00:00
2011-04-02 08:59:18 +00:00
//
// Save the configuration object to disk
//
2021-06-22 19:25:00 +00:00
nconf.save()
2011-05-20 03:12:56 +00:00
```
2011-04-02 08:59:18 +00:00
2011-11-24 05:26:32 +00:00
If you run the above script:
``` bash
2020-06-02 10:21:30 +00:00
$ NODE_ENV=production sample.js
2011-11-24 05:26:32 +00:00
```
The output will be:
```
NODE_ENV: production
database: { host: '127.0.0.1', port: 5984 }
```
2011-09-19 01:34:45 +00:00
## Hierarchical configuration
2015-07-09 18:07:35 +00:00
Configuration management can get complicated very quickly for even trivial applications running in production. `nconf` addresses this problem by enabling you to setup a hierarchy for different sources of configuration with no defaults. **The order in which you attach these configuration sources determines their priority in the hierarchy.** Let's take a look at the options available to you
2011-11-24 05:26:32 +00:00
2. **nconf.env(options)** Loads `process.env` into the hierarchy.
3. **nconf.file(options)** Loads the configuration data at options.file into the hierarchy.
4. **nconf.defaults(options)** Loads the data in options.store into the hierarchy.
5. **nconf.overrides(options)** Loads the data in options.store into the hierarchy.
A sane default for this could be:
``` js
2021-06-22 19:25:00 +00:00
import Nconf from 'nconf-lite'
const nconf = new Nconf()
2012-08-07 05:52:29 +00:00
2011-11-24 05:26:32 +00:00
//
// 1. any overrides
//
nconf.overrides({
'always': 'be this value'
});
2012-08-07 05:52:29 +00:00
2011-11-24 05:26:32 +00:00
//
// 2. `process.env`
//
2020-06-02 10:21:30 +00:00
nconf.env();
2012-08-07 05:52:29 +00:00
2011-11-24 05:26:32 +00:00
//
2012-07-10 05:50:18 +00:00
// 4. Values in `config.json`
2011-11-24 05:26:32 +00:00
//
2012-07-10 05:50:18 +00:00
nconf.file('/path/to/config.json');
//
// Or with a custom name
2014-06-18 00:56:42 +00:00
// Note: A custom key must be supplied for hierarchy to work if multiple files are used.
2012-07-10 05:50:18 +00:00
//
nconf.file('custom', '/path/to/config.json');
2011-11-24 05:26:32 +00:00
//
// 5. Any default values
//
nconf.defaults({
'if nothing else': 'use this value'
});
```
2011-09-19 01:34:45 +00:00
2011-11-24 05:26:32 +00:00
## API Documentation
2011-09-19 01:34:45 +00:00
2017-10-21 20:42:24 +00:00
### nconf.any(names, callback)
2017-11-13 04:11:01 +00:00
Given a set of key names, gets the value of the first key found to be truthy. The key names can be given as separate arguments
2017-10-21 20:42:24 +00:00
or as an array. If the last argument is a function, it will be called with the result; otherwise, the value is returned.
``` js
//
// Get one of 'NODEJS_PORT' and 'PORT' as a return value
//
2021-06-22 19:25:00 +00:00
let port = nconf.any('NODEJS_PORT', 'PORT');
2017-10-21 20:42:24 +00:00
```
2021-06-22 19:25:00 +00:00
### nconf.use(name)
Fetch a specific store with the specified name.
2011-09-19 01:34:45 +00:00
``` js
//
// Load a file store onto nconf with the specified settings
//
2021-06-22 19:25:00 +00:00
nconf.file('custom', '/path/to/config.json');
2011-09-19 01:34:45 +00:00
//
2021-06-22 19:25:00 +00:00
// Grab the instance and set it to be readonly
2011-09-19 01:34:45 +00:00
//
2021-06-22 19:25:00 +00:00
nconf.use('custom').readOnly = true
2016-05-14 19:55:23 +00:00
```
2016-01-27 17:29:26 +00:00
### nconf.required(keys)
Declares a set of string keys to be mandatory, and throw an error if any are missing.
2016-05-14 19:55:23 +00:00
``` js
2016-01-27 17:29:26 +00:00
nconf.defaults({
keya: 'a',
});
nconf.required(['keya', 'keyb']);
// Error: Missing required keys: keyb
2011-09-19 01:34:45 +00:00
```
2017-11-04 04:34:27 +00:00
You can also chain `.required()` calls when needed. for example when a configuration depends on another configuration store
```js
config
.env()
.required([ 'STAGE']) //here you should have STAGE otherwise throw an error
.file( 'stage', path.resolve( 'configs', 'stages', config.get( 'STAGE' ) + '.json' ) )
.required([ 'OAUTH:redirectURL']) // here you should have OAUTH:redirectURL, otherwise throw an error
.file( 'oauth', path.resolve( 'configs', 'oauth', config.get( 'OAUTH:MODE' ) + '.json' ) )
.file( 'app', path.resolve( 'configs', 'app.json' ) )
.required([ 'LOGS_MODE']) // here you should haveLOGS_MODE, otherwise throw an error
2021-06-22 19:25:00 +00:00
.literal( 'logs', require( path.resolve( 'configs', 'logs', config.get( 'LOGS_MODE' ) + '.js') ))
2017-11-04 04:34:27 +00:00
.defaults( defaults );
```
2011-09-19 01:34:45 +00:00
2011-04-02 08:59:18 +00:00
## Storage Engines
### Memory
2011-04-02 09:13:34 +00:00
A simple in-memory storage engine that stores a nested JSON representation of the configuration. To use this engine, just call `.use()` with the appropriate arguments. All calls to `.get()` , `.set()` , `.clear()` , `.reset()` methods are synchronous since we are only dealing with an in-memory object.
2011-05-20 03:12:56 +00:00
2012-08-07 05:52:29 +00:00
``` js
2011-04-02 09:13:34 +00:00
nconf.use('memory');
2011-05-20 03:12:56 +00:00
```
2011-04-02 08:59:18 +00:00
2011-11-24 05:26:32 +00:00
### Env
Responsible for loading the values parsed from `process.env` into the configuration hierarchy.
2017-10-26 02:57:58 +00:00
By default, the env variables values are loaded into the configuration as strings.
#### Options
##### `lowerCase: {true|false}` (default: `false`)
Convert all input keys to lower case. Values are not modified.
If this option is enabled, all calls to `nconf.get()` must pass in a lowercase string (e.g. `nconf.get('port')` )
##### `parseValues: {true|false}` (default: `false`)
Attempt to parse well-known values (e.g. 'false', 'true', 'null', 'undefined', '3', '5.1' and JSON values)
into their proper types. If a value cannot be parsed, it will remain a string.
##### `transform: function(obj)`
Pass each key/value pair to the specified function for transformation.
The input `obj` contains two properties passed in the following format:
```
{
key: '< string > ',
value: '< string > '
}
```
The transformation function may alter both the key and the value.
The function may return either an object in the asme format as the input or a value that evaluates to false.
If the return value is falsey, the entry will be dropped from the store, otherwise it will replace the original key/value.
*Note: If the return value doesn't adhere to the above rules, an exception will be thrown.*
#### Examples
2011-11-24 05:26:32 +00:00
``` js
2011-09-19 01:34:45 +00:00
//
2011-11-24 05:26:32 +00:00
// Can optionally also be an Array of values to limit process.env to.
2011-09-19 01:34:45 +00:00
//
2012-08-07 05:52:29 +00:00
nconf.env(['only', 'load', 'these', 'values', 'from', 'process.env']);
2012-06-21 07:04:06 +00:00
//
// Can also specify a separator for nested keys (instead of the default ':')
//
2021-06-22 19:25:00 +00:00
nconf.env({ separator: '__' });
2012-06-21 07:18:22 +00:00
// Get the value of the env variable 'database__host'
2021-06-22 19:25:00 +00:00
let dbHost = nconf.get('database:host');
2012-06-21 07:18:22 +00:00
2017-08-16 03:58:13 +00:00
//
2017-11-13 04:11:01 +00:00
// Can also lowerCase keys.
// Especially handy when dealing with environment variables which are usually
2020-06-02 10:21:30 +00:00
// uppercased.
2017-08-16 03:58:13 +00:00
//
// Given an environment variable PORT=3001
nconf.env();
2021-06-22 19:25:00 +00:00
let port = nconf.get('port') // undefined
2017-08-16 03:58:13 +00:00
nconf.env({ lowerCase: true });
2021-06-22 19:25:00 +00:00
let port = nconf.get('port') // 3001
2017-08-16 03:58:13 +00:00
2012-06-21 07:18:22 +00:00
//
2014-01-10 00:26:07 +00:00
// Or use all options
2012-06-21 07:18:22 +00:00
//
2012-06-21 07:04:06 +00:00
nconf.env({
separator: '__',
2014-01-10 00:26:07 +00:00
match: /^whatever_matches_this_will_be_whitelisted/
2017-08-16 03:58:13 +00:00
whitelist: ['database__host', 'only', 'load', 'these', 'values', 'if', 'whatever_doesnt_match_but_is_whitelisted_gets_loaded_too'],
2017-10-21 19:39:16 +00:00
lowerCase: true,
2017-10-26 02:57:58 +00:00
parseValues: true,
transform: function(obj) {
if (obj.key === 'foo') {
obj.value = 'baz';
}
return obj;
}
2012-06-21 07:18:22 +00:00
});
2021-06-22 19:25:00 +00:00
let dbHost = nconf.get('database:host');
2011-11-24 05:26:32 +00:00
```
### Literal
Loads a given object literal into the configuration hierarchy. Both `nconf.defaults()` and `nconf.overrides()` use the Literal store.
``` js
nconf.defaults({
'some': 'default value'
});
2011-09-19 01:34:45 +00:00
```
2011-04-02 08:59:18 +00:00
### File
2021-06-22 19:25:00 +00:00
Based on the Memory store, but provides additional methods `.save()` and `.load()` which allow you to read your configuration to and from file. As with the Memory store, all method calls are synchronous includ `.save()` and `.load()` .
2015-09-20 07:34:44 +00:00
It is important to note that setting keys in the File engine will not be persisted to disk until a call to `.save()` is made. Note a custom key must be supplied as the first parameter for hierarchy to work if multiple files are used.
2011-04-02 09:13:34 +00:00
2011-05-20 03:12:56 +00:00
``` js
2012-03-02 18:59:06 +00:00
nconf.file('path/to/your/config.json');
// add multiple files, hierarchically. notice the unique key for each file
nconf.file('user', 'path/to/your/user.json');
nconf.file('global', 'path/to/your/global.json');
2021-06-22 19:25:00 +00:00
// Set a variable in the user store and save it
nconf.user('user').set('some:variable', true)
nconf.user('user').save()
2011-05-20 03:12:56 +00:00
```
2011-04-02 09:13:34 +00:00
The file store is also extensible for multiple file formats, defaulting to `JSON` . To use a custom format, simply pass a format object to the `.use()` method. This object must have `.parse()` and `.stringify()` methods just like the native `JSON` object.
2011-04-02 08:59:18 +00:00
2014-01-16 22:05:05 +00:00
If the file does not exist at the provided path, the store will simply be empty.
2015-09-20 07:34:44 +00:00
#### Encrypting file contents
2021-06-22 19:25:00 +00:00
Encryption and decrypting file contents using the `secure` option:
2015-09-20 07:34:44 +00:00
``` js
nconf.file('secure-file', {
file: 'path/to/secure-file.json',
secure: {
secret: 'super-secretzzz-keyzz',
alg: 'aes-256-ctr'
}
})
```
2019-05-16 03:27:38 +00:00
This will encrypt each key using [`crypto.createCipheriv` ](https://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv_options ), defaulting to `aes-256-ctr` . The encrypted file contents will look like this:
2015-09-20 07:34:44 +00:00
```
{
"config-key-name": {
"alg": "aes-256-ctr", // cipher used
2019-05-16 03:27:38 +00:00
"value": "af07fbcf", // encrypted contents
"iv": "49e7803a2a5ef98c7a51a8902b76dd10" // initialization vector
2015-09-20 07:34:44 +00:00
},
"another-config-key": {
"alg": "aes-256-ctr", // cipher used
2019-05-16 03:27:38 +00:00
"value": "e310f6d94f13", // encrypted contents
"iv": "b654e01aed262f37d0acf200be193985" // initialization vector
2015-09-20 07:34:44 +00:00
},
}
```
2011-11-21 00:59:33 +00:00
## Installation
2016-05-14 19:55:23 +00:00
``` bash
2021-06-22 19:25:00 +00:00
npm install nconf-lite --save
2011-05-20 03:12:56 +00:00
```
2011-04-02 08:59:18 +00:00
## Run Tests
Tests are written in vows and give complete coverage of all APIs and storage engines.
2011-05-20 03:12:56 +00:00
2011-09-19 01:34:45 +00:00
``` bash
$ npm test
2011-05-20 03:12:56 +00:00
```
2011-04-02 08:59:18 +00:00
2021-06-22 19:25:00 +00:00
#### Original author: [Charlie Robbins](http://nodejitsu.com)
#### Rewriter of all that garbage: TheThing
2011-11-21 00:59:33 +00:00
#### License: MIT
2011-07-08 21:01:22 +00:00
2021-06-22 19:25:00 +00:00
[0]: http://github.com/nfp-projects/nconf-lite