4
\$\begingroup\$

I don't like the idea of sprinkling process.env all over the place and wanted to abstract it out a bit. I'm new to Node and know there must be a better way to do a few things.

  1. Not repeat the name 4 times (twice as a string and twice as a field)
  2. Any cleaner way to create properties and centralize existence checks than how I've done it? Mind you, I am trying to keep this Node 4.3.2 compatible sans Babel transpilers to keep it simple and working in AWS Lambda's NodeJs environment.

// module

module.exports = {

}

var configError = function (keyName) {
  console.error("ExternalVars error! Could not load a value for: "+keyName);
  process.exit(1);
}

// TODO: extract repeated function?
Object.defineProperty(module.exports, 'SAMPLE_SECRET', {
    get: function() {
        if (!process.env.SAMPLE_SECRET)
            configError('SAMPLE_SECRET');
        else
            return process.env.SAMPLE_SECRET;
    }
});

Object.defineProperty(module.exports, 'SAMPLE_SECRET_MORE', {
    get: function() {
        if (!process.env.SAMPLE_SECRET_MORE)
            configError('SAMPLE_SECRET_MORE');
        else
            return process.env.SAMPLE_SECRET_MORE;
    }
});

// usage example

var externalvars = require('./config/externalvars.js');

var sampleSecret = externalvars.SAMPLE_SECRET;
var sampleSecretMore = externalvars.SAMPLE_SECRET_MORE;
\$\endgroup\$
2
\$\begingroup\$

Disclaimer: since I'm not familiar with export/import realm, my suggestion below might be too naive and not work. If so, rather than only downvoting, thanks in advance for a little comment pointing me to a resource which would enlight how and why I'm wrong.

That's said, with merely my pure JS skills, here is how I'd work:

var keys = [
  'SAMPLE_SECRET',
  'SAMPLE_SECRET_MORE'
];
keys.forEach(function(keyName) {
  Object.defineProperty(module.exports, keyName, {
      get: function() {
          if (!process.env[keyName]) {
              console.error(
                "ExternalVars error! Could not load a value for: " + keyName
              );
              process.exit(1);
          } else {
              return process.env[keyName];
          }
      }
  });
});
\$\endgroup\$
4
  • \$\begingroup\$ This nicely removes the redundancy but for reasons I don't understand evaluates the getter without me calling it. For instance I set a value of process.env.SAMPLE_SECRET and then ask for it back and it tells me it can't find a value for SAMPLE_SECRET_MORE despite not asking for it. \$\endgroup\$
    – ss2k
    Dec 4 '16 at 18:10
  • \$\begingroup\$ @ss2k "evaluates the getter without me calling it": that's inherent to the way my proposed snippet works. And reading your comment I understand it doesn't exactly fits your need. In other words I believed you wanted to have something like a general configuration (hence my keys list), which would be early prepared for each registered key. Now you might consider replacing my keys.forEach(function(keyName) {...}); by function(keyName) {...} and invoke it when needed. BTW I realized my code was abruptly terminated, missing ); at the end. Corrected. \$\endgroup\$
    – cFreed
    Dec 4 '16 at 21:00
  • \$\begingroup\$ I wasn't able to replace as you had suggested without a syntax error. Can you write out your alternate version? \$\endgroup\$
    – ss2k
    Dec 6 '16 at 0:29
  • \$\begingroup\$ @ss2k My "alternate version" is merely what I wrote in my previous comment. In other words, embed the Object.defineProperty() statement in a function, say processEnv(keyname), then call it when needed, e.g. processEnv(SAMPLE_SECRET). \$\endgroup\$
    – cFreed
    Dec 6 '16 at 10:25
1
\$\begingroup\$

Untested, but this should be equivalent to yours:

const requiredKeys = ['SAMPLE_SECRET', 'SAMPLE_SECRET_MORE']

const keyValues = requiredKeys.reduce((m,x) => {
  if (!process.env[x]) {
    console.error("ExternalVars error! Could not load a value for: "+keyName)
    process.exit(1)
  }
  m[x] = process.env[x]
  return m
}, {})

export default keyValues
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.