# common-env **Repository Path**: mirrors_FGRibreau/common-env ## Basic Information - **Project Name**: common-env - **Description**: :key: The only configuration library you will ever need - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-24 - **Last Updated**: 2026-07-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README
[](https://circleci.com/gh/FGRibreau/common-env/) [](https://coveralls.io/github/FGRibreau/common-env?branch=master) [](http://badge.fury.io/js/common-env) [](https://www.npmjs.com/package/common-env) [](https://www.codementor.io/francois-guillaume-ribreau?utm_source=github&utm_medium=button&utm_term=francois-guillaume-ribreau&utm_campaign=github) [](http://bit.ly/2c7uFJq)  [](https://join.slack.com/t/fgribreau/shared_invite/zt-edpjwt2t-Zh39mDUMNQ0QOr9qOj~jrg) # Philosophy Here is my principle: [](https://www.uslide.io/presentations/Aw6sX5ug-Tfzw5rNXAmdJg) \* besides i18n translation key and things like that of course (well, now that we've got symbols in ES6...) # NPM ```shell npm install common-env ``` #### Usage ```javascript 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 ``` #### env.getOrDie(envVarName) #### env.getOrElse(envVarName, default) #### env.getOrElseAll(object) `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: ```javascript 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 ``` #### Events 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)` ```javascript // 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 ``` #### Specifying multiple aliases It's sometimes useful to be able to specify aliases, for instance [Clever-cloud](http://clever-cloud.com) or [Heroku](https://heroku.com) 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](http://en.wikipedia.org/wiki/Fundamental_theorem_of_software_engineering) enabling you to specify environment aliases that won't impact your codebase. #### How to handle environment variable arrays 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](https://github.com/FGRibreau/common-env/issues/6). 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: ```js 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. #### How to specify environment variable arrays Common-env is able to use arrays as key values for instance: ```javascript // 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: ```shell $ 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'] ``` #### How to specify environment variable arrays using $aliases ```javascript // 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: ```shell $ 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. ##### fail-fast behaviour 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](https://en.wikipedia.org/wiki/Fail-fast) principle. ### How to define type converters 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: ```js // ... 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: ```js // ... 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)` #### How common-env resolves environment variables Let's take the following configuration object: ```javascript { 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`: - Common-env will first read `ADDON_RABBITMQ_LOGIN` environment variable, if it exists, its value will be used. - If not common-env will read `LOCAL_RABBITMQ_LOGIN`, if it exists, its value will be used. - If not common-env will read `AMQP_LOGIN`, if it exists, its value will be used. - If not common-env will fallback on `$default` value.