
Security News
ECMAScript 2025 Finalized with Iterator Helpers, Set Methods, RegExp.escape, and More
ECMAScript 2025 introduces Iterator Helpers, Set methods, JSON modules, and more in its latest spec update approved by Ecma in June 2025.
common-env
Advanced tools
A nice little helper for retrieving configuration from environment variable
Here is my principle:
See the talk (in french) about the why [15:23-21:30]
* besides i18n translation key and things like that of course (well, now that we've got symbols in ES6...)
npm install common-env
var env = require('common-env')();
var config = env.getOrElseAll({
amqp: {
login: {
$default: 'guest',
$aliases: ['ADDON_RABBITMQ_LOGIN', 'LOCAL_RABBITMQ_LOGIN']
},
password: 'guest',
host: 'localhost',
port: 5672
}
});
t.strictEqual(config.amqp.login, 'plop'); // converted from env
getOrElseAll
allows you to specify a configuration object with default values that will be resolved from environment variables.
Let say we start a script with AMQP_LOGIN=plop AMQP_CONNECT=true AMQP_EXCHANGES[0]_NAME=new_exchange FACEBOOK_SCOPE="user,timeline" FACEBOOK_BACKOFF="200,800" node test.js
with test.js
defined as follow:
var env = require('common-env')();
var config = env.getOrElseAll({
amqp: {
login: 'guest',
password: 'guest',
host: 'localhost',
port: 5672,
connect: false,
exchanges:[{
name: 'first_exchange'
},{
name: 'second_exchange'
}]
},
FULL_UPPER_CASE: {
PORT: 8080
},
facebook:{
scope:['user', 'timeline', 'whatelse'],
backOff: [200, 500, 700]
},
MICROSTATS: {
HASHKEY: 'B:mx:global'
}
});
t.strictEqual(config.amqp.login, 'plop'); // extracted and converted from env
t.strictEqual(config.amqp.port, 5672);
t.strictEqual(config.amqp.connect, true); // extracted and converted from env
t.strictEqual(config.amqp.exchanges[0].name, 'new_exchange'); // extracted from env
t.strictEqual(config.FULL_UPPER_CASE.PORT, 8080);
t.strictEqual(config.facebook.scope, ['user', 'timeline']); // extracted and converted from env
t.strictEqual(config.facebook.backoff, [200, 800]); // extracted and converted from env
Common-env will emit the following events:
env:fallback(key, $default)
: each time a environment key was not found and that common-env fallback on $default
.env:found(key, value, $default)
// let say NODE_ENV was set to "production"
var env = require('common-env')();
var config = env
.on('env:found', function (fullKeyName, value, $secure) {
value = $secure ? '***' : value;
console.log('[env] %s was defined, using: %s', fullKeyName, String(value));
})
.on('env:fallback', function (fullKeyName, $default, $secure) {
$default = $secure ? '***' : $default;
console.log('[env] %s was not defined, using default: %s', fullKeyName, String($default));
})
.getOrElseAll({
node: {
env: 'production'
},
redsmin: {
gc: {
enabled: false
}
}
});
// Will print
// [env] NODE_ENV was defined, using: production
// [env] REDSMIN_GC_ENABLED was not defined, using default: false
It's sometimes useful to be able to specify aliases, for instance Clever-cloud or Heroku expose their own environment variable names while your application's internal code may not want to rely on them. You may not want to depend on your hosting provider conventions.
Common-env adds a layer of indirection enabling you to specify environment aliases that won't impact your codebase.
Since v6, common-env is able to read arrays from environment variables. Before going further, please don't forget that environment variables do not support arrays, thus MY_ENV_VAR[0]_A
is not a valid environment variable name, as well as MY_ENV_VAR$0$_A
and so on. In fact, the only supported characters are [0-9_]
. But since we wanted a lot array support we had to find a work-around.
And here is what we did:
Configuration key path | Generated environment key |
---|---|
amqp.exchanges[0].name | AMQP_EXCHANGES__0_NAME |
amqp.exchanges[10].name | AMQP_EXCHANGES__10_NAME |
As you can see, we a replacing [0]
, with __0
and thus common-env is compliant with the limited character support while providing an awesome abstraction for configuration through environment variables.
Note that only the first element of the array will be used as a description for every other element of the array. So in the following code:
const config = env.getOrElseAll({
mysql: {
hosts: [{
host: '127.0.0.1',
port: 3306
}, {
auth: {
$type: env.types.String,
$secure: true
}
}]
}
});
only the first object
{ host: '127.0.0.1', port: 3306 }
will be used as a type template for every defined elements.
One last thing, common-env is smart enough to build plain arrays (not sparse), so if you defined MYSQL_HOSTS__10_PORT=3310
, config.mysql.hosts
will contains 10 objects as you thought it would.
Common-env is able to use arrays as key values for instance:
// test.js
var env = require('common-env')();
var config = env.getOrElse({
amqp:{
hosts:['192.168.1.1', '192.168.1.2']
}
});
console.log(config.amqp.hosts);
Running the above script we can override amqp.hosts
values with the AMQP_HOSTS
environment variable we get:
$ node test.js
['192.168.1.1', '192.168.1.2']
$ AMQP_HOSTS='127.0.0.1' node test.js
['127.0.0.1']
$ AMQP_HOSTS='88.23.21.21,88.23.21.22,88.23.21.23' node test.js
['88.23.21.21', '88.23.21.22', '88.23.21.23']
// test.js
var env = require('common-env')();
var config = env.getOrElse({
amqp:{
hosts:{
$default: ['192.168.1.1', '192.168.1.2'],
$aliases: ['ADDON_RABBITMQ_HOSTS', 'LOCAL_RABBITMQ_HOSTS']
}
}
});
console.log(config.amqp.hosts);
Running the above script we can override amqp.hosts
values with the ADDON_RABBITMQ_HOSTS
or LOCAL_RABBITMQ_HOSTS
environment variable aliases we get:
$ node test.js
['192.168.1.1', '192.168.1.2']
$ ADDON_RABBITMQ_HOSTS='127.0.0.1' node test.js
['127.0.0.1']
$ LOCAL_RABBITMQ_HOSTS='88.23.21.21,88.23.21.22,88.23.21.23' node test.js
['88.23.21.21', '88.23.21.22', '88.23.21.23']
Aliases don't supports arrays in their names and never will.
If $default
is not defined and no environment variables (aliases included) resolve to a value then common-env will throw an error. This error should not be caught in order to make the app crash, following the fail-fast principle.
Since common-env uses $default
to infer the environment variable type, if $default
is not available common-env won't be able to use the right type, for instance:
// ...
var config = env.getOrElseAll({
redis:{
hosts: {
$aliases: ['REDIS_ADDON_PORTS']
}
}
});
config.redis.ports
should be an array of number but instead common-env will fallback to a string because it can't infer what should be the type of config.redis.ports
. That's where $type
is handy if gives you a way to tell common-env how it should convert the value:
// ...
var config = env.getOrElseAll({
redis:{
hosts: {
$aliases: ['REDIS_ADDON_PORTS'],
$type: env.types.Array(env.types.Number)
}
}
Note that $aliases
isn't mandatory with $type
.
As of today, currently supported types are:
env.types.String
env.types.Integer
env.types.Float
env.types.Boolean
env.types.Array(env.types.String)
env.types.Array(env.types.Integer)
env.types.Array(env.types.Float)
env.types.Array(env.types.Boolean)
Let's take the following configuration object:
{
amqp: {
login: {
$default: 'guest',
$aliases: ['ADDON_RABBITMQ_LOGIN', 'LOCAL_RABBITMQ_LOGIN']
},
password: 'guest',
host: 'localhost',
port: 5672
}
}
Here is how common-env will resolve amqp.login
:
ADDON_RABBITMQ_LOGIN
environment variable, if it exists, its value will be used.LOCAL_RABBITMQ_LOGIN
, if it exists, its value will be used.AMQP_LOGIN
, if it exists, its value will be used.$default
value.
Common-env 1.x.x-2.x.x was displaying logs, here is how to retrieve the same behaviour in 3.x.x.
var logger = console;
var config = require('common-env/withLogger')(logger).getOrElseAll({
amqp: {
login: {
$default: 'guest',
$aliases: ['ADDON_RABBITMQ_LOGIN', 'LOCAL_RABBITMQ_LOGIN']
},
password: 'guest',
host: 'localhost',
port: 5672
}
});
var logger = console;
var config = require('common-env/withLogger')(logger).getOrElseAll({
amqp: {
password: {
$default: 'guest',
$secure: true
}
}
});
// Console output:
// [env] AMQP_PASSWORD was not defined, using default: ***"
// [env] AMQP_PASSWORD was defined, using: ***"
I maintain this project in my free time, if it helped you please support my work via paypal or Bitcoins, thanks a lot!
FAQs
A nice little helper for retrieving configuration from environment variable
The npm package common-env receives a total of 2,492 weekly downloads. As such, common-env popularity was classified as popular.
We found that common-env demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
ECMAScript 2025 introduces Iterator Helpers, Set methods, JSON modules, and more in its latest spec update approved by Ecma in June 2025.
Security News
A new Node.js homepage button linking to paid support for EOL versions has sparked a heated discussion among contributors and the wider community.
Research
North Korean threat actors linked to the Contagious Interview campaign return with 35 new malicious npm packages using a stealthy multi-stage malware loader.