Thinking about conf
files
What is this?
This is the third part of my 'learning to code' series, it's been slow progress but all progress is progress. If you're interested in reading about the project here are the first 2 parts of the series:
What are conf files?
I have a background with Linux and server maintenance, it's quite common for programs to have .conf
files to contain all of their settings. For web applications, I've made in the past, I've always hardcoded the database's location and then stored all other settings there. That approach doesn't really work when you want to make open source software as it needs to be easy for anyone to use it in their infrastructure.
To this end, I started thinking about using .conf
with node. It should be easy enough, I thought, we have fs
built in and that's all we need. So I set about writing a little something to handle reading the conf file and getting the settings imported. This is what I ended up with.
The conf file
"General": {
"name": "ignis"
},
"MongoDB": {
"host": "localhost",
"port": "27017",
}
The function to read it
module.exports = {
"loadConf": async () => {
const fs = require('fs');
const ConfFileLoc = "ignis.conf";
async function getConfFile() {
return new Promise((resolve) => {
fs.readFile(ConfFileLoc, (err, data) => {
if (err) throw err;
resolve(JSON.parse(`{${data}}`));
});
});
}
let conf = await getConfFile();
return conf;
}
}
So what's the problem?
I tried to access this data from another file, as I imagine it would be helpful to be able to read the .conf
file from anywhere, but it would only tell me there was a pending promise. I worked out a way around this but it felt a bit hacky and I'm sure there's a simpler solution to this.
const ch = require('./conf_helper');
(async () => {
let conf = await ch.loadConf()
console.log(conf)
})()
As you can see I've set the whole section as an async
function but I'd have to have the entire file, apart from imports, in the async
function which feels like a bad idea.
I want to help.
If you want to help me out you can either leave a comment on this post or respond to my GitHub issue about it. If I'm doing it a totally stupid way feel free to tell me, my aim is to learn how to do things properly.
Side note.
You may have noticed I mentioned MongoDB in my examples above I'm not certain I want to use this yet. Historically, I've always used MySQL but MongoDB was suggested as a better solution so I'm looking into it. If you have any input for database discussion the GitHub issue is the place to go.
Fin.
Thank you so much for reading this far and coming with me on my journey of learning. If there is anything I can do to make these posts more interesting/engaging please let me know in the comments, I really appreciate any, and all, input I get and want to make this a good series for you, the read, as well as myself.
Thanks again,
Andrew.
Top comments (10)
You could use dotenv to load configuration variables easily from a
.env
file. It's very convenient for database urls and api keys and similar things.If you want to keep your solution to read the config file, though, there are a couple of things you can do about the pending promise:
The easiest is to load the file with
fs.readFileSync
. If you are loading the file only once at start up, there is no reason why you need that call to be async.If you really need a start up operation that is asynchronous (like connecting to a MongoDB instance), you can hook your start up function at the point where the promise resolves and inject the resolved value to all the code that is dependant on it.
I don't use
async/await
, but you can take a look at how I start an express server after initiating a connection to MongoDB here.To reiterate though, I strongly suggest you use dotenv to store database urls and similar data that you don't want to commit to your version control system. And if that doesn't suit you for any reason, there is likely no good reason not to use
fs.readFileSync
to read your config file at the app start.dotenv
looks like it does exactly what I need, thank you so much 🙂Personally for configurations, I usually have a
config.json
file with the values I need, since in JavaScript you can require the file and most intellisense modules will pick up all the keys in the file.Another option is to set environment variables using something like PM2, which is what I use to actually run my node modules. You create a simple
pm2.config.json
and add the environment variables in there and on startup the values are available withprocess.env.VARIABLE_NAME
.If you're interested, I'll put a more detailed example in your git repo for you to take a look at.
Also, the beauty of the
config.json
is there's no more need for the fs module 😊Any examples would be great, thank you 🙂
I think I found a solution that works for me, I like the idea of the file being
.conf
and I found this Node Module. It had a few bits I didn't like so I wrote a wrapper around it. Here's what I've ended up with.And here is the test I wrote to go with it.
Which outputs
Thanks for all your help 🙂
In my experience it's a million times easier to stand up a free tier MongoDB through their atlas service. If you need a local instance, I believe two or three commands is all it takes and you have it up and running locally and only accepting connections from the local host.
Their main reason was that they prefer the syntax but my own research suggested that it was faster and easier to find online hosting for.