Yashua Yashua - 1 year ago 52
Node.js Question

Writing ENV variables to configure an npm module

I currently have a project in a loose ES6 module format and my database connection is hard coded. I am wanting to turn this into an npm module and am now facing the issue of how to best allow the end user to configure the code. My first attempt was to rewrite it as classes to be instantiated but it is making the use of the code more convoluted than before so am looking at alternatives. I am exploring my configuration options. It looks like writing to the process env would be the way but I am pondering potential issues, no-nos and other options I have not considered.

Is having the user write config to process env an acceptable method of configuring an npm module? It's a bit like a global write so am dealing with namespace considerations for one. I have also considered using

but that's not going to work for things like credentials. Likewise using an rc file is cumbersome. I have not found any docs on the proper methodology if any.

process.env['MY_COOL_MODULE_DB'] = ...

There are basically 5ish options as I see it:

  1. hardcode - not an option

  2. create a configured scope such as classes - what I have now and bleh

  3. use a config such as node-config - not really a user friendly option for npm

  4. store as globals/env. As suggested in comment I can wrap that process in an exported function and thereby ensure that I have a complex non collisive namespace while abstracting that from end user

  5. Ask user to create some
    file - I would if I was big time like AWS but not in this case.

I mention this npm use case but this really applies to the general challenge of configuring code that is exported as functions. I have use cases for classes but when the only need is creating a configured scope at the expense (in my case) of more complex code I am not sure its worth it.

Update I realize this is a bit of a discussion question but it's helped me wrap my brain around options. I think something like this:

// options.js
let options = {}
export function setOptions(o) { options = o }
export function getOptions(o) { return options }

Then have the user call
and call this
internally. I realize that since Node requires the module just once that my
object will be kept configured as I pass it around.

Answer Source

NPM modules should IMO be agnostic as to where configuration is stored. That should be left up to the developer, and they may pick their favorite method (env vars, rc files, JSON files, whatever).

The configuration can be passed to your module in various ways. A common way is to export a function that takes an options object:

export default options => {
  let db = database.connect(options.database);

From there, it really depends on what exactly your module provides. If it's just a bunch of loosely coupled functions, you can just return an object:

export default options => {
  let db = database.connect(options.database);
  return {
    getUsers() { return db.getUsers() }

If you want to allow multiple versions of that object to exist simultaneously, you can use classes:

class MyClass {
  constructor(options) {

export default options => {
  return new MyClass(options)

Or export the entire class itself.

If the number of configuration options is limited (say 3 or less), you can also allow them to be passed as separate arguments, instead of passing an object.