diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..34c1576 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# CHANGELOG + +### Version 0.5.0 + +* `nconf.stores.*` is now `nconf.*` +* `nconf.stores` now represents the set of nconf.* Store instances on the nconf object. +* Added `nconf.argv()`, `nconf.env()`, `nconf.file()`, `nconf.overrides()`, `nconf.defaults()`. +* `nconf.system` no longer exists. The `nconf.System` store has been broken into `nconf.Argv`, `nconf.Env` and `nconf.Literal` +* Fixed bugs in hierarchical configuration loading. \ No newline at end of file diff --git a/README.md b/README.md index 60a8728..10a63fb 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Hierarchical node.js configuration with files, environment variables, command-line arguments, and atomic object merging. -## Getting started +## Example 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 `:`. Lets dive right into sample usage: ``` js @@ -10,9 +10,18 @@ Using nconf is easy; it is designed to be a simple key-value store with support nconf = require('nconf'); // - // Setup nconf to use the 'file' store and set a couple of values; + // Setup nconf to use (in-order): + // 1. Command-line arguments + // 2. Environment variables + // 3. A file located at 'path/to/config.json' + // + nconf.argv() + .env() + .file({ file: 'path/to/config.json' }); + + // + // Set a few variables on `nconf`. // - nconf.add('file', { file: 'path/to/your/config.json' }); nconf.set('database:host', '127.0.0.1'); nconf.set('database:port', 5984); @@ -20,7 +29,9 @@ Using nconf is easy; it is designed to be a simple key-value store with support // Get the entire database object from nconf. This will output // { host: '127.0.0.1', port: 5984 } // - console.dir(nconf.get('database')); + console.log('foo: ' + nconf.get('foo')); + console.log('NODE_ENV: ' + nconf.get('NODE_ENV')); + console.log('database: ' + nconf.get('database')); // // Save the configuration object to disk @@ -32,14 +43,62 @@ Using nconf is easy; it is designed to be a simple key-value store with support }); ``` +If you run the above script: + +``` bash + $ NODE_ENV=production sample.js --foo bar +``` + +The output will be: + +``` + foo: bar + NODE_ENV: production + database: { host: '127.0.0.1', port: 5984 } +``` + ## Hierarchical configuration -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 some sane defaults (in-order): +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.** Lets take a look at the options available to you - 1. Manually set overrides - 2. Command-line arguments - 3. Environment variables - 4. Any additional user stores (in the order they were added) + 1. **nconf.argv(options)** Loads `process.argv` using optimist. If `options` is supplied it is passed along to optimist. + 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 + var nconf = require('nconf'); + + // + // 1. any overrides + // + nconf.overrides({ + 'always': 'be this value' + }); + + // + // 2. `process.env` + // 3. `process.argv` + // + nconf.env().argv(); + + // + // 4. Values in `config.json` + // + nconf.file({ file: 'config.json' }); + + // + // 5. Any default values + // + nconf.defaults({ + 'if nothing else': 'use this value' + }); +``` + +## API Documentation The top-level of `nconf` is an instance of the `nconf.Provider` abstracts this all for you into a simple API. @@ -47,8 +106,8 @@ The top-level of `nconf` is an instance of the `nconf.Provider` abstracts this a Adds a new store with the specified `name` and `options`. If `options.type` is not set, then `name` will be used instead: ``` js + nconf.add('user', { type: 'file', file: '/path/to/userconf.json' }); nconf.add('global', { type: 'file', file: '/path/to/globalconf.json' }); - nconf.add('userconf', { type: 'file', file: '/path/to/userconf.json' }); ``` ### nconf.use(name, options) @@ -73,30 +132,6 @@ Removes the store with the specified `name.` The configuration stored at that le nconf.remove('file'); ``` -## Working with Configuration -`nconf` will traverse the set of stores that you have setup in-order to ensure that the value in the store of the highest priority is used. For example to setup following sample configuration: - -1. Command-line arguments -2. Environment variables -3. User configuration -3. Global configuration - -``` js - var nconf = require('nconf'); - - // - // Read in command-line arugments and environment variables - // - nconf.argv = nconf.env = true; - - // - // Setup the `user` store followed by the `global` store. Note that - // order is significant in these operations. - // - nconf.add('user', { file: 'path/to/user-config.json' }); - nconf.add('global', { file: 'path/to/global-config.json' }) -``` - ## Storage Engines ### Memory @@ -106,32 +141,40 @@ A simple in-memory storage engine that stores a nested JSON representation of th nconf.use('memory'); ``` -### System -Based on the Memory store, but exposes hooks into manual overrides, command-line arguments, and environment variables (in that order of priority). Every instance of `nconf.Provider`, including the top-level `nconf` object itself already has a `System` store at the top-level, so configuring it only requires setting properties +### Argv +Responsible for loading the values parsed from `process.argv` by `optimist` into the configuration hierarchy. ``` js // - // `nconf.get(awesome)` will always return true regardless of - // command-line arguments or environment variables. + // Can optionally also be an object literal to pass to `optimist`. // - nconf.overrides = { awesome: true }; - + nconf.argv(options); +``` + +### Env +Responsible for loading the values parsed from `process.env` into the configuration hierarchy. + +``` js // - // Can also be an object literal to pass to `optimist`. + // Can optionally also be an Array of values to limit process.env to. // - nconf.argv = true; - - // - // Can also be an array of variable names to restrict loading to. - // - nconf.env = true; + nconf.env(['only', 'load', 'these', 'values', 'from', 'process.env']); +``` + +### 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' + }); ``` ### File 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 with the exception of `.save()` and `.load()` which take callback functions. 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. ``` js - nconf.use('file', { file: 'path/to/your/config.json' }); + nconf.file({ file: 'path/to/your/config.json' }); ``` 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.