pax_global_header00006660000000000000000000000064141346130660014516gustar00rootroot0000000000000052 comment=98f2fc9bd634f6dab61bc1a0003de4dbf8f9a9ad node-config-3.3.7/000077500000000000000000000000001413461306600137205ustar00rootroot00000000000000node-config-3.3.7/.editorconfig000066400000000000000000000000271413461306600163740ustar00rootroot00000000000000[*.js] indent_size = 2 node-config-3.3.7/.gitignore000066400000000000000000000000511413461306600157040ustar00rootroot00000000000000.project node_modules npm-debug.log .ideanode-config-3.3.7/.npmignore000066400000000000000000000000551413461306600157170ustar00rootroot00000000000000node_modules test tools ISSUE_TEMPLATE.md .* node-config-3.3.7/.npmrc000066400000000000000000000001301413461306600150320ustar00rootroot00000000000000# Prevent accidental publish to private repository registry=https://registry.npmjs.org/ node-config-3.3.7/.travis.yml000066400000000000000000000001611413461306600160270ustar00rootroot00000000000000language: node_js sudo: false before_install: - npm update -g npm node_js: - "10" - "12" - "14" - "15" node-config-3.3.7/History.md000066400000000000000000000453421413461306600157130ustar00rootroot000000000000003.3.6 / 2021-03-08 ================== * Added publishConfig element to package.json to prevent publishing to the wrong repository - @lorenwest 3.3.5 / 2021-03-05 ================== * FIX [#628](https://github.com/lorenwest/node-config/issues/628) Uncaught ReferenceError: node_env_var_name is not defined @prnake 3.3.4 / 2021-02-26 ================== * FIX #517 0 loadFileConfigs incorrectly adds to getConfigSources @NguyenMatthieu 3.3.3 / 2020-11-26 ================== * FIX #460 - Strict mode warning refer to appropriate env variable @iCodeOkay * Use Buffer.alloc and Buffer.from instead of contrsuctor @Fcmam5 * Add support for experimental .cjs modules @lenkan 3.3.2 / 2020-09-24 ================== * Fixed issue with Buffers in config throwing error in util.makeImmutable (#608) - Michal Wadas * Added boolean and numeric types to custom environment variables - Ankur Narkhede @ankurnarkhede 3.3.1 / 2020-03-25 ================== * Fix security vulnerability in json5 dependency - @twkel 3.3.0 / 2020-02-26 ================== * Allow all defined values in `substituteDeep` - @fostyfost 3.2.6 / 2020-02-21 ================== * Updated copyright date ranges 3.2.5 / 2020-01-16 ================== * Fixed issue with getCustomEnvVars and multiple config dirs #585 - @dekelev 3.2.4 / 2019-10-25 ================== * Improved error handling of env variables value parse - @leonardovillela 3.2.3 / 2019-10-03 ================== * Fixed strict mode warning #460 - @fedulovivan 3.2.2 / 2019-07-20 ================== * Fixed delimiter bug in configDirs to match O/S delimiter - @iMoses 3.2.1 / 2019-07-18 ================== * Fixed TypeError: obj.toString is not a function - @leosuncin 3.2.0 / 2019-07-11 ================== * Asynchronous configs - @iMoses * Multiple config directories - @iMoses * Improved parser support - @iMoses 3.1.0 / 2019-04-07 ================== * Support of module.exports syntax for TS config files @keenondrums 3.0.1 / 2018-12-16 ================== * Fixed bug where dot notation extended own key @exogen 3.0.0 / 2018-11-20 ================== * Ensure config array items and objects are sealed @fgheorghe - This required a major version bump in case someone - relied on the ability to mutate non-sealed data. 2.0.2 / 2018-08-28 ================== * Added dot notation to setModuleDefaults - bertho-zero * Updated copyright year - JemiloII 2.0.1 / 2018-07-26 ================== * Removed deprecated code - jpwilliams 2.0.0 / 2018-07-26 ================== Potential for backward incompatibility requiring a major version bump. Safe to upgrade to major version 2 if you're using a recent NodeJS version and you're not trying to mutate config arrays. * Added array immutability - jacobemerick * Removed Node V.4 support 1.31.0 / 2018-05-22 =================== * Load new coffeescript module instead of coffee-script - bastbijl 1.30.0 / 2018-02-26 =================== * Support for nested raw() in javascript configurations - patrickpilch 1.29.4 / 2018-02-03 =================== * Re-publish - last changes didn't make it to npm 1.29.3 / 2018-02-03 =================== * Added soft dependencies so transpilers don't include everything - gewentao 1.29.2 / 2018-01-12 =================== * Patch, and added a test to ts-node - electroma 1.29.1 / 2018-01-07 =================== * Prevent re-registration of ts-node - electroma * Fixed bug in contributor table tool - lorenwest 1.29.0 / 2017-12-26 =================== * Update docs for JavaScript-formatted config files and link them from the README - markstos * Fixed 'hostname' value selection when there is no environment variable for that - wmangelardo 1.28.1 / 2017-11-09 =================== * add nodejs9 to travisci - jfelege 1.28.0 / 2017-11-07 =================== * allow overrides of `NODE_ENV` with `NODE_CONFIG_ENV` - jfelege 1.27.0 / 2017-10-17 =================== * Add method to output plain JS object - willsoto * Updated Node versions in Travis CI - lorenwest 1.26.2 / 2017-08-11 =================== * Update supported nodejs platforms - jfelege 1.26.1 / 2017-05-03 =================== * Fix: failed while merging from RegExp @XadillaX * Chore: reduce package size. @evilebottnawi 1.26.0 / 2017-03-30 =================== * Added tests for extendDeep @IvanVergiliev * Added TypeScript support @cypherq * Update config.js with correctly cased type def @ScionOfBytes 1.25.1 / 2017-02-01 =================== * Fixed undefined CONFIG_SKIP_GITCRYPT variable @lorenwest 1.25.0 / 2017-01-31 =================== * Add support for configuration files stored with git-crypt @cunneen 1.24.0 / 2016-11-02 =================== * Prevent accidental publish to private repository 1.23.0 / 2016-11-02 =================== * Re-publishing because npmjs didn't see 1.22 1.22.0 / 2016-10-25 =================== * original/previous value for deferredConfig @simon-scherzinger * util.loadFileConfigs: support optional source dir @wmertens * Adding raw wrapper to prevent object modification in config @patrickpilch 1.21.0 / 2016-06-01 =================== * Added XML configuration @tusharmath 1.20.4 / 2016-05-23 =================== * Fixed a regression with extending prototype methods @tahoemph 1.20.3 / 2016-05-18 =================== * Fixed a regression with 1.20.2 @kgoerlitz * Added test to prevent this in the future @kgoerlitz 1.20.2 / 2016-05-17 =================== * node v6 compatiblity: remove deprecated __lookupGetter__ use - @thetalecrafter * node v6 compatiblity: handle different SyntaxError format - @pwwolf 1.20.1 / 2016-04-08 =================== * Simplify truthiness check - @markstos * Remove errant console.log - @markstos 1.20.0 / 2016-04-06 =================== * Typo fix @jchip * Handle null sub-object @wmertens * Bug fix for NODE_CONFIG_STRICT_MODE check @markstos * Ran node security check on 4/6/2016 with the following output $ nsp check (+) No known vulnerabilities found 1.19.0 / 2016-01-08 =================== * Resolve defered values in predictable order for consistent results. Fixes #265 @elliotttf @markstos 1.18.0 / 2015-11-17 =================== * More robust handling of JSON @elliotttf 1.17.1 / 2015-11-17 =================== * Patch release for regex bugfix 1.17.0 / 2015-11-17 =================== * Update warning about missing configuration files to mention how to disable the warning #245 @markstos * Upgrade to run CI with travis containers @lorenwest * Fixed bug with comments and inline json @elliotttf 1.16.0 / 2015-09-03 =================== * Change == to === to tighten equality tests #242 @wgpsutherland * Fix attachProtoDeep for setModuleDefaults #243 @benkroeger 1.15.0 / 2015-07-30 =================== * Added full hostname in addition to first segment @vicary 1.14.0 / 2015-06-02 =================== * Added JSON parsing to custom environment variables @leachiM2k * Handle unicode BOM characters @johndkane 1.13.0 / 2015-05-05 =================== * Updated CSON library @dsimidzija 1.12.0 / 2015-02-19 =================== * Better date merging @axelhzf 1.11.0 / 2015-01-14 =================== * Added Hjson support @laktak 1.10.0 / 2015-01-06 =================== * Added TOML support (@jasonhansel) * Another year - changed copyright messages for 2015 * Updated contributors list * New Strict Mode added in 1.9.0 is now documented. (@markstos) * has() now returns false when given an undefined or null key to look up. Previously it threw an exception. (@markstos) * When get() is given an undefined or null key to look up, it now throws a more helpful diagnostic (@robludwig, @markstos) 1.9.0 / 2014-12-08 ================== * New strictness checks have been added to ensure the expected configuration has been loaded. Warnings are now thrown in these cases. If NODE_CONFIG_STRICT_MODE is set, exceptions are thrown instead. (@markstos) * There must be an explicit config file matching `NODE_ENV` if `NODE_ENV` is set. * There must be an explicit config file matching `NODE_APP_INSTANCE` if `NODE_APP_INSTANCE` is set * `NODE_ENV` must not match 'default' or 'local' to avoid ambiguity. * Added .iced extension support (@arthanzel) * Highlight `config.has()` in the README. Use it to check to if a value exists, since `config.get()` throws exceptions on undefined values. (@markstos) * API Change: getConfigSources() now starts to return data on config files that are valid-but-empty. (@markstos) 1.8.1 / 2014-11-14 ================== * Simplify syntax for defer() functions. The 'this' value in the functions is now bound to the main configuration object, so it doesn't have to be passed into the function. (@markstos) * new defer sub-module introduced in 1.8.0 can now be accessed by require('config/defer') For usage, see: https://github.com/lorenwest/node-config/wiki/Configuration-Files#javascript-module---js * Add test coverage for array merging cases. (@markstos) * Bump dependency on cson package to 1.6.1 (@markstos) 1.8.0 / 2014-11-13 ================== * Added deferred function for evaluating configs after load (@markstos) For details, see: https://github.com/lorenwest/node-config/wiki/Configuration-Files#javascript-module---js * Bumped js-yaml dependency (@markstos) 1.7.0 / 2014-10-30 ================== * Added variable substitution in .properties files (@ncuillery) 1.6.0 / 2014-10-22 ================== * Added support for property accessors in configs (@jaylynch) 1.5.0 / 2014-10-20 ================== * Added support for .json5 config files (@bertrandom) 1.4.0 / 2014-10-16 ================== * Added support for .properties config files (@superoven) 1.3.0 / 2014-10-15 ================== * Added support for CSON configuration files (@superoven) 1.2.4 / 2014-10-10 ================== * Repaired the 1.2.3 fix to work both before and after the first get() 1.2.3 / 2014-10-03 ================== * Changed test suite to verify a bug in util.setModuleDefaults() * Fixed util.setModuleDefaults() to work after a get() (and pass the new test) 1.2.2 / 2014-10-03 ================== * Added support for regexp and date configurations (@diversario) 1.2.1 / 2014-09-23 ================== * Wrote test to prove setModuleDefaults() was broken in 1.2.0 * Fixed setModuleDefaults() to not rely on immutable configs 1.2.0 / 2014-09-15 ================== * Feature release * Delaying immutability until after first get() - for external configs * Allowing immutability override with $ALLOW_CONFIG_MUTATIONS=Y 1.1.1 / 2014-09-03 ================== * @th507 - Update support for Coffee-script >=1.7.0 1.1.0 / 2014-09-03 ================== * Feature release * @bradboro - Custom environment variables * @supersheep - Catch error when requiring visionmedia yaml module 1.0.2 / 2014-07-30 =================== * @bradobro - Fixed a variable from leaking into global * @tilfin - Removed un-necessary YAML comment filtering for js-yaml 1.0.1 / 2014-07-25 =================== * Removed test directory from npm install 1.0.0 / 2014-07-23 =================== * Major revision. Upgrade notes: https://github.com/lorenwest/node-config/wiki/Upgrading-From-Config-0.x * Update to semver versioning * Change load ordering from hostname.EXT --> deployment.EXT to deployment.EXT --> hostname.EXT * Allow makeImmutable to accept an array of attributes * Allow makeImmutable to accept no attrs, making all attributes immutable * Allow recursion in makeImmutable, if an attribute is an object * Change node-config behavior to make all configurations immutable * Removed getOriginalConfig as no longer necessary post-immutable * Removed runtime.json file writing and monitoring * Removed previously deprecated $CONFIG_* environment configurations * Deprecated the attribute watch functionality * Added error output if no configurations found * Exposed config loading for alternate configurations * Added config.get() and config.has() methods & tests * Removed reliance on global.NODE_CONFIG so older versions can work with 1.x * Fix empty YAML file causing crash with latest js-yaml * Added SUPPRESS_NO_CONFIG_WARNING for better sub-module support * Moved all documentation [to the wiki](https://github.com/lorenwest/node-config/wiki). 0.4.37 / 2014-07-22 =================== * Fix empty YAML file causing crash with latest js-yaml 0.4.36 / 2014-05-27 =================== * Not writing runtime.json if not used 0.4.35 / 2014-01-16 =================== * NODE_CONFIG_DIR can now contain a relative path for .js and .coffee configurations 0.4.34 / 2014-01-06 =================== * Updated copyright year 0.4.33 / 2013-10-25 =================== * Assure writes to runtime.json are atomic 0.4.32 / 2013-10-24 =================== * Don't freak out if running without a config directory * Don't be so chatty if runtime.json doesn't exist 0.4.31 / 2013-10-18 =================== * Changed getConfigSources to copy array vs. object 0.4.30 / 2013-09-12 =================== * More consistent array extension * No longer requiring a config directory * Not erroneously writing runtime.json * Exposing the original configuration sources * Added --NODE_CONFIG={json} command line overrides * Added $NODE_CONFIG={json} environment variable overrides * Consistent handling of environment variables and command line parameters * Reached 100 regression tests 0.4.29 / 2013-08-07 =================== * Added flag for disabling the write of runtime.json 0.4.28 / 2013-07-31 =================== * Eliminated a totally annoying install warning in newer versions of NPM 0.4.27 / 2013-06-18 =================== * Fixed a bug preventing double underscores in config environment variables 0.4.26 / 2013-06-10 =================== * Re-watch file on rename (allows editing runtime.json with vi) * Allow runtime.json file watch disable via NODE_CONFIG_DISABLE_FILE_WATCH=Y * Change no yaml parser error message to suggest using js-yaml * Changed default clone depth from 6 to 20 to allow for deeper configurations 0.4.25 / 2013-05-24 =================== * Dont fail if config directory doesnt exist 0.4.24 / 2013-04-13 =================== * Added resetRuntime() to reset the runtime.json file * Updated docs to reflect the new public method 0.4.23 / 2013-04-13 =================== * Multiple application instance support via $NODE_APP_INSTANCE * Multi-app testing & documentation 0.4.22 / 2013-03-29 =================== * Added configuration $CONFIG_* environment variables * Added $CONFIG_* documentation and tests * Added NodeJS 0.10 integration test 0.4.21 / 2013-03-06 =================== * Triggering file.watch when an editor saves a file - rename vs. change * Installed Travis-CI continuous integration testing framework 0.4.20 / 2013-02-21 =================== * Merged _diffDeep fix 0.4.19 / 2013-02-21 =================== * Added discovery of .yml in addition to .yaml for YAML configs (w/doc) * Added testing of .yml file discovery * Removed licensing inconsistencies 0.4.18 / 2012-10-30 =================== * Moved coffee-script and js-yaml from optionalDependencies back to devDependencies to trim the install size for those not needing these packages. * Promoted $HOSTNAME and $HOST above OS.hostname() 0.4.17 / 2012-09-26 =================== * Allow the location of runtime.json to be picked up from the environment * Added documentation for the NODE_CONFIG_RUNTIME_JSON environment variable * package.json cleanup - created optionalDependencies and devDependencies 0.4.16 / 2012-08-09 =================== * Allowing a zero interval in watchForConfigFileChanges() to disable file watching. * Fixed a comparator bug in _equalsDeep() * Added a test to confirm deep extending array functionality 0.4.15 / 2012-06-04 =================== * Placed YAML and Coffee-Script libraries back into the download. Still lazy loading into memory. 0.4.14 / 2012-06-01 =================== * Added the local.EXT and local-deployment.EXT configs. * Removed unnecessary debug output * Added retry logic on file parse to reduce read/write collisions * Added support for a better YAML parser * Fixed problems with null configuration values 0.4.13 / 2012-04-25 =================== * Assuring the runtime.json file exists. Undocumented fs.watch() requirement. 0.4.12 / 2012-04-25 =================== * Removed all external dependencies * Lazy loading of yaml and coffee-script only if these file types are used * Added new style file watching if available (retaining pre 6.0 compatibility) * Windows compatibility - file watching changes were required 0.4.11 / 2012-02-15 =================== * Automatically watching runtime.json for changes * Fixed a date comparison bug during file watching * Changed require('sys') to require('util') 0.4.10 / 2012-01-18 =================== * Made sure the CONFIG object is a shared singleton * Added NODE_CONFIG_DIR environment variable to point to a different directory * Added tests and documentation for the above 0.4.9 / 2012-01-06 ================== * Added coffee-script file type support with extension .coffee * Added an example coffee-script configuration file * Added coffee-script module dependency * Added a test for coffee-script configuration files * Documented coffee-script support, regenerated documentation 0.4.8 / 2011-12-20 ================== * Fixed a bug where changes to module default configs weren't persisted * Added a test to validate the bugfix 0.4.7 / 2011-12-16 ================== * Created the makeHidden method to hide a property of an object * Added a value argument to makeImmutable for creating new properties * Fixed setModuleDefaults to hide injected prototype methods * Added documentation and unit tests 0.4.6 / 2011-11-29 ================== * Updated vows from 0.5.8 to 0.5.13 0.4.5 / 2011-11-16 ================== * Updated YAML dependency from "0.1.x" to ">=0.2.2" * Added stripping of comment-only and whitespace-only lines in YAML files for backward compatibility * Added more tests for YAML edge cases * Added a homepage link in package.json to the online documentation * Added History.md 0.4.4 / 2011-11-08 ================== * Removed deprecated modules from package.json 0.4.3 / 2011-08-02 ================== * Made watchForConfigFileChanges public 0.4.2 / 2011-07-11 ================== * Added comment stripping from JSON configuration files 0.4.1 / 2011-07-07 ================== * Added more tests * Return the module config in setModuleDefaults 0.4.0 / 2011-07-06 ================== * Update to version 0.4.0 * Online documentation * Runtime configuration changes * Configuration value watching * Multi-instance node deployments * Better module developer support node-config-3.3.7/ISSUE_TEMPLATE.md000066400000000000000000000017551413461306600164350ustar00rootroot00000000000000**Note: for support questions, please use [StackOverflow](https://stackoverflow.com/questions/tagged/node-config) and tag your question with `node-config`**. *This repository's issues are reserved for feature requests and bug reports.* Before submitting a bug report, please search the issue tracker the wiki first. Many issues have already been discussed. The wiki is located at: https://github.com/lorenwest/node-config/wiki ### I'm submitting a ... - [ ] bug report - [ ] feature request - [ ] support request or question => Please do not submit support request or questions here, see note at the top of this template. ### What is the current behavior? *If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem*: ### What is the expected behavior? ### Please tell us about your environment: - node-config version: x.x.x - node-version: x.x.x ### Other information (e.g. are you using an environment besides Node.js?) node-config-3.3.7/LICENSE000066400000000000000000000021531413461306600147260ustar00rootroot00000000000000// Copyright 2010-2020, Loren West and other contributors // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. node-config-3.3.7/README.md000066400000000000000000000223471413461306600152070ustar00rootroot00000000000000Configure your Node.js Applications =================================== [![NPM](https://nodei.co/npm/config.svg?downloads=true&downloadRank=true)](https://nodei.co/npm/config/)   [![Build Status](https://secure.travis-ci.org/lorenwest/node-config.svg?branch=master)](https://travis-ci.org/lorenwest/node-config)   [release notes](https://github.com/lorenwest/node-config/blob/master/History.md) Introduction ------------ Node-config organizes hierarchical configurations for your app deployments. It lets you define a set of default parameters, and extend them for different deployment environments (development, qa, staging, production, etc.). Configurations are stored in [configuration files](https://github.com/lorenwest/node-config/wiki/Configuration-Files) within your application, and can be overridden and extended by [environment variables](https://github.com/lorenwest/node-config/wiki/Environment-Variables), [command line parameters](https://github.com/lorenwest/node-config/wiki/Command-Line-Overrides), or [external sources](https://github.com/lorenwest/node-config/wiki/Configuring-from-an-External-Source). This gives your application a consistent configuration interface shared among a [growing list of npm modules](https://www.npmjs.org/browse/depended/config) also using node-config. Project Guidelines ------------------ * *Simple* - Get started fast * *Powerful* - For multi-node enterprise deployment * *Flexible* - Supporting multiple config file formats * *Lightweight* - Small file and memory footprint * *Predictable* - Well tested foundation for module and app developers Quick Start --------------- The following examples are in JSON format, but configurations can be in other [file formats](https://github.com/lorenwest/node-config/wiki/Configuration-Files#file-formats). **Install in your app directory, and edit the default config file.** ```shell $ npm install config $ mkdir config $ vi config/default.json ``` ```js { // Customer module configs "Customer": { "dbConfig": { "host": "localhost", "port": 5984, "dbName": "customers" }, "credit": { "initialLimit": 100, // Set low for development "initialDays": 1 } } } ``` **Edit config overrides for production deployment:** ```shell $ vi config/production.json ``` ```json { "Customer": { "dbConfig": { "host": "prod-db-server" }, "credit": { "initialDays": 30 } } } ``` **Use configs in your code:** ```js const config = require('config'); //... const dbConfig = config.get('Customer.dbConfig'); db.connect(dbConfig, ...); if (config.has('optionalFeature.detail')) { const detail = config.get('optionalFeature.detail'); //... } ``` `config.get()` will throw an exception for undefined keys to help catch typos and missing values. Use `config.has()` to test if a configuration value is defined. **Start your app server:** ```shell $ export NODE_ENV=production $ node my-app.js ``` Running in this configuration, the `port` and `dbName` elements of `dbConfig` will come from the `default.json` file, and the `host` element will come from the `production.json` override file. Articles -------- * [Configuration Files](https://github.com/lorenwest/node-config/wiki/Configuration-Files) * [Special features for JavaScript configuration files](https://github.com/lorenwest/node-config/wiki/Special-features-for-JavaScript-configuration-files) * [Common Usage](https://github.com/lorenwest/node-config/wiki/Common-Usage) * [Environment Variables](https://github.com/lorenwest/node-config/wiki/Environment-Variables) * [Reserved Words](https://github.com/lorenwest/node-config/wiki/Reserved-Words) * [Command Line Overrides](https://github.com/lorenwest/node-config/wiki/Command-Line-Overrides) * [Multiple Node Instances](https://github.com/lorenwest/node-config/wiki/Multiple-Node-Instances) * [Sub-Module Configuration](https://github.com/lorenwest/node-config/wiki/Sub-Module-Configuration) * [Configuring from a DB / External Source](https://github.com/lorenwest/node-config/wiki/Configuring-from-an-External-Source) * [Securing Production Config Files](https://github.com/lorenwest/node-config/wiki/Securing-Production-Config-Files) * [External Configuration Management Tools](https://github.com/lorenwest/node-config/wiki/External-Configuration-Management-Tools) * [Examining Configuration Sources](https://github.com/lorenwest/node-config/wiki/Examining-Configuration-Sources) * [Using Config Utilities](https://github.com/lorenwest/node-config/wiki/Using-Config-Utilities) * [Upgrading from Config 0.x](https://github.com/lorenwest/node-config/wiki/Upgrading-From-Config-0.x) * [Webpack usage](https://github.com/lorenwest/node-config/wiki/Webpack-Usage) Further Information --------------------- If you still don't see what you are looking for, here are some more resources to check: * The [wiki may have more pages](https://github.com/lorenwest/node-config/wiki) which are not directly linked from here. * Review [questions tagged with node-config](https://stackexchange.com/filters/207096/node-config) on StackExchange. These are monitored by `node-config` contributors. * [Search the issue tracker](https://github.com/lorenwest/node-config/issues). Hundreds of issues have already been discussed and resolved there. Contributors ------------
lorenwest markstos iMoses elliotttf jfelege leachiM2k
josx enyo leosuncin arthanzel eheikes th507
Osterjour cunneen nsabovic BadgerBadgerBadgerBadger simon-scherzinger leonardovillela
axelhzf benkroeger fgheorghe IvanVergiliev jpwilliams jaylynch
jberrisch kgoerlitz bertho-zero NguyenMatthieu nitzan-shaked robertrossmann
License ------- May be freely distributed under the [MIT license](https://raw.githubusercontent.com/lorenwest/node-config/master/LICENSE). Copyright (c) 2010-2020 Loren West [and other contributors](https://github.com/lorenwest/node-config/graphs/contributors) node-config-3.3.7/async.js000066400000000000000000000046301413461306600153760ustar00rootroot00000000000000var asyncSymbol = Symbol('asyncSymbol'); var deferConfig = require('./defer').deferConfig; /** * @param promiseOrFunc the promise will determine a property's value once resolved * can also be a function to defer which resolves to a promise * @returns {Promise} a marked promise to be resolve later using `resolveAsyncConfigs` */ function asyncConfig(promiseOrFunc) { if (typeof promiseOrFunc === 'function') { // also acts as deferConfig return deferConfig(function (config, original) { var release; function registerRelease(resolve) { release = resolve; } function callFunc() { return promiseOrFunc.call(config, config, original); } var promise = asyncConfig(new Promise(registerRelease).then(callFunc)); promise.release = release; return promise; }); } var promise = promiseOrFunc; promise.async = asyncSymbol; promise.prepare = function(config, prop, property) { if (promise.release) { promise.release(); } return function() { return promise.then(function(value) { Object.defineProperty(prop, property, {value: value}); }); }; }; return promise; } /** * Do not use `config.get` before executing this method, it will freeze the config object * @param config the main config object, returned from require('config') * @returns {Promise} once all promises are resolved, return the original config object */ function resolveAsyncConfigs(config) { var promises = []; var resolvers = []; (function iterate(prop) { var propsToSort = []; for (var property in prop) { if (Object.hasOwnProperty.call(prop, property) && prop[property] != null) { propsToSort.push(property); } } propsToSort.sort().forEach(function(property) { if (prop[property].constructor === Object) { iterate(prop[property]); } else if (prop[property].constructor === Array) { prop[property].forEach(iterate); } else if (prop[property] && prop[property].async === asyncSymbol) { resolvers.push(prop[property].prepare(config, prop, property)); promises.push(prop[property]); } }); })(config); return Promise.all(promises).then(function() { resolvers.forEach(function(resolve) { resolve(); }); return config; }); } module.exports.asyncConfig = asyncConfig; module.exports.resolveAsyncConfigs = resolveAsyncConfigs; node-config-3.3.7/defer.js000066400000000000000000000016361413461306600153510ustar00rootroot00000000000000// Create a deferredConfig prototype so that we can check for it when reviewing the configs later. function DeferredConfig() {} DeferredConfig.prototype.prepare = function() {}; DeferredConfig.prototype.resolve = function() {}; // Accept a function that we'll use to resolve this value later and return a 'deferred' configuration value to resolve it later. function deferConfig(func) { var obj = Object.create(DeferredConfig.prototype); obj.prepare = function(config, prop, property) { var original = prop[property]._original; obj.resolve = function() { var value = func.call(config, config, original); Object.defineProperty(prop, property, {value: value}); return value; }; Object.defineProperty(prop, property, {get: function() { return obj.resolve(); }}); return obj; }; return obj; } module.exports.deferConfig = deferConfig; module.exports.DeferredConfig = DeferredConfig; node-config-3.3.7/lib/000077500000000000000000000000001413461306600144665ustar00rootroot00000000000000node-config-3.3.7/lib/config.js000066400000000000000000001354141413461306600163010ustar00rootroot00000000000000// config.js (c) 2010-2020 Loren West and other contributors // May be freely distributed under the MIT license. // For further details and documentation: // http://lorenwest.github.com/node-config // Dependencies var deferConfig = require('../defer').deferConfig, DeferredConfig = require('../defer').DeferredConfig, RawConfig = require('../raw').RawConfig, Parser = require('../parser'), Utils = require('util'), Path = require('path'), FileSystem = require('fs'); // Static members var DEFAULT_CLONE_DEPTH = 20, NODE_CONFIG, CONFIG_DIR, RUNTIME_JSON_FILENAME, NODE_ENV, APP_INSTANCE, HOST, HOSTNAME, ALLOW_CONFIG_MUTATIONS, CONFIG_SKIP_GITCRYPT, NODE_ENV_VAR_NAME, NODE_CONFIG_PARSER, env = {}, privateUtil = {}, deprecationWarnings = {}, configSources = [], // Configuration sources - array of {name, original, parsed} checkMutability = true, // Check for mutability/immutability on first get gitCryptTestRegex = /^.GITCRYPT/; // regular expression to test for gitcrypt files. /** *

Application Configurations

* *

* The config module exports a singleton object representing all * configurations for this application deployment. *

* *

* Application configurations are stored in files within the config directory * of your application. The default configuration file is loaded, followed * by files specific to the deployment type (development, testing, staging, * production, etc.). *

* *

* For example, with the following config/default.yaml file: *

* *
 *   ...
 *   customer:
 *       initialCredit: 500
 *       db:
 *           name: customer
 *           port: 5984
 *   ...
 * 
* *

* The following code loads the customer section into the CONFIG variable: *

* *

 *   var CONFIG = require('config').customer;
 *   ...
 *   newCustomer.creditLimit = CONFIG.initialCredit;
 *   database.open(CONFIG.db.name, CONFIG.db.port);
 *   ...
 * 
* * @module config * @class Config */ /** *

Get the configuration object.

* *

* The configuration object is a shared singleton object within the application, * attained by calling require('config'). *

* *

* Usually you'll specify a CONFIG variable at the top of your .js file * for file/module scope. If you want the root of the object, you can do this: *

*
 * var CONFIG = require('config');
 * 
* *

* Sometimes you only care about a specific sub-object within the CONFIG * object. In that case you could do this at the top of your file: *

*
 * var CONFIG = require('config').customer;
 * or
 * var CUSTOMER_CONFIG = require('config').customer;
 * 
* * * * @method constructor * @return CONFIG {object} - The top level configuration object */ var Config = function() { var t = this; // Bind all utility functions to this for (var fnName in util) { if (typeof util[fnName] === 'function') { util[fnName] = util[fnName].bind(t); } } // Merge configurations into this util.extendDeep(t, util.loadFileConfigs()); util.attachProtoDeep(t); // Perform strictness checks and possibly throw an exception. util.runStrictnessChecks(t); }; /** * Utilities are under the util namespace vs. at the top level */ var util = Config.prototype.util = {}; /** * Underlying get mechanism * * @private * @method getImpl * @param object {object} - Object to get the property for * @param property {string|string[]} - The property name to get (as an array or '.' delimited string) * @return value {*} - Property value, including undefined if not defined. */ var getImpl= function(object, property) { var t = this, elems = Array.isArray(property) ? property : property.split('.'), name = elems[0], value = object[name]; if (elems.length <= 1) { return value; } // Note that typeof null === 'object' if (value === null || typeof value !== 'object') { return undefined; } return getImpl(value, elems.slice(1)); }; /** *

Get a configuration value

* *

* This will return the specified property value, throwing an exception if the * configuration isn't defined. It is used to assure configurations are defined * before being used, and to prevent typos. *

* * @method get * @param property {string} - The configuration property to get. Can include '.' sub-properties. * @return value {*} - The property value */ Config.prototype.get = function(property) { if(property === null || property === undefined){ throw new Error("Calling config.get with null or undefined argument"); } // Make configurations immutable after first get (unless disabled) if (checkMutability) { if (!util.initParam('ALLOW_CONFIG_MUTATIONS', false)) { util.makeImmutable(config); } checkMutability = false; } var t = this, value = getImpl(t, property); // Produce an exception if the property doesn't exist if (value === undefined) { throw new Error('Configuration property "' + property + '" is not defined'); } // Return the value return value; }; /** * Test that a configuration parameter exists * *
 *    var config = require('config');
 *    if (config.has('customer.dbName')) {
 *      console.log('Customer database name: ' + config.customer.dbName);
 *    }
 * 
* * @method has * @param property {string} - The configuration property to test. Can include '.' sub-properties. * @return isPresent {boolean} - True if the property is defined, false if not defined. */ Config.prototype.has = function(property) { // While get() throws an exception for undefined input, has() is designed to test validity, so false is appropriate if(property === null || property === undefined){ return false; } var t = this; return (getImpl(t, property) !== undefined); }; /** *

* Set default configurations for a node.js module. *

* *

* This allows module developers to attach their configurations onto the * default configuration object so they can be configured by the consumers * of the module. *

* *

Using the function within your module:

*
 *   var CONFIG = require("config");
 *   CONFIG.util.setModuleDefaults("MyModule", {
 *     templateName: "t-50",
 *     colorScheme: "green"
 *   });
 * 
* // Template name may be overridden by application config files * console.log("Template: " + CONFIG.MyModule.templateName); *
* *

* The above example results in a "MyModule" element of the configuration * object, containing an object with the specified default values. *

* * @method setModuleDefaults * @param moduleName {string} - Name of your module. * @param defaultProperties {object} - The default module configuration. * @return moduleConfig {object} - The module level configuration object. */ util.setModuleDefaults = function (moduleName, defaultProperties) { // Copy the properties into a new object var t = this, moduleConfig = util.cloneDeep(defaultProperties); // Set module defaults into the first sources element if (configSources.length === 0 || configSources[0].name !== 'Module Defaults') { configSources.splice(0, 0, { name: 'Module Defaults', parsed: {} }); } util.setPath(configSources[0].parsed, moduleName.split('.'), {}); util.extendDeep(getImpl(configSources[0].parsed, moduleName), defaultProperties); // Create a top level config for this module if it doesn't exist util.setPath(t, moduleName.split('.'), getImpl(t, moduleName) || {}); // Extend local configurations into the module config util.extendDeep(moduleConfig, getImpl(t, moduleName)); // Merge the extended configs without replacing the original util.extendDeep(getImpl(t, moduleName), moduleConfig); // reset the mutability check for "config.get" method. // we are not making t[moduleName] immutable immediately, // since there might be more modifications before the first config.get if (!util.initParam('ALLOW_CONFIG_MUTATIONS', false)) { checkMutability = true; } // Attach handlers & watchers onto the module config object return util.attachProtoDeep(getImpl(t, moduleName)); }; /** *

Make a configuration property hidden so it doesn't appear when enumerating * elements of the object.

* *

* The property still exists and can be read from and written to, but it won't * show up in for ... in loops, Object.keys(), or JSON.stringify() type methods. *

* *

* If the property already exists, it will be made hidden. Otherwise it will * be created as a hidden property with the specified value. *

* *

* This method was built for hiding configuration values, but it can be applied * to any javascript object. *

* *

Example:

*
 *   var CONFIG = require('config');
 *   ...
 *
 *   // Hide the Amazon S3 credentials
 *   CONFIG.util.makeHidden(CONFIG.amazonS3, 'access_id');
 *   CONFIG.util.makeHidden(CONFIG.amazonS3, 'secret_key');
 * 
* * @method makeHidden * @param object {object} - The object to make a hidden property into. * @param property {string} - The name of the property to make hidden. * @param value {*} - (optional) Set the property value to this (otherwise leave alone) * @return object {object} - The original object is returned - for chaining. */ util.makeHidden = function(object, property, value) { // If the new value isn't specified, just mark the property as hidden if (typeof value === 'undefined') { Object.defineProperty(object, property, { enumerable : false }); } // Otherwise set the value and mark it as hidden else { Object.defineProperty(object, property, { value : value, enumerable : false }); } return object; } /** *

Make a javascript object property immutable (assuring it cannot be changed * from the current value).

*

* If the specified property is an object, all attributes of that object are * made immutable, including properties of contained objects, recursively. * If a property name isn't supplied, all properties of the object are made * immutable. *

*

* *

*

* New properties can be added to the object and those properties will not be * immutable unless this method is called on those new properties. *

*

* This operation cannot be undone. *

* *

Example:

*
 *   var config = require('config');
 *   var myObject = {hello:'world'};
 *   config.util.makeImmutable(myObject);
 * 
* * @method makeImmutable * @param object {object} - The object to specify immutable properties for * @param [property] {string | [string]} - The name of the property (or array of names) to make immutable. * If not provided, all owned properties of the object are made immutable. * @param [value] {* | [*]} - Property value (or array of values) to set * the property to before making immutable. Only used when setting a single * property. Retained for backward compatibility. * @return object {object} - The original object is returned - for chaining. */ util.makeImmutable = function(object, property, value) { if (Buffer.isBuffer(object)) { return object; } var properties = null; // Backwards compatibility mode where property/value can be specified if (typeof property === 'string') { return Object.defineProperty(object, property, { value : (typeof value === 'undefined') ? object[property] : value, writable : false, configurable: false }); } // Get the list of properties to work with if (Array.isArray(property)) { properties = property; } else { properties = Object.keys(object); } // Process each property for (var i = 0; i < properties.length; i++) { var propertyName = properties[i], value = object[propertyName]; if (value instanceof RawConfig) { Object.defineProperty(object, propertyName, { value: value.resolve(), writable: false, configurable: false }); } else if (Array.isArray(value)) { // Ensure object items of this array are also immutable. value.forEach((item, index) => { if (util.isObject(item) || Array.isArray(item)) util.makeImmutable(item) }) Object.defineProperty(object, propertyName, { value: Object.freeze(value) }); } else { Object.defineProperty(object, propertyName, { value: value, writable : false, configurable: false }); // Ensure new properties can not be added. Object.preventExtensions(object) // Call recursively if an object. if (util.isObject(value)) { util.makeImmutable(value); } } } return object; }; /** * Return the sources for the configurations * *

* All sources for configurations are stored in an array of objects containing * the source name (usually the filename), the original source (as a string), * and the parsed source as an object. *

* * @method getConfigSources * @return configSources {Array[Object]} - An array of objects containing * name, original, and parsed elements */ util.getConfigSources = function() { var t = this; return configSources.slice(0); }; /** * Looks into an options object for a specific attribute * *

* This method looks into the options object, and if an attribute is defined, returns it, * and if not, returns the default value *

* * @method getOption * @param options {Object | undefined} the options object * @param optionName {string} the attribute name to look for * @param defaultValue { any } the default in case the options object is empty, or the attribute does not exist. * @return options[optionName] if defined, defaultValue if not. */ util.getOption = function(options, optionName, defaultValue) { if (options !== undefined && options[optionName] !== undefined){ return options[optionName]; } else { return defaultValue; } }; /** * Load the individual file configurations. * *

* This method builds a map of filename to the configuration object defined * by the file. The search order is: *

* *
 *   default.EXT
 *   (deployment).EXT
 *   (hostname).EXT
 *   (hostname)-(deployment).EXT
 *   local.EXT
 *   local-(deployment).EXT
 *   runtime.json
 * 
* *

* EXT can be yml, yaml, coffee, iced, json, cson or js signifying the file type. * yaml (and yml) is in YAML format, coffee is a coffee-script, iced is iced-coffee-script, * json is in JSON format, cson is in CSON format, properties is in .properties format * (http://en.wikipedia.org/wiki/.properties), and js is a javascript executable file that is * require()'d with module.exports being the config object. *

* *

* hostname is the $HOST environment variable (or --HOST command line parameter) * if set, otherwise the $HOSTNAME environment variable (or --HOSTNAME command * line parameter) if set, otherwise the hostname found from * require('os').hostname(). *

* *

* Once a hostname is found, everything from the first period ('.') onwards * is removed. For example, abc.example.com becomes abc *

* *

* (deployment) is the deployment type, found in the $NODE_ENV environment * variable (which can be overridden by using $NODE_CONFIG_ENV * environment variable). Defaults to 'development'. *

* *

* The runtime.json file contains configuration changes made at runtime either * manually, or by the application setting a configuration value. *

* *

* If the $NODE_APP_INSTANCE environment variable (or --NODE_APP_INSTANCE * command line parameter) is set, then files with this appendage will be loaded. * See the Multiple Application Instances section of the main documentation page * for more information. *

* * @protected * @method loadFileConfigs * @param configDir { string | null } the path to the directory containing the configurations to load * @param options { object | undefined } parsing options. Current supported option: skipConfigSources: true|false * @return config {Object} The configuration object */ util.loadFileConfigs = function(configDir, options) { // Initialize var t = this, config = {}; // Specify variables that can be used to define the environment var node_env_var_names = ['NODE_CONFIG_ENV', 'NODE_ENV']; // Loop through the variables to try and set environment for (const node_env_var_name of node_env_var_names) { NODE_ENV = util.initParam(node_env_var_name); if (!!NODE_ENV) { NODE_ENV_VAR_NAME = node_env_var_name; break; } } // If we haven't successfully set the environment using the variables, we'll default it if (!NODE_ENV) { NODE_ENV = 'development'; } node_env_var_names.forEach(node_env_var_name => { env[node_env_var_name] = NODE_ENV; }); // Split files name, for loading multiple files. NODE_ENV = NODE_ENV.split(','); CONFIG_DIR = configDir || util.initParam('NODE_CONFIG_DIR', Path.join( process.cwd(), 'config') ); if (CONFIG_DIR.indexOf('.') === 0) { CONFIG_DIR = Path.join(process.cwd() , CONFIG_DIR); } APP_INSTANCE = util.initParam('NODE_APP_INSTANCE'); HOST = util.initParam('HOST'); HOSTNAME = util.initParam('HOSTNAME'); CONFIG_SKIP_GITCRYPT = util.initParam('CONFIG_SKIP_GITCRYPT'); // This is for backward compatibility RUNTIME_JSON_FILENAME = util.initParam('NODE_CONFIG_RUNTIME_JSON', Path.join(CONFIG_DIR , 'runtime.json') ); NODE_CONFIG_PARSER = util.initParam('NODE_CONFIG_PARSER'); if (NODE_CONFIG_PARSER) { try { var parserModule = Path.isAbsolute(NODE_CONFIG_PARSER) ? NODE_CONFIG_PARSER : Path.join(CONFIG_DIR, NODE_CONFIG_PARSER); Parser = require(parserModule); } catch (e) { console.warn('Failed to load config parser from ' + NODE_CONFIG_PARSER); console.log(e); } } // Determine the host name from the OS module, $HOST, or $HOSTNAME // Remove any . appendages, and default to null if not set try { var hostName = HOST || HOSTNAME; if (!hostName) { var OS = require('os'); hostName = OS.hostname(); } } catch (e) { hostName = ''; } // Store the hostname that won. env.HOSTNAME = hostName; // Read each file in turn var baseNames = ['default'].concat(NODE_ENV); // #236: Also add full hostname when they are different. if (hostName) { var firstDomain = hostName.split('.')[0]; NODE_ENV.forEach(function(env) { // Backward compatibility baseNames.push(firstDomain, firstDomain + '-' + env); // Add full hostname when it is not the same if (hostName !== firstDomain) { baseNames.push(hostName, hostName + '-' + env); } }); } NODE_ENV.forEach(function(env) { baseNames.push('local', 'local-' + env); }); var allowedFiles = {}; var resolutionIndex = 1; var extNames = Parser.getFilesOrder(); baseNames.forEach(function(baseName) { extNames.forEach(function(extName) { allowedFiles[baseName + '.' + extName] = resolutionIndex++; if (APP_INSTANCE) { allowedFiles[baseName + '-' + APP_INSTANCE + '.' + extName] = resolutionIndex++; } }); }); var locatedFiles = util.locateMatchingFiles(CONFIG_DIR, allowedFiles); locatedFiles.forEach(function(fullFilename) { var configObj = util.parseFile(fullFilename, options); if (configObj) { util.extendDeep(config, configObj); } }); // Override configurations from the $NODE_CONFIG environment variable // NODE_CONFIG only applies to the base config if (!configDir) { var envConfig = {}; if (process.env.NODE_CONFIG) { try { envConfig = JSON.parse(process.env.NODE_CONFIG); } catch(e) { console.error('The $NODE_CONFIG environment variable is malformed JSON'); } util.extendDeep(config, envConfig); var skipConfigSources = util.getOption(options,'skipConfigSources', false); if (!skipConfigSources){ configSources.push({ name: "$NODE_CONFIG", parsed: envConfig, }); } } // Override configurations from the --NODE_CONFIG command line var cmdLineConfig = util.getCmdLineArg('NODE_CONFIG'); if (cmdLineConfig) { try { cmdLineConfig = JSON.parse(cmdLineConfig); } catch(e) { console.error('The --NODE_CONFIG={json} command line argument is malformed JSON'); } util.extendDeep(config, cmdLineConfig); var skipConfigSources = util.getOption(options,'skipConfigSources', false); if (!skipConfigSources){ configSources.push({ name: "--NODE_CONFIG argument", parsed: cmdLineConfig, }); } } // Place the mixed NODE_CONFIG into the environment env['NODE_CONFIG'] = JSON.stringify(util.extendDeep(envConfig, cmdLineConfig, {})); } // Override with environment variables if there is a custom-environment-variables.EXT mapping file var customEnvVars = util.getCustomEnvVars(CONFIG_DIR, extNames); util.extendDeep(config, customEnvVars); // Extend the original config with the contents of runtime.json (backwards compatibility) var runtimeJson = util.parseFile(RUNTIME_JSON_FILENAME) || {}; util.extendDeep(config, runtimeJson); util.resolveDeferredConfigs(config); // Return the configuration object return config; }; /** * Return a list of fullFilenames who exists in allowedFiles * Ordered according to allowedFiles argument specifications * * @protected * @method locateMatchingFiles * @param configDirs {string} the config dir, or multiple dirs separated by a column (:) * @param allowedFiles {object} an object. keys and supported filenames * and values are the position in the resolution order * @returns {string[]} fullFilenames - path + filename */ util.locateMatchingFiles = function(configDirs, allowedFiles) { return configDirs.split(Path.delimiter) .reduce(function(files, configDir) { if (configDir) { try { FileSystem.readdirSync(configDir).forEach(function(file) { if (allowedFiles[file]) { files.push([allowedFiles[file], Path.join(configDir, file)]); } }); } catch(e) {} return files; } }, []) .sort(function(a, b) { return a[0] - b[0]; }) .map(function(file) { return file[1]; }); }; // Using basic recursion pattern, find all the deferred values and resolve them. util.resolveDeferredConfigs = function (config) { var deferred = []; function _iterate (prop) { // We put the properties we are going to look it in an array to keep the order predictable var propsToSort = []; // First step is to put the properties of interest in an array for (var property in prop) { if (Object.hasOwnProperty.call(prop, property) && prop[property] != null) { propsToSort.push(property); } } // Second step is to iterate of the elements in a predictable (sorted) order propsToSort.sort().forEach(function (property) { if (prop[property].constructor === Object) { _iterate(prop[property]); } else if (prop[property].constructor === Array) { for (var i = 0; i < prop[property].length; i++) { if (prop[property][i] instanceof DeferredConfig) { deferred.push(prop[property][i].prepare(config, prop[property], i)); } else { _iterate(prop[property][i]); } } } else { if (prop[property] instanceof DeferredConfig) { deferred.push(prop[property].prepare(config, prop, property)); } // else: Nothing to do. Keep the property how it is. } }); } _iterate(config); deferred.forEach(function (defer) { defer.resolve(); }); }; /** * Parse and return the specified configuration file. * * If the file exists in the application config directory, it will * parse and return it as a JavaScript object. * * The file extension determines the parser to use. * * .js = File to run that has a module.exports containing the config object * .coffee = File to run that has a module.exports with coffee-script containing the config object * .iced = File to run that has a module.exports with iced-coffee-script containing the config object * All other supported file types (yaml, toml, json, cson, hjson, json5, properties, xml) * are parsed with util.parseString. * * If the file doesn't exist, a null will be returned. If the file can't be * parsed, an exception will be thrown. * * This method performs synchronous file operations, and should not be called * after synchronous module loading. * * @protected * @method parseFile * @param fullFilename {string} The full file path and name * @param options { object | undefined } parsing options. Current supported option: skipConfigSources: true|false * @return configObject {object|null} The configuration object parsed from the file */ util.parseFile = function(fullFilename, options) { var t = this, // Initialize configObject = null, fileContent = null, stat = null; // Note that all methods here are the Sync versions. This is appropriate during // module loading (which is a synchronous operation), but not thereafter. try { // Try loading the file. fileContent = FileSystem.readFileSync(fullFilename, 'utf-8'); fileContent = fileContent.replace(/^\uFEFF/, ''); } catch (e2) { if (e2.code !== 'ENOENT') { throw new Error('Config file ' + fullFilename + ' cannot be read. Error code is: '+e2.code +'. Error message is: '+e2.message); } return null; // file doesn't exists } // Parse the file based on extension try { // skip if it's a gitcrypt file and CONFIG_SKIP_GITCRYPT is true if (CONFIG_SKIP_GITCRYPT) { if (gitCryptTestRegex.test(fileContent)) { console.error('WARNING: ' + fullFilename + ' is a git-crypt file and CONFIG_SKIP_GITCRYPT is set. skipping.'); return null; } } configObject = Parser.parse(fullFilename, fileContent); } catch (e3) { if (gitCryptTestRegex.test(fileContent)) { console.error('ERROR: ' + fullFilename + ' is a git-crypt file and CONFIG_SKIP_GITCRYPT is not set.'); } throw new Error("Cannot parse config file: '" + fullFilename + "': " + e3); } // Keep track of this configuration sources, including empty ones, unless the skipConfigSources flag is set to true in the options var skipConfigSources = util.getOption(options,'skipConfigSources', false); if (typeof configObject === 'object' && !skipConfigSources) { configSources.push({ name: fullFilename, original: fileContent, parsed: configObject, }); } return configObject; }; /** * Parse and return the specified string with the specified format. * * The format determines the parser to use. * * json = File is parsed using JSON.parse() * yaml (or yml) = Parsed with a YAML parser * toml = Parsed with a TOML parser * cson = Parsed with a CSON parser * hjson = Parsed with a HJSON parser * json5 = Parsed with a JSON5 parser * properties = Parsed with the 'properties' node package * xml = Parsed with a XML parser * * If the file doesn't exist, a null will be returned. If the file can't be * parsed, an exception will be thrown. * * This method performs synchronous file operations, and should not be called * after synchronous module loading. * * @protected * @method parseString * @param content {string} The full content * @param format {string} The format to be parsed * @return {configObject} The configuration object parsed from the string */ util.parseString = function (content, format) { var parser = Parser.getParser(format); if (typeof parser === 'function') { return parser(null, content); } }; /** * Attach the Config class prototype to all config objects recursively. * *

* This allows you to do anything with CONFIG sub-objects as you can do with * the top-level CONFIG object. It's so you can do this: *

* *
 *   var CUST_CONFIG = require('config').Customer;
 *   CUST_CONFIG.get(...)
 * 
* * @protected * @method attachProtoDeep * @param toObject * @param depth * @return toObject */ util.attachProtoDeep = function(toObject, depth) { if (toObject instanceof RawConfig) { return toObject; } // Recursion detection var t = this; depth = (depth === null ? DEFAULT_CLONE_DEPTH : depth); if (depth < 0) { return toObject; } // Adding Config.prototype methods directly to toObject as hidden properties // because adding to toObject.__proto__ exposes the function in toObject for (var fnName in Config.prototype) { if (!toObject[fnName]) { util.makeHidden(toObject, fnName, Config.prototype[fnName]); } } // Add prototypes to sub-objects for (var prop in toObject) { if (util.isObject(toObject[prop])) { util.attachProtoDeep(toObject[prop], depth - 1); } } // Return the original object return toObject; }; /** * Return a deep copy of the specified object. * * This returns a new object with all elements copied from the specified * object. Deep copies are made of objects and arrays so you can do anything * with the returned object without affecting the input object. * * @protected * @method cloneDeep * @param parent {object} The original object to copy from * @param [depth=20] {Integer} Maximum depth (default 20) * @return {object} A new object with the elements copied from the copyFrom object * * This method is copied from https://github.com/pvorb/node-clone/blob/17eea36140d61d97a9954c53417d0e04a00525d9/clone.js * * Copyright © 2011-2014 Paul Vorbach and contributors. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the “Softwareâ€), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: The above copyright notice and this permission * notice shall be included in all copies or substantial portions of the Software. */ util.cloneDeep = function cloneDeep(parent, depth, circular, prototype) { // maintain two arrays for circular references, where corresponding parents // and children have the same index var allParents = []; var allChildren = []; var useBuffer = typeof Buffer != 'undefined'; if (typeof circular === 'undefined') circular = true; if (typeof depth === 'undefined') depth = 20; // recurse this function so we don't reset allParents and allChildren function _clone(parent, depth) { // cloning null always returns null if (parent === null) return null; if (depth === 0) return parent; var child; if (typeof parent != 'object') { return parent; } if (Utils.isArray(parent)) { child = []; } else if (Utils.isRegExp(parent)) { child = new RegExp(parent.source, util.getRegExpFlags(parent)); if (parent.lastIndex) child.lastIndex = parent.lastIndex; } else if (Utils.isDate(parent)) { child = new Date(parent.getTime()); } else if (useBuffer && Buffer.isBuffer(parent)) { child = Buffer.alloc(parent.length); parent.copy(child); return child; } else { if (typeof prototype === 'undefined') child = Object.create(Object.getPrototypeOf(parent)); else child = Object.create(prototype); } if (circular) { var index = allParents.indexOf(parent); if (index != -1) { return allChildren[index]; } allParents.push(parent); allChildren.push(child); } for (var i in parent) { var propDescriptor = Object.getOwnPropertyDescriptor(parent,i); var hasGetter = ((propDescriptor !== undefined) && (propDescriptor.get !== undefined)); if (hasGetter){ Object.defineProperty(child,i,propDescriptor); } else if (util.isPromise(parent[i])) { child[i] = parent[i]; } else { child[i] = _clone(parent[i], depth - 1); } } return child; } return _clone(parent, depth); }; /** * Set objects given a path as a string list * * @protected * @method setPath * @param object {object} - Object to set the property on * @param path {array[string]} - Array path to the property * @param value {*} - value to set, ignoring null */ util.setPath = function (object, path, value) { var nextKey = null; if (value === null || path.length === 0) { return; } else if (path.length === 1) { // no more keys to make, so set the value object[path.shift()] = value; } else { nextKey = path.shift(); if (!Object.hasOwnProperty.call(object, nextKey)) { object[nextKey] = {}; } util.setPath(object[nextKey], path, value); } }; /** * Create a new object patterned after substitutionMap, where: * 1. Terminal string values in substitutionMap are used as keys * 2. To look up values in a key-value store, variables * 3. And parent keys are created as necessary to retain the structure of substitutionMap. * * @protected * @method substituteDeep * @param substitutionMap {object} - an object whose terminal (non-subobject) values are strings * @param variables {object[string:value]} - usually process.env, a flat object used to transform * terminal values in a copy of substitutionMap. * @returns {object} - deep copy of substitutionMap with only those paths whose terminal values * corresponded to a key in `variables` */ util.substituteDeep = function (substitutionMap, variables) { var result = {}; function _substituteVars(map, vars, pathTo) { for (var prop in map) { var value = map[prop]; if (typeof(value) === 'string') { // We found a leaf variable name if (vars[value] !== undefined && vars[value] !== '') { // if the vars provide a value set the value in the result map util.setPath(result, pathTo.concat(prop), vars[value]); } } else if (util.isObject(value)) { // work on the subtree, giving it a clone of the pathTo if ('__name' in value && '__format' in value && vars[value.__name] !== undefined && vars[value.__name] !== '') { try { var parsedValue = util.parseString(vars[value.__name], value.__format); } catch(err) { err.message = '__format parser error in ' + value.__name + ': ' + err.message; throw err; } util.setPath(result, pathTo.concat(prop), parsedValue); } else { _substituteVars(value, vars, pathTo.concat(prop)); } } else { msg = "Illegal key type for substitution map at " + pathTo.join('.') + ': ' + typeof(value); throw Error(msg); } } } _substituteVars(substitutionMap, variables, []); return result; }; /* Map environment variables into the configuration if a mapping file, * `custom-environment-variables.EXT` exists. * * @protected * @method getCustomEnvVars * @param CONFIG_DIR {string} - the passed configuration directory * @param extNames {Array[string]} - acceptable configuration file extension names. * @returns {object} - mapped environment variables or {} if there are none */ util.getCustomEnvVars = function (CONFIG_DIR, extNames) { var result = {}; var resolutionIndex = 1; var allowedFiles = {}; extNames.forEach(function (extName) { allowedFiles['custom-environment-variables' + '.' + extName] = resolutionIndex++; }); var locatedFiles = util.locateMatchingFiles(CONFIG_DIR, allowedFiles); locatedFiles.forEach(function (fullFilename) { var configObj = util.parseFile(fullFilename); if (configObj) { var environmentSubstitutions = util.substituteDeep(configObj, process.env); util.extendDeep(result, environmentSubstitutions); } }); return result; }; /** * Return true if two objects have equal contents. * * @protected * @method equalsDeep * @param object1 {object} The object to compare from * @param object2 {object} The object to compare with * @param depth {integer} An optional depth to prevent recursion. Default: 20. * @return {boolean} True if both objects have equivalent contents */ util.equalsDeep = function(object1, object2, depth) { // Recursion detection var t = this; depth = (depth === null ? DEFAULT_CLONE_DEPTH : depth); if (depth < 0) { return {}; } // Fast comparisons if (!object1 || !object2) { return false; } if (object1 === object2) { return true; } if (typeof(object1) != 'object' || typeof(object2) != 'object') { return false; } // They must have the same keys. If their length isn't the same // then they're not equal. If the keys aren't the same, the value // comparisons will fail. if (Object.keys(object1).length != Object.keys(object2).length) { return false; } // Compare the values for (var prop in object1) { // Call recursively if an object or array if (object1[prop] && typeof(object1[prop]) === 'object') { if (!util.equalsDeep(object1[prop], object2[prop], depth - 1)) { return false; } } else { if (object1[prop] !== object2[prop]) { return false; } } } // Test passed. return true; }; /** * Returns an object containing all elements that differ between two objects. *

* This method was designed to be used to create the runtime.json file * contents, but can be used to get the diffs between any two Javascript objects. *

*

* It works best when object2 originated by deep copying object1, then * changes were made to object2, and you want an object that would give you * the changes made to object1 which resulted in object2. *

* * @protected * @method diffDeep * @param object1 {object} The base object to compare to * @param object2 {object} The object to compare with * @param depth {integer} An optional depth to prevent recursion. Default: 20. * @return {object} A differential object, which if extended onto object1 would * result in object2. */ util.diffDeep = function(object1, object2, depth) { // Recursion detection var t = this, diff = {}; depth = (depth === null ? DEFAULT_CLONE_DEPTH : depth); if (depth < 0) { return {}; } // Process each element from object2, adding any element that's different // from object 1. for (var parm in object2) { var value1 = object1[parm]; var value2 = object2[parm]; if (value1 && value2 && util.isObject(value2)) { if (!(util.equalsDeep(value1, value2))) { diff[parm] = util.diffDeep(value1, value2, depth - 1); } } else if (Array.isArray(value1) && Array.isArray(value2)) { if(!util.equalsDeep(value1, value2)) { diff[parm] = value2; } } else if (value1 !== value2){ diff[parm] = value2; } } // Return the diff object return diff; }; /** * Extend an object, and any object it contains. * * This does not replace deep objects, but dives into them * replacing individual elements instead. * * @protected * @method extendDeep * @param mergeInto {object} The object to merge into * @param mergeFrom... {object...} - Any number of objects to merge from * @param depth {integer} An optional depth to prevent recursion. Default: 20. * @return {object} The altered mergeInto object is returned */ util.extendDeep = function(mergeInto) { // Initialize var t = this; var vargs = Array.prototype.slice.call(arguments, 1); var depth = vargs.pop(); if (typeof(depth) != 'number') { vargs.push(depth); depth = DEFAULT_CLONE_DEPTH; } // Recursion detection if (depth < 0) { return mergeInto; } // Cycle through each object to extend vargs.forEach(function(mergeFrom) { // Cycle through each element of the object to merge from for (var prop in mergeFrom) { // save original value in deferred elements var fromIsDeferredFunc = mergeFrom[prop] instanceof DeferredConfig; var isDeferredFunc = mergeInto[prop] instanceof DeferredConfig; if (fromIsDeferredFunc && Object.hasOwnProperty.call(mergeInto, prop)) { mergeFrom[prop]._original = isDeferredFunc ? mergeInto[prop]._original : mergeInto[prop]; } // Extend recursively if both elements are objects and target is not really a deferred function if (mergeFrom[prop] instanceof Date) { mergeInto[prop] = mergeFrom[prop]; } if (mergeFrom[prop] instanceof RegExp) { mergeInto[prop] = mergeFrom[prop]; } else if (util.isObject(mergeInto[prop]) && util.isObject(mergeFrom[prop]) && !isDeferredFunc) { util.extendDeep(mergeInto[prop], mergeFrom[prop], depth - 1); } else if (util.isPromise(mergeFrom[prop])) { mergeInto[prop] = mergeFrom[prop]; } // Copy recursively if the mergeFrom element is an object (or array or fn) else if (mergeFrom[prop] && typeof mergeFrom[prop] === 'object') { mergeInto[prop] = util.cloneDeep(mergeFrom[prop], depth -1); } // Copy property descriptor otherwise, preserving accessors else if (Object.getOwnPropertyDescriptor(Object(mergeFrom), prop)){ Object.defineProperty(mergeInto, prop, Object.getOwnPropertyDescriptor(Object(mergeFrom), prop)); } else { mergeInto[prop] = mergeFrom[prop]; } } }); // Chain return mergeInto; }; /** * Is the specified argument a regular javascript object? * * The argument is an object if it's a JS object, but not an array. * * @protected * @method isObject * @param obj {*} An argument of any type. * @return {boolean} TRUE if the arg is an object, FALSE if not */ util.isObject = function(obj) { return (obj !== null) && (typeof obj === 'object') && !(Array.isArray(obj)); }; /** * Is the specified argument a javascript promise? * * @protected * @method isPromise * @param obj {*} An argument of any type. * @returns {boolean} */ util.isPromise = function(obj) { return Object.prototype.toString.call(obj) === '[object Promise]'; }; /** *

Initialize a parameter from the command line or process environment

* *

* This method looks for the parameter from the command line in the format * --PARAMETER=VALUE, then from the process environment, then from the * default specified as an argument. *

* * @method initParam * @param paramName {String} Name of the parameter * @param [defaultValue] {Any} Default value of the parameter * @return {Any} The found value, or default value */ util.initParam = function (paramName, defaultValue) { var t = this; // Record and return the value var value = util.getCmdLineArg(paramName) || process.env[paramName] || defaultValue; env[paramName] = value; return value; } /** *

Get Command Line Arguments

* *

* This method allows you to retrieve the value of the specified command line argument. *

* *

* The argument is case sensitive, and must be of the form '--ARG_NAME=value' *

* * @method getCmdLineArg * @param searchFor {String} The argument name to search for * @return {*} false if the argument was not found, the argument value if found */ util.getCmdLineArg = function (searchFor) { var cmdLineArgs = process.argv.slice(2, process.argv.length), argName = '--' + searchFor + '='; for (var argvIt = 0; argvIt < cmdLineArgs.length; argvIt++) { if (cmdLineArgs[argvIt].indexOf(argName) === 0) { return cmdLineArgs[argvIt].substr(argName.length); } } return false; } /** *

Get a Config Environment Variable Value

* *

* This method returns the value of the specified config environment variable, * including any defaults or overrides. *

* * @method getEnv * @param varName {String} The environment variable name * @return {String} The value of the environment variable */ util.getEnv = function (varName) { return env[varName]; } /** * Returns a string of flags for regular expression `re`. * * @param {RegExp} re Regular expression * @returns {string} Flags */ util.getRegExpFlags = function (re) { var flags = ''; re.global && (flags += 'g'); re.ignoreCase && (flags += 'i'); re.multiline && (flags += 'm'); return flags; }; /** * Returns a new deep copy of the current config object, or any part of the config if provided. * * @param {Object} config The part of the config to copy and serialize. Omit this argument to return the entire config. * @returns {Object} The cloned config or part of the config */ util.toObject = function(config) { return JSON.parse(JSON.stringify(config || this)); }; // Run strictness checks on NODE_ENV and NODE_APP_INSTANCE and throw an error if there's a problem. util.runStrictnessChecks = function (config) { var sources = config.util.getConfigSources(); var sourceFilenames = sources.map(function (src) { return Path.basename(src.name); }); NODE_ENV.forEach(function(env) { // Throw an exception if there's no explicit config file for NODE_ENV var anyFilesMatchEnv = sourceFilenames.some(function (filename) { return filename.match(env); }); // development is special-cased because it's the default value if (env && (env !== 'development') && !anyFilesMatchEnv) { _warnOrThrow(NODE_ENV_VAR_NAME+" value of '"+env+"' did not match any deployment config file names."); } // Throw if NODE_ENV matches' default' or 'local' if ((env === 'default') || (env === 'local')) { _warnOrThrow(NODE_ENV_VAR_NAME+" value of '"+env+"' is ambiguous."); } }); // Throw an exception if there's no explicit config file for NODE_APP_INSTANCE var anyFilesMatchInstance = sourceFilenames.some(function (filename) { return filename.match(APP_INSTANCE); }); if (APP_INSTANCE && !anyFilesMatchInstance) { _warnOrThrow("NODE_APP_INSTANCE value of '"+APP_INSTANCE+"' did not match any instance config file names."); } function _warnOrThrow (msg) { var beStrict = process.env.NODE_CONFIG_STRICT_MODE; var prefix = beStrict ? 'FATAL: ' : 'WARNING: '; var seeURL = 'See https://github.com/lorenwest/node-config/wiki/Strict-Mode'; console.error(prefix+msg); console.error(prefix+seeURL); // Accept 1 and true as truthy values. When set via process.env, Node.js casts them to strings. if (["true", "1"].indexOf(beStrict) >= 0) { throw new Error(prefix+msg+' '+seeURL); } } }; // Instantiate and export the configuration var config = module.exports = new Config(); // copy methods to util for backwards compatibility util.stripComments = Parser.stripComments; util.stripYamlComments = Parser.stripYamlComments; // Produce warnings if the configuration is empty var showWarnings = !(util.initParam('SUPPRESS_NO_CONFIG_WARNING')); if (showWarnings && Object.keys(config).length === 0) { console.error('WARNING: No configurations found in configuration directory:' +CONFIG_DIR); console.error('WARNING: To disable this warning set SUPPRESS_NO_CONFIG_WARNING in the environment.'); } node-config-3.3.7/package.json000066400000000000000000000022051413461306600162050ustar00rootroot00000000000000{ "name": "config", "version": "3.3.6", "main": "./lib/config.js", "description": "Configuration control for production node deployments", "author": "Loren West ", "homepage": "http://github.com/lorenwest/node-config.git", "publishConfig": { "registry": "https://registry.npmjs.org/" }, "keywords": [ "conf", "config", "configuration", "node-config", "config-node", "env", "environment" ], "directories": { "lib": "./lib" }, "license": "MIT", "dependencies": { "json5": "^2.1.1" }, "devDependencies": { "@types/node": "^7.0.8", "coffeescript": "2.2.4", "cson": "^3.0.1", "hjson": "^1.2.0", "js-yaml": "^3.2.2", "properties": "~1.2.1", "semver": "5.3.0", "toml": "^2.0.6", "ts-node": "^3.3.0", "typescript": "^2.4.2", "underscore": "^1.8.3", "vows": ">=0.8.1", "x2js": "^2.0.1" }, "repository": { "type": "git", "url": "http://github.com/lorenwest/node-config.git" }, "engines": { "node": ">= 10.0.0" }, "scripts": { "test": "./node_modules/vows/bin/vows test/*.js --spec" } } node-config-3.3.7/parser.js000066400000000000000000000235011413461306600155530ustar00rootroot00000000000000// External libraries are lazy-loaded only if these file types exist. var Yaml = null, VisionmediaYaml = null, Coffee = null, Iced = null, CSON = null, PPARSER = null, JSON5 = null, TOML = null, HJSON = null, XML = null; // Define soft dependencies so transpilers don't include everything var COFFEE_2_DEP = 'coffeescript', COFFEE_DEP = 'coffee-script', ICED_DEP = 'iced-coffee-script', JS_YAML_DEP = 'js-yaml', YAML_DEP = 'yaml', JSON5_DEP = 'json5', HJSON_DEP = 'hjson', TOML_DEP = 'toml', CSON_DEP = 'cson', PPARSER_DEP = 'properties', XML_DEP = 'x2js', TS_DEP = 'ts-node'; var Parser = module.exports; Parser.parse = function(filename, content) { var parserName = filename.substr(filename.lastIndexOf('.') +1); // file extension if (typeof definitions[parserName] === 'function') { return definitions[parserName](filename, content); } // TODO: decide what to do in case of a missing parser }; Parser.xmlParser = function(filename, content) { if (!XML) { XML = require(XML_DEP); } var x2js = new XML(); var configObject = x2js.xml2js(content); var rootKeys = Object.keys(configObject); if(rootKeys.length === 1) { return configObject[rootKeys[0]]; } return configObject; }; Parser.jsParser = function(filename, content) { return require(filename); }; Parser.tsParser = function(filename, content) { if (!require.extensions['.ts']) { require(TS_DEP).register({ lazy: true, transpileOnly: true, compilerOptions: { allowJs: true, } }); } // Imports config if it is exported via module.exports = ... // See https://github.com/lorenwest/node-config/issues/524 var configObject = require(filename); // Because of ES6 modules usage, `default` is treated as named export (like any other) // Therefore config is a value of `default` key. if (configObject.default) { return configObject.default } return configObject; }; Parser.coffeeParser = function(filename, content) { // .coffee files can be loaded with either coffee-script or iced-coffee-script. // Prefer iced-coffee-script, if it exists. // Lazy load the appropriate extension if (!Coffee) { Coffee = {}; // The following enables iced-coffee-script on .coffee files, if iced-coffee-script is available. // This is commented as per a decision on a pull request. //try { // Coffee = require('iced-coffee-script'); //} //catch (e) { // Coffee = require('coffee-script'); //} try { // Try to load coffeescript Coffee = require(COFFEE_2_DEP); } catch (e) { // If it doesn't exist, try to load it using the deprecated module name Coffee = require(COFFEE_DEP); } // coffee-script >= 1.7.0 requires explicit registration for require() to work if (Coffee.register) { Coffee.register(); } } // Use the built-in parser for .coffee files with coffee-script return require(filename); }; Parser.icedParser = function(filename, content) { Iced = require(ICED_DEP); // coffee-script >= 1.7.0 requires explicit registration for require() to work if (Iced.register) { Iced.register(); } }; Parser.yamlParser = function(filename, content) { if (!Yaml && !VisionmediaYaml) { // Lazy loading try { // Try to load the better js-yaml module Yaml = require(JS_YAML_DEP); } catch (e) { try { // If it doesn't exist, load the fallback visionmedia yaml module. VisionmediaYaml = require(YAML_DEP); } catch (e) { } } } if (Yaml) { return Yaml.load(content); } else if (VisionmediaYaml) { // The yaml library doesn't like strings that have newlines but don't // end in a newline: https://github.com/visionmedia/js-yaml/issues/issue/13 content += '\n'; if (typeof VisionmediaYaml.eval === 'function') { return VisionmediaYaml.eval(Parser.stripYamlComments(content)); } return VisionmediaYaml.parse(Parser.stripYamlComments(content)); } else { console.error('No YAML parser loaded. Suggest adding js-yaml dependency to your package.json file.') } }; Parser.jsonParser = function(filename, content) { try { return JSON.parse(content); } catch (e) { // All JS Style comments will begin with /, so all JSON parse errors that // encountered a syntax error will complain about this character. if (e.name !== 'SyntaxError' || e.message.indexOf('Unexpected token /') !== 0) { throw e; } if (!JSON5) { JSON5 = require(JSON5_DEP); } return JSON5.parse(content); } }; Parser.json5Parser = function(filename, content) { if (!JSON5) { JSON5 = require(JSON5_DEP); } return JSON5.parse(content); }; Parser.hjsonParser = function(filename, content) { if (!HJSON) { HJSON = require(HJSON_DEP); } return HJSON.parse(content); }; Parser.tomlParser = function(filename, content) { if(!TOML) { TOML = require(TOML_DEP); } return TOML.parse(content); }; Parser.csonParser = function(filename, content) { if (!CSON) { CSON = require(CSON_DEP); } // Allow comments in CSON files if (typeof CSON.parseSync === 'function') { return CSON.parseSync(Parser.stripComments(content)); } return CSON.parse(Parser.stripComments(content)); }; Parser.propertiesParser = function(filename, content) { if (!PPARSER) { PPARSER = require(PPARSER_DEP); } return PPARSER.parse(content, { namespaces: true, variables: true, sections: true }); }; /** * Strip all Javascript type comments from the string. * * The string is usually a file loaded from the O/S, containing * newlines and javascript type comments. * * Thanks to James Padolsey, and all who contributed to this implementation. * http://james.padolsey.com/javascript/javascript-comment-removal-revisted/ * * @protected * @method stripComments * @param fileStr {string} The string to strip comments from * @param stringRegex {RegExp} Optional regular expression to match strings that * make up the config file * @return {string} The string with comments stripped. */ Parser.stripComments = function(fileStr, stringRegex) { stringRegex = stringRegex || /(['"])(\\\1|.)+?\1/g; var uid = '_' + +new Date(), primitives = [], primIndex = 0; return ( fileStr /* Remove strings */ .replace(stringRegex, function(match){ primitives[primIndex] = match; return (uid + '') + primIndex++; }) /* Remove Regexes */ .replace(/([^\/])(\/(?!\*|\/)(\\\/|.)+?\/[gim]{0,3})/g, function(match, $1, $2){ primitives[primIndex] = $2; return $1 + (uid + '') + primIndex++; }) /* - Remove single-line comments that contain would-be multi-line delimiters E.g. // Comment /* <-- - Remove multi-line comments that contain would be single-line delimiters E.g. /* // <-- */ .replace(/\/\/.*?\/?\*.+?(?=\n|\r|$)|\/\*[\s\S]*?\/\/[\s\S]*?\*\//g, '') /* Remove single and multi-line comments, no consideration of inner-contents */ .replace(/\/\/.+?(?=\n|\r|$)|\/\*[\s\S]+?\*\//g, '') /* Remove multi-line comments that have a replaced ending (string/regex) Greedy, so no inner strings/regexes will stop it. */ .replace(RegExp('\\/\\*[\\s\\S]+' + uid + '\\d+', 'g'), '') /* Bring back strings & regexes */ .replace(RegExp(uid + '(\\d+)', 'g'), function(match, n){ return primitives[n]; }) ); }; /** * Strip YAML comments from the string * * The 2.0 yaml parser doesn't allow comment-only or blank lines. Strip them. * * @protected * @method stripYamlComments * @param fileStr {string} The string to strip comments from * @return {string} The string with comments stripped. */ Parser.stripYamlComments = function(fileStr) { // First replace removes comment-only lines // Second replace removes blank lines return fileStr.replace(/^\s*#.*/mg,'').replace(/^\s*[\n|\r]+/mg,''); }; /** * Parses the environment variable to the boolean equivalent. * Defaults to false * * @param {String} content - Environment variable value * @return {boolean} - Boolean value fo the passed variable value */ Parser.booleanParser = function(filename, content) { return content === 'true'; }; /** * Parses the environment variable to the number equivalent. * Defaults to undefined * * @param {String} content - Environment variable value * @return {Number} - Number value fo the passed variable value */ Parser.numberParser = function(filename, content) { const numberValue = Number(content); return Number.isNaN(numberValue) ? undefined : numberValue; }; var order = ['js', 'cjs', 'ts', 'json', 'json5', 'hjson', 'toml', 'coffee', 'iced', 'yaml', 'yml', 'cson', 'properties', 'xml', 'boolean', 'number']; var definitions = { cjs: Parser.jsParser, coffee: Parser.coffeeParser, cson: Parser.csonParser, hjson: Parser.hjsonParser, iced: Parser.icedParser, js: Parser.jsParser, json: Parser.jsonParser, json5: Parser.json5Parser, properties: Parser.propertiesParser, toml: Parser.tomlParser, ts: Parser.tsParser, xml: Parser.xmlParser, yaml: Parser.yamlParser, yml: Parser.yamlParser, boolean: Parser.booleanParser, number: Parser.numberParser }; Parser.getParser = function(name) { return definitions[name]; }; Parser.setParser = function(name, parser) { definitions[name] = parser; if (order.indexOf(name) === -1) { order.push(name); } }; Parser.getFilesOrder = function(name) { if (name) { return order.indexOf(name); } return order; }; Parser.setFilesOrder = function(name, newIndex) { if (Array.isArray(name)) { return order = name; } if (typeof newIndex === 'number') { var index = order.indexOf(name); order.splice(newIndex, 0, name); if (index > -1) { order.splice(index >= newIndex ? index +1 : index, 1); } } return order; }; node-config-3.3.7/raw.js000066400000000000000000000006001413461306600150430ustar00rootroot00000000000000/** * This is meant to wrap configuration objects that should be left as is, * meaning that the object or its prototype will not be modified in any way */ function RawConfig () { } function raw(rawObj) { var obj = Object.create(RawConfig.prototype); obj.resolve = function () { return rawObj; } return obj; } module.exports.RawConfig = RawConfig; module.exports.raw = raw; node-config-3.3.7/test/000077500000000000000000000000001413461306600146775ustar00rootroot00000000000000node-config-3.3.7/test/1-protected-test.js000066400000000000000000000660271413461306600203540ustar00rootroot00000000000000/** *

Unit tests

* * @module test */ var requireUncached = require('./_utils/requireUncached'); var vows = require('vows'); var assert = require('assert'); // Make a copy of the command line args var argvOrg = process.argv; /** *

Tests for underlying node-config utilities. To run type:

*
npm test
*

Or, in a project that uses node-config:

*
npm test config
* * @class ProtectedTest */ var CONFIG; vows.describe('Protected (hackable) utilities test') .addBatch({ // We initialize the object in a batch so that the globals get changed at /run-time/ not /require-time/, // avoiding conflicts with other tests. // We initialize in our own /batch/ because batches are run in serial, while individual contexts run in parallel. 'Library initialization': { topic : function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/config'; // Hard-code $NODE_ENV=test for testing process.env.NODE_ENV='test'; // Test for multi-instance applications process.env.NODE_APP_INSTANCE='3'; // Test $NODE_CONFIG environment and --NODE_CONFIG command line parameter process.env.NODE_CONFIG='{"EnvOverride":{"parm3":"overridden from $NODE_CONFIG","parm4":100}}'; process.argv.push('--NODE_CONFIG={"EnvOverride":{"parm5":"overridden from --NODE_CONFIG","parm6":101}}'); // Test Environment Variable Substitution var override = 'CUSTOM VALUE FROM JSON ENV MAPPING'; process.env['CUSTOM_JSON_ENVIRONMENT_VAR'] = override; // Dependencies CONFIG = requireUncached(__dirname + '/../lib/config'); return CONFIG; }, 'Library is available': function(config) { assert.isObject(config); } } }) .addBatch({ 'isObject() tests': { 'The function exists': function() { assert.isFunction(CONFIG.util.isObject); }, 'Correctly identifies objects': function() { assert.isTrue(CONFIG.util.isObject({A:"b"})); }, 'Correctly excludes non-objects': function() { assert.isFalse(CONFIG.util.isObject("some string")); assert.isFalse(CONFIG.util.isObject(45)); assert.isFalse(CONFIG.util.isObject([2, 3])); assert.isFalse(CONFIG.util.isObject(["a", "b"])); assert.isFalse(CONFIG.util.isObject(null)); assert.isFalse(CONFIG.util.isObject(undefined)); } }, '_cloneDeep() tests': { topic: function() { // Return an object for copy tests return { elem0:true, elem1:"Element 1", elem2:2, elem3:[1,2,3], elem4:function(){return "hello";}, elem5:{sub1:"sub 1",sub2:2,sub3:[1,2,3]}, elem6: {date: new Date, regexp: /test/i} }; }, 'The function exists': function() { assert.isFunction(CONFIG.util.cloneDeep); }, 'Original and copy should test equivalent (deep)': function(orig) { var copy = CONFIG.util.cloneDeep(orig); assert.deepEqual(copy, orig); }, 'The objects should be different': function(orig) { var copy = CONFIG.util.cloneDeep(orig); copy.elem1 = false; assert.notDeepEqual(copy, orig); }, 'Object clones should be objects': function(orig) { assert.isObject(CONFIG.util.cloneDeep({a:1, b:2})); }, 'Array clones should be arrays': function(orig) { assert.isArray(CONFIG.util.cloneDeep(["a", "b", 3])); }, 'Arrays should be copied by value, not by reference': function(orig) { var copy = CONFIG.util.cloneDeep(orig); assert.deepEqual(copy, orig); copy.elem3[0] = 2; // If the copy wasn't deep, elem3 would be the same object assert.notDeepEqual(copy, orig); }, 'Objects should be copied by value, not by reference': function(orig) { var copy = CONFIG.util.cloneDeep(orig); copy.elem5.sub2 = 3; assert.notDeepEqual(copy, orig); copy = CONFIG.util.cloneDeep(orig); copy.elem5.sub3[1] = 3; assert.notDeepEqual(copy, orig); }, 'Regexps and dates are preserved': function (orig) { var copy = CONFIG.util.cloneDeep(orig); assert.equal(copy.elem6.date.constructor.name, 'Date'); assert.equal(copy.elem6.regexp.toString(), '/test/i'); } }, 'extendDeep() tests': { 'The function exists': function() { assert.isFunction(CONFIG.util.extendDeep); }, 'Performs normal extend': function() { var orig = {elem1:"val1", elem2:"val2"}; var extWith = {elem3:"val3"}; var shouldBe = {elem1:"val1", elem2:"val2", elem3:"val3"}; assert.deepEqual(CONFIG.util.extendDeep(orig, extWith), shouldBe); }, 'Replaces non-objects': function() { var orig = {elem1:"val1", elem2:["val2","val3"],elem3:{sub1:"val4"}}; var extWith = {elem1:1,elem2:["val4"],elem3:"val3"}; var shouldBe = {elem1:1, elem2:["val4"],elem3:"val3"}; assert.deepEqual(CONFIG.util.extendDeep(orig, extWith), shouldBe); }, 'Merges objects': function() { var orig = {e1:"val1", elem2:{sub1:"val4",sub2:"val5"}}; var extWith = {elem2:{sub2:"val6",sub3:"val7"}}; var shouldBe = {e1:"val1", elem2:{sub1:"val4",sub2:"val6",sub3:"val7"}}; assert.deepEqual(CONFIG.util.extendDeep(orig, extWith), shouldBe); }, 'Merges dates': function() { var orig = {e1:"val1", elem2:{sub1:"val4",sub2:new Date(2015, 0, 1)}}; var extWith = {elem2:{sub2:new Date(2015, 0, 2),sub3:"val7"}}; var shouldBe = {e1:"val1", elem2:{sub1:"val4",sub2:new Date(2015, 0, 2),sub3:"val7"}}; assert.deepEqual(CONFIG.util.extendDeep(orig, extWith), shouldBe); }, 'Creates partial objects when mixing objects and non-objects': function () { var orig = {elem1: {sub1: 5}}; var ext1 = {elem1: {sub2: 7}}; var ext2 = {elem1: 7}; var ext3 = {elem1: {sub3: 13}}; // When we get to ext2, the 7 clears all memories of sub1 and sub3. Then, when // we merge with ext3, the 7 is replaced by the new object. var expected = {elem1: {sub3: 13}}; assert.deepEqual(CONFIG.util.extendDeep(orig, ext1, ext2, ext3), expected); }, 'Correctly types new objects and arrays': function() { var orig = {e1:"val1", e3:["val5"]}; var extWith = {e2:{elem1:"val1"}, e3:["val6","val7"]}; var shouldBe = {e1:"val1", e2:{elem1:"val1"}, e3:["val6","val7"]}; var ext = CONFIG.util.extendDeep({}, orig, extWith); assert.isObject(ext.e2); assert.isArray(ext.e3); assert.deepEqual(ext, shouldBe); }, 'Keeps non-merged objects intact': function() { var orig = {e1:"val1", elem2:{sub1:"val4",sub2:"val5"}}; var shouldBe = {e1:"val1", elem2:{sub1:"val4",sub2:"val5"}}; var extWith = {elem3:{sub2:"val6",sub3:"val7"}}; CONFIG.util.extendDeep({}, orig, extWith); assert.deepEqual(orig, shouldBe); }, 'Keeps prototype methods intact': function() { var orig = Object.create({has: function() {}}); var result = CONFIG.util.extendDeep({}, orig, {}); assert.isFunction(result.has); } }, 'equalsDeep() tests': { 'The function exists': function() { assert.isFunction(CONFIG.util.equalsDeep); }, 'Succeeds on two empty objects': function() { assert.isTrue(CONFIG.util.equalsDeep({}, {})); }, 'Succeeds on array comparisons': function() { assert.isTrue(CONFIG.util.equalsDeep([1,'hello',2], [1,'hello',2])); }, 'Succeeds on the same object': function() { var a = {hello:'world'}; assert.isTrue(CONFIG.util.equalsDeep(a, a)); }, 'Succeeds on a regular object': function() { var a = {value_3: 14, hello:'world', value_1: 29}; var b = {value_1: 29, hello:'world', value_3: 14}; assert.isTrue(CONFIG.util.equalsDeep(a, b)); }, 'Succeeds on a deep object': function() { var a = {value_3: 14, hello:'world', value_1: 29, value_4:['now','is','the','time']}; var b = {value_1: 29, hello:'world', value_3: 14, value_4:['now','is','the','time']}; var c = {creditLimit: 10000, deepValue: a}; var d = {deepValue: b, creditLimit:10000}; assert.isTrue(CONFIG.util.equalsDeep(c, d)); }, 'Fails if either object is null': function() { assert.isFalse(CONFIG.util.equalsDeep({}, null)); assert.isFalse(CONFIG.util.equalsDeep(null, {})); assert.isFalse(CONFIG.util.equalsDeep(null, null)); }, 'Fails if either object is undefined': function() { var a = {}; assert.isFalse(CONFIG.util.equalsDeep({})); assert.isFalse(CONFIG.util.equalsDeep(a['noElement'], {})); }, 'Fails if either object is undefined': function() { var a = {}; assert.isFalse(CONFIG.util.equalsDeep({})); assert.isFalse(CONFIG.util.equalsDeep(a['noElement'], {})); }, 'Fails if object1 has more elements': function() { var a = {value_3: 14, hello:'world', value_1: 29, otherElem: 40}; var b = {value_1: 29, hello:'world', value_3: 14}; assert.isFalse(CONFIG.util.equalsDeep(a, b)); }, 'Fails if object2 has more elements': function() { var a = {value_1: 29, hello:'world', value_3: 14}; var b = {value_3: 14, hello:'world', value_1: 29, otherElem: 40}; assert.isFalse(CONFIG.util.equalsDeep(a, b)); }, 'Fails if any value is different': function() { var a = {value_1: 30, hello:'world', value_3: 14, value_4:['now','is','the','time']}; var b = {value_1: 29, hello:'world', value_3: 14, value_4:['now','is','the','time']}; assert.isFalse(CONFIG.util.equalsDeep(a, b)); var a = {value_1: 29, hello:'world', value_3: 14, value_4:['now','is','the','time']}; var b = {value_1: 29, hello:'world', value_3: 14, value_4:['now','isnt','the','time']}; assert.isFalse(CONFIG.util.equalsDeep(a, b)); } }, 'diffDeep() tests': { 'The function exists': function() { assert.isFunction(CONFIG.util.diffDeep); }, 'Returns an empty object if no differences': function() { var a = {value_3: 14, hello:'world', value_1: 29}; var b = {value_1: 29, hello:'world', value_3: 14}; assert.equal(typeof(CONFIG.util.diffDeep(a,b)), 'object'); assert.isTrue(Object.keys(CONFIG.util.diffDeep(a, b)).length == 0); }, 'Returns an empty object if no differences (deep)': function() { var a = {value_3: 14, hello:'world', value_1: 29, value_4:[1,'hello',2], deepObj:{a:22,b:{c:45,a:44}}}; var b = {value_1: 29, hello:'world', value_3: 14, value_4:[1,'hello',2], deepObj:{a:22,b:{a:44,c:45}}}; assert.equal(typeof(CONFIG.util.diffDeep(a,b)), 'object'); assert.isTrue(Object.keys(CONFIG.util.diffDeep(a, b)).length == 0); }, 'Returns just the diff values': function() { var a = {value_3: 14, hello:'wurld', value_1: 29, deepObj:{a:22,b:{c:45,a:44}}}; var b = {value_1: 29, hello:'world', value_3: 14, deepObj:{a:22,b:{a:44,c:45}}}; var diff = CONFIG.util.diffDeep(a,b); assert.equal(Object.keys(diff).length, 1); assert.equal(diff.hello, 'world'); }, 'Returns just the diff values (deep)': function() { var a = {value_3: 14, hello:'wurld', value_1: 29, value_4:[1,'hello',2], deepObj:{a:22,b:{c:45,a:44}}}; var b = {value_1: 29, hello:'wurld', value_3: 14, value_4:[1,'goodbye',2], deepObj:{a:22,b:{a:45,c:44}}}; var diff = CONFIG.util.diffDeep(a,b); assert.equal(Object.keys(diff).length, 2); assert.equal(Object.keys(diff.deepObj).length, 1); assert.equal(Object.keys(diff.deepObj.b).length, 2); assert.equal(diff.deepObj.b.a, 45); assert.equal(diff.deepObj.b.c, 44); assert.deepEqual(diff.value_4, [1, 'goodbye', 2]); } }, 'substituteDeep() tests': { topic: function () { var topic = { TopLevel: 'SOME_TOP_LEVEL', TestModule: { parm1: "SINGLE_SECOND_LEVEL" }, Customers: { dbHost: 'DB_HOST', dbName: 'DB_NAME', oauth: { key: 'OAUTH_KEY', secret: 'OAUTH_SECRET' } } }; return topic; }, 'returns an empty object if the variables mapping is empty': function (topic) { vars = {}; var substituted = CONFIG.util.substituteDeep(topic, vars); assert.deepEqual(substituted, {}); }, 'returns an empty object if none of the variables map to leaf strings': function (topic) { vars = { NON_EXISTENT_VAR: 'ignore_this' }; var substituted = CONFIG.util.substituteDeep(topic, vars); assert.deepEqual(substituted, {}); }, 'returns an object with keys matching down to mapped existing variables': function (topic) { vars = { 'SOME_TOP_LEVEL': 5, 'DB_NAME': 'production_db', 'OAUTH_SECRET': '123456', 'PATH': 'ignore other environment variables' }; var substituted = CONFIG.util.substituteDeep(topic, vars); assert.deepEqual(substituted, { TopLevel: 5, Customers: { dbName: 'production_db', oauth: { secret: '123456' } } }); }, 'Returns an object with keys matching down to mapped existing and defined variables': function (topic) { vars = { 'SOME_TOP_LEVEL': 0, 'DB_HOST': undefined, 'DB_NAME': '', 'OAUTH_SECRET': 'false', 'OAUTH_KEY': 'null', 'PATH': '' }; var substituted = CONFIG.util.substituteDeep(topic, vars); assert.deepEqual(substituted, { TopLevel: 0, Customers: { oauth: { key: 'null', secret: 'false' } } }); }, 'returns an object with keys matching down to mapped existing variables with JSON content': function (topic) { vars = { 'DB_HOST': '{"port":"3306","host":"example.com"}' }; var substituted = CONFIG.util.substituteDeep(topic, vars); assert.deepEqual(substituted, { Customers: { dbHost: '{"port":"3306","host":"example.com"}' } }); }, 'Returns an object with keys matching down to mapped existing and defined variables with JSON content': function (topic) { var dbHostObject = { param1WithZero: 0, param2WithFalse: false, param3WithNull: null, param4WithEmptyObject: {}, param5WithEmptyArray: [], param6WithEmptyString: '' }; var dbHostObjectWithUndefinedProperty = Object.assign({}, dbHostObject, { param7WithUndefined: undefined }); vars = { 'DB_HOST': JSON.stringify(dbHostObjectWithUndefinedProperty) }; var substituted = CONFIG.util.substituteDeep(topic, vars); assert.deepEqual(substituted, { Customers: { dbHost: JSON.stringify(dbHostObject) } }); }, 'returns an object with keys matching down to mapped and JSON-parsed existing variables': function (topic) { vars = { 'DB_HOST': '{"port":"3306","host":"example.com"}' }; topic.Customers.dbHost = {__name: 'DB_HOST', __format: 'json'}; var substituted = CONFIG.util.substituteDeep(topic, vars); assert.deepEqual(substituted, { Customers: { dbHost: { port: '3306', host: 'example.com' } } }); }, 'Returns an object with keys matching down to mapped and JSON-parsed existing and defined variables': function (topic) { var dbHostObject = { param1WithZero: 0, param2WithFalse: false, param3WithNull: null, param4WithEmptyObject: {}, param5WithEmptyArray: [], param6WithEmptyString: '' }; var dbHostObjectWithUndefinedProperty = Object.assign({}, dbHostObject, { param7WithUndefined: undefined }); vars = { 'DB_HOST': JSON.stringify(dbHostObjectWithUndefinedProperty) }; topic.Customers.dbHost = {__name: 'DB_HOST', __format: 'json'}; var substituted = CONFIG.util.substituteDeep(topic, vars); assert.deepEqual(substituted, { Customers: { dbHost: dbHostObject } }); }, // Testing all the things in variable maps that don't make sense because ENV vars are always // strings. 'Throws an error for leaf Array values': function (topic) { vars = { NON_EXISTENT_VAR: 'ignore_this' }; topic.Customers.dbHost = ['a', 'b', 'c']; assert.throws(function () { CONFIG.util.substituteDeep(topic, vars); }); }, 'Throws an error for leaf Boolean values': function (topic) { vars = { NON_EXISTENT_VAR: 'ignore_this' }; topic.Customers.dbHost = false; assert.throws(function () { CONFIG.util.substituteDeep(topic, vars); }); }, 'Throws an error for leaf Numeric values': function (topic) { vars = { NON_EXISTENT_VAR: 'ignore_this' }; topic.Customers.dbHost = 443; assert.throws(function () { CONFIG.util.substituteDeep(topic, vars); }); }, 'Throws an error for leaf null values': function (topic) { vars = { NON_EXISTENT_VAR: 'ignore_this' }; topic.Customers.dbHost = null; assert.throws(function () { CONFIG.util.substituteDeep(topic, vars); }); }, 'Throws an error for leaf Undefined values': function (topic) { vars = { NON_EXISTENT_VAR: 'ignore_this' }; topic.Customers.dbHost = undefined; assert.throws(function () { CONFIG.util.substituteDeep(topic, vars); }); }, 'Throws an error for leaf NaN values': function (topic) { vars = { NON_EXISTENT_VAR: 'ignore_this' }; topic.Customers.dbHost = NaN; assert.throws(function () { CONFIG.util.substituteDeep(topic, vars); }); }, 'Throws an error with message describing variables name that throw a parser error': function(topic) { var JSON_WITH_SYNTAX_ERROR = '{"port":"3306","host" "example.com"}' vars = { 'DB_HOST': JSON_WITH_SYNTAX_ERROR }; topic.Customers.dbHost = {__name: 'DB_HOST', __format: 'json'}; try { CONFIG.util.substituteDeep(topic, vars); assert.isTrue(false); } catch(err) { assert.match(err.message, /__format parser error in DB_HOST: /); } } }, 'setPath() tests:': { topic: function () { return { TestModule: { parm1: "value1" }, Customers: { dbHost: 'base', dbName: 'from_default_js', oauth: { key: 'a_api_key', secret: 'an_api_secret' } }, EnvOverride: { parm_number_1: "from_default_js", parm2: 22 } }; }, 'Ignores null values': function (topic) { CONFIG.util.setPath(topic, ['Customers', 'oauth', 'secret'], null); assert.equal(topic.Customers.oauth.secret, 'an_api_secret'); }, 'Creates top-level keys to set new values': function (topic) { CONFIG.util.setPath(topic, ['NewKey'], 'NEW_VALUE'); assert.equal(topic.NewKey, 'NEW_VALUE'); }, 'Creates sub-keys to set new values': function (topic) { CONFIG.util.setPath(topic, ['TestModule', 'oauth'], 'NEW_VALUE'); assert.equal(topic.TestModule.oauth, 'NEW_VALUE'); }, 'Creates parents to set new values': function (topic) { CONFIG.util.setPath(topic, ['EnvOverride', 'oauth', 'secret'], 'NEW_VALUE'); assert.equal(topic.EnvOverride.oauth.secret, 'NEW_VALUE'); }, 'Overwrites existing values': function (topic) { CONFIG.util.setPath(topic, ['Customers'], 'NEW_VALUE'); assert.equal(topic.Customers, 'NEW_VALUE'); } }, 'stripComments() tests': { // Only testing baseline stripComments functionality. // This implementation handles lots of edge cases that aren't in these tests 'The function exists': function() { assert.isFunction(CONFIG.util.stripComments); }, 'Leaves a simple string without comments alone': function() { var str = "Hello\nWorld"; assert.equal(CONFIG.util.stripComments(str), str); }, 'Strips out line-type comments': function() { var str1 = "var a='Hello'; // Comment about the a variable"; var str2 = "var a='Hello'; "; assert.equal(CONFIG.util.stripComments(str1), str2); }, 'Strips out block-type comments': function() { var str1 = "var a='Hello';/* Block Comment */ var b=24"; var str2 = "var a='Hello'; var b=24"; assert.equal(CONFIG.util.stripComments(str1), str2); }, 'Strips out multi-line block comments': function() { var str1 = "var a='Hello';\n/* Block Comment\n Line 2 comment\n*/\nvar b=24"; var str2 = "var a='Hello';\n\nvar b=24"; assert.equal(CONFIG.util.stripComments(str1), str2); } }, 'parseFile() tests': { topic: function() { return CONFIG.util.parseFile(__dirname + '/config/default.yaml'); }, 'The function exists': function() { assert.isFunction(CONFIG.util.parseFile); }, 'An object is returned': function(config) { assert.isObject(config); }, 'The correct object is returned': function(config) { assert.isObject(config.Customers); assert.isTrue(config.Customers.dbName == 'from_default_yaml'); assert.isTrue(config.Customers.dbPort == 5984); assert.isObject(config.AnotherModule); assert.isTrue(config.AnotherModule.parm2 == "value2"); } }, 'CSON parse tests': { topic: function() { return CONFIG.util.parseFile(__dirname + '/config/default.cson'); }, 'The function exists': function() { assert.isFunction(CONFIG.util.parseFile); }, 'An object is returned': function(config) { assert.isObject(config); }, 'The correct object is returned': function(config) { assert.isObject(config.Customers); assert.isTrue(config.Customers.dbName == 'from_default_cson'); assert.isTrue(config.Customers.dbPassword == 'password will be overwritten.'); assert.isObject(config.AnotherModule); assert.isTrue(config.AnotherModule.parm4 == "value4"); assert.isArray(config.Customers.lang); } }, '.properties parse tests': { topic: function() { return CONFIG.util.parseFile(__dirname + '/config/default.properties'); }, 'The function exists': function() { assert.isFunction(CONFIG.util.parseFile); }, 'An object is returned': function(config) { assert.isObject(config); }, 'The correct object is returned': function(config) { assert.isObject(config.AnotherModule); assert.isTrue(config.AnotherModule.parm5 == "value5"); assert.isObject(config['key with spaces']); assert.isTrue(config['key with spaces'].another_key == 'hello'); assert.isUndefined(config.ignore_this_please); assert.isUndefined(config.i_am_a_comment); }, 'Variable replacements are working': function(config) { assert.isTrue(config.replacement.param == "foobar") }, 'Sections are supported': function(config) { assert.isDefined(config.section.param); assert.isUndefined(config.param); } }, 'loadFileConfigs() tests': { topic: function() { return CONFIG.util.loadFileConfigs(); }, 'The function exists': function() { assert.isFunction(CONFIG.util.loadFileConfigs); }, 'An object is returned': function(configs) { assert.isObject(configs); }, 'The correct object is returned': function(config) { assert.isObject(config.Customers); assert.isTrue(config.Customers.dbHost == 'base'); assert.isTrue(config.Customers.dbName == 'override_from_runtime_json'); } }, 'attachProtoDeep() tests': { topic: function() { // Create an object that contains other objects to see // that the prototype is added to all objects. var watchThis = { subObject: { item1: 23, subSubObject: { item2: "hello" } } }; return CONFIG.util.attachProtoDeep(watchThis); }, 'The function exists': function() { assert.isFunction(CONFIG.util.attachProtoDeep); }, 'The original object is returned': function(config) { assert.isObject(config); assert.isTrue(config.subObject.item1 === 23); assert.isTrue(config.subObject.subSubObject.item2 === "hello"); }, 'The cloneDeep method is attached to the object': function(config) { assert.isTrue({a:27}.a == config.util.cloneDeep({a:27}).a); }, 'The cloneDeep method is also attached to sub-objects': function(config) { assert.isTrue({a:27}.a == config.subObject.util.cloneDeep({a:27}).a); assert.isTrue({a:27}.a == config.subObject.subSubObject.util.cloneDeep({a:27}).a); }, 'Prototype methods are not exposed in the object': function(config) { // This test is here because altering object.__proto__ places the method // directly onto the object. That caused problems when iterating over the // object. This implementation does the same thing, but hides them. assert.isTrue(JSON.stringify(config) == '{"subObject":{"item1":23,"subSubObject":{"item2":"hello"}}}'); } }, 'getCmdLineArg() tests': { topic: function() { // Set process.argv example object var testArgv = [ process.argv[0], process.argv[1], '--NODE_ENV=staging' ]; process.argv = testArgv; return CONFIG.util.getCmdLineArg('NODE_ENV'); }, 'The function exists': function() { assert.isFunction(CONFIG.util.getCmdLineArg); }, 'NODE_ENV should be staging': function(nodeEnv) { assert.equal(nodeEnv, 'staging'); }, 'Returns false if the argument did not match': function() { assert.isFalse(CONFIG.util.getCmdLineArg('NODE_CONFIG_DIR')); }, 'Returns the argument (alternative syntax)': function() { process.argv.push('--NODE_CONFIG_DIR=/etc/nodeConfig'); assert.equal(CONFIG.util.getCmdLineArg('NODE_CONFIG_DIR'), '/etc/nodeConfig'); }, 'Returns always the first matching': function() { process.argv.push('--NODE_ENV=test'); assert.equal(CONFIG.util.getCmdLineArg('NODE_ENV'), 'staging'); }, 'Revert original process arguments': function() { assert.notEqual(process.argv, argvOrg); process.argv = argvOrg; assert.equal(process.argv, argvOrg); } }, 'toObject() tests': { topic: function() { return CONFIG.util.loadFileConfigs(); }, 'The function exists': function() { assert.isFunction(CONFIG.util.toObject); }, 'Returns a serialized version of the current instance if no argument is provided': function() { assert.notDeepStrictEqual(CONFIG.util.toObject(), CONFIG); }, 'Returns a POJO': function() { assert.ok(!(CONFIG.util.toObject() instanceof CONFIG.constructor)); }, 'Returns a serialized version of whatever argument is provided': function() { assert.notDeepStrictEqual(CONFIG.get('Customers'), { dbHost: 'base', dbName: 'override_from_runtime_json', dbPort: 5999, dbString: 'override_from_runtime_json:5999', random: 0.08624527123827352, dbPassword: 'real password', dbPassword2: 'another password', lang: ['en','de','es'], altDbPort: 4400, altDbPort1: 2209, emptySub: null }); } } }) .export(module); node-config-3.3.7/test/10-config/000077500000000000000000000000001413461306600163625ustar00rootroot00000000000000node-config-3.3.7/test/10-config/default.json000066400000000000000000000006151413461306600207030ustar00rootroot00000000000000{ "Customers": { "dbName":"from_default_json", "dbPassword":"password will be overwritten.", "lang":["en","es"] }, "AnotherModule": { "parm1":"value1" }, "staticArray": [2,1,3], "Inline": {"a": "", "b": "1"}, "ContainsQuote": "\"this has a quote\"", "MoreComplexQuote": "Test String" } node-config-3.3.7/test/10-config/encrypted.json000066400000000000000000000001201413461306600212430ustar00rootroot00000000000000GITCRYPTùEc¢…P?T§ÅD” ðû@šÏ•·>Ï äXHì›ê¤ÿ ‚µ­(T¦^ÃBÅnì¾e&,ßj•'râªVóª'ŸÅÂBnode-config-3.3.7/test/10-config/git-crypt-symmetric-key000066400000000000000000000002241413461306600230250ustar00rootroot00000000000000GITCRYPTKEY LçB>úuÂåŠà’¹É=i{@±Ïur/¼²RQªÍ@×3žnå%|K}äƒÁ¢w¾r®C€Ú3ÌGÁp\óAÚ¶+7xL/ª-òSþ…Z[ Ón lEP`ùpjŠª&node-config-3.3.7/test/10-gitcrypt-test.js000066400000000000000000000034011413461306600202730ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Dependencies var vows = require('vows'), assert = require('assert'), path = require('path'); var CONFIG; vows.describe('Test git-crypt integration') .addBatch({ 'initialization with CONFIG_SKIP_GITCRYPT': { topic : function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/10-config'; // Test for multi-instance applications delete process.env.NODE_APP_INSTANCE; process.env.NODE_CONFIG_STRICT_MODE = false; // Hard-code $NODE_ENV=encrypted for testing process.env.NODE_ENV='encrypted'; // Test Environment Variable Substitution process.env.CONFIG_SKIP_GITCRYPT = 1; delete process.env["NODE_CONFIG"] delete process.env["CUSTOM_JSON_ENVIRONMENT_VAR"]; CONFIG = requireUncached(__dirname + '/../lib/config'); return CONFIG; }, 'Config library is available': function() { assert.isObject(CONFIG); }, 'Loading configurations from a JSON file is correct': function() { assert.equal(CONFIG.Customers.dbPassword, 'password will be overwritten.'); } }, }) .addBatch({ 'initialization with encrypted files without CONFIG_SKIP_GITCRYPT': { 'An exception is thrown if CONFIG_SKIP_GITCRYPT is not set': function() { // Hard-code $NODE_ENV=encrypted for testing process.env.NODE_ENV='encrypted'; // Test Environment Variable Substitution process.env.CONFIG_SKIP_GITCRYPT = 0; delete process.env["CONFIG_SKIP_GITCRYPT"]; assert.throws( function () { CONFIG = requireUncached(__dirname + '/../lib/config'); }, /Cannot parse config file/ ); } } }) .export(module);node-config-3.3.7/test/11-regexp.js000066400000000000000000000013321413461306600167450ustar00rootroot00000000000000'use strict'; process.env.NODE_CONFIG_DIR = __dirname + '/config'; process.env.NODE_ENV = 'test'; process.env.NODE_APP_INSTANCE = 'regexp'; var requireUncached = require('./_utils/requireUncached'); var CONFIG = requireUncached(__dirname + '/../lib/config'); var assert = require('assert'); var vows = require('vows'); vows.describe('Tests for regexp').addBatch({ 'Regexp tests Tests': { topic: function() { return CONFIG; }, 'A regexp should not be replaced': function() { assert.deepEqual(CONFIG.SomeMore.regexp1, /This is a Regexp/g); }, 'A regexp should be replaced': function() { assert.deepEqual(CONFIG.SomeMore.regexp2, /This is the replaced/g); } } }) .export(module); node-config-3.3.7/test/12-config/000077500000000000000000000000001413461306600163645ustar00rootroot00000000000000node-config-3.3.7/test/12-config/apollo.json000066400000000000000000000000631413461306600205440ustar00rootroot00000000000000{ "deploymentUsed": "node-config-env-provided" } node-config-3.3.7/test/12-config/development.json000066400000000000000000000000411413461306600215740ustar00rootroot00000000000000{ "deploymentUsed": "default" }node-config-3.3.7/test/12-config/mercury.json000066400000000000000000000000531413461306600207430ustar00rootroot00000000000000{ "deploymentUsed": "node-env-provided" }node-config-3.3.7/test/12-node_env-override.js000066400000000000000000000060671413461306600211000ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); 'use strict'; var NODE_CONFIG_DIR = __dirname + '/12-config' // Dependencies var vows = require('vows'), assert = require('assert'); vows.describe('Tests for NODE_*_ENV load order') .addBatch({ 'Library initialization': { topic: function() { // other test suites modify process.env, let's reset // the following batches with known values and // make sure we have a valid CONFIG object. delete process.env.NODE_ENV; delete process.env.NODE_CONFIG_ENV; process.env.NODE_CONFIG_DIR = NODE_CONFIG_DIR; return requireUncached(__dirname + '/../lib/config'); }, 'Library is available': function(config) { assert.isObject(config); } } }) .addBatch({ 'Verify behavior of undefined NODE_CONFIG_ENV and undefined NODE_ENV': { topic: function() { delete process.env.NODE_ENV; delete process.env.NODE_CONFIG_ENV; return requireUncached(__dirname + '/../lib/config'); }, 'default \'development\' deployment should be used': function(CONFIG) { assert.equal(CONFIG.util.getEnv('NODE_ENV'), 'development'); assert.equal(CONFIG.get('deploymentUsed'), 'default'); } } }) .addBatch({ 'Verify behavior of undefined NODE_CONFIG_ENV with defined NODE_ENV': { topic: function() { process.env.NODE_ENV = 'apollo'; return requireUncached(__dirname + '/../lib/config'); }, 'NODE_CONFIG_ENV by itself should be used': function(CONFIG) { assert.equal(CONFIG.util.getEnv('NODE_CONFIG_ENV'), 'apollo'); assert.equal(CONFIG.get('deploymentUsed'), 'node-config-env-provided'); }, 'Revert process runtime changes': function() { delete process.env.NODE_ENV; } } }) .addBatch({ 'Verify behavior of a defined NODE_CONFIG_ENV and undefined NODE_ENV': { topic: function() { process.env.NODE_CONFIG_ENV = 'mercury'; return requireUncached(__dirname + '/../lib/config'); }, 'NODE_ENV by itself should be used': function(CONFIG) { assert.equal(CONFIG.util.getEnv('NODE_CONFIG_ENV'), 'mercury'); assert.equal(CONFIG.get('deploymentUsed'), 'node-env-provided'); }, 'Revert process runtime changes': function() { delete process.env.NODE_ENV; } } }) .addBatch({ 'Verify behavior of specified NODE_CONFIG_ENV overriding NODE_ENV': { topic: function() { process.env.NODE_CONFIG_ENV = 'apollo'; process.env.NODE_ENV = 'mercury'; return requireUncached(__dirname + '/../lib/config'); }, 'NODE_CONFIG_ENV value should be used': function(CONFIG) { assert.equal(CONFIG.get('deploymentUsed'), 'node-config-env-provided'); }, 'Revert process runtime changes': function() { delete process.env.NODE_CONFIG_ENV; delete process.env.NODE_ENV; } } }) .addBatch({ 'Library destructor': { 'Revert process runtime changes': function() { delete process.env.NODE_CONFIG_DIR; delete process.env.NODE_CONFIG_ENV; delete process.env.NODE_ENV; } } }) .export(module); node-config-3.3.7/test/13-node_env-hostname.js000066400000000000000000000026661413461306600211010ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); 'use strict'; var NODE_CONFIG_DIR = __dirname + '/12-config' // Dependencies var vows = require('vows'), assert = require('assert'); vows.describe('Tests for HOSTNAME and HOST environment variables') .addBatch({ 'When there is no HOSTNAME neither HOST env': { topic: function() { // Test HOST and HOSTNAME delete process.env.HOST; delete process.env.HOSTNAME; return requireUncached(__dirname + '/../lib/config'); }, 'OS.hostname() is the winner': function(CONFIG) { assert.equal(typeof CONFIG.util.getEnv('HOSTNAME'), 'string'); } } }) .addBatch({ 'When HOSTNAME env is set': { topic: function() { // Test HOST and HOSTNAME delete process.env.HOST; process.env.HOSTNAME = 'some.machine'; return requireUncached(__dirname + '/../lib/config'); }, 'HOSTNAME env variable is the winner': function(CONFIG) { assert.equal(CONFIG.util.getEnv('HOSTNAME'), 'some.machine'); } } }) .addBatch({ 'When HOST env is set': { topic: function() { // Test HOST and HOSTNAME delete process.env.HOSTNAME; process.env.HOST = 'other.machine'; return requireUncached(__dirname + '/../lib/config'); }, 'HOST env variable is the winner': function(CONFIG) { assert.equal(CONFIG.util.getEnv('HOSTNAME'), 'other.machine'); } } }) .export(module); node-config-3.3.7/test/14-config/000077500000000000000000000000001413461306600163665ustar00rootroot00000000000000node-config-3.3.7/test/14-config/bare-metal.json000066400000000000000000000000771413461306600212760ustar00rootroot00000000000000{ "db": { "name": "bare-metal-config-env-provided" } } node-config-3.3.7/test/14-config/cloud.json000066400000000000000000000001001413461306600203560ustar00rootroot00000000000000{ "db": { "name": "development-config-env-provided" } } node-config-3.3.7/test/14-config/development.json000066400000000000000000000000431413461306600216000ustar00rootroot00000000000000{ "db": { "port": 3000 } } node-config-3.3.7/test/14-config/local-cloud.json000066400000000000000000000000601413461306600214530ustar00rootroot00000000000000{ "app": { "context": "local cloud" } } node-config-3.3.7/test/14-config/local-development.json000066400000000000000000000000661413461306600226750ustar00rootroot00000000000000{ "app": { "message": "local development" } } node-config-3.3.7/test/14-config/test-bare-metal.json000066400000000000000000000000461413461306600222470ustar00rootroot00000000000000{ "host": { "os": "linux" } } node-config-3.3.7/test/14-config/test-development.json000066400000000000000000000000511413461306600225540ustar00rootroot00000000000000{ "host": { "arch": "x86_64" } } node-config-3.3.7/test/14-node_env-load-multiple-files.js000066400000000000000000000037201413461306600231240ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); 'use strict'; var vows = require('vows'), assert = require('assert'); vows.describe('Tests for load multiple config files that match NODE_ENV values') .addBatch({ 'When there is \'cloud\' and \'development\' values in NODE_ENV': { topic: function() { process.env.NODE_ENV = 'development,cloud' process.env.NODE_CONFIG_DIR = __dirname + '/14-config' return requireUncached(__dirname + '/../lib/config'); }, 'Values ​​of the corresponding files are loaded': function(CONFIG) { assert.equal(CONFIG.get('db.name'), 'development-config-env-provided'); assert.equal(CONFIG.get('db.port'), 3000); }, 'Values ​​of the corresponding local files are loaded': function(CONFIG) { assert.equal(CONFIG.get('app.context'), 'local cloud'); assert.equal(CONFIG.get('app.message'), 'local development'); }, } }) .addBatch({ 'When there is \'cloud\' and \'bare-metal\' values in NODE_ENV and HOST is \'test\'': { topic: function() { process.env.NODE_ENV = 'development,bare-metal' process.env.NODE_CONFIG_DIR = __dirname + '/14-config' process.env.HOST = 'test' return requireUncached(__dirname + '/../lib/config'); }, 'Values ​​of the corresponding files with host prefix are loaded': function(CONFIG) { assert.equal(CONFIG.get('host.os'), 'linux'); assert.equal(CONFIG.get('host.arch'), 'x86_64'); } } }) .addBatch({ 'When there are conflicting values ​​in the files': { topic: function() { process.env.NODE_ENV = 'cloud,bare-metal' process.env.NODE_CONFIG_DIR = __dirname + '/14-config' return requireUncached(__dirname + '/../lib/config'); }, 'Priority of file values is merged by order that was defined in NODE_ENV': function(CONFIG){ assert.equal(CONFIG.get('db.name'), 'bare-metal-config-env-provided'); } } }) .export(module); node-config-3.3.7/test/15-async-configs.js000066400000000000000000000045541413461306600202330ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); var resolveAsyncConfigs = require('../async').resolveAsyncConfigs; // Test declaring async values. // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/15-config'; // Hard-code $NODE_ENV=test for testing process.env.NODE_ENV='test'; // Test for multi-instance applications process.env.NODE_APP_INSTANCE='async'; // Because require'ing config creates and caches a global singleton, // We have to invalidate the cache to build new object based on the environment variables above var CONFIG = requireUncached(__dirname + '/../lib/config'); // Dependencies var vows = require('vows'), assert = require('assert'); vows.describe('Tests for async values - JavaScript').addBatch({ 'Configuration file Tests': { topic: function() { resolveAsyncConfigs(CONFIG).then(function(config) { this.callback(null, config); }.bind(this)).catch(function(err) { this.callback(err); }.bind(this)); }, 'Using asyncConfig() in a config file causes value to be evaluated by resolveAsyncConfigs': function() { assert.equal(CONFIG.welcomeEmail.subject, 'Welcome to New Instance!'); }, 'values which are functions remain untouched unless they are instance of AsyncConfig': function() { // If this had been treated as a async config value it would blow-up. assert.equal(CONFIG.welcomeEmail.aFunc(), 'Still just a function.'); }, // This async function didn't use args, but relied 'this' being bound to the main config object "async functions can simply refer to 'this'" : function () { assert.equal(CONFIG.welcomeEmail.justThis, 'Welcome to this New Instance!'); }, "async promises which return objects should still be treated as a single value." : function () { assert.deepEqual(CONFIG.get('map.centerPoint'), { lat: 3, lon: 4 }); }, "async promise return original value." : function () { assert.equal(CONFIG.original.original, 'an original value'); }, "second async promise return local value." : function () { assert.equal(CONFIG.original.originalPromise, 'not an original value'); }, "verify deferred functionality plays nicely with AsyncConfig." : function () { assert.equal(CONFIG.promiseSubject, 'New Instance! Welcome to New Instance!'); }, } }).export(module);node-config-3.3.7/test/15-config/000077500000000000000000000000001413461306600163675ustar00rootroot00000000000000node-config-3.3.7/test/15-config/default.js000066400000000000000000000025651413461306600203610ustar00rootroot00000000000000 var asyncConfig = require('../../async').asyncConfig; var config = { siteTitle : 'Site title', latitude : 1, longitude : 2, }; // Set up a default value which refers to another value. // The resolution of the value is deferred until all the config files have been loaded // So that if 'config.siteTitle' is overridden, this will point to the correct value. config.welcomeEmail = { subject : asyncConfig(async function (cfg) { var siteTitle = await Promise.resolve(cfg.siteTitle); return "Welcome to "+siteTitle; }), promiseSubject: asyncConfig(Promise.resolve("Welcome to Promise response")), // A plain function should be not disturbed. aFunc : function () { return "Still just a function."; }, // Look ma, no arg passing. The main config object is bound to 'this' justThis: asyncConfig(async function () { var siteTitle = await Promise.resolve(this.siteTitle); return "Welcome to this "+siteTitle; }), }; config.map = { centerPoint : asyncConfig(async function () { var latitude = await Promise.resolve(this.latitude); return { lat: latitude, lon: this.longitude }; }), }; config.original = { // An original value passed to deferred function original: "an original value", // An original value passed to deferred function originalPromise: asyncConfig(Promise.resolve("this will not be used")), }; module.exports = config; node-config-3.3.7/test/15-config/local.js000066400000000000000000000011761413461306600200240ustar00rootroot00000000000000var asyncConfig = require('../../async').asyncConfig; var config = { siteTitle : 'New Instance!', promiseSubject: asyncConfig(async function(cfg) { var subject = await cfg.welcomeEmail.subject; return this.siteTitle+' '+subject; }) }; config.map = { centerPoint : { lat: 3, lon: 4 }, }; config.original = { // An original value passed to deferred function original: asyncConfig(async function(cfg, original) { return await Promise.resolve(original); }), // An original value passed to deferred function originalPromise: asyncConfig(Promise.resolve("not an original value")), }; module.exports = config; node-config-3.3.7/test/16-config/000077500000000000000000000000001413461306600163705ustar00rootroot00000000000000node-config-3.3.7/test/16-config/default.custom000066400000000000000000000001501413461306600212440ustar00rootroot00000000000000file-type: custom file-name: my-custom-awesome-dsl parser: custom-awesomeness custom-key : wow!node-config-3.3.7/test/16-config/default.json000066400000000000000000000001211413461306600207010ustar00rootroot00000000000000{ "file": { "type": "json", "name": "default" }, "parser": "json" }node-config-3.3.7/test/16-config/default.json5000066400000000000000000000000261413461306600207720ustar00rootroot00000000000000{ parser: "json5", }node-config-3.3.7/test/16-config/default.yaml000066400000000000000000000000701413461306600206750ustar00rootroot00000000000000file: type: yaml name: default.yaml parser: js-yaml node-config-3.3.7/test/16-config/local.custom000066400000000000000000000000321413461306600207110ustar00rootroot00000000000000 custom-key : wow!node-config-3.3.7/test/16-config/local.yml000066400000000000000000000000301413461306600201760ustar00rootroot00000000000000file: name: local.yml node-config-3.3.7/test/16-config/parser/000077500000000000000000000000001413461306600176645ustar00rootroot00000000000000node-config-3.3.7/test/16-config/parser/custom-1.js000066400000000000000000000012061413461306600216710ustar00rootroot00000000000000var Parser = require('../../_utils/requireUncached')(__dirname + '/../../../parser'); // change parser order Parser.setFilesOrder('yaml', 0); Parser.setFilesOrder('yml', 1); Parser.setParser('custom', function(filename, content) { return content.split(/\n/g).reduce(function(res, line) { var matches = line.match(/([a-z_\-]+)\s*:\s*(.*)\s*$/i); if (matches) { matches[1].split(/-/g).reduce(function(obj, key, index, keys) { if (index === keys.length -1) { obj[key] = matches[2]; } return obj[key] || (obj[key] = {}); }, res); } return res; }, {}); }); module.exports = Parser; node-config-3.3.7/test/16-config/parser/custom-2.js000066400000000000000000000012001413461306600216640ustar00rootroot00000000000000var Parser = require('../../_utils/requireUncached')(__dirname + '/../../../parser'); Parser.setParser('custom', function(filename, content) { return content.split(/\n/g).reduce(function(res, line) { var matches = line.match(/([a-z_\-]+)\s*:\s*(.*)\s*$/i); if (matches) { matches[1].split(/-/g).reduce(function(obj, key, index, keys) { if (index === keys.length -1) { obj[key] = matches[2]; } return obj[key] || (obj[key] = {}); }, res); } return res; }, {}); }); // change parser order Parser.setFilesOrder(['custom', 'json5', 'json', 'yml']); module.exports = Parser; node-config-3.3.7/test/16-config/parser/custom-3.js000066400000000000000000000005101413461306600216700ustar00rootroot00000000000000var Parser = require('../../_utils/requireUncached')(__dirname + '/../../../parser'); Parser.setParser('json5', function(filename, content) { var json = Parser.json5Parser(filename, content); json.custom = {key: 'json5 rules!'}; return json; }); Parser.setFilesOrder(['yaml', 'yml', 'json5']); module.exports = Parser; node-config-3.3.7/test/16-custom-parser.js000066400000000000000000000054601413461306600202720ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); var Parser = require('../parser'); 'use strict'; var vows = require('vows'), assert = require('assert'); vows.describe('Tests for a custom parser provided by NODE_CONFIG_PARSER') .addBatch({ 'Using the default parser - Sanity check': { topic: function() { process.env.NODE_CONFIG_DIR = __dirname + '/16-config'; return requireUncached(__dirname + '/../lib/config'); }, 'validate default parser order': function(CONFIG) { assert.equal(CONFIG.get('file.type'), 'yaml'); assert.equal(CONFIG.get('file.name'), 'local.yml'); assert.equal(CONFIG.get('parser'), 'js-yaml'); assert.equal(CONFIG.has('custom.key'), false); }, } }) .addBatch({ 'Using setParserOrder to change parsing order': { topic: function() { process.env.NODE_CONFIG_DIR = __dirname + '/16-config'; process.env.NODE_CONFIG_PARSER = __dirname + '/16-config/parser/custom-1'; return requireUncached(__dirname + '/../lib/config'); }, 'validate changes to parser order': function(CONFIG) { assert.equal(CONFIG.get('file.type'), 'custom'); assert.equal(CONFIG.get('file.name'), 'local.yml'); // assert.equal(CONFIG.get('file.name'), 'my-custom-awesome-dsl'); assert.equal(CONFIG.get('parser'), 'custom-awesomeness'); assert.equal(CONFIG.get('custom.key'), 'wow!'); }, } }) .addBatch({ 'Using setParserOrder to replace parsing order': { topic: function() { process.env.NODE_CONFIG_DIR = __dirname + '/16-config'; process.env.NODE_CONFIG_PARSER = __dirname + '/16-config/parser/custom-2'; return requireUncached(__dirname + '/../lib/config'); }, 'validate changes to parser order': function(CONFIG) { assert.equal(CONFIG.get('file.type'), 'json'); assert.equal(CONFIG.get('file.name'), 'local.yml'); assert.equal(CONFIG.get('parser'), 'json'); assert.equal(CONFIG.get('custom.key'), 'wow!'); }, } }) .addBatch({ 'Using setParser to replace a parser': { topic: function() { process.env.NODE_CONFIG_DIR = __dirname + '/16-config'; process.env.NODE_CONFIG_PARSER = __dirname + '/16-config/parser/custom-3'; return requireUncached(__dirname + '/../lib/config'); }, 'validate changes to parser logic': function(CONFIG) { assert.equal(CONFIG.get('file.type'), 'yaml'); assert.equal(CONFIG.get('file.name'), 'local.yml'); assert.equal(CONFIG.get('parser'), 'json5'); assert.equal(CONFIG.get('custom.key'), 'json5 rules!'); }, }, teardown : function (topic) { delete process.env.NODE_CONFIG_PARSER; requireUncached(__dirname + '/../parser'); } }) .export(module); node-config-3.3.7/test/17-config/000077500000000000000000000000001413461306600163715ustar00rootroot00000000000000node-config-3.3.7/test/17-config/default.toml000066400000000000000000000001171413461306600207110ustar00rootroot00000000000000[[messages]] field1 = "1" field2 = "2" [[messages]] field1 = "a" field3 = "3" node-config-3.3.7/test/17-toml.js000066400000000000000000000013731413461306600164410ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); var Parser = require('../parser'); 'use strict'; var vows = require('vows'), assert = require('assert'); vows.describe('Tests for parsing TOML files') .addBatch({ 'Using the default parser - Array of Tables': { topic: function() { process.env.NODE_CONFIG_DIR = __dirname + '/17-config'; return requireUncached(__dirname + '/../lib/config'); }, 'validate array of tables is supported': function(CONFIG) { assert.deepStrictEqual(CONFIG.get('messages'), [ { field1: '1', field2: '2' }, { field1: 'a', field3: '3' } ]); }, } }) .export(module); node-config-3.3.7/test/18-config/000077500000000000000000000000001413461306600163725ustar00rootroot00000000000000node-config-3.3.7/test/18-config/default.json000066400000000000000000000000361413461306600207100ustar00rootroot00000000000000{ "someKey": "testValue" }node-config-3.3.7/test/18-extra-config/000077500000000000000000000000001413461306600175135ustar00rootroot00000000000000node-config-3.3.7/test/18-extra-config/customFile.json000066400000000000000000000000501413461306600225130ustar00rootroot00000000000000{ "arbitraryKey": "arbitraryValue" }node-config-3.3.7/test/18-extra-config/default.json000066400000000000000000000000451413461306600220310ustar00rootroot00000000000000{ "someKey": "anotherTestValue" }node-config-3.3.7/test/18-skipConfigSources.js000066400000000000000000000245311413461306600211300ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Dependencies var vows = require('vows'), assert = require('assert'), Path = require('path'); vows.describe('Testing the skipConfigSources functionality') .addBatch({ 'The config.util.parseFile function,': { 'given a file path and no options parameter': { topic: function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = [__dirname + '/18-config'].join(Path.delimiter); delete process.env.NODE_ENV; process.env.NODE_CONFIG = '{}'; delete process.env.NODE_APP_INSTANCE; process.env.NODE_CONFIG_STRICT_MODE=0; var config = requireUncached(__dirname + '/../lib/config'); return { config, configObject: config.util.parseFile(Path.join(__dirname,'/18-extra-config/customFile.json')) }; }, 'should return the configuration object': function(topic) { assert.deepStrictEqual(topic.configObject,{ arbitraryKey: 'arbitraryValue'}); }, 'should not add the configuration object to the global configuration': function (topic){ assert(!topic.config.has('arbitraryKey')); }, 'should add the file information to the config.util.getConfigSources array': function(topic) { var configSources = topic.config.util.getConfigSources(); var lastEntry = configSources[configSources.length - 1 ]; var fullFileName = Path.join(__dirname,'/18-extra-config/customFile.json'); assert.deepStrictEqual(lastEntry.name, fullFileName); assert.deepStrictEqual(lastEntry.parsed, { arbitraryKey: 'arbitraryValue'}); } }, 'given a file path and an options parameter,': { 'when the skipConfigSources flag is set to false': { topic: function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = [__dirname + '/18-config'].join(Path.delimiter); delete process.env.NODE_ENV; process.env.NODE_CONFIG = '{}'; delete process.env.NODE_APP_INSTANCE; process.env.NODE_CONFIG_STRICT_MODE=0; var config = requireUncached(__dirname + '/../lib/config'); return { config, configObject: config.util.parseFile(Path.join(__dirname,'/18-extra-config/customFile.json'), { skipConfigSources: false }) }; }, 'should return the configuration object': function(topic) { assert.deepStrictEqual(topic.configObject,{ arbitraryKey: 'arbitraryValue'}); }, 'should not add the configuration object to the global configuration': function (topic){ assert(!topic.config.has('arbitraryKey')); }, 'should add the file information to the config.util.getConfigSources array': function(topic) { var configSources = topic.config.util.getConfigSources(); var lastEntry = configSources[configSources.length - 1 ]; var fullFileName = Path.join(__dirname,'/18-extra-config/customFile.json'); assert.deepStrictEqual(lastEntry.name, fullFileName); assert.deepStrictEqual(lastEntry.parsed, { arbitraryKey: 'arbitraryValue'}); } }, 'when the skipConfigSources flag is set to true': { topic: function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = [__dirname + '/18-config'].join(Path.delimiter); delete process.env.NODE_ENV; process.env.NODE_CONFIG = '{}'; delete process.env.NODE_APP_INSTANCE; process.env.NODE_CONFIG_STRICT_MODE=0; var config = requireUncached(__dirname + '/../lib/config'); return { config, configObject: config.util.parseFile(Path.join(__dirname,'/18-extra-config/customFile.json'), { skipConfigSources: true }) }; }, 'should return the configuration object': function(topic) { assert.deepStrictEqual(topic.configObject,{ arbitraryKey: 'arbitraryValue'}); }, 'should not add the configuration object to the global configuration': function (topic){ assert(!topic.config.has('arbitraryKey')); }, 'should not add the file information to the config.util.getConfigSources array': function(topic) { var configSources = topic.config.util.getConfigSources(); var fullFileName = Path.join(__dirname,'/18-extra-config/customFile.json'); assert.strictEqual(configSources.findIndex( (value, index) => { return value.name === fullFileName}), -1) } } } }, 'The config.util.loadFileConfigs function,': { 'given a directory and no options parameter': { topic: function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = [__dirname + '/18-config'].join(Path.delimiter); delete process.env.NODE_ENV; process.env.NODE_CONFIG = '{}'; delete process.env.NODE_APP_INSTANCE; process.env.NODE_CONFIG_STRICT_MODE=0; var config = requireUncached(__dirname + '/../lib/config'); return { config, configObject: config.util.loadFileConfigs(Path.join(__dirname,'/18-extra-config')) }; }, 'should return the configuration object': function(topic) { assert.deepStrictEqual(topic.configObject,{ someKey: 'anotherTestValue'}); }, 'should not add the configuration object to the global configuration': function (topic){ assert.deepStrictEqual(topic.config.get('someKey'),'testValue'); }, 'should add the file information to the config.util.getConfigSources array': function(topic) { var configSources = topic.config.util.getConfigSources(); var lastEntry = configSources[configSources.length - 1 ]; var fullFileName = Path.join(__dirname,'/18-extra-config/default.json'); assert.deepStrictEqual(lastEntry.name, fullFileName); assert.deepStrictEqual(lastEntry.parsed, { someKey: 'anotherTestValue'}); } }, 'given a directory and an options parameter,': { 'when the skipConfigSources flag is set to false': { topic: function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = [__dirname + '/18-config'].join(Path.delimiter); delete process.env.NODE_ENV; process.env.NODE_CONFIG = '{}'; delete process.env.NODE_APP_INSTANCE; process.env.NODE_CONFIG_STRICT_MODE=0; var config = requireUncached(__dirname + '/../lib/config'); return { config, configObject: config.util.loadFileConfigs(Path.join(__dirname,'/18-extra-config'), { skipConfigSources: false }) }; }, 'should return the configuration object': function(topic) { assert.deepStrictEqual(topic.configObject,{ someKey: 'anotherTestValue'}); }, 'should not add the configuration object to the global configuration': function (topic){ assert.deepStrictEqual(topic.config.get('someKey'),'testValue'); }, 'should add the file information to the config.util.getConfigSources array': function(topic) { var configSources = topic.config.util.getConfigSources(); var lastEntry = configSources[configSources.length - 1 ]; var fullFileName = Path.join(__dirname,'/18-extra-config/default.json'); assert.deepStrictEqual(lastEntry.name, fullFileName); assert.deepStrictEqual(lastEntry.parsed, { someKey: 'anotherTestValue'}); } }, 'when the skipConfigSources flag is set to true': { topic: function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = [__dirname + '/18-config'].join(Path.delimiter); delete process.env.NODE_ENV; process.env.NODE_CONFIG = '{}'; delete process.env.NODE_APP_INSTANCE; process.env.NODE_CONFIG_STRICT_MODE=0; var config = requireUncached(__dirname + '/../lib/config'); return { config, configObject: config.util.loadFileConfigs(Path.join(__dirname,'/18-extra-config'), { skipConfigSources: true }) }; }, 'should return the configuration object': function(topic) { assert.deepStrictEqual(topic.configObject,{ someKey: 'anotherTestValue'}); }, 'should not add the configuration object to the global configuration': function (topic){ assert.deepStrictEqual(topic.config.get('someKey'),'testValue'); }, 'should not add the file information to the config.util.getConfigSources array': function(topic) { var configSources = topic.config.util.getConfigSources(); var fullFileName = Path.join(__dirname,'/18-extra-config/default.json'); assert.strictEqual(configSources.findIndex( (value, index) => { return value.name === fullFileName}), -1) } } } } }) .export(module); node-config-3.3.7/test/19-config/000077500000000000000000000000001413461306600163735ustar00rootroot00000000000000node-config-3.3.7/test/19-config/custom-environment-variables.json000066400000000000000000000001621413461306600251070ustar00rootroot00000000000000{ "testValue": "TEST_VALUE", "testJSONValue": { "__name": "TEST_JSON_VALUE", "__format": "json" } } node-config-3.3.7/test/19-config/default.js000066400000000000000000000002021413461306600203470ustar00rootroot00000000000000 var config = { testValue : 'from js', testJSONValue : { fromJS: true, type: 'JSON' }, }; module.exports = config; node-config-3.3.7/test/19-custom-environment-variables.js000066400000000000000000000061531413461306600233130ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Dependencies var vows = require('vows'), assert = require('assert'), Path = require('path'); vows.describe('Testing custom environment variable overrides') .addBatch({ 'custom environment variable overrides,': { 'with unset environment variables': { topic: function () { delete process.env.TEST_VALUE; delete process.env.TEST_JSON_VALUE; // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = [__dirname + '/19-config'].join(Path.delimiter); var config = requireUncached(__dirname + '/../lib/config'); return { config, configObject: config.util.parseFile(Path.join(__dirname,'/19-config/default.js')) }; }, 'should not override from the environment variables': function(topic) { assert.strictEqual(topic.config.testValue,topic.configObject.testValue); assert.deepStrictEqual(topic.config.testJSONValue,topic.configObject.testJSONValue); }, }, 'with empty string environment variables': { topic: function () { process.env.TEST_VALUE = ''; process.env.TEST_JSON_VALUE = ''; // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = [__dirname + '/19-config'].join(Path.delimiter); var config = requireUncached(__dirname + '/../lib/config'); return { config, configObject: config.util.parseFile(Path.join(__dirname,'/19-config/default.js')) }; }, 'should not override from the environment variables': function(topic) { assert.strictEqual(topic.config.testValue,topic.configObject.testValue); assert.deepStrictEqual(topic.config.testJSONValue,topic.configObject.testJSONValue); }, }, 'with string environment variables': { topic: function () { const testValue = 'from env'; const jsonValue = { fromJS: false, type: 'stringified JSON' } process.env.TEST_VALUE = testValue; process.env.TEST_JSON_VALUE = JSON.stringify(jsonValue); // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = [__dirname + '/19-config'].join(Path.delimiter); var config = requireUncached(__dirname + '/../lib/config'); return { config, testValue, jsonValue }; }, 'should override from the environment variables': function(topic) { assert.strictEqual(topic.config.testValue,topic.testValue); assert.deepStrictEqual(topic.config.testJSONValue,topic.jsonValue); }, }, }, }) .export(module); node-config-3.3.7/test/2-config-test.js000066400000000000000000000412771413461306600176310ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Dependencies var vows = require('vows'), assert = require('assert'), FileSystem = require('fs'); /** *

Unit tests for the node-config library. To run type:

*
npm test
*

Or, in a project that uses node-config:

*
npm test config
* * @class ConfigTest */ var CONFIG, MODULE_CONFIG, override, numberInteger, numberFloat; vows.describe('Test suite for node-config') .addBatch({ 'Library initialization': { topic : function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/config'; // Hard-code $NODE_ENV=test for testing process.env.NODE_ENV='test'; // Test for multi-instance applications process.env.NODE_APP_INSTANCE='3'; // Test $NODE_CONFIG environment and --NODE_CONFIG command line parameter process.env.NODE_CONFIG='{"EnvOverride":{"parm3":"overridden from $NODE_CONFIG","parm4":100}}'; process.argv.push('--NODE_CONFIG={"EnvOverride":{"parm5":"overridden from --NODE_CONFIG","parm6":101}}'); // Test Environment Variable Substitution override = 'CUSTOM VALUE FROM JSON ENV MAPPING'; process.env.CUSTOM_JSON_ENVIRONMENT_VAR = override; // Test Environment variable substitution of boolean values process.env.CUSTOM_BOOLEAN_TRUE_ENVIRONMENT_VAR = 'true'; process.env.CUSTOM_BOOLEAN_FALSE_ENVIRONMENT_VAR = 'false'; process.env.CUSTOM_BOOLEAN_ERROR_ENVIRONMENT_VAR = 'notProperBoolean'; // Test Environment variable substitution of numeric values numberInteger = 1001; numberFloat = 3.14 process.env.CUSTOM_NUMBER_INTEGER_ENVIRONMENT_VAR = numberInteger; process.env.CUSTOM_NUMBER_FLOAT_ENVIRONMENT_VAR = numberFloat; process.env.CUSTOM_NUMBER_EMPTY_ENVIRONMENT_VAR = ''; process.env.CUSTOM_NUMBER_STRING_ENVIRONMENT_VAR = 'String'; CONFIG = requireUncached(__dirname + '/../lib/config'); return CONFIG; }, 'Config library is available': function() { assert.isObject(CONFIG); }, 'Config extensions are included with the library': function() { assert.isFunction(CONFIG.util.cloneDeep); } }, }) .addBatch({ 'Configuration file Tests': { 'Loading configurations from a JS module is correct': function() { assert.equal(CONFIG.Customers.dbHost, 'base'); assert.equal(CONFIG.TestModule.parm1, 'value1'); }, 'Loading configurations from a JSON file is correct': function() { assert.equal(CONFIG.AnotherModule.parm1, 'value1'); assert.equal(CONFIG.Inline.a, ''); assert.equal(CONFIG.Inline.b, '1'); assert.equal(CONFIG.ContainsQuote, '"this has a quote"'); }, 'Loading configurations from a .yaml YAML file is correct': function() { assert.equal(CONFIG.AnotherModule.parm2, 'value2'); }, 'Loading configurations from a .yml YAML file is correct': function() { assert.equal(CONFIG.AnotherModule.parm2yml, 'value2yml'); }, 'Loading configurations from a Coffee-Script file is correct': function() { assert.equal(CONFIG.AnotherModule.parm3, 'value3'); }, 'Loading configurations from a CSON file is correct': function() { assert.equal(CONFIG.AnotherModule.parm4, 'value4'); }, 'Loading configurations from a .properties file is correct': function() { assert.equal(CONFIG.AnotherModule.parm5, 'value5'); }, 'Loading configurations from a JSON5 file is correct': function() { assert.equal(CONFIG.AnotherModule.parm6, 'value6'); }, 'Loading configurations from a TOML file is correct': function() { assert.equal(CONFIG.AnotherModule.parm7, 'value7'); }, 'Loading configurations from a Hjson file is correct': function() { assert.equal(CONFIG.AnotherModule.parm8, 'value8'); }, 'Loading configurations from a XML file is correct': function() { assert.equal(CONFIG.AnotherModule.parm9, 'value9'); }, 'Loading configurations from an environment file is correct': function() { assert.equal(CONFIG.Customers.dbPort, '5999'); }, 'Loading configurations from the local file is correct': function() { assert.equal(CONFIG.Customers.dbPassword, 'real password'); }, 'Loading configurations from the local environment file is correct': function() { assert.equal(CONFIG.Customers.dbPassword2, 'another password'); assert.deepEqual(CONFIG.Customers.lang, ['en','de','es']); } }, 'Immutability': { 'Correct mute setup var': function () { assert.equal(CONFIG.MuteThis, 'hello'); }, 'Mutation sticks': function () { CONFIG.MuteThis = 'world'; assert.equal(CONFIG.MuteThis, 'world'); }, 'No mutation after the first get()': function () { assert.equal(CONFIG.get('MuteThis'), 'world'); CONFIG.MuteThis = 'backToHello'; assert.equal(CONFIG.MuteThis, 'world'); } }, 'Configurations from the $NODE_CONFIG environment variable': { 'Configuration can come from the $NODE_CONFIG environment': function() { assert.equal(CONFIG.EnvOverride.parm3, 'overridden from $NODE_CONFIG'); }, 'Type correct configurations from $NODE_CONFIG': function() { assert.equal(CONFIG.EnvOverride.parm4, 100); } }, 'Configurations from the --NODE_CONFIG command line': { 'Configuration can come from the --NODE_CONFIG command line argument': function() { assert.equal(CONFIG.EnvOverride.parm5, 'overridden from --NODE_CONFIG'); }, 'Type correct configurations from --NODE_CONFIG': function() { assert.equal(CONFIG.EnvOverride.parm6, 101); } }, 'Configurations from custom environment variables': { // only testing the `custom-environment-variables.json` now // NOT testing unset environment variable because of module caching (CONFIG would have to be recreated // NOT testing absence of `custom-environment-variables.json` because current tests don't mess with the filesystem 'Configuration can come from an environment variable mapped in custom_environment_variables.json': function () { assert.equal(CONFIG.get('customEnvironmentVariables.mappedBy.json'), override); }, 'Environment variables specified as boolean true': function () { assert.equal(CONFIG.get('customEnvironmentVariables.mappedBy.formats.booleanTrue'), true); }, 'Environment variables specified as boolean false': function () { assert.equal(CONFIG.get('customEnvironmentVariables.mappedBy.formats.booleanFalse'), false); }, 'Environment variables not specified as a proper boolean value': function () { assert.equal(CONFIG.get('customEnvironmentVariables.mappedBy.formats.notProperBoolean'), false); }, 'Environment variables specified as an integer number': function () { assert.equal(CONFIG.get('customEnvironmentVariables.mappedBy.formats.numberInteger'), numberInteger); }, 'Environment variables specified as a floating number': function () { assert.equal(CONFIG.get('customEnvironmentVariables.mappedBy.formats.numberFloat'), numberFloat); }, 'Environment variables specified as a number but empty string passed': function () { assert.throws(function () { CONFIG.get('customEnvironmentVariables.mappedBy.formats.numberEmpty'); }, /Configuration property "customEnvironmentVariables.mappedBy.formats.numberEmpty" is not defined/ ) }, 'Environment variables specified as a number but alphanumeric string passed': function () { assert.throws(function () { CONFIG.get('customEnvironmentVariables.mappedBy.formats.numberString'); }, /Configuration property "customEnvironmentVariables.mappedBy.formats.numberString" is not defined/ ) }, }, 'Assuring a configuration property can be hidden': { topic: function() { var object = { item1: 23, subObject: { item2: "hello" } }; return object; }, 'The makeHidden() method is available': function() { assert.isFunction(CONFIG.util.makeHidden); }, 'The test object (before hiding) is correct': function(object) { assert.isTrue(JSON.stringify(object) == '{"item1":23,"subObject":{"item2":"hello"}}'); }, 'The test object (after hiding) is correct': function(object) { CONFIG.util.makeHidden(object, 'item1'); assert.isTrue(JSON.stringify(object) == '{"subObject":{"item2":"hello"}}'); }, 'The hidden property is readable, and has not changed': function(object) { assert.isTrue(JSON.stringify(object) == '{"subObject":{"item2":"hello"}}'); assert.isTrue(object.item1 == 23); } }, 'Assuring a configuration property can be made immutable': { topic: function() { CONFIG.util.makeImmutable(CONFIG.TestModule, 'parm1'); CONFIG.TestModule.parm1 = "setToThis"; return CONFIG.TestModule.parm1; }, 'The makeImmutable() method is available': function() { assert.isFunction(CONFIG.util.makeImmutable); }, 'Correctly unable to change an immutable configuration': function(value) { assert.isTrue(value != "setToThis"); }, 'Left the original value intact after attempting the change': function(value) { assert.equal(value, "value1"); } }, 'Assuring a configuration array property can be made immutable': { 'Correctly unable to change an immutable configuration': function() { CONFIG.util.makeImmutable(CONFIG.TestModule, 'arr1'); CONFIG.TestModule.arr1 = ['bad value']; assert.isTrue(CONFIG.TestModule.arr1[0] == 'arrValue1'); }, 'Correctly unable to add values to immutable array': function() { CONFIG.util.makeImmutable(CONFIG.TestModule, 'arr1'); try { CONFIG.TestModule.arr1.push('bad value'); } catch (err) { assert.isTrue(err.name == 'TypeError'); } assert.isTrue(!CONFIG.TestModule.arr1.includes('bad value')); } }, 'get() tests': { 'The function exists': function() { assert.isFunction(CONFIG.get); }, 'A top level item is returned': function() { assert.isTrue(typeof CONFIG.get('TestModule') === 'object'); }, 'A sub level item is returned': function() { assert.equal(CONFIG.get('Customers.dbHost'), 'base'); }, 'get is attached deeply': function() { assert.equal(CONFIG.Customers.get('dbHost'), 'base'); }, 'An extended property accessor remains a getter': function() { assert.equal(CONFIG.get('customerDbPort'), '5999'); }, 'A cloned property accessor remains a getter': function() { assert.equal(CONFIG.Customers.get('dbString'), 'override_from_runtime_json:5999'); }, 'A cloned property accessor is made immutable': function() { var random1 = CONFIG.Customers.get('random'), random2 = CONFIG.Customers.get('random'); assert.equal(random1, random2); }, 'A proper exception is thrown on mis-spellings': function() { assert.throws( function () { CONFIG.get('mis.spelled'); }, /Configuration property "mis.spelled" is not defined/ ); }, 'An exception is thrown on non-objects': function() { assert.throws( function () { CONFIG.get('Testmodule.misspelled'); }, /Configuration property "Testmodule.misspelled" is not defined/ ); }, 'get(undefined) throws an exception': function() { assert.throws( function () { CONFIG.get(undefined); }, /Calling config.get with null or undefined argument/ ); }, 'get(null) throws an exception': function() { assert.throws( function () { CONFIG.get(null); }, /Calling config.get with null or undefined argument/ ); }, "get('') throws an exception": function() { assert.throws( function () { CONFIG.get(''); }, /Configuration property "" is not defined/ ); }, }, 'has() tests': { 'The function exists': function() { assert.isFunction(CONFIG.has); }, 'A top level item can be tested': function() { assert.isTrue(CONFIG.has('TestModule')); }, 'A sub level item can be tested': function() { assert.isTrue(CONFIG.has('Customers.dbHost')); }, 'A missing sub level item can be tested': function() { assert.isTrue(CONFIG.has('Customers.emptySub')); assert.isFalse(CONFIG.has('Customers.emptySub.foo')); }, 'has is attached deeply': function() { assert.isTrue(CONFIG.Customers.has('dbHost')); }, 'Correctly identifies not having element': function() { assert.isTrue(!CONFIG.Customers.has('dbHosx')); }, 'Correctly identifies not having element (deep)': function() { assert.isTrue(!CONFIG.has('Customers.dbHosx')); }, 'has(undefined) returns false': function() { assert.isFalse(CONFIG.has(undefined)); }, "has(null) returns false": function() { assert.isFalse(CONFIG.has(null)); }, "has('') returns false": function() { assert.isFalse(CONFIG.has('')); }, }, 'Configuration for module developers': { topic: function() { MODULE_CONFIG = requireUncached(__dirname + '/../lib/config'); // Set some parameters for the test module return MODULE_CONFIG.util.setModuleDefaults("TestModule", { parm1: 1000, parm2: 2000, parm3: 3000, nested: { param4: 4000, param5: 5000 } }); }, 'The setModuleDefaults() method is available': function() { assert.isFunction(MODULE_CONFIG.util.setModuleDefaults); }, 'The module config is in the CONFIG object': function(moduleConfig) { assert.isObject(MODULE_CONFIG.TestModule); assert.deepEqual(MODULE_CONFIG.TestModule, moduleConfig); }, // Regression test for https://github.com/lorenwest/node-config/issues/518 'The module config did not extend itself with its own name': function(moduleConfig) { assert.isFalse('TestModule' in moduleConfig); assert.isFalse('TestModule' in MODULE_CONFIG.TestModule); }, 'Local configurations are mixed in': function(moduleConfig) { assert.equal(moduleConfig.parm1, "value1"); }, 'Defaults remain intact unless overridden': function(moduleConfig) { assert.equal(moduleConfig.parm2, 2000); }, 'Prototypes are applied by setModuleDefaults even if no previous config exists for the module': function() { var BKTestModuleDefaults = { parm1: 1000, parm2: 2000, parm3: 3000, nested: { param4: 4000, param5: 5000 } }; var OtherTestModuleDefaults = { parm6: 6000, parm7: 7000, other: { param8: 8000, param9: 9000 } }; MODULE_CONFIG.util.setModuleDefaults('BKTestModule', BKTestModuleDefaults); MODULE_CONFIG.util.setModuleDefaults('services.OtherTestModule', OtherTestModuleDefaults); var testModuleConfig = MODULE_CONFIG.get('BKTestModule'); var testSubModuleConfig = MODULE_CONFIG.get('services'); assert.deepEqual(BKTestModuleDefaults.nested, testModuleConfig.get('nested')); assert.deepEqual(OtherTestModuleDefaults.other, testSubModuleConfig.OtherTestModule.other); } }, }) .addBatch({ 'Library initialization from multiple directories': { topic : function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/config:' + __dirname + '/x-config'; // Hard-code $NODE_ENV=test for testing process.env.NODE_ENV='test'; // Test for multi-instance applications process.env.NODE_APP_INSTANCE='3'; // Test $NODE_CONFIG environment and --NODE_CONFIG command line parameter process.env.NODE_CONFIG='{"EnvOverride":{"parm3":"overridden from $NODE_CONFIG","parm4":100}}'; process.argv.push('--NODE_CONFIG={"EnvOverride":{"parm5":"overridden from --NODE_CONFIG","parm6":101}}'); // Test Environment Variable Substitution override = 'CUSTOM VALUE FROM JSON ENV MAPPING'; process.env.CUSTOM_JSON_ENVIRONMENT_VAR = override; CONFIG = requireUncached(__dirname + '/../lib/config'); return CONFIG; }, 'Config library is available': function() { assert.isObject(CONFIG); }, 'Config extensions are included with the library': function() { assert.isFunction(CONFIG.util.cloneDeep); } }, 'Multiple config directories': { 'Verify first directory loaded': function() { assert.equal(CONFIG.get('Customers.dbName'), 'from_default_xml'); }, 'Verify second directory loaded': function() { assert.equal(CONFIG.get('different.dir'), true); }, 'Verify correct resolution order': function() { assert.equal(CONFIG.get('AnotherModule.parm4'), 'x_config_4_win'); }, } }) .export(module); node-config-3.3.7/test/3-config/000077500000000000000000000000001413461306600163045ustar00rootroot00000000000000node-config-3.3.7/test/3-config/default.js000066400000000000000000000027461413461306600202770ustar00rootroot00000000000000 var defer = require('../../defer').deferConfig; var config = { value: 'value', siteTitle : 'Site title', latitude : 1, longitude : 2, a: defer(function (cfg) { return 'my '+cfg.b; }), b: defer(function () { return this.value; }), c: defer(function (cfg) { return this.a+' '+cfg.b; }), fromList: defer(function() { return this.list[2]+2; }), list: [ 1, 'b', defer(function (cfg) { return cfg.latitude+cfg.longitude; }) ] }; // Set up a default value which refers to another value. // The resolution of the value is deferred until all the config files have been loaded // So that if 'config.siteTitle' is overridden, this will point to the correct value. config.welcomeEmail = { subject : defer(function (cfg) { return "Welcome to "+cfg.siteTitle; }), // A plain function should be not disturbed. aFunc : function () { return "Still just a function."; }, // Look ma, no arg passing. The main config object is bound to 'this' justThis: defer(function () { return "Welcome to this "+this.siteTitle; }), }; config.map = { centerPoint : defer(function () { return { lat: this.latitude, lon: this.longitude }; }), }; config.original = { // An original value passed to deferred function original: "an original value", // A deferred function "skipped" by next deferred function deferredOriginal: defer(function(cfg, original) { return "this will not be used"; }), }; module.exports = config; node-config-3.3.7/test/3-config/local.js000066400000000000000000000011371413461306600177360ustar00rootroot00000000000000var defer = require('../../defer').deferConfig; var config = { siteTitle : 'New Instance!', b: defer(function () { return 'this is '+this.fromList+'!'; }), fromList: defer(function() { return this.list[2]*2; }), }; config.map = { centerPoint : { lat: 3, lon: 4 }, }; config.original = { // An original value passed to deferred function original: defer(function(cfg, original) { return original; }), // This deferred function "skips" the previous one deferredOriginal: defer(function(cfg, original) { return original; // undefined }), }; module.exports = config; node-config-3.3.7/test/3-deferred-configs.js000066400000000000000000000050051413461306600206030ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Test declaring deferred values. // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/3-config'; // Hard-code $NODE_ENV=test for testing process.env.NODE_ENV='test'; // Test for multi-instance applications process.env.NODE_APP_INSTANCE='defer'; // Because require'ing config creates and caches a global singleton, // We have to invalidate the cache to build new object based on the environment variables above var CONFIG = requireUncached(__dirname + '/../lib/config'); // Dependencies var vows = require('vows'), assert = require('assert'); vows.describe('Tests for deferred values - JavaScript').addBatch({ 'Configuration file Tests': { 'Using deferConfig() in a config file causes value to be evaluated at the end': function() { // The deferred function was declared in default-defer.js // Then local-defer.js is located which overloads the siteTitle mentioned in the function // Finally the deferred configurations, now referencing the 'local' siteTitle assert.equal(CONFIG.welcomeEmail.subject, 'Welcome to New Instance!'); }, 'values which are functions remain untouched unless they are instance of DeferredConfig': function() { // If this had been treated as a deferred config value it would blow-up. assert.equal(CONFIG.welcomeEmail.aFunc(), 'Still just a function.'); }, // This defer function didn't use args, but relied 'this' being bound to the main config object "defer functions can simply refer to 'this'" : function () { assert.equal(CONFIG.welcomeEmail.justThis, 'Welcome to this New Instance!'); }, "defer functions which return objects should still be treated as a single value." : function () { assert.deepEqual(CONFIG.get('map.centerPoint'), { lat: 3, lon: 4 }); }, "defer function return original value." : function () { assert.equal(CONFIG.original.original, 'an original value'); }, "second defer function return original value." : function () { assert.equal(CONFIG.original.deferredOriginal, undefined); }, "defer functions resolved within an array" : function () { assert.equal(CONFIG.list[2], 3); assert.equal(CONFIG.fromList, 6); }, "defer functions execution order resolves when accessing other defer functions" : function () { assert.equal(CONFIG.a, 'my this is 6!'); assert.equal(CONFIG.c, 'my this is 6! this is 6!'); }, } }) .export(module); node-config-3.3.7/test/4-array-merging.js000066400000000000000000000026151413461306600201460ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Test declaring deferred values. // The key config files involved here are: // test/config/default-array-merge.js // test/config/local-array-merge.js // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/config'; // Hard-code $NODE_ENV=test for testing process.env.NODE_ENV='test'; // Test for multi-instance applications process.env.NODE_APP_INSTANCE='array-merge'; // Because require'ing config creates and caches a global singleton, // We have to invalidate the cache to build new object based on the environment variables above var CONFIG = requireUncached(__dirname + '/../lib/config'); // Dependencies var vows = require('vows'), assert = require('assert'); vows.describe('Tests for merging arrays').addBatch({ 'Array merging tests Tests': { topic: function() { return CONFIG; }, 'An empty array replaced by a full array should be replaced': function() { assert.deepEqual(CONFIG.arrayMerging.emptyArray, ['not empty anymore']); }, 'An array with one value should be replaced wholesale': function() { assert.deepEqual(CONFIG.arrayMerging.oneItem, ['replaced']); }, "An array replaced by an empty array should be replaced wholesale" : function () { assert.deepEqual(CONFIG.arrayMerging.removeMe, []); } } }) .export(module);node-config-3.3.7/test/5-config/000077500000000000000000000000001413461306600163065ustar00rootroot00000000000000node-config-3.3.7/test/5-config/custom-environment-variables.json000066400000000000000000000000401413461306600250150ustar00rootroot00000000000000{ "testValue": "TEST_VALUE" } node-config-3.3.7/test/5-config/default.js000066400000000000000000000002221413461306600202640ustar00rootroot00000000000000 var config = { siteName : 'default site name', number : 5, }; config.email = { subject : 'default subject', } module.exports = config; node-config-3.3.7/test/5-config/empty.json000066400000000000000000000000031413461306600203300ustar00rootroot00000000000000{} node-config-3.3.7/test/5-config/local.js000066400000000000000000000001151413461306600177330ustar00rootroot00000000000000 var config = { siteName : 'local site name', }; module.exports = config; node-config-3.3.7/test/5-extra-config/000077500000000000000000000000001413461306600174275ustar00rootroot00000000000000node-config-3.3.7/test/5-extra-config/custom-environment-variables.json000066400000000000000000000000361413461306600261430ustar00rootroot00000000000000{ "siteName": "SITE_NAME" } node-config-3.3.7/test/5-getConfigSources.js000066400000000000000000000066351413461306600206620ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Dependencies var vows = require('vows'), assert = require('assert'), Path = require('path'); vows.describe('Tests config.util.getConfigSources').addBatch({ 'tests with NODE_CONFIG env set, and --NODE_CONFIG command line flag': { topic: function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = [__dirname + '/5-config', __dirname + '/5-extra-config'].join(Path.delimiter); delete process.env.NODE_ENV; process.env.NODE_CONFIG = '{}'; delete process.env.NODE_APP_INSTANCE; process.env.NODE_CONFIG_STRICT_MODE=0; process.argv = ["node","path/to/some.js","--NODE_CONFIG='{}'"]; var config = requireUncached(__dirname + '/../lib/config'); return config.util.getConfigSources(); }, 'Two files plus NODE_CONFIG in env and as command line args should result in four entries': function(topic) { assert.equal(topic.length,6); }, "The environment variable and command line args are the last two overrides": function (topic) { assert.equal(topic[2].name,'$NODE_CONFIG'); assert.equal(topic[3].name,"--NODE_CONFIG argument"); }, }, 'tests without NODE_ENV set': { topic: function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/5-config'; delete process.env.NODE_ENV; delete process.env.NODE_CONFIG; delete process.env.NODE_APP_INSTANCE; process.env.NODE_CONFIG_STRICT_MODE=0; process.argv = []; var config = requireUncached(__dirname + '/../lib/config'); return config.util.getConfigSources(); }, 'Two files should result in two entries': function(topic) { assert.equal(topic.length,3); }, "The keys for each object are 'name', 'original', and 'parsed'": function(topic) { assert.deepEqual(Object.keys(topic[0]).sort(), ['name','original','parsed']); }, }, 'tests with NODE_ENV set': { topic: function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/5-config'; process.env.NODE_ENV='test'; delete process.env.NODE_CONFIG; delete process.env.NODE_APP_INSTANCE; process.argv = []; var config = requireUncached(__dirname + '/../lib/config'); return config.util.getConfigSources(); }, 'Two files should result in two entries': function(topic) { assert.equal(topic.length,3); }, "The keys for each object are 'name', 'original', and 'parsed'": function(topic) { assert.deepEqual(Object.keys(topic[0]).sort(), ['name','original','parsed']); }, }, 'Files which return empty objects still end up in getConfigSources()': { topic: function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/5-config'; process.env.NODE_ENV='empty'; delete process.env.NODE_CONFIG; delete process.env.NODE_APP_INSTANCE; process.argv = []; var config = requireUncached(__dirname + '/../lib/config'); return config.util.getConfigSources(); }, 'Three files should result in 3 entries': function(topic) { assert.equal(topic.length,4); }, 'Second file is named empty': function (topic) { assert.equal(Path.basename(topic[1].name), 'empty.json'); }, } }) .export(module); node-config-3.3.7/test/6-config/000077500000000000000000000000001413461306600163075ustar00rootroot00000000000000node-config-3.3.7/test/6-config/default-valid-instance.json000066400000000000000000000001121413461306600235170ustar00rootroot00000000000000{ "siteTitle" : "A valid site title from default-valid-instance.json" } node-config-3.3.7/test/6-config/default.json000066400000000000000000000000731413461306600206260ustar00rootroot00000000000000{ "siteTitle" : "A valid site title from default.json" } node-config-3.3.7/test/6-config/local.json000066400000000000000000000000711413461306600202720ustar00rootroot00000000000000{ "siteTitle" : "A valid site title from local.json" } node-config-3.3.7/test/6-config/production.json000066400000000000000000000000751413461306600213720ustar00rootroot00000000000000{ "siteTitle" : "A valid site title from production.json" }node-config-3.3.7/test/6-config/valid-deployment.json000066400000000000000000000001041413461306600224520ustar00rootroot00000000000000{ "siteTitle" : "A valid site title from valid-deployment.json" } node-config-3.3.7/test/6-strict-mode.js000066400000000000000000000113061413461306600176330ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Dependencies var vows = require('vows'), assert = require('assert'); vows.describe('Tests for strict mode').addBatch({ "Specifying an unused NODE_ENV value and valid NODE_APP_INSTANCE value throws an exception": _expectException({ NODE_ENV : 'BOOM', APP_INSTANCE : 'valid-instance', exceptionMessage : "FATAL: NODE_ENV value of 'BOOM' did not match any deployment config file names. " + "See https://github.com/lorenwest/node-config/wiki/Strict-Mode", }), // Because NODE_ENV=development = default "Specifying NODE_ENV=development with no development file does not throw an exception. ": _expectException({ NODE_ENV : 'development', APP_INSTANCE : 'valid-instance', exceptionMessage : null, }), "Specifying NODE_ENV=production,cloud with no cloud file throws an exception. ": _expectException({ NODE_ENV : 'production,cloud', APP_INSTANCE : 'valid-instance', exceptionMessage : "FATAL: NODE_ENV value of 'cloud' did not match any deployment config file names. " + "See https://github.com/lorenwest/node-config/wiki/Strict-Mode" }), "Specifying an unused NODE_APP_INSTANCE and valid NODE_ENV value throws an exception": _expectException({ NODE_ENV : 'valid-deployment', APP_INSTANCE : 'BOOM', exceptionMessage : "FATAL: NODE_APP_INSTANCE value of 'BOOM' did not match any instance config file names. " + "See https://github.com/lorenwest/node-config/wiki/Strict-Mode", }), "NODE_ENV=default throws exception: reserved word": _expectException({ NODE_ENV : 'default', APP_INSTANCE : 'valid-instance', exceptionMessage :"FATAL: NODE_ENV value of 'default' is ambiguous. " +"See https://github.com/lorenwest/node-config/wiki/Strict-Mode", }), "NODE_ENV=production,default throws exception: reserved word": _expectException({ NODE_ENV : 'production,default', APP_INSTANCE : 'valid-instance', exceptionMessage :"FATAL: NODE_ENV value of 'default' is ambiguous. " +"See https://github.com/lorenwest/node-config/wiki/Strict-Mode", }), "NODE_ENV=local throws exception: reserved word": _expectException({ NODE_ENV : 'local', APP_INSTANCE : 'valid-instance', exceptionMessage :"FATAL: NODE_ENV value of 'local' is ambiguous. " +"See https://github.com/lorenwest/node-config/wiki/Strict-Mode", }), "Specifying reserved word for NODE_CONFIG_ENV throws reserved word exception with appropriate wording": _expectException({ NODE_CONFIG_ENV : 'local', APP_INSTANCE : 'valid-instance', exceptionMessage :"FATAL: NODE_CONFIG_ENV value of 'local' is ambiguous. " +"See https://github.com/lorenwest/node-config/wiki/Strict-Mode", }), "Specifying NODE_CONFIG_ENV=production,cloud with no cloud file throws an exception with appropriate wording": _expectException({ NODE_CONFIG_ENV : 'cloud', APP_INSTANCE : 'valid-instance', exceptionMessage :"FATAL: NODE_CONFIG_ENV value of 'cloud' did not match any deployment config file names. " +"See https://github.com/lorenwest/node-config/wiki/Strict-Mode", }), }) .export(module); // helper function to create similar tests // Pass in NODE_ENV and APP_INSTANCE and an 'exceptionMessage' that is' expected to be generated by the combo under strict mode. function _expectException (opts) { return { topic: function () { // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/6-config'; process.env.NODE_CONFIG_STRICT_MODE = 1; process.env.NODE_APP_INSTANCE = opts.APP_INSTANCE; if (!!opts.NODE_ENV) { process.env.NODE_ENV = opts.NODE_ENV; } if (!!opts.NODE_CONFIG_ENV) { process.env.NODE_CONFIG_ENV = opts.NODE_CONFIG_ENV; } delete process.env.NODE_CONFIG; try { var config = requireUncached(__dirname + '/../lib/config'); } catch (e) { return e; } // No error return null; }, 'Exception is an error object': function(error) { // Allow case for exceptionMessage=null to indicate no error if (opts.exceptionMessage) { assert.instanceOf(error,Error); } }, 'Exception contains expected string': function (error) { // This conditional allows to test for error===null if (error) { assert.equal(error.message, opts.exceptionMessage ); } else { assert.equal(error, opts.exceptionMessage ); } } }; }node-config-3.3.7/test/7-config/000077500000000000000000000000001413461306600163105ustar00rootroot00000000000000node-config-3.3.7/test/7-config/defaultNoBOM.json000066400000000000000000000000731413461306600214620ustar00rootroot00000000000000{ "siteTitle" : "A valid site title from default.json" } node-config-3.3.7/test/7-config/defaultWithUnicodeBOM.json000066400000000000000000000004031413461306600233250ustar00rootroot00000000000000{ "Customers": { "dbName":"from_default_json", "dbPassword":"password will be overwritten.", "dbPassword2":"password will be overwritten.", "lang":["en","es"] }, "AnotherModule": { "parm1":"value1" }, "staticArray": [2,1,3] } node-config-3.3.7/test/7-unicode-situations.js000066400000000000000000000027241413461306600212340ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Dependencies var vows = require('vows'), assert = require('assert'), path = require('path'); // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/7-config'; // Hard-code $NODE_ENV=test for testing delete process.env.NODE_ENV; // Test for multi-instance applications delete process.env.NODE_APP_INSTANCE; process.env.NODE_CONFIG_STRICT_MODE = false; var CONFIG = requireUncached(__dirname + '/../lib/config'); vows.describe('Tests for Unicode situations') .addBatch({ 'Parsing of BOM related files': { 'A standard config file having no BOM should continue to parse without error': function () { var result = null, standardNoBomConfigFile = process.env.NODE_CONFIG_DIR + path.sep + 'defaultNoBOM.json'; assert.doesNotThrow(function () { result = CONFIG.util.parseFile(standardNoBomConfigFile); }, 'standard config file with no BOM has a parse error'); }, 'A config file with a BOM should parse without error': function () { var result = null, configFileWithBom = process.env.NODE_CONFIG_DIR + path.sep + 'defaultWithUnicodeBOM.json'; assert.doesNotThrow(function () { result = CONFIG.util.parseFile(configFileWithBom); }, 'config file with BOM has a parse error'); } } }) .export(module); node-config-3.3.7/test/8-config-extending.js000066400000000000000000000023031413461306600206300ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Dependencies var vows = require('vows'), assert = require('assert'), path = require('path'); // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/8-config'; // Hard-code $NODE_ENV=test for testing delete process.env.NODE_ENV; // Test for multi-instance applications delete process.env.NODE_APP_INSTANCE; process.env.NODE_CONFIG_STRICT_MODE = false; var CONFIG = requireUncached(__dirname + '/../lib/config'); vows.describe('Tests for config extending') .addBatch({ 'Extending a base configuration with another configuration': { 'Extending a configuration with another configuration should work without error': function () { process.env.NODE_CONFIG_DIR = __dirname + '/8-config'; var base_config = require(process.env.NODE_CONFIG_DIR + path.sep + 'base-config.json'); CONFIG.util.attachProtoDeep(base_config); assert.doesNotThrow(function () { result = CONFIG.util.extendDeep(base_config, CONFIG); }, 'Extending a configuration with another configuration has an error'); } } }) .export(module);node-config-3.3.7/test/8-config/000077500000000000000000000000001413461306600163115ustar00rootroot00000000000000node-config-3.3.7/test/8-config/base-config.json000066400000000000000000000001251413461306600213570ustar00rootroot00000000000000{ "testValue": "base configuration value", "anotherValue": "Another value" }node-config-3.3.7/test/8-config/default.json000066400000000000000000000000631413461306600206270ustar00rootroot00000000000000{ "testValue": "override configuration value" }node-config-3.3.7/test/9-config/000077500000000000000000000000001413461306600163125ustar00rootroot00000000000000node-config-3.3.7/test/9-config/default.js000066400000000000000000000006031413461306600202730ustar00rootroot00000000000000var raw = require('../../raw').raw; module.exports = { circularReference: raw(process.stdout), testObj: raw({ foo: 'bar' }), yell: raw(function(input) { return input + '!'; }), aPromise: Promise.resolve('this is a promise result'), innerRaw: { innerCircularReference: raw(process.stdout) }, nestedRaw: raw({ nested: { test: process.stdout } }) } node-config-3.3.7/test/9-raw-configs.js000066400000000000000000000027471413461306600176340ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); 'use strict'; process.env.NODE_CONFIG_DIR = __dirname + '/9-config'; process.env.NODE_ENV='test'; process.env.NODE_APP_INSTANCE='raw'; var CONFIG = requireUncached(__dirname + '/../lib/config'); // Dependencies var vows = require('vows'), assert = require('assert'); vows.describe('Tests for raw config values').addBatch({ 'Configuration file Tests': { topic: function() { try { CONFIG.get('aPromise').then(val => this.callback(null, val)); } catch(err) { this.callback(); } }, 'Objects wrapped with raw should be unmodified': function() { assert.equal(CONFIG.get('circularReference'), process.stdout); assert.deepEqual(CONFIG.get('testObj'), { foo: 'bar' }); assert.isFunction(CONFIG.get('yell')); }, 'Inner configuration objects wrapped with raw should be unmodified': function() { assert.equal(CONFIG.get('innerRaw').innerCircularReference, process.stdout); assert.equal(CONFIG.get('innerRaw.innerCircularReference'), process.stdout); }, 'Supports multiple levels of nesting': function() { assert.equal(CONFIG.get('nestedRaw').nested.test, process.stdout); assert.equal(CONFIG.get('nestedRaw.nested').test, process.stdout); assert.equal(CONFIG.get('nestedRaw.nested.test'), process.stdout); }, 'Supports keeping promises raw by default': function(err, val) { assert.equal(val, 'this is a promise result'); } } }) .export(module); node-config-3.3.7/test/_utils/000077500000000000000000000000001413461306600161765ustar00rootroot00000000000000node-config-3.3.7/test/_utils/requireUncached.js000066400000000000000000000004511413461306600216430ustar00rootroot00000000000000// // Because require'ing config creates and caches a global singleton, // We have to invalidate the cache to build new object based on the environment variables above module.exports = function requireUncached(module){ delete require.cache[require.resolve(module)]; return require(module); }node-config-3.3.7/test/config/000077500000000000000000000000001413461306600161445ustar00rootroot00000000000000node-config-3.3.7/test/config/custom-environment-variables.json000066400000000000000000000020401413461306600246550ustar00rootroot00000000000000{ // With a comment "customEnvironmentVariables": { "mappedBy": { "json": "CUSTOM_JSON_ENVIRONMENT_VAR", "formats": { "booleanTrue": { "__name": "CUSTOM_BOOLEAN_TRUE_ENVIRONMENT_VAR", "__format": "boolean" }, "booleanFalse": { "__name": "CUSTOM_BOOLEAN_FALSE_ENVIRONMENT_VAR", "__format": "boolean" }, "notProperBoolean": { "__name": "CUSTOM_BOOLEAN_ERROR_ENVIRONMENT_VAR", "__format": "boolean" }, "numberInteger": { "__name": "CUSTOM_NUMBER_INTEGER_ENVIRONMENT_VAR", "__format": "number" }, "numberFloat": { "__name": "CUSTOM_NUMBER_FLOAT_ENVIRONMENT_VAR", "__format": "number" }, "numberEmpty": { "__name": "CUSTOM_NUMBER_EMPTY_ENVIRONMENT_VAR", "__format": "number" }, "numberString": { "__name": "CUSTOM_NUMBER_STRING_ENVIRONMENT_VAR", "__format": "number" } } } } } node-config-3.3.7/test/config/default-3.json000066400000000000000000000001071413461306600206210ustar00rootroot00000000000000{ "Customers": { "altDbPort": 4400, "altDbPort1": 4402 } } node-config-3.3.7/test/config/default-array-merge.js000066400000000000000000000003031413461306600223330ustar00rootroot00000000000000 var defer = require('../../defer').deferConfig; var config = { arrayMerging: { emptyArray : [], oneItem : ['one'], removeMe : ['some value'], }, }; module.exports = config; node-config-3.3.7/test/config/default.coffee000066400000000000000000000001461413461306600207420ustar00rootroot00000000000000module.exports = AnotherModule: parm3: "value3" Customers: dbName: "from_default_coffee" node-config-3.3.7/test/config/default.cson000066400000000000000000000004371413461306600204600ustar00rootroot00000000000000{ #comment Customers: { dbName: 'from_default_cson' dbPassword: 'password will be overwritten.' dbPassword2: 'password will be overwritten.' lang: [ 'en' 'es' ] }, AnotherModule: { parm4: "value4" }, staticArray: [ 2 1 3 ] } node-config-3.3.7/test/config/default.hjson000066400000000000000000000003301413461306600206270ustar00rootroot00000000000000{ # Comment to test comment ignoring // Comment to test comment ignoring /* Comment to test comment ignoring */ Customers: { dbName: from_default_hjson } AnotherModule: { parm8: value8 } } node-config-3.3.7/test/config/default.js000066400000000000000000000012061413461306600201250ustar00rootroot00000000000000// Common configuration parameters module.exports = { TestModule: { parm1:"value1", arr1: ["arrValue1"], buffer: Buffer.from([1,2,3,4,5]), }, Customers: { dbHost:'base', dbName:'from_default_js', dbPort: 'this_is_overridden', get dbString() { return '' + this.dbName + ':' + this.dbPort; }, get random() { return Math.random(); } }, EnvOverride: { parm_number_1: "from_default_js", parm2: 22 }, MuteThis: 'hello', get customerDbPort() { return '' + this.Customers.dbPort; }, SomeMore: { regexp1: /This is a Regexp/g, regexp2: /This is another/g }, }; node-config-3.3.7/test/config/default.json000066400000000000000000000007001413461306600204600ustar00rootroot00000000000000{ "Customers": { "dbName":"from_default_json", "dbPassword":"password will be overwritten.", "dbPassword2":"password will be overwritten.", "lang":["en","es"] }, "AnotherModule": { "parm1":"value1" }, "staticArray": [2,1,3], "Inline": {"a": "", "b": "1"}, "ContainsQuote": "\"this has a quote\"", "MoreComplexQuote": "Test String" } node-config-3.3.7/test/config/default.json5000066400000000000000000000002261413461306600205500ustar00rootroot00000000000000{ // Comment to test comment ignoring "Customers": { "dbName":"from_default_json5", }, "AnotherModule": { "parm6":"value6" } } node-config-3.3.7/test/config/default.properties000066400000000000000000000003361413461306600217100ustar00rootroot00000000000000AnotherModule.parm5 = value5 key\ with\ spaces.another_key = hello !ignore_this_please = something #i_am_a_comment = something replacement.root = foo replacement.param = ${replacement.root}bar [section] param = something node-config-3.3.7/test/config/default.toml000066400000000000000000000000401413461306600204570ustar00rootroot00000000000000[AnotherModule] parm7 = "value7"node-config-3.3.7/test/config/default.xml000066400000000000000000000002741413461306600203150ustar00rootroot00000000000000 from_default_xml en es value9 node-config-3.3.7/test/config/default.yaml000066400000000000000000000002401413461306600204500ustar00rootroot00000000000000# Example of the baseline configuration in YAML Customers: dbPort: 5984 dbName: from_default_yaml emptySub: # empty AnotherModule: parm2: value2 node-config-3.3.7/test/config/default.yml000066400000000000000000000001551413461306600203140ustar00rootroot00000000000000# Example of the baseline configuration in YAML, using .yml extension AnotherModule: parm2yml: value2yml node-config-3.3.7/test/config/local-3.yml000066400000000000000000000000371413461306600201210ustar00rootroot00000000000000 Customers: altDbPort1: 2209 node-config-3.3.7/test/config/local-array-merge.js000066400000000000000000000004221413461306600220030ustar00rootroot00000000000000 var config = { arrayMerging: { emptyArray : ['not empty anymore'], // override empty array with a value oneItem : ['replaced'], // Replace one item with another. removeMe : [], // Replace a full array with an empty one }, }; module.exports = config; node-config-3.3.7/test/config/local-regexp.js000066400000000000000000000001151413461306600210610ustar00rootroot00000000000000module.exports = { SomeMore: { regexp2: /This is the replaced/g } }; node-config-3.3.7/test/config/local-test.json000066400000000000000000000001331413461306600211030ustar00rootroot00000000000000{ "Customers": { "dbPassword2":"another password", "lang":["en","de","es"] } } node-config-3.3.7/test/config/local.yaml000066400000000000000000000000511413461306600201160ustar00rootroot00000000000000 Customers: dbPassword: real password node-config-3.3.7/test/config/runtime.json000066400000000000000000000002651413461306600205250ustar00rootroot00000000000000{ "TestModule": { "parm3": 1234 }, "Customers": { "dbName": "override_from_runtime_json" }, "watchThisValue": 10788, "dynamicArray": [ 99287, 72082 ] }node-config-3.3.7/test/config/test.yaml000066400000000000000000000000761413461306600200120ustar00rootroot00000000000000# This is loaded if $NODE_ENV=test Customers: dbPort: 5999 node-config-3.3.7/test/util.js000066400000000000000000000067211413461306600162200ustar00rootroot00000000000000 // Tests for config.util functions // Dependencies var vows = require('vows'), assert = require('assert'), path = require('path'), config = require('../lib/config'), initParam = config.util.initParam, loadFileConfigs = config.util.loadFileConfigs; vows.describe('Tests for config util functions') .addBatch({ 'Tests for util.initParam': { 'When no command line or env var is set, default value is returned.': function () { assert(initParam('EMPTY','mydefault'),'mydefault'); }, 'When process.env is set and cmdline is not, process.env is used ': function () { process.env.ENV_ONLY = 'in-the-env'; assert(initParam('ENV_ONLY','mydefault'),'in-the-env'); }, 'When process.env is set and cmdline *is* set, cmd-line is used ': function () { process.env.BOTH = 'in-the-env'; process.argv=['--BOTH=in-the-argv']; assert(initParam('BOTH','mydefault'),'in-the-argv'); }, 'After calling initParam, value is reflected in getEnv() even if it did not come from process.env': function () { process.argv=['ignore','ignore','--FROMARG=in-the-argv']; assert(initParam('FROMARG','mydefault'),'in-the-argv'); assert(config.util.getEnv('FROMARG'),'in-the-argv'); }, 'Setting a zero value in the process.env works (process.env inherently casts values to strings)': function () { process.env.ENV_ONLY = '0'; assert.strictEqual(initParam('ENV_ONLY','mydefault'),'0'); }, 'Setting a zero value on the command line works. ': function () { process.argv=['ignore','ignore','--FROMARG=0']; assert.strictEqual(initParam('FROMARG','mydefault'),'0'); }, }, 'Tests for util.loadFileConfigs': { 'It can load data from a given directory': function () { var result = loadFileConfigs(path.join(__dirname, '5-config')); assert.strictEqual(result.number, 5); }, 'It ignores NODE_CONFIG when loading from directory': function () { var prev = process.env.NODE_CONFIG; process.env.NODE_CONFIG = '{"number":4}' var result = loadFileConfigs(path.join(__dirname, '5-config')); assert.strictEqual(result.number, 5); process.env.NODE_CONFIG = prev; }, }, 'Tests for util.isPromise': { 'It can identify a new Promise': function () { assert.isTrue(config.util.isPromise(new Promise(() => {}))); }, 'It can identify a resolved Promise': function () { assert.isTrue(config.util.isPromise(Promise.resolve())); }, 'It can identify a rejected Promise': function () { // Use .catch to avoid `UnhandledPromiseRejectionWarning`, DO NOT REMOVE assert.isTrue(config.util.isPromise(Promise.reject().catch(function () {}))); }, 'It can identify other things different as no promises': function () { var testCases = [ new Function(), function () {}, true, false, new Boolean(), class {}, '', new String(), [], {}, Object.create(null), new Map(), null, undefined, NaN, Infinity, 0, 1.1 -1, ]; testCases.forEach(function (testCase) { assert.isFalse(config.util.isPromise(testCase)); }); } } }) .export(module); node-config-3.3.7/test/x-config-test-ts-module-exports.js000066400000000000000000000024751413461306600233450ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Dependencies var vows = require('vows'), assert = require('assert'), FileSystem = require('fs'); /** *

Unit tests for the node-config library. To run type:

*
npm test
*

Or, in a project that uses node-config:

*
npm test config
* * @class ConfigTest */ var CONFIG, override; vows.describe('Test suite for node-config TypeScript support with module.exports') .addBatch({ 'Library initialization with TypeScript config files': { topic : function () { // Clear after previous tests process.env.NODE_APP_INSTANCE = ''; process.env.NODE_ENV = ''; process.env.NODE_CONFIG = ''; // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/x-config-ts-module-exports'; // Disable after previous tests process.env.NODE_CONFIG_STRICT_MODE = false; CONFIG = requireUncached(__dirname + '/../lib/config'); return CONFIG; }, 'Config library is available': function() { assert.isObject(CONFIG); } }, }) .addBatch({ 'Configuration file Tests': { 'Loading configurations from a TypeScript file is correct': function() { assert.equal(CONFIG.siteTitle, 'New Instance!'); } }, }) .export(module); node-config-3.3.7/test/x-config-test-ts.js000066400000000000000000000034231413461306600203520ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Dependencies var vows = require('vows'), assert = require('assert'), FileSystem = require('fs'); /** *

Unit tests for the node-config library. To run type:

*
npm test
*

Or, in a project that uses node-config:

*
npm test config
* * @class ConfigTest */ var CONFIG, override; vows.describe('Test suite for node-config TypeScript support with default export') .addBatch({ 'Library initialization with TypeScript config files': { topic : function () { // Clear after previous tests process.env.NODE_APP_INSTANCE = ''; process.env.NODE_ENV = ''; process.env.NODE_CONFIG = ''; // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/x-config-ts'; // Disable after previous tests process.env.NODE_CONFIG_STRICT_MODE = false; CONFIG = requireUncached(__dirname + '/../lib/config'); return CONFIG; }, 'Config library is available': function() { assert.isObject(CONFIG); } }, }) .addBatch({ 'Configuration file Tests': { 'Loading configurations from a TypeScript file is correct': function() { assert.equal(CONFIG.siteTitle, 'New Instance!'); } }, }) .addBatch({ 'Start in the environment with existing .ts extension handler': { 'Library reuses existing .ts file handler': function() { var existingHandler = require.extensions['.ts']; assert.ok(existingHandler, 'Existing handler is defined by the environment'); CONFIG = requireUncached(__dirname + '/../lib/config'); assert.strictEqual(require.extensions['.ts'], existingHandler, 'Should not overwrite existing handler'); } }, }) .export(module); node-config-3.3.7/test/x-config-ts-module-exports/000077500000000000000000000000001413461306600220225ustar00rootroot00000000000000node-config-3.3.7/test/x-config-ts-module-exports/default.ts000066400000000000000000000002431413461306600240150ustar00rootroot00000000000000import { Config } from './types'; const defaultConfig: Config = { siteTitle : 'Site title', latitude : 1, longitude : 2 }; module.exports = defaultConfig node-config-3.3.7/test/x-config-ts-module-exports/local.ts000066400000000000000000000002121413461306600234570ustar00rootroot00000000000000import { Config } from './types'; const localConfig: Partial = { siteTitle : 'New Instance!', }; module.exports = localConfig; node-config-3.3.7/test/x-config-ts-module-exports/types.ts000066400000000000000000000001321413461306600235320ustar00rootroot00000000000000export interface Config { siteTitle: string; latitude: number; longitude: number; };node-config-3.3.7/test/x-config-ts/000077500000000000000000000000001413461306600170355ustar00rootroot00000000000000node-config-3.3.7/test/x-config-ts/default.ts000066400000000000000000000022351413461306600210330ustar00rootroot00000000000000import { Config } from './types'; import { deferConfig as defer } from '../../defer.js'; const defaultConfig: Config = { siteTitle : 'Site title', latitude : 1, longitude : 2 }; // Set up a default value which refers to another value. // The resolution of the value is deferred until all the config files have been loaded // So that if 'config.siteTitle' is overridden, this will point to the correct value. defaultConfig['welcomeEmail'] = { subject : defer(cfg => `Welcome to ${cfg.siteTitle}`), // A plain function should be not disturbed. aFunc() { return "Still just a function."; }, // Look ma, no arg passing. The main config object is bound to 'this' justThis: defer(function () { return `Welcome to this ${this.siteTitle}`; }), }; defaultConfig['map'] = { centerPoint : defer(function () { return { lat: this.latitude, lon: this.longitude }; }), }; defaultConfig['original'] = { // An original value passed to deferred function original: "an original value", // A deferred function "skipped" by next deferred function deferredOriginal: defer((cfg, original) => "this will not be used"), }; export default defaultConfig; node-config-3.3.7/test/x-config-ts/local.ts000066400000000000000000000007441413461306600205040ustar00rootroot00000000000000import { Config } from './types'; import { deferConfig as defer } from '../../defer'; const localConfig: Config = { siteTitle : 'New Instance!', }; localConfig['map'] = { centerPoint : { lat: 3, lon: 4 }, }; localConfig['original'] = { // An original value passed to deferred function original: defer((cfg, original) => original), // This deferred function "skips" the previous one deferredOriginal: defer((cfg, original) => original), }; export default localConfig; node-config-3.3.7/test/x-config-ts/types.ts000066400000000000000000000002331413461306600205470ustar00rootroot00000000000000export interface Config { siteTitle?: string; latitude?: number; longitude?: number; welcomeEmail?: object; map?: object; original?: object; };node-config-3.3.7/test/x-config/000077500000000000000000000000001413461306600164115ustar00rootroot00000000000000node-config-3.3.7/test/x-config/default.xml000066400000000000000000000001411413461306600205530ustar00rootroot00000000000000 x_config_4_win node-config-3.3.7/test/x-config/local.yml000066400000000000000000000000271413461306600202250ustar00rootroot00000000000000different: dir: True node-config-3.3.7/test/x-deferred-configs-ts.js000066400000000000000000000042341413461306600213370ustar00rootroot00000000000000var requireUncached = require('./_utils/requireUncached'); // Test declaring deferred values. // Change the configuration directory for testing process.env.NODE_CONFIG_DIR = __dirname + '/x-config-ts'; // Hard-code $NODE_ENV=test for testing process.env.NODE_ENV='test'; // Test for multi-instance applications process.env.NODE_APP_INSTANCE='defer'; // Because require'ing config creates and caches a global singleton, // We have to invalidate the cache to build new object based on the environment variables above var CONFIG = requireUncached(__dirname + '/../lib/config'); // Dependencies var vows = require('vows'), assert = require('assert'); vows.describe('Tests for deferred values - TypeScript').addBatch({ 'Configuration file Tests': { 'Using deferConfig() in a config file causes value to be evaluated at the end': function() { // The deferred function was declared in default-defer.js // Then local-defer.js is located which overloads the siteTitle mentioned in the function // Finally the deferred configurations, now referencing the 'local' siteTitle assert.equal(CONFIG.welcomeEmail.subject, 'Welcome to New Instance!'); }, 'values which are functions remain untouched unless they are instance of DeferredConfig': function() { // If this had been treated as a deferred config value it would blow-up. assert.equal(CONFIG.welcomeEmail.aFunc(), 'Still just a function.'); }, // This defer function didn't use args, but relied 'this' being bound to the main config object "defer functions can simply refer to 'this'" : function () { assert.equal(CONFIG.welcomeEmail.justThis, 'Welcome to this New Instance!'); }, "defer functions which return objects should still be treated as a single value." : function () { assert.deepEqual(CONFIG.get('map.centerPoint'), { lat: 3, lon: 4 }); }, "defer function return original value." : function () { assert.equal(CONFIG.original.original, 'an original value'); }, "second defer function return original value." : function () { assert.equal(CONFIG.original.deferredOriginal, undefined); }, } }) .export(module);node-config-3.3.7/tools/000077500000000000000000000000001413461306600150605ustar00rootroot00000000000000node-config-3.3.7/tools/contributors.js000077500000000000000000000050261413461306600201610ustar00rootroot00000000000000#!/usr/local/bin/node /** * Merge current contributors into the README.md file */ var request = require('request'), _ = require('underscore'), fs = require('fs'); // Constants REPO = 'lorenwest/node-config'; README_FILE = './README.md'; // HTML template parts _.templateSettings = { interpolate : /\{\{(.+?)\}\}/g }; var TABLE_TEMPLATE = _.template('{{rows}}
'); var ROW_TEMPLATE = _.template('{{people}}'); var PERSON_TEMPLATE = _.template('{{login}}\n'); var PEOPLE_PER_ROW = 6; // Read the contributor list from github, return as an HTML table function getContributorTable(callback) { var options = { url: 'https://api.github.com/repos/' + REPO + '/contributors', headers: { 'User-Agent': 'README.md contributor generator, github/lorenwest' } } request(options, function(error, response, body) { if (error) { console.error('Cannot load contributor list', error); process.exit(1); } var contributors; try { contributors = JSON.parse(body); } catch (e) { console.error('Error loading contributor list: ' + body); } // Un-comment to show what github spits out // console.log(JSON.stringify(contributors,null,2)); // Process each contributor var rows = []; var row = []; for (var contributorNum in contributors) { var contributor = contributors[contributorNum]; if (row.length === PEOPLE_PER_ROW) { rows.push(ROW_TEMPLATE({people:row.join('')})); row = []; } row.push(PERSON_TEMPLATE(contributor)); } // Add the last row and return the table rows.push(ROW_TEMPLATE({people:row.join('')})); callback(null, TABLE_TEMPLATE({rows: rows.join('')})); }); }; // Get the contributor table, then merge getContributorTable(function(error, htmlTable) { if (error) { console.error('Not complete. Exiting.'); process.exit(1); } // Replace the contributor table var replacing = false; var fileLines = fs.readFileSync(README_FILE).toString().split('\n'); for (var i = 0; i < fileLines.length; i++) { if (fileLines[i].indexOf('
') === 0) { replacing = false; } fileLines.splice(i--,1); } } fs.writeFileSync(README_FILE, fileLines.join('\n')); console.log('Contributor table replaced.'); }); node-config-3.3.7/tools/gen-docs.sh000077500000000000000000000034701413461306600171220ustar00rootroot00000000000000#!/bin/sh # The location of your yuidoc install yuidoc_home=${yuidoc_home:-../yui/yui-doc} # The location of the files to parse. Parses subdirectories, but will fail if # there are duplicate file names in these directories. You can specify multiple # source trees: # parser_in="%HOME/www/yui/src %HOME/www/event/src" parser_in="lib test" # The location to output the parser data. This output is a file containing a # json string, and copies of the parsed files. parser_tmp=${parser_tmp:-./tmp} # The directory to put the html file outputted by the generator generator_out=./doc # The location of the template files. Any subdirectories here will be copied # verbatim to the destination directory. template=./doc/template # The version of your project to display within the documentation. version=`grep version package.json | sed 's/.*: "\(.*\)".*/\1/'` # The version of YUI the project is using. This effects the output for # YUI configuration attributes. This should start with '2' or '3'. yuiversion=3 # The project and URL project="Node.js Configuration" project_url="https://github.com/lorenwest/node-config" ############################################################################## # add -s to the end of the line to show items marked private rm doc/*.html $yuidoc_home/bin/yuidoc.py \ $parser_in \ -p $parser_tmp \ -o $generator_out \ -t $template \ -m "$project" \ -u "$project_url" \ -v $version \ -Y $yuiversion rm -rf $parser_tmp echo Copying the documentation to ../lorenwest.github.com/node-config/$version rm -rf ../lorenwest.github.com/node-config/$version cp -R doc ../lorenwest.github.com/node-config/$version echo Copying the documentation to ../lorenwest.github.com/node-config/latest rm -rf ../lorenwest.github.com/node-config/latest cp -R doc ../lorenwest.github.com/node-config/latest