Compare commits

..

205 commits

Author SHA1 Message Date
296a65dfe1 2.1.0 2021-10-14 09:53:17 +00:00
2ee285e1c4 argv: Add support for boolean flags when equal sign is used 2021-10-14 09:52:56 +00:00
129e50367d circleci: Switch to alpine and add more versions 2021-06-23 09:41:27 +00:00
f43d81a2cd Merge branch 'master' of https://github.com/nfp-projects/nconf-lite 2021-06-23 09:39:42 +00:00
fa46b3b043 Fix ci and update engine in package 2021-06-23 09:39:40 +00:00
863fec827d Add .circleci/config.yml 2021-06-23 09:36:46 +00:00
98980c3453
Update README.md 2021-06-22 19:25:39 +00:00
1014cdec86 Finished completely rewriting both library and unit tests 2021-06-22 19:25:00 +00:00
1104c0d3ad Migrating a bunch of tests to ecmamodule 2021-06-07 08:58:26 +00:00
44a22ce6dd Move async to main dependancy 2020-06-02 10:36:58 +00:00
b824493aa6 Updated version to 1.0.0, updated changelog 2020-06-02 10:23:51 +00:00
2f66137a81 Update package and readme 2020-06-02 10:21:30 +00:00
c8a8d29d63 Add package-lock to ignore 2020-06-02 10:15:21 +00:00
455103a330 Remove argv and its huge yargs dependancy 2020-06-02 10:15:06 +00:00
renovate[bot]
aad2c1e449 [dist] Update dependency yargs to v14 (#334) 2019-11-14 14:56:06 -05:00
renovate[bot]
ee8e89c1b0 [dist] Update dependency eslint to v6 (#330) 2019-06-23 21:33:55 -04:00
renovate[bot]
0ee6938568 [dist] Update dependency yargs to v13 (#321) 2019-06-14 22:33:09 -04:00
Eric Bickle
7d625086ca Fix saveToFile tests on Windows. indexzero#325 (#329) 2019-06-14 22:11:34 -04:00
Eric Bickle
85edc9afad [fix] Jest as devDependency indexzero/nconf#327 (#328) 2019-06-14 22:03:35 -04:00
Indospace.io
20e00efd6c Change require fs (#313)
what is there now is bad, everyone will think they need the fs library, when they only need it for the last example.
2019-05-16 17:05:20 -04:00
renovate[bot]
e6f27f5d2c [dist] Update dependency jest to v24 (#320) 2019-05-16 17:03:06 -04:00
Matt Hamann
d582066743
Upgraded encryption using CipherIV (#322)
* Remove package-lock.json from gitignore

* Update dependencies and fix repo url

* Fix test

* Update to cipheriv

* Bump version

* Sync package-lock

* Revert extraneous package changes

* Revert minor doc change
2019-05-15 23:27:38 -04:00
renovate[bot]
10318c0098 Configure Renovate (#319)
* Add renovate.json

* [dist] Update renovate.json
2019-05-14 14:09:08 -04:00
indexzero
48c92ce989 [dist tiny] Remove unused CircleCI configs. 2019-05-13 23:23:50 -04:00
indexzero
52afef5218 [tiny dist] Regenerate package-lock.json file. 2019-05-13 23:14:22 -04:00
Charlie Robbins
75641ffaee
[dist] Drop unsupported versions of Node. No automated publishing just yet. (#318) 2019-05-13 23:10:23 -04:00
Matt Hamann
1bb9d091f1 Switch to circleci (#317) 2019-05-13 22:56:47 -04:00
Adrien Becchis
b8686aeff0 Migrating test to jest (#292)
* set up jest dependencies

* add parser option to eslint to support es6

* migrate first test to jest

* migrate the argv test to shpec

* convert the env and literal store tests

* convert the file-store tests

* convert the memory-store tests

* convert the hierarchy tests

* convert the provider-save test

* convert the complete test

* convert the provider test

* convert the conf test

* tweak a test that was no longer working (context changed)

* replace in place the helpers file

* remove vows dependency

* update the test invocation to rely on jest

* update the argv test to be able to use the jest --verbose option

* Some tweaks to the test to have them working

* Update node version tested (+10 +12 -9)

* Replace const by var until we drop 0.10/0.12/4 node

* Replace let by var until we drop 0.10/0.12/4 node
2019-04-29 22:26:02 -04:00
Matt Hamann
17376d4d17
Update packages to resolve security vulnerabilities (#306) 2018-09-27 13:03:17 -04:00
louis-murray
391665cc38 Enable writes env and argv stores with a flag (#285)
* added fucntionality to toggle readonly for env store

* fixed issue with using lint

* updated readme to reflect env options change

* updated tests to better test readOnly property

* added fucntionality to toggle readonly for env store

* fixed issue with using lint

* updated readme to reflect env options change

* updated tests to better test readOnly property

* updated tests to fix issues.

* updated argv to have readOnly toggle-able

* added tests for argv toggle-able readonly
2017-11-12 23:11:01 -05:00
Austin Burdine
6c5ba64db6 whitelist npm published files (#236)
- reduces files published to npm and downloaded with every install
2017-11-11 10:48:49 -05:00
Adrien Becchis
c1e15681db Upgrading dependencies (#280)
* upgrade yargs and async dependencies.

were breaking change, but no impact according the tests

* upgrade yargs and package-lock.json

* add node 8 to the tested versions

* add node 8 to the allowed failures as requested

* add node 9 to travis build as acceptable failure and remove node 7
2017-11-06 11:15:12 -05:00
bryce-gibson
b6699aba2d Don't do array lookups on strings. (#188)
`hasOwnProperty(number)` can return true for strings.

This is unlikely to be the desired usage, and can mean that odd
responses are returned by nconf.

Disable trying to check `hasOwnProperty` of strings.
2017-11-04 21:39:00 -04:00
Adrien Becchis
467ab753c8 Regex as env separator (#288)
* use regexp as env separator (support shorthand specification)

* add test to cover the env separator
2017-11-04 21:30:56 -04:00
Adrien Becchis
e5db2ef6d7 Argv store separator (#291)
* argv store now accept a separator argument to create nested values

* remove stub file that shouldnt have been commited

* write a test to ensure separator is working well and use delete rather than undefined assign
2017-11-04 21:30:14 -04:00
Ahmed Ayoub
3607767f90 fixes #258 chainable .required() (#259)
* fixes #258 chainable .required()

* fixes #258 use var instead of let for travis builds
2017-11-04 00:34:27 -04:00
Matt Hamann
bac910a6df 0.9.1 2017-11-03 23:52:19 -04:00
Adrien Becchis
2bdf7e1a32 Clean Argv Store options (#290)
* unset parse/transform from options and ensure they are not yargs options

* use delete rather than undefined assignement
2017-11-03 23:41:23 -04:00
Adrien Becchis
b9321b200a transformer can now return an undefined key (#289) 2017-11-03 23:22:13 -04:00
Matt Hamann
81ce0be01e Update changelog 2017-10-31 20:20:27 -04:00
Augusto Franzoia
b1ee63cfa4 fix error in transform function when dealing with dropped entries (#287) 2017-10-31 17:12:31 -04:00
Matt Hamann
9f70ba148f [doc] Update changelog 2017-10-30 11:27:11 -04:00
Matt Hamann
8afcf991eb [dist] Version bump. 0.9.0 2017-10-30 10:26:30 -04:00
Adrien Becchis
b41c505c6e Save conf to dedicated file (#283)
* Added support for saving configuration to a specific file

Added support for saving configuration to a specific file

* add test to cover the save to file feature

* add posibility to specify a format to save to file

* add a test with nconf-yaml to ensure specifying a format works
2017-10-30 10:01:55 -04:00
Matt Hamann
52e0a3566e Update changelog 2017-10-28 21:16:03 -04:00
AdrieanKhisbe
fa215a44f1 add tests for the normal configuration of yargs via argv 2017-10-28 17:13:38 -04:00
AdrieanKhisbe
802a8d623f test for yargs custom instance (more flexible check isYargs) 2017-10-28 17:13:38 -04:00
Nicolas Deveaud
3e26bb2756 Add posibility to pass a yargs instance to argv() method 2017-10-28 17:13:38 -04:00
Matt Hamann
856fdf8dff First pass at transform functions (#279) 2017-10-25 22:57:58 -04:00
Matt Hamann
b9c345bf96 Fix parseValues option name 2017-10-21 21:58:30 -04:00
Matt Hamann
35088a3313 Added nconf.any method (#278)
* Added nconf.any method

Fixes #126
Implemented on the Provider class
Takes an array of keys, or a variable argument list
Supports both callback and non-callback invocations

* Use an explicit search base in file store test

Fixes #224
Test file was created under process.env.HOME, but test was searching in
the current working directory. If the cwd was not on the same drive as
the home directory, the test would fail.

* Added some API documentation to README for 'any'

* Tweak `.any` documentation
2017-10-21 16:42:24 -04:00
Matt Hamann
ca10d0eaf8 Add basic linting rules 2017-10-21 16:01:06 -04:00
Brian Harrington
bfb0220fe1 Remove unused module (#277)
crypto is no longer used in file.js
2017-10-21 15:47:41 -04:00
Matt Hamann
532ac9cc57 Support parsing simple values from env/argv strings (#273)
* simple parse, indexzero/nconf#72

* documentation for tryParse option

* Combine JSON parsing and simple parsing
2017-10-21 15:39:16 -04:00
Matt Hamann
b8402d4eab Enable support for parsing JSON environment variables (#272)
* Add support for applying JSON string

* only take JSON Object or JSON Array into consideration

* Add tests and make JSON-parsing opt-in
2017-09-27 16:32:26 -04:00
Matt Hamann
f46c449a9e 0.8.5 2017-08-15 23:59:31 -04:00
Matt Hamann
552300a687 [doc] Document lowerCase option in .env(options) (#268)
- Add missing documentation about the lowerCase option
2017-08-15 23:58:13 -04:00
evoye
5e8a34d6cf enable use with webpack by removing unnecessary fs call (#252) 2017-08-15 23:39:34 -04:00
Chris Manson
608b607782 Add test for merging with defaults (#255)
* implementing a test for merging with defaults

* bypassing strange common tests

* trying to fix travis build in node 7

* adding node 8 to tests

* removing node 8
2017-08-15 23:37:19 -04:00
Charlie Robbins
0c5774fec7 Merge pull request #211 from vanjan/fix-env-ignore-case
Copy `process.env` before lower-casing the keys
2016-08-25 12:48:47 -04:00
Charlie Robbins
011be49a5c Merge pull request #222 from katacarbix/patch-1
Fixed some issues with code escaping in README.md
2016-06-15 05:52:32 -04:00
Charter Jacobson
d70b6a0335 Fixed some issues with code escaping 2016-05-14 14:55:23 -05:00
Jan Klosinski
392c6022c9 Copy process.env before lower-casing the keys
`process.env` is read-only in GitBash (and potentially other consoles),
so the `lowerCase` flag had no effect.
2016-03-01 17:08:35 +00:00
Jarrett Cruger
3d4e589578 [dist] Version bump. 0.8.4 2016-02-03 00:39:12 -08:00
Charlie Robbins
b065c4ccd9 Merge pull request #209 from indexzero/better-DX
[fix] handle buffers
2016-02-02 21:46:14 -08:00
Jarrett Cruger
4431c33162 [fix] handle buffers so we dont get ambiguous errors when we dont strictly read the file as utf8 2016-02-02 16:38:48 -08:00
Jarrett Cruger
54cab2059a [dist] Version bump. 0.8.3 2016-02-01 22:26:12 -08:00
Charlie Robbins
f554382435 Merge pull request #208 from indexzero/clean-secure
[fix] cleanup secure with new module
2016-02-02 01:24:49 -05:00
Jarrett Cruger
b447268097 [fix] cleanup secure with new module 2016-02-01 22:21:15 -08:00
Jarrett Cruger
3d4682a62f Merge pull request #207 from moberemk/patch-1
Update README.md
2016-01-27 12:32:26 -05:00
Mark Oberemk
de551d42ec Update README.md
Add basic documentation explaining the `nconf.required` method
2016-01-27 12:29:26 -05:00
Charlie Robbins
4a59c9b577 Merge pull request #191 from wturyn/feature-mandatory-keys
Feature: mandatory keys - required() method
2016-01-27 09:20:20 -08:00
Charlie Robbins
e58d55429d Merge pull request #195 from AdrieanKhisbe/features/improved-ci
Improved CI
2015-12-22 14:21:07 -05:00
AdrieanKhisbe
c242f777a6 [travis test] setup coveralls config + update README badges 2015-12-03 08:18:44 +01:00
AdrieanKhisbe
c8dbede0ca [test] setup istanbul coverage 2015-12-03 08:03:12 +01:00
AdrieanKhisbe
bdecdc29cf [travis] add v5 to node version tested 2015-12-03 07:48:52 +01:00
Wojtek Turyn
5d6e236b73 fixed 2015-10-15 10:44:26 +02:00
Wojtek Turyn
37a84ae8df required() method 2015-10-15 10:16:33 +02:00
indexzero
ddee9bc8f5 [dist] Version bump. 0.8.2 2015-10-07 15:32:55 -04:00
indexzero
86bfd7c5bc [fix] Do not trim \n from files read in. 2015-10-07 15:31:53 -04:00
indexzero
ff0f174520 [dist] Version bump. 0.8.1 2015-10-02 01:01:20 -07:00
indexzero
11b2448471 [fix] Correct property path. Trim read secret keys from disk. 2015-10-02 01:00:55 -07:00
indexzero
438a2c8ef5 [doc] Remove node@0.8.0 from travis. Drop nodeci because it is 503 atm`. 2015-09-21 17:11:52 -07:00
indexzero
ebd8e48342 [dist] Version bump. 0.8.0 2015-09-20 01:39:50 -07:00
indexzero
be085c9ad5 [doc] Update CHANGELOG.md. 2015-09-20 01:39:41 -07:00
indexzero
0922563593 [doc fix] Remove unused and outdated literate coding documentation. 2015-09-20 01:37:09 -07:00
Charlie Robbins
e503718468 Merge pull request #186 from indexzero/fix-redis
Fix some minor consistency issues in Redis
2015-09-20 01:14:43 -07:00
Charlie Robbins
d4ebf49908 Merge pull request #185 from indexzero/crypto
[wip] Allow for "secure" option to be passed to `nconf.stores.File`
2015-09-20 01:13:26 -07:00
indexzero
4b5030dbc2 [fix] Only merge actual objects, not null values. Fixes #150. 2015-09-20 01:10:37 -07:00
Rob Rodriguez
a3589fab95 Fixing provider issue in source 2015-09-20 01:08:45 -07:00
Rob Rodriguez
51653e6486 Passing the value parameter to the providers
The nconf-redis provider needs the value for some reason, if its absent
this call will fail. It should be there anyway.
2015-09-20 01:07:21 -07:00
indexzero
2030144d88 [test dist] Add test/fixtures/secure.json. 2015-09-20 00:36:49 -07:00
indexzero
9dbed2d2cd [doc minor] Update docs for secure information. 2015-09-20 00:34:44 -07:00
indexzero
0358545ae5 [test api] Make the format capable of sub-objects. 2015-09-20 00:26:34 -07:00
indexzero
04c0f3a001 [api test] Encrypt individual keys instead of entire stringified contents. Added basic unit tests. 2015-09-19 00:12:50 -07:00
indexzero
d2b3561e09 [dist] Update .travis.yml. 2015-09-18 20:55:39 -07:00
indexzero
442d2b4233 [api] Allow for secure to be simply a secret string. 2015-09-18 20:52:16 -07:00
indexzero
2de2bc0b66 [api] Allow for "secure" option to be passed to nconf.stores.File to perform content encryption / decryption with crypto.createCipher. 2015-09-18 20:52:16 -07:00
Jarrett Cruger
4c07028e40 Merge pull request #173 from NickHeiner/patch-2
Quick grammar fix
2015-09-17 18:49:48 -07:00
Jarrett Cruger
75cea11f62 Merge pull request #163 from pgilad/patch-1
Add license attribute
2015-09-17 18:47:11 -07:00
Jarrett Cruger
394286cd16 Merge pull request #172 from Oza94/fix-child-process-tests
fix random fails on tests that use child process
2015-09-17 18:46:57 -07:00
Jarrett Cruger
54f2287dd8 Merge pull request #177 from olalonde/master
env({lowerCase:true}) option to make it possible to get() keys in lower case
2015-09-17 18:46:27 -07:00
Jarrett Cruger
38cade0fc2 Merge pull request #167 from josephpage/patch-1
Add tests for node 0.12 and io.js
2015-08-19 23:13:21 -04:00
Jarrett Cruger
32aabcab69 Merge pull request #171 from ChristianMurphy/update-async
Update Async.js
2015-08-19 12:31:23 -04:00
Jarrett Cruger
8332f5a343 Merge pull request #183 from ChristianMurphy/filter-undefined
filter out undefined values
2015-08-19 12:30:27 -04:00
Christian Murphy
5d95f13eb0 filter out undefined values 2015-08-19 09:16:16 -07:00
Joseph Page
7d6be3265b [travis] fix yaml syntax (supposed to solve nvm bugs #182) 2015-08-19 17:52:09 +02:00
Joseph Page
abeeca0d5f [travis] fix npm bugs for node 0.8 (recommended way) 2015-08-19 17:47:01 +02:00
Joseph Page
d252288dae Merge commit '80195744af4929731ff1c87e9b29e37a2c48e464' into patch-1 2015-08-19 17:45:38 +02:00
Christian Murphy
be0ee00b2a Merge branch 'master' of https://github.com/indexzero/nconf into update-async 2015-08-19 08:03:38 -07:00
Christian Murphy
59056fe364 Update Async and ini 2015-08-19 07:58:50 -07:00
Joseph Page
a2b812f704 Add travis tests for iojs 2015-08-13 20:45:57 +02:00
Joseph Page
32d560c95d Add tests for node 0.12 2015-08-13 20:45:57 +02:00
Christian Murphy
80195744af Merge branch 'master' of https://github.com/indexzero/nconf into update-travis 2015-08-04 11:51:26 -07:00
indexzero
c2b8b97778 [dist] Version bump. 0.7.2 2015-08-04 10:31:48 -07:00
Remy Sharp
3c11ef50e5 fix: env.match test
The previous test was expecting the .match value to be a function rather than a regexp which is what the README shows. So I've fixed the code to match against a real regexp, and test if the stringified version of the regexp function is [object RegExp].

I've also updated the tests to prime the process.env with values that are specifically tested for to ensure it's correctly loading the env values.

Fixex indexzero/nconf#178
2015-08-04 10:30:33 -07:00
Olivier Lalonde
8a21ef36d5 env({lowerCase:true}) option to make it possible to get() keys in lower case 2015-08-04 18:56:43 +08:00
indexzero
372521b124 [doc] Add the badges!. 2015-07-29 17:16:12 -07:00
Jarrett Cruger
8afdf63497 Merge pull request #168 from ChristianMurphy/replace-optimist-with-yargs
Replace optimist with yargs
2015-07-12 19:34:18 -04:00
Nick Heiner
89dff39d55 Quick grammar fix 2015-07-09 14:07:35 -04:00
Pierre Beaujeu
339e59afd5 fix random fails on tests that use child process
Listen to 'close' event rather than 'exit' event which can be fired before
stdio is closed.
2015-07-09 17:33:52 +02:00
Christian Murphy
a65e1a3317 update async 2015-07-07 16:01:08 -07:00
Christian Murphy
a82b53941d update badge and use container build 2015-07-07 13:36:21 -07:00
Christian Murphy
80ec01b91d replace optimist with yargs 2015-07-07 13:06:41 -07:00
Gilad Peleg
e5b33ceb05 Add license attribute
https://docs.npmjs.com/files/package.json#license
http://npm1k.org/
2015-05-19 12:56:17 +03:00
Jarrett Cruger
d335b5a0f5 Merge pull request #141 from NickHeiner/patch-1
Grammar nit
2015-01-20 14:23:27 -05:00
Nick Heiner
6d86950914 Grammar nit 2015-01-20 13:41:46 -05:00
Jarrett Cruger
dc6aed2050 [dist] Version bump. 0.7.1 2014-11-26 12:52:01 -05:00
Jarrett Cruger
87a3b82418 [fix] we shouldnt be reversing here fixes #127 2014-11-26 12:51:33 -05:00
Jarrett Cruger
6271cdb35d Revert "fixing the tests"
This reverts commit f69e43a423.
2014-11-26 12:49:50 -05:00
indexzero
f0d5b6eb30 [dist] Fix travis. 2014-11-26 01:34:28 -05:00
indexzero
a2a132181a [dist] Version bump. 0.7.0 2014-11-26 01:32:16 -05:00
indexzero
352f07559a [dist] "Real" CHANGELOG.md again. 2014-11-26 01:32:00 -05:00
indexzero
af0e9fb7e7 [dist fix] Cleanup some whitespace. 2014-11-26 01:31:48 -05:00
indexzero
09342555ba [fix] Fixed regression introduced by #98. 2014-11-26 01:28:31 -05:00
indexzero
8d5fb25701 [fix] Fix my own sloppy coding fixing the sloppy coding from #76. 2014-11-26 01:14:44 -05:00
Charlie Robbins
5502f2cf98 Merge pull request #111 from martinheidegger/patch-1
Adding helpful information in case parsing failed.
2014-11-26 01:08:02 -05:00
Charlie Robbins
2496f59994 Merge pull request #100 from tommystanton/doc_improve
Add some documentation about File and Literal
2014-11-26 01:07:03 -05:00
indexzero
f07bc40d64 [fix] Fix inconsistent style from #98. 2014-11-26 01:06:44 -05:00
Charlie Robbins
d5bd26c0b6 Merge pull request #98 from joaoafrmartins/master
filter process.env by regexp
2014-11-26 01:06:11 -05:00
indexzero
0b8aa903c7 [fix test] Remove leftover console.log() from #79. 2014-11-26 01:05:06 -05:00
Charlie Robbins
c6d8f5d140 Merge pull request #79 from jfromaniello/master
Use optionally a different separator for memorystore
2014-11-26 01:04:35 -05:00
indexzero
f771500266 [dist] Semantic cleanup from sloppy coding in #76. 2014-11-26 01:02:59 -05:00
indexzero
ffce2cbec1 [dist] Update package.json versions. 2014-11-26 01:02:42 -05:00
Charlie Robbins
a3404b4062 Merge pull request #76 from jmonster/usage
Resolves #64, usage and help
2014-11-26 00:59:36 -05:00
Charlie Robbins
7b01b46313 Merge pull request #117 from MitchellMcKenna/master
Update Readme to note additional nconf.file() calls require using a custom key
2014-11-11 03:12:44 -05:00
Charlie Robbins
51a4fea561 Merge pull request #99 from meritt/patch-1
Delete CHANGELOG.md
2014-09-24 23:00:38 -04:00
Charlie Robbins
ddd4b616ee Merge pull request #102 from gabegorelick/tilde-versions
Use ~ for dependencies
2014-09-24 23:00:23 -04:00
Charlie Robbins
1602a9e1a3 Merge pull request #116 from Blooie/master
fixing the tests
2014-09-24 23:00:07 -04:00
Mitchell McKenna
6301d7d9c6 Update Readme; multiple file() needs custom key
- Update the Readme with notes that when using multiple config files,
  the user must use a custom key as the first parameter in additional
  nconf.file() calls in order for config heirarchy/inheritance to work
  properly.

Fixes #97, Fixes #109, Fixes #110
2014-06-17 17:56:42 -07:00
Chris Manson
f69e43a423 fixing the tests 2014-05-27 17:43:24 +01:00
Martin Heidegger
c8b6c98c7a Adding helpful information in case parsing failed.
I stumbled over 2 slight problems of broken configuration files:

1) It said that a error in my JSON file existed (even though it was a yaml file, parsed by libyaml)
2) It didn't tell me which error occured.

both should be fixed with this PR
2014-03-09 21:40:10 +09:00
Christopher Jeffrey
8105c761ad [fix] only reverse keys for "get" action to be safe. 2014-02-12 12:32:34 -06:00
Jarrett Cruger
999c6fbc6e Merge pull request #104 from flatiron/precedence_fix
[fix] have latter stores precede the former stores again.
2014-02-12 13:33:29 -05:00
Christopher Jeffrey
2241a36789 [fix] have latter stores precede the former stores again. 2014-02-12 12:26:38 -06:00
Jarrett Cruger
1bd1561cdd Merge pull request #103 from flatiron/precedence_fix
[fix] have latter stores precede the former stores.
2014-02-12 13:16:58 -05:00
Christopher Jeffrey
0bb89ee2b4 [fix] have latter stores precede the former stores. 2014-02-11 12:40:41 -06:00
Gabe Gorelick
43505a53ae Use ~ for dependencies 2014-02-05 10:42:15 -05:00
Jarrett Cruger
05d73de3d0 [fix] No need to test 0.6 anymore 2014-01-27 15:52:42 -05:00
Tommy Stanton
79b9b84300 [doc] Add a Literal example to add() 2014-01-16 14:15:35 -08:00
Tommy Stanton
3a7b788e35 [doc] The store for File is empty if non-existent 2014-01-16 14:05:05 -08:00
Alexey Simonenko
9891814b27 Delete CHANGELOG.md
Changelog not updated for more than 2 years, it is better to remove it so as not to mislead.
2014-01-12 21:23:15 +03:00
joaoafrmartins
120f5f0a4b added documentation 2014-01-10 00:26:07 +00:00
joaoafrmartins
681fd2f6b4 added regexp filtering to nconf env store 2014-01-10 00:17:52 +00:00
Jarrett Cruger
022b9bc507 [dist] Version bump. 0.6.9 2013-12-01 22:23:41 -08:00
Jarrett Cruger
9aa33b565a [dist] bump optimist version, fixes #89 2013-12-01 22:22:24 -08:00
Jarrett Cruger
92311c81c3 [rm] kill pkginfo 2013-12-01 22:21:21 -08:00
Jarrett Cruger
c713936e8d [dist] bump async 2013-12-01 22:20:34 -08:00
Jarrett Cruger
cd81efac7e [dist] Version bump. 0.6.8 2013-10-29 14:50:10 -04:00
Jarrett Cruger
5f148d5aa5 Merge pull request #90 from midknight41/master
added support for BOM in load() and loadSync(), fixed travis build too.
2013-10-26 17:05:16 -07:00
midknight41
6c1eb5e917 fixed white spacing and added (embarrassing absent) variable declarations 2013-10-26 20:40:12 +01:00
midknight41
ccd609c1c3 updated version of vows as v0.6 didn't work with node 0.10 2013-10-10 21:27:25 +01:00
midknight41
5546469061 updated .travis.yml as travis doesn't support node 0.4 or 0.9 2013-10-04 08:10:53 +01:00
midknight41
6641ed234a made bom tests more meaningful 2013-10-03 15:58:13 +01:00
midknight41
2ce8aea8fc made bom tests more meaningful 2013-10-03 15:53:02 +01:00
midknight41
f7733c1719 included bom test fixtures 2013-10-03 14:37:39 +01:00
midknight41
24f77a0edd included bom test fixtures 2013-10-03 14:37:07 +01:00
midknight41
29f1ca281b added support for BOM in load() and loadSync() 2013-10-03 09:17:36 +01:00
Charlie Robbins
62589145f3 Merge pull request #82 from mfloryan/fileinfo
Fileinfo
2013-06-21 23:14:20 -07:00
Marcin Floryan
ada15db9e3 Test that invalid file name is indicated 2013-04-29 21:36:26 +01:00
Marcin Floryan
0135d95a06 Additional error information when JSON config file cannot be read 2013-04-29 16:34:48 +01:00
José F. Romaniello
039057c730 allow different separator for memorystore 2013-04-05 15:07:33 -03:00
Johnny Domino
b73b0e1a37 attach help and showHelp arguments to the argv store 2013-02-23 12:33:23 -05:00
Johnny Domino
4894c8fcf7 resolves #64 passing usage string to optimist 2013-02-23 12:32:42 -05:00
Charlie Robbins
818526ca62 Merge pull request #63 from SchoonologyRRL/patch-1
Updated Memory.merge to handle null values
2012-12-20 22:56:54 -08:00
Michael Schoonmaker
5d2ebfbe9f Added test to confirm merging an Object and null behaves as expected. 2012-12-20 19:02:36 -08:00
indexzero
d77c55d4ba [dist] Version bump. 0.6.7 2012-12-20 18:13:50 -05:00
Michael Hart
bb57c497d3 Prefer this fix for #65 to 6045618 2012-12-20 18:12:42 -05:00
indexzero
aec2b4eb46 [dist] Version bump. 0.6.6 2012-12-20 18:07:16 -05:00
Charlie Robbins
e26f1af48c Merge pull request #67 from flatiron/gh-65
Fix for #65
2012-12-20 15:06:38 -08:00
indexzero
60456186d7 [fix] Fix for #65 2012-12-20 18:03:37 -05:00
indexzero
0d795ecf81 [test] Better tests to show #65 2012-12-20 14:08:36 -05:00
indexzero
f19f0b6c39 [test] Added failing test to illustrate #65 2012-12-20 14:01:04 -05:00
Maciej Małecki
bcbaf3a133 [dist] Bump version to 0.6.5 2012-11-02 18:17:08 +01:00
Maciej Małecki
8b65e195eb [test] Test on newer node versions 2012-11-02 18:09:17 +01:00
Michael Schoonmaker
ed41c51850 Updated Memory.merge to handle null values
Previously, if the Memory store was merged with an object containing a null value, the following Error occurred:

TypeError: Object.keys called on non-object
    at Function.keys (native)
    at Memory.merge (/.../node_modules/nconf/lib/nconf/stores/memory.js:199:17)
    at Memory.merge (/.../node_modules/nconf/lib/nconf/stores/memory.js:200:17)
    at Array.every (native)
    at Memory.merge (/.../node_modules/nconf/lib/nconf/stores/memory.js:199:29)
    at common.merge (/.../node_modules/nconf/lib/nconf/common.js:99:13)
    at Array.forEach (native)
    at common.merge (/.../node_modules/nconf/lib/nconf/common.js:98:22)
    at Array.forEach (native)
    at Object.common.merge (/.../node_modules/nconf/lib/nconf/common.js:97:8)

This commit prevents that.
2012-09-27 11:26:56 -07:00
Pavan Kumar Sunkara
2ba437807a Merge pull request #62 from tellnes/loadFrom
Fix ini files for memory loadFrom option
2012-09-16 19:32:47 -07:00
Christian Tellnes
8e987b8d3d make it possible to use other formats than json in common.loadFiles and common.loadFilesSync 2012-09-16 17:45:00 +02:00
Bradley Meck
f9b24f1aa6 Merge pull request #61 from flatiron/merge-null
[fix] null values should merge properly instead of throwing errors
2012-09-08 18:11:54 -07:00
Bradley Meck
da39d3cac3 [fix] null values should merge properly instead of throwing errors 2012-09-08 20:10:58 -05:00
Bradley Meck
f21557e783 Merge pull request #60 from flatiron/root-actions
[fix] #59 root get/set should work via null/undefined as key
2012-09-07 12:10:56 -07:00
Bradley Meck
7421836387 [fix] heirarchy fixture file path wrong in tests 2012-09-07 09:40:15 -05:00
Bradley Meck
683f78918c [fix] #59 root get/set should work via null/undefined as key 2012-09-07 09:29:30 -05:00
Joshua Holbrook
ec9a13e901 Merge pull request #54 from eethann/master
Add docs for optimist options hash
2012-08-06 23:24:22 -07:00
Ethan Winn
0f092ab5a4 Added docs for options hash to optimist.
I had to dig a bit to figure out how to get options working on argv,
thought I'd save others the time.
2012-08-07 01:52:29 -04:00
76 changed files with 3370 additions and 3845 deletions

33
.circleci/config.yml Normal file
View file

@ -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

8
.gitignore vendored
View file

@ -1,8 +1,4 @@
.DS_Store
config.json
test/fixtures/*.json
!test/fixtures/complete.json
!test/fixtures/malformed.json
node_modules/
node_modules/*
npm-debug.log
node_modules
npm-debug.log

1
.npmrc Normal file
View file

@ -0,0 +1 @@
package-lock=false

View file

@ -1,11 +0,0 @@
language: node_js
node_js:
- 0.4
- 0.6
- 0.7
notifications:
email:
- travis@nodejitsu.com
irc: "irc.freenode.org#nodejitsu"

View file

@ -1,9 +1,12 @@
# CHANGELOG
v2.0.0 / Tue, 2 Jun 2020
========================
### Version 0.5.0
Completely redesigned and re-written with zero dependencies among other things.
* `nconf.stores.*` is now `nconf.*`
* `nconf.stores` now represents the set of nconf.* Store instances on the nconf object.
* Added `nconf.argv()`, `nconf.env()`, `nconf.file()`, `nconf.overrides()`, `nconf.defaults()`.
* `nconf.system` no longer exists. The `nconf.System` store has been broken into `nconf.Argv`, `nconf.Env` and `nconf.Literal`
* Fixed bugs in hierarchical configuration loading.
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

View file

@ -1,4 +1,4 @@
Copyright (c) 2011 Nodejitsu Inc.
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
@ -16,4 +16,4 @@ 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.
THE SOFTWARE.

266
README.md
View file

@ -1,30 +1,32 @@
# nconf [![Build Status](https://secure.travis-ci.org/flatiron/nconf.png)](http://travis-ci.org/flatiron/nconf)
# nconf-lite
Hierarchical node.js configuration with files, environment variables, command-line arguments, and atomic object merging.
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.
It is a hierarchical node.js configuration with files, environment variables, and atomic object merging.
Compared to nconf running at 952KB with over 220 files *installed*, nconf-lite is clocking at measly 42KB with only 11 files of easily reviewable code and a ton more unit test, testing almost every micro functionality.
## Example
Using nconf is easy; it is designed to be a simple key-value store with support for both local and remote storage. Keys are namespaced and delimited by `:`. Lets dive right into sample usage:
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:
``` js
var fs = require('fs'),
nconf = require('nconf');
import Nconf from 'nconf-lite'
const nconf = new Nconf()
//
// Setup nconf to use (in-order):
// 1. Command-line arguments
// Setup nconf to use (in-order):
// 2. Environment variables
// 3. A file located at 'path/to/config.json'
//
nconf.argv()
.env()
.file({ file: 'path/to/config.json' });
nconf.env()
.file({ file: 'path/to/config.json' });
//
// Set a few variables on `nconf`.
//
nconf.set('database:host', '127.0.0.1');
nconf.set('database:port', 5984);
//
// Get the entire database object from nconf. This will output
// { host: '127.0.0.1', port: 5984 }
@ -32,36 +34,30 @@ Using nconf is easy; it is designed to be a simple key-value store with support
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 --foo bar
$ NODE_ENV=production sample.js
```
The output will be:
```
foo: bar
NODE_ENV: production
database: { host: '127.0.0.1', port: 5984 }
```
## Hierarchical configuration
Configuration management can get complicated very quickly for even trivial applications running in production. `nconf` addresses this problem by enabling you to setup a hierarchy for different sources of configuration with no defaults. **The order in which you attach these configuration sources determines their priority in the hierarchy.** Lets take a look at the options available to you
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
1. **nconf.argv(options)** Loads `process.argv` using optimist. If `options` is supplied it is passed along to optimist.
2. **nconf.env(options)** Loads `process.env` into the hierarchy.
3. **nconf.file(options)** Loads the configuration data at options.file into the hierarchy.
4. **nconf.defaults(options)** Loads the data in options.store into the hierarchy.
@ -70,21 +66,21 @@ Configuration management can get complicated very quickly for even trivial appli
A sane default for this could be:
``` js
var nconf = require('nconf');
import Nconf from 'nconf-lite'
const nconf = new Nconf()
//
// 1. any overrides
//
nconf.overrides({
'always': 'be this value'
});
//
// 2. `process.env`
// 3. `process.argv`
//
nconf.env().argv();
nconf.env();
//
// 4. Values in `config.json`
//
@ -92,19 +88,10 @@ A sane default for this could be:
//
// 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');
//
// Or searching from a base directory.
// Note: `name` is optional.
//
nconf.file(name, {
file: 'config.json',
dir: 'search/from/here',
search: true
});
//
// 5. Any default values
//
@ -115,36 +102,55 @@ A sane default for this could be:
## API Documentation
The top-level of `nconf` is an instance of the `nconf.Provider` abstracts this all for you into a simple API.
### nconf.add(name, options)
Adds a new store with the specified `name` and `options`. If `options.type` is not set, then `name` will be used instead:
### 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
nconf.add('user', { type: 'file', file: '/path/to/userconf.json' });
nconf.add('global', { type: 'file', file: '/path/to/globalconf.json' });
//
// Get one of 'NODEJS_PORT' and 'PORT' as a return value
//
let port = nconf.any('NODEJS_PORT', 'PORT');
```
### nconf.use(name, options)
Similar to `nconf.add`, except that it can replace an existing store if new options are provided
### nconf.use(name)
Fetch a specific store with the specified name.
``` js
//
// Load a file store onto nconf with the specified settings
//
nconf.use('file', { file: '/path/to/some/config-file.json' });
nconf.file('custom', '/path/to/config.json');
//
// Replace the file store with new settings
// Grab the instance and set it to be readonly
//
nconf.use('file', { file: 'path/to/a-new/config-file.json' });
nconf.use('custom').readOnly = true
```
### nconf.remove(name)
Removes the store with the specified `name.` The configuration stored at that level will no longer be used for lookup(s).
### nconf.required(keys)
Declares a set of string keys to be mandatory, and throw an error if any are missing.
``` js
nconf.remove('file');
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
@ -152,44 +158,88 @@ Removes the store with the specified `name.` The configuration stored at that le
### 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.
``` js
nconf.use('memory');
```
### Argv
Responsible for loading the values parsed from `process.argv` by `optimist` into the configuration hierarchy.
``` js
//
// Can optionally also be an object literal to pass to `optimist`.
//
nconf.argv(options);
nconf.use('memory');
```
### 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']);
nconf.env(['only', 'load', 'these', 'values', 'from', 'process.env']);
//
// Can also specify a separator for nested keys (instead of the default ':')
//
nconf.env('__');
nconf.env({ separator: '__' });
// Get the value of the env variable 'database__host'
var dbHost = nconf.get('database:host');
let dbHost = nconf.get('database:host');
//
// Or use both options
// 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: '__',
whitelist: ['database__host', 'only', 'load', 'these', 'values']
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;
}
});
var dbHost = nconf.get('database:host');
let dbHost = nconf.get('database:host');
```
### Literal
@ -202,56 +252,59 @@ Loads a given object literal into the configuration hierarchy. Both `nconf.defau
```
### File
Based on the Memory store, but provides additional methods `.save()` and `.load()` which allow you to read your configuration to and from file. As with the Memory store, all method calls are synchronous with the exception of `.save()` and `.load()` which take callback functions. It is important to note that setting keys in the File engine will not be persisted to disk until a call to `.save()` is made.
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()`.
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
There is a separate Redis-based store available through [nconf-redis][0]. To install and use this store simply:
If the file does not exist at the provided path, the store will simply be empty.
``` bash
$ npm install nconf
$ npm install nconf-redis
```
#### Encrypting file contents
Once installing both `nconf` and `nconf-redis`, you must require both modules to use the Redis store:
Encryption and decrypting file contents using the `secure` option:
``` js
var nconf = require('nconf');
//
// Requiring `nconf-redis` will extend the `nconf`
// module.
//
require('nconf-redis');
nconf.use('redis', { host: 'localhost', port: 6379, ttl: 60 * 60 * 1000 });
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
### Installing npm (node package manager)
```
curl http://npmjs.org/install.sh | sh
```
### Installing nconf
```
[sudo] npm install nconf
```
## 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:
```
open docs/nconf.html
``` bash
npm install nconf-lite --save
```
## Run Tests
@ -261,7 +314,8 @@ Tests are written in vows and give complete coverage of all APIs and storage eng
$ npm test
```
#### Author: [Charlie Robbins](http://nodejitsu.com)
#### Original author: [Charlie Robbins](http://nodejitsu.com)
#### Rewriter of all that garbage: TheThing
#### License: MIT
[0]: http://github.com/indexzero/nconf-redis
[0]: http://github.com/nfp-projects/nconf-lite

View file

@ -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 */

View file

@ -1,20 +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 &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="nconf/common.html"> nconf/common.html </a> <a class="source" href="nconf/formats.html"> nconf/formats.html </a> <a class="source" href="nconf/provider.html"> nconf/provider.html </a> <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/system.html"> nconf/stores/system.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">&#182;</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="kd">var</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;fs&#39;</span><span class="p">),</span>
<span class="nx">async</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;async&#39;</span><span class="p">),</span>
<span class="nx">common</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;./nconf/common&#39;</span><span class="p">),</span>
<span class="nx">Provider</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;./nconf/provider&#39;</span><span class="p">).</span><span class="nx">Provider</span><span class="p">,</span>
<span class="nx">nconf</span> <span class="o">=</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Provider</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">&#182;</a> </div> <p>Expose the version from the package.json using <code>pkginfo</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">require</span><span class="p">(</span><span class="s1">&#39;pkginfo&#39;</span><span class="p">)(</span><span class="nx">module</span><span class="p">,</span> <span class="s1">&#39;version&#39;</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">&#182;</a> </div> <p>Expose the various components included with nconf</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="nx">common</span><span class="p">.</span><span class="nx">key</span><span class="p">;</span>
<span class="nx">nconf</span><span class="p">.</span><span class="nx">path</span> <span class="o">=</span> <span class="nx">common</span><span class="p">.</span><span class="nx">path</span><span class="p">;</span>
<span class="nx">nconf</span><span class="p">.</span><span class="nx">loadFiles</span> <span class="o">=</span> <span class="nx">common</span><span class="p">.</span><span class="nx">loadFiles</span><span class="p">;</span>
<span class="nx">nconf</span><span class="p">.</span><span class="nx">loadFilesSync</span> <span class="o">=</span> <span class="nx">common</span><span class="p">.</span><span class="nx">loadFilesSync</span><span class="p">;</span>
<span class="nx">nconf</span><span class="p">.</span><span class="nx">formats</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;./nconf/formats&#39;</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">&#39;./nconf/stores&#39;</span><span class="p">);</span>
<span class="nx">nconf</span><span class="p">.</span><span class="nx">Provider</span> <span class="o">=</span> <span class="nx">Provider</span><span class="p">;</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View file

@ -1,85 +0,0 @@
<!DOCTYPE html> <html> <head> <title>common.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 &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="..//nconf/common.html"> nconf/common.html </a> <a class="source" href="..//nconf/formats.html"> nconf/formats.html </a> <a class="source" href="..//nconf/provider.html"> nconf/provider.html </a> <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/system.html"> nconf/stores/system.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> common.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">&#182;</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
<span class="cm"> * utils.js: Utility functions 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="kd">var</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;fs&#39;</span><span class="p">),</span>
<span class="nx">async</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;async&#39;</span><span class="p">),</span>
<span class="nx">formats</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;./formats&#39;</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">&#39;./stores/Memory&#39;</span><span class="p">).</span><span class="nx">Memory</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">common</span> <span class="o">=</span> <span class="nx">exports</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">&#182;</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">common</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">&#39;:&#39;</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">&#182;</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">common</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">&#39;:&#39;</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">&#182;</a> </div> <h3>function loadFiles (files, callback)</h3>
<h4>@files {Object|Array} List of files (or settings object) to load.</h4>
<h4>@callback {function} Continuation to respond to when complete.</h4>
<p>Loads all the data in the specified <code>files</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">common</span><span class="p">.</span><span class="nx">loadFiles</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">files</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">files</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="p">{});</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">options</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">files</span><span class="p">)</span> <span class="o">?</span> <span class="p">{</span> <span class="nx">files</span><span class="o">:</span> <span class="nx">files</span> <span class="p">}</span> <span class="o">:</span> <span class="nx">files</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">&#182;</a> </div> <p>Set the default JSON format if not already
specified</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</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">formats</span><span class="p">.</span><span class="nx">json</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">parseFile</span> <span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</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="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">return</span> <span class="o">!</span><span class="nx">err</span>
<span class="o">?</span> <span class="nx">next</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">options</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="o">:</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="p">}</span>
<span class="nx">async</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">files</span><span class="p">,</span> <span class="nx">parseFile</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">objs</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">common</span><span class="p">.</span><span class="nx">merge</span><span class="p">(</span><span class="nx">objs</span><span class="p">));</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">&#182;</a> </div> <h3>function loadFilesSync (files)</h3>
<h4>@files {Object|Array} List of files (or settings object) to load.</h4>
<p>Loads all the data in the specified <code>files</code> synchronously.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">common</span><span class="p">.</span><span class="nx">loadFilesSync</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">files</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">files</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</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">&#182;</a> </div> <p>Set the default JSON format if not already
specified</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">options</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">files</span><span class="p">)</span> <span class="o">?</span> <span class="p">{</span> <span class="nx">files</span><span class="o">:</span> <span class="nx">files</span> <span class="p">}</span> <span class="o">:</span> <span class="nx">files</span><span class="p">;</span>
<span class="nx">options</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">formats</span><span class="p">.</span><span class="nx">json</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">common</span><span class="p">.</span><span class="nx">merge</span><span class="p">(</span><span class="nx">files</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">options</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">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="s1">&#39;utf8&#39;</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">&#182;</a> </div> <h3>function merge (objs)</h3>
<h4>@objs {Array} Array of object literals to merge</h4>
<p>Merges the specified <code>objs</code> using a temporary instance
of <code>stores.Memory</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">common</span><span class="p">.</span><span class="nx">merge</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">objs</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Memory</span><span class="p">();</span>
<span class="nx">objs</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">obj</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">obj</span><span class="p">).</span><span class="nx">forEach</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="p">{</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">merge</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]);</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">store</span><span class="p">.</span><span class="nx">store</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">&#182;</a> </div> <h3>function capitalize (str)</h3>
<h4>@str {string} String to capitalize</h4>
<p>Capitalizes the specified <code>str</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">common</span><span class="p">.</span><span class="nx">capitalize</span> <span class="o">=</span> <span class="kd">function</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">&amp;&amp;</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>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View file

@ -1,22 +0,0 @@
<!DOCTYPE html> <html> <head> <title>formats.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 &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="..//nconf/common.html"> nconf/common.html </a> <a class="source" href="..//nconf/formats.html"> nconf/formats.html </a> <a class="source" href="..//nconf/provider.html"> nconf/provider.html </a> <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/system.html"> nconf/stores/system.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> formats.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">&#182;</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
<span class="cm"> * formats.js: Default formats supported by nconf</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">ini</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;ini&#39;</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">formats</span> <span class="o">=</span> <span class="nx">exports</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">&#182;</a> </div> <h3>@json</h3>
<p>Standard JSON format which pretty prints <code>.stringify()</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">formats</span><span class="p">.</span><span class="nx">json</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">stringify</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">obj</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="p">},</span>
<span class="nx">parse</span><span class="o">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</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">&#182;</a> </div> <h3>@ini</h3>
<p>Standard INI format supplied from the <code>ini</code> module
http://en.wikipedia.org/wiki/INI_file</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">formats</span><span class="p">.</span><span class="nx">ini</span> <span class="o">=</span> <span class="nx">ini</span><span class="p">;</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View file

@ -1,378 +0,0 @@
<!DOCTYPE html> <html> <head> <title>provider.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 &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="..//nconf/common.html"> nconf/common.html </a> <a class="source" href="..//nconf/formats.html"> nconf/formats.html </a> <a class="source" href="..//nconf/provider.html"> nconf/provider.html </a> <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/system.html"> nconf/stores/system.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> provider.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">&#182;</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
<span class="cm"> * provider.js: Abstraction providing an interface into pluggable configuration storage.</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">&#39;async&#39;</span><span class="p">),</span>
<span class="nx">common</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;./common&#39;</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">&#39;./stores&#39;</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">&#182;</a> </div> <h3>function Provider (options)</h3>
<h4>@options {Object} Options for this instance.</h4>
<p>Constructor function for the Provider object responsible
for exposing the pluggable storage features of <code>nconf</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">Provider</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Provider</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="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-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>Setup default options for working with <code>stores</code>,
<code>overrides</code>, <code>process.env</code> and <code>process.argv</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <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">_overrides</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">overrides</span> <span class="o">||</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_argv</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">argv</span> <span class="o">||</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_env</span><span class="err"> </span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">env</span> <span class="o">||</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_reserved</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">Provider</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_stores</span> <span class="o">=</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">&#182;</a> </div> <p>Add the default <code>system</code> store for working with
<code>overrides</code>, <code>process.env</code>, <code>process.argv</code> and
a simple in-memory objects.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="s1">&#39;system&#39;</span><span class="p">,</span> <span class="nx">options</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">options</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">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">store</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">name</span> <span class="o">||</span> <span class="nx">options</span><span class="p">.</span><span class="nx">store</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="nx">store</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">stores</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">stores</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">store</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">self</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">store</span><span class="p">.</span><span class="nx">name</span> <span class="o">||</span> <span class="nx">store</span><span class="p">.</span><span class="nx">type</span><span class="p">,</span> <span class="nx">store</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">&#182;</a> </div> <h3>function use (name, options)</h3>
<h4>@type {string} Type of the nconf store to use.</h4>
<h4>@options {Object} Options for the store instance.</h4>
<p>Adds (or replaces) a new store with the specified <code>name</code>
and <code>options</code>. If <code>options.type</code> is not set, then <code>name</code>
will be used instead:</p>
<p>provider.use('file');
provider.use('file', { type: 'file', filename: '/path/to/userconf' })</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Provider</span><span class="p">.</span><span class="nx">prototype</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">name</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="nx">name</span> <span class="o">===</span> <span class="s1">&#39;system&#39;</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_reserved</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">!==</span> <span class="o">-</span><span class="mi">1</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">&#39;Cannot use reserved name: &#39;</span> <span class="o">+</span> <span class="nx">name</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="kd">var</span> <span class="nx">type</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">type</span> <span class="o">||</span> <span class="nx">name</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">sameOptions</span> <span class="p">(</span><span class="nx">store</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">options</span><span class="p">).</span><span class="nx">every</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="p">{</span>
<span class="k">return</span> <span class="nx">options</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">===</span> <span class="nx">store</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="k">this</span><span class="p">[</span><span class="nx">name</span><span class="p">],</span>
<span class="nx">update</span> <span class="o">=</span> <span class="nx">store</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">sameOptions</span><span class="p">(</span><span class="nx">store</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">store</span> <span class="o">||</span> <span class="nx">update</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">update</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">remove</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">name</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">this</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">&#182;</a> </div> <h3>function add (name, options)</h3>
<h4>@name {string} Name of the store to add to this instance</h4>
<h4>@options {Object} Options for the store to create</h4>
<p>Adds a new store with the specified <code>name</code> and <code>options</code>. If <code>options.type</code>
is not set, then <code>name</code> will be used instead:</p>
<p>provider.add('memory');
provider.add('userconf', { type: 'file', filename: '/path/to/userconf' })</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Provider</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">add</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">name</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="k">this</span><span class="p">.</span><span class="nx">_reserved</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">!==</span> <span class="o">-</span><span class="mi">1</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">&#39;Cannot use reserved name: &#39;</span> <span class="o">+</span> <span class="nx">name</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="kd">var</span> <span class="nx">type</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">type</span> <span class="o">||</span> <span class="nx">name</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">stores</span><span class="p">).</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">common</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="o">===</span> <span class="o">-</span><span class="mi">1</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">&#39;Cannot add store with unknown type: &#39;</span> <span class="o">+</span> <span class="nx">type</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="k">this</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="k">this</span><span class="p">.</span><span class="nx">_stores</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">[</span><span class="nx">name</span><span class="p">].</span><span class="nx">loadSync</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">[</span><span class="nx">name</span><span class="p">].</span><span class="nx">loadSync</span><span class="p">();</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">&#182;</a> </div> <h3>function remove (name)</h3>
<h4>@name {string} Name of the store to remove from this instance</h4>
<p>Removes a store with the specified <code>name</code> from this instance. Users
are allowed to pass in a type argument (e.g. <code>memory</code>) as name if
this was used in the call to <code>.add()</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Provider</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">remove</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_reserved</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">!==</span> <span class="o">-</span><span class="mi">1</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">&#39;Cannot use reserved name: &#39;</span> <span class="o">+</span> <span class="nx">name</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">[</span><span class="nx">name</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">&#39;Cannot remove store that does not exist: &#39;</span> <span class="o">+</span> <span class="nx">name</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">delete</span> <span class="k">this</span><span class="p">[</span><span class="nx">name</span><span class="p">];</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_stores</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_stores</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">name</span><span class="p">),</span> <span class="mi">1</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">&#182;</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">Provider</span><span class="p">.</span><span class="nx">prototype</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">common</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> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</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">Provider</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></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>If there is no callback we can short-circuit into the default
logic for traversing stores.</p> </td> <td class="code"> <div class="highlight"><pre> <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="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_execute</span><span class="p">(</span><span class="s1">&#39;get&#39;</span><span class="p">,</span> <span class="mi">1</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-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>Otherwise the asynchronous, hierarchical <code>get</code> is
slightly more complicated because we do not need to traverse
the entire set of stores, but up until there is a defined value.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">current</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
<span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span>
<span class="nx">response</span><span class="p">;</span>
<span class="nx">async</span><span class="p">.</span><span class="nx">whilst</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">typeof</span> <span class="nx">response</span> <span class="o">===</span> <span class="s1">&#39;undefined&#39;</span> <span class="o">&amp;&amp;</span> <span class="nx">current</span> <span class="o">&lt;</span> <span class="nx">self</span><span class="p">.</span><span class="nx">_stores</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="p">},</span> <span class="kd">function</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">store</span> <span class="o">=</span> <span class="nx">self</span><span class="p">[</span><span class="nx">self</span><span class="p">.</span><span class="nx">_stores</span><span class="p">[</span><span class="nx">current</span><span class="p">]];</span>
<span class="nx">current</span><span class="o">++</span><span class="p">;</span>
<span class="k">if</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">length</span> <span class="o">&gt;=</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</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="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">response</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">response</span> <span class="o">=</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">next</span><span class="p">();</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">response</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">&#182;</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">Provider</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="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_execute</span><span class="p">(</span><span class="s1">&#39;set&#39;</span><span class="p">,</span> <span class="mi">2</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-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</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">Provider</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="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_execute</span><span class="p">(</span><span class="s1">&#39;reset&#39;</span><span class="p">,</span> <span class="mi">0</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-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</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">Provider</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="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_execute</span><span class="p">(</span><span class="s1">&#39;clear&#39;</span><span class="p">,</span> <span class="mi">1</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-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <h3>function merge ([key,] value [, callback])</h3>
<h4>@key {string} Key to merge the value into</h4>
<h4>@value {literal|Object} Value to merge into the key</h4>
<h4>@callback {function} <strong>Optional</strong> Continuation to respond to when complete.</h4>
<p>Merges the properties in <code>value</code> into the existing object value at <code>key</code>. </p>
<ol>
<li>If the existing value <code>key</code> is not an Object, it will be completely overwritten.</li>
<li>If <code>key</code> is not supplied, then the <code>value</code> will be merged into the root.</li>
</ol> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Provider</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">merge</span> <span class="o">=</span> <span class="kd">function</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">args</span> <span class="o">=</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">callback</span> <span class="o">=</span> <span class="k">typeof</span> <span class="nx">args</span><span class="p">[</span><span class="nx">args</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="o">===</span> <span class="s1">&#39;function&#39;</span> <span class="o">&amp;&amp;</span> <span class="nx">args</span><span class="p">.</span><span class="nx">pop</span><span class="p">(),</span>
<span class="nx">value</span> <span class="o">=</span> <span class="nx">args</span><span class="p">.</span><span class="nx">pop</span><span class="p">(),</span>
<span class="nx">key</span> <span class="o">=</span> <span class="nx">args</span><span class="p">.</span><span class="nx">pop</span><span class="p">();</span>
<span class="kd">function</span> <span class="nx">mergeProperty</span> <span class="p">(</span><span class="nx">prop</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">self</span><span class="p">.</span><span class="nx">_execute</span><span class="p">(</span><span class="s1">&#39;merge&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">value</span><span class="p">[</span><span class="nx">prop</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="o">!</span><span class="nx">key</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">&#39;object&#39;</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">onError</span><span class="p">(</span><span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">&#39;Cannot merge non-Object into top-level.&#39;</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">async</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</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="nx">mergeProperty</span><span class="p">,</span> <span class="nx">callback</span> <span class="o">||</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="p">})</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_execute</span><span class="p">(</span><span class="s1">&#39;merge&#39;</span><span class="p">,</span> <span class="mi">2</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-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</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">Provider</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="kd">function</span> <span class="nx">loadStoreSync</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">self</span><span class="p">[</span><span class="nx">name</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">store</span><span class="p">.</span><span class="nx">loadSync</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">&#39;nconf store &#39;</span> <span class="o">+</span> <span class="nx">store</span><span class="p">.</span><span class="nx">type</span> <span class="o">+</span> <span class="s1">&#39; has no loadSync() method&#39;</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">store</span><span class="p">.</span><span class="nx">loadSync</span><span class="p">();</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">loadStore</span><span class="p">(</span><span class="nx">name</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">store</span> <span class="o">=</span> <span class="nx">self</span><span class="p">[</span><span class="nx">name</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">store</span><span class="p">.</span><span class="nx">load</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">store</span><span class="p">.</span><span class="nx">loadSync</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="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">&#39;nconf store &#39;</span> <span class="o">+</span> <span class="nx">store</span><span class="p">.</span><span class="nx">type</span> <span class="o">+</span> <span class="s1">&#39; has no load() method&#39;</span><span class="p">));</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">store</span><span class="p">.</span><span class="nx">loadSync</span>
<span class="o">?</span> <span class="nx">next</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">store</span><span class="p">.</span><span class="nx">loadSync</span><span class="p">())</span>
<span class="o">:</span> <span class="nx">store</span><span class="p">.</span><span class="nx">load</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-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>If we don't have a callback and the current
store is capable of loading synchronously
then do so.</p> </td> <td class="code"> <div class="highlight"><pre> <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="k">return</span> <span class="nx">common</span><span class="p">.</span><span class="nx">merge</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_stores</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">loadStoreSync</span><span class="p">));</span>
<span class="p">}</span>
<span class="nx">async</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_stores</span><span class="p">,</span> <span class="nx">loadStore</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">objs</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">common</span><span class="p">.</span><span class="nx">merge</span><span class="p">(</span><span class="nx">objs</span><span class="p">));</span>
<span class="p">});</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">&#182;</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">Provider</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="o">&amp;&amp;</span> <span class="k">typeof</span> <span class="nx">value</span> <span class="o">===</span> <span class="s1">&#39;function&#39;</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="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">saveStoreSync</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">self</span><span class="p">[</span><span class="nx">name</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">store</span><span class="p">.</span><span class="nx">saveSync</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">&#39;nconf store &#39;</span> <span class="o">+</span> <span class="nx">store</span><span class="p">.</span><span class="nx">type</span> <span class="o">+</span> <span class="s1">&#39; has no saveSync() method&#39;</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">store</span><span class="p">.</span><span class="nx">saveSync</span><span class="p">();</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">saveStore</span><span class="p">(</span><span class="nx">name</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">store</span> <span class="o">=</span> <span class="nx">self</span><span class="p">[</span><span class="nx">name</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">store</span><span class="p">.</span><span class="nx">save</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">store</span><span class="p">.</span><span class="nx">saveSync</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="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">&#39;nconf store &#39;</span> <span class="o">+</span> <span class="nx">store</span><span class="p">.</span><span class="nx">type</span> <span class="o">+</span> <span class="s1">&#39; has no save() method&#39;</span><span class="p">));</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">store</span><span class="p">.</span><span class="nx">saveSync</span>
<span class="o">?</span> <span class="nx">next</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">store</span><span class="p">.</span><span class="nx">saveSync</span><span class="p">())</span>
<span class="o">:</span> <span class="nx">store</span><span class="p">.</span><span class="nx">save</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-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>If we don't have a callback and the current
store is capable of saving synchronously
then do so.</p> </td> <td class="code"> <div class="highlight"><pre> <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="k">return</span> <span class="nx">common</span><span class="p">.</span><span class="nx">merge</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_stores</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">saveStoreSync</span><span class="p">));</span>
<span class="p">}</span>
<span class="nx">async</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_stores</span><span class="p">,</span> <span class="nx">saveStore</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">objs</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-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">&#182;</a> </div> <h3>@private function _execute (action, syncLength, [arguments])</h3>
<h4>@action {string} Action to execute on <code>this.store</code>.</h4>
<h4>@syncLength {number} Function length of the sync version.</h4>
<h4>@arguments {Array} Arguments array to apply to the action</h4>
<p>Executes the specified <code>action</code> on all stores for this instance, ensuring a callback supplied
to a synchronous store function is still invoked.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Provider</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">_execute</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">action</span><span class="p">,</span> <span class="nx">syncLength</span> <span class="cm">/* [arguments] */</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">args</span> <span class="o">=</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="mi">2</span><span class="p">),</span>
<span class="nx">callback</span> <span class="o">=</span> <span class="k">typeof</span> <span class="nx">args</span><span class="p">[</span><span class="nx">args</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="o">===</span> <span class="s1">&#39;function&#39;</span> <span class="o">&amp;&amp;</span> <span class="nx">args</span><span class="p">.</span><span class="nx">pop</span><span class="p">(),</span>
<span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span>
<span class="nx">response</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">runAction</span> <span class="p">(</span><span class="nx">name</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">store</span> <span class="o">=</span> <span class="nx">self</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
<span class="k">return</span> <span class="nx">store</span><span class="p">[</span><span class="nx">action</span><span class="p">].</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="nx">syncLength</span>
<span class="o">?</span> <span class="nx">store</span><span class="p">[</span><span class="nx">action</span><span class="p">].</span><span class="nx">apply</span><span class="p">(</span><span class="nx">store</span><span class="p">,</span> <span class="nx">args</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">next</span><span class="p">))</span>
<span class="o">:</span> <span class="nx">next</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="nx">store</span><span class="p">[</span><span class="nx">action</span><span class="p">].</span><span class="nx">apply</span><span class="p">(</span><span class="nx">store</span><span class="p">,</span> <span class="nx">args</span><span class="p">));</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">async</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">self</span><span class="p">.</span><span class="nx">_stores</span><span class="p">,</span> <span class="nx">runAction</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>
<span class="k">this</span><span class="p">.</span><span class="nx">_stores</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">self</span><span class="p">[</span><span class="nx">name</span><span class="p">];</span>
<span class="nx">response</span> <span class="o">=</span> <span class="nx">store</span><span class="p">[</span><span class="nx">action</span><span class="p">].</span><span class="nx">apply</span><span class="p">(</span><span class="nx">store</span><span class="p">,</span> <span class="nx">args</span><span class="p">);</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">response</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">&#182;</a> </div> <h3>@argv {boolean}</h3>
<p>Gets or sets a property representing overrides which supercede all
other values for this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Provider</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">__defineSetter__</span><span class="p">(</span><span class="s1">&#39;overrides&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">val</span><span class="p">)</span> <span class="p">{</span> <span class="nx">updateSystem</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="s1">&#39;overrides&#39;</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="p">});</span>
<span class="nx">Provider</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">__defineGetter__</span><span class="p">(</span><span class="s1">&#39;overrides&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_argv</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">&#182;</a> </div> <h3>@argv {boolean}</h3>
<p>Gets or sets a property indicating if we should wrap calls to <code>.get</code>
by checking <code>optimist.argv</code>. Can be a boolean or the pass-thru
options for <code>optimist</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Provider</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">__defineSetter__</span><span class="p">(</span><span class="s1">&#39;argv&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">val</span><span class="p">)</span> <span class="p">{</span> <span class="nx">updateSystem</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="s1">&#39;argv&#39;</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="p">});</span>
<span class="nx">Provider</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">__defineGetter__</span><span class="p">(</span><span class="s1">&#39;argv&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_argv</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">&#182;</a> </div> <h3>@env {boolean}</h3>
<p>Gets or sets a property indicating if we should wrap calls to <code>.get</code>
by checking <code>process.env</code>. Can be a boolean or an Array of
environment variables to extract.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">Provider</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">__defineSetter__</span><span class="p">(</span><span class="s1">&#39;env&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">val</span><span class="p">)</span> <span class="p">{</span> <span class="nx">updateSystem</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="s1">&#39;env&#39;</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="p">});</span>
<span class="nx">Provider</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">__defineGetter__</span><span class="p">(</span><span class="s1">&#39;env&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_env</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">&#182;</a> </div> <p>Throw the <code>err</code> if a callback is not supplied</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">function</span> <span class="nx">onError</span><span class="p">(</span><span class="nx">err</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="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">err</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">throw</span> <span class="nx">err</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">&#182;</a> </div> <p>Helper function for working with the
default <code>system</code> store for providers.</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">function</span> <span class="nx">updateSystem</span><span class="p">(</span><span class="nx">prop</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">system</span> <span class="o">=</span> <span class="k">this</span><span class="p">[</span><span class="s1">&#39;system&#39;</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">system</span><span class="p">[</span><span class="nx">prop</span><span class="p">]</span> <span class="o">===</span> <span class="nx">value</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">value</span> <span class="o">=</span> <span class="nx">value</span> <span class="o">||</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">this</span><span class="p">[</span><span class="s1">&#39;_&#39;</span> <span class="o">+</span> <span class="nx">prop</span><span class="p">]</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
<span class="nx">system</span><span class="p">[</span><span class="nx">prop</span><span class="p">]</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
<span class="nx">system</span><span class="p">.</span><span class="nx">loadSync</span><span class="p">();</span>
<span class="p">}</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View file

@ -1,19 +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 &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="..//nconf/common.html"> nconf/common.html </a> <a class="source" href="..//nconf/formats.html"> nconf/formats.html </a> <a class="source" href="..//nconf/provider.html"> nconf/provider.html </a> <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/system.html"> nconf/stores/system.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">&#182;</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">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;fs&#39;</span><span class="p">),</span>
<span class="nx">common</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;./common&#39;</span><span class="p">),</span>
<span class="nx">stores</span> <span class="o">=</span> <span class="nx">exports</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">&#182;</a> </div> <p>Setup all stores as lazy-loaded getters.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">fs</span><span class="p">.</span><span class="nx">readdirSync</span><span class="p">(</span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">&#39;/stores&#39;</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">file</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="s1">&#39;.js&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">),</span>
<span class="nx">name</span> <span class="o">=</span> <span class="nx">common</span><span class="p">.</span><span class="nx">capitalize</span><span class="p">(</span><span class="nx">store</span><span class="p">);</span>
<span class="nx">stores</span><span class="p">.</span><span class="nx">__defineGetter__</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;./stores/&#39;</span> <span class="o">+</span> <span class="nx">store</span><span class="p">)[</span><span class="nx">name</span><span class="p">];</span>
<span class="p">});</span>
<span class="p">});</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View file

@ -1,170 +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 &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="../..//nconf/common.html"> nconf/common.html </a> <a class="source" href="../..//nconf/formats.html"> nconf/formats.html </a> <a class="source" href="../..//nconf/provider.html"> nconf/provider.html </a> <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/system.html"> nconf/stores/system.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">&#182;</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">&#39;fs&#39;</span><span class="p">),</span>
<span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;path&#39;</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">&#39;util&#39;</span><span class="p">),</span>
<span class="nx">formats</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;../formats&#39;</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">&#39;./memory&#39;</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">&#182;</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="o">||</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">&#39;Missing required option `files`&#39;</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">type</span> <span class="o">=</span> <span class="s1">&#39;file&#39;</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">dir</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">dir</span> <span class="o">||</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</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">formats</span><span class="p">.</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">&#182;</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">&#182;</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">&#182;</a> </div> <h3>function saveSync (value, callback)</h3>
<h4>@value {Object} <em>Ignored</em> Left here for consistency</h4>
<h4>@callback {function} <strong>Optional</strong> 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> synchronously.</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">saveSync</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="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFileSync</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="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="nx">ex</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span><span class="p">(</span><span class="nx">ex</span><span class="p">);</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">&#182;</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">path</span><span class="p">.</span><span class="nx">exists</span><span class="p">(</span><span class="nx">self</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">exists</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">exists</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">&#182;</a> </div> <p>If the path we are attempting to load doesn't exist, create it</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">self</span><span class="p">.</span><span class="nx">save</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="nx">self</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="nx">callback</span><span class="p">(</span><span class="nx">err</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>
<span class="k">else</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">&#182;</a> </div> <p>Else, the path exists, read it from disk</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span><span class="p">(</span><span class="nx">self</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="k">try</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">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="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="nx">ex</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="s2">&quot;Error parsing your JSON configuration file.&quot;</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">self</span><span class="p">.</span><span class="nx">store</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-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <h3>function load (callback)</h3>
<h4>@callback {function} <strong>Optional</strong> Continuation to respond to when complete.</h4>
<p>Attempts to load the data stored in <code>this.file</code> synchronously and responds appropriately.</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">loadSync</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">path</span><span class="p">.</span><span class="nx">existsSync</span><span class="p">(</span><span class="nx">self</span><span class="p">.</span><span class="nx">file</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">&#182;</a> </div> <p>If the path we are attempting to load doesn't exist, create it</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">self</span><span class="p">.</span><span class="nx">saveSync</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="p">{};</span>
<span class="nx">data</span> <span class="o">=</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">&#182;</a> </div> <p>Else, the path exists, read it from disk</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span> <span class="p">{</span>
<span class="nx">data</span> <span class="o">=</span> <span class="k">this</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">fs</span><span class="p">.</span><span class="nx">readFileSync</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="s1">&#39;utf8&#39;</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="nx">data</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="nx">ex</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="s2">&quot;Error parsing your JSON configuration file.&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">data</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">&#182;</a> </div> <h3>function search (base)</h3>
<h4>@base {string} Base directory (or file) to begin searching for the target file.</h4>
<p>Attempts to find <code>this.file</code> by iteratively searching up the
directory structure </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">search</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">base</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">looking</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
<span class="nx">fullpath</span><span class="p">,</span>
<span class="nx">previous</span><span class="p">,</span>
<span class="nx">stats</span><span class="p">;</span>
<span class="nx">base</span> <span class="o">=</span> <span class="nx">base</span> <span class="o">||</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">();</span>
<span class="k">if</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="mi">0</span><span class="p">]</span> <span class="o">===</span> <span class="s1">&#39;/&#39;</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">&#182;</a> </div> <p>If filename for this instance is a fully qualified path
(i.e. it starts with a <code>'/'</code>) then check if it exists</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span> <span class="p">{</span>
<span class="nx">stats</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">statSync</span><span class="p">(</span><span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</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">if</span> <span class="p">(</span><span class="nx">stats</span><span class="p">.</span><span class="nx">isFile</span><span class="p">())</span> <span class="p">{</span>
<span class="nx">fullpath</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">file</span><span class="p">;</span>
<span class="nx">looking</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="nx">ex</span><span class="p">)</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">&#182;</a> </div> <p>Ignore errors</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">looking</span> <span class="o">&amp;&amp;</span> <span class="nx">base</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">&#182;</a> </div> <p>Attempt to stat the realpath located at <code>base</code>
if the directory does not exist then return false.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">stat</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">statSync</span><span class="p">(</span><span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">base</span><span class="p">));</span>
<span class="nx">looking</span> <span class="o">=</span> <span class="nx">stat</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="nx">ex</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">while</span> <span class="p">(</span><span class="nx">looking</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">&#182;</a> </div> <p>Iteratively look up the directory structure from <code>base</code></p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span> <span class="p">{</span>
<span class="nx">stats</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">statSync</span><span class="p">(</span><span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">fullpath</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">base</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="nx">looking</span> <span class="o">=</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="nx">ex</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">previous</span> <span class="o">=</span> <span class="nx">base</span><span class="p">;</span>
<span class="nx">base</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">base</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">previous</span> <span class="o">===</span> <span class="nx">base</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">&#182;</a> </div> <p>If we've reached the top of the directory structure then simply use
the default file path.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span> <span class="p">{</span>
<span class="nx">stats</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">statSync</span><span class="p">(</span><span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">fullpath</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">dir</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">if</span> <span class="p">(</span><span class="nx">stats</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">())</span> <span class="p">{</span>
<span class="nx">fullpath</span> <span class="o">=</span> <span class="kc">undefined</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="nx">ex</span><span class="p">)</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">&#182;</a> </div> <p>Ignore errors</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">}</span>
<span class="nx">looking</span> <span class="o">=</span> <span class="kc">false</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">&#182;</a> </div> <p>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 <code>this.file</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">file</span> <span class="o">=</span> <span class="nx">fullpath</span> <span class="o">||</span> <span class="k">this</span><span class="p">.</span><span class="nx">file</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">fullpath</span><span class="p">;</span>
<span class="p">};</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View file

@ -1,143 +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 &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="../..//nconf/common.html"> nconf/common.html </a> <a class="source" href="../..//nconf/formats.html"> nconf/formats.html </a> <a class="source" href="../..//nconf/provider.html"> nconf/provider.html </a> <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/system.html"> nconf/stores/system.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">&#182;</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">common</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;../common&#39;</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">&#182;</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">type</span> <span class="o">=</span> <span class="s1">&#39;memory&#39;</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="k">this</span><span class="p">.</span><span class="nx">readOnly</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">loadFrom</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">loadFrom</span> <span class="o">||</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">loadFrom</span><span class="p">)</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="nx">common</span><span class="p">.</span><span class="nx">loadFilesSync</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">loadFrom</span><span class="p">);</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">&#182;</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">common</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">&#182;</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">&gt;</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="p">(</span><span class="nx">target</span> <span class="o">&amp;&amp;</span> <span class="nx">key</span> <span class="k">in</span> <span class="nx">target</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">&#182;</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="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">readOnly</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">false</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">common</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">&#182;</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">&#182;</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">&gt;</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="o">||</span> <span class="k">typeof</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="s1">&#39;object&#39;</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">&#182;</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">&#182;</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="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">readOnly</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">false</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">common</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">&#182;</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">&#182;</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">&gt;</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">&#182;</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">&#182;</a> </div> <h3>function merge (key, value)</h3>
<h4>@key {string} Key to merge the value into</h4>
<h4>@value {literal|Object} Value to merge into the key</h4>
<p>Merges the properties in <code>value</code> into the existing object value
at <code>key</code>. If the existing value <code>key</code> is not an Object, it will be
completely overwritten.</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">merge</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="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">readOnly</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</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">&#182;</a> </div> <p>If the key is not an <code>Object</code> or is an <code>Array</code>,
then simply set it. Merging is for Objects.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">value</span> <span class="o">!==</span> <span class="s1">&#39;object&#39;</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="p">{</span>
<span class="k">return</span> <span class="k">this</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="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">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">common</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">fullKey</span> <span class="o">=</span> <span class="nx">key</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">&#182;</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-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</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">&gt;</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-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</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>
</pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>If the current value at the key target is not an <code>Object</code>,
or is an <code>Array</code> then simply override it because the new value
is an Object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="k">typeof</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="s1">&#39;object&#39;</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">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="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>
<span class="k">return</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="nx">every</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">nested</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">self</span><span class="p">.</span><span class="nx">merge</span><span class="p">(</span><span class="nx">fullKey</span> <span class="o">+</span> <span class="s1">&#39;:&#39;</span> <span class="o">+</span> <span class="nx">nested</span><span class="p">,</span> <span class="nx">value</span><span class="p">[</span><span class="nx">nested</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">&#182;</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">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">readOnly</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">false</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>

View file

@ -1,98 +0,0 @@
<!DOCTYPE html> <html> <head> <title>system.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 &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="../..//nconf/common.html"> nconf/common.html </a> <a class="source" href="../..//nconf/formats.html"> nconf/formats.html </a> <a class="source" href="../..//nconf/provider.html"> nconf/provider.html </a> <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/system.html"> nconf/stores/system.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> system.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">&#182;</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
<span class="cm"> * system.js: Simple memory-based store for process environment variables and</span>
<span class="cm"> * command-line arguments.</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">util</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;util&#39;</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">&#39;./memory&#39;</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">&#182;</a> </div> <h3>function System (options)</h3>
<h4>@options {Object} Options for this instance.</h4>
<p>Constructor function for the System nconf store, a simple abstraction
around the Memory store that can read process environment variables
and command-line arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">System</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">System</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="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">type</span> <span class="o">=</span> <span class="s1">&#39;system&#39;</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">overrides</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">overrides</span> <span class="o">||</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">env</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">env</span> <span class="o">||</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">argv</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">argv</span> <span class="o">||</span> <span class="kc">false</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">&#182;</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">System</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">&#182;</a> </div> <h3>function loadSync ()</h3>
<p>Loads the data passed in from <code>process.env</code> into this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">System</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">loadSync</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">env</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">loadEnv</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">argv</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">loadArgv</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">overrides</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">loadOverrides</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">store</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">&#182;</a> </div> <h3>function loadOverrides ()</h3>
<p>Loads any overrides set on this instance into
the underlying managed <code>Memory</code> store.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">System</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">loadOverrides</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">overrides</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</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="k">this</span><span class="p">.</span><span class="nx">overrides</span><span class="p">);</span>
<span class="nx">keys</span><span class="p">.</span><span class="nx">forEach</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="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">self</span><span class="p">.</span><span class="nx">overrides</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="k">this</span><span class="p">.</span><span class="nx">store</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">&#182;</a> </div> <h3>function loadArgv ()</h3>
<p>Loads the data passed in from the command-line arguments
into this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">System</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">loadArgv</span> <span class="o">=</span> <span class="kd">function</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">argv</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="k">this</span><span class="p">.</span><span class="nx">argv</span> <span class="o">===</span> <span class="s1">&#39;object&#39;</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">argv</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;optimist&#39;</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">argv</span><span class="p">).</span><span class="nx">argv</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">argv</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">argv</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;optimist&#39;</span><span class="p">).</span><span class="nx">argv</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">argv</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">argv</span><span class="p">).</span><span class="nx">forEach</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="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">argv</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="k">this</span><span class="p">.</span><span class="nx">store</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">&#182;</a> </div> <h3>function loadEnv ()</h3>
<p>Loads the data passed in from <code>process.env</code> into this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">System</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">loadEnv</span> <span class="o">=</span> <span class="kd">function</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="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">env</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">).</span><span class="nx">filter</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="p">{</span>
<span class="k">return</span> <span class="o">!</span><span class="nx">self</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">length</span> <span class="o">||</span> <span class="nx">self</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="o">!==</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}).</span><span class="nx">forEach</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="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">process</span><span class="p">.</span><span class="nx">env</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="k">this</span><span class="p">.</span><span class="nx">store</span><span class="p">;</span>
<span class="p">};</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

177
lib/common.mjs Normal file
View file

@ -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
}, {})
}

View file

@ -1,39 +0,0 @@
/*
* nconf.js: Top-level include for the nconf module
*
* (C) 2011, Nodejitsu Inc.
*
*/
var fs = require('fs'),
async = require('async'),
common = require('./nconf/common'),
Provider = require('./nconf/provider').Provider,
nconf = module.exports = new Provider();
//
// Expose the version from the package.json using `pkginfo`.
//
require('pkginfo')(module, 'version');
//
// Setup all stores as lazy-loaded getters.
//
fs.readdirSync(__dirname + '/nconf/stores').forEach(function (file) {
var store = file.replace('.js', ''),
name = common.capitalize(store);
nconf.__defineGetter__(name, function () {
return require('./nconf/stores/' + store)[name];
});
});
//
// Expose the various components included with nconf
//
nconf.key = common.key;
nconf.path = common.path;
nconf.loadFiles = common.loadFiles;
nconf.loadFilesSync = common.loadFilesSync;
nconf.formats = require('./nconf/formats');
nconf.Provider = Provider;

181
lib/nconf.mjs Normal file
View file

@ -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

View file

@ -1,111 +0,0 @@
/*
* utils.js: Utility functions for the nconf module.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var fs = require('fs'),
async = require('async'),
formats = require('./formats'),
Memory = require('./stores/memory').Memory;
var common = exports;
//
// ### function path (key)
// #### @key {string} The ':' delimited key to split
// Returns a fully-qualified path to a nested nconf key.
//
common.path = function (key) {
return key.split(':');
};
//
// ### function key (arguments)
// Returns a `:` joined string from the `arguments`.
//
common.key = function () {
return Array.prototype.slice.call(arguments).join(':');
};
//
// ### function loadFiles (files, callback)
// #### @files {Object|Array} List of files (or settings object) to load.
// #### @callback {function} Continuation to respond to when complete.
// Loads all the data in the specified `files`.
//
common.loadFiles = function (files, callback) {
if (!files) {
return callback(null, {});
}
var options = Array.isArray(files) ? { files: files } : files;
//
// Set the default JSON format if not already
// specified
//
options.format = options.format || formats.json;
function parseFile (file, next) {
fs.readFile(file, function (err, data) {
return !err
? next(null, options.format.parse(data.toString()))
: next(err);
});
}
async.map(files, parseFile, function (err, objs) {
return err ? callback(err) : callback(null, common.merge(objs));
});
};
//
// ### function loadFilesSync (files)
// #### @files {Object|Array} List of files (or settings object) to load.
// Loads all the data in the specified `files` synchronously.
//
common.loadFilesSync = function (files) {
if (!files) {
return;
}
//
// Set the default JSON format if not already
// specified
//
var options = Array.isArray(files) ? { files: files } : files;
options.format = options.format || formats.json;
return common.merge(files.map(function (file) {
return options.format.parse(fs.readFileSync(file, 'utf8'));
}));
};
//
// ### function merge (objs)
// #### @objs {Array} Array of object literals to merge
// Merges the specified `objs` using a temporary instance
// of `stores.Memory`.
//
common.merge = function (objs) {
var store = new Memory();
objs.forEach(function (obj) {
Object.keys(obj).forEach(function (key) {
store.merge(key, obj[key]);
});
});
return store.store;
};
//
// ### function capitalize (str)
// #### @str {string} String to capitalize
// Capitalizes the specified `str`.
//
common.capitalize = function (str) {
return str && str[0].toUpperCase() + str.slice(1);
};

View file

@ -1,28 +0,0 @@
/*
* formats.js: Default formats supported by nconf
*
* (C) 2011, Nodejitsu Inc.
*
*/
var ini = require('ini');
var formats = exports;
//
// ### @json
// Standard JSON format which pretty prints `.stringify()`.
//
formats.json = {
stringify: function (obj, replacer, spacing) {
return JSON.stringify(obj, replacer || null, spacing || 2)
},
parse: JSON.parse
};
//
// ### @ini
// Standard INI format supplied from the `ini` module
// http://en.wikipedia.org/wiki/INI_file
//
formats.ini = ini;

View file

@ -1,565 +0,0 @@
/*
* provider.js: Abstraction providing an interface into pluggable configuration storage.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var async = require('async'),
common = require('./common');
//
// ### function Provider (options)
// #### @options {Object} Options for this instance.
// Constructor function for the Provider object responsible
// for exposing the pluggable storage features of `nconf`.
//
var Provider = exports.Provider = function (options) {
//
// Setup default options for working with `stores`,
// `overrides`, `process.env` and `process.argv`.
//
options = options || {};
this.stores = {};
this.sources = [];
this.init(options);
};
//
// Define wrapper functions for using basic stores
// in this instance
//
['argv', 'env'].forEach(function (type) {
Provider.prototype[type] = function (options) {
return this.add(type, options);
};
});
//
// ### function file (key, options)
// #### @key {string|Object} Fully qualified options, name of file store, or path.
// #### @path {string|Object} **Optional** Full qualified options, or path.
// Adds a new `File` store to this instance. Accepts the following options
//
// nconf.file({ file: '.jitsuconf', dir: process.env.HOME, search: true });
// nconf.file('path/to/config/file');
// nconf.file('userconfig', 'path/to/config/file');
// nconf.file('userconfig', { file: '.jitsuconf', search: true });
//
Provider.prototype.file = function (key, options) {
if (arguments.length == 1) {
options = typeof key === 'string' ? { file: key } : key;
key = 'file';
}
else {
options = typeof options === 'string'
? { file: options }
: options;
}
options.type = 'file';
return this.add(key, options);
};
//
// Define wrapper functions for using
// overrides and defaults
//
['defaults', 'overrides'].forEach(function (type) {
Provider.prototype[type] = function (options) {
options = options || {};
if (!options.type) {
options.type = 'literal';
}
return this.add(type, options);
};
});
//
// ### function use (name, options)
// #### @type {string} Type of the nconf store to use.
// #### @options {Object} Options for the store instance.
// Adds (or replaces) a new store with the specified `name`
// and `options`. If `options.type` is not set, then `name`
// will be used instead:
//
// provider.use('file');
// provider.use('file', { type: 'file', filename: '/path/to/userconf' })
//
Provider.prototype.use = function (name, options) {
options = options || {};
var type = options.type || name;
function sameOptions (store) {
return Object.keys(options).every(function (key) {
return options[key] === store[key];
});
}
var store = this.stores[name],
update = store && !sameOptions(store);
if (!store || update) {
if (update) {
this.remove(name);
}
this.add(name, options);
}
return this;
};
//
// ### function add (name, options)
// #### @name {string} Name of the store to add to this instance
// #### @options {Object} Options for the store to create
// Adds a new store with the specified `name` and `options`. If `options.type`
// is not set, then `name` will be used instead:
//
// provider.add('memory');
// provider.add('userconf', { type: 'file', filename: '/path/to/userconf' })
//
Provider.prototype.add = function (name, options) {
options = options || {};
var type = options.type || name;
if (!require('../nconf')[common.capitalize(type)]) {
throw new Error('Cannot add store with unknown type: ' + type);
}
this.stores[name] = this.create(type, options);
if (this.stores[name].loadSync) {
this.stores[name].loadSync();
}
return this;
};
//
// ### function remove (name)
// #### @name {string} Name of the store to remove from this instance
// Removes a store with the specified `name` from this instance. Users
// are allowed to pass in a type argument (e.g. `memory`) as name if
// this was used in the call to `.add()`.
//
Provider.prototype.remove = function (name) {
delete this.stores[name];
return this;
};
//
// ### 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`.
//
Provider.prototype.create = function (type, options) {
return new (require('../nconf')[common.capitalize(type.toLowerCase())])(options);
};
//
// ### function init (options)
// #### @options {Object} Options to initialize this instance with.
// Initializes this instance with additional `stores` or `sources` in the
// `options` supplied.
//
Provider.prototype.init = function (options) {
var self = this;
//
// Add any stores passed in through the options
// to this instance.
//
if (options.type) {
this.add(options.type, options);
}
else if (options.store) {
this.add(options.store.name || options.store.type, options.store);
}
else if (options.stores) {
Object.keys(options.stores).forEach(function (name) {
var store = options.stores[name];
self.add(store.name || name || store.type, store);
});
}
//
// Add any read-only sources to this instance
//
if (options.source) {
this.sources.push(this.create(options.source.type || options.source.name, options.source));
}
else if (options.sources) {
Object.keys(options.sources).forEach(function (name) {
var source = options.sources[name];
self.sources.push(self.create(source.type || source.name || name, source));
});
}
};
//
// ### 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).
//
Provider.prototype.get = function (key, callback) {
//
// If there is no callback we can short-circuit into the default
// logic for traversing stores.
//
if (!callback) {
return this._execute('get', 1, key, callback);
}
//
// Otherwise the asynchronous, hierarchical `get` is
// slightly more complicated because we do not need to traverse
// the entire set of stores, but up until there is a defined value.
//
var current = 0,
names = Object.keys(this.stores),
self = this,
response,
mergeObjs = [];
async.whilst(function () {
return typeof response === 'undefined' && current < names.length;
}, function (next) {
var store = self.stores[names[current]];
current++;
if (store.get.length >= 2) {
return store.get(key, function (err, value) {
if (err) {
return next(err);
}
response = value;
// Merge objects if necessary
if (typeof response === 'object' && !Array.isArray(response)) {
mergeObjs.push(response);
response = undefined;
}
next();
});
}
response = store.get(key);
// Merge objects if necessary
if (typeof response === 'object' && !Array.isArray(response)) {
mergeObjs.push(response);
response = undefined;
}
next();
}, function (err) {
if (!err && mergeObjs.length) {
response = common.merge(mergeObjs.reverse());
}
return err ? callback(err) : callback(null, response);
});
};
//
// ### 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.
//
Provider.prototype.set = function (key, value, callback) {
return this._execute('set', 2, key, value, callback);
};
//
// ### function reset (callback)
// #### @callback {function} **Optional** Continuation to respond to when complete.
// Clears all keys associated with this instance.
//
Provider.prototype.reset = function (callback) {
return this._execute('reset', 0, 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.
//
Provider.prototype.clear = function (key, callback) {
return this._execute('clear', 1, key, callback);
};
//
// ### function merge ([key,] value [, callback])
// #### @key {string} Key to merge the value into
// #### @value {literal|Object} Value to merge into the key
// #### @callback {function} **Optional** Continuation to respond to when complete.
// Merges the properties in `value` into the existing object value at `key`.
//
// 1. If the existing value `key` is not an Object, it will be completely overwritten.
// 2. If `key` is not supplied, then the `value` will be merged into the root.
//
Provider.prototype.merge = function () {
var self = this,
args = Array.prototype.slice.call(arguments),
callback = typeof args[args.length - 1] === 'function' && args.pop(),
value = args.pop(),
key = args.pop();
function mergeProperty (prop, next) {
return self._execute('merge', 2, prop, value[prop], next);
}
if (!key) {
if (Array.isArray(value) || typeof value !== 'object') {
return onError(new Error('Cannot merge non-Object into top-level.'), callback);
}
return async.forEach(Object.keys(value), mergeProperty, callback || function () { })
}
return this._execute('merge', 2, key, value, callback);
};
//
// ### function load (callback)
// #### @callback {function} Continuation to respond to when complete.
// Responds with an Object representing all keys associated in this instance.
//
Provider.prototype.load = function (callback) {
var self = this;
function getStores () {
var stores = Object.keys(self.stores);
stores.reverse();
return stores.map(function (name) {
return self.stores[name];
});
}
function loadStoreSync(store) {
if (!store.loadSync) {
throw new Error('nconf store ' + store.type + ' has no loadSync() method');
}
return store.loadSync();
}
function loadStore(store, next) {
if (!store.load && !store.loadSync) {
return next(new Error('nconf store ' + store.type + ' has no load() method'));
}
return store.loadSync
? next(null, store.loadSync())
: store.load(next);
}
function loadBatch (targets, done) {
if (!done) {
return common.merge(targets.map(loadStoreSync));
}
async.map(targets, loadStore, function (err, objs) {
return err ? done(err) : done(null, common.merge(objs));
});
}
function mergeSources (data) {
//
// If `data` was returned then merge it into
// the system store.
//
if (data && typeof data === 'object') {
self.use('sources', {
type: 'literal',
store: data
});
}
}
function loadSources () {
var sourceHierarchy = self.sources.splice(0);
sourceHierarchy.reverse();
//
// If we don't have a callback and the current
// store is capable of loading synchronously
// then do so.
//
if (!callback) {
mergeSources(loadBatch(sourceHierarchy));
return loadBatch(getStores());
}
loadBatch(sourceHierarchy, function (err, data) {
if (err) {
return callback(err);
}
mergeSources(data);
return loadBatch(getStores(), callback);
});
}
return self.sources.length
? loadSources()
: loadBatch(getStores(), callback);
};
//
// ### function save (callback)
// #### @callback {function} **optional** Continuation to respond to when
// complete.
// Instructs each provider to save. If a callback is provided, we will attempt
// asynchronous saves on the providers, falling back to synchronous saves if
// this isn't possible. If a provider does not know how to save, it will be
// ignored. Returns an object consisting of all of the data which was
// actually saved.
//
Provider.prototype.save = function (value, callback) {
if (!callback && typeof value === 'function') {
callback = value;
value = null;
}
var self = this,
names = Object.keys(this.stores);
function saveStoreSync(memo, name) {
var store = self.stores[name];
//
// If the `store` doesn't have a `saveSync` method,
// just ignore it and continue.
//
if (store.saveSync) {
var ret = store.saveSync();
if (typeof ret == 'object' && ret !== null) {
memo.push(ret);
}
}
return memo;
}
function saveStore(memo, name, next) {
var store = self.stores[name];
//
// If the `store` doesn't have a `save` or saveSync`
// method(s), just ignore it and continue.
//
if (store.save) {
return store.save(function (err, data) {
if (err) {
return next(err);
}
if (typeof data == 'object' && data !== null) {
memo.push(data);
}
next(null, memo);
});
}
else if (store.saveSync) {
memo.push(store.saveSync());
}
next(null, memo);
}
//
// If we don't have a callback and the current
// store is capable of saving synchronously
// then do so.
//
if (!callback) {
return common.merge(names.reduce(saveStoreSync, []));
}
async.reduce(names, [], saveStore, function (err, objs) {
return err ? callback(err) : callback(null, common.merge(objs));
});
};
//
// ### @private function _execute (action, syncLength, [arguments])
// #### @action {string} Action to execute on `this.store`.
// #### @syncLength {number} Function length of the sync version.
// #### @arguments {Array} Arguments array to apply to the action
// Executes the specified `action` on all stores for this instance, ensuring a callback supplied
// to a synchronous store function is still invoked.
//
Provider.prototype._execute = function (action, syncLength /* [arguments] */) {
var args = Array.prototype.slice.call(arguments, 2),
callback = typeof args[args.length - 1] === 'function' && args.pop(),
destructive = ['set', 'clear', 'merge', 'reset'].indexOf(action) !== -1,
self = this,
response,
mergeObjs = [];
function runAction (name, next) {
var store = self.stores[name];
if (destructive && store.readOnly) {
return next();
}
return store[action].length > syncLength
? store[action].apply(store, args.concat(next))
: next(null, store[action].apply(store, args));
}
if (callback) {
return async.forEach(Object.keys(this.stores), runAction, function (err) {
return err ? callback(err) : callback();
});
}
Object.keys(this.stores).forEach(function (name) {
if (typeof response === 'undefined') {
var store = self.stores[name];
if (destructive && store.readOnly) {
return;
}
response = store[action].apply(store, args);
// Merge objects if necessary
if (action === 'get' && typeof response === 'object' && !Array.isArray(response)) {
mergeObjs.push(response);
response = undefined;
}
}
});
if (mergeObjs.length) {
response = common.merge(mergeObjs.reverse());
}
return response;
}
//
// Throw the `err` if a callback is not supplied
//
function onError(err, callback) {
if (callback) {
return callback(err);
}
throw err;
}

View file

@ -1,61 +0,0 @@
/*
* argv.js: Simple memory-based store for command-line arguments.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var util = require('util'),
Memory = require('./memory').Memory;
//
// ### 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 command-line arguments.
//
var Argv = exports.Argv = function (options) {
Memory.call(this, options);
this.type = 'argv';
this.readOnly = true;
this.options = options || false;
};
// Inherit from the Memory store
util.inherits(Argv, Memory);
//
// ### function loadSync ()
// Loads the data passed in from `process.argv` into this instance.
//
Argv.prototype.loadSync = function () {
this.loadArgv();
return this.store;
};
//
// ### function loadArgv ()
// Loads the data passed in from the command-line arguments
// into this instance.
//
Argv.prototype.loadArgv = function () {
var self = this,
argv;
argv = typeof this.options === 'object'
? require('optimist')(process.argv.slice(2)).options(this.options).argv
: require('optimist')(process.argv.slice(2)).argv;
if (!argv) {
return;
}
this.readOnly = false;
Object.keys(argv).forEach(function (key) {
self.set(key, argv[key]);
});
this.readOnly = true;
return this.store;
};

View file

@ -1,67 +0,0 @@
/*
* env.js: Simple memory-based store for environment variables
*
* (C) 2011, Nodejitsu Inc.
*
*/
var util = require('util'),
common = require('../common'),
Memory = require('./memory').Memory;
//
// ### 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.
//
var Env = exports.Env = function (options) {
Memory.call(this, options);
options = options || {};
this.type = 'env';
this.readOnly = true;
this.whitelist = options.whitelist || [];
this.separator = options.separator || '';
if (options instanceof Array) {
this.whitelist = options;
}
if (typeof(options) === 'string') {
this.separator = options;
}
};
// Inherit from the Memory store
util.inherits(Env, Memory);
//
// ### function loadSync ()
// Loads the data passed in from `process.env` into this instance.
//
Env.prototype.loadSync = function () {
this.loadEnv();
return this.store;
};
//
// ### function loadEnv ()
// Loads the data passed in from `process.env` into this instance.
//
Env.prototype.loadEnv = function () {
var self = this;
this.readOnly = false;
Object.keys(process.env).filter(function (key) {
return !self.whitelist.length || self.whitelist.indexOf(key) !== -1;
}).forEach(function (key) {
if (self.separator) {
self.set(common.key.apply(common, key.split(self.separator)), process.env[key]);
} else {
self.set(key, process.env[key]);
}
});
this.readOnly = true;
return this.store;
};

View file

@ -1,228 +0,0 @@
/*
* file.js: Simple file storage engine for nconf files
*
* (C) 2011, Nodejitsu Inc.
*
*/
var fs = require('fs'),
path = require('path'),
util = require('util'),
formats = require('../formats'),
Memory = require('./memory').Memory,
exists = fs.exists || path.exists,
existsSync = fs.existsSync || path.existsSync;
//
// ### 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 || !options.file) {
throw new Error ('Missing required option `file`');
}
Memory.call(this, options);
this.type = 'file';
this.file = options.file;
this.dir = options.dir || process.cwd();
this.format = options.format || formats.json;
this.json_spacing = options.json_spacing || 2;
if (options.search) {
this.search(this.dir);
}
};
// 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, null, this.json_spacing), function (err) {
return err ? callback(err) : callback();
});
};
//
// ### function saveSync (value, callback)
// #### @value {Object} _Ignored_ Left here for consistency
// #### @callback {function} **Optional** Continuation to respond to when complete.
// Saves the current configuration object to disk at `this.file`
// using the format specified by `this.format` synchronously.
//
File.prototype.saveSync = function (value) {
try {
fs.writeFileSync(this.file, this.format.stringify(this.store, null, this.json_spacing));
}
catch (ex) {
throw(ex);
}
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) {
var 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 {
self.store = self.format.parse(data.toString());
}
catch (ex) {
return callback(new Error("Error parsing your JSON configuration file."));
}
callback(null, self.store);
});
});
};
//
// ### function loadSync (callback)
// Attempts to load the data stored in `this.file` synchronously
// and responds appropriately.
//
File.prototype.loadSync = function () {
var data, self = this;
if (!existsSync(self.file)) {
self.store = {};
data = {};
}
else {
//
// Else, the path exists, read it from disk
//
try {
data = this.format.parse(fs.readFileSync(this.file, 'utf8'));
this.store = data;
}
catch (ex) {
throw new Error("Error parsing your JSON configuration file.")
}
}
return data;
};
//
// ### 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) {
var 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 {
var 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;
};

View file

@ -1,29 +0,0 @@
/*
* literal.js: Simple literal Object store for nconf.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var util = require('util'),
Memory = require('./memory').Memory
var Literal = exports.Literal = function Literal (options) {
Memory.call(this, options);
options = options || {}
this.type = 'literal';
this.readOnly = true;
this.store = options.store || options;
};
// Inherit from Memory store.
util.inherits(Literal, Memory);
//
// ### function loadSync (callback)
// Returns the data stored in `this.store` synchronously.
//
Literal.prototype.loadSync = function () {
return this.store;
};

View file

@ -1,210 +0,0 @@
/*
* memory.js: Simple memory storage engine for nconf configuration(s)
*
* (C) 2011, Nodejitsu Inc.
*
*/
var common = require('../common');
//
// ### 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 = {};
this.readOnly = false;
this.loadFrom = options.loadFrom || null;
if (this.loadFrom) {
this.store = common.loadFilesSync(this.loadFrom);
}
};
//
// ### 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);
//
// Scope into the object to get the appropriate nested context
//
while (path.length > 0) {
key = path.shift();
if (!(target && key in target)) {
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) {
if (this.readOnly) {
return false;
}
var target = this.store,
path = common.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] || typeof target[key] !== 'object') {
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) {
if (this.readOnly) {
return false;
}
var target = this.store,
path = common.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 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`. If the existing value `key` is not an Object, it will be
// completely overwritten.
//
Memory.prototype.merge = function (key, value) {
if (this.readOnly) {
return false;
}
//
// If the key is not an `Object` or is an `Array`,
// then simply set it. Merging is for Objects.
//
if (typeof value !== 'object' || Array.isArray(value)) {
return this.set(key, value);
}
var self = this,
target = this.store,
path = common.path(key),
fullKey = 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();
//
// If the current value at the key target is not an `Object`,
// or is an `Array` then simply override it because the new value
// is an Object.
//
if (typeof target[key] !== 'object' || Array.isArray(target[key])) {
target[key] = value;
return true;
}
return Object.keys(value).every(function (nested) {
return self.merge(common.key(fullKey, nested), value[nested]);
});
};
//
// ### function reset (callback)
// Clears all keys associated with this instance.
//
Memory.prototype.reset = function () {
if (this.readOnly) {
return false;
}
this.mtimes = {};
this.store = {};
return true;
};
//
// ### function loadSync
// Returns the store managed by this instance
//
Memory.prototype.loadSync = function () {
return this.store || {};
};

72
lib/stores/argv.mjs Normal file
View file

@ -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

102
lib/stores/env.mjs Normal file
View file

@ -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

386
lib/stores/file.mjs Normal file
View file

@ -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

15
lib/stores/literal.mjs Normal file
View 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

212
lib/stores/memory.mjs Normal file
View file

@ -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

View file

@ -1,35 +1,42 @@
{
"name": "nconf",
"description": "Hierarchical node.js configuration with files, environment variables, command-line arguments, and atomic object merging.",
"version": "0.6.4",
"author": "Nodejitsu Inc. <info@nodejitsu.com>",
"maintainers": [
"indexzero <charlie@nodejitsu.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/flatiron/nconf.git"
"url": "http://github.com/nfp-projects/nconf-lite.git"
},
"keywords": [
"configuration",
"key value store",
"plugabble"
],
"dependencies": {
"async": "0.1.x",
"ini": "1.x.x",
"optimist": "0.3.x",
"pkginfo": "0.2.x"
"watch": {
"test": {
"patterns": [
"{lib,test}/*"
],
"extensions": "js,mjs",
"quiet": true,
"inherit": true
}
},
"dependencies": {},
"devDependencies": {
"vows": "0.6.x"
"eltro": "^1.0.2"
},
"main": "./lib/nconf",
"main": "./lib/nconf.mjs",
"scripts": {
"test": "vows test/*-test.js test/**/*-test.js --spec"
"test": "eltro test/**/*.test.mjs -r dot",
"test:watch": "npm-watch test",
"lint": "eslint ."
},
"files": [
"lib"
],
"engines": {
"node": ">= 0.4.0"
}
"node": ">= 13.0.0"
},
"license": "MIT"
}

View file

@ -1,32 +0,0 @@
/*
* common.js: Tests for common utility function in nconf.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var fs = require('fs'),
path = require('path'),
vows = require('vows'),
assert = require('assert'),
helpers = require('./helpers'),
nconf = require('../lib/nconf');
var mergeDir = path.join(__dirname, 'fixtures', 'merge'),
files = fs.readdirSync(mergeDir).map(function (f) { return path.join(mergeDir, f) });
vows.describe('nconf/common').addBatch({
"Using nconf.common module": {
"the loadFiles() method": {
topic: function () {
nconf.loadFiles(files, this.callback);
},
"should merge the files correctly": helpers.assertMerged
},
"the loadFilesSync() method": {
"should merge the files correctly": function () {
helpers.assertMerged(null, nconf.loadFilesSync(files));
}
}
}
}).export(module);

258
test/common.test.mjs Normal file
View file

@ -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}"')
})
})

View file

@ -1,126 +0,0 @@
/*
* complete-test.js: Complete test for multiple stores.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var fs = require('fs'),
path = require('path'),
vows = require('vows'),
assert = require('assert'),
nconf = require('../lib/nconf'),
data = require('./fixtures/data').data,
helpers = require('./helpers');
var completeTest = helpers.fixture('complete-test.json'),
complete = helpers.fixture('complete.json');
vows.describe('nconf/multiple-stores').addBatch({
"When using the nconf with multiple providers": {
topic: function () {
var that = this;
helpers.cp(complete, completeTest, function () {
nconf.env();
nconf.file({ file: completeTest });
nconf.use('argv', { type: 'literal', store: data });
that.callback();
});
},
"should have the correct `stores`": function () {
assert.isObject(nconf.stores.env);
assert.isObject(nconf.stores.argv);
assert.isObject(nconf.stores.file);
},
"env vars": {
"are present": function () {
Object.keys(process.env).forEach(function (key) {
assert.equal(nconf.get(key), process.env[key]);
});
}
},
"json vars": {
topic: function () {
fs.readFile(complete, 'utf8', this.callback);
},
"are present": function (err, data) {
assert.isNull(err);
data = JSON.parse(data);
Object.keys(data).forEach(function (key) {
assert.deepEqual(nconf.get(key), data[key]);
});
}
},
"literal vars": {
"are present": function () {
Object.keys(data).forEach(function (key) {
assert.deepEqual(nconf.get(key), data[key]);
});
}
},
"and saving *synchronously*": {
topic: function () {
nconf.set('weebls', 'stuff');
return nconf.save();
},
"correct return value": function (topic) {
Object.keys(topic).forEach(function (key) {
assert.deepEqual(topic[key], nconf.get(key));
});
},
"the file": {
topic: function () {
fs.readFile(completeTest, 'utf8', this.callback);
},
"saved correctly": function (err, data) {
data = JSON.parse(data);
Object.keys(data).forEach(function (key) {
assert.deepEqual(data[key], nconf.get(key));
});
assert.equal(nconf.get('weebls'), 'stuff');
}
}
},
teardown: function () {
// remove the file so that we can test saving it async
fs.unlinkSync(completeTest);
}
}
}).addBatch({
// Threw this in it's own batch to make sure it's run separately from the
// sync check
"When using the nconf with multiple providers": {
"and saving *asynchronously*": {
topic: function () {
nconf.set('weebls', 'crap');
nconf.save(this.callback);
},
"correct return value": function (err, data) {
assert.isNull(err);
Object.keys(data).forEach(function (key) {
assert.deepEqual(data[key], nconf.get(key));
});
},
"the file": {
topic: function () {
fs.readFile(completeTest, 'utf8', this.callback);
},
"saved correctly": function (err, data) {
assert.isNull(err);
data = JSON.parse(data);
Object.keys(data).forEach(function (key) {
assert.deepEqual(nconf.get(key), data[key]);
});
assert.equal(nconf.get('weebls'), 'crap');
}
}
},
teardown: function () {
fs.unlinkSync(completeTest);
nconf.remove('file');
nconf.remove('memory');
nconf.remove('argv');
nconf.remove('env');
}
}
}).export(module);

19
test/fixtures/bom.json vendored Normal file
View file

@ -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
}

View file

@ -1,12 +1,6 @@
/*
* data.js: Simple data fixture for configuration test.
*
* (C) 2011, Nodejitsu Inc.
*
*/
exports.data = {
literal: 'bazz',
export const data = {
isNull: null,
literal: 'bazz',
arr: ['one', 2, true, { value: 'foo' }],
obj: {
host: 'localhost',
@ -19,7 +13,7 @@ exports.data = {
}
};
exports.merge = {
export const merge = {
prop1: 1,
prop2: [1, 2, 3],
prop3: {

View file

@ -1,3 +0,0 @@
{
"test": "empty"
}

View file

@ -12,5 +12,8 @@
"first": 1,
"second": 2
}
},
"unicorn": {
"exists": true
}
}

View file

@ -5,5 +5,6 @@
"something4": true
},
"dates": true,
"elderberries": true
}
"elderberries": true,
"unicorn": null
}

9
test/fixtures/merge/file3.json vendored Normal file
View file

@ -0,0 +1,9 @@
{
"candy": {
"something": "much better something for you",
"something18": "completely unique",
"something5": {
"second": 99
}
}
}

19
test/fixtures/no-bom.json vendored Normal file
View file

@ -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
}

View file

@ -1,10 +0,0 @@
/*
* default-argv.js: Test fixture for using optimist defaults with nconf.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var nconf = require('../../../lib/nconf').argv().env();
process.stdout.write(nconf.get('something'));

View file

@ -1,16 +0,0 @@
/*
* nconf-change-argv.js: Test fixture for changing argv on the fly
*
* (C) 2011, Nodejitsu Inc.
*
*/
var nconf = require('../../../lib/nconf').argv();
//
// Remove 'badValue', 'evenWorse' and 'OHNOEZ'
//
process.argv.splice(3, 3);
nconf.stores['argv'].loadArgv();
process.stdout.write(nconf.get('something'));

View file

@ -1,10 +0,0 @@
/*
* nconf-env.js: Test fixture for using process.env defaults with nconf.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var nconf = require('../../../lib/nconf').env();
process.stdout.write(nconf.get('SOMETHING'));

View file

@ -1,17 +0,0 @@
/*
* nconf-hierarchical-file-argv.js: Test fixture for using optimist defaults and a file store with nconf.
*
* (C) 2011, Nodejitsu Inc.
* (C) 2011, Sander Tolsma
*
*/
var path = require('path'),
nconf = require('../../../lib/nconf');
nconf.argv();
nconf.add('file', {
file: path.join(__dirname, '../hierarchy/hierarchical.json')
});
process.stdout.write(nconf.get('something') || 'undefined');

View file

@ -1,18 +0,0 @@
/*
* nconf-hierarchical-load-merge.js: Test fixture for loading and merging nested objects across stores.
*
* (C) 2012, Nodejitsu Inc.
* (C) 2012, Michael Hart
*
*/
var path = require('path'),
nconf = require('../../../lib/nconf');
nconf.argv()
.file(path.join(__dirname, '..', 'merge', 'file1.json'));
process.stdout.write(JSON.stringify({
apples: nconf.get('apples'),
candy: nconf.get('candy')
}));

View file

@ -1,32 +0,0 @@
/*
* nconf-hierarchical-load-save.js: Test fixture for using optimist, envvars and a file store with nconf.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var fs = require('fs'),
path = require('path'),
nconf = require('../../../lib/nconf');
//
// Setup nconf to use (in-order):
// 1. Command-line arguments
// 2. Environment variables
// 3. A file located at 'path/to/config.json'
//
nconf.argv()
.env()
.file({ file: path.join(__dirname, '..', 'load-save.json') });
//
// Set a few variables on `nconf`.
//
nconf.set('database:host', '127.0.0.1');
nconf.set('database:port', 5984);
process.stdout.write(nconf.get('foo'));
//
// Save the configuration object to disk
//
nconf.save();

View file

@ -1,11 +0,0 @@
/*
* nconf-nested-env.js: Test fixture for env with nested keys.
*
* (C) 2012, Nodejitsu Inc.
* (C) 2012, Michael Hart
*
*/
var nconf = require('../../../lib/nconf').env('_');
process.stdout.write(nconf.get('SOME:THING'));

View file

@ -1,12 +0,0 @@
/*
* provider-argv.js: Test fixture for using optimist defaults with nconf.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var nconf = require('../../../lib/nconf');
var provider = new (nconf.Provider)().argv();
process.stdout.write(provider.get('something'));

View file

@ -1,12 +0,0 @@
/*
* provider-argv.js: Test fixture for using process.env defaults with nconf.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var nconf = require('../../../lib/nconf');
var provider = new (nconf.Provider)().env();
process.stdout.write(provider.get('SOMETHING'));

22
test/fixtures/secure-iv.json vendored Normal file
View file

@ -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"
}
}

18
test/fixtures/secure.json vendored Normal file
View file

@ -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"
}
}

28
test/fixtures/store.json vendored Normal file
View file

@ -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"
}
}
}

View file

@ -1,68 +0,0 @@
/*
* helpers.js: Test helpers for nconf.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var assert = require('assert'),
spawn = require('child_process').spawn,
util = require('util'),
fs = require('fs'),
path = require('path'),
nconf = require('../lib/nconf');
exports.assertMerged = function (err, merged) {
merged = merged instanceof nconf.Provider
? merged.store.store
: merged;
assert.isNull(err);
assert.isObject(merged);
assert.isTrue(merged.apples);
assert.isTrue(merged.bananas);
assert.isObject(merged.candy);
assert.isTrue(merged.candy.something1);
assert.isTrue(merged.candy.something2);
assert.isTrue(merged.candy.something3);
assert.isTrue(merged.candy.something4);
assert.isTrue(merged.dates);
assert.isTrue(merged.elderberries);
};
exports.assertSystemConf = function (options) {
return {
topic: function () {
var 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];
});
}
var child = spawn('node', [options.script].concat(options.argv), { env: env });
child.stdout.once('data', this.callback.bind(this, null));
},
"should respond with the value passed into the script": function (_, data) {
assert.equal(data.toString(), 'foobar');
}
}
}
// copy a file
exports.cp = function (from, to, callback) {
fs.readFile(from, function (err, data) {
if (err) return callback(err);
fs.writeFile(to, data, callback);
});
};
exports.fixture = function (file) {
return path.join(__dirname, 'fixtures', file);
};

64
test/helpers.mjs Normal file
View file

@ -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));
};

View file

@ -1,113 +0,0 @@
/*
* hierarchy-test.js: Basic tests for hierarchical file stores.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var assert = require('assert'),
fs = require('fs'),
path = require('path'),
spawn = require('child_process').spawn,
vows = require('vows'),
nconf = require('../lib/nconf');
var configDir = path.join(__dirname, 'fixtures', 'hierarchy'),
globalConfig = path.join(configDir, 'global.json'),
userConfig = path.join(configDir, 'user.json');
vows.describe('nconf/hierarchy').addBatch({
"When using nconf": {
"configured with two file stores": {
topic: function () {
nconf.add('user', { type: 'file', file: userConfig });
nconf.add('global', { type: 'file', file: globalConfig });
nconf.load();
return nconf;
},
"should have the appropriate keys present": function () {
assert.equal(nconf.get('title'), 'My specific title');
assert.equal(nconf.get('color'), 'green');
assert.equal(nconf.get('movie'), 'Kill Bill');
}
},
"configured with two file stores using `file`": {
topic: function () {
nconf.file('user', userConfig);
nconf.file('global', globalConfig);
nconf.load();
return nconf;
},
"should have the appropriate keys present": function () {
assert.equal(nconf.get('title'), 'My specific title');
assert.equal(nconf.get('color'), 'green');
assert.equal(nconf.get('movie'), 'Kill Bill');
}
},
"configured with .argv(), .env() and .file()": {
topic: function () {
var configFile = path.join(__dirname, 'fixtures', 'load-save.json'),
script = path.join(__dirname, 'fixtures', 'scripts', 'nconf-hierarchical-load-save.js'),
argv = ['--foo', 'foo', '--bar', 'bar'],
that = this,
data = '',
child;
try { fs.unlinkSync(configFile) }
catch (ex) { }
child = spawn('node', [script].concat(argv));
child.stdout.on('data', function (d) {
data += d;
});
child.on('exit', function () {
fs.readFile(configFile, 'utf8', that.callback.bind(null, null, data));
});
},
"should not persist information passed in to process.env and process.argv to disk ": function (_, data, _, ondisk){
assert.equal(data, 'foo');
assert.deepEqual(JSON.parse(ondisk), {
database: {
host: '127.0.0.1',
port: 5984
}
});
}
},
"configured with .argv(), .file() and invoked with nested command line options": {
topic: function () {
var script = path.join(__dirname, 'fixtures', 'scripts', 'nconf-hierarchical-load-merge.js'),
argv = ['--candy:something', 'foo', '--candy:something5:second', 'bar'],
that = this,
data = '',
child;
child = spawn('node', [script].concat(argv));
child.stdout.on('data', function (d) {
data += d;
});
child.on('exit', function() {
that.callback(null, data);
});
},
"should merge nested objects ": function (err, data) {
assert.deepEqual(JSON.parse(data), {
apples: true,
candy: {
something: 'foo',
something1: true,
something2: true,
something5: {
first: 1,
second: 'bar'
}
}
});
}
}
}
}).export(module);

56
test/hierarchy.test.mjs Normal file
View 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
}
})
})

View file

@ -1,38 +0,0 @@
/*
* mock-store.js: Mock store for ensuring certain operations are actually called.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var util = require('util'),
events = require('events'),
nconf = require('../../lib/nconf');
var Mock = nconf.Mock = function () {
events.EventEmitter.call(this);
this.type = 'mock';
};
// Inherit from Memory store.
util.inherits(Mock, events.EventEmitter);
//
// ### function save (value, callback)
// #### @value {Object} _Ignored_ Left here for consistency
// #### @callback {function} Continuation to respond to when complete.
// Waits `1000ms` and then calls the callback and emits the `save` event.
//
Mock.prototype.save = function (value, callback) {
if (!callback && typeof value === 'function') {
callback = value;
value = null;
}
var self = this;
setTimeout(function () {
self.emit('save');
callback();
}, 1000);
};

View file

@ -1,107 +0,0 @@
/*
* file-store-test.js: Tests for the nconf File store.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var fs = require('fs'),
path = require('path'),
vows = require('vows'),
assert = require('assert'),
nconf = require('../lib/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');
nconf.load();
assert.instanceOf(nconf.stores['memory'], nconf.Memory);
}
},
"it should": {
topic: function () {
fs.readFile(path.join(__dirname, '..', 'package.json'), this.callback);
},
"have the correct version set": function (err, data) {
assert.isNull(err);
data = JSON.parse(data.toString());
assert.equal(nconf.version, data.version);
}
}
}
}).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": {
"without a callback": {
"should respond with the correct value": function () {
assert.equal(nconf.get('foo:bar:bazz'), 'buzz');
}
},
"with a callback": {
topic: function () {
nconf.get('foo:bar:bazz', this.callback);
},
"should respond with the correct value": function (err, value) {
assert.equal(value, 'buzz');
}
}
}
}
}
}).addBatch({
"When using nconf": {
"with the memory store": {
"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 respond with the merged store": function () {
assert.deepEqual(nconf.load(), {
title: 'My specific title',
color: 'green',
movie: 'Kill Bill'
});
}
},
"with a callback": {
topic: function () {
nconf.load(this.callback.bind(null, null));
},
"should respond with the merged store": function (ign, err, store) {
assert.isNull(err);
assert.deepEqual(store, {
title: 'My specific title',
color: 'green',
movie: 'Kill Bill'
});
}
}
}
}
}
}).export(module);

194
test/nconf.test.mjs Normal file
View file

@ -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')
})
})

View file

@ -1,39 +0,0 @@
/*
* provider-save-test.js: Ensures consistency for Provider `save` operations.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var assert = require('assert'),
vows = require('vows'),
nconf = require('../lib/nconf');
//
// Expose `nconf.Mock`
//
require('./mocks/mock-store');
vows.describe('nconf/provider/save').addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"with a Mock store": {
topic: function () {
return nconf.use('mock');
},
"the save() method": {
topic: function () {
var mock = nconf.stores.mock,
that = this;
mock.on('save', function () { that.saved = true });
nconf.save(this.callback);
},
"should actually save before responding": function () {
assert.isTrue(this.saved);
}
}
}
}
}
}).export(module);

View file

@ -1,165 +0,0 @@
/*
* provider-test.js: Tests for the nconf Provider object.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var assert = require('assert'),
fs = require('fs'),
path = require('path'),
spawn = require('child_process').spawn,
vows = require('vows'),
helpers = require('./helpers'),
nconf = require('../lib/nconf');
var fixturesDir = path.join(__dirname, 'fixtures'),
mergeFixtures = path.join(fixturesDir, 'merge'),
files = [path.join(mergeFixtures, 'file1.json'), path.join(mergeFixtures, 'file2.json')],
override = JSON.parse(fs.readFileSync(files[0]), 'utf8');
function assertProvider(test) {
return {
topic: new nconf.Provider(),
"should use the correct File store": test
};
}
vows.describe('nconf/provider').addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"calling the use() method with the same store type and different options": {
topic: new nconf.Provider().use('file', { file: files[0] }),
"should use a new instance of the store type": function (provider) {
var old = provider.stores['file'];
assert.equal(provider.stores.file.file, files[0]);
provider.use('file', { file: files[1] });
assert.notStrictEqual(old, provider.stores.file);
assert.equal(provider.stores.file.file, files[1]);
}
},
"when 'argv' is true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'provider-argv.js'),
argv: ['--something', 'foobar']
}),
"when 'env' is true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'provider-env.js'),
env: { SOMETHING: 'foobar' }
})
},
"the default nconf provider": {
"when 'argv' is set to true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-argv.js'),
argv: ['--something', 'foobar'],
env: { SOMETHING: true }
}),
"when 'env' is set to true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-env.js'),
env: { SOMETHING: 'foobar' }
}),
"when 'argv' is set to true and process.argv is modified": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-change-argv.js'),
argv: ['--something', 'badValue', 'evenWorse', 'OHNOEZ', 'foobar']
}),
"when hierarchical 'argv' get": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-hierarchical-file-argv.js'),
argv: ['--something', 'foobar'],
env: { SOMETHING: true }
}),
"when 'env' is set to true with a nested separator": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-nested-env.js'),
env: { SOME_THING: 'foobar' }
})
}
}
}).addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"the merge() method": {
topic: new nconf.Provider().use('file', { file: files[1] }),
"should have the result merged in": function (provider) {
provider.load();
provider.merge(override);
helpers.assertMerged(null, provider.stores.file.store);
assert.equal(provider.stores.file.store.candy.something, 'file1');
}
}
}
}
}).addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"the load() method": {
"when sources are passed in": {
topic: new nconf.Provider({
sources: {
user: {
type: 'file',
file: files[0]
},
global: {
type: 'file',
file: files[1]
}
}
}),
"should respect the hierarchy ": function (provider) {
var merged = provider.load();
helpers.assertMerged(null, merged);
assert.equal(merged.candy.something, 'file1');
}
},
"when multiple stores are used": {
topic: new nconf.Provider().overrides({foo: {bar: 'baz'}})
.add('file1', {type: 'file', file: files[0]})
.add('file2', {type: 'file', file: files[1]}),
"should respect the hierarchy": function(provider) {
var merged = provider.load();
helpers.assertMerged(null, merged);
assert.equal(merged.foo.bar, 'baz');
assert.equal(merged.candy.something, 'file1');
}
}
}
}
}
}).addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"the .file() method": {
"with a single filepath": assertProvider(function (provider) {
provider.file(helpers.fixture('store.json'));
assert.isObject(provider.stores.file);
}),
"with a name and a filepath": assertProvider(function (provider) {
provider.file('custom', helpers.fixture('store.json'));
assert.isObject(provider.stores.custom);
}),
"with a single object": assertProvider(function (provider) {
provider.file({
dir: helpers.fixture('hierarchy'),
file: 'store.json',
search: true
});
assert.isObject(provider.stores.file);
assert.equal(provider.stores.file.file, helpers.fixture('store.json'));
}),
"with a name and an object": assertProvider(function (provider) {
provider.file('custom', {
dir: helpers.fixture('hierarchy'),
file: 'store.json',
search: true
});
assert.isObject(provider.stores.custom);
assert.equal(provider.stores.custom.file, helpers.fixture('store.json'));
})
}
}
}
}).export(module);

225
test/provider.test.mjs Normal file
View file

@ -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();
});
});
})
})
})*/
});

View file

@ -1,22 +0,0 @@
/*
* argv-test.js: Tests for the nconf argv store.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var vows = require('vows'),
assert = require('assert'),
helpers = require('../helpers'),
nconf = require('../../lib/nconf');
vows.describe('nconf/stores/argv').addBatch({
"An instance of nconf.Argv": {
topic: new nconf.Argv(),
"should have the correct methods defined": function (argv) {
assert.isFunction(argv.loadSync);
assert.isFunction(argv.loadArgv);
assert.isFalse(argv.options);
}
}
}).export(module);

171
test/stores/argv.test.mjs Normal file
View file

@ -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')
})
})

View file

@ -1,24 +0,0 @@
/*
* env-test.js: Tests for the nconf env store.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var vows = require('vows'),
assert = require('assert'),
helpers = require('../helpers'),
nconf = require('../../lib/nconf');
vows.describe('nconf/stores/env').addBatch({
"An instance of nconf.Env": {
topic: new nconf.Env(),
"should have the correct methods defined": function (env) {
assert.isFunction(env.loadSync);
assert.isFunction(env.loadEnv);
assert.isArray(env.whitelist);
assert.lengthOf(env.whitelist, 0);
assert.equal(env.separator, '');
}
}
}).export(module);

245
test/stores/env.test.mjs Normal file
View file

@ -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]
})
})
})

View file

@ -1,175 +0,0 @@
/*
* file-store-test.js: Tests for the nconf File store.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var fs = require('fs'),
path = require('path'),
vows = require('vows'),
assert = require('assert'),
nconf = require('../../lib/nconf'),
data = require('../fixtures/data').data,
store;
vows.describe('nconf/stores/file').addBatch({
"When using the nconf file store": {
"with a valid JSON file": {
topic: function () {
var filePath = path.join(__dirname, '..', 'fixtures', 'store.json');
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
this.store = store = new nconf.File({ file: filePath });
return null;
},
"the load() method": {
topic: function () {
this.store.load(this.callback);
},
"should load the data correctly": function (err, data) {
assert.isNull(err);
assert.deepEqual(data, this.store.store);
}
}
},
"with a malformed JSON file": {
topic: function () {
var filePath = path.join(__dirname, '..', 'fixtures', 'malformed.json');
this.store = new nconf.File({ file: filePath });
return null;
},
"the load() method with a malformed JSON config file": {
topic: function () {
this.store.load(this.callback.bind(null, null));
},
"should respond with an error": function (_, err) {
assert.isTrue(!!err);
}
}
}
}
}).addBatch({
"When using the nconf file store": {
topic: function () {
var tmpPath = path.join(__dirname, '..', 'fixtures', 'tmp.json'),
tmpStore = new nconf.File({ file: tmpPath });
return tmpStore;
},
"the save() method": {
topic: function (tmpStore) {
var that = this;
Object.keys(data).forEach(function (key) {
tmpStore.set(key, data[key]);
});
tmpStore.save(function () {
fs.readFile(tmpStore.file, function (err, d) {
fs.unlinkSync(tmpStore.file);
return err
? that.callback(err)
: that.callback(err, JSON.parse(d.toString()));
});
});
},
"should save the data correctly": function (err, read) {
assert.isNull(err);
assert.deepEqual(read, data);
}
}
}
}).addBatch({
"When using the nconf file store": {
topic: function () {
var tmpPath = path.join(__dirname, '..', 'fixtures', 'tmp.json'),
tmpStore = new nconf.File({ file: tmpPath });
return tmpStore;
},
"the saveSync() method": {
topic: function (tmpStore) {
var that = this;
Object.keys(data).forEach(function (key) {
tmpStore.set(key, data[key]);
});
var saved = tmpStore.saveSync();
fs.readFile(tmpStore.file, function (err, d) {
fs.unlinkSync(tmpStore.file);
return err
? that.callback(err)
: that.callback(err, JSON.parse(d.toString()), saved);
});
},
"should save the data correctly": function (err, read, saved) {
assert.isNull(err);
assert.deepEqual(read, data);
assert.deepEqual(read, saved);
}
}
}
}).addBatch({
"When using the nconf file store": {
"the set() method": {
"should respond with true": function () {
assert.isTrue(store.set('foo:bar:bazz', 'buzz'));
assert.isTrue(store.set('falsy:number', 0));
assert.isTrue(store.set('falsy:string', ''));
assert.isTrue(store.set('falsy:boolean', false));
assert.isTrue(store.set('falsy:object', null));
}
},
"the get() method": {
"should respond with the correct value": function () {
assert.equal(store.get('foo:bar:bazz'), 'buzz');
assert.equal(store.get('falsy:number'), 0);
assert.equal(store.get('falsy:string'), '');
assert.equal(store.get('falsy:boolean'), false);
assert.equal(store.get('falsy:object'), null);
}
},
"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');
}
}
}
}).addBatch({
"When using the nconf file store": {
"the search() method": {
"when the target file exists higher in the directory tree": {
topic: function () {
var filePath = this.filePath = path.join(process.env.HOME, '.nconf');
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
return new (nconf.File)({
file: '.nconf'
})
},
"should update the file appropriately": function (store) {
store.search();
assert.equal(store.file, this.filePath);
fs.unlinkSync(this.filePath);
}
},
"when the target file doesn't exist higher in the directory tree": {
topic: function () {
var filePath = this.filePath = path.join(__dirname, '..', 'fixtures', 'search-store.json');
return new (nconf.File)({
dir: path.dirname(filePath),
file: 'search-store.json'
})
},
"should update the file appropriately": function (store) {
store.search();
assert.equal(store.file, this.filePath);
}
}
}
}
}).export(module);

250
test/stores/file.test.mjs Normal file
View file

@ -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)
})
*/

View file

@ -1,31 +0,0 @@
/*
* literal-test.js: Tests for the nconf literal store.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var vows = require('vows'),
assert = require('assert'),
helpers = require('../helpers'),
nconf = require('../../lib/nconf');
vows.describe('nconf/stores/literal').addBatch({
"An instance of nconf.Literal": {
topic: new nconf.Literal({
foo: 'bar',
one: 2
}),
"should have the correct methods defined": function (literal) {
assert.equal(literal.type, 'literal');
assert.isFunction(literal.get);
assert.isFunction(literal.set);
assert.isFunction(literal.merge);
assert.isFunction(literal.loadSync);
},
"should have the correct values in the store": function (literal) {
assert.equal(literal.store.foo, 'bar');
assert.equal(literal.store.one, 2);
}
}
}).export(module);

View file

@ -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')
})
})

View file

@ -1,84 +0,0 @@
/*
* memory-store-test.js: Tests for the nconf Memory store.
*
* (C) 2011, Nodejitsu Inc.
*
*/
var vows = require('vows'),
assert = require('assert'),
nconf = require('../../lib/nconf'),
merge = require('../fixtures/data').merge;
vows.describe('nconf/stores/memory').addBatch({
"When using the nconf memory store": {
topic: new nconf.Memory(),
"the set() method": {
"should respond with true": function (store) {
assert.isTrue(store.set('foo:bar:bazz', 'buzz'));
assert.isTrue(store.set('falsy:number', 0));
assert.isTrue(store.set('falsy:string', ''));
assert.isTrue(store.set('falsy:boolean', false));
assert.isTrue(store.set('falsy:object', null));
}
},
"the get() method": {
"should respond with the correct value": function (store) {
assert.equal(store.get('foo:bar:bazz'), 'buzz');
assert.equal(store.get('falsy:number'), 0);
assert.equal(store.get('falsy:string'), '');
assert.equal(store.get('falsy:boolean'), false);
assert.equal(store.get('falsy:object'), null);
},
"should not fail when retrieving non-existent keys": function (store) {
assert.doesNotThrow(function() {
assert.equal(store.get('this:key:does:not:exist'), undefined);
}, TypeError);
},
"should not fail when drilling into non-objects": function (store) {
assert.doesNotThrow(function() {
assert.equal(store.get('falsy:number:uh:oh'), undefined);
}, TypeError);
}
},
"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');
}
},
"the merge() method": {
"when overriding an existing literal value": function (store) {
store.set('merge:literal', 'string-value');
store.merge('merge:literal', merge);
assert.deepEqual(store.get('merge:literal'), merge);
},
"when overriding an existing Array value": function (store) {
store.set('merge:array', [1,2,3,4]);
store.merge('merge:array', merge);
assert.deepEqual(store.get('merge:literal'), merge);
},
"when merging into an existing Object value": function (store) {
store.set('merge:object', {
prop1: 2,
prop2: 'prop2',
prop3: {
bazz: 'bazz'
},
prop4: ['foo', 'bar']
});
store.merge('merge:object', merge);
assert.equal(store.get('merge:object:prop1'), 1);
assert.equal(store.get('merge:object:prop2').length, 3);
assert.deepEqual(store.get('merge:object:prop3'), {
foo: 'bar',
bar: 'foo',
bazz: 'bazz'
});
assert.equal(store.get('merge:object:prop4').length, 2);
}
}
}
}).export(module);

379
test/stores/memory.test.mjs Normal file
View file

@ -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)
})
})
})

View file

@ -1,50 +0,0 @@
var fs = require('fs'),
path = require('path'),
nconf = require('./lib/nconf');
//
// Configure the provider with a single store and
// support for command-line arguments and environment
// variables.
//
var single = new nconf.Provider({
env: true,
argv: true,
store: {
type: 'file',
file: path.join(__dirname, 'config.json')
}
});
//
// Configure the provider with multiple hierarchical stores
// representing `user` and `global` configuration values.
//
var multiple = new nconf.Provider({
stores: [
{ name: 'user', type: 'file', file: path.join(__dirname, 'user-config.json') },
{ name: 'global', type: 'global', file: path.join(__dirname, 'global-config.json') }
]
});
//
// Setup nconf to use 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()))
});
});