nconf
nconf copied to clipboard
nconf.defaults does not seem to be working
var fs = require('fs'),
nconf = require('nconf');
var path = require('path');
const rootPath = __dirname;
const fileName = 'config.json';
nconf.defaults({
'port': 80,
'folder': 'myFolder'
});
nconf.save((err) => {
if (err) {
console.log('Failed to write configuration: ' + err);
} else {
fs.readFile(path.join(rootPath, fileName), function(err, data) {
console.log('Successfully saved configuration: ', JSON.parse(data.toString()));
});
}
});
All i get written to config.json is {}
. Am i doing something wrong?
Edit1: Ended up implementing this:
function ensureDefault(field, value) {
if (!nconf.get(field)) {
nconf.set(field, value);
}
}
You need to add a File
store to nconf.
https://github.com/indexzero/nconf#file
Did not work with a file either.
ps: i closed the issue by mistake
Order matters, since defaults
is just a named Literal
store. Did you put the File
store first?
EDIT: You may want to look at this issue: https://github.com/indexzero/nconf/issues/218
Yes.
What is the proper way to write default values on a file if they are undefined?
@bertolo1988 It depends on what you're trying to accomplish. In most cases, the way nconf is designed, there is no need to actually store defaults in a file, even if you need to store set values in a file for persistence. In fact, if you're loading and saving to a single file, and your application is evolving, you can easily end up with stale or unused values in your file if you need to change your defaults at any point.
I'll go into why further in, but here are the use cases that might make sense to me for what you're asking:
- Exporting all current keys/values into a file for external use, config backup, or cross-application config transfer
- You can get all current values, according to the order that nconf stores were added (earlier store values take precedence) by writing the contents of nconf.get() to a file. Without arguments, it returns all keys/values.
- Using key/values in the file in another part of your application or another application without using nconf or its methods
- You can do the same as the above use case, but nconf may not be the tool you're looking for. You'd be better served using another persistent store, be it redis, mongo, nedb, etc. that doesn't abstract the storage logic away from you as much and behaves consistently between or within an application.
- Using nconf methods to persistently store saved values that are different than defaults and calling nconf methods to get the correct values for keys
- This is how nconf is designed to work; don't worry about what's in the file, because you'll get a default if a key is unset in your file.
The third case here is one I ran into while overthinking it a bit and checking through the issues for a bug. In this, and in the previously mentioned issue #218, there is an assumption that I also made, which is that the file store is always a complete representation of all available config key/values. It is not; this is why you can have multiple file stores, and why the save() method can seem a bit wonky at times with those.
Functionally, there is no need for nconf to store default values anywhere; when an nconf object is instantiated, all store values are essentially in memory, including anything added by file() or load() methods. Your defaults store, which should always be added last, is persistent by nature of being part of the application code. However you generate defaults, be it hard coded or something more convoluted, those values are always part of the object, and used in the get() method if no other stores have a value set for the key. Also storing these in the file would be redundant. The file only stores what is different from defaults, ideally.
Let's say you decide your application needs to change a default value, and you've got it in production one or more places already, and this value is using the current default. The code using this config value will be changing or at least assuming the default value behavior, so your expectation is that the change in default is going to carry over to production systems when you update code. However, in a very basic way, writing your defaults to a file outside of nconf methods is very likely to prevent this from happening. Let's say it's a boolean, and the original default value for your key was true, and you're changing it to be false. Your external logic has already written this key's value to your file as true, which was the previous default. Unless you account for this with more conditionals in your code change, it will remain set as true after your update in the files on your production instances of your application, even though you expected it to be the default value since you never explicitly set the key's value using nconf.set(). In this case, your results will be the exact opposite of your expectation. If you instead just used the file and default stores as written in the nconf documentation, the value from nconf.get will always be the defaults value, so it will return false as expected in this scenario.
With persistent storage, and configs especially, it's typical to assume a single 'source of truth' so you always are working with consistent values; further, it's easy to assume (as I did) that if you use a file to store values, that that file is your single 'source of truth'. nconf, as implemented, views its instance, not any single store, as the source of truth, and abstracts the logic away from you with simple get() and set() methods. The purpose is to make hierarchical configs, in memory, a simple interface, rather than using maps, or endless conditionals, or anything else, in your application. If that doesn't do what you need it to, it'd be simpler to write a module for your application specific to your config and defaults that uses a single file and compares against your defaults using a map.
That said, and against all better judgement, there are a few ways, using nconf or external logic, to force defaults values into your file in they're not set there:
- @todbot is keeping defaults in a separate JSON file and just copying that as the starting point for the config file passed to nconf.file(). This works well if your defaults won't change, ever, and you only need to init your configs once in the application lifecycle.
- You can set up nconf as specified (adding file store then defaults store), and loop through your defaults with Object.keys(), or use Array.map... or however, after you add your stores, doing a compare between your file values and defaults values, adding unset key/value pairs directly to the file store(e.g. nconf.stores.file.set()), and the calling the save() method at the end of that. It's icky, but works.
- You can override the nconf.save() method with your own module to include logic that does the same as 2 above on each save.
...but it's unlikely you'll need to do any of this if you're just using nconf as designed. If you do have a specific use case that isn't covered here, I'd be interested to know.