env-to-object
Advanced tools
Comparing version 1.0.0 to 1.1.0
103
lib/index.js
@@ -5,28 +5,58 @@ 'use strict'; | ||
var deepSet = require( 'utils-deep-set' ), | ||
parseJSON = require( 'utils-json-parse' ), | ||
isnan = require( 'validate.io-nan' ), | ||
isObject = require( 'validate.io-object' ); | ||
var deepSet = require( 'utils-deep-set' ); | ||
var isObject = require( 'validate.io-object' ); | ||
var merge = require( 'utils-merge2' )(); | ||
var validate = require( './validate.js' ); | ||
var error = require( './error.js' ); | ||
// PARSERS // | ||
var PARSERS = { | ||
'string': require( './string.js' ), | ||
'number': require( './number.js' ), | ||
'integer': require( './integer.js' ), | ||
'boolean': require( './boolean.js' ), | ||
'object': require( './object.js' ), | ||
'date': require( './date.js' ), | ||
'regexp': require( './regexp.js' ) | ||
}; | ||
// ENVIRONMENT VARIABLES // | ||
/** | ||
* FUNCTION: env( map ) | ||
* FUNCTION: env( map[, options] ) | ||
* Maps environment variables to a configuration object. | ||
* | ||
* @param {Object} map - environment variable mapping | ||
* @param {Object} [options] - function options | ||
* @param {Object} [options.parsers] - environment variable parsers | ||
* @returns {Object} configuration object | ||
*/ | ||
function env( map ) { | ||
var keys, | ||
out, | ||
len, | ||
val, | ||
o, | ||
i; | ||
function env( map, options ) { | ||
var parse; | ||
var opts; | ||
var keys; | ||
var err; | ||
var key; | ||
var out; | ||
var len; | ||
var val; | ||
var p; | ||
var o; | ||
var i; | ||
if ( !isObject( map ) ) { | ||
throw new TypeError( 'invalid input argument. Map argument must be an object. Value: `' + map + '`.' ); | ||
} | ||
opts = { | ||
'parsers': {} | ||
}; | ||
if ( arguments.length > 1 ) { | ||
err = validate( opts, options ); | ||
if ( err ) { | ||
throw err; | ||
} | ||
} | ||
p = merge( {}, PARSERS, opts.parsers ); | ||
keys = Object.keys( map ); | ||
@@ -36,42 +66,21 @@ len = keys.length; | ||
for ( i = 0; i < len; i++ ) { | ||
o = map[ keys[ i ] ]; | ||
val = process.env[ keys[ i ] ]; | ||
key = keys[ i ]; | ||
o = map[ key ]; | ||
val = process.env[ key ]; | ||
if ( val === void 0 ) { | ||
continue; | ||
} | ||
if ( o.type === 'number' ) { | ||
val = parseFloat( val ); | ||
if ( isnan( val ) ) { | ||
throw new TypeError( 'invalid value. ' + keys[ i ] + ' environment variable must be a number. Value: `' + val + '`.' ); | ||
if ( o.type === void 0 ) { | ||
parse = p[ 'string' ]; | ||
val = parse( val, o ); | ||
} else { | ||
parse = p[ o.type ]; | ||
if ( parse === void 0 ) { | ||
throw new Error( 'invalid type. Unsupported/unrecognized environment variable value type. Type: `' + o.type + '`.' ); | ||
} | ||
val = parse( val, o ); | ||
} | ||
else if ( o.type === 'boolean' ) { | ||
if ( | ||
val === 'true' || | ||
val === 'TRUE' || | ||
val === 'True' || | ||
val === 'T' || | ||
val === 't' | ||
) { | ||
val = true; | ||
} | ||
else if ( | ||
val === 'false' || | ||
val === 'FALSE' || | ||
val === 'False' || | ||
val === 'F' || | ||
val === 'f' | ||
) { | ||
val = false; | ||
} | ||
else { | ||
throw new TypeError( 'invalid value. ' + keys[ i ] + ' environment variable must be a boolean. Value: `' + val + '`.' ); | ||
} | ||
if ( val instanceof Error ) { | ||
throw error( val, key ); | ||
} | ||
else if ( o.type === 'object' ) { | ||
val = parseJSON( val ); | ||
if ( val instanceof Error ) { | ||
throw new TypeError( 'invalid value. ' + keys[ i ] + ' environment variable must be a valid JSON object. Value: `' + val + '`. Error: `' + val.message + '`.' ); | ||
} | ||
} | ||
deepSet( out, o.keypath, val, { | ||
@@ -78,0 +87,0 @@ 'create': true, |
{ | ||
"name": "env-to-object", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Maps environment variables to a configuration object.", | ||
@@ -36,3 +36,4 @@ "author": { | ||
"obj", | ||
"convert" | ||
"convert", | ||
"coerce" | ||
], | ||
@@ -45,2 +46,7 @@ "bugs": { | ||
"utils-json-parse": "^1.0.0", | ||
"utils-merge2": "^1.0.0", | ||
"utils-regex-from-string": "^1.0.0", | ||
"validate.io-boolean-primitive": "^1.0.0", | ||
"validate.io-function": "^1.0.2", | ||
"validate.io-integer": "^1.0.5", | ||
"validate.io-nan": "^1.0.3", | ||
@@ -50,2 +56,3 @@ "validate.io-object": "^1.0.4" | ||
"devDependencies": { | ||
"@kgryte/noop": "^1.0.0", | ||
"chai": "3.x.x", | ||
@@ -52,0 +59,0 @@ "codecov.io": "^0.1.5", |
357
README.md
@@ -21,3 +21,3 @@ Environment Variables | ||
#### env( map ) | ||
#### env( map[, options] ) | ||
@@ -61,33 +61,324 @@ Maps [environment variables](https://en.wikipedia.org/wiki/Environment_variable) to a configuration `object`. | ||
An [environment variable](https://en.wikipedia.org/wiki/Environment_variable) mapping __must__ include a [`keypath`](https://github.com/kgryte/utils-deep-set), which is a dot-delimited `object` path. By default, this module parses an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value as a `string`. The following types are supported: | ||
An [environment variable](https://en.wikipedia.org/wiki/Environment_variable) mapping __must__ include a [`keypath`](https://github.com/kgryte/utils-deep-set), which is a dot-delimited `object` path. By default, this module parses an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value as a `string`. The following [types](#types) are supported: | ||
* __string__: coerce an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value to a `string` (__default__). | ||
* __number__: coerce an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value to a `number`. | ||
* __boolean__: coerce an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value to a `boolean`. The following values are supported: | ||
- `TRUE` | ||
- `True` | ||
- `true` | ||
- `T` | ||
- `t` | ||
- `FALSE` | ||
- `False` | ||
- `false` | ||
- `F` | ||
- `f` | ||
* __object__: [parse](https://github.com/kgryte/utils-json-parse) an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value as a JSON `object`. Note that a value must be valid [JSON](https://github.com/kgryte/utils-json-parse). | ||
* [__string__](#string) | ||
* [__number__](#number) | ||
* [__integer__](#integer) | ||
* [__boolean__](#boolean) | ||
* [__object__](#object) | ||
* [__date__](#date) | ||
* [__regexp__](#regexp) | ||
If an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) does __not__ exist, the corresponding configuration `keypath` will __not__ exist in the output `object`. | ||
The `function` accepts the following `options`: | ||
* __parsers__: an `object` containing [environment variable](https://en.wikipedia.org/wiki/Environment_variable) parsers. Each `key` should correspond to a defined `type`, and each `value` should be a `function` which accepts an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value and any associated `options`. | ||
``` javascript | ||
var map = { | ||
'CUSTOM_TYPE': { | ||
'keypath': 'custom', | ||
'type': 'custom', | ||
... // => options | ||
} | ||
}; | ||
var parsers = { | ||
'custom': custom | ||
}; | ||
function custom( str, opts ) { | ||
var v = parseInt( str, 10 ); | ||
if ( v !== v ) { | ||
return new TypeError( 'invalid value. Value must be an integer. Value: `' + str + '`.' ); | ||
} | ||
return v * 6; | ||
} | ||
process.env[ 'CUSTOM_TYPE' ] = '5'; | ||
var out = env( map, parsers ); | ||
/* | ||
{ | ||
'custom': 30 | ||
} | ||
*/ | ||
``` | ||
--- | ||
## Types | ||
#### string | ||
(__default__) Coerce an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value to a `string`. | ||
``` javascript | ||
var map = { | ||
'UNSET_ENV_VAR': { | ||
'keypath': 'a.b.c' | ||
'STR': { | ||
'keypath': 'str', | ||
'type': 'string' | ||
} | ||
}; | ||
process.env[ 'STR' ] = 'beep'; | ||
var out = env( map ); | ||
// returns {} | ||
/* | ||
{ | ||
'str': 'beep' | ||
} | ||
*/ | ||
process.env[ 'STR' ] = '1234'; | ||
var out = env( map ); | ||
/* | ||
{ | ||
'str': '1234' | ||
} | ||
*/ | ||
``` | ||
=== | ||
#### number | ||
Coerce an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value to a `number`. | ||
``` javascript | ||
var map = { | ||
'NUM': { | ||
'keypath': 'num', | ||
'type': 'number' | ||
} | ||
}; | ||
process.env[ 'NUM' ] = '3.14'; | ||
var out = env( map ); | ||
/* | ||
{ | ||
'num': 3.14 | ||
} | ||
*/ | ||
process.env[ 'NUM' ] = 'bop'; | ||
var out = env( map ); | ||
// => throws | ||
``` | ||
=== | ||
#### integer | ||
Coerce an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value to an `integer`. | ||
``` javascript | ||
var map = { | ||
'INT': { | ||
'keypath': 'int', | ||
'type': 'integer' | ||
} | ||
}; | ||
process.env[ 'INT' ] = '2'; | ||
var out = env( map ); | ||
/* | ||
{ | ||
'int': 2 | ||
} | ||
*/ | ||
process.env[ 'INT' ] = 'beep'; | ||
var out = env( map ); | ||
// => throws | ||
``` | ||
The `integer` type has the following `options`: | ||
* __radix__: an `integer` on the interval `[2,36]`. | ||
``` javascript | ||
var map = { | ||
'INT': { | ||
'keypath': 'int', | ||
'type': 'integer', | ||
'radix': 2 | ||
} | ||
}; | ||
process.env[ 'INT' ] = '1'; | ||
var out = env( map ); | ||
/* | ||
{ | ||
'int': 1 | ||
} | ||
*/ | ||
process.env[ 'INT' ] = '2'; | ||
var out = env( map ); | ||
// => throws | ||
``` | ||
=== | ||
#### boolean | ||
Coerce an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value to a `boolean`. The `boolean` type supports the following options: | ||
* __strict__: `boolean` indicating whether to accept only `'true'` and `'false'` as acceptable `boolean` strings. Default: `false`. | ||
In non-strict mode, the following values are supported: | ||
- `TRUE`, `True`, `true`, `T`, `t` | ||
- `FALSE`, `False`, `false`, `F`, `f` | ||
``` javascript | ||
var map = { | ||
'BOOL': { | ||
'keypath': 'bool', | ||
'type': 'boolean' | ||
} | ||
}; | ||
process.env[ 'BOOL' ] = 'TRUE'; | ||
var out = env( map ); | ||
/* | ||
{ | ||
'bool': true | ||
} | ||
*/ | ||
process.env[ 'BOOL' ] = 'beep'; | ||
var out = env( map ); | ||
// => throws | ||
``` | ||
To restrict the set of allowed values, set the `strict` option to `true`. | ||
``` javascript | ||
var map = { | ||
'BOOL': { | ||
'keypath': 'bool', | ||
'type': 'boolean', | ||
'strict': true | ||
} | ||
}; | ||
process.env[ 'BOOL' ] = 'false'; | ||
var out = env( map ); | ||
/* | ||
{ | ||
'bool': false | ||
} | ||
*/ | ||
process.env[ 'BOOL' ] = 'TRUE'; | ||
var out = env( map ); | ||
// => throws | ||
``` | ||
=== | ||
#### object | ||
[Parse](https://github.com/kgryte/utils-json-parse) an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) value as a JSON `object`. Note that a value must be valid [JSON](https://github.com/kgryte/utils-json-parse). | ||
``` javascript | ||
var map = { | ||
'OBJ': { | ||
'keypath': 'obj', | ||
'type': 'object' | ||
} | ||
}; | ||
process.env[ 'OBJ' ] = '{"beep":"boop"}'; | ||
var out = env( map ); | ||
/* | ||
{ | ||
'obj': { | ||
'beep': 'boop' | ||
} | ||
} | ||
*/ | ||
process.env[ 'OBJ' ] = '[1,2,3,"4",null]'; | ||
var out = env( map ); | ||
/* | ||
{ | ||
'obj': [ 1, 2, 3, '4', null ] | ||
} | ||
*/ | ||
process.env[ 'OBJ' ] = '{"beep:"boop"}'; | ||
var out = env( map ); | ||
// => throws | ||
``` | ||
=== | ||
#### date | ||
Coerce an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) to a `Date` object. | ||
``` javascript | ||
var map = { | ||
'DATE': { | ||
'keypath': 'date', | ||
'type': 'date' | ||
} | ||
}; | ||
process.env[ 'DATE' ] = '2015-10-17'; | ||
var out = env( map ); | ||
/* | ||
{ | ||
'date': <Date> | ||
} | ||
*/ | ||
process.env[ 'DATE' ] = 'beep'; | ||
var out = env( map ); | ||
// => throws | ||
``` | ||
=== | ||
#### regexp | ||
[Parse](https://github.com/kgryte/utils-regex-from-string) an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) as a `RegExp`. | ||
``` javascript | ||
var map = { | ||
'REGEXP': { | ||
'keypath': 're', | ||
'type': 'regexp' | ||
} | ||
}; | ||
process.env[ 'RE' ] = '/\\w+/'; | ||
var out = env( map ); | ||
/* | ||
{ | ||
're': /\w+/ | ||
} | ||
*/ | ||
process.env[ 'RE' ] = 'beep'; | ||
var out = env( map ); | ||
// => throws | ||
``` | ||
--- | ||
## Notes | ||
* If an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) does __not__ exist, the corresponding configuration `keypath` will __not__ exist in the output `object`. | ||
``` javascript | ||
var map = { | ||
'UNSET_ENV_VAR': { | ||
'keypath': 'a.b.c' | ||
} | ||
}; | ||
var out = env( map ); | ||
// returns {} | ||
``` | ||
--- | ||
## Examples | ||
@@ -112,3 +403,4 @@ | ||
'keypath': 'bool', | ||
'type': 'boolean' | ||
'type': 'boolean', | ||
'strict': true | ||
}, | ||
@@ -122,2 +414,14 @@ 'ARR': { | ||
'type': 'object' | ||
}, | ||
"DATE": { | ||
"keypath": "date", | ||
"type": "date" | ||
}, | ||
"REGEX": { | ||
"keypath": "re", | ||
"type": "regexp" | ||
}, | ||
"INT": { | ||
"keypath": "int", | ||
"type": "integer" | ||
} | ||
@@ -132,2 +436,5 @@ }; | ||
process.env[ 'NESTED' ] = '{"hello":"world"}'; | ||
process.env[ 'DATE' ] = '2015-10-18T07:00:01.000Z'; | ||
process.env[ 'REGEX'] = '/\\w+/'; | ||
process.env[ 'INT' ] = '1234'; | ||
@@ -150,3 +457,6 @@ var out = env( map ); | ||
} | ||
} | ||
}, | ||
'date': <date>, | ||
're': /\w+/, | ||
'int': 1234 | ||
} | ||
@@ -165,6 +475,7 @@ */ | ||
``` bash | ||
$ DEFAULT=boop STR=beep NUM='5432.1' BOOL='FALSE' ARR='[4,3,2,1]' NESTED='{"world":"hello"}' node ./examples/index.js | ||
$ DEFAULT=boop STR=beep NUM='5432.1' BOOL='false' ARR='[4,3,2,1]' NESTED='{"world":"hello"}' DATE='2015-10-19T06:59:59.000Z' REGEX='/\\.+/' node ./examples/index.js | ||
``` | ||
--- | ||
## Tests | ||
@@ -171,0 +482,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
23116
15
382
530
9
7
1
+ Addedutils-merge2@^1.0.0
+ Addedvalidate.io-function@^1.0.2
+ Addedvalidate.io-integer@^1.0.5
+ Addedconst-max-uint32@1.0.2(transitive)
+ Addedconst-pinf-float64@1.0.0(transitive)
+ Addedobject-keys@1.1.1(transitive)
+ Addedregex-regex@1.0.0(transitive)
+ Addedtype-name@1.1.02.0.2(transitive)
+ Addedutils-copy@1.1.1(transitive)
+ Addedutils-copy-error@1.0.1(transitive)
+ Addedutils-indexof@1.0.0(transitive)
+ Addedutils-merge2@1.0.0(transitive)
+ Addedutils-regex-from-string@1.0.0(transitive)
+ Addedvalidate.io-array-like@1.0.2(transitive)
+ Addedvalidate.io-buffer@1.0.2(transitive)
+ Addedvalidate.io-function@1.0.2(transitive)
+ Addedvalidate.io-integer@1.0.5(transitive)
+ Addedvalidate.io-integer-primitive@1.0.0(transitive)
+ Addedvalidate.io-nonnegative-integer@1.0.0(transitive)
+ Addedvalidate.io-number@1.0.3(transitive)
+ Addedvalidate.io-number-primitive@1.0.0(transitive)
+ Addedvalidate.io-positive-integer@1.0.0(transitive)