Compare commits
351 Commits
Author | SHA1 | Date |
---|---|---|
Jonatan Nilsson | 296a65dfe1 | |
Jonatan Nilsson | 2ee285e1c4 | |
Jonatan Nilsson | 129e50367d | |
Jonatan Nilsson | f43d81a2cd | |
Jonatan Nilsson | fa46b3b043 | |
Jonatan Nilsson | 863fec827d | |
Jonatan Nilsson | 98980c3453 | |
Jonatan Nilsson | 1014cdec86 | |
Jonatan Nilsson | 1104c0d3ad | |
Jonatan Nilsson | 44a22ce6dd | |
Jonatan Nilsson | b824493aa6 | |
Jonatan Nilsson | 2f66137a81 | |
Jonatan Nilsson | c8a8d29d63 | |
Jonatan Nilsson | 455103a330 | |
renovate[bot] | aad2c1e449 | |
renovate[bot] | ee8e89c1b0 | |
renovate[bot] | 0ee6938568 | |
Eric Bickle | 7d625086ca | |
Eric Bickle | 85edc9afad | |
Indospace.io | 20e00efd6c | |
renovate[bot] | e6f27f5d2c | |
Matt Hamann | d582066743 | |
renovate[bot] | 10318c0098 | |
indexzero | 48c92ce989 | |
indexzero | 52afef5218 | |
Charlie Robbins | 75641ffaee | |
Matt Hamann | 1bb9d091f1 | |
Adrien Becchis | b8686aeff0 | |
Matt Hamann | 17376d4d17 | |
louis-murray | 391665cc38 | |
Austin Burdine | 6c5ba64db6 | |
Adrien Becchis | c1e15681db | |
bryce-gibson | b6699aba2d | |
Adrien Becchis | 467ab753c8 | |
Adrien Becchis | e5db2ef6d7 | |
Ahmed Ayoub | 3607767f90 | |
Matt Hamann | bac910a6df | |
Adrien Becchis | 2bdf7e1a32 | |
Adrien Becchis | b9321b200a | |
Matt Hamann | 81ce0be01e | |
Augusto Franzoia | b1ee63cfa4 | |
Matt Hamann | 9f70ba148f | |
Matt Hamann | 8afcf991eb | |
Adrien Becchis | b41c505c6e | |
Matt Hamann | 52e0a3566e | |
AdrieanKhisbe | fa215a44f1 | |
AdrieanKhisbe | 802a8d623f | |
Nicolas Deveaud | 3e26bb2756 | |
Matt Hamann | 856fdf8dff | |
Matt Hamann | b9c345bf96 | |
Matt Hamann | 35088a3313 | |
Matt Hamann | ca10d0eaf8 | |
Brian Harrington | bfb0220fe1 | |
Matt Hamann | 532ac9cc57 | |
Matt Hamann | b8402d4eab | |
Matt Hamann | f46c449a9e | |
Matt Hamann | 552300a687 | |
evoye | 5e8a34d6cf | |
Chris Manson | 608b607782 | |
Charlie Robbins | 0c5774fec7 | |
Charlie Robbins | 011be49a5c | |
Charter Jacobson | d70b6a0335 | |
Jan Klosinski | 392c6022c9 | |
Jarrett Cruger | 3d4e589578 | |
Charlie Robbins | b065c4ccd9 | |
Jarrett Cruger | 4431c33162 | |
Jarrett Cruger | 54cab2059a | |
Charlie Robbins | f554382435 | |
Jarrett Cruger | b447268097 | |
Jarrett Cruger | 3d4682a62f | |
Mark Oberemk | de551d42ec | |
Charlie Robbins | 4a59c9b577 | |
Charlie Robbins | e58d55429d | |
AdrieanKhisbe | c242f777a6 | |
AdrieanKhisbe | c8dbede0ca | |
AdrieanKhisbe | bdecdc29cf | |
Wojtek Turyn | 5d6e236b73 | |
Wojtek Turyn | 37a84ae8df | |
indexzero | ddee9bc8f5 | |
indexzero | 86bfd7c5bc | |
indexzero | ff0f174520 | |
indexzero | 11b2448471 | |
indexzero | 438a2c8ef5 | |
indexzero | ebd8e48342 | |
indexzero | be085c9ad5 | |
indexzero | 0922563593 | |
Charlie Robbins | e503718468 | |
Charlie Robbins | d4ebf49908 | |
indexzero | 4b5030dbc2 | |
Rob Rodriguez | a3589fab95 | |
Rob Rodriguez | 51653e6486 | |
indexzero | 2030144d88 | |
indexzero | 9dbed2d2cd | |
indexzero | 0358545ae5 | |
indexzero | 04c0f3a001 | |
indexzero | d2b3561e09 | |
indexzero | 442d2b4233 | |
indexzero | 2de2bc0b66 | |
Jarrett Cruger | 4c07028e40 | |
Jarrett Cruger | 75cea11f62 | |
Jarrett Cruger | 394286cd16 | |
Jarrett Cruger | 54f2287dd8 | |
Jarrett Cruger | 38cade0fc2 | |
Jarrett Cruger | 32aabcab69 | |
Jarrett Cruger | 8332f5a343 | |
Christian Murphy | 5d95f13eb0 | |
Joseph Page | 7d6be3265b | |
Joseph Page | abeeca0d5f | |
Joseph Page | d252288dae | |
Christian Murphy | be0ee00b2a | |
Christian Murphy | 59056fe364 | |
Joseph Page | a2b812f704 | |
Joseph Page | 32d560c95d | |
Christian Murphy | 80195744af | |
indexzero | c2b8b97778 | |
Remy Sharp | 3c11ef50e5 | |
Olivier Lalonde | 8a21ef36d5 | |
indexzero | 372521b124 | |
Jarrett Cruger | 8afdf63497 | |
Nick Heiner | 89dff39d55 | |
Pierre Beaujeu | 339e59afd5 | |
Christian Murphy | a65e1a3317 | |
Christian Murphy | a82b53941d | |
Christian Murphy | 80ec01b91d | |
Gilad Peleg | e5b33ceb05 | |
Jarrett Cruger | d335b5a0f5 | |
Nick Heiner | 6d86950914 | |
Jarrett Cruger | dc6aed2050 | |
Jarrett Cruger | 87a3b82418 | |
Jarrett Cruger | 6271cdb35d | |
indexzero | f0d5b6eb30 | |
indexzero | a2a132181a | |
indexzero | 352f07559a | |
indexzero | af0e9fb7e7 | |
indexzero | 09342555ba | |
indexzero | 8d5fb25701 | |
Charlie Robbins | 5502f2cf98 | |
Charlie Robbins | 2496f59994 | |
indexzero | f07bc40d64 | |
Charlie Robbins | d5bd26c0b6 | |
indexzero | 0b8aa903c7 | |
Charlie Robbins | c6d8f5d140 | |
indexzero | f771500266 | |
indexzero | ffce2cbec1 | |
Charlie Robbins | a3404b4062 | |
Charlie Robbins | 7b01b46313 | |
Charlie Robbins | 51a4fea561 | |
Charlie Robbins | ddd4b616ee | |
Charlie Robbins | 1602a9e1a3 | |
Mitchell McKenna | 6301d7d9c6 | |
Chris Manson | f69e43a423 | |
Martin Heidegger | c8b6c98c7a | |
Christopher Jeffrey | 8105c761ad | |
Jarrett Cruger | 999c6fbc6e | |
Christopher Jeffrey | 2241a36789 | |
Jarrett Cruger | 1bd1561cdd | |
Christopher Jeffrey | 0bb89ee2b4 | |
Gabe Gorelick | 43505a53ae | |
Jarrett Cruger | 05d73de3d0 | |
Tommy Stanton | 79b9b84300 | |
Tommy Stanton | 3a7b788e35 | |
Alexey Simonenko | 9891814b27 | |
joaoafrmartins | 120f5f0a4b | |
joaoafrmartins | 681fd2f6b4 | |
Jarrett Cruger | 022b9bc507 | |
Jarrett Cruger | 9aa33b565a | |
Jarrett Cruger | 92311c81c3 | |
Jarrett Cruger | c713936e8d | |
Jarrett Cruger | cd81efac7e | |
Jarrett Cruger | 5f148d5aa5 | |
midknight41 | 6c1eb5e917 | |
midknight41 | ccd609c1c3 | |
midknight41 | 5546469061 | |
midknight41 | 6641ed234a | |
midknight41 | 2ce8aea8fc | |
midknight41 | f7733c1719 | |
midknight41 | 24f77a0edd | |
midknight41 | 29f1ca281b | |
Charlie Robbins | 62589145f3 | |
Marcin Floryan | ada15db9e3 | |
Marcin Floryan | 0135d95a06 | |
José F. Romaniello | 039057c730 | |
Johnny Domino | b73b0e1a37 | |
Johnny Domino | 4894c8fcf7 | |
Charlie Robbins | 818526ca62 | |
Michael Schoonmaker | 5d2ebfbe9f | |
indexzero | d77c55d4ba | |
Michael Hart | bb57c497d3 | |
indexzero | aec2b4eb46 | |
Charlie Robbins | e26f1af48c | |
indexzero | 60456186d7 | |
indexzero | 0d795ecf81 | |
indexzero | f19f0b6c39 | |
Maciej Małecki | bcbaf3a133 | |
Maciej Małecki | 8b65e195eb | |
Michael Schoonmaker | ed41c51850 | |
Pavan Kumar Sunkara | 2ba437807a | |
Christian Tellnes | 8e987b8d3d | |
Bradley Meck | f9b24f1aa6 | |
Bradley Meck | da39d3cac3 | |
Bradley Meck | f21557e783 | |
Bradley Meck | 7421836387 | |
Bradley Meck | 683f78918c | |
Joshua Holbrook | ec9a13e901 | |
Ethan Winn | 0f092ab5a4 | |
indexzero | 7279bc11b3 | |
indexzero | d96d2544bc | |
indexzero | 7e8d9d6bce | |
indexzero | 04e22303bd | |
indexzero | c7c6b6f6ef | |
indexzero | 30734301e7 | |
indexzero | 8b53c12729 | |
indexzero | 80a79733d3 | |
indexzero | 7515f66572 | |
indexzero | eeddb70f20 | |
Pavan Kumar Sunkara | 6dd2351991 | |
Michael Hart | 9aaafc5a22 | |
Michael Hart | 3c08fad1c9 | |
Michael Hart | e15f787940 | |
Michael Hart | 92d4e9ea14 | |
Michael Hart | 8921d0502e | |
Michael Hart | 6cbc323005 | |
Michael Hart | 26d81e8dca | |
Joshua Holbrook | 6b1b019353 | |
Christian Tellnes | 83440f9956 | |
Maciej Małecki | 87b0dd01c9 | |
Christian Howe | 1f67d35305 | |
Jonathan Stewmon | 6353d028f7 | |
Russell Frank | d3e68976c8 | |
Russell Frank | 94bdb7dbd8 | |
Russell Frank | 36e061c4bd | |
Pavan Kumar Sunkara | 29eb5f905d | |
Jordan Harband | 6ce0b7aef3 | |
Maciej Małecki | b3699314cf | |
Maciej Małecki | d8c4749335 | |
indexzero | 464af417fe | |
indexzero | 6a6e092062 | |
indexzero | 6242caafda | |
indexzero | d0a91219ec | |
indexzero | 9e9e37bb84 | |
Jonathan Stewmon | fdb73f007b | |
Jonathan Stewmon | a216336290 | |
Jonathan Stewmon | 6b6bf85802 | |
Jonathan Stewmon | 5c43d546d1 | |
Jonathan Stewmon | 2804b1fb37 | |
Maciej Małecki | e0e070ab28 | |
Maciej Małecki | 963387cfd4 | |
Maciej Małecki | d5ce1ed68f | |
Pavan Kumar Sunkara | cf9889ea81 | |
indexzero | 62cb7fb3d9 | |
indexzero | 6c720ee109 | |
indexzero | 4643a14a5c | |
indexzero | 90b029782e | |
indexzero | 53d854a789 | |
indexzero | b658f68a89 | |
indexzero | a9c354032b | |
indexzero | f4f1fdf464 | |
indexzero | bbcb2712f1 | |
indexzero | 021850a14d | |
indexzero | 0fbc9a2722 | |
indexzero | 16a18bffe6 | |
indexzero | c3cebe7cb4 | |
indexzero | 78ce55602f | |
indexzero | 1aa2f1f315 | |
Sander Tolsma | 47a56ccb5a | |
indexzero | c3c315d648 | |
Marak Squires | 2c1ef7118c | |
Marak Squires | 223ad35ae2 | |
Maciej Małecki | 1b258bf5b3 | |
Maciej Małecki | ef3222e7ab | |
indexzero | f4723e9654 | |
Maciej Małecki | 2475d06cb2 | |
Maciej Małecki | bbc5885fc1 | |
Maciej Małecki | 51700cae88 | |
Maciej Małecki | 07f8c3e558 | |
Maciej Małecki | bab96b045a | |
indexzero | b96151e617 | |
Joshua Holbrook | d8a30203ce | |
indexzero | 2e33082f0b | |
indexzero | 86e22cb927 | |
indexzero | a2464d244b | |
indexzero | e243b0befe | |
indexzero | d0aee0d451 | |
indexzero | 0234e17804 | |
indexzero | d334d07b6e | |
indexzero | a490c7729b | |
indexzero | 0addce424d | |
indexzero | c4c8d7b76f | |
indexzero | f867e749b9 | |
indexzero | 1ef5797e83 | |
indexzero | 7ef9b11d33 | |
indexzero | a0638805ce | |
indexzero | da2da7aea8 | |
indexzero | 2bda7b6216 | |
indexzero | 54ea0950c2 | |
indexzero | e631d239d5 | |
indexzero | 8a3172868e | |
indexzero | 2e47d027ce | |
indexzero | 954b5fdc2e | |
indexzero | fb392ddc51 | |
indexzero | e8904e95c6 | |
indexzero | a6533aa7bf | |
indexzero | add8922c04 | |
indexzero | 57f0742455 | |
indexzero | b6adab2825 | |
indexzero | 8620e6ba91 | |
indexzero | 49a1a6dea3 | |
indexzero | d485f5edde | |
indexzero | 7e4623ec46 | |
indexzero | 1b0f34793b | |
indexzero | d8b5a80280 | |
Marak Squires | c43685160d | |
Charlie Robbins | d8627a9475 | |
Dominic Tarr | 6c6887a850 | |
indexzero | ae5aec6830 | |
indexzero | 76db254740 | |
indexzero | d7495f8373 | |
indexzero | 4c7aea99d3 | |
indexzero | f611066b60 | |
indexzero | be7688782a | |
indexzero | 7ffbf0a4ab | |
indexzero | 13f5753405 | |
indexzero | c9e60d96b5 | |
indexzero | 4459ba54a1 | |
indexzero | a4f00be991 | |
indexzero | c21ab02f44 | |
indexzero | 1b47f58343 | |
Sami Samhuri | 8a79ef04fd | |
Sami Samhuri | 6acc1fc533 | |
Sami Samhuri | faa8ab9486 | |
avian | bdf2fc8cd7 | |
avian | e7c216e970 | |
indexzero | e26bbe25f2 | |
indexzero | 78202ecb6c | |
indexzero | 87351caac8 | |
indexzero | badbb59e3f | |
indexzero | 9da37dff2a | |
indexzero | 4a61560671 | |
indexzero | 3b104f2026 | |
indexzero | d65922dc7a | |
indexzero | b9951b44c1 | |
indexzero | da8559427f | |
indexzero | 067d58a99d | |
indexzero | 96859f913c | |
indexzero | d99ab32cc5 | |
indexzero | 7484fdb7a0 | |
indexzero | 04a59e93d6 | |
indexzero | 9bd6e266a7 | |
indexzero | 4094125b30 | |
indexzero | 81e1883df5 | |
indexzero | b850ae2dd0 |
|
@ -0,0 +1,33 @@
|
|||
version: 2.1
|
||||
|
||||
commands:
|
||||
test-nodejs:
|
||||
steps:
|
||||
- run:
|
||||
name: Versions
|
||||
command: npm version
|
||||
- checkout
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: npm install
|
||||
- run:
|
||||
name: Test
|
||||
command: npm test
|
||||
jobs:
|
||||
node-v14:
|
||||
docker:
|
||||
- image: node:14-alpine
|
||||
steps:
|
||||
- test-nodejs
|
||||
node-v16:
|
||||
docker:
|
||||
- image: node:16-alpine
|
||||
steps:
|
||||
- test-nodejs
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
node-multi-build:
|
||||
jobs:
|
||||
- node-v14
|
||||
- node-v16
|
|
@ -1,3 +1,4 @@
|
|||
.DS_Store
|
||||
config.json
|
||||
test/fixtures/store.json
|
||||
node_modules
|
||||
npm-debug.log
|
|
@ -0,0 +1,12 @@
|
|||
v2.0.0 / Tue, 2 Jun 2020
|
||||
========================
|
||||
|
||||
Completely redesigned and re-written with zero dependencies among other things.
|
||||
|
||||
|
||||
v1.0.0 / Tue, 2 Jun 2020
|
||||
========================
|
||||
|
||||
This is quite the change as master had been updated over the years since the v.0.9.1 release. However it should be smaller and lighter.
|
||||
|
||||
* Major change: Removed all dependancies to yargs and removed argv support
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (C) 2011 Charlie Robbins and the Contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
335
README.md
335
README.md
|
@ -1,84 +1,321 @@
|
|||
# nconf
|
||||
# nconf-lite
|
||||
|
||||
A hybrid local / remote configuration storage library for node.js.
|
||||
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.
|
||||
|
||||
## Installation
|
||||
It is a hierarchical node.js configuration with files, environment variables, and atomic object merging.
|
||||
|
||||
### Installing npm (node package manager)
|
||||
<pre>
|
||||
curl http://npmjs.org/install.sh | sh
|
||||
</pre>
|
||||
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 almost every micro functionality.
|
||||
|
||||
### Installing nconf
|
||||
<pre>
|
||||
[sudo] npm install nconf
|
||||
</pre>
|
||||
## 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 `:`. Let's dive right into sample usage:
|
||||
|
||||
## Usage
|
||||
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
|
||||
import Nconf from 'nconf-lite'
|
||||
const nconf = new Nconf()
|
||||
|
||||
<pre>
|
||||
var fs = require('fs'),
|
||||
nconf = require('nconf');
|
||||
|
||||
//
|
||||
// Setup nconf to user the 'file' store and set a couple of values;
|
||||
// Setup nconf to use (in-order):
|
||||
// 2. Environment variables
|
||||
// 3. A file located at 'path/to/config.json'
|
||||
//
|
||||
nconf.env()
|
||||
.file({ file: 'path/to/config.json' });
|
||||
|
||||
//
|
||||
// Set a few variables on `nconf`.
|
||||
//
|
||||
nconf.use('file', { file: 'path/to/your/config.json' });
|
||||
nconf.set('database:host', '127.0.0.1');
|
||||
nconf.set('database:port', 5984);
|
||||
|
||||
|
||||
//
|
||||
// Get the entire database object from nconf
|
||||
// Get the entire database object from nconf. This will output
|
||||
// { host: '127.0.0.1', port: 5984 }
|
||||
//
|
||||
var database = 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
|
||||
//
|
||||
nconf.save(function (err) {
|
||||
fs.readFile('path/to/your/config.json', function (err, data) {
|
||||
console.dir(JSON.parse(data.toString()))
|
||||
});
|
||||
nconf.save()
|
||||
```
|
||||
|
||||
If you run the above script:
|
||||
|
||||
``` bash
|
||||
$ NODE_ENV=production sample.js
|
||||
```
|
||||
|
||||
The output will be:
|
||||
|
||||
```
|
||||
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 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
|
||||
|
||||
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
|
||||
import Nconf from 'nconf-lite'
|
||||
const nconf = new Nconf()
|
||||
|
||||
//
|
||||
// 1. any overrides
|
||||
//
|
||||
nconf.overrides({
|
||||
'always': 'be this value'
|
||||
});
|
||||
</pre>
|
||||
|
||||
//
|
||||
// 2. `process.env`
|
||||
//
|
||||
nconf.env();
|
||||
|
||||
//
|
||||
// 4. Values in `config.json`
|
||||
//
|
||||
nconf.file('/path/to/config.json');
|
||||
|
||||
//
|
||||
// Or with a custom name
|
||||
// Note: A custom key must be supplied for hierarchy to work if multiple files are used.
|
||||
//
|
||||
nconf.file('custom', '/path/to/config.json');
|
||||
|
||||
//
|
||||
// 5. Any default values
|
||||
//
|
||||
nconf.defaults({
|
||||
'if nothing else': 'use this value'
|
||||
});
|
||||
```
|
||||
|
||||
## API Documentation
|
||||
|
||||
### nconf.any(names, callback)
|
||||
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
|
||||
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
|
||||
//
|
||||
let port = nconf.any('NODEJS_PORT', 'PORT');
|
||||
```
|
||||
|
||||
### nconf.use(name)
|
||||
Fetch a specific store with the specified name.
|
||||
|
||||
``` js
|
||||
//
|
||||
// Load a file store onto nconf with the specified settings
|
||||
//
|
||||
nconf.file('custom', '/path/to/config.json');
|
||||
//
|
||||
// Grab the instance and set it to be readonly
|
||||
//
|
||||
nconf.use('custom').readOnly = true
|
||||
```
|
||||
|
||||
### nconf.required(keys)
|
||||
Declares a set of string keys to be mandatory, and throw an error if any are missing.
|
||||
|
||||
``` js
|
||||
nconf.defaults({
|
||||
keya: 'a',
|
||||
});
|
||||
|
||||
nconf.required(['keya', 'keyb']);
|
||||
// Error: Missing required keys: keyb
|
||||
```
|
||||
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
|
||||
.literal( 'logs', require( path.resolve( 'configs', 'logs', config.get( 'LOGS_MODE' ) + '.js') ))
|
||||
.defaults( defaults );
|
||||
```
|
||||
|
||||
## Storage Engines
|
||||
|
||||
### Memory
|
||||
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.
|
||||
<pre>
|
||||
|
||||
``` js
|
||||
nconf.use('memory');
|
||||
</pre>
|
||||
```
|
||||
|
||||
### Env
|
||||
Responsible for loading the values parsed from `process.env` into the configuration hierarchy.
|
||||
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
|
||||
|
||||
``` js
|
||||
//
|
||||
// Can optionally also be an Array of values to limit process.env to.
|
||||
//
|
||||
nconf.env(['only', 'load', 'these', 'values', 'from', 'process.env']);
|
||||
|
||||
//
|
||||
// Can also specify a separator for nested keys (instead of the default ':')
|
||||
//
|
||||
nconf.env({ separator: '__' });
|
||||
// Get the value of the env variable 'database__host'
|
||||
let dbHost = nconf.get('database:host');
|
||||
|
||||
//
|
||||
// Can also lowerCase keys.
|
||||
// Especially handy when dealing with environment variables which are usually
|
||||
// uppercased.
|
||||
//
|
||||
|
||||
// Given an environment variable PORT=3001
|
||||
nconf.env();
|
||||
let port = nconf.get('port') // undefined
|
||||
|
||||
nconf.env({ lowerCase: true });
|
||||
let port = nconf.get('port') // 3001
|
||||
|
||||
//
|
||||
// Or use all options
|
||||
//
|
||||
nconf.env({
|
||||
separator: '__',
|
||||
match: /^whatever_matches_this_will_be_whitelisted/
|
||||
whitelist: ['database__host', 'only', 'load', 'these', 'values', 'if', 'whatever_doesnt_match_but_is_whitelisted_gets_loaded_too'],
|
||||
lowerCase: true,
|
||||
parseValues: true,
|
||||
transform: function(obj) {
|
||||
if (obj.key === 'foo') {
|
||||
obj.value = 'baz';
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
});
|
||||
let dbHost = nconf.get('database:host');
|
||||
```
|
||||
|
||||
### 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 engine, 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.
|
||||
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()`.
|
||||
|
||||
<pre>
|
||||
nconf.use('file', { file: 'path/to/your/config.json' });
|
||||
</pre>
|
||||
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.
|
||||
|
||||
``` js
|
||||
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');
|
||||
|
||||
// Set a variable in the user store and save it
|
||||
nconf.user('user').set('some:variable', true)
|
||||
nconf.user('user').save()
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
### Redis
|
||||
The Redis engine will persist all of your configuration settings to a Redis server. All calls to `.get()`, `.set()`, `.clear()`, `.reset()` are asynchronous taking an additional callback parameter.
|
||||
If the file does not exist at the provided path, the store will simply be empty.
|
||||
|
||||
<pre>
|
||||
nconf.use('redis', { host: 'localhost', port: 6379, ttl: 60 * 60 * 1000 });
|
||||
</pre>
|
||||
#### Encrypting file contents
|
||||
|
||||
The Redis engine also has an in-memory cache with a default TTL of one hour. To change this, just pass the `ttl` option to `.use()`.
|
||||
Encryption and decrypting file contents using the `secure` option:
|
||||
|
||||
## More Documentation
|
||||
There is more documentation available through docco. I haven't gotten around to making a gh-pages branch so in the meantime if you clone the repository you can view the docs:
|
||||
<pre>
|
||||
open docs/nconf.html
|
||||
</pre>
|
||||
``` js
|
||||
nconf.file('secure-file', {
|
||||
file: 'path/to/secure-file.json',
|
||||
secure: {
|
||||
secret: 'super-secretzzz-keyzz',
|
||||
alg: 'aes-256-ctr'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```
|
||||
{
|
||||
"config-key-name": {
|
||||
"alg": "aes-256-ctr", // cipher used
|
||||
"value": "af07fbcf", // encrypted contents
|
||||
"iv": "49e7803a2a5ef98c7a51a8902b76dd10" // initialization vector
|
||||
},
|
||||
"another-config-key": {
|
||||
"alg": "aes-256-ctr", // cipher used
|
||||
"value": "e310f6d94f13", // encrypted contents
|
||||
"iv": "b654e01aed262f37d0acf200be193985" // initialization vector
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Installation
|
||||
``` bash
|
||||
npm install nconf-lite --save
|
||||
```
|
||||
|
||||
## Run Tests
|
||||
Tests are written in vows and give complete coverage of all APIs and storage engines.
|
||||
<pre>
|
||||
vows test/*-test.js --spec
|
||||
</pre>
|
||||
|
||||
#### Author: [Charlie Robbins](http://nodejitsu.com)
|
||||
``` bash
|
||||
$ npm test
|
||||
```
|
||||
|
||||
#### Original author: [Charlie Robbins](http://nodejitsu.com)
|
||||
#### Rewriter of all that garbage: TheThing
|
||||
#### License: MIT
|
||||
|
||||
[0]: http://github.com/nfp-projects/nconf-lite
|
||||
|
|
194
docs/docco.css
194
docs/docco.css
|
@ -1,194 +0,0 @@
|
|||
/*--------------------- Layout and Typography ----------------------------*/
|
||||
body {
|
||||
font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
color: #252519;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
a {
|
||||
color: #261a3b;
|
||||
}
|
||||
a:visited {
|
||||
color: #261a3b;
|
||||
}
|
||||
p {
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
h4, h5, h6 {
|
||||
color: #333;
|
||||
margin: 6px 0 6px 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
h2, h3 {
|
||||
margin-bottom: 0;
|
||||
color: #000;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 40px;
|
||||
margin-bottom: 15px;
|
||||
color: #000;
|
||||
}
|
||||
#container {
|
||||
position: relative;
|
||||
}
|
||||
#background {
|
||||
position: fixed;
|
||||
top: 0; left: 525px; right: 0; bottom: 0;
|
||||
background: #f5f5ff;
|
||||
border-left: 1px solid #e5e5ee;
|
||||
z-index: -1;
|
||||
}
|
||||
#jump_to, #jump_page {
|
||||
background: white;
|
||||
-webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
|
||||
-webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
|
||||
font: 10px Arial;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
text-align: right;
|
||||
}
|
||||
#jump_to, #jump_wrapper {
|
||||
position: fixed;
|
||||
right: 0; top: 0;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
#jump_wrapper {
|
||||
padding: 0;
|
||||
display: none;
|
||||
}
|
||||
#jump_to:hover #jump_wrapper {
|
||||
display: block;
|
||||
}
|
||||
#jump_page {
|
||||
padding: 5px 0 3px;
|
||||
margin: 0 0 25px 25px;
|
||||
}
|
||||
#jump_page .source {
|
||||
display: block;
|
||||
padding: 5px 10px;
|
||||
text-decoration: none;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
#jump_page .source:hover {
|
||||
background: #f5f5ff;
|
||||
}
|
||||
#jump_page .source:first-child {
|
||||
}
|
||||
table td {
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
td.docs, th.docs {
|
||||
max-width: 450px;
|
||||
min-width: 450px;
|
||||
min-height: 5px;
|
||||
padding: 10px 25px 1px 50px;
|
||||
overflow-x: hidden;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
.docs pre {
|
||||
margin: 15px 0 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
.docs p tt, .docs p code {
|
||||
background: #f8f8ff;
|
||||
border: 1px solid #dedede;
|
||||
font-size: 12px;
|
||||
padding: 0 0.2em;
|
||||
}
|
||||
.pilwrap {
|
||||
position: relative;
|
||||
}
|
||||
.pilcrow {
|
||||
font: 12px Arial;
|
||||
text-decoration: none;
|
||||
color: #454545;
|
||||
position: absolute;
|
||||
top: 3px; left: -20px;
|
||||
padding: 1px 2px;
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
}
|
||||
td.docs:hover .pilcrow {
|
||||
opacity: 1;
|
||||
}
|
||||
td.code, th.code {
|
||||
padding: 14px 15px 16px 25px;
|
||||
width: 100%;
|
||||
vertical-align: top;
|
||||
background: #f5f5ff;
|
||||
border-left: 1px solid #e5e5ee;
|
||||
}
|
||||
pre, tt, code {
|
||||
font-size: 12px; line-height: 18px;
|
||||
font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------- Syntax Highlighting -----------------------------*/
|
||||
td.linenos { background-color: #f0f0f0; padding-right: 10px; }
|
||||
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
|
||||
body .hll { background-color: #ffffcc }
|
||||
body .c { color: #408080; font-style: italic } /* Comment */
|
||||
body .err { border: 1px solid #FF0000 } /* Error */
|
||||
body .k { color: #954121 } /* Keyword */
|
||||
body .o { color: #666666 } /* Operator */
|
||||
body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
||||
body .cp { color: #BC7A00 } /* Comment.Preproc */
|
||||
body .c1 { color: #408080; font-style: italic } /* Comment.Single */
|
||||
body .cs { color: #408080; font-style: italic } /* Comment.Special */
|
||||
body .gd { color: #A00000 } /* Generic.Deleted */
|
||||
body .ge { font-style: italic } /* Generic.Emph */
|
||||
body .gr { color: #FF0000 } /* Generic.Error */
|
||||
body .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
body .gi { color: #00A000 } /* Generic.Inserted */
|
||||
body .go { color: #808080 } /* Generic.Output */
|
||||
body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
body .gs { font-weight: bold } /* Generic.Strong */
|
||||
body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
body .gt { color: #0040D0 } /* Generic.Traceback */
|
||||
body .kc { color: #954121 } /* Keyword.Constant */
|
||||
body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */
|
||||
body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */
|
||||
body .kp { color: #954121 } /* Keyword.Pseudo */
|
||||
body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */
|
||||
body .kt { color: #B00040 } /* Keyword.Type */
|
||||
body .m { color: #666666 } /* Literal.Number */
|
||||
body .s { color: #219161 } /* Literal.String */
|
||||
body .na { color: #7D9029 } /* Name.Attribute */
|
||||
body .nb { color: #954121 } /* Name.Builtin */
|
||||
body .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
||||
body .no { color: #880000 } /* Name.Constant */
|
||||
body .nd { color: #AA22FF } /* Name.Decorator */
|
||||
body .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||
body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
||||
body .nf { color: #0000FF } /* Name.Function */
|
||||
body .nl { color: #A0A000 } /* Name.Label */
|
||||
body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
||||
body .nt { color: #954121; font-weight: bold } /* Name.Tag */
|
||||
body .nv { color: #19469D } /* Name.Variable */
|
||||
body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
||||
body .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
body .mf { color: #666666 } /* Literal.Number.Float */
|
||||
body .mh { color: #666666 } /* Literal.Number.Hex */
|
||||
body .mi { color: #666666 } /* Literal.Number.Integer */
|
||||
body .mo { color: #666666 } /* Literal.Number.Oct */
|
||||
body .sb { color: #219161 } /* Literal.String.Backtick */
|
||||
body .sc { color: #219161 } /* Literal.String.Char */
|
||||
body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
|
||||
body .s2 { color: #219161 } /* Literal.String.Double */
|
||||
body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
||||
body .sh { color: #219161 } /* Literal.String.Heredoc */
|
||||
body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
||||
body .sx { color: #954121 } /* Literal.String.Other */
|
||||
body .sr { color: #BB6688 } /* Literal.String.Regex */
|
||||
body .s1 { color: #219161 } /* Literal.String.Single */
|
||||
body .ss { color: #19469D } /* Literal.String.Symbol */
|
||||
body .bp { color: #954121 } /* Name.Builtin.Pseudo */
|
||||
body .vc { color: #19469D } /* Name.Variable.Class */
|
||||
body .vg { color: #19469D } /* Name.Variable.Global */
|
||||
body .vi { color: #19469D } /* Name.Variable.Instance */
|
||||
body .il { color: #666666 } /* Literal.Number.Integer.Long */
|
103
docs/nconf.html
103
docs/nconf.html
|
@ -1,103 +0,0 @@
|
|||
<!DOCTYPE html> <html> <head> <title>nconf.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="nconf/stores/file.html"> nconf/stores/file.html </a> <a class="source" href="nconf/stores/memory.html"> nconf/stores/memory.html </a> <a class="source" href="nconf/stores/redis.html"> nconf/stores/redis.html </a> <a class="source" href="nconf/stores.html"> nconf/stores.html </a> <a class="source" href="nconf.html"> nconf.html </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> nconf.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
|
||||
<span class="cm"> * nconf.js: Top-level include for the nconf module</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> * (C) 2011, Charlie Robbins</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> */</span>
|
||||
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">paths</span><span class="p">.</span><span class="nx">unshift</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">);</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">nconf</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">;</span>
|
||||
|
||||
<span class="nx">nconf</span><span class="p">.</span><span class="nx">stores</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'nconf/stores'</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <h3>function use (type, options)</h3>
|
||||
|
||||
<h4>@type {string} Type of the nconf store to use.</h4>
|
||||
|
||||
<h4>@options {Object} Options for the store instance.</h4>
|
||||
|
||||
<p>Sets the active <code>nconf.store</code> to a new instance of the
|
||||
specified <code>type</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">nconf</span><span class="p">.</span><span class="nx">use</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">nconf</span><span class="p">.</span><span class="nx">store</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">stores</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">options</span><span class="p">);</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <h3>function get (key, callback)</h3>
|
||||
|
||||
<h4>@key {string} Key to retrieve for this instance.</h4>
|
||||
|
||||
<h4>@callback {function} <strong>Optional</strong> Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Retrieves the value for the specified key (if any).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">nconf</span><span class="p">.</span><span class="nx">get</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <h3>function set (key, value, callback)</h3>
|
||||
|
||||
<h4>@key {string} Key to set in this instance</h4>
|
||||
|
||||
<h4>@value {literal|Object} Value for the specified key</h4>
|
||||
|
||||
<h4>@callback {function} <strong>Optional</strong> Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Sets the <code>value</code> for the specified <code>key</code> in this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">nconf</span><span class="p">.</span><span class="nx">set</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <h3>function clear (key, callback)</h3>
|
||||
|
||||
<h4>@key {string} Key to remove from this instance</h4>
|
||||
|
||||
<h4>@callback {function} <strong>Optional</strong> Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Removes the value for the specified <code>key</code> from this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">nconf</span><span class="p">.</span><span class="nx">clear</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">clear</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <h3>function load (callback)</h3>
|
||||
|
||||
<h4>@callback {function} Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Responds with an Object representing all keys associated in this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">nconf</span><span class="p">.</span><span class="nx">load</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">load</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">error</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">'nconf store '</span> <span class="o">+</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">type</span> <span class="o">+</span> <span class="s1">' has no load() method'</span><span class="p">);</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">callback</span> <span class="p">(</span><span class="nx">error</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">return</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <h3>function save (value, callback)</h3>
|
||||
|
||||
<h4>@value {Object} <strong>Optional</strong> Config object to set for this instance</h4>
|
||||
|
||||
<h4>@callback {function} Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Removes any existing configuration settings that may exist in this
|
||||
instance and then adds all key-value pairs in <code>value</code>. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">nconf</span><span class="p">.</span><span class="nx">save</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">callback</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
|
||||
<span class="nx">value</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">save</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">error</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">'nconf store '</span> <span class="o">+</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">type</span> <span class="o">+</span> <span class="s1">' has no save() method'</span><span class="p">);</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">callback</span> <span class="p">(</span><span class="nx">error</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">return</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">save</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <h3>function reset (callback)</h3>
|
||||
|
||||
<h4>@callback {function} <strong>Optional</strong> Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Clears all keys associated with this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">nconf</span><span class="p">.</span><span class="nx">reset</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">reset</span><span class="p">(</span><span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <h3>function key (arguments)</h3>
|
||||
|
||||
<p>Returns a <code>:</code> joined string from the <code>arguments</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">slice</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">arguments</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">':'</span><span class="p">);</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <h3>function path (key)</h3>
|
||||
|
||||
<h4>@key {string} The ':' delimited key to split</h4>
|
||||
|
||||
<p>Returns a fully-qualified path to a nested nconf key. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">nconf</span><span class="p">.</span><span class="nx">path</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">key</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">':'</span><span class="p">);</span>
|
||||
<span class="p">};</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
|
@ -1,27 +0,0 @@
|
|||
<!DOCTYPE html> <html> <head> <title>stores.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="../docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="..//nconf/stores/file.html"> nconf/stores/file.html </a> <a class="source" href="..//nconf/stores/memory.html"> nconf/stores/memory.html </a> <a class="source" href="..//nconf/stores/redis.html"> nconf/stores/redis.html </a> <a class="source" href="..//nconf/stores.html"> nconf/stores.html </a> <a class="source" href="..//nconf.html"> nconf.html </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> stores.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
|
||||
<span class="cm"> * stores.js: Top-level include for all nconf stores</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> * (C) 2011, Charlie Robbins</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> */</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">stores</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">;</span>
|
||||
|
||||
<span class="kd">function</span> <span class="nx">capitalize</span> <span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">str</span> <span class="o">&&</span> <span class="nx">str</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">toUpperCase</span><span class="p">()</span> <span class="o">+</span> <span class="nx">str</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
|
||||
<span class="p">};</span>
|
||||
|
||||
<span class="nx">stores</span><span class="p">.</span><span class="nx">Memory</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'nconf/stores/memory'</span><span class="p">).</span><span class="nx">Memory</span><span class="p">;</span>
|
||||
<span class="nx">stores</span><span class="p">.</span><span class="nx">File</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'nconf/stores/file'</span><span class="p">).</span><span class="nx">File</span><span class="p">;</span>
|
||||
<span class="nx">stores</span><span class="p">.</span><span class="nx">Redis</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'nconf/stores/redis'</span><span class="p">).</span><span class="nx">Redis</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <h3>function create (type, options)</h3>
|
||||
|
||||
<h4>@type {string} Type of the nconf store to use.</h4>
|
||||
|
||||
<h4>@options {Object} Options for the store instance.</h4>
|
||||
|
||||
<p>Creates a store of the specified <code>type</code> using the
|
||||
specified <code>options</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">stores</span><span class="p">.</span><span class="nx">create</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="nx">stores</span><span class="p">[</span><span class="nx">capitalize</span><span class="p">(</span><span class="nx">type</span><span class="p">.</span><span class="nx">toLowerCase</span><span class="p">())](</span><span class="nx">options</span><span class="p">);</span>
|
||||
<span class="p">};</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
|
@ -1,58 +0,0 @@
|
|||
<!DOCTYPE html> <html> <head> <title>file.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="../../docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="../..//nconf/stores/file.html"> nconf/stores/file.html </a> <a class="source" href="../..//nconf/stores/memory.html"> nconf/stores/memory.html </a> <a class="source" href="../..//nconf/stores/redis.html"> nconf/stores/redis.html </a> <a class="source" href="../..//nconf/stores.html"> nconf/stores.html </a> <a class="source" href="../..//nconf.html"> nconf.html </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> file.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
|
||||
<span class="cm"> * file.js: Simple file storage engine for nconf files</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> * (C) 2011, Charlie Robbins</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> */</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'fs'</span><span class="p">),</span>
|
||||
<span class="nx">util</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'util'</span><span class="p">),</span>
|
||||
<span class="nx">Memory</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./memory'</span><span class="p">).</span><span class="nx">Memory</span><span class="p">;</span>
|
||||
</pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <h3>function File (options)</h3>
|
||||
|
||||
<h4>@options {Object} Options for this instance</h4>
|
||||
|
||||
<p>Constructor function for the File nconf store, a simple abstraction
|
||||
around the Memory store that can persist configuration to disk.</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">File</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">File</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">options</span><span class="p">.</span><span class="nx">file</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="p">(</span><span class="s1">'Missing required option `files`'</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">Memory</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">options</span><span class="p">);</span>
|
||||
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">file</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">file</span><span class="p">;</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">format</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">format</span> <span class="o">||</span> <span class="nx">JSON</span><span class="p">;</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Inherit from the Memory store</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">util</span><span class="p">.</span><span class="nx">inherits</span><span class="p">(</span><span class="nx">File</span><span class="p">,</span> <span class="nx">Memory</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <h3>function save (value, callback)</h3>
|
||||
|
||||
<h4>@value {Object} <em>Ignored</em> Left here for consistency</h4>
|
||||
|
||||
<h4>@callback {function} Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Saves the current configuration object to disk at <code>this.file</code>
|
||||
using the format specified by <code>this.format</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">File</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">save</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">callback</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
|
||||
<span class="nx">value</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">format</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">store</span><span class="p">),</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">err</span> <span class="o">?</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">:</span> <span class="nx">callback</span><span class="p">();</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <h3>function load (callback)</h3>
|
||||
|
||||
<h4>@callback {function} Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Responds with an Object representing all keys associated in this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">File</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">load</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">data</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">format</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">store</span> <span class="o">=</span> <span class="nx">data</span><span class="p">;</span>
|
||||
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">self</span><span class="p">.</span><span class="nx">store</span><span class="p">);</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">};</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
|
@ -1,83 +0,0 @@
|
|||
<!DOCTYPE html> <html> <head> <title>memory.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="../../docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="../..//nconf/stores/file.html"> nconf/stores/file.html </a> <a class="source" href="../..//nconf/stores/memory.html"> nconf/stores/memory.html </a> <a class="source" href="../..//nconf/stores/redis.html"> nconf/stores/redis.html </a> <a class="source" href="../..//nconf/stores.html"> nconf/stores.html </a> <a class="source" href="../..//nconf.html"> nconf.html </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> memory.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
|
||||
<span class="cm"> * memory.js: Simple memory storage engine for nconf configuration(s)</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> * (C) 2011, Charlie Robbins</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> */</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">nconf</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'nconf'</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <h3>function Memory (options)</h3>
|
||||
|
||||
<h4>@options {Object} Options for this instance</h4>
|
||||
|
||||
<p>Constructor function for the Memory nconf store which maintains
|
||||
a nested json structure based on key delimiters <code>:</code>.</p>
|
||||
|
||||
<p>e.g. <code>my:nested:key</code> ==> <code>{ my: { nested: { key: } } }</code> </p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">Memory</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Memory</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">options</span> <span class="o">=</span> <span class="nx">options</span> <span class="o">||</span> <span class="p">{};</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">store</span> <span class="o">=</span> <span class="p">{};</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">mtimes</span> <span class="o">=</span> <span class="p">{};</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <h3>function get (key)</h3>
|
||||
|
||||
<h4>@key {string} Key to retrieve for this instance.</h4>
|
||||
|
||||
<p>Retrieves the value for the specified key (if any).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Memory</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">get</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">target</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">store</span><span class="p">,</span>
|
||||
<span class="nx">path</span> <span class="o">=</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">path</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Scope into the object to get the appropriate nested context</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">while</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">key</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">target</span><span class="p">[</span><span class="nx">key</span><span class="p">])</span> <span class="p">{</span>
|
||||
<span class="k">return</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">target</span> <span class="o">=</span> <span class="nx">target</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">target</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <h3>function set (key, value)</h3>
|
||||
|
||||
<h4>@key {string} Key to set in this instance</h4>
|
||||
|
||||
<h4>@value {literal|Object} Value for the specified key</h4>
|
||||
|
||||
<p>Sets the <code>value</code> for the specified <code>key</code> in this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Memory</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">set</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">target</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">store</span><span class="p">,</span>
|
||||
<span class="nx">path</span> <span class="o">=</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">path</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
|
||||
</pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Update the <code>mtime</code> (modified time) of the key</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">mtimes</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
|
||||
</pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Scope into the object to get the appropriate nested context</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">while</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">key</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">target</span><span class="p">[</span><span class="nx">key</span><span class="p">])</span> <span class="p">{</span>
|
||||
<span class="nx">target</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="p">{};</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">target</span> <span class="o">=</span> <span class="nx">target</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Set the specified value in the nested JSON structure</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">key</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
|
||||
<span class="nx">target</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
|
||||
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <h3>function clear (key)</h3>
|
||||
|
||||
<h4>@key {string} Key to remove from this instance</h4>
|
||||
|
||||
<p>Removes the value for the specified <code>key</code> from this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Memory</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">clear</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">target</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">store</span><span class="p">,</span>
|
||||
<span class="nx">path</span> <span class="o">=</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">path</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
|
||||
</pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Remove the key from the set of <code>mtimes</code> (modified times)</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">delete</span> <span class="k">this</span><span class="p">.</span><span class="nx">mtimes</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
|
||||
</pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Scope into the object to get the appropriate nested context</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">while</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">key</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">target</span><span class="p">[</span><span class="nx">key</span><span class="p">])</span> <span class="p">{</span>
|
||||
<span class="k">return</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">target</span> <span class="o">=</span> <span class="nx">target</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Delete the key from the nested JSON structure</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">key</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
|
||||
<span class="k">delete</span> <span class="nx">target</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
|
||||
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <h3>function reset (callback)</h3>
|
||||
|
||||
<p>Clears all keys associated with this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Memory</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">reset</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">mtimes</span> <span class="o">=</span> <span class="p">{};</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">store</span> <span class="o">=</span> <span class="p">{};</span>
|
||||
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
|
@ -1,250 +0,0 @@
|
|||
<!DOCTYPE html> <html> <head> <title>redis.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="../../docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="../..//nconf/stores/file.html"> nconf/stores/file.html </a> <a class="source" href="../..//nconf/stores/memory.html"> nconf/stores/memory.html </a> <a class="source" href="../..//nconf/stores/redis.html"> nconf/stores/redis.html </a> <a class="source" href="../..//nconf/stores.html"> nconf/stores.html </a> <a class="source" href="../..//nconf.html"> nconf.html </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> redis.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
|
||||
<span class="cm"> * redis.js: Redis storage engine for nconf configuration(s)</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> * (C) 2011, Charlie Robbins</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> */</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">async</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'async'</span><span class="p">),</span>
|
||||
<span class="nx">eyes</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'eyes'</span><span class="p">),</span>
|
||||
<span class="nx">redis</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'redis'</span><span class="p">),</span>
|
||||
<span class="nx">nconf</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'nconf'</span><span class="p">),</span>
|
||||
<span class="nx">Memory</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./Memory'</span><span class="p">).</span><span class="nx">Memory</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <h3>function Redis (options)</h3>
|
||||
|
||||
<h4>@options {Object} Options for this instance</h4>
|
||||
|
||||
<p>Constructor function for the Redis nconf store which maintains
|
||||
a nested Redis key structure based on key delimiters <code>:</code>.</p>
|
||||
|
||||
<p>e.g.
|
||||
my:nested:key, 'value'
|
||||
namespace:keys ==> ['my']
|
||||
namespace:nested:keys ==> ['key']
|
||||
namespace:nested:key ==> 'value'</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">Redis</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Redis</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">options</span> <span class="o">=</span> <span class="nx">options</span> <span class="o">||</span> <span class="p">{}</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">namespace</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">namespace</span> <span class="o">||</span> <span class="s1">'nconf'</span><span class="p">;</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">host</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">host</span> <span class="o">||</span> <span class="s1">'localhost'</span><span class="p">;</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">port</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">port</span> <span class="o">||</span> <span class="mi">6379</span><span class="p">;</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">ttl</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">ttl</span> <span class="o">||</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">;</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">cache</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Memory</span><span class="p">();</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">redis</span> <span class="o">=</span> <span class="nx">redis</span><span class="p">.</span><span class="nx">createClient</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">port</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">host</span><span class="p">);</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <h3>function get (key, callback)</h3>
|
||||
|
||||
<h4>@key {string} Key to retrieve for this instance.</h4>
|
||||
|
||||
<h4>@callback {function} Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Retrieves the value for the specified key (if any).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Redis</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">get</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span>
|
||||
<span class="nx">result</span> <span class="o">=</span> <span class="p">{},</span>
|
||||
<span class="nx">now</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">(),</span>
|
||||
<span class="nx">mtime</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">mtimes</span><span class="p">[</span><span class="nx">key</span><span class="p">],</span>
|
||||
<span class="nx">fullKey</span> <span class="o">=</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">namespace</span><span class="p">,</span> <span class="nx">key</span><span class="p">);</span>
|
||||
</pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>If the key exists in the cache and the ttl is less than
|
||||
the value set for this instance, return from the cache.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">mtime</span> <span class="o">&&</span> <span class="nx">now</span> <span class="o">-</span> <span class="nx">mtime</span> <span class="o"><</span> <span class="k">this</span><span class="p">.</span><span class="nx">ttl</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">key</span><span class="p">));</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Get the set of all children keys for the <code>key</code> supplied. If the value
|
||||
to be returned is an Object, this list will not be empty.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">smembers</span><span class="p">(</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">(</span><span class="nx">fullKey</span><span class="p">,</span> <span class="s1">'keys'</span><span class="p">),</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">keys</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">function</span> <span class="nx">addValue</span> <span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">source</span><span class="p">),</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">next</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">result</span><span class="p">[</span><span class="nx">source</span><span class="p">]</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
|
||||
<span class="nx">next</span><span class="p">();</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">keys</span> <span class="o">&&</span> <span class="nx">keys</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>If the value to be retrieved is an Object, recursively attempt
|
||||
to get the value from redis. Here we use a recursive call to <code>this.get</code>
|
||||
to support nested Object keys.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">async</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">keys</span><span class="p">,</span> <span class="nx">addValue</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">result</span><span class="p">);</span>
|
||||
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">result</span><span class="p">);</span>
|
||||
<span class="p">})</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">else</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>If there are no keys, then the value to be retrieved is a literal
|
||||
and we can simply return the value from redis directly. </p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">self</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">fullKey</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">result</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">result</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">result</span><span class="p">);</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <h3>function set (key, value, callback)</h3>
|
||||
|
||||
<h4>@key {string} Key to set in this instance</h4>
|
||||
|
||||
<h4>@value {literal|Object} Value for the specified key</h4>
|
||||
|
||||
<h4>@callback {function} Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Sets the <code>value</code> for the specified <code>key</code> in this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Redis</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">set</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span>
|
||||
<span class="nx">path</span> <span class="o">=</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">path</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
|
||||
|
||||
<span class="kd">function</span> <span class="nx">addKey</span> <span class="p">(</span><span class="nx">partial</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">partial</span><span class="p">),</span>
|
||||
<span class="nx">base</span> <span class="o">=</span> <span class="p">[</span><span class="nx">self</span><span class="p">.</span><span class="nx">namespace</span><span class="p">].</span><span class="nx">concat</span><span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">index</span><span class="p">)),</span>
|
||||
<span class="nx">parent</span> <span class="o">=</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">base</span><span class="p">.</span><span class="nx">concat</span><span class="p">([</span><span class="s1">'keys'</span><span class="p">]));</span>
|
||||
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">sadd</span><span class="p">(</span><span class="nx">parent</span><span class="p">,</span> <span class="nx">partial</span><span class="p">,</span> <span class="nx">next</span><span class="p">);</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Iterate over the entire key path and add each key to the
|
||||
parent key-set if it doesn't exist already.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">async</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">path</span><span class="p">,</span> <span class="nx">addKey</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">fullKey</span> <span class="o">=</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">(</span><span class="nx">self</span><span class="p">.</span><span class="nx">namespace</span><span class="p">,</span> <span class="nx">key</span><span class="p">);</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="o">&&</span> <span class="k">typeof</span> <span class="nx">value</span> <span class="o">===</span> <span class="s1">'object'</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>If the value is an <code>Object</code> (and not an <code>Array</code>) then
|
||||
nest into the value and set the child keys appropriately.
|
||||
This is done for efficient lookup when setting Object keys.
|
||||
(i.e. If you set and Object then wish to later retrieve only a
|
||||
member of that Object, the entire Object need not be retrieved). </p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">self</span><span class="p">.</span><span class="nx">_setObject</span><span class="p">(</span><span class="nx">fullKey</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">else</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>If the value is a simple literal (or an <code>Array</code>) then JSON
|
||||
stringify it and put it into Redis.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">value</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">);</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">fullKey</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <h3>function clear (key, callback)</h3>
|
||||
|
||||
<h4>@key {string} Key to remove from this instance</h4>
|
||||
|
||||
<h4>@callback {function} Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Removes the value for the specified <code>key</code> from this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Redis</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">clear</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span>
|
||||
<span class="nx">result</span> <span class="o">=</span> <span class="p">{},</span>
|
||||
<span class="nx">path</span> <span class="o">=</span> <span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">namespace</span><span class="p">].</span><span class="nx">concat</span><span class="p">(</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">path</span><span class="p">(</span><span class="nx">key</span><span class="p">)),</span>
|
||||
<span class="nx">last</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">pop</span><span class="p">(),</span>
|
||||
<span class="nx">fullKey</span> <span class="o">=</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">namespace</span><span class="p">,</span> <span class="nx">key</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Clear the key from the cache for this instance</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">clear</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
|
||||
</pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Remove the <code>key</code> from the parent set of keys.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">srem</span><span class="p">(</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">concat</span><span class="p">([</span><span class="s1">'keys'</span><span class="p">])),</span> <span class="nx">last</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Remove the value from redis by iterating over the set of keys (if any)
|
||||
and deleting each value. If no keys, then just delete the simple literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">self</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">smembers</span><span class="p">(</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">(</span><span class="nx">fullKey</span><span class="p">,</span> <span class="s1">'keys'</span><span class="p">),</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">keys</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">function</span> <span class="nx">removeValue</span> <span class="p">(</span><span class="nx">child</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Recursively call <code>self.clear</code> here to ensure we remove any
|
||||
nested Objects completely from this instance.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">self</span><span class="p">.</span><span class="nx">clear</span><span class="p">(</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">child</span><span class="p">),</span> <span class="nx">next</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">keys</span> <span class="o">&&</span> <span class="nx">keys</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>If there are child keys then iterate over them,
|
||||
removing each child along the way.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">async</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">keys</span><span class="p">,</span> <span class="nx">removeValue</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">else</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>Otherwise if this is just a simple literal, then
|
||||
simply remove it from Redis directly.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">self</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">del</span><span class="p">(</span><span class="nx">fullKey</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <h3>function save (value, callback)</h3>
|
||||
|
||||
<h4>@value {Object} Config object to set for this instance</h4>
|
||||
|
||||
<h4>@callback {function} Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Removes any existing configuration settings that may exist in this
|
||||
instance and then adds all key-value pairs in <code>value</code>. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Redis</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">save</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="o">||</span> <span class="k">typeof</span> <span class="nx">value</span> <span class="o">!==</span> <span class="s1">'object'</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">'`value` to be saved must be an object.'</span><span class="p">));</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span>
|
||||
<span class="nx">keys</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
|
||||
</pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Clear all existing keys associated with this instance.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">reset</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>Iterate over the keys in the new value, setting each of them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">async</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">keys</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">[</span><span class="nx">key</span><span class="p">],</span> <span class="nx">next</span><span class="p">);</span>
|
||||
<span class="p">},</span> <span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <h3>function load (callback)</h3>
|
||||
|
||||
<h4>@callback {function} Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Responds with an Object representing all keys associated in this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Redis</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">load</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span>
|
||||
<span class="nx">result</span> <span class="o">=</span> <span class="p">{};</span>
|
||||
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">smembers</span><span class="p">(</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">namespace</span><span class="p">,</span> <span class="s1">'keys'</span><span class="p">),</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">keys</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="kd">function</span> <span class="nx">addValue</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">next</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">result</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
|
||||
<span class="nx">next</span><span class="p">();</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">async</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">keys</span><span class="p">,</span> <span class="nx">addValue</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">err</span> <span class="o">?</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">:</span> <span class="nx">callback</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">result</span><span class="p">);</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <h3>function reset (callback)</h3>
|
||||
|
||||
<h4>@callback {function} Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Clears all keys associated with this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Redis</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">reset</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
|
||||
</pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>Get the list of of top-level keys, then clear each of them</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">smembers</span><span class="p">(</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">namespace</span><span class="p">,</span> <span class="s1">'keys'</span><span class="p">),</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">existing</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">async</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">existing</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">clear</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">next</span><span class="p">);</span>
|
||||
<span class="p">},</span> <span class="nx">callback</span><span class="p">);</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <h3>@private function _setObject (key, value, callback)</h3>
|
||||
|
||||
<h4>@key {string} Key to set in this instance</h4>
|
||||
|
||||
<h4>@value {Object} Value for the specified key</h4>
|
||||
|
||||
<h4>@callback {function} Continuation to respond to when complete.</h4>
|
||||
|
||||
<p>Internal helper function for setting all keys of a nested object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Redis</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">_setObject</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span>
|
||||
<span class="nx">keys</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
|
||||
|
||||
<span class="kd">function</span> <span class="nx">addValue</span> <span class="p">(</span><span class="nx">child</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Add the child key to the parent key-set, then set the value.
|
||||
Recursively call <code>_setObject</code> in the event of nested Object(s).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">self</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">sadd</span><span class="p">(</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="s1">'keys'</span><span class="p">),</span> <span class="nx">child</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">next</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">fullKey</span> <span class="o">=</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">key</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">child</span><span class="p">),</span>
|
||||
<span class="nx">childValue</span> <span class="o">=</span> <span class="nx">value</span><span class="p">[</span><span class="nx">child</span><span class="p">];</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">childValue</span><span class="p">)</span> <span class="o">&&</span> <span class="k">typeof</span> <span class="nx">childValue</span> <span class="o">===</span> <span class="s1">'object'</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">_setObject</span><span class="p">(</span><span class="nx">fullKey</span><span class="p">,</span> <span class="nx">childValue</span><span class="p">,</span> <span class="nx">next</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">else</span> <span class="p">{</span>
|
||||
<span class="nx">childValue</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">childValue</span><span class="p">);</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">fullKey</span><span class="p">,</span> <span class="nx">childValue</span><span class="p">,</span> <span class="nx">next</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</a> </div> <p>Iterate over the keys of the Object and set the appropriate values.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">async</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">keys</span><span class="p">,</span> <span class="nx">addValue</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">err</span> <span class="o">?</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">:</span> <span class="nx">callback</span><span class="p">();</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">};</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
|
@ -0,0 +1,177 @@
|
|||
import fs from 'fs'
|
||||
import Memory from './stores/memory.mjs'
|
||||
|
||||
//
|
||||
// ### function validkeyvalue(key)
|
||||
// #### @key {any} key to check
|
||||
// Return string of key if valid string type key,
|
||||
// otherwise transform into new key containing
|
||||
// the error message
|
||||
export function validkeyvalue(key) {
|
||||
let type = typeof(key)
|
||||
if (key && type !== 'string' && type !== 'number') {
|
||||
return '__invalid_valuetype_of_' + type + '__'
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
//
|
||||
// ### function path (key)
|
||||
// #### @key {string} The ':' delimited key to split
|
||||
// Returns a fully-qualified path to a nested nconf key.
|
||||
// If given null or undefined it should return an empty path.
|
||||
// '' should still be respected as a path.
|
||||
//
|
||||
export function path(key, separator) {
|
||||
let invalidType = validkeyvalue(key)
|
||||
if (invalidType) {
|
||||
return [invalidType]
|
||||
}
|
||||
separator = separator || ':'
|
||||
return key == null
|
||||
|| key === ''
|
||||
? []
|
||||
: key.toString().split(separator)
|
||||
}
|
||||
|
||||
//
|
||||
// ### function key (arguments)
|
||||
// Returns a `:` joined string from the `arguments`.
|
||||
//
|
||||
export function key(...path) {
|
||||
return path.map(function(item) {
|
||||
return validkeyvalue(item) || ('' + item)
|
||||
}).join(':')
|
||||
}
|
||||
|
||||
//
|
||||
// ### function key (arguments)
|
||||
// Returns a joined string from the `arguments`,
|
||||
// first argument is the join delimiter.
|
||||
//
|
||||
export function keyed(separator, ...path) {
|
||||
return path.map(function(item) {
|
||||
return validkeyvalue(item) || ('' + item)
|
||||
}).join(separator)
|
||||
}
|
||||
|
||||
// taken from isobject npm library
|
||||
export function isObject(val) {
|
||||
return val != null && typeof val === 'object' && Array.isArray(val) === false
|
||||
}
|
||||
|
||||
// Return a new recursive deep instance of array of objects
|
||||
// or values to make sure no original object ever get touched
|
||||
export function mergeRecursiveArray(arr) {
|
||||
return arr.map(function(item) {
|
||||
if (isObject(item)) return mergeRecursive({}, item)
|
||||
if (Array.isArray(item)) return mergeRecursiveArray(item)
|
||||
return item
|
||||
})
|
||||
}
|
||||
|
||||
// Recursively merges the child into the parent.
|
||||
export function mergeRecursive(parent, child) {
|
||||
Object.keys(child).forEach(key => {
|
||||
// Arrays will always overwrite for now
|
||||
if (Array.isArray(child[key])) {
|
||||
parent[key] = mergeRecursiveArray(child[key])
|
||||
} else if (child[key] && typeof child[key] === 'object') {
|
||||
// We don't wanna support cross merging between array and objects
|
||||
// so we overwrite the old value (at least for now).
|
||||
if (parent[key] && Array.isArray(parent[key])) {
|
||||
parent[key] = mergeRecursive({}, child[key])
|
||||
} else {
|
||||
parent[key] = mergeRecursive(parent[key] || {}, child[key])
|
||||
}
|
||||
} else {
|
||||
parent[key] = child[key]
|
||||
}
|
||||
})
|
||||
|
||||
return parent
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ### function merge (objs)
|
||||
// #### @objs {Array} Array of object literals to merge
|
||||
// Merges the specified `objs` together into a new object.
|
||||
// This differs from the old logic as it does not affect or chagne
|
||||
// any of the objects being merged.
|
||||
//
|
||||
export function merge(orgOut, orgObjs) {
|
||||
let out = orgOut
|
||||
let objs = orgObjs
|
||||
if (objs === undefined) {
|
||||
out = {}
|
||||
objs = orgOut
|
||||
}
|
||||
if (!Array.isArray(objs)) {
|
||||
throw new Error('merge called with non-array of objects')
|
||||
}
|
||||
for (let x = 0; x < objs.length; x++) {
|
||||
out = mergeRecursive(out, objs[x])
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
//
|
||||
// ### function capitalize (str)
|
||||
// #### @str {string} String to capitalize
|
||||
// Capitalizes the specified `str` if string, otherwise
|
||||
// returns the original object
|
||||
//
|
||||
export function capitalize(str) {
|
||||
if (typeof(str) !== 'string' && typeof(str) !== 'number') {
|
||||
return str
|
||||
}
|
||||
let out = str.toString()
|
||||
return out && (out[0].toString()).toUpperCase() + out.slice(1)
|
||||
}
|
||||
|
||||
//
|
||||
// ### function parseValues (any)
|
||||
// #### @any {string} String to parse as json or return as is
|
||||
// try to parse `any` as a json stringified
|
||||
//
|
||||
export function parseValues(value) {
|
||||
if (value === 'undefined') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(value)
|
||||
} catch (ignore) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ### function transform(map, fn)
|
||||
// #### @map {object} Object of key/value pairs to apply `fn` to
|
||||
// #### @fn {function} Transformation function that will be applied to every key/value pair
|
||||
// transform a set of key/value pairs and return the transformed result
|
||||
export function transform(map, fn) {
|
||||
var pairs = Object.keys(map).map(function(key) {
|
||||
var result = fn(key, map[key])
|
||||
|
||||
if (!result) {
|
||||
return null
|
||||
} else if (result.key) {
|
||||
return result
|
||||
}
|
||||
|
||||
throw new Error('Transform function passed to store returned an invalid format: ' + JSON.stringify(result))
|
||||
})
|
||||
|
||||
|
||||
return pairs
|
||||
.filter(function(pair) {
|
||||
return pair !== null
|
||||
})
|
||||
.reduce(function(accumulator, pair) {
|
||||
accumulator[pair.key] = pair.value
|
||||
return accumulator
|
||||
}, {})
|
||||
}
|
130
lib/nconf.js
130
lib/nconf.js
|
@ -1,130 +0,0 @@
|
|||
/*
|
||||
* nconf.js: Top-level include for the nconf module
|
||||
*
|
||||
* (C) 2011, Charlie Robbins
|
||||
*
|
||||
*/
|
||||
|
||||
require.paths.unshift(__dirname);
|
||||
|
||||
var nconf = exports;
|
||||
|
||||
nconf.stores = require('nconf/stores');
|
||||
|
||||
//
|
||||
// ### function use (type, options)
|
||||
// #### @type {string} Type of the nconf store to use.
|
||||
// #### @options {Object} Options for the store instance.
|
||||
// Sets the active `nconf.store` to a new instance of the
|
||||
// specified `type`.
|
||||
//
|
||||
nconf.use = function (type, options) {
|
||||
if (!nconf.store || type.toLowerCase() !== nconf.store.type) {
|
||||
nconf.store = new nconf.stores.create(type, options);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### function get (key, callback)
|
||||
// #### @key {string} Key to retrieve for this instance.
|
||||
// #### @callback {function} **Optional** Continuation to respond to when complete.
|
||||
// Retrieves the value for the specified key (if any).
|
||||
//
|
||||
nconf.get = function (key, callback) {
|
||||
return nconf.store.get(key, callback);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function set (key, value, callback)
|
||||
// #### @key {string} Key to set in this instance
|
||||
// #### @value {literal|Object} Value for the specified key
|
||||
// #### @callback {function} **Optional** Continuation to respond to when complete.
|
||||
// Sets the `value` for the specified `key` in this instance.
|
||||
//
|
||||
nconf.set = function (key, value, callback) {
|
||||
return nconf.store.set(key, value, callback);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function clear (key, callback)
|
||||
// #### @key {string} Key to remove from this instance
|
||||
// #### @callback {function} **Optional** Continuation to respond to when complete.
|
||||
// Removes the value for the specified `key` from this instance.
|
||||
//
|
||||
nconf.clear = function (key, callback) {
|
||||
return nconf.store.clear(key, callback);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function load (callback)
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Responds with an Object representing all keys associated in this instance.
|
||||
//
|
||||
nconf.load = function (callback) {
|
||||
if (!nconf.store.load) {
|
||||
var error = new Error('nconf store ' + nconf.store.type + ' has no load() method');
|
||||
if (callback) {
|
||||
return callback (error);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
return nconf.store.load(callback);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function save (value, callback)
|
||||
// #### @value {Object} **Optional** Config object to set for this instance
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Removes any existing configuration settings that may exist in this
|
||||
// instance and then adds all key-value pairs in `value`.
|
||||
//
|
||||
nconf.save = function (value, callback) {
|
||||
if (!callback) {
|
||||
callback = value;
|
||||
value = null;
|
||||
}
|
||||
|
||||
if (!nconf.store.save) {
|
||||
var error = new Error('nconf store ' + nconf.store.type + ' has no save() method');
|
||||
if (callback) {
|
||||
return callback (error);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
return nconf.store.save(value, callback);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function reset (callback)
|
||||
// #### @callback {function} **Optional** Continuation to respond to when complete.
|
||||
// Clears all keys associated with this instance.
|
||||
//
|
||||
nconf.reset = function (callback) {
|
||||
return nconf.store.reset(callback);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function key (arguments)
|
||||
// Returns a `:` joined string from the `arguments`.
|
||||
//
|
||||
nconf.key = function () {
|
||||
return Array.prototype.slice.call(arguments).join(':');
|
||||
};
|
||||
|
||||
//
|
||||
// ### function path (key)
|
||||
// #### @key {string} The ':' delimited key to split
|
||||
// Returns a fully-qualified path to a nested nconf key.
|
||||
//
|
||||
nconf.path = function (key) {
|
||||
return key.split(':');
|
||||
};
|
||||
|
||||
//
|
||||
// Use the `memory` engine by default
|
||||
//
|
||||
nconf.use('memory');
|
|
@ -0,0 +1,181 @@
|
|||
import fs from 'fs'
|
||||
import { fileURLToPath } from 'url'
|
||||
import path from 'path'
|
||||
import * as common from './common.mjs'
|
||||
import Literal from './stores/literal.mjs'
|
||||
import Memory from './stores/memory.mjs'
|
||||
import File from './stores/file.mjs'
|
||||
import Env from './stores/env.mjs'
|
||||
import Argv from './stores/argv.mjs'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
const pckg = JSON.parse(fs.readFileSync(path.resolve(path.join(__dirname, '../package.json'))))
|
||||
|
||||
const AvailableStores = [
|
||||
['memory', Memory],
|
||||
['file', File],
|
||||
['defaults', Literal],
|
||||
['overrides', Literal],
|
||||
['literal', Literal],
|
||||
['env', Env],
|
||||
['argv', Argv],
|
||||
]
|
||||
|
||||
function Nconf(options) {
|
||||
let opts = options || {}
|
||||
this.sources = []
|
||||
this.using = new Map()
|
||||
this.version = pckg.version
|
||||
this.init()
|
||||
}
|
||||
|
||||
Nconf.prototype.key = common.key
|
||||
Nconf.prototype.path = common.path
|
||||
|
||||
Nconf.prototype.init = function() {
|
||||
AvailableStores.forEach((storeType) => {
|
||||
let nameCapital = common.capitalize(storeType[0])
|
||||
let nameLower = storeType[0].toLowerCase()
|
||||
|
||||
Object.defineProperty(this, nameCapital, {
|
||||
value: storeType[1],
|
||||
writable: false,
|
||||
enumerable: true,
|
||||
})
|
||||
Object.defineProperty(this, nameLower, {
|
||||
value: function(leName, leOpts) {
|
||||
let name = leName
|
||||
let options = leOpts || {}
|
||||
if (typeof(name) !== 'string') {
|
||||
name = nameLower
|
||||
options = leName || {}
|
||||
}
|
||||
this.add(name, new this[nameCapital](options))
|
||||
return this
|
||||
},
|
||||
writable: false,
|
||||
enumerable: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Nconf.prototype.any = function(...items) {
|
||||
let check = items
|
||||
if (items.length === 1 && Array.isArray(items[0])) {
|
||||
check = items[0]
|
||||
}
|
||||
for (let i = 0; i < check.length; i++) {
|
||||
let found = this.get(check[i])
|
||||
if (found) return found
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
Nconf.prototype.get = function(key) {
|
||||
let out = []
|
||||
for (let i = 0; i < this.sources.length; i++) {
|
||||
let found = this.sources[i].get(key)
|
||||
if (found && !out.length && (Array.isArray(found) || typeof(found) !== 'object')) {
|
||||
return found
|
||||
}
|
||||
if (found) {
|
||||
out.push(found)
|
||||
}
|
||||
}
|
||||
if (!out.length) return undefined
|
||||
return common.merge(out.reverse())
|
||||
}
|
||||
Nconf.prototype.set = function(key, value) {
|
||||
for (let i = 0; i < this.sources.length; i++) {
|
||||
if (!this.sources[i].readOnly) {
|
||||
if (this.sources[i].set(key, value))
|
||||
return this
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
Nconf.prototype.clear = function(key) {
|
||||
for (let i = 0; i < this.sources.length; i++) {
|
||||
this.sources[i].clear(key)
|
||||
}
|
||||
if (this.get(key)) {
|
||||
return false
|
||||
}
|
||||
return this
|
||||
}
|
||||
Nconf.prototype.load = function() {
|
||||
for (let i = 0; i < this.sources.length; i++) {
|
||||
if (typeof(this.sources[i].load) === 'function') {
|
||||
this.sources[i].load()
|
||||
}
|
||||
}
|
||||
}
|
||||
Nconf.prototype.save = function() {
|
||||
for (let i = 0; i < this.sources.length; i++) {
|
||||
if (typeof(this.sources[i].save) === 'function') {
|
||||
this.sources[i].save()
|
||||
}
|
||||
}
|
||||
}
|
||||
Nconf.prototype.reset = function() {
|
||||
throw new Error('Deprecated, create new instance instead')
|
||||
}
|
||||
|
||||
Nconf.prototype.required = function(...items) {
|
||||
let check = items
|
||||
if (items.length === 1 && Array.isArray(items[0])) {
|
||||
check = items[0]
|
||||
}
|
||||
let missing = []
|
||||
for (let i = 0; i < check.length; i++) {
|
||||
if (!this.get(check[i])) {
|
||||
missing.push(check[i])
|
||||
}
|
||||
}
|
||||
|
||||
if (missing.length) {
|
||||
throw new Error('Missing required keys: ' + missing.join(', '));
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
Nconf.prototype.add = function(name, store) {
|
||||
let oldStore = this.using.get(name)
|
||||
|
||||
if (typeof(store.load) === 'function') {
|
||||
store.load()
|
||||
}
|
||||
|
||||
if (oldStore) {
|
||||
this.sources.splice(this.sources.indexOf(oldStore), 1)
|
||||
this.using.delete(name)
|
||||
}
|
||||
this.using.set(name, store)
|
||||
this.sources.push(store)
|
||||
}
|
||||
|
||||
Nconf.prototype.use = function(name) {
|
||||
return this.using.get(name)
|
||||
}
|
||||
|
||||
Nconf.register = function(name, val) {
|
||||
AvailableStores.push([name, val])
|
||||
let nameCapital = common.capitalize(name)
|
||||
Object.defineProperty(Nconf, nameCapital, {
|
||||
value: val,
|
||||
writable: false,
|
||||
enumerable: true,
|
||||
})
|
||||
}
|
||||
|
||||
AvailableStores.forEach((storeType) => {
|
||||
let nameCapital = common.capitalize(storeType[0])
|
||||
Object.defineProperty(Nconf, nameCapital, {
|
||||
value: storeType[1],
|
||||
writable: false,
|
||||
enumerable: true,
|
||||
})
|
||||
})
|
||||
|
||||
export default Nconf
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* stores.js: Top-level include for all nconf stores
|
||||
*
|
||||
* (C) 2011, Charlie Robbins
|
||||
*
|
||||
*/
|
||||
|
||||
var stores = exports;
|
||||
|
||||
function capitalize (str) {
|
||||
return str && str[0].toUpperCase() + str.slice(1);
|
||||
};
|
||||
|
||||
stores.Memory = require('nconf/stores/memory').Memory;
|
||||
stores.File = require('nconf/stores/file').File;
|
||||
stores.Redis = require('nconf/stores/redis').Redis;
|
||||
|
||||
//
|
||||
// ### function create (type, options)
|
||||
// #### @type {string} Type of the nconf store to use.
|
||||
// #### @options {Object} Options for the store instance.
|
||||
// Creates a store of the specified `type` using the
|
||||
// specified `options`.
|
||||
//
|
||||
stores.create = function (type, options) {
|
||||
return new stores[capitalize(type.toLowerCase())](options);
|
||||
};
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* file.js: Simple file storage engine for nconf files
|
||||
*
|
||||
* (C) 2011, Charlie Robbins
|
||||
*
|
||||
*/
|
||||
|
||||
var fs = require('fs'),
|
||||
util = require('util'),
|
||||
Memory = require('./memory').Memory;
|
||||
|
||||
//
|
||||
// ### function File (options)
|
||||
// #### @options {Object} Options for this instance
|
||||
// Constructor function for the File nconf store, a simple abstraction
|
||||
// around the Memory store that can persist configuration to disk.
|
||||
//
|
||||
var File = exports.File = function (options) {
|
||||
if (!options.file) {
|
||||
throw new Error ('Missing required option `files`');
|
||||
}
|
||||
|
||||
Memory.call(this, options);
|
||||
|
||||
this.type = 'file';
|
||||
this.file = options.file;
|
||||
this.format = options.format || JSON;
|
||||
};
|
||||
|
||||
// Inherit from the Memory store
|
||||
util.inherits(File, Memory);
|
||||
|
||||
//
|
||||
// ### function save (value, callback)
|
||||
// #### @value {Object} _Ignored_ Left here for consistency
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Saves the current configuration object to disk at `this.file`
|
||||
// using the format specified by `this.format`.
|
||||
//
|
||||
File.prototype.save = function (value, callback) {
|
||||
if (!callback) {
|
||||
callback = value;
|
||||
value = null;
|
||||
}
|
||||
|
||||
fs.writeFile(this.file, this.format.stringify(this.store), function (err) {
|
||||
return err ? callback(err) : callback();
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### function load (callback)
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Responds with an Object representing all keys associated in this instance.
|
||||
//
|
||||
File.prototype.load = function (callback) {
|
||||
var self = this;
|
||||
fs.readFile(this.file, function (err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
data = self.format.parse(data.toString());
|
||||
self.store = data;
|
||||
callback(null, self.store);
|
||||
});
|
||||
};
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* memory.js: Simple memory storage engine for nconf configuration(s)
|
||||
*
|
||||
* (C) 2011, Charlie Robbins
|
||||
*
|
||||
*/
|
||||
|
||||
var nconf = require('nconf');
|
||||
|
||||
//
|
||||
// ### function Memory (options)
|
||||
// #### @options {Object} Options for this instance
|
||||
// Constructor function for the Memory nconf store which maintains
|
||||
// a nested json structure based on key delimiters `:`.
|
||||
//
|
||||
// e.g. `my:nested:key` ==> `{ my: { nested: { key: } } }`
|
||||
//
|
||||
var Memory = exports.Memory = function (options) {
|
||||
options = options || {};
|
||||
this.type = 'memory';
|
||||
this.store = {};
|
||||
this.mtimes = {};
|
||||
};
|
||||
|
||||
//
|
||||
// ### function get (key)
|
||||
// #### @key {string} Key to retrieve for this instance.
|
||||
// Retrieves the value for the specified key (if any).
|
||||
//
|
||||
Memory.prototype.get = function (key) {
|
||||
var target = this.store,
|
||||
path = nconf.path(key);
|
||||
|
||||
//
|
||||
// Scope into the object to get the appropriate nested context
|
||||
//
|
||||
while (path.length > 0) {
|
||||
key = path.shift();
|
||||
if (!target[key]) {
|
||||
return;
|
||||
}
|
||||
|
||||
target = target[key];
|
||||
if (path.length === 0) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### function set (key, value)
|
||||
// #### @key {string} Key to set in this instance
|
||||
// #### @value {literal|Object} Value for the specified key
|
||||
// Sets the `value` for the specified `key` in this instance.
|
||||
//
|
||||
Memory.prototype.set = function (key, value) {
|
||||
var target = this.store,
|
||||
path = nconf.path(key);
|
||||
|
||||
//
|
||||
// Update the `mtime` (modified time) of the key
|
||||
//
|
||||
this.mtimes[key] = Date.now();
|
||||
|
||||
//
|
||||
// Scope into the object to get the appropriate nested context
|
||||
//
|
||||
while (path.length > 1) {
|
||||
key = path.shift();
|
||||
if (!target[key]) {
|
||||
target[key] = {};
|
||||
}
|
||||
|
||||
target = target[key];
|
||||
}
|
||||
|
||||
// Set the specified value in the nested JSON structure
|
||||
key = path.shift();
|
||||
target[key] = value;
|
||||
return true;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function clear (key)
|
||||
// #### @key {string} Key to remove from this instance
|
||||
// Removes the value for the specified `key` from this instance.
|
||||
//
|
||||
Memory.prototype.clear = function (key) {
|
||||
var target = this.store,
|
||||
path = nconf.path(key);
|
||||
|
||||
//
|
||||
// Remove the key from the set of `mtimes` (modified times)
|
||||
//
|
||||
delete this.mtimes[key];
|
||||
|
||||
//
|
||||
// Scope into the object to get the appropriate nested context
|
||||
//
|
||||
while (path.length > 1) {
|
||||
key = path.shift();
|
||||
if (!target[key]) {
|
||||
return;
|
||||
}
|
||||
|
||||
target = target[key];
|
||||
}
|
||||
|
||||
// Delete the key from the nested JSON structure
|
||||
key = path.shift();
|
||||
delete target[key];
|
||||
return true;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function reset (callback)
|
||||
// Clears all keys associated with this instance.
|
||||
//
|
||||
Memory.prototype.reset = function () {
|
||||
this.mtimes = {};
|
||||
this.store = {};
|
||||
return true;
|
||||
}
|
|
@ -1,339 +0,0 @@
|
|||
/*
|
||||
* redis.js: Redis storage engine for nconf configuration(s)
|
||||
*
|
||||
* (C) 2011, Charlie Robbins
|
||||
*
|
||||
*/
|
||||
|
||||
var async = require('async'),
|
||||
redis = require('redis'),
|
||||
nconf = require('nconf'),
|
||||
Memory = require('./Memory').Memory;
|
||||
|
||||
//
|
||||
// ### function Redis (options)
|
||||
// #### @options {Object} Options for this instance
|
||||
// Constructor function for the Redis nconf store which maintains
|
||||
// a nested Redis key structure based on key delimiters `:`.
|
||||
//
|
||||
// e.g.
|
||||
// my:nested:key, 'value'
|
||||
// namespace:keys ==> ['my']
|
||||
// namespace:nested:keys ==> ['key']
|
||||
// namespace:nested:key ==> 'value'
|
||||
//
|
||||
var Redis = exports.Redis = function (options) {
|
||||
options = options || {};
|
||||
this.type = 'redis';
|
||||
this.namespace = options.namespace || 'nconf';
|
||||
this.host = options.host || 'localhost';
|
||||
this.port = options.port || 6379;
|
||||
this.ttl = options.ttl || 60 * 60 * 1000;
|
||||
this.cache = new Memory();
|
||||
this.redis = redis.createClient(options.port, options.host);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function get (key, callback)
|
||||
// #### @key {string} Key to retrieve for this instance.
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Retrieves the value for the specified key (if any).
|
||||
//
|
||||
Redis.prototype.get = function (key, callback) {
|
||||
var self = this,
|
||||
result = {},
|
||||
now = Date.now(),
|
||||
mtime = this.cache.mtimes[key],
|
||||
fullKey = nconf.key(this.namespace, key);
|
||||
|
||||
//
|
||||
// If the key exists in the cache and the ttl is less than
|
||||
// the value set for this instance, return from the cache.
|
||||
//
|
||||
if (mtime && now - mtime < this.ttl) {
|
||||
return callback(null, this.cache.get(key));
|
||||
}
|
||||
|
||||
//
|
||||
// Get the set of all children keys for the `key` supplied. If the value
|
||||
// to be returned is an Object, this list will not be empty.
|
||||
//
|
||||
this.redis.smembers(nconf.key(fullKey, 'keys'), function (err, keys) {
|
||||
function addValue (source, next) {
|
||||
self.get(nconf.key(key, source), function (err, value) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
result[source] = value;
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
if (keys && keys.length > 0) {
|
||||
//
|
||||
// If the value to be retrieved is an Object, recursively attempt
|
||||
// to get the value from redis. Here we use a recursive call to `this.get`
|
||||
// to support nested Object keys.
|
||||
//
|
||||
async.forEach(keys, addValue, function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
self.cache.set(key, result);
|
||||
callback(null, result);
|
||||
})
|
||||
}
|
||||
else {
|
||||
//
|
||||
// If there are no keys, then the value to be retrieved is a literal
|
||||
// and we can simply return the value from redis directly.
|
||||
//
|
||||
self.redis.get(fullKey, function (err, value) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
result = JSON.parse(value);
|
||||
if (result) {
|
||||
self.cache.set(key, result);
|
||||
}
|
||||
|
||||
callback(null, result);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### function set (key, value, callback)
|
||||
// #### @key {string} Key to set in this instance
|
||||
// #### @value {literal|Object} Value for the specified key
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Sets the `value` for the specified `key` in this instance.
|
||||
//
|
||||
Redis.prototype.set = function (key, value, callback) {
|
||||
var self = this,
|
||||
path = nconf.path(key);
|
||||
|
||||
function addKey (partial, next) {
|
||||
var index = path.indexOf(partial),
|
||||
base = [self.namespace].concat(path.slice(0, index)),
|
||||
parent = nconf.key.apply(null, base.concat(['keys']));
|
||||
|
||||
self.redis.sadd(parent, partial, next);
|
||||
};
|
||||
|
||||
//
|
||||
// Iterate over the entire key path and add each key to the
|
||||
// parent key-set if it doesn't exist already.
|
||||
//
|
||||
async.forEach(path, addKey, function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var fullKey = nconf.key(self.namespace, key);
|
||||
|
||||
if (!Array.isArray(value) && typeof value === 'object') {
|
||||
//
|
||||
// If the value is an `Object` (and not an `Array`) then
|
||||
// nest into the value and set the child keys appropriately.
|
||||
// This is done for efficient lookup when setting Object keys.
|
||||
// (i.e. If you set and Object then wish to later retrieve only a
|
||||
// member of that Object, the entire Object need not be retrieved).
|
||||
//
|
||||
self._setObject(fullKey, value, callback);
|
||||
}
|
||||
else {
|
||||
//
|
||||
// If the value is a simple literal (or an `Array`) then JSON
|
||||
// stringify it and put it into Redis.
|
||||
//
|
||||
value = JSON.stringify(value);
|
||||
self.cache.set(key, value);
|
||||
self.redis.set(fullKey, value, callback);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### function clear (key, callback)
|
||||
// #### @key {string} Key to remove from this instance
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Removes the value for the specified `key` from this instance.
|
||||
//
|
||||
Redis.prototype.clear = function (key, callback) {
|
||||
var self = this,
|
||||
result = {},
|
||||
path = [this.namespace].concat(nconf.path(key)),
|
||||
last = path.pop(),
|
||||
fullKey = nconf.key(this.namespace, key);
|
||||
|
||||
//
|
||||
// Clear the key from the cache for this instance
|
||||
//
|
||||
this.cache.clear(key);
|
||||
|
||||
//
|
||||
// Remove the `key` from the parent set of keys.
|
||||
//
|
||||
this.redis.srem(nconf.key.apply(null, path.concat(['keys'])), last, function (err) {
|
||||
//
|
||||
// Remove the value from redis by iterating over the set of keys (if any)
|
||||
// and deleting each value. If no keys, then just delete the simple literal.
|
||||
//
|
||||
self.redis.smembers(nconf.key(fullKey, 'keys'), function (err, keys) {
|
||||
function removeValue (child, next) {
|
||||
//
|
||||
// Recursively call `self.clear` here to ensure we remove any
|
||||
// nested Objects completely from this instance.
|
||||
//
|
||||
self.clear(nconf.key(key, child), next);
|
||||
}
|
||||
|
||||
if (keys && keys.length > 0) {
|
||||
//
|
||||
// If there are child keys then iterate over them,
|
||||
// removing each child along the way.
|
||||
//
|
||||
async.forEach(keys, removeValue, callback);
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Otherwise if this is just a simple literal, then
|
||||
// simply remove it from Redis directly.
|
||||
//
|
||||
self.redis.del(fullKey, callback);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### function save (value, callback)
|
||||
// #### @value {Object} Config object to set for this instance
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Removes any existing configuration settings that may exist in this
|
||||
// instance and then adds all key-value pairs in `value`.
|
||||
//
|
||||
Redis.prototype.save = function (value, callback) {
|
||||
if (Array.isArray(value) || typeof value !== 'object') {
|
||||
return callback(new Error('`value` to be saved must be an object.'));
|
||||
}
|
||||
|
||||
var self = this,
|
||||
keys = Object.keys(value);
|
||||
|
||||
//
|
||||
// Clear all existing keys associated with this instance.
|
||||
//
|
||||
this.reset(function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
//
|
||||
// Iterate over the keys in the new value, setting each of them.
|
||||
//
|
||||
async.forEach(keys, function (key, next) {
|
||||
self.set(key, value[key], next);
|
||||
}, callback);
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### function load (callback)
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Responds with an Object representing all keys associated in this instance.
|
||||
//
|
||||
Redis.prototype.load = function (callback) {
|
||||
var self = this,
|
||||
result = {};
|
||||
|
||||
this.redis.smembers(nconf.key(this.namespace, 'keys'), function (err, keys) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
function addValue (key, next) {
|
||||
self.get(key, function (err, value) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
result[key] = value;
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
async.forEach(keys, addValue, function (err) {
|
||||
return err ? callback(err) : callback(null, result);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### function reset (callback)
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Clears all keys associated with this instance.
|
||||
//
|
||||
Redis.prototype.reset = function (callback) {
|
||||
var self = this;
|
||||
|
||||
//
|
||||
// Get the list of of top-level keys, then clear each of them
|
||||
//
|
||||
this.redis.smembers(nconf.key(this.namespace, 'keys'), function (err, existing) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
async.forEach(existing, function (key, next) {
|
||||
self.clear(key, next);
|
||||
}, callback);
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private function _setObject (key, value, callback)
|
||||
// #### @key {string} Key to set in this instance
|
||||
// #### @value {Object} Value for the specified key
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Internal helper function for setting all keys of a nested object.
|
||||
//
|
||||
Redis.prototype._setObject = function (key, value, callback) {
|
||||
var self = this,
|
||||
keys = Object.keys(value);
|
||||
|
||||
function addValue (child, next) {
|
||||
//
|
||||
// Add the child key to the parent key-set, then set the value.
|
||||
// Recursively call `_setObject` in the event of nested Object(s).
|
||||
//
|
||||
self.redis.sadd(nconf.key(key, 'keys'), child, function (err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
var fullKey = nconf.key(key, child),
|
||||
childValue = value[child];
|
||||
|
||||
if (!Array.isArray(childValue) && typeof childValue === 'object') {
|
||||
self._setObject(fullKey, childValue, next);
|
||||
}
|
||||
else {
|
||||
childValue = JSON.stringify(childValue);
|
||||
self.redis.set(fullKey, childValue, next);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Iterate over the keys of the Object and set the appropriate values.
|
||||
//
|
||||
async.forEach(keys, addValue, function (err) {
|
||||
return err ? callback(err) : callback();
|
||||
});
|
||||
};
|
|
@ -0,0 +1,72 @@
|
|||
import util from 'util'
|
||||
import Memory from './memory.mjs'
|
||||
import * as common from '../common.mjs'
|
||||
|
||||
//
|
||||
// ### function Argv (options)
|
||||
// #### @options {Object} Options for this instance.
|
||||
// Constructor function for the Argv nconf store, a simple abstraction
|
||||
// around the Memory store that can read basic arguments.
|
||||
//
|
||||
const Argv = function(orgOpts) {
|
||||
let options = orgOpts || {}
|
||||
|
||||
Memory.call(this, options)
|
||||
|
||||
this.readOnly = true
|
||||
this.separator = options.separator || ''
|
||||
this.lowerCase = options.lowerCase || false
|
||||
this.parseValues = options.parseValues || false
|
||||
this.transform = options.transform || false
|
||||
this.prefix = options.prefix || '--'
|
||||
this.useEqualsign = options.useEqualsign || false
|
||||
|
||||
if (!this.prefix) {
|
||||
throw new Error('')
|
||||
}
|
||||
}
|
||||
|
||||
// Inherit from the Memory store
|
||||
util.inherits(Argv, Memory)
|
||||
|
||||
//
|
||||
// ### function load ()
|
||||
// Loads the data passed in from `process.env` into this instance.
|
||||
//
|
||||
Argv.prototype.load = function () {
|
||||
this.store = {}
|
||||
let args = process.argv.slice(2)
|
||||
|
||||
this.readOnly = false
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i].startsWith(this.prefix)) {
|
||||
let key = args[i].slice(this.prefix.length)
|
||||
if (this.lowerCase) {
|
||||
key = key.toLowerCase()
|
||||
}
|
||||
if (this.separator) {
|
||||
key = common.key(...key.split(this.separator))
|
||||
}
|
||||
if (this.useEqualsign) {
|
||||
let equalSignIndex = key.indexOf('=')
|
||||
if (equalSignIndex > 0) {
|
||||
this.set(key.slice(0, equalSignIndex), key.slice(equalSignIndex + 1))
|
||||
} else {
|
||||
this.set(key, true)
|
||||
}
|
||||
} else if (args[i + 1] && !args[i + 1].startsWith(this.prefix)) {
|
||||
this.set(key, args[i + 1])
|
||||
i++
|
||||
} else {
|
||||
this.set(key, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.readOnly = true
|
||||
|
||||
return this.store
|
||||
}
|
||||
|
||||
export default Argv
|
|
@ -0,0 +1,102 @@
|
|||
import util from 'util'
|
||||
import Memory from './memory.mjs'
|
||||
import * as common from '../common.mjs'
|
||||
|
||||
//
|
||||
// ### function Env (options)
|
||||
// #### @options {Object} Options for this instance.
|
||||
// Constructor function for the Env nconf store, a simple abstraction
|
||||
// around the Memory store that can read process environment variables.
|
||||
//
|
||||
const Env = function(orgOpts) {
|
||||
let options = orgOpts || {}
|
||||
|
||||
if (Array.isArray(options)) {
|
||||
options = { whitelist: options }
|
||||
}
|
||||
|
||||
Memory.call(this, options)
|
||||
|
||||
this.readOnly = true
|
||||
this.whitelist = options.whitelist || []
|
||||
this.separator = options.separator || ''
|
||||
this.lowerCase = options.lowerCase || false
|
||||
this.parseValues = options.parseValues || false
|
||||
this.transform = options.transform || false
|
||||
|
||||
if (!Array.isArray(this.whitelist)) {
|
||||
throw new Error('Env parameter whitelist was not an array or contained non-string elements')
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.whitelist.length; i++) {
|
||||
if (typeof(this.whitelist[i]) !== 'string') {
|
||||
throw new Error('Env parameter whitelist was not an array or contained non-string elements')
|
||||
}
|
||||
this.whitelist[i] = this.whitelist[i].toLowerCase()
|
||||
}
|
||||
|
||||
if (options.match) {
|
||||
if (typeof(options.match) === 'string') {
|
||||
options.match = new RegExp(options.match)
|
||||
}
|
||||
if (typeof(options.match.test) !== 'function') {
|
||||
throw new Error('Env parameter match was not a valid RegExp')
|
||||
}
|
||||
this.match = options.match
|
||||
}
|
||||
}
|
||||
|
||||
// Inherit from the Memory store
|
||||
util.inherits(Env, Memory)
|
||||
|
||||
//
|
||||
// ### function load ()
|
||||
// Loads the data passed in from `process.env` into this instance.
|
||||
//
|
||||
Env.prototype.load = function () {
|
||||
let env = {}
|
||||
if (this.lowerCase) {
|
||||
Object.keys(process.env).forEach(function (key) {
|
||||
env[key.toLowerCase()] = process.env[key]
|
||||
})
|
||||
} else {
|
||||
env = process.env
|
||||
}
|
||||
|
||||
if (this.transform) {
|
||||
env = common.transform(env, this.transform)
|
||||
}
|
||||
|
||||
this.readOnly = false
|
||||
|
||||
Object.keys(env).filter((key) => {
|
||||
if (this.match && this.whitelist.length) {
|
||||
return key.match(this.match) || this.whitelist.indexOf(key.toLowerCase()) !== -1
|
||||
}
|
||||
else if (this.match) {
|
||||
return key.match(this.match)
|
||||
}
|
||||
else {
|
||||
return !this.whitelist.length || this.whitelist.indexOf(key.toLowerCase()) !== -1
|
||||
}
|
||||
}).forEach((key) => {
|
||||
var val = env[key]
|
||||
|
||||
if (this.parseValues) {
|
||||
val = common.parseValues(val)
|
||||
}
|
||||
|
||||
if (this.separator) {
|
||||
this.set(common.key(...key.split(this.separator)), val)
|
||||
}
|
||||
else {
|
||||
this.set(key, val)
|
||||
}
|
||||
})
|
||||
|
||||
this.readOnly = true
|
||||
|
||||
return this.store
|
||||
}
|
||||
|
||||
export default Env
|
|
@ -0,0 +1,386 @@
|
|||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import util from 'util'
|
||||
import crypto from 'crypto'
|
||||
import Memory from './memory.mjs'
|
||||
|
||||
const fsPromise = fs.promises
|
||||
|
||||
//
|
||||
// ### function File (options)
|
||||
// #### @options {Object} Options for this instance
|
||||
// Constructor function for the File nconf store, a simple abstraction
|
||||
// around the Memory store that can persist configuration to disk.
|
||||
//
|
||||
const File = function (orgOpts) {
|
||||
let options = orgOpts
|
||||
if (typeof(options) === 'string') {
|
||||
options = { file: options }
|
||||
}
|
||||
if (!options || !options.file) {
|
||||
throw new Error('Missing required option `file`')
|
||||
}
|
||||
|
||||
Memory.call(this, options)
|
||||
|
||||
this.file = options.file
|
||||
// this.dir = options.dir || process.cwd()
|
||||
this.format = options.format || JSON
|
||||
this.secure = options.secure
|
||||
// this.spacing = options.json_spacing || options.spacing || 2
|
||||
|
||||
if (this.secure) {
|
||||
this.secure = typeof(this.secure === 'string')
|
||||
? { secret: this.secure.toString() }
|
||||
: this.secure
|
||||
|
||||
this.secure.alg = this.secure.alg || 'aes-256-ctr'
|
||||
// if (this.secure.secretPath) {
|
||||
// this.secure.secret = fs.readFileSync(this.secure.secretPath, 'utf8')
|
||||
// }
|
||||
|
||||
if (!this.secure.secret) {
|
||||
throw new Error('secure.secret option is required')
|
||||
}
|
||||
}
|
||||
|
||||
// if (options.search) {
|
||||
// this.search(this.dir)
|
||||
// }
|
||||
}
|
||||
|
||||
// Inherit from the Memory store
|
||||
util.inherits(File, Memory)
|
||||
|
||||
File.prototype.load = function () {
|
||||
this.store = {}
|
||||
|
||||
let fileData
|
||||
try {
|
||||
fileData = fs.readFileSync(this.file, 'utf8')
|
||||
}
|
||||
catch (ex) {
|
||||
throw new Error('Error opening ' + this.file + ': ' + ex.message)
|
||||
}
|
||||
|
||||
// Deals with file that include BOM
|
||||
if (fileData.charAt(0) === '\uFEFF') {
|
||||
fileData = fileData.substr(1)
|
||||
}
|
||||
|
||||
try {
|
||||
this.store = this.parse(fileData)
|
||||
}
|
||||
catch (ex) {
|
||||
throw new Error("Error parsing your configuration file: [" + this.file + ']: ' + ex.message)
|
||||
}
|
||||
|
||||
return this.store
|
||||
}
|
||||
|
||||
File.prototype.loadAsync = function () {
|
||||
this.store = {}
|
||||
|
||||
return fsPromise.readFile(this.file, 'utf8')
|
||||
.then(fileData => {
|
||||
let data = fileData
|
||||
if (data.charAt(0) === '\uFEFF') {
|
||||
data = data.substr(1)
|
||||
}
|
||||
|
||||
try {
|
||||
this.store = this.parse(data)
|
||||
} catch (err) {
|
||||
return Promise.reject(new Error("Error parsing your configuration file: [" + this.file + ']: ' + err.message))
|
||||
}
|
||||
|
||||
return this.store
|
||||
}, err => {
|
||||
return Promise.reject(new Error('Error opening ' + this.file + ': ' + err.message))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ### function parse (contents)
|
||||
// Returns a decrypted version of the contents IFF
|
||||
// `this.secure` is enabled.
|
||||
//
|
||||
File.prototype.parse = function (contents) {
|
||||
let parsed = this.format.parse(contents)
|
||||
|
||||
if (this.secure) {
|
||||
parsed = Object.keys(parsed).reduce((acc, key) => {
|
||||
let value = parsed[key]
|
||||
if (!value.iv) {
|
||||
throw new Error(`Encrypted file ${this.file} is outdated (encrypted without iv). Please re-encrypt your file.`)
|
||||
}
|
||||
let decipher = crypto.createDecipheriv(value.alg, this.secure.secret, Buffer.from(value.iv, 'hex'))
|
||||
let plaintext = decipher.update(value.value, 'hex', 'utf8')
|
||||
plaintext += decipher.final('utf8')
|
||||
acc[key] = this.format.parse(plaintext)
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
|
||||
return parsed
|
||||
}
|
||||
|
||||
//
|
||||
// ### function save (path)
|
||||
// #### @path {string} The path to the file where we save the configuration to
|
||||
// Saves the current configuration object to disk at `this.file`
|
||||
//
|
||||
File.prototype.save = function (orgPath) {
|
||||
let path = orgPath
|
||||
if (!path) {
|
||||
path = this.file
|
||||
}
|
||||
fs.writeFileSync(path, this.stringify())
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
//
|
||||
// ### function save (path)
|
||||
// #### @path {string} The path to the file where we save the configuration to
|
||||
// Saves the current configuration object to disk at `this.file`
|
||||
//
|
||||
File.prototype.saveAsync = function(orgPath) {
|
||||
let path = orgPath
|
||||
if (!path) {
|
||||
path = this.file
|
||||
}
|
||||
|
||||
return fsPromise.writeFile(path, this.stringify()).then(() => {
|
||||
return this
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
// ### function stringify ()
|
||||
// Returns an encrypted version of the contents IIF
|
||||
// `this.secure` is enabled
|
||||
//
|
||||
File.prototype.stringify = function () {
|
||||
let data = this.store
|
||||
|
||||
if (this.secure) {
|
||||
data = Object.keys(data).reduce((acc, key) => {
|
||||
let value = this.format.stringify(data[key])
|
||||
let iv = crypto.randomBytes(16)
|
||||
let cipher = crypto.createCipheriv(this.secure.alg, this.secure.secret, iv)
|
||||
let ciphertext = cipher.update(value, 'utf8', 'hex')
|
||||
ciphertext += cipher.final('hex')
|
||||
acc[key] = { alg: this.secure.alg, value: ciphertext, iv: iv.toString('hex') }
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
|
||||
return this.format.stringify(data, null, this.spacing)
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
//
|
||||
// ### function save (value, callback)
|
||||
// #### @value {Object} _Ignored_ Left here for consistency
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Saves the current configuration object to disk at `this.file`
|
||||
// using the format specified by `this.format`.
|
||||
//
|
||||
File.prototype.save = function (value, callback) {
|
||||
this.saveToFile(this.file, value, callback)
|
||||
}
|
||||
|
||||
//
|
||||
// ### function saveToFile (path, value, callback)
|
||||
// #### @path {string} The path to the file where we save the configuration to
|
||||
// #### @format {Object} Optional formatter, default behing the one of the store
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Saves the current configuration object to disk at `this.file`
|
||||
// using the format specified by `this.format`.
|
||||
//
|
||||
File.prototype.saveToFile = function (path, format, callback) {
|
||||
if (!callback) {
|
||||
callback = format
|
||||
format = this.format
|
||||
}
|
||||
|
||||
fs.writeFile(path, this.stringify(format), callback)
|
||||
}
|
||||
|
||||
//
|
||||
// ### function saveSync (value, callback)
|
||||
// Saves the current configuration object to disk at `this.file`
|
||||
// using the format specified by `this.format` synchronously.
|
||||
//
|
||||
File.prototype.saveSync = function () {
|
||||
fs.writeFileSync(this.file, this.stringify())
|
||||
return this.store
|
||||
}
|
||||
|
||||
//
|
||||
// ### function load (callback)
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Responds with an Object representing all keys associated in this instance.
|
||||
//
|
||||
File.prototype.load = function (callback) {
|
||||
let self = this
|
||||
|
||||
exists(self.file, function (exists) {
|
||||
if (!exists) {
|
||||
return callback(null, {})
|
||||
}
|
||||
|
||||
//
|
||||
// Else, the path exists, read it from disk
|
||||
//
|
||||
fs.readFile(self.file, function (err, data) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
try {
|
||||
// Deals with string that include BOM
|
||||
let stringData = data.toString()
|
||||
if (stringData.charAt(0) === '\uFEFF') {
|
||||
stringData = stringData.substr(1)
|
||||
}
|
||||
|
||||
self.store = self.parse(stringData)
|
||||
}
|
||||
catch (ex) {
|
||||
return callback(new Error("Error parsing your configuration file: [" + self.file + ']: ' + ex.message))
|
||||
}
|
||||
|
||||
callback(null, self.store)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
// ### function loadSync (callback)
|
||||
// Attempts to load the data stored in `this.file` synchronously
|
||||
// and responds appropriately.
|
||||
//
|
||||
File.prototype.loadSync = function () {
|
||||
if (!existsSync(this.file)) {
|
||||
this.store = {}
|
||||
return this.store
|
||||
}
|
||||
|
||||
//
|
||||
// Else, the path exists, read it from disk
|
||||
//
|
||||
try {
|
||||
// Deals with file that include BOM
|
||||
let fileData = fs.readFileSync(this.file, 'utf8')
|
||||
if (fileData.charAt(0) === '\uFEFF') {
|
||||
fileData = fileData.substr(1)
|
||||
}
|
||||
|
||||
this.store = this.parse(fileData)
|
||||
}
|
||||
catch (ex) {
|
||||
throw new Error("Error parsing your configuration file: [" + this.file + ']: ' + ex.message)
|
||||
}
|
||||
|
||||
return this.store
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ### function search (base)
|
||||
// #### @base {string} Base directory (or file) to begin searching for the target file.
|
||||
// Attempts to find `this.file` by iteratively searching up the
|
||||
// directory structure
|
||||
//
|
||||
File.prototype.search = function (base) {
|
||||
let looking = true,
|
||||
fullpath,
|
||||
previous,
|
||||
stats
|
||||
|
||||
base = base || process.cwd()
|
||||
|
||||
if (this.file[0] === '/') {
|
||||
//
|
||||
// If filename for this instance is a fully qualified path
|
||||
// (i.e. it starts with a `'/'`) then check if it exists
|
||||
//
|
||||
try {
|
||||
stats = fs.statSync(fs.realpathSync(this.file))
|
||||
if (stats.isFile()) {
|
||||
fullpath = this.file
|
||||
looking = false
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
//
|
||||
// Ignore errors
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
if (looking && base) {
|
||||
//
|
||||
// Attempt to stat the realpath located at `base`
|
||||
// if the directory does not exist then return false.
|
||||
//
|
||||
try {
|
||||
let stat = fs.statSync(fs.realpathSync(base))
|
||||
looking = stat.isDirectory()
|
||||
}
|
||||
catch (ex) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
while (looking) {
|
||||
//
|
||||
// Iteratively look up the directory structure from `base`
|
||||
//
|
||||
try {
|
||||
stats = fs.statSync(fs.realpathSync(fullpath = path.join(base, this.file)))
|
||||
looking = stats.isDirectory()
|
||||
}
|
||||
catch (ex) {
|
||||
previous = base
|
||||
base = path.dirname(base)
|
||||
|
||||
if (previous === base) {
|
||||
//
|
||||
// If we've reached the top of the directory structure then simply use
|
||||
// the default file path.
|
||||
//
|
||||
try {
|
||||
stats = fs.statSync(fs.realpathSync(fullpath = path.join(this.dir, this.file)))
|
||||
if (stats.isDirectory()) {
|
||||
fullpath = undefined
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
//
|
||||
// Ignore errors
|
||||
//
|
||||
}
|
||||
|
||||
looking = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Set the file for this instance to the fullpath
|
||||
// that we have found during the search. In the event that
|
||||
// the search was unsuccessful use the original value for `this.file`.
|
||||
//
|
||||
this.file = fullpath || this.file
|
||||
|
||||
return fullpath
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
export default File
|
|
@ -0,0 +1,15 @@
|
|||
import { inherits } from 'util'
|
||||
import Memory from './memory.mjs'
|
||||
|
||||
function Literal (options) {
|
||||
Memory.call(this, options)
|
||||
|
||||
this.type = 'literal'
|
||||
this.readOnly = true
|
||||
this.store = options
|
||||
}
|
||||
|
||||
// Inherit from Memory store.
|
||||
inherits(Literal, Memory)
|
||||
|
||||
export default Literal
|
|
@ -0,0 +1,212 @@
|
|||
import * as common from '../common.mjs'
|
||||
|
||||
//
|
||||
// ### function Memory (options)
|
||||
// #### @options {Object} Options for this instance
|
||||
// Constructor function for the Memory nconf store which maintains
|
||||
// a nested json structure based on key delimiters `:`.
|
||||
//
|
||||
// e.g. `my:nested:key` ==> `{ my: { nested: { key: } } }`
|
||||
//
|
||||
function Memory(orgOpts) {
|
||||
let options = orgOpts || {}
|
||||
this.type = 'memory'
|
||||
this.store = {}
|
||||
this.readOnly = options.readOnly || false
|
||||
this.logicalSeparator = options.logicalSeparator || ':'
|
||||
this.parseValues = options.parseValues || false
|
||||
}
|
||||
|
||||
//
|
||||
// ### function get (key)
|
||||
// #### @key {string} Key to retrieve for this instance.
|
||||
// Retrieves the value for the specified key (if any).
|
||||
//
|
||||
Memory.prototype.get = function (key) {
|
||||
var target = this.store,
|
||||
path = common.path(key, this.logicalSeparator)
|
||||
|
||||
//
|
||||
// Scope into the object to get the appropriate nested context
|
||||
//
|
||||
while (path.length > 0) {
|
||||
key = path.shift()
|
||||
if (target && typeof target !== 'string' && target.hasOwnProperty(key)) {
|
||||
target = target[key]
|
||||
continue
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
return target
|
||||
}
|
||||
|
||||
//
|
||||
// ### function set (key, value)
|
||||
// #### @key {string} Key to set in this instance
|
||||
// #### @value {literal|Object} Value for the specified key
|
||||
// Sets the `value` for the specified `key` in this instance.
|
||||
//
|
||||
Memory.prototype.set = function (orgKey, orgValue) {
|
||||
if (this.readOnly) {
|
||||
return false
|
||||
}
|
||||
|
||||
let key = orgKey
|
||||
let value = orgValue
|
||||
|
||||
if (value === undefined && typeof(key) === 'object') {
|
||||
key = null
|
||||
value = orgKey
|
||||
}
|
||||
|
||||
let target = this.store
|
||||
let path = common.path(key, this.logicalSeparator)
|
||||
|
||||
if (path.length === 0) {
|
||||
//
|
||||
// Root must be an object
|
||||
//
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
return false
|
||||
}
|
||||
|
||||
this.store = value
|
||||
return true
|
||||
}
|
||||
|
||||
key = path.shift()
|
||||
|
||||
//
|
||||
// Scope into the object to get the appropriate nested context
|
||||
//
|
||||
while (path.length) {
|
||||
if (!target[key]) {
|
||||
target[key] = {}
|
||||
}
|
||||
|
||||
target = target[key]
|
||||
key = path.shift()
|
||||
}
|
||||
|
||||
if (this.parseValues) {
|
||||
value = common.parseValues(value)
|
||||
}
|
||||
if (value) {
|
||||
if (Array.isArray(value)) {
|
||||
value = common.mergeRecursiveArray(value)
|
||||
} else if (typeof(value) === 'object') {
|
||||
value = common.merge([value])
|
||||
}
|
||||
}
|
||||
target[key] = value
|
||||
return true
|
||||
}
|
||||
|
||||
//
|
||||
// ### function clear (key)
|
||||
// #### @key {string} Key to remove from this instance
|
||||
// Removes the value for the specified `key` from this instance.
|
||||
//
|
||||
Memory.prototype.clear = function (key) {
|
||||
if (this.readOnly) {
|
||||
return false
|
||||
}
|
||||
|
||||
let target = this.store
|
||||
let value = target
|
||||
let path = common.path(key, this.logicalSeparator)
|
||||
|
||||
//
|
||||
// Scope into the object to get the appropriate nested context
|
||||
//
|
||||
let i = 0
|
||||
for (; i < path.length - 1; i++) {
|
||||
key = path[i]
|
||||
value = target[key]
|
||||
if (typeof value !== 'function' && typeof value !== 'object') {
|
||||
return false
|
||||
}
|
||||
target = value
|
||||
}
|
||||
|
||||
// Delete the key from the nested JSON structure
|
||||
key = path[i]
|
||||
delete target[key]
|
||||
return true
|
||||
}
|
||||
|
||||
//
|
||||
// ### function merge (key, value)
|
||||
// #### @key {string} Key to merge the value into
|
||||
// #### @value {literal|Object} Value to merge into the key
|
||||
// Merges the properties in `value` into the existing object value
|
||||
// at `key`.
|
||||
//
|
||||
Memory.prototype.merge = function (orgFullKey, orgValue) {
|
||||
if (this.readOnly) {
|
||||
return false
|
||||
}
|
||||
|
||||
let fullKey = orgFullKey
|
||||
let value = orgValue
|
||||
|
||||
// If fullkey is an object, do basic merge on root
|
||||
if (typeof(fullKey) === 'object') {
|
||||
this.store = common.merge(this.store, [fullKey])
|
||||
return true
|
||||
}
|
||||
|
||||
if (typeof(fullKey) === 'number') {
|
||||
fullKey = fullKey.toString()
|
||||
}
|
||||
|
||||
let target = this.store
|
||||
let path = common.path(fullKey, this.logicalSeparator)
|
||||
let key = path.shift()
|
||||
|
||||
//
|
||||
// Scope into the object to get the appropriate nested context
|
||||
//
|
||||
while (path.length) {
|
||||
if (!target[key]) {
|
||||
target[key] = {}
|
||||
}
|
||||
|
||||
target = target[key]
|
||||
key = path.shift()
|
||||
}
|
||||
|
||||
// Check if we actually need to do any merging. Sometimes a simple assign or "set"
|
||||
// is all that is needed. This might be instances where the value is "null" (which
|
||||
// would mean no merging is required) or if we're dealing with arrays on either side.
|
||||
if (!value || typeof(value) !== 'object' || Array.isArray(value) || !target[key] || typeof(target[key]) !== 'object' || Array.isArray(target[key])) {
|
||||
return this.set(fullKey, value)
|
||||
}
|
||||
|
||||
target[key] = common.merge(target[key], [value])
|
||||
return true
|
||||
}
|
||||
|
||||
//
|
||||
// ### function reset (callback)
|
||||
// Clears all keys associated with this instance.
|
||||
//
|
||||
Memory.prototype.reset = function () {
|
||||
if (this.readOnly) {
|
||||
return false
|
||||
}
|
||||
|
||||
this.store = {}
|
||||
return true
|
||||
}
|
||||
|
||||
//
|
||||
// ### function loadSync
|
||||
// Returns the store managed by this instance
|
||||
//
|
||||
Memory.prototype.loadSync = function () {
|
||||
return this.store || {}
|
||||
}
|
||||
|
||||
export default Memory
|
49
package.json
49
package.json
|
@ -1,19 +1,42 @@
|
|||
{
|
||||
"name": "nconf",
|
||||
"description": "A hybrid local / remote configuration storage library for node.js.",
|
||||
"version": "0.1.1",
|
||||
"author": "Charlie Robbins <charlie.robbins@gmail.com>",
|
||||
"name": "nconf-lite",
|
||||
"description": "Zero dependency hierarchical node.js configuration with files, environment variables, command-line arguments, and atomic object merging.",
|
||||
"version": "2.1.0",
|
||||
"author": "Jonatan Nilsson <jonatan@nilsson.is>",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/indexzero/nconf.git"
|
||||
"url": "http://github.com/nfp-projects/nconf-lite.git"
|
||||
},
|
||||
"keywords": ["configuration", "key value store", "redis"],
|
||||
"dependencies": {
|
||||
"async": ">= 0.1.8",
|
||||
"redis": ">= 0.5.9",
|
||||
"vows": ">= 0.5.8"
|
||||
"keywords": [
|
||||
"configuration",
|
||||
"key value store",
|
||||
"plugabble"
|
||||
],
|
||||
"watch": {
|
||||
"test": {
|
||||
"patterns": [
|
||||
"{lib,test}/*"
|
||||
],
|
||||
"extensions": "js,mjs",
|
||||
"quiet": true,
|
||||
"inherit": true
|
||||
}
|
||||
},
|
||||
"main": "./lib/nconf",
|
||||
"scripts": { "test": "vows test/*-test.js --spec" },
|
||||
"engines": { "node": ">= 0.4.5" }
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"eltro": "^1.0.2"
|
||||
},
|
||||
"main": "./lib/nconf.mjs",
|
||||
"scripts": {
|
||||
"test": "eltro test/**/*.test.mjs -r dot",
|
||||
"test:watch": "npm-watch test",
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 13.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,258 @@
|
|||
import { Eltro as t, assert} from 'eltro'
|
||||
import * as common from '../lib/common.mjs'
|
||||
|
||||
t.describe('#validkeyvalue', function() {
|
||||
t.test('should return key if valid key', function() {
|
||||
assert.strictEqual(common.validkeyvalue('asdf'), null)
|
||||
assert.strictEqual(common.validkeyvalue(''), null)
|
||||
assert.strictEqual(common.validkeyvalue(), null)
|
||||
assert.strictEqual(common.validkeyvalue(null), null)
|
||||
assert.strictEqual(common.validkeyvalue(undefined), null)
|
||||
})
|
||||
t.test('should return invalid valuetype in result', function() {
|
||||
assert.strictEqual(common.validkeyvalue([]), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.validkeyvalue({}), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.validkeyvalue([]), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.validkeyvalue({}), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.validkeyvalue(() => {}), '__invalid_valuetype_of_function__')
|
||||
assert.strictEqual(common.validkeyvalue(function() {}), '__invalid_valuetype_of_function__')
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#path()', function() {
|
||||
t.test('it should support normal operation', function() {
|
||||
assert.deepStrictEqual(common.path('a:b:c'), ['a','b','c'])
|
||||
assert.deepStrictEqual(common.path('a'), ['a'])
|
||||
})
|
||||
t.test('it should support different separator', function() {
|
||||
assert.deepStrictEqual(common.path('a:b:c', '__'), ['a:b:c'])
|
||||
assert.deepStrictEqual(common.path('a__b__c', '__'), ['a','b','c'])
|
||||
assert.deepStrictEqual(common.path('a', '__'), ['a'])
|
||||
})
|
||||
t.test('it should work with non-string keys', function() {
|
||||
assert.deepStrictEqual(common.path(1, '__'), ['1'])
|
||||
assert.deepStrictEqual(common.path(4.3, '__'), ['4.3'])
|
||||
})
|
||||
t.test('it should return invalid value on non-supported keys', function() {
|
||||
assert.deepStrictEqual(common.path([], '__'), ['__invalid_valuetype_of_object__'])
|
||||
assert.strictEqual(common.path([], '__').length, 1)
|
||||
assert.deepStrictEqual(common.path({}, '__'), ['__invalid_valuetype_of_object__'])
|
||||
assert.strictEqual(common.path({}, '__').length, 1)
|
||||
assert.deepStrictEqual(common.path([]), ['__invalid_valuetype_of_object__'])
|
||||
assert.strictEqual(common.path([]).length, 1)
|
||||
assert.deepStrictEqual(common.path({}), ['__invalid_valuetype_of_object__'])
|
||||
assert.strictEqual(common.path({}).length, 1)
|
||||
assert.deepStrictEqual(common.path(() => {}), ['__invalid_valuetype_of_function__'])
|
||||
assert.strictEqual(common.path(() => {}).length, 1)
|
||||
assert.deepStrictEqual(common.path(function() {}), ['__invalid_valuetype_of_function__'])
|
||||
assert.strictEqual(common.path(function() {}).length, 1)
|
||||
})
|
||||
t.test('it should support empty values and return empty path', function() {
|
||||
assert.deepStrictEqual(common.path(null, '__'), [])
|
||||
assert.strictEqual(common.path(null, '__').length, 0)
|
||||
assert.deepStrictEqual(common.path(undefined, '__'), [])
|
||||
assert.strictEqual(common.path(undefined, '__').length, 0)
|
||||
assert.deepStrictEqual(common.path('', '__'), [])
|
||||
assert.strictEqual(common.path('', '__').length, 0)
|
||||
assert.deepStrictEqual(common.path(null), [])
|
||||
assert.strictEqual(common.path(null).length, 0)
|
||||
assert.deepStrictEqual(common.path(undefined), [])
|
||||
assert.strictEqual(common.path(undefined).length, 0)
|
||||
assert.deepStrictEqual(common.path(''), [])
|
||||
assert.strictEqual(common.path('').length, 0)
|
||||
assert.deepStrictEqual(common.path(), [])
|
||||
assert.strictEqual(common.path().length, 0)
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#key()', function() {
|
||||
t.test('it should work with common values', function() {
|
||||
assert.strictEqual(common.key('a'), 'a')
|
||||
assert.strictEqual(common.key('a', 'b'), 'a:b')
|
||||
assert.strictEqual(common.key('a', 'b', 'c'), 'a:b:c')
|
||||
assert.strictEqual(common.key(123), '123')
|
||||
assert.strictEqual(common.key(5.4), '5.4')
|
||||
assert.strictEqual(common.key('a', 123, 'b'), 'a:123:b')
|
||||
assert.strictEqual(common.key('a', 5.4, 'b'), 'a:5.4:b')
|
||||
assert.strictEqual(common.key('a', 123, 456), 'a:123:456')
|
||||
assert.strictEqual(common.key('a', 5.4, 456), 'a:5.4:456')
|
||||
})
|
||||
t.test('it should text replace invalid keys with the invalid value string', function() {
|
||||
assert.strictEqual(common.key([]), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.key({}), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.key([]), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.key({}), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.key(() => {}), '__invalid_valuetype_of_function__')
|
||||
assert.strictEqual(common.key(function() {}), '__invalid_valuetype_of_function__')
|
||||
assert.strictEqual(common.key('a', [], 'b'), 'a:__invalid_valuetype_of_object__:b')
|
||||
assert.strictEqual(common.key('a', {}, 'b'), 'a:__invalid_valuetype_of_object__:b')
|
||||
assert.strictEqual(common.key('a', [], 'b'), 'a:__invalid_valuetype_of_object__:b')
|
||||
assert.strictEqual(common.key('a', {}, 'b'), 'a:__invalid_valuetype_of_object__:b')
|
||||
assert.strictEqual(common.key('a', () => {}, 'b'), 'a:__invalid_valuetype_of_function__:b')
|
||||
assert.strictEqual(common.key('a', function() {}, 'b'), 'a:__invalid_valuetype_of_function__:b')
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#keyed()', function() {
|
||||
t.test('it should work with common values', function() {
|
||||
assert.strictEqual(common.keyed('__', 'a'), 'a')
|
||||
assert.strictEqual(common.keyed('__', 'a', 'b'), 'a__b')
|
||||
assert.strictEqual(common.keyed('__', 'a', 'b', 'c'), 'a__b__c')
|
||||
assert.strictEqual(common.keyed('__', 123), '123')
|
||||
assert.strictEqual(common.keyed('__', 5.4), '5.4')
|
||||
assert.strictEqual(common.keyed('__', 'a', 123, 'b'), 'a__123__b')
|
||||
assert.strictEqual(common.keyed('__', 'a', 5.4, 'b'), 'a__5.4__b')
|
||||
assert.strictEqual(common.keyed('__', 'a', 123, 456), 'a__123__456')
|
||||
assert.strictEqual(common.keyed('__', 'a', 5.4, 456), 'a__5.4__456')
|
||||
})
|
||||
t.test('it should text replace invalid keys with the invalid value string', function() {
|
||||
assert.strictEqual(common.keyed('__', []), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.keyed('__', {}), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.keyed('__', []), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.keyed('__', {}), '__invalid_valuetype_of_object__')
|
||||
assert.strictEqual(common.keyed('__', () => {}), '__invalid_valuetype_of_function__')
|
||||
assert.strictEqual(common.keyed('__', function() {}), '__invalid_valuetype_of_function__')
|
||||
assert.strictEqual(common.keyed('__', 'a', [], 'b'), 'a____invalid_valuetype_of_object____b')
|
||||
assert.strictEqual(common.keyed('__', 'a', {}, 'b'), 'a____invalid_valuetype_of_object____b')
|
||||
assert.strictEqual(common.keyed('__', 'a', [], 'b'), 'a____invalid_valuetype_of_object____b')
|
||||
assert.strictEqual(common.keyed('__', 'a', {}, 'b'), 'a____invalid_valuetype_of_object____b')
|
||||
assert.strictEqual(common.keyed('__', 'a', () => {}, 'b'), 'a____invalid_valuetype_of_function____b')
|
||||
assert.strictEqual(common.keyed('__', 'a', function() {}, 'b'), 'a____invalid_valuetype_of_function____b')
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#merge()', function() {
|
||||
t.test('should throw if not sent an array', function() {
|
||||
assert.throws(function() { common.merge({}) })
|
||||
assert.throws(function() { common.merge('asdf') })
|
||||
assert.throws(function() { common.merge(12412) })
|
||||
assert.throws(function() { common.merge(null) })
|
||||
assert.throws(function() { common.merge(undefined) })
|
||||
assert.throws(function() { common.merge() })
|
||||
})
|
||||
|
||||
t.test('it should be able to merge properly', function() {
|
||||
// Test individual check and then re-check that the original are untouched
|
||||
let fn = function() { return true }
|
||||
let a = null
|
||||
let b = null
|
||||
let c = null
|
||||
|
||||
|
||||
a = { a: 1 }
|
||||
b = { b: 2 }
|
||||
assert.deepStrictEqual(common.merge([a, b]), { a: 1, b: 2 })
|
||||
assert.deepStrictEqual(a, { a: 1 })
|
||||
assert.deepStrictEqual(b, { b: 2 })
|
||||
|
||||
a = { a: 1 }
|
||||
b = { b: 2 }
|
||||
c = { a: 3 }
|
||||
assert.deepStrictEqual(common.merge([a, b, c]), { a: 3, b: 2 })
|
||||
assert.deepStrictEqual(a, { a: 1 })
|
||||
assert.deepStrictEqual(b, { b: 2 })
|
||||
assert.deepStrictEqual(c, { a: 3 })
|
||||
|
||||
a = { a: [1, 2] }
|
||||
b = { a: [2, 3] }
|
||||
assert.deepStrictEqual(common.merge([a, b]), { a: [2, 3] })
|
||||
assert.deepStrictEqual(b, { a: [2, 3] })
|
||||
assert.deepStrictEqual(a, { a: [1, 2] })
|
||||
|
||||
a = { a: [1, 2] }
|
||||
b = { a: [2, [3, 4]] }
|
||||
assert.deepStrictEqual(common.merge([a, b]), { a: [2, [3, 4]] })
|
||||
assert.deepStrictEqual(a, { a: [1, 2] })
|
||||
assert.deepStrictEqual(b, { a: [2, [3, 4]] })
|
||||
|
||||
a = { a: fn }
|
||||
b = { b: 2 }
|
||||
assert.deepStrictEqual(common.merge([a, b]), { a: fn, b: 2 })
|
||||
assert.deepStrictEqual(a, { a: fn })
|
||||
assert.deepStrictEqual(b, { b: 2 })
|
||||
|
||||
a = { a: fn }
|
||||
b = { b: 2 }
|
||||
c = { a: 3 }
|
||||
assert.deepStrictEqual(common.merge([a, b, c]), { a: 3, b: 2 })
|
||||
assert.deepStrictEqual(a, { a: fn })
|
||||
assert.deepStrictEqual(b, { b: 2 })
|
||||
assert.deepStrictEqual(c, { a: 3 })
|
||||
|
||||
a = { apples: true, bananas: true, foo: { bar: "boo" }, candy: { something: "file1", something1: true, something2: true, something5: { first: 1, second: 2 } }, unicorn: { exists: true }}
|
||||
b = { candy: { something: "file2", something3: true, something4: true }, dates: true, elderberries: true, unicorn: null }
|
||||
assert.deepStrictEqual(common.merge([a, b]), { apples: true, bananas: true, foo: { bar: "boo" }, candy: { something: "file2", something1: true, something2: true, something3: true, something4: true, something5: { first: 1, second: 2 } }, dates: true, elderberries: true, unicorn: null })
|
||||
assert.deepStrictEqual(a, { apples: true, bananas: true, foo: { bar: "boo" }, candy: { something: "file1", something1: true, something2: true, something5: { first: 1, second: 2 } }, unicorn: { exists: true }})
|
||||
assert.deepStrictEqual(b, { candy: { something: "file2", something3: true, something4: true }, dates: true, elderberries: true, unicorn: null })
|
||||
|
||||
// weird behavior from old merge but I have no better idea to turn arrays
|
||||
// into object so this is "good enough" for now
|
||||
a = { a: 1 }
|
||||
b = { a: 2 }
|
||||
c = ['test']
|
||||
assert.deepStrictEqual(common.merge([a, b, c]), { '0': 'test', a: 2 })
|
||||
assert.deepStrictEqual(a, { a: 1 })
|
||||
assert.deepStrictEqual(b, { a: 2 })
|
||||
assert.deepStrictEqual(c, ['test'])
|
||||
})
|
||||
|
||||
t.test('it should support edge cases properly', function() {
|
||||
let a = { a: { b: 1 } }
|
||||
let b = { a: ['test'] }
|
||||
let out = common.merge([a, b])
|
||||
assert.deepStrictEqual(out, { a: ['test'] })
|
||||
b = { a: { b: 1 } }
|
||||
out = common.merge(out, [b])
|
||||
assert.deepStrictEqual(out, { a: { b: 1 } })
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
t.describe('#capitalize()', function() {
|
||||
t.test('should return original if not string', function() {
|
||||
const assertObject = {}
|
||||
const assertArray = []
|
||||
assert.strictEqual(common.capitalize(assertObject), assertObject)
|
||||
assert.strictEqual(common.capitalize(assertArray), assertArray)
|
||||
assert.strictEqual(common.capitalize(null), null)
|
||||
assert.strictEqual(common.capitalize(undefined), undefined)
|
||||
assert.strictEqual(common.capitalize(), undefined)
|
||||
})
|
||||
|
||||
t.test('should adapt value to string if value type', function() {
|
||||
assert.strictEqual(common.capitalize(12412), '12412')
|
||||
assert.strictEqual(common.capitalize(123.4), '123.4')
|
||||
})
|
||||
|
||||
|
||||
t.test('should otherwise capitalize', function() {
|
||||
assert.strictEqual(common.capitalize('asdf'), 'Asdf')
|
||||
assert.strictEqual(common.capitalize('test test'), 'Test test')
|
||||
assert.strictEqual(common.capitalize('FOO'), 'FOO')
|
||||
assert.strictEqual(common.capitalize('f'), 'F')
|
||||
assert.strictEqual(common.capitalize('F'), 'F')
|
||||
assert.strictEqual(common.capitalize(''), '')
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#parseValues()', function() {
|
||||
t.test('should special handle undefined', function() {
|
||||
assert.strictEqual(common.parseValues('undefined'), undefined)
|
||||
})
|
||||
|
||||
t.test('should normally json parse string', function() {
|
||||
assert.strictEqual(common.parseValues('null'), null)
|
||||
assert.deepStrictEqual(common.parseValues('{"a": 1}'), { a: 1 })
|
||||
assert.deepStrictEqual(common.parseValues('["a", 1]'), [ 'a', 1 ])
|
||||
assert.strictEqual(common.parseValues('123'), 123)
|
||||
assert.strictEqual(common.parseValues('"{\\"a\\": 1}"'), '{"a": 1}')
|
||||
})
|
||||
|
||||
t.test('should otherwise return original string if errors are found', function() {
|
||||
assert.strictEqual(common.parseValues('anull'), 'anull')
|
||||
assert.deepStrictEqual(common.parseValues('a{"a": 1}'), 'a{"a": 1}')
|
||||
assert.deepStrictEqual(common.parseValues('a["a", 1]'), 'a["a", 1]')
|
||||
assert.strictEqual(common.parseValues('a123'), 'a123')
|
||||
assert.strictEqual(common.parseValues('a"{\\"a\\": 1}"'), 'a"{\\"a\\": 1}"')
|
||||
})
|
||||
})
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* file-store-test.js: Tests for the nconf File store.
|
||||
*
|
||||
* (C) 2011, Charlie Robbins
|
||||
*
|
||||
*/
|
||||
|
||||
require.paths.unshift(require('path').join(__dirname, '..', 'lib'));
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
vows = require('vows'),
|
||||
assert = require('assert'),
|
||||
nconf = require('nconf'),
|
||||
data = require('./fixtures/data').data,
|
||||
store;
|
||||
|
||||
vows.describe('nconf/stores/file').addBatch({
|
||||
"When using the nconf file store": {
|
||||
topic: function () {
|
||||
var filePath = path.join(__dirname, 'fixtures', 'store.json');
|
||||
fs.writeFileSync(filePath, JSON.stringify(data));
|
||||
store = new nconf.stores.File({ file: filePath });
|
||||
return null;
|
||||
},
|
||||
"the load() method": {
|
||||
topic: function () {
|
||||
store.load(this.callback);
|
||||
},
|
||||
"should load the data correctly": function (err, data) {
|
||||
assert.isNull(err);
|
||||
assert.deepEqual(data, store.store);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"When using the nconf file store": {
|
||||
"the set() method": {
|
||||
"should respond with true": function () {
|
||||
assert.isTrue(store.set('foo:bar:bazz', 'buzz'));
|
||||
}
|
||||
},
|
||||
"the get() method": {
|
||||
"should respond with the correct value": function () {
|
||||
assert.equal(store.get('foo:bar:bazz'), 'buzz');
|
||||
}
|
||||
},
|
||||
"the clear() method": {
|
||||
"should respond with the true": function () {
|
||||
assert.equal(store.get('foo:bar:bazz'), 'buzz');
|
||||
assert.isTrue(store.clear('foo:bar:bazz'));
|
||||
assert.isTrue(typeof store.get('foo:bar:bazz') === 'undefined');
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"I've seen things": {
|
||||
"like": [
|
||||
"carrots",
|
||||
"handbags",
|
||||
"cheese",
|
||||
"toilets",
|
||||
"russians",
|
||||
"planets",
|
||||
"hampsters",
|
||||
"weddings",
|
||||
"poets",
|
||||
"stalin",
|
||||
"kuala lumpur"
|
||||
]
|
||||
},
|
||||
"host": "weebls-stuff.com",
|
||||
"port": 78304
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"I've seen things": {
|
||||
"like": [
|
||||
"carrots",
|
||||
"handbags",
|
||||
"cheese",
|
||||
"toilets",
|
||||
"russians",
|
||||
"planets",
|
||||
"hampsters",
|
||||
"weddings",
|
||||
"poets",
|
||||
"stalin",
|
||||
"kuala lumpur"
|
||||
]
|
||||
},
|
||||
"host": "weebls-stuff.com",
|
||||
"port": 78304
|
||||
}
|
|
@ -1,12 +1,6 @@
|
|||
/*
|
||||
* data.js: Simple data fixture for configuration test.
|
||||
*
|
||||
* (C) 2011, Charlie Robbins
|
||||
*
|
||||
*/
|
||||
|
||||
exports.data = {
|
||||
literal: 'bazz',
|
||||
export const data = {
|
||||
isNull: null,
|
||||
literal: 'bazz',
|
||||
arr: ['one', 2, true, { value: 'foo' }],
|
||||
obj: {
|
||||
host: 'localhost',
|
||||
|
@ -17,4 +11,13 @@ exports.data = {
|
|||
password: 'password'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const merge = {
|
||||
prop1: 1,
|
||||
prop2: [1, 2, 3],
|
||||
prop3: {
|
||||
foo: 'bar',
|
||||
bar: 'foo'
|
||||
}
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"title": "My generic title",
|
||||
"color": "red",
|
||||
"movie": "Kill Bill"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"title": "My specific title",
|
||||
"color": "green"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"literal": "bazz",
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"apples": true,
|
||||
"bananas": true,
|
||||
"foo": {
|
||||
"bar": "boo"
|
||||
},
|
||||
"candy": {
|
||||
"something": "file1",
|
||||
"something1": true,
|
||||
"something2": true,
|
||||
"something5": {
|
||||
"first": 1,
|
||||
"second": 2
|
||||
}
|
||||
},
|
||||
"unicorn": {
|
||||
"exists": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"candy": {
|
||||
"something": "file2",
|
||||
"something3": true,
|
||||
"something4": true
|
||||
},
|
||||
"dates": true,
|
||||
"elderberries": true,
|
||||
"unicorn": null
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"candy": {
|
||||
"something": "much better something for you",
|
||||
"something18": "completely unique",
|
||||
"something5": {
|
||||
"second": 99
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"I've seen things": {
|
||||
"like": [
|
||||
"carrots",
|
||||
"handbags",
|
||||
"cheese",
|
||||
"toilets",
|
||||
"russians",
|
||||
"planets",
|
||||
"hampsters",
|
||||
"weddings",
|
||||
"poets",
|
||||
"stalin",
|
||||
"kuala lumpur"
|
||||
]
|
||||
},
|
||||
"host": "weebls-stuff.com",
|
||||
"port": 78304
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"isNull": {
|
||||
"alg": "aes-256-ctr",
|
||||
"value": "16f39325",
|
||||
"iv": "49e7803a2a5ef98c7a51a8902b76dd10"
|
||||
},
|
||||
"literal": {
|
||||
"alg": "aes-256-ctr",
|
||||
"value": "647965c22605",
|
||||
"iv": "b654e01aed262f37d0acf200be193985"
|
||||
},
|
||||
"arr": {
|
||||
"alg": "aes-256-ctr",
|
||||
"value": "70c6d3b2ec3820e4d4fa3d7834fcf7fd51190a9e580944583ca7b30f42d230b7f271e72287f6c2ab4624685c779936aa2ed19b90",
|
||||
"iv": "b5263665331158c2165fe623a895870f"
|
||||
},
|
||||
"obj": {
|
||||
"alg": "aes-256-ctr",
|
||||
"value": "521f1995698896d2fe7d76d16bec9e86b9b5b25bcfae3a4f3c52ad6f0425c3fd059793b9dec7927c616f4c4c57f2b9ee833f8c865d9aa42bbb37203763703755a0c79afd13f8c0e96e9ac47f490a12105583e31ff628104e6b216265b849cdf6642eb8a4b5bd6f532339a5f5737bd6a7ae6e7bb22148cbcfa549802336cb1322fb701151b25b5863c5c6d5047875aed9806350ae0e292c259e82d5a561eb672402d20230a0c3107ff2b1e6259ccb1bbbe7a25ce965ce56cb32f679",
|
||||
"iv": "355f307363d69ed58345ae395744f5f0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"isNull": {
|
||||
"alg": "aes-256-ctr",
|
||||
"value": "af07fbcf"
|
||||
},
|
||||
"literal": {
|
||||
"alg": "aes-256-ctr",
|
||||
"value": "e310f6d94f13"
|
||||
},
|
||||
"arr": {
|
||||
"alg": "aes-256-ctr",
|
||||
"value": "9a78b783175e69bb8f3458042b1c098d8ed9613410fac185b3735099224f8fe4ece0f0da8decfddbbf0eab3b7c391c47772b5441"
|
||||
},
|
||||
"obj": {
|
||||
"alg": "aes-256-ctr",
|
||||
"value": "ba78b783175968add93a680429424ae4cf957d2916ebcfa399730bb17200ddb0ecacb183c1b1ebcd950ced76726964062e74643c995c47372bfb1311bee8f65bbeb5a1d9426537a6d83635220ec7934e1d7cc187f7218cd4afadfa2f107fb42c232d80d95c160ee704fa8e922998b0b3e47ec579dd0baef7cae6d7dbaa203d732adb5cff22b80d810d7191237999cd8dc528d8f2201ae128a9f9e2df96d1a816aa73e3e6b8e6246cd98b454e453b36f43f9117cb4af8fa85429a92"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"isNull": null,
|
||||
"literal": "bazz",
|
||||
"arr": [
|
||||
"one",
|
||||
2,
|
||||
true,
|
||||
{
|
||||
"value": "foo"
|
||||
}
|
||||
],
|
||||
"obj": {
|
||||
"host": "localhost",
|
||||
"port": 5984,
|
||||
"array": [
|
||||
"one",
|
||||
2,
|
||||
true,
|
||||
{
|
||||
"foo": "bar"
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"username": "admin",
|
||||
"password": "password"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
import { assert } from 'eltro'
|
||||
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { exec as ex } from 'child_process'
|
||||
import { fileURLToPath } from 'url'
|
||||
import Nconf from '../lib/nconf.mjs'
|
||||
|
||||
|
||||
let __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
export function assertMerged(err, merged) {
|
||||
merged = merged instanceof Nconf
|
||||
? merged.store.store
|
||||
: merged;
|
||||
|
||||
assert.strictEqual(err, null)
|
||||
assert.strictEqual(typeof(merged), 'object')
|
||||
assert.ok(merged.apples)
|
||||
assert.ok(merged.bananas)
|
||||
assert.strictEqual(typeof(merged.candy), 'object')
|
||||
assert.ok(merged.candy.something1)
|
||||
assert.ok(merged.candy.something2)
|
||||
assert.ok(merged.candy.something3)
|
||||
assert.ok(merged.candy.something4)
|
||||
assert.ok(merged.dates)
|
||||
assert.ok(merged.elderberries)
|
||||
};
|
||||
|
||||
// copy a file
|
||||
export function cp(from, to) {
|
||||
return new Promise(function(res, rej) {
|
||||
fs.readFile(from, function (err, data) {
|
||||
if (err) return rej(err);
|
||||
fs.writeFile(to, data, function(err, data) {
|
||||
if (err) return rej(err)
|
||||
res(data)
|
||||
});
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
/*export function exec(script, prefix = 'node') {
|
||||
let command = `${prefix} ${script}`
|
||||
return new Promise(function(res, rej) {
|
||||
ex(command,
|
||||
function (err, stdout, stderr) {
|
||||
if (err) {
|
||||
err.stdout = stdout
|
||||
err.stderr = stderr
|
||||
return rej(err)
|
||||
}
|
||||
res({
|
||||
stdout,
|
||||
stderr,
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
}*/
|
||||
|
||||
export function fixture(file) {
|
||||
return path.resolve(path.join(__dirname, 'fixtures', file));
|
||||
};
|
|
@ -0,0 +1,56 @@
|
|||
import { Eltro as t, assert} from 'eltro'
|
||||
import * as helpers from './helpers.mjs'
|
||||
import Nconf from '../lib/nconf.mjs'
|
||||
|
||||
var globalConfig = helpers.fixture('hierarchy/global.json')
|
||||
var userConfig = helpers.fixture('hierarchy/user.json')
|
||||
var file3 = helpers.fixture('merge/file3.json')
|
||||
|
||||
t.test('configured with two file stores should work', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.file('user', {type: 'file', file: userConfig})
|
||||
nconf.file('global', {type: 'file', file: globalConfig})
|
||||
nconf.load()
|
||||
|
||||
assert.strictEqual(nconf.get('title'), 'My specific title')
|
||||
assert.strictEqual(nconf.get('color'), 'green')
|
||||
assert.strictEqual(nconf.get('movie'), 'Kill Bill')
|
||||
})
|
||||
|
||||
t.test('configured with two file stores with just filenames should work', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.file('user', userConfig)
|
||||
nconf.file('global', globalConfig)
|
||||
nconf.load()
|
||||
|
||||
assert.strictEqual(nconf.get('title'), 'My specific title')
|
||||
assert.strictEqual(nconf.get('color'), 'green')
|
||||
assert.strictEqual(nconf.get('movie'), 'Kill Bill')
|
||||
})
|
||||
|
||||
t.test('configured with .file(), .defaults() should deep merge objects correctly', async function() {
|
||||
let nconf = new Nconf()
|
||||
.file('localOverrides', file3)
|
||||
.defaults({
|
||||
"candy": {
|
||||
"something": "a nice default",
|
||||
"something1": true,
|
||||
"something2": true,
|
||||
"something5": {
|
||||
"first": 1,
|
||||
"second": 2
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
assert.deepStrictEqual(nconf.get('candy'), {
|
||||
something: 'much better something for you',
|
||||
something1: true,
|
||||
something2: true,
|
||||
something18: 'completely unique',
|
||||
something5: {
|
||||
first: 1,
|
||||
second: 99
|
||||
}
|
||||
})
|
||||
})
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* memory-store-test.js: Tests for the nconf Memory store.
|
||||
*
|
||||
* (C) 2011, Charlie Robbins
|
||||
*
|
||||
*/
|
||||
|
||||
require.paths.unshift(require('path').join(__dirname, '..', 'lib'));
|
||||
|
||||
var vows = require('vows'),
|
||||
assert = require('assert'),
|
||||
nconf = require('nconf');
|
||||
|
||||
vows.describe('nconf/stores/memory').addBatch({
|
||||
"When using the nconf memory store": {
|
||||
topic: new nconf.stores.Memory(),
|
||||
"the set() method": {
|
||||
"should respond with true": function (store) {
|
||||
assert.isTrue(store.set('foo:bar:bazz', 'buzz'));
|
||||
}
|
||||
},
|
||||
"the get() method": {
|
||||
"should respond with the correct value": function (store) {
|
||||
assert.equal(store.get('foo:bar:bazz'), 'buzz');
|
||||
}
|
||||
},
|
||||
"the clear() method": {
|
||||
"should respond with the true": function (store) {
|
||||
assert.equal(store.get('foo:bar:bazz'), 'buzz');
|
||||
assert.isTrue(store.clear('foo:bar:bazz'));
|
||||
assert.isTrue(typeof store.get('foo:bar:bazz') === 'undefined');
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* file-store-test.js: Tests for the nconf File store.
|
||||
*
|
||||
* (C) 2011, Charlie Robbins
|
||||
*
|
||||
*/
|
||||
|
||||
require.paths.unshift(require('path').join(__dirname, '..', 'lib'));
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
vows = require('vows'),
|
||||
assert = require('assert'),
|
||||
nconf = require('nconf'),
|
||||
data = require('./fixtures/data').data;
|
||||
|
||||
vows.describe('nconf').addBatch({
|
||||
"When using the nconf": {
|
||||
"should have the correct methods set": function () {
|
||||
assert.isFunction(nconf.key);
|
||||
assert.isFunction(nconf.path);
|
||||
assert.isFunction(nconf.use);
|
||||
assert.isFunction(nconf.get);
|
||||
assert.isFunction(nconf.set);
|
||||
assert.isFunction(nconf.clear);
|
||||
assert.isFunction(nconf.load);
|
||||
assert.isFunction(nconf.save);
|
||||
assert.isFunction(nconf.reset);
|
||||
},
|
||||
"the use() method": {
|
||||
"should instaniate the correct store": function () {
|
||||
nconf.use('memory');
|
||||
assert.instanceOf(nconf.store, nconf.stores.Memory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"When using the nconf": {
|
||||
"with the memory store": {
|
||||
"the set() method": {
|
||||
"should respond with true": function () {
|
||||
assert.isTrue(nconf.set('foo:bar:bazz', 'buzz'));
|
||||
}
|
||||
},
|
||||
"the get() method": {
|
||||
"should respond with the correct value": function () {
|
||||
assert.equal(nconf.get('foo:bar:bazz'), 'buzz');
|
||||
}
|
||||
},
|
||||
"the clear() method": {
|
||||
"should respond with the true": function () {
|
||||
assert.equal(nconf.get('foo:bar:bazz'), 'buzz');
|
||||
assert.isTrue(nconf.clear('foo:bar:bazz'));
|
||||
assert.isTrue(typeof nconf.get('foo:bar:bazz') === 'undefined');
|
||||
}
|
||||
},
|
||||
"the load() method": {
|
||||
"without a callback": {
|
||||
"should throw an exception": function () {
|
||||
assert.throws(function () {
|
||||
nconf.load();
|
||||
})
|
||||
}
|
||||
},
|
||||
"with a callback": {
|
||||
topic: function () {
|
||||
nconf.load(this.callback.bind(null, null));
|
||||
},
|
||||
"should respond with an error": function (ign, err) {
|
||||
assert.isNotNull(err);
|
||||
}
|
||||
}
|
||||
},
|
||||
"the save() method": {
|
||||
"without a callback": {
|
||||
"should throw an exception": function () {
|
||||
assert.throws(function () {
|
||||
nconf.save();
|
||||
})
|
||||
}
|
||||
},
|
||||
"with a callback": {
|
||||
topic: function () {
|
||||
nconf.save(this.callback.bind(null, null));
|
||||
},
|
||||
"should respond with an error": function (ign, err) {
|
||||
assert.isNotNull(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
|
@ -0,0 +1,194 @@
|
|||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { Eltro as t, assert} from 'eltro'
|
||||
import Nconf from '../lib/nconf.mjs'
|
||||
import * as helpers from './helpers.mjs'
|
||||
|
||||
t.describe('nconf', function() {
|
||||
t.test('should have the correct methods set', function() {
|
||||
let nconf = new Nconf()
|
||||
assert.strictEqual(typeof(nconf.key), 'function')
|
||||
assert.strictEqual(typeof(nconf.path), 'function')
|
||||
assert.strictEqual(typeof(nconf.use), 'function')
|
||||
assert.strictEqual(typeof(nconf.any), 'function')
|
||||
assert.strictEqual(typeof(nconf.get), 'function')
|
||||
assert.strictEqual(typeof(nconf.set), 'function')
|
||||
assert.strictEqual(typeof(nconf.clear), 'function')
|
||||
assert.strictEqual(typeof(nconf.load), 'function')
|
||||
assert.strictEqual(typeof(nconf.save), 'function')
|
||||
assert.strictEqual(typeof(nconf.reset), 'function')
|
||||
assert.strictEqual(typeof(nconf.required), 'function')
|
||||
})
|
||||
|
||||
t.test('memory() should instaniate the correct store', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.memory()
|
||||
assert.ok(nconf.use('memory') instanceof Nconf.Memory)
|
||||
})
|
||||
|
||||
t.test('should have the correct version set', function () {
|
||||
let nconf = new Nconf()
|
||||
let pckg = JSON.parse(fs.readFileSync(helpers.fixture('../../package.json')))
|
||||
assert.ok(pckg.version)
|
||||
assert.strictEqual(nconf.version, pckg.version)
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#required()', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.memory()
|
||||
nconf.set('foo:bar:bazz', 'buzz')
|
||||
|
||||
t.test('should throw error with missing keys', function() {
|
||||
assert.throws(function() {
|
||||
nconf.required(['missingtest', 'foo:bar:bazz'])
|
||||
}, /missingtest/)
|
||||
})
|
||||
|
||||
t.test('should throw error with missing keys with non-array parameter', function() {
|
||||
assert.throws(function() {
|
||||
nconf.required(['missingtest', 'foo:bar:bazz'])
|
||||
}, /missingtest/)
|
||||
})
|
||||
|
||||
t.test('should return the provider if all keys exist', function() {
|
||||
assert.strictEqual(nconf.required(['foo:bar:bazz']), nconf)
|
||||
})
|
||||
})
|
||||
t.describe('#any()', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.memory()
|
||||
nconf.set('foo:bar:bazz', 'buzz')
|
||||
|
||||
t.test('should return if found', function() {
|
||||
assert.strictEqual(nconf.any(['missingtest', 'nope', 'foo:bar:bazz']), 'buzz')
|
||||
})
|
||||
t.test('should return first item found', function() {
|
||||
assert.deepStrictEqual(nconf.any(['missingtest', 'foo', 'nope', 'foo:bar:bazz']), {
|
||||
bar: {
|
||||
bazz: 'buzz',
|
||||
},
|
||||
})
|
||||
})
|
||||
t.test('should return if found as paramaters', function() {
|
||||
assert.strictEqual(nconf.any('missingtest', 'nope', 'foo:bar:bazz'), 'buzz')
|
||||
})
|
||||
t.test('should return undefined otherwise', function() {
|
||||
assert.strictEqual(nconf.any(['missingtest', 'nope']), undefined)
|
||||
})
|
||||
})
|
||||
t.describe('#set()', function() {
|
||||
t.test('should respond with self if success', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.memory()
|
||||
assert.strictEqual(nconf.set('foo:bar:bazz', 'buzz'), nconf)
|
||||
})
|
||||
|
||||
t.test('should respond with false if not successful', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.memory({ readOnly: true })
|
||||
assert.strictEqual(nconf.set('foo:bar:bazz', 'buzz'), false)
|
||||
})
|
||||
|
||||
t.test('should always set the first writeable store', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.memory('first')
|
||||
nconf.memory('second')
|
||||
nconf.use('second').set('foo:bar:bazz', 'buzz')
|
||||
assert.strictEqual(nconf.get('foo:bar:bazz'), 'buzz')
|
||||
nconf.set('foo:bar:bazz', 'overwritten')
|
||||
assert.strictEqual(nconf.get('foo:bar:bazz'), 'overwritten')
|
||||
assert.strictEqual(nconf.use('second').get('foo:bar:bazz'), 'buzz')
|
||||
})
|
||||
|
||||
t.test('should respond allow access to the root and complain about non-objects', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.memory()
|
||||
assert.notOk(nconf.set(null, null))
|
||||
assert.notOk(nconf.set(null, undefined))
|
||||
assert.notOk(nconf.set(null))
|
||||
assert.notOk(nconf.set(null, ''))
|
||||
assert.notOk(nconf.set(null, 1))
|
||||
var original = nconf.get()
|
||||
assert.ok(nconf.set(null, nconf.get()))
|
||||
assert.notStrictEqual(nconf.get(), original)
|
||||
assert.deepStrictEqual(nconf.get(), original)
|
||||
})
|
||||
})
|
||||
t.describe('#get()', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.memory()
|
||||
nconf.set('foo:bar:bazz', 'buzz')
|
||||
|
||||
t.test('should respond with the correct value', function() {
|
||||
assert.strictEqual(nconf.get('foo:bar:bazz'), 'buzz')
|
||||
})
|
||||
|
||||
t.test('unknown keys should return undefined', function() {
|
||||
assert.strictEqual(nconf.get('foo:bar:bazz:toString'), undefined)
|
||||
})
|
||||
|
||||
t.test('should not step inside strings', function() {
|
||||
assert.strictEqual(nconf.get('foo:bar:bazz:0'), undefined)
|
||||
})
|
||||
|
||||
t.test('should respond allow access to the root', function() {
|
||||
assert.ok(nconf.get(null))
|
||||
assert.ok(nconf.get(undefined))
|
||||
assert.ok(nconf.get())
|
||||
assert.deepStrictEqual(nconf.get(), { foo: { bar: { bazz: 'buzz' } } })
|
||||
})
|
||||
|
||||
t.test('should merge stores correctly', function() {
|
||||
let testMerge = new Nconf()
|
||||
testMerge.memory('higherpriority')
|
||||
testMerge.set('foo:bar', {
|
||||
bazz: 'overwritten',
|
||||
test: 1
|
||||
})
|
||||
testMerge.memory('lowerdefaults')
|
||||
testMerge.use('lowerdefaults').set('foo:bar:bazz', 'buzz')
|
||||
testMerge.use('lowerdefaults').set('foo:bar:buzz', 'buzz')
|
||||
|
||||
assert.strictEqual(testMerge.get('foo:bar:bazz'), 'overwritten')
|
||||
assert.strictEqual(testMerge.get('foo:bar:buzz'), 'buzz')
|
||||
|
||||
assert.deepStrictEqual(testMerge.get('foo:bar'), {
|
||||
bazz: 'overwritten',
|
||||
buzz: 'buzz',
|
||||
test: 1,
|
||||
})
|
||||
})
|
||||
})
|
||||
t.describe('#clear()', function() {
|
||||
t.test('should respond with self if success', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.memory().set('foo:bar:bazz', 'buzz')
|
||||
assert.strictEqual(nconf.get('foo:bar:bazz'), 'buzz')
|
||||
assert.strictEqual(nconf.clear('foo:bar:bazz'), nconf)
|
||||
assert.strictEqual(nconf.get('foo:bar:bazz'), undefined)
|
||||
})
|
||||
|
||||
t.test('should respond with self if success even with readOnly store', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf
|
||||
.literal({ testetytest: 'buzz' })
|
||||
.memory()
|
||||
.set('foo:bar:bazz', 'buzz')
|
||||
|
||||
assert.strictEqual(nconf.get('foo:bar:bazz'), 'buzz')
|
||||
assert.strictEqual(nconf.get('testetytest'), 'buzz')
|
||||
assert.strictEqual(nconf.clear('foo:bar:bazz'), nconf)
|
||||
assert.strictEqual(nconf.get('foo:bar:bazz'), undefined)
|
||||
assert.strictEqual(nconf.use('literal').get('foo:bar:bazz'), undefined)
|
||||
})
|
||||
|
||||
t.test('should respond with false if clearing readonly value', function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.literal({ testetytest: 'buzz' })
|
||||
|
||||
assert.strictEqual(nconf.get('testetytest'), 'buzz')
|
||||
assert.notOk(nconf.clear('testetytest'))
|
||||
assert.strictEqual(nconf.get('testetytest'), 'buzz')
|
||||
})
|
||||
})
|
|
@ -0,0 +1,225 @@
|
|||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { spawn } from 'child_process'
|
||||
import { Eltro as t, assert} from 'eltro'
|
||||
import * as helpers from './helpers.mjs'
|
||||
// import nconf from '../lib/nconf-o.mjs'
|
||||
import Nconf from '../lib/nconf.mjs'
|
||||
|
||||
let files = [
|
||||
helpers.fixture('merge/file1.json'),
|
||||
helpers.fixture('merge/file2.json'),
|
||||
];
|
||||
let override = JSON.parse(fs.readFileSync(files[0]), 'utf8');
|
||||
|
||||
function assertSystemConf(options) {
|
||||
return new Promise(function(res, rej) {
|
||||
let env = null;
|
||||
|
||||
if (options.env) {
|
||||
env = {}
|
||||
Object.keys(process.env).forEach(function (key) {
|
||||
env[key] = process.env[key];
|
||||
});
|
||||
|
||||
Object.keys(options.env).forEach(function (key) {
|
||||
env[key] = options.env[key];
|
||||
});
|
||||
}
|
||||
|
||||
let child = spawn('node', [options.script].concat(options.argv), {env: env});
|
||||
child.stdout.once('data', data => {
|
||||
res(data.toString())
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
t.describe('When using nconf', function() {
|
||||
t.test("calling add with the same store type and different options should use the new instance", function() {
|
||||
let nconf = new Nconf()
|
||||
nconf.file({ file: files[0] })
|
||||
let old = nconf.using.get('file');
|
||||
|
||||
assert.ok(old)
|
||||
assert.strictEqual(old.file, files[0]);
|
||||
nconf.file({ file: files[1] });
|
||||
|
||||
let newOne = nconf.using.get('file');
|
||||
assert.notStrictEqual(old, newOne);
|
||||
assert.strictEqual(newOne.file, files[1]);
|
||||
})
|
||||
|
||||
/*
|
||||
t.test("respond with correct arg when 'env' is true", async function() {
|
||||
let result = await assertSystemConf({
|
||||
script: helpers.fixture('scripts/provider-env.mjs'),
|
||||
env: {SOMETHING: 'foobar'}
|
||||
})
|
||||
|
||||
assert.strictEqual(result.toString(), 'foobar')
|
||||
});
|
||||
|
||||
t.test("respond with correct arg when 'env' is true and 'parseValues' option is true", function() {
|
||||
let env = {
|
||||
SOMETHING: 'foobar',
|
||||
SOMEBOOL: 'true',
|
||||
SOMENULL: 'null',
|
||||
SOMEUNDEF: 'undefined',
|
||||
SOMEINT: '3600',
|
||||
SOMEFLOAT: '0.5',
|
||||
SOMEBAD: '5.1a'
|
||||
};
|
||||
let oenv = {};
|
||||
Object.keys(env).forEach(function (key) {
|
||||
if (process.env[key]) oenv[key] = process.env[key];
|
||||
process.env[key] = env[key];
|
||||
});
|
||||
let provider = new nconf.Provider().use('env', {parseValues: true});
|
||||
Object.keys(env).forEach(function (key) {
|
||||
delete process.env[key];
|
||||
if (oenv[key]) process.env[key] = oenv[key];
|
||||
});
|
||||
|
||||
assert.strictEqual(provider.get('SOMETHING'), 'foobar');
|
||||
assert.strictEqual(provider.get('SOMEBOOL'), true);
|
||||
assert.notStrictEqual(provider.get('SOMEBOOL'), 'true');
|
||||
assert.strictEqual(provider.get('SOMENULL'), null);
|
||||
assert.strictEqual(provider.get('SOMEUNDEF'), undefined);
|
||||
assert.strictEqual(provider.get('SOMEINT'), 3600);
|
||||
assert.strictEqual(provider.get('SOMEFLOAT'), .5);
|
||||
assert.strictEqual(provider.get('SOMEBAD'), '5.1a');
|
||||
});
|
||||
|
||||
t.describe("an instance of 'nconf.Provider'", function() {
|
||||
t.describe("the merge() method", function() {
|
||||
t.test("should have the result merged in", function() {
|
||||
let provider = new nconf.Provider().use('file', {file: files[1]});
|
||||
provider.load();
|
||||
provider.merge(override);
|
||||
helpers.assertMerged(null, provider.stores.file.store);
|
||||
assert.strictEqual(provider.stores.file.store.candy.something, 'file1');
|
||||
});
|
||||
|
||||
t.test("should merge Objects over null", function() {
|
||||
let provider = new nconf.Provider().use('file', {file: files[1]});
|
||||
provider.load();
|
||||
provider.merge(override);
|
||||
assert.strictEqual(provider.stores.file.store.unicorn.exists, true);
|
||||
});
|
||||
|
||||
})
|
||||
t.describe("the load() method", function() {
|
||||
t.test("should respect the hierarchy when sources are passed in", function() {
|
||||
let provider = new nconf.Provider({
|
||||
sources: {
|
||||
user: {
|
||||
type: 'file',
|
||||
file: files[0]
|
||||
},
|
||||
global: {
|
||||
type: 'file',
|
||||
file: files[1]
|
||||
}
|
||||
}
|
||||
});
|
||||
let merged = provider.load();
|
||||
helpers.assertMerged(null, merged);
|
||||
assert.strictEqual(merged.candy.something, 'file1');
|
||||
})
|
||||
t.test("should respect the hierarchy when multiple stores are used", function() {
|
||||
let provider = new nconf.Provider().overrides({foo: {bar: 'baz'}})
|
||||
.add('file1', {type: 'file', file: files[0]})
|
||||
.add('file2', {type: 'file', file: files[1]});
|
||||
|
||||
let merged = provider.load();
|
||||
|
||||
helpers.assertMerged(null, merged);
|
||||
assert.strictEqual(merged.foo.bar, 'baz');
|
||||
assert.strictEqual(merged.candy.something, 'file1');
|
||||
})
|
||||
})
|
||||
})
|
||||
t.describe("the .file() method", function() {
|
||||
t.test("should use the correct File store with a single filepath", function() {
|
||||
let provider = new nconf.Provider();
|
||||
provider.file(helpers.fixture('store.json'));
|
||||
assert.strictEqual(typeof(provider.stores.file), 'object');
|
||||
});
|
||||
t.test("should use the correct File store with a name and a filepath", function() {
|
||||
let provider = new nconf.Provider();
|
||||
provider.file('custom', helpers.fixture('store.json'));
|
||||
assert.strictEqual(typeof(provider.stores.custom), 'object');
|
||||
});
|
||||
t.test("should use the correct File store with a single object", function() {
|
||||
let provider = new nconf.Provider();
|
||||
provider.file({
|
||||
dir: helpers.fixture(''),
|
||||
file: 'store.json',
|
||||
search: true
|
||||
});
|
||||
|
||||
assert.strictEqual(typeof(provider.stores.file), 'object');
|
||||
assert.strictEqual(provider.stores.file.file, helpers.fixture('store.json'));
|
||||
});
|
||||
t.test("should use the correct File store with a name and an object", function() {
|
||||
let provider = new nconf.Provider();
|
||||
provider.file('custom', {
|
||||
dir: helpers.fixture(''),
|
||||
file: 'store.json',
|
||||
search: true
|
||||
});
|
||||
|
||||
assert.strictEqual(typeof(provider.stores.custom), 'object');
|
||||
assert.strictEqual(provider.stores.custom.file, helpers.fixture('store.json'));
|
||||
})*/
|
||||
/*t.describe("the any() method", function() {
|
||||
let provider = new nconf.Provider({
|
||||
type: 'literal',
|
||||
store: {
|
||||
key: "getThisValue"
|
||||
}
|
||||
})
|
||||
t.describe("without a callback", function() {
|
||||
t.test("should respond with the correct value given an array of keys with one matching", function() {
|
||||
assert.strictEqual(provider.any(["notthis", "orthis", "key"]), 'getThisValue');
|
||||
})
|
||||
t.test("should respond with null given an array of keys with no match", function() {
|
||||
assert.strictEqual(provider.any(["notthis", "orthis"]), null);
|
||||
});
|
||||
t.test("should respond with the correct value given a variable argument list of keys with one matching", function() {
|
||||
assert.strictEqual(provider.any("notthis", "orthis", "key"), 'getThisValue');
|
||||
});
|
||||
t.test("should respond with null given no arguments", function() {
|
||||
assert.strictEqual(provider.any(), null);
|
||||
});
|
||||
})
|
||||
t.describe("with a callback", function() {
|
||||
t.test("should respond with the correct value given an array of keys with one matching", function(done) {
|
||||
provider.any(["notthis", "orthis", "key"], (err, value) => {
|
||||
assert.strictEqual(value, 'getThisValue');
|
||||
done();
|
||||
});
|
||||
});
|
||||
t.test("should respond with an undefined value given an array of keys with no match", function(done) {
|
||||
provider.any(["notthis", "orthis"], (err, value) => {
|
||||
assert.strictEqual(value, undefined)
|
||||
done();
|
||||
});
|
||||
});
|
||||
t.test("should respond with the correct value given a variable argument list of keys with one matching", function(done) {
|
||||
provider.any("notthis", "orthis", "key", (err, value) => {
|
||||
assert.strictEqual(value, 'getThisValue');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
t.test("should respond with an undefined value given no keys", function(done) {
|
||||
provider.any((err, value) => {
|
||||
assert.strictEqual(value, undefined)
|
||||
done();
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
})*/
|
||||
});
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
* redis-store-test.js: Tests for the redis nconf storage engine.
|
||||
*
|
||||
* (C) 2011, Charlie Robbins
|
||||
*
|
||||
*/
|
||||
|
||||
require.paths.unshift(require('path').join(__dirname, '..', 'lib'));
|
||||
|
||||
var vows = require('vows'),
|
||||
assert = require('assert'),
|
||||
nconf = require('nconf'),
|
||||
data = require('./fixtures/data').data;
|
||||
|
||||
vows.describe('nconf/stores/redis').addBatch({
|
||||
"When using the nconf redis store": {
|
||||
topic: new nconf.stores.Redis(),
|
||||
"the set() method": {
|
||||
"with a literal": {
|
||||
topic: function (store) {
|
||||
store.set('foo:literal', 'bazz', this.callback)
|
||||
},
|
||||
"should respond without an error": function (err, ok) {
|
||||
assert.isNull(err);
|
||||
}
|
||||
},
|
||||
"with an Array": {
|
||||
topic: function (store) {
|
||||
store.set('foo:array', data.arr, this.callback)
|
||||
},
|
||||
"should respond without an": function (err, ok) {
|
||||
assert.isNull(err);
|
||||
}
|
||||
},
|
||||
"with an Object": {
|
||||
topic: function (store) {
|
||||
store.set('foo:object', data.obj, this.callback)
|
||||
},
|
||||
"should respond without an error": function (err, ok) {
|
||||
assert.isNull(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"When using the nconf redis store": {
|
||||
topic: new nconf.stores.Redis(),
|
||||
"the get() method": {
|
||||
"with a literal value": {
|
||||
topic: function (store) {
|
||||
store.get('foo:literal', this.callback);
|
||||
},
|
||||
"should respond with the correct value": function (err, value) {
|
||||
assert.equal(value, data.literal);
|
||||
}
|
||||
},
|
||||
"with an Array value": {
|
||||
topic: function (store) {
|
||||
store.get('foo:array', this.callback);
|
||||
},
|
||||
"should respond with the correct value": function (err, value) {
|
||||
assert.deepEqual(value, data.arr);
|
||||
}
|
||||
},
|
||||
"with an Object value": {
|
||||
topic: function (store) {
|
||||
store.get('foo:object', this.callback);
|
||||
},
|
||||
"should respond with the correct value": function (err, value) {
|
||||
assert.deepEqual(value, data.obj);
|
||||
}
|
||||
},
|
||||
"with a nested Object value": {
|
||||
topic: function (store) {
|
||||
store.get('foo:object:auth', this.callback);
|
||||
},
|
||||
"should respond with the correct value": function (err, value) {
|
||||
assert.deepEqual(value, data.obj.auth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"When using the nconf redis store": {
|
||||
topic: new nconf.stores.Redis(),
|
||||
"the clear() method": {
|
||||
topic: function (store) {
|
||||
var that = this;
|
||||
store.clear('foo', function (err) {
|
||||
if (err) {
|
||||
return that.callback(err);
|
||||
}
|
||||
|
||||
store.get('foo', that.callback);
|
||||
});
|
||||
},
|
||||
"should actually remove the value from Redis": function (err, value) {
|
||||
assert.isNull(err);
|
||||
assert.isNull(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"When using the nconf redis store": {
|
||||
topic: new nconf.stores.Redis(),
|
||||
"the save() method": {
|
||||
topic: function (store) {
|
||||
var that = this;
|
||||
store.save(data, function (err) {
|
||||
if (err) {
|
||||
return that.callback(err);
|
||||
}
|
||||
|
||||
store.get('obj', that.callback);
|
||||
});
|
||||
},
|
||||
"should set all values correctly": function (err, value) {
|
||||
assert.isNull(err);
|
||||
assert.deepEqual(value, data.obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"When using the nconf redis store": {
|
||||
topic: new nconf.stores.Redis(),
|
||||
"the load() method": {
|
||||
topic: function (store) {
|
||||
store.load(this.callback);
|
||||
},
|
||||
"should respond with the correct object": function (err, value) {
|
||||
assert.isNull(err);
|
||||
assert.deepEqual(value, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"When using the nconf redis store": {
|
||||
topic: new nconf.stores.Redis(),
|
||||
"the reset() method": {
|
||||
topic: function (store) {
|
||||
var that = this;
|
||||
this.store = store;
|
||||
|
||||
store.reset(function (err) {
|
||||
if (err) {
|
||||
return that.callback(err);
|
||||
}
|
||||
|
||||
store.get('obj', that.callback);
|
||||
});
|
||||
},
|
||||
"should remove all keys from redis": function (err, value) {
|
||||
assert.isNull(err);
|
||||
assert.isNull(value);
|
||||
assert.length(Object.keys(this.store.cache.store), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
|
@ -0,0 +1,171 @@
|
|||
import { Eltro as t, assert} from 'eltro'
|
||||
import Nconf from '../../lib/nconf.mjs'
|
||||
|
||||
t.describe('#load()', () => {
|
||||
t.test('should support pairs of arguments together as strings', function() {
|
||||
process.argv = ['bla', 'bla',
|
||||
'--foobar', '123',
|
||||
'--testety', 'hello',
|
||||
]
|
||||
let store = new Nconf.Argv()
|
||||
store.load()
|
||||
assert.strictEqual(store.get('foobar'), '123')
|
||||
assert.strictEqual(store.get('testety'), 'hello')
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
foobar: '123',
|
||||
testety: 'hello',
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should support custom prefix argument', function() {
|
||||
process.argv = ['bla', 'bla',
|
||||
'-foobar', '123',
|
||||
'-testety', 'hello',
|
||||
]
|
||||
let store = new Nconf.Argv({ prefix: '-' })
|
||||
store.load()
|
||||
|
||||
assert.strictEqual(store.get('foobar'), '123')
|
||||
assert.strictEqual(store.get('testety'), 'hello')
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
foobar: '123',
|
||||
testety: 'hello',
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should support individual options as boolean', function() {
|
||||
process.argv = ['bla', 'bla',
|
||||
'--booleanone',
|
||||
'--foobar', '123',
|
||||
'--testety', 'hello',
|
||||
'--booleantwo',
|
||||
]
|
||||
let store = new Nconf.Argv()
|
||||
store.load()
|
||||
|
||||
assert.strictEqual(store.get('foobar'), '123')
|
||||
assert.strictEqual(store.get('testety'), 'hello')
|
||||
assert.strictEqual(store.get('booleanone'), true)
|
||||
assert.strictEqual(store.get('booleantwo'), true)
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
foobar: '123',
|
||||
testety: 'hello',
|
||||
booleanone: true,
|
||||
booleantwo: true,
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should support forcing everything as lowercase', function() {
|
||||
process.argv = ['bla', 'bla',
|
||||
'--FOOBAR', '123',
|
||||
'--TESTETY', 'hello',
|
||||
]
|
||||
let store = new Nconf.Argv({ lowerCase: true })
|
||||
store.load()
|
||||
|
||||
assert.strictEqual(store.get('foobar'), '123')
|
||||
assert.strictEqual(store.get('testety'), 'hello')
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
foobar: '123',
|
||||
testety: 'hello',
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should support making objects', function() {
|
||||
process.argv = ['bla', 'bla',
|
||||
'--foo:bar:baz', '123',
|
||||
'--foo:bar:testety', 'hello',
|
||||
]
|
||||
let store = new Nconf.Argv()
|
||||
store.load()
|
||||
assert.strictEqual(store.get('foo:bar:baz'), '123')
|
||||
assert.strictEqual(store.get('foo:bar:testety'), 'hello')
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
foo: {
|
||||
bar: {
|
||||
baz: '123',
|
||||
testety: 'hello',
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should support custom seperator', function() {
|
||||
process.argv = ['bla', 'bla',
|
||||
'--foo__bar__baz', '123',
|
||||
'--foo__bar__testety', 'hello',
|
||||
]
|
||||
let store = new Nconf.Argv({ separator: '__' })
|
||||
store.load()
|
||||
assert.strictEqual(store.get('foo:bar:baz'), '123')
|
||||
assert.strictEqual(store.get('foo:bar:testety'), 'hello')
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
foo: {
|
||||
bar: {
|
||||
baz: '123',
|
||||
testety: 'hello',
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should support parse values', function() {
|
||||
process.argv = ['bla', 'bla',
|
||||
'--foo', '123',
|
||||
'--bar', '0.123',
|
||||
'--asdf', '{"hello":"world"}',
|
||||
'--testety', 'hello',
|
||||
]
|
||||
let store = new Nconf.Argv({ parseValues: true })
|
||||
store.load()
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
foo: 123,
|
||||
bar: 0.123,
|
||||
asdf: {
|
||||
hello: 'world',
|
||||
},
|
||||
testety: 'hello',
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should support usage of equal sign instead', function() {
|
||||
process.argv = ['bla', 'bla',
|
||||
'--foo=123',
|
||||
'--testety=hello',
|
||||
]
|
||||
let store = new Nconf.Argv({ useEqualsign: true })
|
||||
store.load()
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
foo: '123',
|
||||
testety: 'hello',
|
||||
})
|
||||
})
|
||||
|
||||
t.test('equal sign should support boolean values', function() {
|
||||
process.argv = ['bla', 'bla',
|
||||
'--booleanone',
|
||||
'--foobar=123',
|
||||
'--testety=hello',
|
||||
'--booleantwo',
|
||||
]
|
||||
let store = new Nconf.Argv({ useEqualsign: true })
|
||||
store.load()
|
||||
assert.strictEqual(store.get('booleanone'), true)
|
||||
assert.strictEqual(store.get('booleantwo'), true)
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
foobar: '123',
|
||||
testety: 'hello',
|
||||
booleanone: true,
|
||||
booleantwo: true,
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should be smart with the usage of equal sign', function() {
|
||||
process.argv = ['bla', 'bla',
|
||||
'--foo=hello=world',
|
||||
]
|
||||
let store = new Nconf.Argv({ useEqualsign: true })
|
||||
store.load()
|
||||
assert.strictEqual(store.get('foo'), 'hello=world')
|
||||
})
|
||||
})
|
|
@ -0,0 +1,245 @@
|
|||
import { Eltro as t, assert} from 'eltro'
|
||||
import Nconf from '../../lib/nconf.mjs'
|
||||
|
||||
t.describe('#load()', () => {
|
||||
let backupEnv = {}
|
||||
let testEnv = {
|
||||
SOMETHING: 'foobar',
|
||||
SOMEBOOL: 'true',
|
||||
SOMENULL: 'null',
|
||||
SOMEUNDEF: 'undefined',
|
||||
SOMEINT: '3600',
|
||||
SOMEFLOAT: '0.5',
|
||||
SOMEBAD: '5.1a',
|
||||
ANOTHER__TEST__THIS: 'foobar',
|
||||
}
|
||||
|
||||
t.before(function() {
|
||||
Object.keys(testEnv).forEach(function (key) {
|
||||
if (process.env[key]) backupEnv[key] = process.env[key]
|
||||
process.env[key] = testEnv[key]
|
||||
})
|
||||
})
|
||||
|
||||
t.test("should default read everything as string", function() {
|
||||
let store = new Nconf.Env()
|
||||
store.load()
|
||||
|
||||
assert.strictEqual(store.get('SOMETHING'), 'foobar')
|
||||
assert.strictEqual(store.get('SOMEBOOL'), 'true')
|
||||
assert.strictEqual(store.get('SOMENULL'), 'null')
|
||||
assert.strictEqual(store.get('SOMEUNDEF'), 'undefined')
|
||||
assert.strictEqual(store.get('SOMEINT'), '3600')
|
||||
assert.strictEqual(store.get('SOMEFLOAT'), '0.5')
|
||||
assert.strictEqual(store.get('SOMEBAD'), '5.1a')
|
||||
assert.strictEqual(store.get('ANOTHER__TEST__THIS'), 'foobar')
|
||||
})
|
||||
|
||||
t.test("should support parseValues correctly", function() {
|
||||
let store = new Nconf.Env({parseValues: true})
|
||||
store.load()
|
||||
|
||||
assert.strictEqual(store.get('SOMETHING'), 'foobar')
|
||||
assert.strictEqual(store.get('SOMEBOOL'), true)
|
||||
assert.notStrictEqual(store.get('SOMEBOOL'), 'true')
|
||||
assert.strictEqual(store.get('SOMENULL'), null)
|
||||
assert.strictEqual(store.get('SOMEUNDEF'), undefined)
|
||||
assert.strictEqual(store.get('SOMEINT'), 3600)
|
||||
assert.strictEqual(store.get('SOMEFLOAT'), .5)
|
||||
assert.strictEqual(store.get('SOMEBAD'), '5.1a')
|
||||
assert.strictEqual(store.get('ANOTHER__TEST__THIS'), 'foobar')
|
||||
})
|
||||
|
||||
t.test("should support lowercase", function() {
|
||||
let store = new Nconf.Env({lowerCase: true})
|
||||
store.load()
|
||||
|
||||
assert.notOk(store.get('SOMETHING'))
|
||||
assert.notOk(store.get('SOMEBOOL'))
|
||||
assert.notOk(store.get('SOMENULL'))
|
||||
assert.notOk(store.get('SOMEUNDEF'))
|
||||
assert.notOk(store.get('SOMEINT'))
|
||||
assert.notOk(store.get('SOMEFLOAT'))
|
||||
assert.notOk(store.get('SOMEBAD'))
|
||||
assert.notOk(store.get('ANOTHER__TEST__THIS'))
|
||||
assert.strictEqual(store.get('something'), 'foobar')
|
||||
assert.strictEqual(store.get('somebool'), 'true')
|
||||
assert.strictEqual(store.get('somenull'), 'null')
|
||||
assert.strictEqual(store.get('someundef'), 'undefined')
|
||||
assert.strictEqual(store.get('someint'), '3600')
|
||||
assert.strictEqual(store.get('somefloat'), '0.5')
|
||||
assert.strictEqual(store.get('somebad'), '5.1a')
|
||||
assert.strictEqual(store.get('another__test__this'), 'foobar')
|
||||
})
|
||||
|
||||
t.test("should support transform", function() {
|
||||
let store = new Nconf.Env({transform: function(key, value) {
|
||||
if (!testEnv[key]) return null
|
||||
return {
|
||||
key: key[0].toUpperCase() + key.slice(1).toLowerCase(),
|
||||
value: 1,
|
||||
}
|
||||
}})
|
||||
store.load()
|
||||
|
||||
assert.strictEqual(store.get('Something'), 1)
|
||||
assert.strictEqual(store.get('Somebool'), 1)
|
||||
assert.strictEqual(store.get('Somenull'), 1)
|
||||
assert.strictEqual(store.get('Someundef'), 1)
|
||||
assert.strictEqual(store.get('Someint'), 1)
|
||||
assert.strictEqual(store.get('Somefloat'), 1)
|
||||
assert.strictEqual(store.get('Somebad'), 1)
|
||||
assert.strictEqual(store.get('Another__test__this'), 1)
|
||||
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
Something: 1,
|
||||
Somebool: 1,
|
||||
Somenull: 1,
|
||||
Someundef: 1,
|
||||
Someint: 1,
|
||||
Somefloat: 1,
|
||||
Somebad: 1,
|
||||
Another__test__this: 1,
|
||||
})
|
||||
})
|
||||
|
||||
t.test("should support matches", function() {
|
||||
let store = new Nconf.Env({match: /^SOME/})
|
||||
store.load()
|
||||
|
||||
assert.strictEqual(store.get('SOMETHING'), 'foobar')
|
||||
assert.strictEqual(store.get('SOMEBOOL'), 'true')
|
||||
assert.strictEqual(store.get('SOMENULL'), 'null')
|
||||
assert.strictEqual(store.get('SOMEUNDEF'), 'undefined')
|
||||
assert.strictEqual(store.get('SOMEINT'), '3600')
|
||||
assert.strictEqual(store.get('SOMEFLOAT'), '0.5')
|
||||
assert.strictEqual(store.get('SOMEBAD'), '5.1a')
|
||||
assert.notOk(store.get('Another__test__this'))
|
||||
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
SOMETHING: 'foobar',
|
||||
SOMEBOOL: 'true',
|
||||
SOMENULL: 'null',
|
||||
SOMEUNDEF: 'undefined',
|
||||
SOMEINT: '3600',
|
||||
SOMEFLOAT: '0.5',
|
||||
SOMEBAD: '5.1a',
|
||||
})
|
||||
})
|
||||
|
||||
t.test("should support whitelist", function() {
|
||||
let store = new Nconf.Env({whitelist: ['ANOTHER__TEST__THIS']})
|
||||
store.load()
|
||||
|
||||
assert.notOk(store.get('SOMETHING'), 'foobar')
|
||||
assert.notOk(store.get('SOMEBOOL'), 'true')
|
||||
assert.notOk(store.get('SOMENULL'), 'null')
|
||||
assert.notOk(store.get('SOMEUNDEF'), 'undefined')
|
||||
assert.notOk(store.get('SOMEINT'), '3600')
|
||||
assert.notOk(store.get('SOMEFLOAT'), '0.5')
|
||||
assert.notOk(store.get('SOMEBAD'), '5.1a')
|
||||
assert.strictEqual(store.get('ANOTHER__TEST__THIS'), 'foobar')
|
||||
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
ANOTHER__TEST__THIS: 'foobar',
|
||||
})
|
||||
})
|
||||
|
||||
t.test("whitelist should be case insensitive", function() {
|
||||
let store = new Nconf.Env({whitelist: ['another__test__this']})
|
||||
store.load()
|
||||
|
||||
assert.strictEqual(store.get('ANOTHER__TEST__THIS'), 'foobar')
|
||||
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
ANOTHER__TEST__THIS: 'foobar',
|
||||
})
|
||||
})
|
||||
|
||||
t.test("should support whitelist with match", function() {
|
||||
let store = new Nconf.Env({
|
||||
whitelist: ['another__test__this'],
|
||||
match: /^SOMEBOOL/,
|
||||
})
|
||||
store.load()
|
||||
|
||||
assert.strictEqual(store.get('ANOTHER__TEST__THIS'), 'foobar')
|
||||
assert.strictEqual(store.get('SOMEBOOL'), 'true')
|
||||
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
ANOTHER__TEST__THIS: 'foobar',
|
||||
SOMEBOOL: 'true',
|
||||
})
|
||||
})
|
||||
|
||||
t.test("should support custom seperator", function() {
|
||||
let store = new Nconf.Env({
|
||||
whitelist: ['another__test__this', 'somebool'],
|
||||
separator: '__',
|
||||
})
|
||||
store.load()
|
||||
|
||||
assert.strictEqual(store.get('ANOTHER:TEST:THIS'), 'foobar')
|
||||
assert.strictEqual(store.get('SOMEBOOL'), 'true')
|
||||
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
ANOTHER: {
|
||||
TEST: {
|
||||
THIS: 'foobar',
|
||||
},
|
||||
},
|
||||
SOMEBOOL: 'true',
|
||||
})
|
||||
})
|
||||
|
||||
t.test("should stay readOnly always", function() {
|
||||
let store = new Nconf.Env({whitelist: ['another__test__this']})
|
||||
assert.strictEqual(store.readOnly, true)
|
||||
store.load()
|
||||
assert.strictEqual(store.readOnly, true)
|
||||
})
|
||||
|
||||
t.test("should throw if whitelist is invalid", function() {
|
||||
assert.throws(function() {
|
||||
new Nconf.Env({whitelist: 'another__test__this'})
|
||||
}, /[Ww]hitelist.+[Aa]rray/)
|
||||
|
||||
assert.throws(function() {
|
||||
new Nconf.Env({whitelist: ['another__test__this', 123]})
|
||||
}, /[Ww]hitelist.+[Aa]rray/)
|
||||
})
|
||||
|
||||
t.test("should throw if match is invalid", function() {
|
||||
assert.throws(function() {
|
||||
new Nconf.Env({match: 1234})
|
||||
}, /[Mm]atch.+[Rr]eg[Ee]xp/)
|
||||
|
||||
assert.throws(function() {
|
||||
new Nconf.Env({match: {}})
|
||||
}, /[Mm]atch.+[Rr]eg[Ee]xp/)
|
||||
})
|
||||
|
||||
t.test("should automatically convert string match to RegExp", function() {
|
||||
let store = new Nconf.Env({match: 'asdf'})
|
||||
assert.ok(store.match)
|
||||
assert.ok(store.match.test('asdf'))
|
||||
assert.notOk(store.match.test('test'))
|
||||
})
|
||||
|
||||
t.test("should support whitelist directly in parameter", function() {
|
||||
let store = new Nconf.Env(['another__test__this'])
|
||||
store.load()
|
||||
|
||||
assert.strictEqual(store.get('ANOTHER__TEST__THIS'), 'foobar')
|
||||
|
||||
assert.deepStrictEqual(store.get(), {
|
||||
ANOTHER__TEST__THIS: 'foobar',
|
||||
})
|
||||
})
|
||||
|
||||
t.after(function() {
|
||||
Object.keys(backupEnv).forEach(function (key) {
|
||||
process.env[key] = backupEnv[key]
|
||||
})
|
||||
})
|
||||
})
|
|
@ -0,0 +1,250 @@
|
|||
import fs from 'fs'
|
||||
import { Eltro as t, assert} from 'eltro'
|
||||
import * as helpers from '../helpers.mjs'
|
||||
import { data } from '../fixtures/data.mjs'
|
||||
import Nconf from '../../lib/nconf.mjs'
|
||||
|
||||
const fsPromise = fs.promises
|
||||
|
||||
// let yamlFormat = require('nconf-yaml')
|
||||
|
||||
t.describe('#load()', function() {
|
||||
let validFile = helpers.fixture('store.json')
|
||||
fs.writeFileSync(validFile, JSON.stringify(data, null, 2))
|
||||
let malformedFile = helpers.fixture('malformed.json')
|
||||
let bomFile = helpers.fixture('bom.json')
|
||||
let noBomPath = helpers.fixture('no-bom.json')
|
||||
|
||||
t.test('with valid json should load correctly', function() {
|
||||
let store = new Nconf.File({file: validFile})
|
||||
store.load()
|
||||
assert.deepStrictEqual(store.store, data)
|
||||
})
|
||||
|
||||
t.test('with only file string as option', function() {
|
||||
let store = new Nconf.File(validFile)
|
||||
store.load()
|
||||
assert.deepStrictEqual(store.store, data)
|
||||
})
|
||||
|
||||
t.test('malformed JSON should respond with an error and indicate file name', function() {
|
||||
let store = new Nconf.File({file: malformedFile})
|
||||
assert.throws(() => {
|
||||
store.load()
|
||||
}, /malformed\.json/)
|
||||
})
|
||||
|
||||
t.test('with a valid UTF8 JSON file that contains a BOM', function() {
|
||||
let store = new Nconf.File(bomFile)
|
||||
store.load()
|
||||
assert.strictEqual(store.get('port'), 78304)
|
||||
assert.strictEqual(store.get('host'), 'weebls-stuff.com')
|
||||
})
|
||||
|
||||
t.test('with a valid UTF8 JSON file that contains no BOM', function() {
|
||||
let store = new Nconf.File(noBomPath)
|
||||
store.load()
|
||||
assert.strictEqual(store.get('port'), 78304)
|
||||
assert.strictEqual(store.get('host'), 'weebls-stuff.com')
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#loadAsync()', function() {
|
||||
let validFile = helpers.fixture('store.json')
|
||||
fs.writeFileSync(validFile, JSON.stringify(data, null, 2))
|
||||
let malformedFile = helpers.fixture('malformed.json')
|
||||
let bomFile = helpers.fixture('bom.json')
|
||||
let noBomPath = helpers.fixture('no-bom.json')
|
||||
|
||||
t.test('with valid json should load correctly', function() {
|
||||
let store = new Nconf.File({file: validFile})
|
||||
return store.loadAsync().then(function(newData) {
|
||||
assert.strictEqual(newData, store.store)
|
||||
assert.deepStrictEqual(store.store, data)
|
||||
})
|
||||
})
|
||||
|
||||
t.test('with only file string as option', function() {
|
||||
let store = new Nconf.File(validFile)
|
||||
return store.loadAsync().then(function() {
|
||||
assert.deepStrictEqual(store.store, data)
|
||||
})
|
||||
})
|
||||
|
||||
t.test('malformed JSON should respond with an error and indicate file name', function() {
|
||||
let store = new Nconf.File({file: malformedFile})
|
||||
assert.isRejected(store.loadAsync()).then(function(err) {
|
||||
assert.match(err.message, /malformed\.json/)
|
||||
})
|
||||
})
|
||||
|
||||
t.test('with a valid UTF8 JSON file that contains a BOM', function() {
|
||||
let store = new Nconf.File(bomFile)
|
||||
return store.loadAsync().then(function() {
|
||||
assert.strictEqual(store.get('port'), 78304)
|
||||
assert.strictEqual(store.get('host'), 'weebls-stuff.com')
|
||||
})
|
||||
})
|
||||
|
||||
t.test('with a valid UTF8 JSON file that contains no BOM', function() {
|
||||
let store = new Nconf.File(noBomPath)
|
||||
return store.loadAsync().then(function() {
|
||||
assert.strictEqual(store.get('port'), 78304)
|
||||
assert.strictEqual(store.get('host'), 'weebls-stuff.com')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#save()', function() {
|
||||
let testPath = helpers.fixture('tmp.json')
|
||||
let testSecondPath = helpers.fixture('tmp2.json')
|
||||
|
||||
t.test('should save the data correctly to original file specified', function() {
|
||||
let store = new Nconf.File({file: testPath})
|
||||
|
||||
Object.keys(data).forEach(function (key) {
|
||||
store.set(key, data[key])
|
||||
})
|
||||
|
||||
assert.strictEqual(store.save(), store)
|
||||
|
||||
let readData = JSON.parse(fs.readFileSync(store.file))
|
||||
assert.deepStrictEqual(readData, data)
|
||||
})
|
||||
|
||||
t.test('should save the data to specified file', function() {
|
||||
let store = new Nconf.File({file: testPath})
|
||||
|
||||
Object.keys(data).forEach(function (key) {
|
||||
store.set(key, data[key])
|
||||
})
|
||||
|
||||
store.save(testSecondPath)
|
||||
|
||||
let readData = JSON.parse(fs.readFileSync(testSecondPath))
|
||||
assert.deepStrictEqual(readData, data)
|
||||
})
|
||||
|
||||
t.after(function() {
|
||||
return Promise.all([
|
||||
fsPromise.unlink(testPath),
|
||||
fsPromise.unlink(testSecondPath),
|
||||
]).catch(function() {})
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#saveAsync()', function() {
|
||||
let testPath = helpers.fixture('tmp.json')
|
||||
let testSecondPath = helpers.fixture('tmp2.json')
|
||||
|
||||
t.test('should save the data correctly to original file specified', function() {
|
||||
let store = new Nconf.File({file: testPath})
|
||||
|
||||
Object.keys(data).forEach(function (key) {
|
||||
store.set(key, data[key])
|
||||
})
|
||||
|
||||
return store.saveAsync().then(function(checkStore) {
|
||||
assert.strictEqual(checkStore, store)
|
||||
return fsPromise.readFile(store.file)
|
||||
}).then(function(readData) {
|
||||
assert.deepStrictEqual(JSON.parse(readData), data)
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should save the data to specified file', function() {
|
||||
let store = new Nconf.File({file: testPath})
|
||||
|
||||
Object.keys(data).forEach(function (key) {
|
||||
store.set(key, data[key])
|
||||
})
|
||||
|
||||
return store.saveAsync(testSecondPath).then(function() {
|
||||
return fsPromise.readFile(testSecondPath)
|
||||
}).then(function(readData) {
|
||||
assert.deepStrictEqual(JSON.parse(readData), data)
|
||||
})
|
||||
})
|
||||
|
||||
t.after(function() {
|
||||
return Promise.all([
|
||||
fsPromise.unlink(testPath),
|
||||
fsPromise.unlink(testSecondPath),
|
||||
]).catch(function() {})
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#secure', function() {
|
||||
t.test('the stringify() method should encrypt properly', function() {
|
||||
let secureStore = new Nconf.File({
|
||||
file: helpers.fixture('secure-iv.json'),
|
||||
secure: 'super-secret-key-32-characterszz'
|
||||
})
|
||||
secureStore.store = data
|
||||
|
||||
let contents = JSON.parse(secureStore.stringify())
|
||||
Object.keys(data).forEach(key => {
|
||||
assert.strictEqual(typeof(contents[key]), 'object')
|
||||
assert.strictEqual(typeof(contents[key].value), 'string')
|
||||
assert.strictEqual(contents[key].alg, 'aes-256-ctr')
|
||||
assert.strictEqual(typeof(contents[key].iv), 'string')
|
||||
})
|
||||
})
|
||||
|
||||
t.test('the parse() method should decrypt properly', function() {
|
||||
let secureStore = new Nconf.File({
|
||||
file: helpers.fixture('secure-iv.json'),
|
||||
secure: 'super-secret-key-32-characterszz'
|
||||
})
|
||||
secureStore.store = data
|
||||
|
||||
let contents = secureStore.stringify()
|
||||
let parsed = secureStore.parse(contents)
|
||||
assert.deepStrictEqual(parsed, data)
|
||||
})
|
||||
|
||||
t.test('the load() method should decrypt properly', function() {
|
||||
let secureStore = new Nconf.File({
|
||||
file: helpers.fixture('secure-iv.json'),
|
||||
secure: 'super-secret-key-32-characterszz'
|
||||
})
|
||||
secureStore.load()
|
||||
assert.deepStrictEqual(secureStore.store, data)
|
||||
})
|
||||
|
||||
t.test('it should throw error on legacy encrypted files', function() {
|
||||
let secureStore = new Nconf.File({
|
||||
file: helpers.fixture('secure.json'),
|
||||
secure: 'super-secretzzz'
|
||||
})
|
||||
|
||||
assert.throws(function() {
|
||||
secureStore.load()
|
||||
}, /[Oo]utdated/)
|
||||
})
|
||||
})
|
||||
|
||||
/*
|
||||
|
||||
t.test('the search() method when the target file exists higher in the directory tree should update the file appropriately', function() {
|
||||
let searchBase = require('os').homedir()
|
||||
let filePath = path.join(searchBase, '.nconf')
|
||||
fs.writeFileSync(filePath, JSON.stringify(data, null, 2))
|
||||
let store = new Nconf.File({
|
||||
file: '.nconf'
|
||||
})
|
||||
store.search(store.searchBase)
|
||||
expect(store.file).toEqual(filePath)
|
||||
fs.unlinkSync(filePath)
|
||||
})
|
||||
t.test('the search() method when the target file doesn't exist higher in the directory tree should update the file appropriately', function() {
|
||||
let filePath = helpers.fixture('search-store.json')
|
||||
let store = new Nconf.File({
|
||||
dir: path.dirname(filePath),
|
||||
file: 'search-store.json'
|
||||
})
|
||||
store.search()
|
||||
expect(store.file).toEqual(filePath)
|
||||
})
|
||||
|
||||
*/
|
|
@ -0,0 +1,24 @@
|
|||
import { Eltro as t, assert} from 'eltro'
|
||||
import Nconf from '../../lib/nconf.mjs'
|
||||
|
||||
t.describe('nconf/stores/literal, An instance of nconf.Literal', function () {
|
||||
var envOptions = {foo: 'bar', one: 2}
|
||||
|
||||
t.test("should have the correct methods defined", function () {
|
||||
var literal = new Nconf.Literal()
|
||||
assert.ok(literal.readOnly)
|
||||
assert.strictEqual(literal.type, 'literal')
|
||||
assert.strictEqual(typeof(literal.get), 'function')
|
||||
assert.strictEqual(typeof(literal.set), 'function')
|
||||
assert.strictEqual(typeof(literal.merge), 'function')
|
||||
assert.strictEqual(typeof(literal.loadSync), 'function')
|
||||
})
|
||||
|
||||
t.test("should have the correct values in the store", function () {
|
||||
var literal = new Nconf.Literal(envOptions)
|
||||
assert.strictEqual(literal.store.foo, 'bar')
|
||||
assert.strictEqual(literal.store.one, 2)
|
||||
assert.notOk(literal.set('foo', 'foo'))
|
||||
assert.strictEqual(literal.store.foo, 'bar')
|
||||
})
|
||||
})
|
|
@ -0,0 +1,379 @@
|
|||
import { Eltro as t, assert} from 'eltro'
|
||||
import Nconf from '../../lib/nconf.mjs'
|
||||
import { merge } from '../fixtures/data.mjs'
|
||||
|
||||
t.describe('Memory Store', function () {
|
||||
let store = new Nconf.Memory()
|
||||
|
||||
t.describe('#set()', function() {
|
||||
t.test('should return true', function () {
|
||||
assert.ok(store.set('foo:bar:bazz', 'buzz'))
|
||||
assert.ok(store.set('falsy:number', 0))
|
||||
assert.ok(store.set('falsy:string:empty', ''))
|
||||
assert.ok(store.set('falsy:string:value', 'value'))
|
||||
assert.ok(store.set('falsy:boolean', false))
|
||||
assert.ok(store.set('falsy:object', null))
|
||||
})
|
||||
|
||||
t.test('should support numbers as key', function() {
|
||||
assert.notOk(store.get('523453'))
|
||||
assert.ok(store.set(523453, true))
|
||||
assert.ok(store.get('523453'))
|
||||
})
|
||||
|
||||
t.test('should always make sure not store direct references to objects', function() {
|
||||
const assertArray = [ 1, 2 ]
|
||||
const assertObject = { a: 1 }
|
||||
|
||||
assert.ok(store.set('reference:test:arraydirect', assertArray))
|
||||
assert.notStrictEqual(store.get('reference:test:arraydirect'), assertArray)
|
||||
assert.ok(store.set('reference:test:objectdirect', assertObject))
|
||||
assert.notStrictEqual(store.get('reference:test:objectdirect'), assertObject)
|
||||
assert.ok(store.set('reference:test:objectchild', { x: assertArray, y: assertObject }))
|
||||
assert.notStrictEqual(store.get('reference:test:objectchild:x'), assertArray)
|
||||
assert.notStrictEqual(store.get('reference:test:objectchild:y'), assertObject)
|
||||
})
|
||||
|
||||
t.test('should support numbers as key', function() {
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({ version: 1 })
|
||||
assert.ok(inStore.set('version', 2))
|
||||
assert.strictEqual(inStore.get('version'), 2)
|
||||
inStore.readOnly = true
|
||||
assert.notOk(inStore.set('version', 3))
|
||||
assert.strictEqual(inStore.get('version'), 2)
|
||||
})
|
||||
|
||||
t.test('should support numbers as key', function() {
|
||||
let inStore = new Nconf.Memory({ parseValues: true })
|
||||
inStore.set('test', '{"a":1}')
|
||||
assert.ok(inStore.get('test'))
|
||||
assert.deepStrictEqual(inStore.get('test'), { a: 1 })
|
||||
inStore.set('test', 'undefined')
|
||||
assert.notOk(inStore.get('test'))
|
||||
})
|
||||
|
||||
t.test('should not do anything if given invalid set root', function() {
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({ version: 1 })
|
||||
assert.deepStrictEqual(inStore.get(), { version: 1 })
|
||||
assert.notOk(inStore.set(null))
|
||||
assert.deepStrictEqual(inStore.get(), { version: 1 })
|
||||
assert.notOk(inStore.set())
|
||||
assert.deepStrictEqual(inStore.get(), { version: 1 })
|
||||
assert.notOk(inStore.set([1, 2]))
|
||||
assert.deepStrictEqual(inStore.get(), { version: 1 })
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#get()', function() {
|
||||
t.test('should respond with the correct value', function () {
|
||||
store.set('foo:bar:bazz', 'buzz')
|
||||
store.set('falsy:number', 0)
|
||||
store.set('falsy:string:empty', '')
|
||||
store.set('falsy:string:value', 'value')
|
||||
store.set('falsy:boolean', false)
|
||||
store.set('falsy:object', null)
|
||||
assert.strictEqual(store.get('foo:bar:bazz'), 'buzz')
|
||||
assert.strictEqual(store.get('falsy:number'), 0)
|
||||
assert.strictEqual(store.get('falsy:string:empty'), '')
|
||||
assert.strictEqual(store.get('falsy:string:value'), 'value')
|
||||
assert.strictEqual(store.get('falsy:boolean'), false)
|
||||
assert.strictEqual(store.get('falsy:object'), null)
|
||||
})
|
||||
|
||||
t.describe('should not at non-existent keys', function () {
|
||||
t.test('at the root level', function () {
|
||||
assert.strictEqual(store.get('this:key:does:not:exist'), undefined)
|
||||
})
|
||||
|
||||
t.test('within numbers', function () {
|
||||
assert.strictEqual(store.get('falsy:number:not:exist'), undefined)
|
||||
})
|
||||
|
||||
t.test('within booleans', function () {
|
||||
assert.strictEqual(store.get('falsy:boolean:not:exist'), undefined)
|
||||
})
|
||||
|
||||
t.test('within objects', function () {
|
||||
assert.strictEqual(store.get('falsy:object:not:exist'), undefined)
|
||||
})
|
||||
|
||||
t.test('within empty strings', function () {
|
||||
assert.strictEqual(store.get('falsy:string:empty:not:exist'), undefined)
|
||||
})
|
||||
|
||||
t.test('within non-empty strings', function () {
|
||||
assert.strictEqual(store.get('falsy:string:value:not:exist'), undefined)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#clear()', function() {
|
||||
t.test('should return false if readonly', function() {
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({ version: 1 })
|
||||
inStore.readOnly = true
|
||||
assert.notOk(inStore.clear('version'))
|
||||
assert.strictEqual(inStore.get('version'), 1)
|
||||
})
|
||||
|
||||
t.test('the clear() should return true if success', function () {
|
||||
store.set('foo:bar:bazz', 'buzz')
|
||||
assert.strictEqual(store.get('foo:bar:bazz'), 'buzz')
|
||||
assert.ok(store.clear('foo:bar:bazz'))
|
||||
assert.strictEqual(typeof store.get('foo:bar:bazz'), 'undefined')
|
||||
})
|
||||
|
||||
t.test('should return false if not found', function() {
|
||||
store.set('this:exists', 'fornow')
|
||||
assert.strictEqual(store.get('this:exists'), 'fornow')
|
||||
assert.notOk(store.clear('this:exists:but:not:this'))
|
||||
assert.strictEqual(store.get('this:exists'), 'fornow')
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#merge()', function () {
|
||||
t.test('should return false if readonly', function() {
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({ version: 1 })
|
||||
inStore.readOnly = true
|
||||
assert.notOk(inStore.merge({ version: 2 }))
|
||||
assert.strictEqual(inStore.get('version'), 1)
|
||||
})
|
||||
|
||||
t.test('when overriding an existing literal value', function () {
|
||||
store.set('merge:literal', 'string-value')
|
||||
store.merge('merge:literal', merge)
|
||||
assert.deepStrictEqual(store.get('merge:literal'), merge)
|
||||
})
|
||||
|
||||
t.test('when overriding an existing Array value', function () {
|
||||
store.set('merge:array', [1, 2, 3, 4])
|
||||
store.merge('merge:array', merge)
|
||||
assert.deepStrictEqual(store.get('merge:literal'), merge)
|
||||
})
|
||||
|
||||
t.test('when merging into an existing Object value', function () {
|
||||
store.set('merge:object', {
|
||||
prop1: 2,
|
||||
prop2: 'prop2',
|
||||
prop3: {
|
||||
bazz: 'bazz'
|
||||
},
|
||||
prop4: ['foo', 'bar']
|
||||
})
|
||||
assert.strictEqual(store.get('merge:object:prop1'), 2)
|
||||
assert.strictEqual(store.get('merge:object:prop2'), 'prop2')
|
||||
assert.deepStrictEqual(store.get('merge:object:prop3'), {
|
||||
bazz: 'bazz'
|
||||
})
|
||||
assert.strictEqual(store.get('merge:object:prop4').length, 2)
|
||||
|
||||
store.merge('merge:object', merge)
|
||||
|
||||
assert.strictEqual(store.get('merge:object:prop1'), 1)
|
||||
assert.strictEqual(store.get('merge:object:prop2').length, 3)
|
||||
assert.deepStrictEqual(store.get('merge:object:prop3'), {
|
||||
foo: 'bar',
|
||||
bar: 'foo',
|
||||
bazz: 'bazz'
|
||||
})
|
||||
assert.strictEqual(store.get('merge:object:prop4').length, 2)
|
||||
})
|
||||
|
||||
t.test('when merging at root level with an object', function() {
|
||||
const assertFirst = 'herp'
|
||||
const assertAfter = 'derp'
|
||||
const newItem = { asdf: assertAfter }
|
||||
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({
|
||||
version: 1,
|
||||
asdf: assertFirst,
|
||||
})
|
||||
assert.strictEqual(inStore.get('asdf'), assertFirst)
|
||||
assert.strictEqual(inStore.get('version'), 1)
|
||||
assert.ok(inStore.merge(newItem))
|
||||
assert.notStrictEqual(inStore.get(), newItem)
|
||||
assert.strictEqual(inStore.get('asdf'), assertAfter)
|
||||
assert.strictEqual(inStore.get('version'), 1)
|
||||
})
|
||||
|
||||
t.test('when merging at root level with an object with null after', function() {
|
||||
const assertFirst = 'herp'
|
||||
const assertAfter = 'derp'
|
||||
const newItem = { asdf: assertAfter }
|
||||
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({
|
||||
version: 1,
|
||||
asdf: assertFirst,
|
||||
})
|
||||
assert.strictEqual(inStore.get('asdf'), assertFirst)
|
||||
assert.strictEqual(inStore.get('version'), 1)
|
||||
assert.ok(inStore.merge(newItem), null)
|
||||
assert.notStrictEqual(inStore.get(), newItem)
|
||||
assert.strictEqual(inStore.get('asdf'), assertAfter)
|
||||
assert.strictEqual(inStore.get('version'), 1)
|
||||
})
|
||||
|
||||
t.test('when merging at root level with array', function() {
|
||||
const newItem = 'herp'
|
||||
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({
|
||||
version: 1,
|
||||
})
|
||||
assert.strictEqual(inStore.get('version'), 1)
|
||||
assert.notOk(inStore.get('0'))
|
||||
assert.ok(inStore.merge([newItem]))
|
||||
assert.ok(inStore.get('0'))
|
||||
assert.strictEqual(inStore.get('0'), newItem)
|
||||
assert.strictEqual(inStore.get('version'), 1)
|
||||
})
|
||||
|
||||
t.test('when merging at root level with array and null after', function() {
|
||||
const newItem = 'herp'
|
||||
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({
|
||||
version: 1,
|
||||
})
|
||||
assert.strictEqual(inStore.get('version'), 1)
|
||||
assert.notOk(inStore.get('0'))
|
||||
assert.ok(inStore.merge([newItem], null))
|
||||
assert.ok(inStore.get('0'))
|
||||
assert.strictEqual(inStore.get('0'), newItem)
|
||||
assert.strictEqual(inStore.get('version'), 1)
|
||||
})
|
||||
|
||||
t.test('it should always merge at root level if key is object regardless of what comes after', function() {
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({ herp: 1 })
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1 })
|
||||
assert.ok(inStore.merge({ version: 2 }, null))
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1, version: 2 })
|
||||
assert.ok(inStore.merge({ test: 3 }, 1235))
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1, version: 2, test: 3 })
|
||||
assert.ok(inStore.merge({ foo: 4 }, 'sadfsadfs'))
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1, version: 2, test: 3, foo: 4 })
|
||||
assert.ok(inStore.merge({ bar: 5 }, { asdf: 1 }))
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1, version: 2, test: 3, foo: 4, bar: 5 })
|
||||
})
|
||||
|
||||
t.test('it should be robust about key type and overwriting', function() {
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({ herp: 1 })
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1 })
|
||||
assert.ok(inStore.merge(123, null))
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1, '123': null })
|
||||
assert.ok(inStore.merge(123, { a: 1 }))
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1, '123': { a: 1 } })
|
||||
assert.ok(inStore.merge(123, ['a', 1]))
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1, '123': ['a', 1] })
|
||||
})
|
||||
|
||||
t.test('it be able to handle basic value types with basic values', function() {
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({ herp: 1 })
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1 })
|
||||
assert.ok(inStore.merge({ version: 2 }, null))
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1, version: 2 })
|
||||
assert.ok(inStore.merge({ test: 3 }, 1235))
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1, version: 2, test: 3 })
|
||||
assert.ok(inStore.merge({ foo: 4 }, 'sadfsadfs'))
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1, version: 2, test: 3, foo: 4 })
|
||||
assert.ok(inStore.merge({ bar: 5 }, { asdf: 1 }))
|
||||
assert.deepStrictEqual(inStore.get(), { herp: 1, version: 2, test: 3, foo: 4, bar: 5 })
|
||||
})
|
||||
|
||||
t.test('when sending a single path with null, string or number value should overwrite', function() {
|
||||
const assertString = 'Beginning'
|
||||
const assertNumber = 358792
|
||||
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({
|
||||
herp: {
|
||||
derp: 123,
|
||||
},
|
||||
})
|
||||
assert.strictEqual(inStore.get('herp:derp'), 123)
|
||||
assert.ok(inStore.merge('herp:derp', null))
|
||||
assert.strictEqual(inStore.get('herp:derp'), null)
|
||||
assert.ok(inStore.merge('herp:derp', assertString))
|
||||
assert.strictEqual(inStore.get('herp:derp'), assertString)
|
||||
assert.ok(inStore.merge('herp:derp', assertNumber))
|
||||
assert.strictEqual(inStore.get('herp:derp'), assertNumber)
|
||||
})
|
||||
|
||||
t.test('when merging at nonexisting path', function() {
|
||||
const assertNewItem = { a: 1, b: 2 }
|
||||
const assertPath = 'new:path:for:item'
|
||||
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set({
|
||||
version: 1,
|
||||
})
|
||||
assert.strictEqual(inStore.get('version'), 1)
|
||||
assert.notOk(inStore.get(assertPath))
|
||||
|
||||
assert.ok(inStore.merge(assertPath, assertNewItem))
|
||||
assert.ok(inStore.get(assertPath))
|
||||
assert.notStrictEqual(inStore.get(assertPath), assertNewItem)
|
||||
assert.deepStrictEqual(inStore.get(assertPath), assertNewItem)
|
||||
assert.deepStrictEqual(inStore.get().new.path.for.item, assertNewItem)
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#reset()', function() {
|
||||
t.test('should remove everything', function() {
|
||||
const assertRoot = {
|
||||
version: 1,
|
||||
asdf: 'test',
|
||||
}
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set(assertRoot)
|
||||
assert.deepStrictEqual(inStore.get(), assertRoot)
|
||||
inStore.reset()
|
||||
assert.deepStrictEqual(inStore.get(), {})
|
||||
})
|
||||
|
||||
t.test('should do nothing if readonly', function() {
|
||||
const assertRoot = {
|
||||
version: 1,
|
||||
asdf: 'test',
|
||||
}
|
||||
let inStore = new Nconf.Memory()
|
||||
inStore.set(assertRoot)
|
||||
assert.deepStrictEqual(inStore.get(), assertRoot)
|
||||
|
||||
inStore.readOnly = true
|
||||
assert.notOk(inStore.reset())
|
||||
assert.deepStrictEqual(inStore.get(), assertRoot)
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('options', function () {
|
||||
t.describe('logicalSeparator', function () {
|
||||
var store = new Nconf.Memory({logicalSeparator: '||'})
|
||||
|
||||
t.test('when storing with : (colon), should store the config atomicly', function () {
|
||||
store.set('foo:bar:bazz', 'buzz')
|
||||
assert.strictEqual(typeof store.get('foo:bar'), 'undefined')
|
||||
assert.strictEqual(store.get('foo:bar:bazz'), 'buzz')
|
||||
})
|
||||
|
||||
t.test('when storing with separator, should be able to read the object', function () {
|
||||
store.set('foo||bar||bazz', 'buzz')
|
||||
assert.strictEqual(store.get('foo||bar').bazz, 'buzz')
|
||||
assert.strictEqual(store.get('foo').bar.bazz, 'buzz')
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should allow specifying readonly', function () {
|
||||
var store = new Nconf.Memory({ readOnly: true })
|
||||
assert.strictEqual(store.readOnly, true)
|
||||
})
|
||||
})
|
||||
})
|
27
usage.js
27
usage.js
|
@ -1,27 +0,0 @@
|
|||
require.paths.unshift(require('path').join(__dirname, 'lib'));
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
nconf = require('nconf');
|
||||
|
||||
//
|
||||
// Setup nconf to user the 'file' store and set a couple of values;
|
||||
//
|
||||
nconf.use('file', { file: path.join(__dirname, 'config.json') });
|
||||
nconf.set('database:host', '127.0.0.1');
|
||||
nconf.set('database:port', 5984);
|
||||
|
||||
//
|
||||
// Get the entire database object from nconf
|
||||
//
|
||||
var database = nconf.get('database');
|
||||
console.dir(database);
|
||||
|
||||
//
|
||||
// Save the configuration object to disk
|
||||
//
|
||||
nconf.save(function (err) {
|
||||
fs.readFile(path.join(__dirname, 'config.json'), function (err, data) {
|
||||
console.dir(JSON.parse(data.toString()))
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue