env-var
Verification, sanatization, and type coercion for environment variables in Node.js
Install
npm install env-var --save
Usage
In the example below we read the environment variable DB_PASSWORD
const env = require('env-var');
const PASSWORD = env.get('DB_PASSWORD')
.required()
.convertFromBase64()
.asString();
TypeScript / ES6
import * as env from 'env-var';
const PORT = env.get('PORT').required().asIntPositive();
Why use this?
Because this:
const env = require('env-var');
const MAX_BATCH_SIZE = env.get('MAX_BATCH_SIZE').required().asInt();
Is cleaner than this:
const assert = require('assert');
assert.notEqual(
process.env.MAX_BATCH_SIZE,
undefined,
'MAX_BATCH_SIZE environment variable must be set'
);
const MAX_BATCH_SIZE = parseInt(process.env.MAX_BATCH_SIZE, 10);
assert(
typeof MAX_BATCH_SIZE === 'number' && !isNaN(MAX_BATCH_SIZE),
'MAX_BATCH_SIZE env var must be a valid number'
);
API
env.get([varname, [default]])
You can call this function 3 different ways:
const env = require('env-var')
const limit = env.get('SOME_LIMIT').asIntPositive()
const limit = env.get('SOME_LIMIT', '10').asIntPositive()
const allvars = env.get()
env.EnvVarError
This is the error class used to represent errors raised by this module. Sample
usage:
const env = require('env-var')
try {
env.get('MISSING_VARIABLE').required().asString()
throw new Error('some other error')
} catch (e) {
if (e instanceof env.EnvVarError) {
console.log('we got an env-var error', e)
} else {
console.log('we got some error that wasn\'t an env-var error', e)
}
}
variable
A variable is returned by calling env.get
. It has the exposes the following
functions to validate and access the underlying value.
required(isRequired = true)
Ensure the variable is set on process.env. If the variable is not set this
function will throw an EnvVarError
. If the variable is set it returns itself
so you can access the underlying variable.
Can be bypassed by passing false
, i.e required(false)
Full example:
const env = require('env-var')
const NODE_ENV = env.get('NODE_ENV').asString()
const PORT = env.get('PORT').required().asIntPositive()
const SECRET = env.get('SECRET', 'bad-secret').required(NODE_ENV === 'production').asString()
app.listen(PORT)
convertFromBase64()
Sometimes environment variables need to be encoded as base64. You can use this
function to convert them before reading their value.
For example if we run the script script below, using the command DB_PASSWORD= $(echo -n 'secret_password' | base64) node
, we'd get the following results:
console.log(process.env.DB_PASSWORD)
const dbpass = env.get('DB_PASSWORD').convertFromBase64().asString()
asEnum(validValues: string[])
Converts the value to a string, and matches against the list of valid values.
If the value is not valid, an error will be raised describing valid input.
asInt()
Attempt to parse the variable to an integer. Throws an exception if parsing
fails. This is a strict check, meaning that if the process.env value is "1.2",
an exception will be raised rather than rounding up/down.
asIntPositive()
Performs the same task as asInt(), but also verifies that the number is
positive (greater than zero).
asIntNegative()
Performs the same task as asInt(), but also verifies that the number is
negative (less than zero).
asFloat()
Attempt to parse the variable to a float. Throws an exception if parsing fails.
asFloatPositive()
Performs the same task as asFloat(), but also verifies that the number is
positive (greater than zero).
asFloatNegative()
Performs the same task as asFloat(), but also verifies that the number is
negative (less than zero).
asString()
Return the variable value as a String. Throws an exception if value is not a
String. It's highly unlikely that a variable will not be a String since all
process.env entries you set in bash are Strings by default.
asBool()
Attempt to parse the variable to a Boolean. Throws an exception if parsing
fails. The var must be set to either "true", "false" (upper or lowercase),
0 or 1 to succeed.
asBoolStrict()
Attempt to parse the variable to a Boolean. Throws an exception if parsing
fails. The var must be set to either "true" or "false" (upper or lowercase) to
succeed.
asJson()
Attempt to parse the variable to a JSON Object or Array. Throws an exception if
parsing fails.
asJsonArray()
The same as asJson but checks that the data is a JSON Array, e.g [1,2].
asJsonObject()
The same as asJson but checks that the data is a JSON Object, e.g {a: 1}.
asArray([delimiter: string])
Reads an environment variable as a string, then splits it on each occurence of
the specified delimiter. By default a comma is used as the delimiter. For
example a var set to "1,2,3" would become ['1', '2', '3'].
asUrlString()
Verifies that the variable is a valid URL string and returns that string. Uses
is-url
to perform validation, so check that module for validation rules.
asUrlObject()
Verifies that the variable is a valid URL string, then parses it using
url.parse
from the Node.js core url
module and returns the parsed Object.
See the Node.js docs for more info
mock(valuesMap)
Can be used during testing for mocking of environment variables.
const env = require('env-var')
const mockedEnv = env.mock({
API_BASE_URL: 'https://my.api.com/'
})
const apiUrl = mockedEnv.get('API_BASE_URL').asUrlString()
Examples
const env = require('env-var');
process.env.STRING = 'test';
process.env.INTEGER = '12';
process.env.BOOL = 'false';
process.env.JSON = '{"key":"value"}';
process.env.COMMA_ARRAY = '1,2,3';
process.env.DASH_ARRAY = '1-2-3';
const allVars = env.get();
const stringVar = env.get('STRING').required().asString();
const intVar = env.get('INTEGER').asInt();
const floatVar = env.get('FLOAT', '23.2').asFloat();
const boolVar = env.get('BOOL').required().asBool();
const jsonVar = env.get('JSON').asJson();
const commaArray = env.get('COMMA_ARRAY').asArray();
const commaArray = env.get('DASH_ARRAY').asArray('-');
const enumVal = env.get('ENVIRONMENT').asEnum(['dev', 'test', 'live'])
Contributors
- @caccialdo
- @evanshortiss
- @hhravn
- @itavy
- @MikeyBurkman
- @pepakriz
- @rmblstrp
Contributing
Contributions are welcomed. If you'd like to discuss an idea open an issue, or a
PR with an initial implementation.
If you want to add a new type it's easy. Add a file to lib/accessors
,
with the name of the type e.g add a file named number-zero.js
into that folder
and populate it with code following this structure:
module.exports = function numberZero (raiseError, environmentValue) {
const val = parseInt(environmentValue)
if (val === 0) {
return ret;
} else {
raiseError('should be zero')
}
}
Next update the accessors
Object in getVariableAccessors()
in
lib/variable.js
to include your new module. The naming convention should be of
the format "asTypeSubtype", so for our number-zero
example it would be done
like so:
asNumberZero: generateAccessor(container, varName, defValue, require('./accessors/number-zero')),
Once you've done that, add some unit tests and use it like so:
env.get('SOME_NUMBER').asNumberZero()