-
Notifications
You must be signed in to change notification settings - Fork 505
Special features for JavaScript configuration files
Files ending in .js and .cjs (as of 4.0) are loaded and run as a CommonJS JavaScript module. The module must export the configuration object. Some folks appreciate the ability to compute configurations, others feel it's not the right thing to do. It's nice to live in a world with choice.
JavaScript modules support the ability to have "deferred" and "raw" values.
Loading files as ESM is a work in progress. Top level async will not work, but as of 4.3.0 other cases may function properly. Full support is not anticipated until 5.0 at the earliest.
In the JavaScript modules you have the option to define a configuration value as a function whose resolution will be deferred until the final merged configuration structure is built.
For example, you set up a default value for a "full name" that is calculated from "first name" and "last name" values which will be provided a config file which overrides the defaults.
Example:
// In default.js
// using defer functions is optional. See example and docs below.
module.exports = ({defer} => ({
firstName: undefined,
lastName: undefined,
fullName: defer(function() { // Using 'this'
return this.firstName + ' ' + this.lastName;
}),
arrow: defer((config) => config.firstName + ' ' + config.lastName),
}); Then in config/production.js:
module.exports = {
firstName : "Jane",
lastName: "Doe",
}Because the resolution of fullName is deferred, it would resolve to refer to the overridden first and last name.
In addition to setting the this value of the function to the config option, it also receives two arguments: The config object is also available as the first argument, and the original, or parent, value of the current value is available as the second argument. This allows a defer function to reference it's own default value without creating an infinite loop. For example, perhaps in the qa environment you want to extend the "test" property which is defined as an array in config/default.js. Then you could use:
// in config/default.js
module.exports = {
"test": [ "a_string" ],
}
// in config/qa.js
// Extend the parent's array
module.exports = ({defer}) => ({
test: defer((config, original) => original.concat('boom'))
});The use of ECMAScript 5 getters in JavaScript configurations is not supported. Using deferred configuration values is the recommended alternative.
defer() now accepts async functions.
Important! - Never call config.get before resolveAsyncConfigs
const promise = fetch('/config/services')
.then(res => res.json()); // Promise example
async function dbSecrets(config, original) {
const doc = await db.collection('config').findOne({service: 'node'});
return doc.secretKeys;
}
module.exports = ({defer}) => ){
mode: 'dev', // unrelated value
fromUrl: defer(() => fetchRequest),
fromDatabase: defer(dbSecrets),
});
Important! - Never call config.get before resolveAsyncConfigs
It will cause the config object to freeze and will make resolving values impossible.
const { Util } = require('config/lib/util');
const config = require('config');
Util.resolveAsyncConfigs(config)
.then(config => require('./main.js'));
// OR - equivalent to:
(async function() {
await Util.resolveAsyncConfigs(config);
await import('./main.js');
})();
Note: support of advance syntax will depend on your node version and/or babel configurations
Note you'll need to call Util.resolveAsyncConfigs() before the first call to config.get() in order to ensure the promises are resolved, because the config object becomes immutable at that time.
If you'd like to include values from another file in JavaScript, no special syntax is required--the full features of Node.js are already available!
config = {
// Load credit configs externally
credit: JSON.parse(fs.readFileSync('./currentCreditPolicy.json'))
}
## Using process.stdout and other objects in JavaScript config files
There may be instances where you would like to place a complex object like `process.stdout` into your configuration file, e.g. logging configuration. But node-config achieves its useful functionality by modifying the config object prototypes then making them immutable - not ideal for `process.stdout`! But you can still achieve the goal by using the `raw` functionality like so:
```javascript
const raw = require('config/raw').raw;
module.exports = {
logOutputStream: raw(process.stdout)
};Review this page
<>